-- Leo's gemini proxy

-- Connecting to idiomdrottning.org:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini; lang=en

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


I’m making the function (since it’s a define-time macro)

It’s fixed arity

But I wanna provide flexibility in how many of those args you’re supplying at a time


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.

-- Response ended

-- Page fetched on Fri Mar 29 11:22:01 2024