Author Topic: Suggested Feature: Variable Parameter Procs/Funcs  (Read 4791 times)

0 Members and 1 Guest are viewing this topic.

Offline freetrav

  • Newbie
  • Posts: 45
    • View Profile
Suggested Feature: Variable Parameter Procs/Funcs
« on: August 24, 2018, 03:44:01 pm »
I recognize that QB64's primary goal is QBASIC/QuickBASIC compatibility, with MS BASIC PDS compatibility just behind that. Nevertheless, there is a feature I recall from a different BASIC, pre-QB, that I would like to see:

I'm not sure of the "formal" name for this capability, but it effectively allowed you to write your own functions and procedures that could take different parameters, and process them based on the number, position, type, etc., of the parameters passed to the function/procedure. A modern language in which this is implemented is PowerShell, with its notion of "ParameterSets". There's a barebones intro to the concept in PowerShell written by (retired) Scripting Guy Ed Wilson.

(The BASIC was Summit Software Technology's BetterBASIC, which looked like - had it been invented today - a hybrid between GW and Q, with some additional features borrowed from other languages. BetterBASIC implemented this particular feature somewhat awkwardly at the code level; you had to write the procedure as PROCNAME.A, PROCNAME.B, etc., for each possible allowable set of parameters - but when you called them, it was always called PROCNAME followed by the parameters. It did, however, allow you to extend builtins using the same method; if you wanted to handle PRINT specially for a user-defined structured type, you would write the procedure PRINT.A that took your user-defined type as a parameter and processed it. I'd prefer something closer to the PowerShell model, but I'm not hard-core about it; any reasonable way to get the effect will be satisfactory.)

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Suggested Feature: Variable Parameter Procs/Funcs
« Reply #1 on: August 24, 2018, 03:51:24 pm »
Hello,

This sounds like a request for OOP in a different guise. Good question really... Maybe some kind of library could be made to absract-up the way one can send parameters to functions, but I dont see this being a native QB64 feature around any corner ahead.
You're not done when it works, you're done when it's right.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Suggested Feature: Variable Parameter Procs/Funcs
« Reply #2 on: August 24, 2018, 03:58:48 pm »
Hello,

This sounds like a request for OOP in a different guise. Good question really... Maybe some kind of library could be made to absract-up the way one can send parameters to functions, but I dont see this being a native QB64 feature around any corner ahead.
o

Or a request for Overloading Functions/Subs:

SUB Sort (Array() AS INTEGER)
SUB Sort (Array() AS SINGLE)
SUB Sort (Array() AS STRING)

3 SUBS, all with the same name, and you'd just call them with:

Sort Myarray()

If the array is an integer, it'd go to the first routine.  Single arrays would go to the second, and strings would go to the third...
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

FellippeHeitor

  • Guest
Re: Suggested Feature: Variable Parameter Procs/Funcs
« Reply #3 on: August 24, 2018, 04:12:52 pm »
Both ideas are very tempting indeed. Overloading functions and SUBs would allow for ommitable parameters and scenarios like Steve just outlined, and that would be great.

The other way around, appending a sub/function name to a variable does indeed look like object oriented programming. I admit it's my dream to have something like

TYPE myCoolType
    a AS INTEGER
    b AS INTEGER

    FUNCTION sum()
        sum = this.a + this.b
    END FUNCTION
END TYPE


...and then we could DIM myCoolVariable AS myCoolType and do things like:

myCoolVariable.a = 10
myCoolVariable.b = 5
PRINT myCoolVariable.sum


But even as I explain it to you guys, having used this. in my explanation shows me that what I wanted was OOP. More specifically JavaScript.

It'd be cool, but looks like a long way from what QB64 really is, as stated in the first post of this thread.
« Last Edit: August 24, 2018, 04:31:06 pm by FellippeHeitor »

Offline freetrav

  • Newbie
  • Posts: 45
    • View Profile
Re: Suggested Feature: Variable Parameter Procs/Funcs
« Reply #4 on: August 27, 2018, 07:56:55 am »
OK, What I was thinking of was definitely "Function/Procedure Overloading", rather than "Object-Oriented Programming", but now that the latter has been mentioned, and both briefly discussed, I could see that being useful as well - in fact, if I'm not up to the 'm' in 'alzheimer', C++ and its descendants support both in an integrated manner (that is, you can have overloaded functions that are members/constructors for user-defined types/structs).

Following on to OOP, it would be reasonable to request operator overloading as well (that is, be able to define what "a + b" means, for a and be being user-defined types) - but this is QB/QB64, not "VB++#Script".

Given that PRINT is already overloaded, inherently, I don't consider Procedure/Function overloading in QB64 to be completely breaking of its QB-ness, any more than some of the other extensions do.

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Suggested Feature: Variable Parameter Procs/Funcs
« Reply #5 on: August 27, 2018, 11:01:40 am »
I thought that whole idea was thoroughly trounced over at .NET a year or two ago, though I can't remember the exact reason for it. I do seem to remember it was discussed. Darn it where is that backup copy of .NET forum its definitely needed.
Granted after becoming radioactive I only have a half-life!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Suggested Feature: Variable Parameter Procs/Funcs
« Reply #6 on: August 28, 2018, 09:25:05 am »
Here is my fake overloading proof of concept, using spaces to delimit "parameters"  instead of commas which might be more natural looking. As you can plainly see, any amount of "parameters" variables and their values can be added, evalOverload needs only, eval>(numeric expression to evaluate), listed anywhere in string.
Code: QB64: [Select]
  1. _TITLE "Overload test eval"
  2. 'testing with QB64 X 64 version 1.2 20180228/86  from git b301f92
  3.  
  4. 'Overload test eval.bas B+ 2018-08-25 started
  5. ' modify Split for special case of spaces to be used as delimiter for overloaded p$ = parameter string
  6.  
  7. ' note: for ease of coding ~ is used for subtraction sign and normal - is reserved to indicate a negative number.
  8.  
  9.  
  10. CONST WW = 800
  11. CONST WH = 600
  12. SCREEN _NEWIMAGE(WW, WH, 32)
  13. _SCREENMOVE (1280 - WW) / 2 + 30, (760 - WH) / 2
  14.  
  15. test$(1) = "seven=7 eval>seven*10~7" ' < this is 7*10-7
  16. test$(2) = "A=2 b=3 C=5 x=10 eval>a*X^2+B*x+c"
  17. test$(3) = "eval>able*x^2+baker*x+charlie able=2 baker=2.99 charlie=5 x=10 eval>able*x^2+baker*x+charlie"
  18. FOR i = 1 TO 3
  19.     PRINT "For: "; test$(i);
  20.     evalOverload test$(i)
  21.     PRINT ", evalOverload returned: "; test$(i)
  22.     PRINT
  23.  
  24. SUB evalOverload (p AS STRING)
  25.     ' p$ comes in as parameters list, goes out as like a function's return value (but in string form of course).
  26.     ' so save p$ before calling and using here if need it again!
  27.  
  28.     DIM pList$(0)
  29.     DIM test AS INTEGER, L AS LONG, R AS LONG, found AS _BYTE, hit AS _BYTE
  30.     p = UCASE$(p)
  31.     Split p, " ", pList$()
  32.     FOR i = 0 TO UBOUND(pList$) 'find eval
  33.         IF INSTR(pList$(i), "EVAL>") THEN
  34.             this$ = rightOf$(pList$(i), "EVAL>"): found = 1: EXIT FOR
  35.         END IF
  36.     NEXT
  37.     IF found = 0 OR this$ = "" THEN PRINT "Did not find eval or what to eval.": p = "": EXIT SUB
  38.     b$ = ""
  39.     FOR i = 1 TO LEN(this$) 'do substitutions
  40.         wd$ = ""
  41.         hit = 0
  42.         WHILE INSTR("ABCDEFGHIJKLMNOPQRSTUVWXYZ", MID$(this$, i, 1)) AND i <= LEN(this$)
  43.             hit = 1
  44.             wd$ = wd$ + MID$(this$, i, 1)
  45.             i = i + 1
  46.         WEND
  47.         IF hit THEN i = i - 1
  48.         IF wd$ <> "" THEN
  49.             found2 = 0
  50.             FOR j = 0 TO UBOUND(Plist$) 'find eval
  51.                 IF leftOf$(pList$(j), "=") = wd$ THEN
  52.                     b$ = b$ + rightOf$(pList$(j), "="): found2 = 1: EXIT FOR
  53.                 END IF
  54.             NEXT
  55.             IF found2 = 0 THEN
  56.                 PRINT "Did not find word, "; wd$; ", in paramters list.": p = "": EXIT SUB
  57.             END IF
  58.         ELSE
  59.             b$ = b$ + MID$(this$, i, 1)
  60.         END IF
  61.     NEXT
  62.  
  63.     FOR j = 1 TO 6
  64.         op$ = MID$("%^/*~+", j, 1) 'notice the starnge sign for minus, to distinguish a neg number from subtraction op
  65.         WHILE INSTR(b$, op$)
  66.             place = INSTR(b$, op$)
  67.             L = place - 1: R = place + 1: lb$ = "": rb$ = ""
  68.             WHILE INSTR("1234567890-.", MID$(b$, L, 1)) AND L >= 1
  69.                 lb$ = MID$(b$, L, 1) + lb$
  70.                 L = L - 1
  71.             WEND
  72.             R = place + 1
  73.             WHILE INSTR("1234567890-.", MID$(b$, R, 1)) AND R <= LEN(b$)
  74.                 rb$ = rb$ + MID$(b$, R, 1)
  75.                 R = R + 1
  76.             WEND
  77.             vl = VAL(lb$): vr = VAL(rb$)
  78.             head$ = MID$(b$, 1, L): tail$ = MID$(b$, R)
  79.             SELECT CASE op$
  80.                 CASE "%": M$ = LTRIM$(STR$(VAL(lb$) MOD VAL(rb$)))
  81.                 CASE "^": M$ = LTRIM$(STR$(VAL(lb$) ^ VAL(rb$)))
  82.                 CASE "/": M$ = LTRIM$(STR$(VAL(lb$) / VAL(rb$)))
  83.                 CASE "*": M$ = LTRIM$(STR$(VAL(lb$) * VAL(rb$)))
  84.                 CASE "~": M$ = LTRIM$(STR$(VAL(lb$) - VAL(rb$)))
  85.                 CASE "+": M$ = LTRIM$(STR$(VAL(lb$) + VAL(rb$)))
  86.             END SELECT
  87.             b$ = head$ + M$ + tail$
  88.         WEND 'while op instr
  89.     NEXT
  90.     'return p  string as result
  91.     p = b$
  92.  
  93. FUNCTION leftOf$ (source$, of$)
  94.     posOf = INSTR(source$, of$)
  95.     IF posOf > 0 THEN leftOf$ = MID$(source$, 1, posOf - 1)
  96.  
  97. FUNCTION rightOf$ (source$, of$)
  98.     posOf = INSTR(source$, of$)
  99.     IF posOf > 0 THEN rightOf$ = MID$(source$, posOf + LEN(of$))
  100.  
  101. 'notes: REDIM the array(0) to be loaded before calling Split '<<<<<<<<<<<<<<<<<<<<<<< IMPORTANT!!!!
  102. SUB Split (mystr AS STRING, delim AS STRING, arr() AS STRING)
  103.     ' bplus modifications of Galleon fix of Bulrush Split reply #13
  104.     ' http://www.[abandoned, outdated and now likely malicious qb64 dot net website - don’t go there]/forum/index.php?topic=1612.0
  105.     ' this sub further developed and tested here: \test\Strings\Split test.bas
  106.     DIM copy AS STRING, p AS LONG, curpos AS LONG, arrpos AS LONG, lc AS LONG, dpos AS LONG
  107.     copy = mystr 'make copy since we are messing with mystr
  108.     'special case if delim is space, probably want to remove all excess space
  109.     IF delim = " " THEN
  110.         copy = RTRIM$(LTRIM$(copy))
  111.         p = INSTR(copy, "  ")
  112.         WHILE p > 0
  113.             copy = MID$(copy, 1, p - 1) + MID$(copy, p + 1)
  114.             p = INSTR(copy, "  ")
  115.         WEND
  116.     END IF
  117.     curpos = 1
  118.     arrpos = 0
  119.     lc = LEN(copy)
  120.     dpos = INSTR(curpos, copy, delim)
  121.     DO UNTIL dpos = 0
  122.         arr(arrpos) = MID$(copy, curpos, dpos - curpos)
  123.         arrpos = arrpos + 1
  124.         REDIM _PRESERVE arr(arrpos + 1) AS STRING
  125.         curpos = dpos + LEN(delim)
  126.         dpos = INSTR(curpos, copy, delim)
  127.     LOOP
  128.     arr(arrpos) = MID$(copy, curpos)
  129.     REDIM _PRESERVE arr(arrpos) AS STRING
  130.  
Yes! there is really only one string parameter, thank you.
« Last Edit: August 28, 2018, 09:32:33 am by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Suggested Feature: Variable Parameter Procs/Funcs
« Reply #7 on: August 28, 2018, 11:50:35 pm »
Dang! I just noticed this:
Quote
test$(3) = "eval>able*x^2+baker*x+charlie able=2 baker=2.99 charlie=5 x=10 eval>able*x^2+baker*x+charlie"
eval>... was in the line twice! I forgot to cut the last one out. It still worked correctly.

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Suggested Feature: Variable Parameter Procs/Funcs
« Reply #8 on: August 29, 2018, 09:44:33 am »
Heya blplus (and anyone else still following),

I have a moral(?) obligation to continue where bplus left off and show where this idea *could* go if you drive it hard for a few, oh, thousand hours. The "idea" of course is that everything is a string, and you represent all of your data as a string (not necessarily storing it that way of course.) If you stay true to the idea, you will wind up with something undoubtedly too slow to operate in the main loop of your gaming engine unless the string parsing is nerfed down a bit. However it will be infinitely portable. Make it right, and it's the last time you need to make it (across several platforms too if you put on a real straight jacket).

All that said, I present to some of you, and remind the rest of you, with one possible epitome of bplus's example, the Sxript project. This qb64 snippet reproduces bplus's example:

Code: QB64: [Select]
  1. REM $Include: 'sxmath.bi'
  2. REM $Include: 'sxript.bi'
  3.  
  4. eval "let(seven,7)", 0
  5. eval "[seven]*10-7", 1
  6.  
  7. eval "<let(A,2),let(b,3),let(C,5),let(X,10)>", 0
  8. eval "[A]*[X]^2 + [b]*[X]+[C]", 1
  9.  
  10. eval "map(<able,baker,charlie,X>,let,<2,2.99,5,10>)", 0
  11. eval "[able]*[X]^2+[baker]*[X]+[charlie]", 1
  12.  
  13.  
  14. SUB eval (a AS STRING, b AS INTEGER)
  15.     DIM c AS STRING
  16.     c = SxriptEval$(a)
  17.     IF b = 1 THEN PRINT c
  18.  
  19. REM $Include: 'sxript.bm'
  20. REM $Include: 'sxmath.bm'

However, since it's a pain in the ass to download the include files, make sure you have them in the right place, so on and so forth, I recommend the (identical) JavaScript implementation if you want to play with the code above. Basically hit this link:

http://www.barnesreport.net/sxript/docs/console/console.html

...and paste this code into the big box on the left:

Code: QB64: [Select]
  1. let(seven,7)                                  :
  2. print_[seven]*10-7                            ,\n:
  3.  
  4. let(A,2):let(b,3):let(C,5):let(X,10)          :
  5. print_[A]*[X]^2 + [b]*[X]+[C]                 ,\n:
  6.  
  7. map(<able,baker,charlie,X>,let,<2,2.99,5,10>) :
  8. print_[able]*[X]^2+[baker]*[X]+[charlie]      ,\n:

Within the Sxript ecosystem, so to speak, you have the full range of functional programming features - i.e. you can do everything without naming a single variable or function if you really insist. Or, it has the usual imperative stuff like line labels and goto's, etc. As is, this creature lends itself naturally to faking OOP capabilities much as JavaScript does. Curious people can keep me on the hook for questions, or have a glance at http://www.barnesreport.net/sxript/index.html for a bit more.
« Last Edit: August 29, 2018, 09:49:38 am by STxAxTIC »
You're not done when it works, you're done when it's right.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Suggested Feature: Variable Parameter Procs/Funcs
« Reply #9 on: September 05, 2018, 08:06:17 am »
On another forum challenged to do a sin table without variables but apparently library files are OK so then INCLUDE files must be OK too, so here is my reply:
Code: QB64: [Select]
  1. _TITLE "test range.bi and bm"
  2. '$include: 'range.bi'
  3.  
  4. PRINT Range("1 to 100 step 1 do sin")
  5. PRINT "End of sin(1 to 100 stepping by 1) table."
  6.  
  7. PRINT: PRINT "Sin at 90 degree intervals:"
  8. PRINT Range("0 to 6.2832 step 1.5708 do sin")
  9.  
  10. PRINT: PRINT "Squares of numbers from 3.5 to 5.5 stepping by .5"
  11. PRINT Range("5.5 to 3.5 step .5 do square")
  12.  
  13. '$include: 'range.bm'
  14.  
  15.  
 [ You are not allowed to view this attachment ]  

Anyone want to see Range code? ;)
« Last Edit: September 05, 2018, 08:08:24 am by bplus »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Suggested Feature: Variable Parameter Procs/Funcs
« Reply #10 on: September 05, 2018, 08:11:11 am »
On another forum challenged to do a sin table without variables but apparently library files are OK so then INCLUDE files must be OK too, so here is my reply:

Wouldn't the easiest way just be to put the values into DATA statements, creating an actual table?  LOL
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Suggested Feature: Variable Parameter Procs/Funcs
« Reply #11 on: September 05, 2018, 07:50:56 pm »
Hmm...

Need some clarity - is the original text of the challenge around? Unless you use a gimmick, you're probably using variables somewhere - even if you wanna chicken and egg the problem like Steve (sarcastically of course) suggested.
You're not done when it works, you're done when it's right.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Suggested Feature: Variable Parameter Procs/Funcs
« Reply #12 on: September 05, 2018, 08:16:00 pm »
Tomaaz
Quote
The whole challenge is completely pointless. What about something like this:

Write a program that writes on the screen values of sinus for numbers form 1 to 100 without using any variable name.

Perl
Code: [Select]

print for (map {sin() (1..100)})


How many other languages can do it?

You can bet your sweet bippy variables are involved somewhere but I guess the trick is to not let them show.

Some languages shown had it built-in, others achieved the results with library extensions.
« Last Edit: September 05, 2018, 08:28:51 pm by bplus »

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Suggested Feature: Variable Parameter Procs/Funcs
« Reply #13 on: September 05, 2018, 08:56:05 pm »
Aha, yeah this (in the language mentioned above):

Code: QB64: [Select]
  1. include(`../test/vector.txt'):
  2.  
  3. print_apply(sin,fill(1,100,100))
You're not done when it works, you're done when it's right.