WinBatch® Technical Support Forum

All Things WinBatch => WinBatch => Topic started by: snowsnowsnow on April 26, 2016, 01:19:07 PM

Title: Fun with arrays!
Post by: snowsnowsnow on April 26, 2016, 01:19:07 PM
Try out this program.  Why doesn't array "A" in the main program retain the values assigned to it in the Function?  Remember that arrays are passed "by reference", which, in layman's terms, means that the object referred to inside the function is the same object as the object that exists in the caller.

Note: Yes, I know all about how DefineFunction works and that most variables are "local" to the function and thus not visible outside.  But arrays passed as arguments *are* different (special).

Code (winbatch) Select

#DefineFunction udfArrayize(s,d,A)
A = Arrayize(s,d)
Return ArrInfo(A,1) - 1
#EndFunction

A = Arrayize("","")
n0 = udfArrayize("a b c"," ",A)
Pause("Result: %n0%",StrCat("ArrInfo(A,1) = ",ArrInfo(A,1)))
FOR I = 0 TO n0
    Pause(I,A[I])
NEXT
Title: Re: Fun with arrays!
Post by: td on April 26, 2016, 02:23:05 PM
Me things you are confusing variables containing references with pointers to variables.   If you assigned an integer value of 0 to your A variable and passed it to your UDF and in the UDF assigned the value of 1 to that same A variable, you certainly would not  expect (I hope) the A variable to have changed after the script returns from the UDF call.  Your UDF creates an entirely new array reference and assigned it to the variable with UDF scope. Since that variable has UDF scope, the array reference it contains is destroyed when the variable goes out of scope.  The passed in array has its reference count incremented when the reference is assigned to the UDF parameter variable and decremented when the UDF assigns a completely different array references to that variable.  The net affect on the original array variable and reference is nada.   
Title: Re: Fun with arrays!
Post by: td on April 26, 2016, 02:35:00 PM
Consider the following and how it demonstrates the concept of array references:
Code (winbatch) Select
#DefineFunction udfArrayize(s,d,A)
   nMax = min(ItemCount(s, d),ArrInfo(a,1)) - 1
   for i = 0 to nMax
      A[i] = ItemExtract(i+1, s, d)
   next
   Return ArrInfo(A,1) - 1
#EndFunction

A = Arrayize("1 2 3"," ")
n0 = udfArrayize("a b c"," ",A)
Pause("Result: %n0%",StrCat("ArrInfo(A,1) = ",ArrInfo(A,1)))
for i = 0 TO n0
    Pause(i,A[i])
next

Title: Re: Fun with arrays!
Post by: snowsnowsnow on April 27, 2016, 01:00:48 AM
OK - I get it (I think).

The point is that Arrayize() does not populate an existing array (As I lazily assumed, although I should have known better).  Rather, it creates a brand new array - wiping out any existing array that might have existed with the name to which the new array has been assigned.
Title: Re: Fun with arrays!
Post by: td on April 27, 2016, 08:14:22 AM
Right on.
Title: Re: Fun with arrays!
Post by: snowsnowsnow on April 27, 2016, 09:19:01 AM
Quote from: td on April 27, 2016, 08:14:22 AM
Right on.

Which leads to the question of whether there is anyway to implement what I'm actually trying to do here.  That is, a version of Arrayize() that returns the number (minus 1 - for a reason that should, I would hope, be clear) of elements created (*), as well as making the array itself available to the caller.

As I think about it, it seems it might actually be do-able using gosub (which would keep everything in scope of the caller) rather than UDF or UDS...

(*) I.e., the highest legal subscript, which is what I usually want.
Title: Re: Fun with arrays!
Post by: td on April 27, 2016, 10:55:24 AM
I believe with your  version of WinBatch, you could simply use the '&' pointer creation operator to make your array parameter an [in] and [out] parameter (burger parameter?).   Something like:

Code (winbatch) Select
udfArrayize("a b c"," ",&A)

and

Code (winbatch) Select
*A=Arrayize(s,d)
Title: Re: Fun with arrays!
Post by: snowsnowsnow on April 27, 2016, 01:04:40 PM
Quote from: td on April 27, 2016, 10:55:24 AM
I believe with your  version of WinBatch, you could simply use the '&' pointer creation operator to make your array parameter an [in] and [out] parameter (burger parameter?).

Yes!  Thank you, that works!

Here is the revised code:

Code (winbatch) Select

#DefineFunction udfArrayize(s,d,A)
*A = Arrayize(s,d)
Return ArrInfo(*A,1) - 1
#EndFunction

n0 = udfArrayize("a b c"," ",&A)
Pause("Result: %n0%",StrCat("ArrInfo(A,1) = ",ArrInfo(A,1)))
FOR I = 0 TO n0
    Pause(I,A[I])
NEXT


But I am curious about one thing - you will notice that in the above code, I did not have to initialize (i.e., create) the A array before passing &A to the UDF.  Doesn't that seem odd by the usual WinBatch standard - which is that any variable (i.e., object) has to be initialized before it an be used?  What exactly is &A when A has not been referenced previously?
Title: Re: Fun with arrays!
Post by: td on April 27, 2016, 01:44:36 PM
No mystery.  The & operator instantiates the variable on as needed basis just like the PtrGlobalDefine function does.  From the function's documentation:

'If "variable-name" does not already exist, it will be created.' 
Title: Re: Fun with arrays!
Post by: snowsnowsnow on April 27, 2016, 01:50:20 PM
Quote from: td on April 27, 2016, 01:44:36 PM
No mystery.  The & operator instantiates the variable on as needed basis just like the PtrGlobalDefine function does.  From the function's documentation:

'If "variable-name" does not already exist, it will be created.'

OK - then no worries.

Anyway, thanks again - this solves my problem.
And now I get to reverse my previous position that pointers are not useful.
Title: Re: Fun with arrays!
Post by: snowsnowsnow on April 28, 2016, 03:13:56 AM
Actually, it occurs to me that one could just as easily do it using a UDS instead of with pointers.  This has the feature that it always uses the same array - Yes, this is a feature, not a bug/limitation.

This works:

Code (winbatch) Select

#DefineSubroutine udsArrayize(_s,_d)
A = Arrayize(_s,_d)
Return ArrInfo(A,1) - 1
#EndSubroutine


Note, incidentally, the need to precede the 's' and 'd' parameters with the underscore...
Title: Re: Fun with arrays!
Post by: td on April 28, 2016, 06:37:45 AM
UDFs have several advantages over UFSs but that is a discussion for another day.