Nice. (to fill 10 chars)
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:
Obviously, the most burdensome aspect of this function is just handling all the potential optional arguments and putting them into an array.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
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.
Nice. (to fill 10 chars)
I think there are missing some Forum-sections as beta-testing and support
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
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)
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
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:
Within the SUB/FUNCTION, array bounds would be determined using UBOUND as usual.Sub foo(Byval S1() As String, Byval S2() As String)
Second, each bracketed expression would get assigned to a temporary array, then passed to the function. In this case,
would be turned into the equivalent of this:foo(["Hello", "This", "Is", "S1"], ["And", "This", "Is", "S2"])
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.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 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.
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.
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:
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.FUNCTION FOO ( S(OPTIONAL) AS STRING) AS STRING FUNCTION FOO ( S ... AS STRING) AS STRING FUNCTION FOO ( S(...) AS STRING) AS STRING
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:
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: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
whereas the call the F2 is made just like it looks: Y = F2("ONE","TWO").DIM temp(2) AS STRING temp(1) = "ONE" temp(2) = "TWO" x = F1(temp)
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.
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:
and it should enable this way so for those too lazy to count theirselves:foo({"This","Is","S1"},{"Here", "Is", "S2"})
btw. that should work with numeral "array-assignements" also then.Dim A() as String = {"Hello", "I", "Am", "Element", "Five"} ' which equals Dim A() as String Array Assign A() = "Hello", "I", "Am", "Element", "Five"
Last edited by ReneMiner; 05-07-2013 at 18:26.
I think there are missing some Forum-sections as beta-testing and support
Bookmarks