The 3 dots Sub querry

Post

Posted
Rating:
#1 (In Topic #516)
Avatar
Guru
cogier is in the usergroup ‘Guru’
Hi,

Can anybody tell me what the 3 dots do as the help example is not very helpful! The text below is taken from here.
<HR>[hr][/hr]</HR>
Passing extra arguments to another function

SINCE 3.6

The … keyword can be used to transmit the extra arguments to another function accepting them.
Example

Code (gambas)

  1. Sub PrintMessage(sType As String, sFormat As String, ...)
  2.  
  3.   ' Do some stuff
  4.  
  5.  
  6. Sub PrintWarning(sFormat As String, ...)
  7.  
  8.   PrintMessage("warning", sFormat, ...)
  9.  
  10.  
Online now: No Back to the top

Post

Posted
Rating:
#2
Guru
BruceSteers is in the usergroup ‘Guru’
Lol , yeah , that example does not seem to actually pass any arguments it just shows how to , as it has already described lol.

I find a lot of that in Gambas help.
The help text seems to say nothing more than what is obvious.

Like Control.Public    (sets control to Public)    aaah i see, I'd have never guessed ;) lol
(I actually edited that wiki page to be a bit more descriptive)
Online now: No Back to the top

Post

Posted
Rating:
#3
Avatar
Regular
stevedee is in the usergroup ‘Regular’

cogier said

Hi,

Can anybody tell me what the 3 dots do as the help example is not very helpful! …

Here is a simple example…

Code (gambas)

  1. Public Sub Button1_Click()
  2.  
  3.   ThreeDots(TextBox1.Text, TextBox2.Text, TextBox3.Text)
  4.  
  5.  
  6. Public Function ThreeDots(strName As String, strGender As String, ...) As Boolean
  7.  
  8.   Message.Info(strName & " is " & strGender, ...)
  9.  
  10.  

…but I'll try to think of a better one after lunch.
Online now: No Back to the top

Post

Posted
Rating:
#4
Avatar
Regular
stevedee is in the usergroup ‘Regular’
OK, so the 3 dots allow you to pass any data type (I think) so in the example above you could add:-

Code (gambas)

  1. Public Sub Button2_Click()
  2.  
  3.   ThreeDots(TextBox1.Text, TextBox2.Text, True)
  4.   CanDisplayName(TextBox1.Text, TextBox2.Text, ...)
  5.  
  6.  
  7. Public Function CanDisplayName(strName As String, blnChoice As Boolean) As Boolean
  8.  
  9.   If blnChoice Then
  10.     Me.text = "OK to display name"
  11.  


Where 3dot variable is now type boolean.


…still not a great example, but does this help?
Online now: No Back to the top

Post

Posted
Rating:
#5
Avatar
Regular
stevedee is in the usergroup ‘Regular’
OK, it gets a bit more interesting when you have potentially an unknown number of arguments at the time that you write a Method for some Class.

In this example, the functions ThreeMoreDots & LoadData can cope with a variable bunch of data. Obviously the Button function in this case is only creating 10 data variables.

Code (gambas)

  1. Public iarrNumbers As New Integer[100]
  2.  
  3. Public Sub Button4_Click()
  4.  
  5.   For index = 0 To 9
  6.     iarrNumbers[index] = index
  7.   Next
  8.   Me.Text = CStr(ThreeMoreDots("Lucky Numbers", iarrNumbers))
  9.  
  10.  
  11.  
  12. Public Function ThreeMoreDots(strDataSeries As String, ...) As String
  13.  
  14.   Return LoadData(strDataSeries, ...)
  15.  
  16.  
  17. Public Function LoadData(sDataSeries As String, arrData As Integer[]) As String
  18.  
  19.   For index = 0 To arrData.Max
  20.     iSum += arrData[index]
  21.   Next
  22.   Return "Sum of data series called;  " & sDataSeries & ": " & CStr(iSum)
  23.      

I can't see any other way of referencing  the data other than using it as an argument to a Sub/Function (hence the LoadData function above).

It would be very nice if:-

Code (gambas)

  1. intType = TypeOf(...)
worked, but it doesn't.

The … in Gambas is basically an implementation of "variadic" function that you will find in other languages (Variadic function - Wikipedia)

Its seems to be generally regarded as a bad idea! This is mainly because the data presented to the method may not be the correct type.
Online now: No Back to the top

Post

Posted
Rating:
#6
Avatar
Guru
cogier is in the usergroup ‘Guru’
 Hi Steve,

Thanks for the code and explanation, I can see why you say it's a bad idea you could end up with any old data being passed! Code can often be hard to read but this would just add even more confusion.

I can't see why anybody would want to use it, unless someone has a good reason for it that I can't see….?

(I deleted you duplications)
Online now: No Back to the top

Post

Posted
Rating:
#7
Avatar
Regular
stevedee is in the usergroup ‘Regular’
It looks to me as if there is something missing in Gambas. Some other languages have built in methods to help with this.

Take a look at this Basic implementation: Variadic function - Rosetta Code
Online now: No Back to the top

Post

Posted
Rating:
#8
Guru
BruceSteers is in the usergroup ‘Guru’
I dunno , it seems to work.
It looks to me just like a way of saving writing extra unneeded code when you want to pass a load of arguments through one function to another but not really need them in the first function.

If you consider this example…
as the form loads it calls Test() with a load of arguments.
The Test() function only wants the sName argument and it then calls PrintTest() that does want all the args.

Code (gambas)

  1. Public Sub Form_Open()
  2.  
  3.   Test("value of one", "1", 1, 1)
  4.   Test("value of one & 1/2", "1.5", 1.5, 1.5)
  5.  
  6.  
  7. Public Sub Test(sName As String, ...)
  8.  
  9.   Print "running Test " & sName
  10.   PrintTest(sName, ...)
  11.  
  12.  
  13. Public Sub PrintTest(sName As String, sVar As String, iVar As Integer, vVar As Variant)
  14.  
  15.   Print "name: "; sName
  16.   Print "text: "; sVar
  17.   Print "integer: "; Str(iVar)
  18.   Print "TypeValue:"; TypeOf(vVar); ": "; Str(vVar)
  19.  
  20.  
  21.  


So there the function Test()

I have not needed to use

Code (gambas)

  1. Public Sub Test(sName As String, sVar As String, iVar As Integer, vVar As Variant)
  2.  
  3.   Print "running Test " & sName
  4.   PrintTest(sName, sVar, iVar, vVar)
  5.  
  6.  

and pass all the arguments that PrintTest() wants but Test() does not , the … takes care of it.

As for variable types and using an unknown count of args i guess that's up to the programmer. If you was not using the … method but filling in the fields like in the lower example then your types would be known and taken care off. and for unknown quantities you would use an array[]
Online now: No Back to the top

Post

Posted
Rating:
#9
Guru
BruceSteers is in the usergroup ‘Guru’

cogier said

Hi,

Can anybody tell me what the 3 dots do as the help example is not very helpful!

You were right about the info not being helpful
I found it a bit confusing too.

I thought it needed an update to be clearer.

Now it reads more like this.

Passing extra arguments to another function
Since 3.6

If you pass a number of arguments to function1() and it then passes them to Function2() but does not use them.
The … keyword can be used to transmit the extra arguments to the function accepting them.

Example

Code (gambas)

  1. Sub GotWarning()
  2.  
  3.   ProcessSomething("warning", "format description", "info")
  4.  
  5.  
  6. Sub ProcessSomething(sType As String, ...)
  7.  
  8.   Print "Got message type " & sType
  9.   ' Do something with sType
  10.  
  11.   PrintMessage(sType, ...)
  12.  
  13.  
  14. Sub PrintMessage(sType As String, sFormat As String, sInfo As String)
  15.  
  16.   ' Do some stuff with the arguments passed.
  17.  
  18.  
Online now: No Back to the top

Post

Posted
Rating:
#10
Guru
BruceSteers is in the usergroup ‘Guru’

stevedee said


I can't see any other way of referencing  the data other than using it as an argument to a Sub/Function (hence the LoadData function above).

It would be very nice if:-

Code (gambas)

  1. intType = TypeOf(...)
worked, but it doesn't.

The … in Gambas is basically an implementation of "variadic" function that you will find in other languages (Variadic function - Wikipedia)

Its seems to be generally regarded as a bad idea! This is mainly because the data presented to the method may not be the correct type.

I don't think it's been designed like that.
It's not something you can address or access in any way it's just a keyword to pass arguments through to another function.
 (like the LoadData function).

Cant see how you'd do it in gambas with the way it already uses dots for oop

I tried checking […].Count but it says "unexpected …"
….Count is a no no too.

Handy though.
I've passed many an argument through to another that i didn't need to, will keep … in mind  :)
Online now: No Back to the top

Post

Posted
Rating:
#11
Guru
BruceSteers is in the usergroup ‘Guru’
Doh! we all missed it.

Param class
/comp/gb/param - Gambas Documentation

Param.Count
Param.All

this deals with the … arguments lol.

Better adjust the wiki again.
 :roll:
Online now: No Back to the top

Post

Posted
Rating:
#12
Guru
BruceSteers is in the usergroup ‘Guru’
I've updated the wiki again.

I think the main problem for us was the info about using Param.class was shown before the previous example and not in the bit about using … so we all missed it :-\

Do you think the wiki explains it better now?

/lang/methoddecl - Gambas Documentation
Online now: No Back to the top

Post

Posted
Rating:
#13
Avatar
Regular
stevedee is in the usergroup ‘Regular’

BruceSteers said

…Do you think the wiki explains it better now?

I need some 'quality thinking time' to do this justice, which I don't have right now. But my initial reaction would be to show 2 examples rather than lumping it all together:-

Example 1: Variadic Function

Code (gambas)

  1. Sub Main()
  2.  
  3.   ProcessVariadic("warning", "format description", "info", -1)
  4.  
  5.  
  6.  
  7. Sub ProcessVariadic(...)
  8.  
  9. ' Here we use the Param class to access and print all arguments supplied via "..." (you must take care of variable types if they are unknown)
  10.  
  11. Print "There are " & Param.Count & " arguments"
  12.  
  13.  Dim iType As Integer
  14.  
  15.   For Each vVar As Variant In Param.All
  16.  
  17.   iType = TypeOf(vVar)
  18.  
  19.     If iType = gb.String Then
  20.        Print "Arg is a String: " & vVar
  21.     Else If iType = gb.Integer Then
  22.        Print "Arg is Integer: " & Str(vVar)
  23.     Endif
  24.  
  25.   Next
  26.  
  27.  
  28.  

I'd probably replace the If…then…else block in the above with Select Case as there are several data types that require filtering.
A cleaned-up version could also be posted on the Rosetta Code wiki: Variadic function - Rosetta Code {Charlie likes doing that}
_______________

Example 2:  Function to Function?

Code (gambas)

  1. Sub Main()
  2.  
  3.   PassSomeArgs("warning", "format description", "info")
  4.  
  5.  
  6.  
  7. Sub PassSomeArgs(sType As String, ...)
  8.  
  9.   ' Do something with sType and pass all the other args to the next function.
  10.  
  11.   Print "Got message type " & sType
  12.  
  13.   PrintMessage(sType, ...)
  14.  
  15.  
  16. Sub PrintMessage(sType As String, sFormat As String, sInfo As String)
  17.  
  18.   ' Do some stuff with the known number of arguments passed.
  19.  
  20.  
  21.  
  22.  
  23.  

…but I've lost-the-plot with this example, so this is where I need some time to give it more thought.

I hope this is of some help Bruce
Online now: No Back to the top

Post

Posted
Rating:
#14
Guru
BruceSteers is in the usergroup ‘Guru’

stevedee said

BruceSteers said

…Do you think the wiki explains it better now?

I need some 'quality thinking time' to do this justice, which I don't have right now. But my initial reaction would be to show 2 examples rather than lumping it all together:-

Example 1: Variadic Function

Code (gambas)

  1. Sub Main()
  2.  
  3.   ProcessVariadic("warning", "format description", "info", -1)
  4.  
  5.  
  6.  
  7. Sub ProcessVariadic(...)
  8.  
  9. ' Here we use the Param class to access and print all arguments supplied via "..." (you must take care of variable types if they are unknown)
  10.  
  11. Print "There are " & Param.Count & " arguments"
  12.  
  13.  Dim iType As Integer
  14.  
  15.   For Each vVar As Variant In Param.All
  16.  
  17.   iType = TypeOf(vVar)
  18.  
  19.     If iType = gb.String Then
  20.        Print "Arg is a String: " & vVar
  21.     Else If iType = gb.Integer Then
  22.        Print "Arg is Integer: " & Str(vVar)
  23.     Endif
  24.  
  25.   Next
  26.  
  27.  
  28.  

I'd probably replace the If…then…else block in the above with Select Case as there are several data types that require filtering.
A cleaned-up version could also be posted on the Rosetta Code wiki: Variadic function - Rosetta Code {Charlie likes doing that}
_______________

Example 2:  Function to Function?

Code (gambas)

  1. Sub Main()
  2.  
  3.   PassSomeArgs("warning", "format description", "info")
  4.  
  5.  
  6.  
  7. Sub PassSomeArgs(sType As String, ...)
  8.  
  9.   ' Do something with sType and pass all the other args to the next function.
  10.  
  11.   Print "Got message type " & sType
  12.  
  13.   PrintMessage(sType, ...)
  14.  
  15.  
  16. Sub PrintMessage(sType As String, sFormat As String, sInfo As String)
  17.  
  18.   ' Do some stuff with the known number of arguments passed.
  19.  
  20.  
  21.  

…but I've lost-the-plot with this example, so this is where I need some time to give it more thought.

I hope this is of some help Bruce

the PassSomeArgs() function shows how to use … to simply pass arguments through one function to another, no need to use Param that way as you know the amount of args and types.
It saves typing the following…

Code (gambas)

  1. Sub PassSomeArgs(sType As String, sFormat As String, sInfo As String)
  2.  
  3.   Print "Got message type " & sType
  4.   PrintMessage(sType, sFormat, sInfo)
  5.  
  6.  

As sFormat and sInfo are not used in the PassSomeArgs() function it shows the additional args can be passed through using …
I was trying to keep the examples simple as it's already quite big on the page wasn't looking to show how to handle every variable type, just a simple example showing the basics, which is more than it did do..
I might make a more detailed example in a separate page and link to it instead.
Online now: No Back to the top

Post

Posted
Rating:
#15
Avatar
Regular
stevedee is in the usergroup ‘Regular’
Well, I can't see the point of the 2nd example (Function to Function, or whatever you want to call it).

If you need to know what the datatype is that's passed by "…" to the second function, whats the point?
Seems to me that you could replace the 2 functions with one function.

When do you need to deal with an unknown quantity of arguments or characters?
When you open a string file, there are methods to deal with any length of the string.
When you grab stuff from a website, you can use a Collection (or a JSONCollection) to handle the data.

Also, why does my Message example work when there is no mention in Help that it should?

There also seems to be confusion with the use of "…" in Help files. Here is one example:-

Code

Value = Choose ( Choice , Result1 , Result2 [ , ... ] )


I think [, …] just means 'and so on'

In fact if you look closely at "methoddecl" you will see two versions of 3 dots.


Code

[ FAST [ UNSAFE] ] [ STATIC ] \{ PUBLIC | PRIVATE } \{ PROCEDURE | SUB }
  Identifier
  (
    [ [ BYREF ] Parameter AS Datatype [ , … ] ] [ , ]
    [ OPTIONAL [ BYREF ] Optional Parameter AS Datatype [ , … ] ] [ , ] [ ... ]
  )
  ...
END


I think its a mess and needs a "not recommended for use" warning.
Online now: No Back to the top

Post

Posted
Rating:
#16
Guru
BruceSteers is in the usergroup ‘Guru’
Well, I can't see the point of the 2nd example (Function to Function, or whatever you want to call it).

If you need to know what the datatype is that's passed by "…" to the second function, whats the point?
Seems to me that you could replace the 2 functions with one function.

I'd call it Pass Some Args. like the function name.
It's more about saving writing code, yes the 2 functions could be one but what if the code was far more complex and it was simpler to do it that way. perhaps you have a bunch of args to pass to a couple of functions but don't want to set global variables.
Maybe the use of it that way does not suit your coding style but it may suit someone else.

When do you need to deal with an unknown quantity of arguments or characters?

myUnknownQuantityOfArgs=Args.All.Copy  ?  for one.


Also, why does my Message example work when there is no mention in Help that it should?
err I have no idea what this refers to.

There also seems to be confusion with the use of "…" in Help files. Here is one example:-

Code: Select all

Value = Choose ( Choice , Result1 , Result2 [ , … ] )


I think [, …] just means 'and so on'

In fact if you look closely at "methoddecl" you will see two versions of 3 dots.

Code: Select all

[ FAST [ UNSAFE] ] [ STATIC ] { PUBLIC | PRIVATE } { PROCEDURE | SUB }
  Identifier
  (
    [ [ BYREF ] Parameter AS Datatype [ , … ] ] [ , ]
    [ OPTIONAL [ BYREF ] Optional Parameter AS Datatype [ , … ] ] [ , ] [ … ]
  )
  …
END


I think its a mess and needs a "not recommended for use" warning.

I think it just needs clarity, I've done the best i can with my knowledge.
But i can see many uses for the function if understood better how it all works.
The wiki last week was rubbish and showed nothing. We all missed the bit about using Param.class as the info was misplaced on the page.
It's not perfect and it's not handling every possible thing as it's a simple example on a help page.
I think it's clearer and covering the bases better now though even if you don't see the point in using it that way , can you see it can be used that way?

You're right about the possible confusion between the actual use of … keyword and … meaning and so on.
Probably won't matter as it's only on that page where Param and … are a keyword. I'm sure most will twig the difference.

Bruce
Online now: No Back to the top

Post

Posted
Rating:
#17
Guru
BruceSteers is in the usergroup ‘Guru’
Essentially the … keyword seems a waste of time if you consider the alternatives, a simple Array[]

you could use

MyFunction(…)

' use Param to get all args if any.

End

Or you could use

MyFunction(Optional MyArgs As Variant[])

' Use the array.

End

But it's there . and it will suit the coding style of some.
:)
Online now: No Back to the top

Post

Posted
Rating:
#18
Avatar
Regular
stevedee is in the usergroup ‘Regular’

BruceSteers said

…I think it just needs clarity, I've done the best i can with my knowledge…

Bruce, you are doing a great job!

…but you did ask for input. My opinion is just that…my opinion.
Its up to you (as you have taken on this task) to apply a garbage filter and use what you think is appropriate.

In my view, the Help system for Microsoft Visual Basic 6 (Not .NET) is the Gold Standard. Just about everything in the language is covered with a description of the syntax followed by at least one, and often more than one example. I just couldn't believe how clearly everything about VB.Classic was laid out, having spent a few years previously working with Borlands Turbo Pascal.

Gambas was created to be the Visual Basic language for Linux, so it has always frustrated me that Gambas Help is not a patch on VB Help. The original disconnect between Methoddecl and the Param class is just one example. But there are probably many more where cross-referencing would be helpful, maybe even essential.

I think Gambas could of had a much larger user base if the documentation had been sorted out 10 years ago.

…but hey! that's just my opinion!
Online now: No Back to the top
1 guest and 0 members have just viewed this.