Python vs Scheme: function parameters (part I)
Python supports various ways to handle arguments passed to functions:
# regular def f(a, b, c): ... # default arguments def f(a, b=3, c=100): ... # any number of positional parameters def f(x, *args): ... # any number of keyword arguments def f(y, **kwargs): ... # or a mixture! def f(self, *args, **kwargs): ...
Scheme supports a few similar forms, and what it doesn't have is complemented by Chicken. Let's have a look.
The "regular" argument list looks like this:
> (define (f a b c)
(list a b c))
> (f 1 2 3)
(1 2 3)
> (f 3 4)
...error: not enough arguments...
;; (Python) def f(a, b, c): ...
f takes three arguments, no more, no less.
> (define (g a b . rest)
(list a b rest))
> (g 1 2)
(1 2 ())
> (g 1 2 3)
(1 2 (3))
> (g 1 2 3 4 5 6 7)
(1 2 (3 4 5 6 7))
;; (Python) def g(a, b, *rest): ...
g takes two mandatory arguments, and any number of optional arguments, which are stored in the list rest. So, we can call (g 1 2) in which case rest is empty, but we can also call it as (g 1 2 3 4) which gives rest the value (3 4).
If we want a function that takes any number of arguments, with no mandatory ones, we use the following:
> (define (h . args) (list args)) > (h) (()) > (h 1 2 3) ((1 2 3)) ;; (Python) def h(*args): ...
Note, however, that this doesn't work for a lambda (because (lambda (. args)) is not valid syntax). In that case, use args rather than an argument list:
> (define i (lambda args (list args))) > (i) (()) > (i 1 2 3) ((1 2 3))
This is all the argument handling that Scheme has to offer (in R5RS; read more about it here). Chicken has several extensions to this standard, more about which tomorrow.
Rudolf Olah said,
January 2, 2008 @ 2:12 pm
Just a quick tip. SRFI-89 (http://srfi.schemers.org/srfi-89/srfi-89.html) contains a specification for optional and named parameters (a.k.a keyword parameters). I'm not sure if Chicken Scheme uses something else or if it even implements SRFI-89.
Hans Nowak said,
January 2, 2008 @ 4:02 pm
Thanks, I'll look at it. According to the Chicken user manual, SRFI-89 is not in the list of SRFIs supported by Chicken... but I don't know how up-to-date that list is.
Rudolf Olah said,
January 3, 2008 @ 9:13 pm
I think all SRFIs include an implementation. At the bottom of SRFI-89 there's some code and it will probably work. Of course you also need SRFI-88 implemented. Fortunately, there's a hack implementation of that at the bottom of the SRFI-88 final report.
"The implementation of keyword objects requires changing the reader and the evaluator. Although the changes are expected to be straightforward they are obviously highly system dependent. Here we offer a simplistic `user-level' implementation (a.k.a. kludge) that will work in Scheme implementations that allow colons anywhere in the symbol."
So it's possible to get that stuff into your Scheme even if it isn't implemented at the system level. Of course I haven't tried the code so I don't know if it works in Chicken Scheme. Would be awesome if it did though :)
Hans Nowak said,
January 4, 2008 @ 12:31 pm
I think that this kind of optional argument is already supported by Chicken (maybe it's part of a different SRFI, maybe it's something else, I don't know). It doesn't define 'define*' or 'lambda*', but #!optional, #!key and #!rest do support this kind of arguments. (See part II of this post.) Maybe that's why nobody in the Chicken community has bothered to implement SRFI-89 so far.
Hans Nowak said,
January 6, 2008 @ 2:11 pm
A message was posted in the newsgroup/mailing list today stating that an egg was added for SRFI-89.