PlanetSquires Forums

Please login or register.

Login with username, password and session length
Advanced search  

Author Topic: Choose function from Visual Basic  (Read 196 times)

Bumblebee

  • Little Newbie
  • *
  • Posts: 44
Choose function from Visual Basic
« on: May 21, 2020, 06:45:43 PM »

Would it be possible to recreate the choose function in FreeBasic?

Function Choose(Index As Single, ParamArray Choice() As Variant)
Member of VBA.Interaction
Selects and returns a value from a list of arguments
eg. a = Choose(n,"Blue","Green","Aqua","Yellow,"Gold")
If n = 2 then a = "Green"

Select Case seems to be a 'wasteful' alternative.
Best alternative I have is to Read/Data into an string array, then select from the array index.
Logged

Paul Squires

  • Administrator
  • Guru Member
  • *****
  • Posts: 9287
  • Windows 10
    • PlanetSquires Software
Re: Choose function from Visual Basic
« Reply #1 on: May 21, 2020, 08:46:09 PM »

Here is one way to do it. Functions that allow for a variable number of parameters can be problematic. That is because the function will GPF if you attempt to access an argument greater than the number of arguments in the list. For this reason, the programmer normally has to specify the number of items in the list. You will notice that FB has some built in functions that allow you pass a variable number of arguments (eg. CHR() ). To prevent a crash, the compiler passes to the runtime library function a hidden parameter to the CHR() function telling it how many arguments the programmer supplied in his code when calling the function.

I have shown two versions of the function. The first will crash if you specify a position more than number of of strings in the list (but the calling syntax is the same as the VB Choose function), whereas the second version is safer because there is an additional parameter whereby the programmer specifically specifies the number of strings in the list.

Code: [Select]

'' 
''  This function does not check that nPosition is within the
''  valid range of choices (there is no built in way to know
''  how many variable arguments exist until they are processed
''  at runtime).
''
function strChoose cdecl ( byval nPosition as long, ... ) as string
   dim as zstring ptr pzs
   dim as string st
   
   dim as cva_list args
   
   cva_start( args, nPosition )

   for i as long = 1 to nPosition
      pzs = cva_arg( args, zstring ptr)
      if i = nPosition then
         st = *pzs
         exit for
      end if
   next
   
   cva_end( args )
   
   function = st
end function
 

''
''  This version prevents crashes when nPosition exceeds the variable
''  list of choices by comparing against the programmer supplied numArgs.
''
function strChoose2 cdecl ( byval nPosition as long, byval numArgs as long, ... ) as string
   dim as zstring ptr pzs
   dim as string st
   
   dim as cva_list args
   
   cva_start( args, numArgs )

   for i as long = 1 to nPosition
      if i > numArgs then exit for
      pzs = cva_arg( args, zstring ptr)
      if i = nPosition then
         st = *pzs
         exit for
      end if
   next
   
   cva_end( args )
   
   function = st
end function


dim as long n = 2    ' will GPF is n > list of choices

dim as string a = strChoose( n,"Blue","Green","Aqua","Yellow","Gold")
? "a = "; a

n = 2   ' will not GPF because programmer has specified the list size
dim as string b = strChoose2( n, 5, "Blue","Green","Aqua","Yellow","Gold")
? "b = "; b

sleep

« Last Edit: May 21, 2020, 08:47:45 PM by Paul Squires »
Logged
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Paul Squires

  • Administrator
  • Guru Member
  • *****
  • Posts: 9287
  • Windows 10
    • PlanetSquires Software
Re: Choose function from Visual Basic
« Reply #2 on: May 21, 2020, 09:03:36 PM »

A way around this that C programmers use is to pass an additional value with your list with a null value.

So, instead of using this syntax:
dim as string c = strChoose3( n, "Blue","Green","Aqua","Yellow","Gold" )

You use this syntax:
dim as string c = strChoose3( n, "Blue","Green","Aqua","Yellow","Gold", 0 )   '<--- notice the terminating Null (0)

Code: [Select]
'' 
''  This function does not check that nPosition is within the
''  valid range of choices but will exit if the last supplied
''  argument is NULL
''
function strChoose3 cdecl ( byval nPosition as long, ... ) as string
   dim as zstring ptr pzs
   dim as string st
   
   dim as cva_list args
   
   cva_start( args, nPosition )

   for i as long = 1 to nPosition
      pzs = cva_arg( args, zstring ptr)
      if pzs = 0 then exit for
      if i = nPosition then
         st = *pzs
         exit for
      end if
   next
   
   cva_end( args )
   
   function = st
end function


n = 2
dim as string c = strChoose3( n, "Blue","Green","Aqua","Yellow","Gold", 0 )
? "c = "; c

sleep
Logged
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Bumblebee

  • Little Newbie
  • *
  • Posts: 44
Re: Choose function from Visual Basic
« Reply #3 on: May 22, 2020, 08:14:55 AM »

Thank-you for the examples.
This description suggests that the null value approach was taken:
https://docs.microsoft.com/en-us/openspecs/microsoft_general_purpose_programming_languages/ms-vbal/2f178971-8a8b-4d07-a21e-d0fa82b9db7c
From my limited understanding VB is an interpreted language.

I'll test your functions out, however there are 23 items to choose from.
In the original VB code, I had broken these into 3 separate choose functions of 9,9 and 5 items.
You can see why I don't want to use Select/Case.
Read/Data is not available in VB, so that's a new option I can consider.
Logged