Results 1 to 9 of 9

Thread: Idea about "VAR ARG" parameters

  1. #1

    Idea about "VAR ARG" parameters

    In the post regarding blank-delimited concatenation, a sample function was shown that took 16 arguments. 16 was an arbitrary number; we can put up to 32 if we are ambitious enough to type that many, but here is what it looked like:

    FUNCTION $ (S01 AS STRING, _
       OPTIONAL S02 AS STRING, _
                S03 AS STRING, _
                S04 AS STRING, _
                S05 AS STRING, _
                S06 AS STRING, _
                S07 AS STRING, _
                S08 AS STRING, _
                S09 AS STRING, _
                S10 AS STRING, _
                S11 AS STRING, _
                S12 AS STRING, _
                S13 AS STRING, _
                S14 AS STRING, _
                S15 AS STRING, _
                S16 AS STRING) AS STRING
    
        DIM I AS LONG, X(16) AS STRING, GAP AS STRING, RESULT AS STRING
    
        IF FUNCTION_CParams >= 01 THEN X(01) = S01
        IF FUNCTION_CParams >= 02 THEN X(02) = S02
        IF FUNCTION_CParams >= 03 THEN X(03) = S03
        IF FUNCTION_CParams >= 04 THEN X(04) = S04
        IF FUNCTION_CParams >= 05 THEN X(05) = S05
        IF FUNCTION_CParams >= 06 THEN X(06) = S06
        IF FUNCTION_CParams >= 07 THEN X(07) = S07
        IF FUNCTION_CParams >= 08 THEN X(08) = S08
        IF FUNCTION_CParams >= 09 THEN X(09) = S09
        IF FUNCTION_CParams >= 10 THEN X(10) = S10
        IF FUNCTION_CParams >= 11 THEN X(11) = S11
        IF FUNCTION_CParams >= 12 THEN X(12) = S12
        IF FUNCTION_CParams >= 13 THEN X(13) = S13
        IF FUNCTION_CParams >= 14 THEN X(14) = S14
        IF FUNCTION_CParams >= 15 THEN X(15) = S15
        IF FUNCTION_CParams >= 16 THEN X(16) = S16
    
        FOR I = 1 TO 16
            IF VERIFY (X(I), " ") > 0 THEN 
                RESULT = RESULT & GAP & X(I)
                GAP = " "
            END IF
        NEXT
        RETURN RESULT
    
    END FUNCTION
    
    Obviously, the most burdensome aspect of this function is just handling all the potential optional arguments and putting them into an array.

    The C language has long had a way to deal with this concept, using what is called "variable arguments", commonly abbreviated to VAR ARGS. This provides a way to access arguments on the 'stack' without knowing ahead of time what they were.

    I believe TB could fairly easily incorporate such a facility. It would be a matter of treating the arguments as a variable-length array of some given type. While a new keyword like VARARGS could be created to address this, there's no reason why OPTIONAL couldn't be used in a new way. The variable number of arguments would effectively be put into an array, whose size could be determined with a call to UBOUND.

    Here is the function above rewritten to use these concepts. Note how much shorter it is. Here, S(OPTIONAL) means that S is array of STRING values of varying size, which is determined by the UBOUND function.

    FUNCTION $ ( S(OPTIONAL) AS STRING ) AS STRING 
    
        DIM I AS LONG, GAP AS STRING, RESULT AS STRING
    
        FOR I = 1 TO UBOUND (S)
            IF VERIFY (S(I), " ") > 0 THEN 
                RESULT = RESULT & GAP & S(I)
                GAP = " "
            END IF
        NEXT
        RETURN RESULT
    
    END FUNCTION
    
    Last edited by Robert Hodge; 04-07-2013 at 16:03.

  2. #2
    thinBasic MVPs
    Join Date
    Oct 2012
    Location
    Germany
    Age
    54
    Posts
    1,530
    Rep Power
    171
    Nice. (to fill 10 chars)
    I think there are missing some Forum-sections as beta-testing and support

  3. #3
    Super Moderator Petr Schreiber's Avatar
    Join Date
    Aug 2005
    Location
    Brno - Czech Republic
    Posts
    7,128
    Rep Power
    732
    Hi Robert,

    interesting concepts as usually. Regarding passing of array with arbitrary dimensions - it is possible right now:
    String myArray(3) = "A", "B", "C"
    
    MsgBox 0, Func(myArray)
    
    Function Func( S() As String ) As String
     
        Dim I As Long, GAP As String, RESULT As String
     
        For I = 1 To UBound (S)
            If Verify (S(I), " ") > 0 Then
                RESULT = RESULT & GAP & S(I)
                GAP = " "
            End If
        Next
        Return RESULT
     
    End Function
    

    Petr
    Learn 3D graphics with ThinBASIC, learn TBGL!
    Windows 10 64bit - Intel Core i5-3350P @ 3.1GHz - 16 GB RAM - NVIDIA GeForce GTX 1050 Ti 4GB

  4. #4
    Quote Originally Posted by Petr Schreiber View Post
    Hi Robert,

    interesting concepts as usually. Regarding passing of array with arbitrary dimensions - it is possible right now:
    String myArray(3) = "A", "B", "C"
    
    MsgBox 0, Func(myArray)
    
    Function Func( S() As String ) As String
     
        Dim I As Long, GAP As String, RESULT As String
     
        For I = 1 To UBound (S)
            If Verify (S(I), " ") > 0 Then
                RESULT = RESULT & GAP & S(I)
                GAP = " "
            End If
        Next
        Return RESULT
     
    End Function
    
    Petr
    The key difference here is that you would not be passing an array, but individual parameters.

    So, you'd have a function header like

    Function Func( S(OPTIONAL) As String ) As String

    and then call it as x= Func ("ABC", "DEF") rather than an array argument. Basically, when TB saw the combination of

    Func( S(OPTIONAL) As String

    and

    x = Func ("ABC", "DEF")

    it would create some "parameter setup code" that did the equivalent of:

    DIM temp(2) AS STRING
    temp(1) = "ABC"
    temp(2) = "DEF"
    x = Func (temp)

  5. #5
    thinBasic MVPs
    Join Date
    Oct 2012
    Location
    Germany
    Age
    54
    Posts
    1,530
    Rep Power
    171
    I see some problem here:

    example

    Sub foo(Byval S1(Optional) As String, Byval S2(Optional) As String)

    how to determine which ends where? use brackets?

    foo(["Hello", "This", "Is", "S1"], ["And", "This", "Is", "S2"]) ???
    I think there are missing some Forum-sections as beta-testing and support

  6. #6
    Quote Originally Posted by ReneMiner View Post
    I see some problem here:

    example

    Sub foo(Byval S1(Optional) As String, Byval S2(Optional) As String)

    how to determine which ends where? use brackets?

    foo(["Hello", "This", "Is", "S1"], ["And", "This", "Is", "S2"]) ???
    That's an excellent question. The short answer is, given the proposed notation like S1(OPTIONAL), there could only be one such parameter in the function foo. For basically the same reason that the current OPTIONAL attribute applies to all parameters that follow it, you could only have one OPTIONAL array as a parameter.

    I think your bracket notation is brilliant. What you would probably call this is an "array constructor". How would that work?

    First, since the array constructor would construct a temporary, but ordinary (garden-variety) array, the (OPTIONAL) notation would not be needed in the function header, which would now look like this:

    Sub foo(Byval S1() As String, Byval S2() As String)
    
    Within the SUB/FUNCTION, array bounds would be determined using UBOUND as usual.

    Second, each bracketed expression would get assigned to a temporary array, then passed to the function. In this case,

    foo(["Hello", "This", "Is", "S1"], ["And", "This", "Is", "S2"])
    
    would be turned into the equivalent of this:

    DIM temp1(4), temp2(4) AS STRING
    
    temp1(1) = "Hello"
    temp1(2) = "This"
    temp1(3) = "Is"
    temp1(4) = "S1" 
    
    temp2(1) = "And"
    temp2(2) = "This"
    temp2(3) = "Is"
    temp2(4) = "S2"
    
    foo (temp1, temp2)
    
    The advantages of the "array constructor" syntax is that (a) it doesn't require new SUB/FUNCTION parameter syntax, (b) doesn't require coordination between the SUB/FUNCTION header declaration and the call to the function (that is, the code generation process is much less complex), existing functions that already take standard array arguments could be used with array-constructor arguments without having to rewrite the function argument(s) as NAME(OPTIONAL), and (d) it offers the ability to have more than one variable-length 'literal array' to be passed, as you suggest in your example code.

    The main difficulty I see is in setting up the temp arrays to pass parameters. You showed your sample 'foo' function as taking its parameters BYVAL, and that's fine. If for some reason you wanted to pass a bunch of variables BYREF, it might be trickier. I have confidence that Eros could figure that out, but it would be a little harder to implement.

    Only other issue to verify is that brackets aren't used anywhere else in TB. I don't think they are, but maybe some syntax is 'lurking around' somewhere that I'm not aware of. Eros would have to confirm that.

    Bracketed array constructors? I like.

  7. #7
    A form of ellipsis (...) could be the answer:

    function foo(s ... as string)
    'receive params as s(1),s(2) etc.
    end function

    foo "cabbage","king","shoe","" 'using empty string as end marker
    Last edited by Charles Pegge; 05-07-2013 at 15:52.

  8. #8
    Quote Originally Posted by Charles Pegge View Post
    A form of ellipsis (...) could be the answer:

    function foo(s ... as string)
    'receive params as s(1),s(2) etc.
    end function

    foo "cabbage","king","shoe","" 'using empty string as end marker
    The ... ellipsis notation is used in C/C++, and it's certainly possible. That would be an alternative to my OPTIONAL notation. Here, any of these would basically say the same thing:

    FUNCTION FOO ( S(OPTIONAL) AS STRING) AS STRING
    FUNCTION FOO ( S ... AS STRING) AS STRING
    FUNCTION FOO ( S(...) AS STRING) AS STRING
    
    etc. The specific syntax isn't that critical; you'd just have to decide on something that wouldn't break the language or the lexical scanner, and agree to it, then implement it.

    But, the point Rene brings up is a stronger one. If you are going to alter the calling sequence based on the function header, it complicates the language. Consider the following examples, where I will use the S(OPTIONAL) notation, just to pick one:

    X = F1("ONE", "TWO")
    Y = F2("ONE", "TWO")
    
    FUNCTION F1 ( S(OPTIONAL) AS STRING) AS STRING
        ...
    END FUNCTION
    
    FUNCTION F2 (S1 AS STRING, S2 AS STRING) AS STRING
        ...
    END FUNCTION
    
    The problem comes in when the calls are issued. By all appearances, the calls to F1 and F2 look "identical", but because F1 takes an OPTIONAL ARRAY, TB has to create a temporary STRING array, insert the values into it, then call the function, like this:

        DIM temp(2) AS STRING
        temp(1) = "ONE"
        temp(2) = "TWO"
        x = F1(temp)
    
    whereas the call the F2 is made just like it looks: Y = F2("ONE","TWO").

    So, TB can't just look at the call to the SUB/FUNCTION itself - it would have to coordinate the call with the information in the header to decide how to launch the function. That's quite a bit harder. Not that it can't be done, and I am sure Eros could figure this out if sufficiently motivated, but it would be a good bit of work. But - even if this were done - you would STILL have to alter the SUB/FUNCTION header with the new syntax, whether that was S(OPTIONAL) or S ... or whatever. That means any existing functions that took arrays could not be used; you'd have to have one version for arrays, and another for this OPTIONAL/'ellipsis' notation. Again, not that this couldn't be done, but you could not resue any existing code to take advantage of the new feature; you would have to write all new code.

    That's why I think Rene's "bracketed array constructor" idea is a better idea - better than mine even. It's easier to implement, and can be used for more things, and can be applied to existing function code that accepts array parameters.

  9. #9
    thinBasic MVPs
    Join Date
    Oct 2012
    Location
    Germany
    Age
    54
    Posts
    1,530
    Rep Power
    171
    If the brackets are used for something already - (was it some matrix-stuff for multi-dimensional arrays?) - one certainly could use those curly braces also:
    foo({"This","Is","S1"},{"Here", "Is", "S2"})
    
    and it should enable this way so for those too lazy to count theirselves:
    Dim A() as String = {"Hello", "I", "Am", "Element", "Five"}
    ' which equals
    
    Dim A() as String
    Array Assign A() = "Hello", "I", "Am", "Element", "Five"
    
    btw. that should work with numeral "array-assignements" also then.
    Last edited by ReneMiner; 05-07-2013 at 18:26.
    I think there are missing some Forum-sections as beta-testing and support

Similar Threads

  1. Is there a need for a new thinBasic-specific "idea" forum?
    By Robert Hodge in forum QOD: Question Of the Day
    Replies: 4
    Last Post: 10-06-2013, 22:53
  2. Forum: added "Auto Youtube Link-Converter" plugin
    By ErosOlmi in forum Web and Forum
    Replies: 0
    Last Post: 07-05-2011, 12:47
  3. Replies: 17
    Last Post: 21-02-2010, 07:45
  4. Uses "File", "Crypto" ... ???
    By marcuslee in forum thinBasic General
    Replies: 3
    Last Post: 01-12-2009, 19:38

Members who have read this thread: 0

There are no members to list at the moment.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •