Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

How to check function arguments ?

 [1/22] from: jason::cunliffe::verizon::net at: 8-Jun-2002 11:54


It's kind of embarrassing, but I've forgotten the REBOL idioms for something really basic.. How to check for arguments provided to a function? How to check when the argument is optional and when it is missing? somefunc: func [arg1 arg2 ... argN] [ ; check args here and respond ] thanks ./Jason

 [2/22] from: greggirwin:mindspring at: 8-Jun-2002 13:26


Hi Jason, << It's kind of embarrassing, but I've forgotten the REBOL idioms for something really basic.. How to check for arguments provided to a function? How to check when the argument is optional and when it is missing? somefunc: func [arg1 arg2 ... argN] [ ; check args here and respond ] >> Do you mean refinements? ; arg-2 is an optional arg. flag-it is a refinment with no args. somefunc: func [arg1 /has-arg-2 arg2 /flag-it] [ if has-arg-2 [ print arg-2 ] if flag-it [print "flagged"] ] --Gregg

 [3/22] from: jason:cunliffe:verizon at: 8-Jun-2002 16:10


Hi Gregg
> Do you mean refinements?
..not exactly thanks, but your example taught me something handy:-)
>> somefunc: func [inp] [print [inp * 3.14159]] >> somefunc 4
12.56636
>> somefunc
** Script Error: somefunc is missing its inp argument ** Near: somefunc Q1: How to catch the missing param so the script won't crash? ./Jason

 [4/22] from: carl:cybercraft at: 9-Jun-2002 10:07


On 09-Jun-02, Jason Cunliffe wrote:
> Hi Gregg >> Do you mean refinements?
<<quoted lines omitted: 6>>
> ** Near: somefunc > Q1: How to catch the missing param so the script won't crash?
Hi Jason, If it's just error trapping you want, then use "error? try". ie...
>> error? try [somefunc]
== true
>> error? try [somefunc wrong-input]
== true
>> error? try [somefunc wrong-input and-another-wrong-input]
== true
>> error? try [somefunc 3]
9.42477 == false Though you shouldn't be using error-trapping to catch errors in the script of course! (: However, going by your first post I gathered you wanted a function to work on an arbitrary number of arguments. I'm not sure if it can be done in REBOL the way you are wanting, but the REBOL way to do it is to supply the arguments in a block. 'join's a good example...
>> ? join
USAGE: JOIN value rest DESCRIPTION: Concatenates values. JOIN is a function value. ARGUMENTS: value -- Base value (Type: any) rest -- Value or block of values (Type: any) So...
>> join "a" "b"
== "ab"
>> join "a" ["b" "c" "d" "e"]
== "abcde" Obviously that always requires two arguments with the second one being optionally a block, but if it's zero or more arguments you're after, just have a block with an empty one equating to no arguments. ie... sum: func [numbers [number! block!] /local total][ if number? numbers [return numbers] if empty? numbers [return none] total: 0 forall numbers [total: total + numbers/1] total ]
>> sum 1
== 1
>> sum [1]
== 1
>> sum [1 2]
== 3
>> sum [1 2 3]
== 6 And nothing in a block returns a none...
>> sum []
== none Hope that helps. -- Carl Read

 [5/22] from: rotenca:telvia:it at: 9-Jun-2002 1:59


Hi Jason,
> >> somefunc: func [inp] [print [inp * 3.14159]] > >> somefunc 4
<<quoted lines omitted: 3>>
> ** Near: somefunc > Q1: How to catch the missing param so the script won't crash?
somefunc: func [inp [any-type!]] [if value? 'inp [print [inp * 3.14159]]] --- Ciao Romano

 [6/22] from: chalz:earthlink at: 9-Jun-2002 0:04


Easiest solution is like Romano said: Just use any-type! I use it in a die rolling CGI script, where you can do: roll?2d6 or roll?2d6+3 (or +-3) I also use: args: system/options/args

 [7/22] from: g:santilli:tiscalinet:it at: 9-Jun-2002 12:55


Hi Jason, On Saturday, June 08, 2002, 10:10:10 PM, you wrote: JC> Q1: How to catch the missing param so the script won't crash? Well, there's a way, but I don't recommend it as it can create more problems than it solves.
>> somefunc: func [inp [number! unset!]] [print either value? 'inp [inp * 3.14159] ["no value passed"]] >> somefunc 4
12.56636
>> somefunc
no value passed No I ask, what would you expect to get from: somefunc print "done." Do you expect this:
>> do [
[ somefunc [ print "done." [ ] done. no value passed Maybe you better get what's going on if I write it as:
>> somefunc print "done."
done. no value passed Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

 [8/22] from: jason:cunliffe:verizon at: 9-Jun-2002 9:21


hmm.. Q: How to tell if a word already exists or if is just an argument value being passed?
>> somefunc: func [inp [any-type!]][if value? 'inp [print inp "do stuff"]] >> somefunc
== none
>> somefunc "hello"
hello == "do stuff"
>> somefunc print now
9-Jun-2002/8:32:33-4:00 == none When the input to somefunc is something like 'print' or any word in the rebol dictionary, we might assume that it is not a valid argument. Arguments we would be expecting would usually be a number, a name, a time, a block, etc.. So we could check for an existing known word, then perhaps it is not an argument. I don't know how to do that kind of lookup and could be slow.. It seems pretty limiting unless we are only passing in very simple strings and numbers, which in fact we often are in cgi work. But the obvious escape is just put all args in a block.
>> somefunc exists? %test.xml ;;; empty argument, keep going.. >> somefunc [exists? %test.xml] ;;; evaluate block and use as argument >> somefunc [1 "love" now ] ;;; evaluate block and use as argument >> somefunc [name "jason" email [jasonic--nomadics--org] startdir %.] ;;; name,
email are keywords arguments Which creates Python's **Kw variable keyword arguments very nicely. Except for a concise local way to embed default handling. if error? try [startdir] [startdir: "%/home/jasonic"] That works, but it's verbose next to Python. Any idiom suggestions to improve upon it within a function? Anyway feel like I just reinvented some primal rebol wheel here! Must be time to study scope and context more.. I suppose I need an 'arg-block tool I can use widely. Can anyone point me to examples using blocks as arguments, and techniques for parsing them? thanks ./Jason

 [9/22] from: jason:cunliffe:verizon at: 9-Jun-2002 1:11


Hi Romano and everyone
> somefunc: func [inp [any-type!]] [if value? 'inp [print [inp * 3.14159]]]
..damn that's clever.. thanks! It's a very interesting idiom the way it depends upon those two quite different but crucial parts any-type! 'inp Doing quite a lot of Vanilla programming, so it's sometimes cgi, some times internal functions. But the more flexible the args, the better - you don't have to remember, and it makes modular API development easier. Before REBOL, I was in love with Python, which has some great features for function args: 1. Keyword arguments with defaults 2. - Variable Length arguments Here's an example from Core Python Programming by Wesley Chun [good book] def tupleVarArgs(arg1, arg2='defaultB', *theRest) 'display regular args and non-keyword variable args' print 'formal arg1:', arg1 print 'formal arg2:', arg2 for eachXtrArg in theRest: print 'another arg:', eachXtrArg When a double ** is used it signifies variable Keyword arguments [Python Dictionary]. Python dicts are close to REBOL blocks depending how you use them, so I guess variable keyword args could be done with a combination of REBOL's refinements and some other magic. REBOL makes one work harder for the defaults. Perhaps you already know some more cool idioms ;-) thanks ./Jason

 [10/22] from: jason:cunliffe:verizon at: 9-Jun-2002 8:23


> >> somefunc print "done." > done. > no value passed
..yikes! Gabriele that's a very good point. I guess it's back to the drawing board to think about this some more. REBOL is so full of funny surprises. cheers ./Jason

 [11/22] from: g:santilli:tiscalinet:it at: 9-Jun-2002 15:57


Hi Jason, On Sunday, June 09, 2002, 7:11:36 AM, you wrote: JC> REBOL makes one work harder for the defaults. Perhaps you already know some more JC> cool idioms ;-) f: func [/opt optional-arg] [ optional-arg: any [optional-arg "default value"] print optional-arg ] Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

 [12/22] from: g:santilli:tiscalinet:it at: 9-Jun-2002 16:12


Hi Jason, On Sunday, June 09, 2002, 3:21:28 PM, you wrote: JC> When the input to somefunc is something like 'print' or any word in the rebol JC> dictionary, we might assume that it is not a valid argument. Arguments we would JC> be expecting would usually be a number, a name, a time, a block, etc.. So we JC> could check for an existing known word, then perhaps it is not an argument. I JC> don't know how to do that kind of lookup and could be slow.. It seems pretty JC> limiting unless we are only passing in very simple strings and numbers, which in JC> fact we often are in cgi work. I don't think that what you want to do can be done, at least easily (even if you get the word 'PRINT, and decide to leave it alone, how do you tell REBOL to evaluate it AFTER your function?). REBOL does not support variable number of arguments because of its freeform syntax. If you like parens, then you can workaround the problem with variable args with them:
>> (somefunc) print "done"
no value passed done JC> Which creates Python's **Kw variable keyword arguments very nicely. Yes, and you can even create your own dialect, which can make things even better. JC> Except for a concise local way to embed default handling. See my earlier post. :) Of course it needs to be modified if you want to use it with varargs,
>> get-or: func [word default] [either value? word [get word] [default]] >> somefunc: func [inp [any-type!]] [inp: get-or 'inp "default value" print inp] >> somefunc
default value
>> somefunc 1
1 or any variation,
>> set-default: func [word default] [if not value? word [set word default] word] >> get-or2: func [word default] [any [if value? word [word] default]]
JC> Anyway feel like I just reinvented some primal rebol wheel here! Must be time to JC> study scope and context more.. I suppose I need an 'arg-block tool I can use JC> widely. I still think you'd better go with refinements, or just pass NONE to mean "default"; if your function is complex enough to make this a problem, then pass a single block and PARSE it (i.e. make your own dialect :). JC> Can anyone point me to examples using blocks as arguments, and techniques for JC> parsing them? LAYOUT? ;-) Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

 [13/22] from: ingo:2b1 at: 9-Jun-2002 20:13


Hi Jason, Jason Cunliffe wrote:
> hmm.. > Q: How to tell if a word already exists or if is just an argument value being
<<quoted lines omitted: 13>>
> When the input to somefunc is something like 'print' or any word in the rebol > dictionary, we might assume that it is not a valid argument.
Well, trouble is, some-func never gets to see 'print, let's walk through it:
>> somefunc print "hello"
The interpreter finds 'somefunc, and sees that it's a function which would be happy to get an argument (in our example it would be equally happy without one, but that will only be checked _after_ nothing at all has been found). Now it stumbles on 'print "ahh, that's word, now let's find the value of that word". The value happens to be a function, this function wants one argument, too, so it eats the string "hello", does its work, and the return value of print (which is nothing at all, by the way), is given to somefunc as an argument. You could change somefunc like this
>>somefunc: func['inp[any-type!]][if value? 'inp [print inp "do stuff"]]
(Notice the 'tick in front of inp) Now you'll get:
>> somefunc print "hello"
print == "hello" -> somefunc eats the _word_ 'print, without evaluating it, and "hello" is just returned, because there's nothing left to do with it. It is possible to do the print command now, but the problem is to get to prints argument. And now for something completely different. Your real problem is, that Rebol functions just try to get all their arguments, and there seems to be no way to tell a function where to stop searching, while most other languages have a means for that, be it semicolons, parents, or what not. Now Rebol has some Lisp ancestry, so you can always use those lispy parens:
>> (somefunc)
== none
>> (somefunc) print "hello"
hello <..>
> But the obvious escape is just put all args in a block.
Well, that's the most rebolious way, I think. I hope that shines a little light on the subject, Ingo

 [14/22] from: rotenca:telvia:it at: 9-Jun-2002 21:50


Hi Gabriele,
> JC> REBOL makes one work harder for the defaults. Perhaps you already know
some more
> JC> cool idioms ;-) > > f: func [/opt optional-arg] [ > optional-arg: any [optional-arg "default value"]
print optional-arg
> ]
But remember:
>> f/opt none
default value
>> f/opt false
default value A more direct approach: f: func [/opt optional-arg] [ optional-arg: either opt [optional-arg]["default value"] print optional-arg ] --- Ciao Romano

 [15/22] from: christian:ensel:gmx at: 9-Jun-2002 22:44

Re: How to check function arguments? - Syntax REBOLution ...


Hello Gabriele, on Sunday, 09-Jun-02, 15:12:46, Gabriele Santilli wrote:
> REBOL does not support variable number of arguments because of its > freeform syntax.
As with all rules there seems to be an expection: The list of arguments to MAKE as specified by
>> source make
== make: native [ "Constructs and returns a new value." type [any-type!] "The datatype or example value." spec [any-type!] "The attributes of the new value." ] says there are exactly two arguments TYPE and SPEC, which is true in the case of
>> make block! 5
== [] But that given I really can't explain why
>> make function! [] ; two arguments, as suggested
** Script Error: Invalid argument: (missing value) ** Near: make function! [] fails and why instead of
>> make function! [[ ... ] [ ... ]] ; two arguments
- which one should consider to be what MAKE expects of us to do - we're all used to write
>> make function! [ ... ] [ ... ] ; three arguments
obviously violating the specification of make ... As said before, I really can't explain this to me. Looks as if all ANY-FUNCTION!s are equal, but some NATIVE!s are more equal ... Any ideas, somebody? Regards, Christian

 [16/22] from: g:santilli:tiscalinet:it at: 10-Jun-2002 2:49


Hi Christian, On Sunday, June 09, 2002, 11:44:37 PM, you wrote: CE> As with all rules there seems to be an expection: Indeed, there are some exceptions. Not only MAKE, but also DO; they are likely to access the internal interpreter state to fetch extra arguments when needed. It would be cool to be able to do it via REBOL too (i.e. like knowing the position where your function was called and using something like DO/NEXT on it), but I don't think this will ever be high priority on RT's list. :) Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

 [17/22] from: carl:cybercraft at: 10-Jun-2002 13:39

Re: How to check function arguments ?


On 09-Jun-02, Charles wrote:
> Easiest solution is like Romano said: Just use any-type! I use it > in a die rolling CGI script, where you can do: roll?2d6
<<quoted lines omitted: 3>>
> I also use: > args: system/options/args
Ah - I didn't know of that solution. And I hadn't noticed that type: any is different than any-type!...
>> x: func [y][whatever] >> ? x
USAGE: X y DESCRIPTION: (undocumented) ARGUMENTS: y -- (Type: any)
>> x: func [y [any-type!]][whatever] >> ? x
USAGE: X y DESCRIPTION: (undocumented) ARGUMENTS: y -- (Type: any-type) But no need to explain the difference. It's not something I urgently need to know today. (; -- Carl Read

 [18/22] from: lmecir:mbox:vol:cz at: 10-Jun-2002 8:48

Re: How to check function arguments? - Syntax REBOLution ...


Hi Christian and all, my essay http://www.rebolforces.com/~ladislav/argstake.html describes how Rebol functions take their arguments. If you want to see some parsing example, have a look at the APPLY function in http://www.rebolforces.com/~ladislav/highfun.r -L ----- Original Message ----- From: "Christian Ensel" Hello Gabriele, on Sunday, 09-Jun-02, 15:12:46, Gabriele Santilli wrote:
> REBOL does not support variable number of arguments because of its > freeform syntax.
As with all rules there seems to be an expection: ...snipped... As said before, I really can't explain this to me. Looks as if all ANY-FUNCTION!s are equal, but some NATIVE!s are more equal ... Any ideas, somebody? Regards, Christian

 [19/22] from: rotenca::telvia::it at: 10-Jun-2002 9:14


You can read: http://www.rebolforces.com/~ladislav/argstake.html --- Ciao Romano

 [20/22] from: ammon:rcslv at: 8-Jun-2002 16:26

Re: How to check function arguments ?


>>? any
USAGE: ANY block DESCRIPTION: Shortcut OR. Evaluates and returns the first value that is not FALSE or NONE. ANY is a native value. ARGUMENTS: block -- Block of expressions (Type: block) any-type! is a suedo-type that includes any data-type! HTH Ammon A short time ago, Carl Read, sent an email stating:

 [21/22] from: christian:ensel:gmx at: 10-Jun-2002 22:35

Re: How to check function arguments? - Syntax REBOLution ...


Hi [Ladislav Romano Gabriele], On monday, 10-Jun-02, 07:48:53, Ladislav Mecir wrote:
> my essay http://www.rebolforces.com/~ladislav/argstake.html describes how > Rebol functions take their arguments.
Not that for one single moment I thought I've discovered a not so well-known rebol behaviour ... ;) Thanks to you all for pointing me to this article, regards, Christian

 [22/22] from: lmecir:mbox:vol:cz at: 10-Jun-2002 23:06


Hi all, some minor changes at my rebsite (see http://www.rebolforces.com/~ladislav ), especially evaluation.html now contains two possible definitions of recursive blocks. -L

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted