Arc Forumnew | comments | leaders | submitlogin
Currying
3 points by mariusg 5160 days ago | 2 comments
Hi everybody. Can't we use the [+ _ 3] syntax for currying?

If we re-interpret [fn-name arg1 ... argn] as (curry fn-name arg1 ... argn) as define curry as something like:

  (defun combine (curry-args call-args)
    (let* ((args (mapcar #'(lambda (x)
                             (if (eq '_ x) (pop call-args) x))
                   curry-args)))
      (append args call-args)))

  (defun curry (fn &rest curry-args)
    #'(lambda (&rest call-args)
        (apply fn (combine curry-args call-args))))
(please excuse use of Common Lisp and possibly bad style, I'm currently learning all this...)

- [/ _ 2] would mean the same as before

- [foo _ _] would get different meaning, this a downside, but perhaps not that bad

- [+ 3 _] can be written as [+ 3]

- (= map-inc [map [+ 1]]) is possible

- (funcall [foo _ 2 _ 4] 1 3 5 6) is (foo 1 2 3 4 5 6)

What do you think?

Marius



3 points by rocketnia 5160 days ago | link

I usually don't care about currying, but I like this. XD There are places I might miss the ability to use _ from inside other parentheses, like [... (foo _ bar) ...], but it would be interesting to explore the advantages.

Anarki[1] already lets us change the square bracket behavior by redefining the 'make-br-fn macro. In ar[2], it's the 'square-bracket macro.

Here's my take on your idea. When the operator is actually a macro, I just treat it the old way rather than unsuccessfully calling 'apply on it:

  (mac make-br-fn contents
    (iflet (op . args) contents
      (if (isa (bound&eval op) 'mac)
        `(fn (_) ,contents)
        (w/uniq g-args
          `(fn ,g-args
             (apply ,@(map (fn (x) (case x _ `(pop ,g-args) x))
                           contents)
                    ,g-args))))
      `(fn args (whenlet (op . args) args (apply op args)))))
Here's a half-demonstration thanks to http://tryarc.org/. It doesn't provide 'make-br-fn or 'square-bracket, so I haven't bothered to actually use the square brakcets:

  arc> ((make-br-fn car) '(1 2 3))
  1
  arc> ((make-br-fn list 1 _ _ 4 _) 2 3 5 6)
  (1 2 3 4 5 6)
  arc> (macex '(make-br-fn list 1 _ _ 4 _))
  (fn gs1022 (apply list 1 (pop gs1022) (pop gs1022) 4 (pop gs1022) gs1022))
  arc> (macex '(make-br-fn list))
  (fn gs1023 (apply list gs1023))
  arc> (macex '(make-br-fn))
  (fn args (whenlet (op . args) args (apply op args)))
  arc> ((make-br-fn))
  nil
  arc> ((make-br-fn) + 1 2)
  3
  arc> (((make-br-fn fn (it) _.it) inc) 4)
  Error: "reference to undefined identifier: _fn"
  arc> (((make-br-fn afn (it) _.it) inc) 4)
  5
As you can see, my approach has a little bit of room for improvement. The 'fn special form isn't actually a macro, so this treats it like a function. :-p (Also, I don't do anything about ssyntax, like [a:b c d] or [a&b c].)

---

[1] https://github.com/nex3/arc

[2] https://github.com/awwx/ar

-----

2 points by akkartik 5160 days ago | link

I'm trying to think about how this would interact with the way to more explicitly specify currying in http://arclanguage.org/item?id=13790

-----