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