Page 1 of 2

Pass by reference

Posted: Mon Mar 30, 2009 10:19 am
by Mistrel
We can already do this:

Code: Select all

Procedure That(*This.Integer)
  *This\i=2
EndProcedure

That(@This)
Debug This
But it would be so much simpler if we could do this:

Code: Select all

Procedure That(&This)
  This=2
EndProcedure

That(This)
Debug This
Without pass by reference it's very cumbersome to do something like this, for example:

Code: Select all

Procedure That(*This.Something)
  *This=AllocateMemory(SizeOf(Something))
  *This\a=1
  *This\b=2
  *This\c=3
EndProcedure

Define *This.Something
That(@*This)
Debug *This\a
Debug *This\b
Debug *This\c
We have to do this instead:

Code: Select all

Procedure That(*This.Something)
  *OldAddress=*This
  *This=AllocateMemory(SizeOf(Something))
  *This\a=1
  *This\b=2
  *This\c=3
  PokeI(*OldAddress,*This)
EndProcedure

Define *This.Something
That(@*This)
Debug *This\a
Debug *This\b
Debug *This\c
Something as simple as this would be ideal:

Code: Select all

Procedure That(&*This.Something)
  *This=AllocateMemory(SizeOf(Something))
  *This\a=1
  *This\b=2
  *This\c=3
EndProcedure

Define *This.Something
That(*This)
Debug *This\a
Debug *This\b
Debug *This\c
Or this:

Code: Select all

Procedure That(*This.Something)
  *This=AllocateMemory(SizeOf(Something))
  *This\a=1
  *This\b=2
  *This\c=3
EndProcedure

Define *This.Something
That(&*This)
Debug *This\a
Debug *This\b
Debug *This\c
Am I missing some simple solution here or is this type of parameter passing too complex for PureBasic to handle gracefully?

Posted: Mon Mar 30, 2009 11:07 am
by Kaeru Gaman
I sorry I don't understand what you want to achieve with your second example....

*reads over it half a dozen times*

you mean to create a pointer outside a proc,
and then inside allocate mem and bend the pointer towards it?

Posted: Mon Mar 30, 2009 12:53 pm
by Hroudtwolf
How about this?

Code: Select all

Structure tVoid
   v.i
EndStructure

Procedure That ( *Void.tVoid )
  *Void\v = AllocateMemory( SizeOf ( tVoid ) ) 
EndProcedure

Define *This 
That(@*This)
Debug *This
Regards

Wolf

Posted: Mon Mar 30, 2009 1:19 pm
by Mistrel
Hroudtwolf wrote:How about this?

Code: Select all

Structure tVoid
   v.i
EndStructure

Procedure That ( *Void.tVoid )
  *Void\v = AllocateMemory( SizeOf ( tVoid ) ) 
EndProcedure

Define *This 
That(@*This)
Debug *This
Regards

Wolf
That's no different from the integer method. This still doesn't provide a way to allocate memory for and assign values to the new memory within the function and get it out without the roundabout method I mentioned before.

Posted: Mon Mar 30, 2009 1:23 pm
by Hroudtwolf
This possibility is quite enough.

-1
'Cause, I disapprove of syntax changes.

Regards

Wolf

Posted: Mon Mar 30, 2009 1:30 pm
by Mistrel
With pass by reference it would be much simpler to break down functions that use pointers like this.

I have several functions that use identical code that should be an a separate function but to do so would make the function difficult to decipher and maintain because of having to address pointers in such a roundabout way.
Hroudtwolf wrote:'Cause, I disapprove of syntax changes.
I admit, it's usefulness isn't obvious unless you start using it on a regular basis.

Posted: Mon Mar 30, 2009 1:54 pm
by Kaeru Gaman
I'm not sure, but I guess what you want is what are Interfaces and Prototypes for...

Posted: Mon Mar 30, 2009 9:27 pm
by tinman
How about this?

It's more awkward than pointers in C or references in C++ because you have to create a structure for the level of indirection rather than just adding on a few extra *'s, but you can do it directly in PB syntax without having to resort to Poke.

Code: Select all

Structure PointerToSomething
    *something.Something
EndStructure

Procedure That(*This.PointerToSomething)
  *This\something=AllocateMemory(SizeOf(Something))
  *This\something\a=1
  *This\something\b=2
  *This\something\c=3
EndProcedure

Define *This.Something
That(@*This)
Debug *This\a
Debug *This\b
Debug *This\c
You'd only really need a couple of levels of indirection at most (usually).

Posted: Tue Mar 31, 2009 12:50 am
by Mistrel
Thanks, tinman. That is a much more elegant solution (I knew I was forgetting something obvious) but when looking back at the code months from now I'm afraid it will still be misleading, considering it's a hack on a per-structure basis.

It solves the problem but it still makes the intent more difficult to interpret.

Posted: Tue Mar 31, 2009 8:04 am
by bembulak
Why not use the "shared" keyword?
I really guess it's meant for "passing" by value, because it's used get outside values inside a procedure.

Posted: Tue Mar 31, 2009 8:57 am
by Mistrel
You can't used shared for instances where the address passed is for a user-defined variable.

Posted: Thu Apr 02, 2009 11:25 am
by Mistrel
Kaeru Gaman wrote:I sorry I don't understand what you want to achieve with your second example....

*reads over it half a dozen times*

you mean to create a pointer outside a proc,
and then inside allocate mem and bend the pointer towards it?
Pass by reference is basically the equivalent functionality of the "shared" keyword but the variable is passed as a parameter instead of being declared statically.

To be more specific, the variable passed by reference is available within the same scope of the function. It means you don't have to pass by-address and then peek/poke/structured pointer your values in.

It's a great convenience, I think. In my opinion it can make code that involves a lot of dynamic allocation and pointer-passing much easier to read and write.

Yes please!

Posted: Sun Apr 05, 2009 10:22 pm
by USCode
Mistrel wrote: ... It's a great convenience, I think. In my opinion it can make code that involves a lot of dynamic allocation and pointer-passing much easier to read and write.
+1
I couldn't agree more. Delphi has something similar with the "var" keyword and in VB I believe it's "ByRef".
In my view it makes code clearer as well as being VERY convenient.
Many folks don't want to deal directly with pointers and a simple pass by reference keyword would be much appreciated.

Re: Pass by reference

Posted: Mon Apr 06, 2009 7:50 am
by Demivec
Mistrel wrote:Am I missing some simple solution here or is this type of parameter passing too complex for PureBasic to handle gracefully?
Mistrel wrote:It's a great convenience, I think. In my opinion it can make code that involves a lot of dynamic allocation and pointer-passing much easier to read and write.
In looking at the examples you provided nothing you did made the code any easier to read. The ways that you suggested to make it easier to write seemed to only involve exchanging the "@" character for an "&" character. That hardly seems helpful or worthwhile.

Side note: IMHO your best bet to making it easier to read is to use more meaningful variables and procedure names.

Here's my version of the same example procedure:

Code: Select all

Structure Something
  a.i
  b.i
  c.i
EndStructure

Procedure newSomething(*ptrThis.Integer)
  Protected *this.Something = AllocateMemory(SizeOf(Something))
  *ptrThis\i = *this
  *this\a = 1
  *this\b = 2
  *this\c = 3
EndProcedure
  

Define *this.Something

newSomething(@*this)

Debug *this\a
Debug *this\b
Debug *this\c
To show how this compares to what you suggested, here they are side by side:

Code: Select all

Structure Something                                                 
  a.i
  b.i
  c.i
EndStructure

Procedure newSomething(*ptrThis.Integer)                           Procedure That(&*This.Something)         
  Protected *this.Something = AllocateMemory(SizeOf(Something))      *This=AllocateMemory(SizeOf(Something))
  *ptrThis\i = *this                                                                           
  *this\a = 1                                                        *This\a=1                            
  *this\b = 2                                                        *This\b=2                            
  *this\c = 3                                                        *This\c=3                            
EndProcedure                                                       EndProcedure 
                                                                                     
                                                                                     
Define *this.Something                                             Define *This.Something                   
newSomething(@*this)                                               That(*This)                              
Debug *this\a                                                      Debug *This\a                            
Debug *this\b                                                      Debug *This\b          
Debug *this\c                                                      Debug *This\c
I count only one line of difference. You be the judge. I favor this method over the one tinman suggested because it doesn't require creating additional structures.
USCode wrote:Many folks don't want to deal directly with pointers and a simple pass by reference keyword would be much appreciated
Since performing these operations means you are working with pointers it wouldn't matter if you used "NotAPtr this.Something" instead of "*this.Something", because you have to remember where the values are being read and written to. As noted previously using an "&" in the definition of a procedure parameter is just as hard as using "@" in a procedure call. The person using it needs to know why they are using it.


- 1
It seems a suggestion for redundant functionality that is already well covered by "*" pointers and the "@" operator and wouldn't help anyone who is already confused about using pointers.

@Edit: added the word "help" to the last sentence, it had been omitted as an oversight.

Posted: Mon Apr 06, 2009 12:08 pm
by Kaeru Gaman
Mistrel wrote:
Kaeru Gaman wrote:*reads over it half a dozen times*
Pass by reference is basically the equivalent functionality of the "shared" keyword but the variable is passed as a parameter instead of being declared statically.

To be more specific, the variable passed by reference is available within the same scope of the function. It means you don't have to pass by-address and then peek/poke/structured pointer your values in.

It's a great convenience, I think. In my opinion it can make code that involves a lot of dynamic allocation and pointer-passing much easier to read and write.
I know what "pass byRef" means...

but I don't see any advantage in all the points here.
working with structured pointers make it ALWAYS clearly visible that you are handling a byRef Value and no local Variable....
it's the "style" of PureBasic, and it's ok as it is.


if one needs more conveniance, I would rather recommend and support a feature request for quick-and-easy stucture-field-autocomplete in the IDE...