💾 Archived View for idiomdrottning.org › define-curry captured on 2024-05-10 at 11:38:57. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2021-12-03)

-=-=-=-=-=-=-

define-curry

Update: Now part of brev-separate.

A friend suggested a define-curry macro and to me what immediately came to mind was something like this:

(define-curry (foo bar baz bax)
  (print baz)
  (+ bar baz bax))

(=
 (foo 100 20 3)
 ((foo 100) 20 3)
 ((foo 100 20) 3)
 ((foo) 100 20 3)
 (((foo) 100) 20 3)
 (((foo 100) 20) 3)
 ((((foo) 100) 20) 3))

Prints seven 20 and evals #t.

Here is the implementation:

(import miscmacros)

(define-syntax-rule
  (define-curry (name . args) . body)
  (define (name . friends)
    (if (= (length friends) (length 'args))
        (apply (lambda args . body)  friends)
        (lambda stragglers
          (apply name (append friends stragglers))))))

Bonus episode

Here is a partial application functional combinator that’s arbitrary arity but not recursive. It’s a replacement for cut when every slot is at the end of the arg list.

(define (🍛 name . args)
  (lambda stragglers
    (apply name (append args stragglers))))

(= 54321
 ((🍛 + 1 20 300) 4000 50000)
 ((🍛 (🍛 + 1 20 300) 4000) 50000))

⇒ #t

I’ve seen people asking “why use the macro when you have this partial applicator”?

The advantages of this applicator is that you get arbitrary arity and that you can use it on existing procedures. Pretty great and I use it a lot.

The advantage of the macro, for fixed arity functions, is that it lets you repeatedly curry it. You can add as many or as few argument as you want and until you’ve jammed all the args in there, it’s still a proc. Only as you put those last args in place is when that procedure’s called for the value. I don’t use that as much because it’s for situations when

In other words, pretty niche. I just think it’s neat.

For example:

(map (foo 12 45) '(20 30 40))

or

(map (foo 12) '(12 16) '(80 1000))

The example I used earlier:

((🍛 (🍛 + 1 20 300) 4000) 50000)

If that had been a function made with define-curry instead, say it was called jank, we could’ve:

(((jank 1 20 300) 4000) 50000)

The recursive partial application is built in.