This is the mail archive of the guile@cygnus.com mailing list for the guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Second try at an optional argument interface



OK, people seem to really dislike the brackets. I thought they were
cute and intuitive, but the functionality matters more to me than the
synatx. Here are the comments from my next try which I've stuck as
optargs.scm.3 in the /pub/guile/contrib/incoming directory on
ftp.red-bean.com. (optargs.scm.2 was a mistake, please just delete
it). It's also available off of http://web.mit.edu/mstachow/www.  To
summarize, I added support for keyword arguments, changed the syntax
to something more like DSSSL (and Common Lisp), and added let-style
macros like scsh's for both optional and keyword arg parsing. I hope
people find this version more aesthetically pleasing.

Here's the documentation comments extracted:

;;; {Optional Arguments}
;;;
;;; The C interface for creating Guile procedures has a very handy
;;; "optional argument" feature. This module attempts to provide
;;; similar functionality for procedures defined in Scheme with
;;; a convenient and attractive syntax.
;;;
;;; exported macros and variables are:
;;;   bound?
;;;   let-optional
;;;   let-optional*
;;;   let-keywords
;;;   let-keywords*
;;;   lambda*
;;;   define*
;;;   define*-public   
;;;

;; bound? var
;;   Checks if a variable is bound in the current environment.
;;
;; defined? doesn't quite cut it as it stands, since it only
;; cheks bindings in the top-level environment, not those in
;; local scope only.
;;

;; let-optional rest-arg (binding ...) . body
;; let-optional* rest-arg (binding ...) . body
;;   macros used to bind optional arguments
;;
;; These two macros give you an optional argument interface that
;; is very "Schemey" and introduces no fancy syntax. They are
;; compatible with the scsh macros of the same name, but are slightly
;; extended. Each of binding may be of one of the forms <var> or
;; (<var> <default-value>). rest-arg should be the rest-argument of
;; the procedures these are used from. The items in rest-arg are
;; sequentially bound to the variable namess are given. When rest-arg
;; runs out, the remaining vars are bound either to the default values
;; or left unbound if no default value was specified. rest-arg remains
;; bound to whatever may have been left of rest-arg.
;;

;; let-keywords rest-arg (binding ...) . body
;; let-keywords* rest-arg (binding ...) . body
;;   macros used to bind keyword arguments
;;
;; These macros pick out keyword arguments from rest-arg, but do not
;; modify it. This is consistent at least with Common Lisp, which
;; duplicates keyword args in the rest arg. More explanation of what
;; keyword arguments in a lambda list look like can be found below in
;; the documentation for lambda*.  Bindings can have the same form as
;; for let-optional.  
;;

;;   reader extensions for #&key #&optional
;; #&key and #&optional need to be quoted in normal code, but need not be 
;; in an extended lambda-list provided by lambda*, define*, or 
;; define*-public (see below). In other words, they act sort of like 
;; symbols, except they aren't. They're being temporarily used until
;; #!optional and #!key are available.

;; lambda* args . body
;;   lambda extended for optional and keyword arguments
;;   
;; lambda* creates a procedure that takes optional arguments. These
;; are specified by putting them inside brackets at the end of the
;; paramater list, but before any dotted rest argument. For example,
;;   (lambda* (a b #&optional c d . e) '())
;; creates a procedure with fixed arguments a and b, optional arguments c
;; and d, and rest argument e. If the optional arguments are omitted
;; in a call, the variables for them are unbound in the procedure. This
;; can be checked with the bound? macro.
;;
;; lambda* can also take keyword arguments. For example, a procedure
;; defined like this:
;;   (lambda* (#&key xyzzy larch) '())
;; can be called with any of the argument lists (#:xyzzy 11)
;; (#:larch 13) (#:larch 42 #:xyzzy 19) (). Whichever arguments
;; are given as keywords are bound to values.
;;
;; Optional and keyword arguments can also be given default values
;; which they take on when they are not present in a call, by giving a
;; two-item list in place of an optional argument, for example in:
;;   (lambda* (foo #&optional (bar 42) #&key (baz 73)) (list foo bar baz)) 
;; foo is a fixed argument, bar is an optional argument with default
;; value 42, and baz is a keyword argument with default value 73.
;; Default value expressions are not evaluated unless they are needed
;; and until the procedure is called.  
;;

;; define* args . body
;; define*-public args . body
;;   define and define-public extended for optional and keyword arguments
;;
;; define* and define*-public support optional arguments with
;; a similar syntax to lambda*. They also support arbitrary-depth
;; currying, just like Guile's define. Some examples:
;;   (define* (x y #&optional a (z 3) #&key w . u) (display (list y z u)))
;; defines a procedure x with a fixed argument y, an optional agument
;; a, another optional argument z with default value 3, a keyword argument w,
;; and a rest argument u.
;;   (define-public* ((foo #&optional bar) #&optional baz) '())
;; This illustrates currying. A procedure foo is defined, which,
;; when called with an optional argument bar, returns a procedure that
;; takes an optional argument baz. 
;;


 - Maciej Stachowiak