Variable by reference in procedure

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
User avatar
Demivec
Addict
Addict
Posts: 4283
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Variable by reference in procedure

Post by Demivec »

It would seem that PureBasic already allows returning more than one value from a procedure by the use of pointers as parameters. The process allows the return of structures also.

Code: Select all

Procedure.i test (in$, x.i, *refStr.C:haracter, *outY.Integer, *outStr.String)
  ; procedure code
  *outY\I = 42
  *outStr\s = in$ + ": " + x + " : " Str(*refStr\c)
EndProcedure

;This works. 
test(s$, m.i, @example.s, @newY.i, @newString.String)

;Problems can occur with literals or unstructured string variables (of type .s or $ because
; pointer to structure instead of string contents is needed so string can be modified).
;test(s$, m.i, @"still OK", @600613, @notChangeable.s)
The two problems that remain are pointers to reference literals and getting the pointer to a string structure of a unstructured string variable (of type .s or $). I'll ignore any possible issues with literals because I think these are minor, infrequent or trivial.

The main issue that remains is getting the pointer to the string structure that is used for a string variable declared as either type .s or $. This begs for a new operator, keyword or compiler function. Some such as mk-soft have tried to come up with solutions or suggestions to fix this.

Here are some examples:

Code: Select all

;new operator
*ptrStringStructure = @@some.s ;@@ is the suggested operator

;new keyword
;RefTo is my suggested keyword, I just made this up so I'm sure there are better choices ;)
;it would possibly be limited to being used in a parameter list.
;Other keywords suggested are ByRef or Out.
*ptrStringStructure = RefTo some.s

;or
Procedure.i test (in$, x.i, *refStr.Character, *outY.Integer, RefTo *outStr.String): EndProcedure 
;test(s$, m.i, @"still OK", @600613, @wasNotChangeable.s) 

;or
Procedure.i test (in$, x.i, *refStr.Character, *outY.Integer, *outStr.String):EndProcedure 
;test(s$, m.i, @"still OK", @600613, RefTo wasNotChangeable.s) 

;new compiler function RefTo()
*ptrStringStructure = RefTo(some.s)

;or
Procedure.i test (in$, x.i, *refStr.Character, *outY.Integer, *outStr.String):EndProcedure 
;test(s$, m.i, @"still OK", @600613, RefTo(nowChangeable.s)) 
While the names for the things can be discussed to come to something agreeable, I don't think there is needed any additional possibilities than the ones I enumerated. It is needed for advanced string pointer use inside procedures when a parameter is a common string variable. PureBasic hides these structure details for common use and if really needs a way to unhide these details for advanced use cases.

I don't think it would break anything. I personally favor a new compiler function so it is obvious what is happening and to show it is expressly wanted when passing a parameter.
Last edited by Demivec on Tue May 13, 2025 7:43 am, edited 3 times in total.
AZJIO
Addict
Addict
Posts: 2274
Joined: Sun May 14, 2017 1:48 am

Re: Variable by reference in procedure

Post by AZJIO »

If you use @@some.s, then there is no need to use "RefTo" for "*outStr.String" in the function parameters. We could use "RefTo var.s" to create a structure inside the function, but show it to us as a var variable. Then we wouldn't have to use a structure inside the function.

As for the name, it is better to use the well-known name ByRef.

We could solve such a CopyMemoryString("Hello", @*Pointer) entry here as CopyMemoryString("Hello", @@some.s) so as not to create an intermediate variable.
User avatar
Piero
Addict
Addict
Posts: 1204
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: Variable by reference in procedure

Post by Piero »

Code: Select all

Structure ss
   s.s
   ss.s
EndStructure

Procedure s(*s.ss)
   *s\s + *s\ss + " World!"
EndProcedure

Define s.ss\ss = "Hello"

s(s) ; @mk-soft ;P
Debug s\s
User avatar
mk-soft
Always Here
Always Here
Posts: 6595
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Variable by reference in procedure

Post by mk-soft »

You don't need an extra structure

Code: Select all

Procedure foo(*inout.string)
  *inout\s + " World!"
EndProcedure

Define text.string

text\s = "Hello"
foo(text)
Debug text\s
My Projects EventDesigner V3 / ThreadToGUI / OOP-BaseClass / Windows: Module ActiveScript
PB v3.30 / v5.75 - OS Mac Mini - VM Window Pro / Linux Ubuntu
Downloads on my OneDrive
User avatar
Piero
Addict
Addict
Posts: 1204
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: Variable by reference in procedure

Post by Piero »

mk-soft wrote: Sun Feb 22, 2026 12:45 pm You don't need an extra structure

Code: Select all

Procedure foo(*inout.string)
  *inout\s + " World!"
EndProcedure

Define text.string

text\s = "Hello"
foo(text)
Debug text\s
You process/return only 1 (string) variable into the procedure :x

NOTE: it was made.ss\ss to confuse you (just for fun)… the real message is: THANKS FRE… OoOPS!
SMaag
Enthusiast
Enthusiast
Posts: 385
Joined: Sat Jan 14, 2023 6:55 pm
Location: Bavaria/Germany

Re: Variable by reference in procedure

Post by SMaag »

There is an other way I use somtimes. It's a little bit tricky but the best way to prevent errors.

Code: Select all

EnableExplicit

Prototype test(String$)
Global test.test

; use this Macro only in Procedures and only once!
Macro _HookStringByRef(_ptrStr)
  Protected HookString.String
  Protected *pHook.Integer =@HookString
  *pHook\i=_ptrStr
EndMacro

Macro _UnHookStringByRef()
  *pHook\i=0  
EndMacro
 
Procedure _test(*String)
  _HookStringByRef(*String)  ; Hook the StringPointer into a String Structure
  HookString\s = "5678"      ; Manipulate the hooked String
  _UnHookStringByRef()       ; Unhook the string!
EndProcedure
test = @_test()


Define s.s="1234"
test(s)
Debug s
User avatar
Piero
Addict
Addict
Posts: 1204
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: Variable by reference in procedure

Post by Piero »

It isn't very clear to me if you Gurus would need 'Out' (also) for ultra-faster processing…
I find using structures already very handy, e.g., you can create an easily reusable/expandable/resettable "group"…

Code: Select all

Structure ss
   s.s
   ss.s
   ;…
EndStructure

Procedure s(*s.ss)
   *s\s + *s\ss + " World!"
EndProcedure

Define s.ss\ss = "Hello"

s(s)
Debug s\s

ClearStructure(s,ss) ; reset
s\ss = "Hi"
s(s)
Debug s\s
Post Reply