#lang spicy
(define (map f)
(foldr (compose cons f) empty))
(module+ main
(define a '(1 2 3))
(define (f x) (* x x))
(map f a))
Compare not spicy:
#lang racket
(define (->1 f) (λ (a b) (values (f a) b)))
(define (map f . args)
(apply curry foldr (compose cons (->1 f)) empty args))
(module+ main
(define a '(1 2 3))
(define (f x) (* x x))
(map f a))
For fewer parentheses, combine spicy with sweet-exp:
#lang sweet-exp spicy
define map(f)
foldr (compose cons f) empty
module+ main
define a '(1 2 3)
define (f x) (* x x)
map f a
To spice locally, spicy/sauce
:
#lang sweet-exp racket
require spicy/sauce
module+ main
with-curry
define mymap-local(f)
foldr (compose cons f) empty
mymap-local
λ (x) {x * x}
'(1 2 3)
;
splicing-with-curry
define mymap(f)
foldr (compose cons f) empty
;; now autocurry is off
(mymap (λ (x) {x * x}))
'(1 2 3)
Some more simple examples, based on those in Hughes (1984): Why functional programming matters and racketified.
For details, take the tour.
- All function applications are curried. Currying is applied from the left.
- Keyword arguments can be passed in the initial call, just like when currying manually in Racket.
- Any arguments over max-arity are passed through on the right, by constructing a multiple-values object.
- This makes the above example possible, although the arities of
f
andcons
are different.
- This makes the above example possible, although the arities of
- If the application also returns a multiple-values, the remaining arguments (if any) are appended into it.
- If the application produces only one value, which is another curried procedure, it is applied to the remaining arguments.
- See the tour for where this is useful.
- The auto-curried procedure immediately switches to the mode where any acceptable arity triggers a call.
- In contrast, currying manually in Racket always curries at least once (if a higher arity exists).
- Hence some variadic functions (notably e.g.
+
,*
) cannot be auto-curried inspicy
, since they accept any arity ≥ 0. - Curry manually to revert to Racket's usual processing:
+ 1
→ 1, butcurry + 1
→#<procedure:curried>
.- It will still use the customized
curry
function fromspicy
, but skips the automatic mode switching.
- It will still use the customized
- Copy the files anywhere you want.
- Open a terminal in the
spicy/
subfolder. raco pkg install
To uninstall, raco pkg remove spicy
.
Essentially, a custom #%app
macro to rewrite function applications at compile time, a customized curry
, and four lines of code to package that as a language that borrows everything else from Racket.
Also, the compose
function is overridden by a curry-aware version, which spices its arguments.
Primarily meant for teaching purposes. Tested only on toy examples.
Not completely seamless, and cannot be. Automatic currying and variadic functions do not play well together; also, dynamic typing implies that the system won't notice if you miss an argument somewhere - which may make your code hard to debug. For discussion on the topic, see e.g. here, here and here.
Contains a customized version of Racket's curry
, which is used under GNU LGPL 3.0.
- sweet-exp is currently used by the implementation in spicy/expander.rkt.