Currying in Scheme (cut operator)
curry :: ((a, b) -> c) -> a -> b -> c
In scheme this is called cut
. You can remember it as curry upon this / cut as in an operator section (indicated by the holes: <>
).
By example:
(cut cons (+ a 1) <>) is the same as (lambda (x2) (cons (+ a 1) x2))
<>
indicates a slot to be filled.
As you can see above, cons (+ a 1)
requires another argument to “cons to”, “<>” serves as the placeholder in this slot.
Other examples:
(cut list 1 <> 3 <> 5) is the same as (lambda (x2 x4) (list 1 x2 3 x4 5))
(cut list) is the same as (lambda () (list))
We also have variable length slots (<...>)
, to hold a variable number of arguments.
(cut list 1 <> 3 <...>) is the same as (lambda (x2 . xs) (apply list 1 x2 3 xs))
(cut <> a b) is the same as (lambda (f) (f a b))
Implementation
(define-syntax cut
(syntax-rules ()
((cut . slots-or-exprs)
(srfi-26-internal-cut () () . slots-or-exprs))))
(define-syntax srfi-26-internal-cut
(syntax-rules (<> <...>)
;; construct fixed- or variable-arity procedure:
;; (begin proc) throws an error if proc is not an <expression>
((srfi-26-internal-cut (slot-name ...) (proc arg ...))
(lambda (slot-name ...) ((begin proc) arg ...)))
((srfi-26-internal-cut (slot-name ...) (proc arg ...) <...>)
(lambda (slot-name ... . rest-slot) (apply proc arg ... rest-slot)))
;; process one slot-or-expr
((srfi-26-internal-cut (slot-name ...) (position ...) <> . se)
(srfi-26-internal-cut (slot-name ... x) (position ... x) . se))
((srfi-26-internal-cut (slot-name ...) (position ...) nse . se)
(srfi-26-internal-cut (slot-name ...) (position ... nse) . se))))