Next: Assignments, Previous: Literals, Up: Core syntax [Contents][Index]
[R7RS+ base] Evaluates to a procedure. The environment in effect when this expression is evaluated is stored in the procedure. When the procedure is called, body is evaluated sequentially in the stored environment extended by the bindings of the formal arguments, and returns the value(s) of the last expression in the body.
^
is a concise alias of lambda
. It is Gauche’s extension.
(lambda (a b) (+ a b))
⇒ procedure that adds two arguments
((lambda (a b) (+ a b)) 1 2) ⇒ 3
((^(a b) (+ a b)) 1 2) ⇒ 3
Gauche also extends R7RS lambda
to take extended syntax in
formals to specify optional and keyword arguments easily.
The same functionality can be written in pure R7RS, with parsing
variable-length arguments explicitly, but the code tends
to be longer and verbose. It is recommended to use extended syntax
unless you’re writing portable code.
Formals should have one of the following forms:
(variable …)
:
The procedure takes a fixed number of arguments.
The actual arguments are bound to the corresponding variables.
((lambda (a) a) 1) ⇒ 1 ((lambda (a) a) 1 2) ⇒ error - wrong number of arguments
variable
:
The procedure takes any number of arguments.
The actual arguments are collected to form a new list and bound to
the variable.
((lambda a a) 1 2 3) ⇒ (1 2 3)
(variable_0 … variable_N-1 . variable_N)
:
The procedure takes at least N arguments. The actual arguments
up to N is bound to the corresponding variables.
If more than N arguments are given, the rest arguments are
collected to form a new list and bound to variable_N.
((lambda (a b . c) (print "a=" a " b=" b " c=" c)) 1 2 3 4 5)
⇒ prints a=1 b=2 c=(3 4 5)
(variable … extended-spec …)
:
Extended argument specification. Zero or more variables that
specifies required formal arguments, followed
by an extended spec, a list beginning with
a keyword :optional
, :key
or :rest
.
The extended-spec part consists of the optional argument spec, the keyword argument spec and the rest argument spec. They can appear in any combinations.
:optional optspec …
Specifies optional arguments. Each optspec can be either one of the following forms:
variable (variable init-expr)
The variable names the formal argument, which is bound to
the value of the actual argument if given, or the value of
the expression init-expr otherwise. If optspec is just
a variable, and the actual argument is not given to it, then
variable will be bound to #<undef>
(see Undefined values).
The expression init-expr is only evaluated if the actual argument for variable is not given. The scope in which init-expr is evaluated includes the preceding formal arguments.
((lambda (a b :optional (c (+ a b))) (list a b c)) 1 2) ⇒ (1 2 3) ((lambda (a b :optional (c (+ a b))) (list a b c)) 1 2 -1) ⇒ (1 2 -1) ((lambda (a b :optional c) (list a b c)) 1 2) ⇒ (1 2 #<undef>) ((lambda (:optional (a 0) (b (+ a 1))) (list a b)) ) ⇒ (0 1)
The procedure signals an error if more actual arguments than
the number of required and optional arguments are given, unless it also has
:key
or :rest
argument spec.
((lambda (:optional a b) (list a b)) 1 2 3) ⇒ error - too many arguments ((lambda (:optional a b :rest r) (list a b r)) 1 2 3) ⇒ (1 2 (3))
:key keyspec … [:allow-other-keys [variable]]
Specifies keyword arguments. Each keyspec can be either one of the following forms.
variable (variable init-expr) ((keyword variable) init-expr)
The variable names the formal argument, which is bound to the
actual argument given with the keyword of the same name as variable.
When the actual argument is not given, init-expr is evaluated
and the result is bound to variable in the second and third form,
or #<undef>
is bound in the first form.
(define f (lambda (a :key (b (+ a 1)) (c (+ b 1))) (list a b c))) (f 10) ⇒ (10 11 12) (f 10 :b 4) ⇒ (10 4 5) (f 10 :c 8) ⇒ (10 11 8) (f 10 :c 1 :b 3) ⇒ (10 3 1)
With the third form you can name the formal argument differently from the keyword to specify the argument.
((lambda (:key ((:aa a) -1)) a) :aa 2) ⇒ 2
By default, the procedure with keyword argument spec raises an
error if a keyword argument with an unrecognized keyword is given.
Giving :allow-other-keys
in the formals suppresses this behavior.
If you give variable after :allow-other-keys
,
the list of unrecognized keywords and their arguments are bound to it.
Again, see the example below will help to understand the behavior.
((lambda (:key a) a) :a 1 :b 2) ⇒ error - unknown keyword :b ((lambda (:key a :allow-other-keys) a) :a 1 :b 2) ⇒ 1 ((lambda (:key a :allow-other-keys z) (list a z)) :a 1 :b 2) ⇒ (1 (:b 2))
When used with :optional
argument spec, the keyword arguments
are searched after all the optional arguments are bound.
((lambda (:optional a b :key c) (list a b c)) 1 2 :c 3) ⇒ (1 2 3) ((lambda (:optional a b :key c) (list a b c)) :c 3) ⇒ (:c 3 #<undef>) ((lambda (:optional a b :key c) (list a b c)) 1 :c 3) ⇒ error - keyword list not even
:rest variable
Specifies the rest argument. If specified without :optional
argument spec, a list of remaining arguments after required arguments are
taken is bound to variable. If specified with :optional
argument spec, the actual arguments are first bound to required and
all optional arguments, and the remaining arguments are bound to variable.
((lambda (a b :rest z) (list a b z)) 1 2 3 4 5) ⇒ (1 2 (3 4 5)) ((lambda (a b :optional c d :rest z) (list a b c d z)) 1 2 3 4 5) ⇒ (1 2 3 4 (5)) ((lambda (a b :optional c d :rest z) (list a b c d z)) 1 2 3) ⇒ (1 2 3 #<undef> ())
When the rest argument spec is used with the keyword argument spec, both accesses the same list of actual argument—the remaining arguments after required and optional arguments are taken.
((lambda (:optional a :rest r :key k) (list a r k)) 1 :k 3) ⇒ (1 (:k 3) 3)
See also let-optionals*
, let-keywords
and
let-keywords*
macros in Optional argument parsing
for an alternative way to receive optional/keyword arguments
within the spec of R7RS.
A shorthand notation of (lambda (c) body …)
.
where c can be any character in #[_a-z]
.
(map (^x (* x x)) '(1 2 3 4 5)) ⇒ (1 4 9 16 25)
[SRFI-26] Convenience macros to notate a procedure compactly. This form can be used to realize partial application, a.k.a sectioning or projection.
Each expr-or-slot must be either an expression or a symbol <>
,
indicating a ’slot’.
The last expr-or-slot can be a symbol <...>
,
indicating a ’rest-slot’.
Cut
expands into a lambda
form that takes as many arguments
as the number of slots in the given form, and
whose body is an expression
(expr-or-slot expr-or-slot2 …)
where each occurrence of <>
is replaced to the corresponding
argument.
In case there is a rest-slot symbol, the resulting procedure is also
of variable arity, and all the extra arguments are passed
to the call of expr-or-slot. See the fourth example below.
(cut cons (+ a 1) <>) ≡ (lambda (x2) (cons (+ a 1) x2)) (cut list 1 <> 3 <> 5) ≡ (lambda (x2 x4) (list 1 x2 3 x4 5)) (cut list) ≡ (lambda () (list)) (cut list 1 <> 3 <...>) ≡ (lambda (x2 . xs) (apply list 1 x2 3 xs)) (cut <> a b) ≡ (lambda (f) (f a b)) ;; Usage (map (cut * 2 <>) '(1 2 3 4)) (for-each (cut write <> port) exprs)
Cute
is a variation of cut
that evaluates expr-or-slots
before creating the procedure.
(cute cons (+ a 1) <>) ≡ (let ((xa (+ a 1))) (lambda (x2) (cons xa x2)))
Gauche provides a couple of different ways to write partial
applications concisely; see the $
macro below, and also
the pa$
procedure (see Combinators).
A macro to chain applications, hinted from Haskell’s $
operator
(although the meaning is different).
Within the macro arguments arg …, $
delimits
the last argument. For example, the following code makes
the last argument for the procedure f
to be (g c d …)
($ f a b $ g c d ...) ≡ (f a b (g c d ...))
The $
notation can be chained.
($ f a b $ g c d $ h e f ...) ≡ (f a b (g c d (h e f ...)))
If $*
appears in the argument list instead of $
,
it fills the rest of the arguments, instead of just the last argument.
($ f a b $* g c d ...) ≡ (apply f a b (g c d ...)) ($ f a b $* g $ h $* hh ...) ≡ (apply f a b (g (apply h (hh ...))))
Furthermore, if the argument list ends with $
or $*
,
the whole expression becomes a procedure expecting the last argument(s).
($ f a b $ g c d $ h e f $) ≡ (lambda (arg) (f a b (g c d (h e f arg)))) ≡ (.$ (cut f a b <>) (cut g c d <>) (cut h e f <>)) ($ f a b $ g c d $ h e f $*) ≡ (lambda args (f a b (g c d (apply h e f args)))) ≡ (.$ (cut f a b <>) (cut g c d <>) (cut h e f <...>))
The more functional the code becomes, the more you are tempted to write it as a chain of nested function calls. Scheme’s syntax can get awkward in such code. Close parentheses tend to clutter at the end of expressions. Inner applications tends to pushed toward right columns with the standard indentation rules. Compare the following two code functionally equivalent to each other:
(intersperse ":" (map transform-it (delete-duplicates (map cdr (group-sequence input))))) ($ intersperse ":" $ map transform-it $ delete-duplicates $ map cdr $ group-sequence input)
It is purely a matter of taste, and also this kind of syntax sugars can be easily abused. Use with care, but it may work well if used sparingly, like spices.
As a corner case, if neither $
nor $*
appear in the
argument list, it just calls the function. It is useful when
the function has long name and you don’t want to indent arguments
too further right.
($ f a b c) ≡ (f a b c)
[R7RS case-lambda]
Each clause should have the form (formals expr …),
where formals is a formal arguments list as for lambda
.
This expression evaluates to a procedure that accepts a variable
number of arguments and is lexically scoped in the same manner as
procedures resulting from lambda
expressions.
When the procedure is called with some arguments,
then the first clause for which the arguments agree with
formals is selected, where agreement is specified as for
the formals of a lambda
expression.
The variables of formals
are bound to the given
arguments, and the expr … are evaluated within the environment.
It is an error for the arguments not to agree with the formals of any clause.
(define f
(case-lambda
[() 'zero]
[(a) `(one ,a)]
[(a b) `(two ,a ,b)]))
(f) ⇒ zero
(f 1) ⇒ (one 1)
(f 1 2) ⇒ (two 1 2)
(f 1 2 3) ⇒ Error: wrong number of arguments to case lambda
(define g
(case-lambda
[() 'zero]
[(a) `(one ,a)]
[(a . b) `(more ,a ,@b)]))
(g) ⇒ zero
(g 1) ⇒ (one 1)
(g 1 2 3) ⇒ (more 1 2 3)
Note that the clauses are examined sequentially to match the number of
arguments, so in the following example g2
never returns (one ...)
.
(define g2 (case-lambda [() 'zero] [(a . b) `(more ,a ,@b)] [(a) `(one ,a)])) (g2 1) ⇒ (more 1)
Next: Assignments, Previous: Literals, Up: Core syntax [Contents][Index]