LB Booster
Programming >> Language extensions >> Passing Arrays
http://lbb.conforums.com/index.cgi?board=extensions&action=display&num=1394695833

Passing Arrays
Post by JosephE on Mar 13th, 2014, 07:30am

Can anyone provide an example of an array being passed to a function so I can see what the syntax for it is? smiley
Re: Passing Arrays
Post by Richard Russell on Mar 13th, 2014, 09:21am

on Mar 13th, 2014, 07:30am, JosephE wrote:
Can anyone provide an example of an array being passed to a function so I can see what the syntax for it is? :)

Here's a simple example:

Code:
    one(5) = 123
    call test one()
    end

sub test two()
    print two(5)
end sub 

To demonstrate that the array two() is genuinely 'local' to the SUB:

Code:
    one(5) = 123
    two(5) = 456
    call test one()
    print two(5)
    end

sub test two()
    print two(5)
end sub 

Arrays are automatically passed 'by reference' (you don't need to specify BYREF):

Code:
    one(5) = 123
    two(5) = 456
    call test one()
    print two(5)
    print one(5)
    end

sub test two()
    print two(5)
    two(5) = 789
end sub 

Of course you can use a FUNCTION instead of a SUB:

Code:
    one(5) = 123
    two(5) = 456
    print test(one())
    print two(5)
    print one(5)
    end

function test(two())
    test = two(5)
    two(5) = 789
end function 

Richard.
Re: Passing Arrays
Post by JosephE on Mar 13th, 2014, 8:35pm

Richard, these are absolutely wonderful. Thank you so much.

I've written a simple UBound function to determine the upper-index limit of an array. However, it's acting funny. It's returning one more than it seems like it should. I'm wondering if it has to do with how I've implemented the On Error part.

Here's my code:

Code:
*incorrect code removed* 


Edit: After thinking about it, I realize why it does that. It seems the UBound function should simply be UBound = i - 1.

Code:
ReDim things(5) ' Make it hold five things

Print UBound(things())

End


Function UBound(array())
	' Returns the upper index limit of array().
	' ---------------------------------------------------------- '
	On Error Goto [Error]
	While 1
		temp = array(i)
		i = i + 1
	WEnd
	[Error]
		UBound = i - 1 ' Return value
End Function 

Re: Passing Arrays
Post by Richard Russell on Mar 13th, 2014, 9:11pm

on Mar 13th, 2014, 8:35pm, JosephE wrote:
I've written a simple UBound function to determine the upper-index limit of an array.

Nice. However it might be a bit slow with a large array. You could use a 'binary chop' to make it a lot faster:

Code:
Function UBound(array())
    ' Returns the upper index limit of array().
    ' ---------------------------------------------------------- '
    s = 2^24
    do
        On Error Goto [Error]
        [Error]
        s = int(s / 2)
        temp = array(UBound + s)
        UBound = UBound + s
    loop until s = 0
End Function 

An alternative approach would be to cheat and incorporate a little bit of BBC BASIC code:

Code:
Function UBound(array())
    !UBound = DIM(array(),1)
End Function 

Richard.

Re: Passing Arrays
Post by JosephE on Mar 13th, 2014, 9:20pm

Richard, that's genius. I had no idea. I have seen binary chop methods before but didn't think to try implementing one.

I'm alright with cheating if it works, haha.

I'm trying to make a few functions to do a redim preserve, but I'm having trouble. Here's where I'm at. Note that it doesn't even output the last print statement:

Code:
' Simple Array Functions
' by Joseph Essin
' Feel free to use in your own code. No need to credit me.
'
' For use with LBB:
' http://www.bbcbasic.co.uk/lbb/
'
' The functionality to make this work is not found in
' Liberty BASIC alone. This is for use with Richard Russell's
' Liberty BASIC Booster "compiler."
'
' Please find LBB below:
'
' http://www.bbcbasic.co.uk/lbb/
' -------------------------------------------------------------- '

' These are necessary for the Array Library.
' Don't name any of your arrays these names
' or you'll be subject to data loss.
Redim ArrayLib(0)
' -------------------------------------------------------------- '


Redim things(5) ' Make it hold five things

For i = 1 To 5
	things(i) = 5^i
	Print i, things(i)
Next i

Print "UBound before redim preserve: "; UBound(things())

Call RedimPreserve things(), 10

Print "UBound after redim preserve: "; UBound(things())

End


Function UBound(array())
    ' Returns the upper index limit of array().
    ' ---------------------------------------------------------- '
    ' Special thanks to Richard for the implementation of the
    ' binary chop method.
    ' ---------------------------------------------------------- '
    s = 2^24
    do
        On Error Goto [Error]
        [Error]
        s = int(s / 2)
        temp = array(UBound + s)
        UBound = UBound + s
    loop until s = 0
End Function



Sub RedimPreserve array(), newSize
	' Redimensions the given one-dimensional array() to the
	' specified newSize.
    ' ---------------------------------------------------------- '
	' Array indexes begin at 0, so keep that in mind when
	' specifying newSize.
	' ---------------------------------------------------------- '
	u = UBound(array()) ' Get the upper limit
	Redim ArrayLib(u)
	For i = 0 To u
        ArrayLib(i) = array(i) ' Get old contents
	Next i
	Redim array(newSize) ' Resize given array.
	For i = 0 To u
        array(i) = ArrayLib(i) ' Replace old contents that were lost.
	Next i
End Sub 

Re: Passing Arrays
Post by Richard Russell on Mar 13th, 2014, 9:55pm

on Mar 13th, 2014, 9:20pm, JosephE wrote:
Note that it doesn't even output the last print statement

Something really screwy is happening there. Leave it with me and I'll try to figure it out. Sorry for the inconvenience. embarassed

Richard.

Re: Passing Arrays
Post by JosephE on Mar 13th, 2014, 9:56pm

on Mar 13th, 2014, 9:55pm, Richard Russell wrote:
Something really screwy is happening there. Leave it with me and I'll try to figure it out. Sorry for the inconvenience.


Okay, thank you! There's no inconvenience. This is just my spring break hobby programming time XD
Re: Passing Arrays
Post by Richard Russell on Mar 13th, 2014, 10:23pm

on Mar 13th, 2014, 9:55pm, Richard Russell wrote:
Leave it with me and I'll try to figure it out.

Right, I'm awfully sorry but although LBB allows you to pass an entire array to a SUB or FUNCTION you can't REDIM it inside the function. Unfortunately it doesn't report an error if you try, but just crashes in a strange way as you have discovered.

So I'm afraid you won't be able to make a RedimPreserve function that way. sad

Richard.
Re: Passing Arrays
Post by JosephE on Mar 13th, 2014, 10:25pm

Ah, okay, that's what I was afraid of. It's not a huge deal. smiley
Re: Passing Arrays
Post by Richard Russell on Mar 14th, 2014, 12:34am

on Mar 13th, 2014, 10:25pm, JosephE wrote:
Ah, okay, that's what I was afraid of. It's not a huge deal. smiley

It would be possible to modify LBB so RedimPreserve can work, but I am unsure whether the benefit justifies the effort. What do you (and others) think?

Richard.

Re: Passing Arrays
Post by JosephE on Mar 14th, 2014, 02:47am

on Mar 14th, 2014, 12:34am, Richard Russell wrote:
It would be possible to modify LBB so RedimPreserve can work, but I am unsure whether the benefit justifies the effort. What do you (and others) think?


Obviously I would be in favor of that.

However, if you simply added the preserve functionality like in Visual BASIC (or any other syntax you prefer), I wouldn't even need to write the subroutine ;)

As in:
Code:
ReDim Preserve array(newSize) 

Re: Passing Arrays
Post by Richard Russell on Mar 14th, 2014, 05:15am

on Mar 14th, 2014, 02:47am, JosephE wrote:
However, if you simply added the preserve functionality

It's not simple! For a start it would involve adding a new keyword PRESERVE which raises issues of compatibility with programs which might have used it as a variable name. Then there's the fact that BBC BASIC, which is the underlying technology behind LBB, doesn't support that functionality natively so it would have to be bodged using a technique similar to yours. And one would have to consider whether it was sensible to add REDIM PRESERVE without at the same time adding other array-related functionality such as a UBOUND function.

On the other hand tweaking LBB so that your technique actually works should be relatively straightforward and safe.

Richard.
Re: Passing Arrays
Post by JosephE on Mar 14th, 2014, 08:49am

on Mar 14th, 2014, 05:15am, Richard Russell wrote:
On the other hand tweaking LBB so that your technique actually works should be relatively straightforward and safe.


I can definitely live without it. But if you get bored, there's an idea haha.
Re: Passing Arrays
Post by Richard Russell on Mar 14th, 2014, 11:59am

on Mar 14th, 2014, 08:49am, JosephE wrote:
I can definitely live without it. But if you get bored, there's an idea haha.

If I need to release a new version for another reason, perhaps to fix a bug, I will definitely incorporate the modification at the same time. If I'd known about your requirement a day earlier I could have included it in v2.52, but there you go.

Richard.

Re: Passing Arrays
Post by JosephE on Mar 14th, 2014, 6:11pm

Okay, I edited the wiki page on arrays to mention that limitation for the time being. smiley
Re: Passing Arrays
Post by Richard Russell on Mar 14th, 2014, 8:49pm

on Mar 14th, 2014, 6:11pm, JosephE wrote:
I edited the wiki page on arrays to mention that limitation for the time being.

Many thanks for the valuable contributions to the Wiki.

Richard.
Re: Passing Arrays
Post by JosephE on Mar 14th, 2014, 10:36pm

You bet! I've been learning a lot about LBB and I figured I'd help you document it.
Re: Passing Arrays
Post by Richard Russell on Mar 16th, 2014, 11:08am

on Mar 13th, 2014, 9:20pm, JosephE wrote:
Code:
' Simple Array Functions
' by Joseph Essin 

If you are working with arrays, you will be interested to know that LBB supports some whole-array arithmetic operations, for example adding two arrays together without needing to code a loop:

Code:
    a() = b() + c() 

Previously this facility has been undocumented (frankly I had forgotten that it was supported!) but now I've written a Wiki article listing the various things you can do:

http://bb4w.wikispaces.com/Array+arithmetic

Richard.
Re: Passing Arrays
Post by JosephE on Mar 16th, 2014, 10:41pm

on Mar 16th, 2014, 11:08am, Richard Russell wrote:
If you are working with arrays, you will be interested to know that LBB supports some whole-array arithmetic operations, for example adding two arrays together without needing to code a loop


Wow, that's amazing. And very handy.
Re: Passing Arrays
Post by Richard Russell on Mar 22nd, 2014, 10:52pm

on Mar 13th, 2014, 9:20pm, JosephE wrote:
I'm trying to make a few functions to do a redim preserve

The code below now works; it requires LBB v2.53, and the BYREF is essential to allow the array to be redimensioned inside the function/sub:

Code:
' Simple Array Functions
' by Joseph Essin
' Feel free to use in your own code. No need to credit me.
'
' For use with LBB:
' http://www.bbcbasic.co.uk/lbb/
'
' The functionality to make this work is not found in
' Liberty BASIC alone. This is for use with Richard Russell's
' Liberty BASIC Booster "compiler."
'
' Please find LBB below:
'
' http://www.bbcbasic.co.uk/lbb/
' -------------------------------------------------------------- '

' These are necessary for the Array Library.
' Don't name any of your arrays these names
' or you'll be subject to data loss.
Redim ArrayLib(0)
' -------------------------------------------------------------- '


Redim things(5) ' Make it hold five things

For i = 1 To 5
	things(i) = 5^i
	Print i, things(i)
Next i

Print "UBound before redim preserve: "; UBound(things())

Call RedimPreserve things(), 10

Print "UBound after redim preserve: "; UBound(things())

End


Function UBound(array())
    ' Returns the upper index limit of array().
    ' ---------------------------------------------------------- '
    ' Special thanks to Richard for the implementation of the
    ' binary chop method.
    ' ---------------------------------------------------------- '
    s = 2^24
    do
        On Error Goto [Error]
        [Error]
        s = int(s / 2)
        temp = array(UBound + s)
        UBound = UBound + s
    loop until s = 0
End Function



Sub RedimPreserve byref array(), newSize
	' Redimensions the given one-dimensional array() to the
	' specified newSize.
    ' ---------------------------------------------------------- '
	' Array indexes begin at 0, so keep that in mind when
	' specifying newSize.
	' ---------------------------------------------------------- '
	u = UBound(array()) ' Get the upper limit
	Redim ArrayLib(u)
	For i = 0 To u
        ArrayLib(i) = array(i) ' Get old contents
	Next i
	Redim array(newSize) ' Resize given array.
	For i = 0 To u
        array(i) = ArrayLib(i) ' Replace old contents that were lost.
	Next i
End Sub 

Richard.
Re: Passing Arrays
Post by JosephE on Mar 23rd, 2014, 11:33pm

on Mar 22nd, 2014, 10:52pm, Richard Russell wrote:
The code below now works; it requires LBB v2.53, and the BYREF is essential to allow the array to be redimensioned inside the function/sub:


Wow, you've been busy! Thank you smiley
Re: Passing Arrays
Post by bluatigro on Feb 17th, 2015, 09:56am


pasing arrays into subs and functions
ok thats nice

but how do i make a function that outputs a array ?
Re: Passing Arrays
Post by Richard Russell on Feb 17th, 2015, 11:47am

on Feb 17th, 2015, 09:56am, bluatigro wrote:
but how do i make a function that outputs a array ?

You pass the array BYREF, as follows:

Code:
    call mySub myArray()
    print myArray(50)
    end

sub mySub byref a()
    dim a(100)
    a(50) = 12345
end sub 

Here myArray() does not yet exist when the sub is called; the local array a() is created inside the sub and then passed back to the caller as myArray(). On return from the sub a() ceases to exist.

LB 4 doesn't have any functionality like this; arrays are always global so it is impossible to write a general-purpose function which operates on any specified array. This is in my opinion a major weakness.

Richard.
Re: Passing Arrays
Post by JosephE on Mar 1st, 2015, 03:07am

Just wanted to follow up and say thanks for your help. The ability to re-dimension arrays and preserve their contents is very useful. smiley
Re: Passing Arrays
Post by JosephE on Mar 1st, 2015, 03:36am

In fact, here's an up-to-date version of the code that supports scaling of string and numeric arrays:

Code:
' Simple Array Functions
' by Joseph Essin and Richard Russell
'
' For use with LBB:
' http://www.bbcbasic.co.uk/lbb/
'
' The functionality to make this work is not found in
' Liberty BASIC alone. This is for use with Richard Russell's
' Liberty BASIC Booster "compiler." Richard even customized LBB
' to allow these user-defined functions to work.
'
' Please find LBB below:
' http://www.bbcbasic.co.uk/lbb/
' -------------------------------------------------------------- '

' -------------------------------------------------------------- '
' These are necessary for the Array Library.
' Don't name any of your arrays these names
' or you'll be subject to data loss.
redim ArrayLib(0)
redim ArrayLib$(0)
' -------------------------------------------------------------- '
function nsize(array())
  ' Returns the upper index limit of the numeric array array().
  s = 2^24
  do
    on error goto [Error]
    [Error]
    s = int(s / 2)
    temp = array(nsize + s)
    nsize = nsize + s
  loop until s = 0
end function

function size(array$())
  ' Returns the upper index limit of the string array array$().
  s = 2^24
  do
    on error goto [Error]
    [Error]
    s = int(s / 2)
    temp$ = array$(size + s)
    size = size + s
  loop until s = 0
end function

sub preserve byref array(), newSize
	' Redimensions the given one-dimensional numeric array to the
	' specified newSize.
	u = nsize(array()) ' Get the upper limit
	redim ArrayLib(u)
	for i = 0 To u
    ArrayLib(i) = array(i) ' Get old contents
	next i
	redim array(newSize) ' Resize given array.
	for i = 0 To u
    array(i) = ArrayLib(i) ' Replace old contents
	next i
end sub

sub preserve$ byref array$(), newSize
	' Redimensions the given one-dimensional string array to the
	' specified newSize.
	u = size(array$()) ' Get the upper limit
	redim ArrayLib$(u)
	for i = 0 To u
    ArrayLib$(i) = array$(i) ' Get old contents
	next i
	redim array$(newSize) ' Resize given array.
	for i = 0 To u
    array$(i) = ArrayLib$(i) ' Replace old contents
	next i
end sub