1. 17
    1. 3


      ((((((((((((((foo))))) 100)))))))) 20 3)
    2. 1

      The only problem I see is that there are arbitrary arity procedures, and this define-curry would only work for fixed arity.

      1. 2

        Yeah. As stated in the post and elaborated in threads here.

      1. 2

        That’s great but that’s not all this is.

        The kind of stuff on that Rosetta page would be a simple

        (define ((multiplier a) b) (* a b))

        What I posted is a macro for arbitrary-arity, level-recursive currying, and (in the bonus episode) an arbitrary-arity currying functional combinator.

    3. 1

      How does this differ to the currying syntax that some schemes provide directly in define or lambda (https://srfi.schemers.org/srfi-219/)?

      1. 4

        Yes, a lot of schemes provide directly in a lambda or define the ability to make something like this:

        (define (((foo bar) baz) bax) (+ bar baz bax))

        That is an amazing construct, I’m into it, I’m happy Scheme can do it.

        I made a post here about that type of curry a month ago and a comment about that type of curry an hour ago.

        What I’ve made here is more awesome in the following way.

        With (define (((foo bar) baz) bax) (+ bar baz bax)), you have to predict the arities exactly.

        Sure, you can do

        (map (lambda (proc) (proc 500)) (map (foo 3) '(10 20 30)))

        and get (513 523 533).

        But with the define-curry I’ve made here, if you do

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

        Not only does the above map work (and give the same (513 523 533) result). You can curry any of the arguments. All or none or just some.

        (define (((foo bar) baz) bax) (+ bar baz bax)) means that you predict that you are gonna add on one argument first, and then the other, and then the other.

        Or you might want to take two arguments first and only leave one argument hanging: (define ((foo bar baz) bax) (+ bar baz bax)) or you might want to take one argument first and leavet two arguments hanging: (define ((foo bar) baz bax) (+ bar baz bax))

        You have to know before. The procedures aren’t flexible at all.

        With (define-curry (foo bar baz bax) (+ bar baz bax)), you can call foo with any number of arguments and it’ll wait for the rest.

        You can even use it like any normal procedure and do (foo 10 200 3) right away to get 213. Or you can do (foo 10 200) and wait for the last number, or (foo 10) and wait for the last two numbers. And if you do, you can even then only give it one and keep waiting even more on that last number .You get a procedure that’s ready for anything!

        That’s what I mean by arbitrary-arity, level-recursive currying.

        That’s why my example was:

         (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))

        All those forms evaluate to the same thing! That’s the baller part! And (((foo) 100 20) 3) also or for that matter (((((foo)) 100)) 20 3).

        This is great, all those times I’ve used a procedure and been like “aw, man, I wish this was curried!”

        If it had been curried (using the SRFI-219 style curries), that would’ve gotten obnoxious quickly too, because I would’ve had to add in those extra parens everytime I didn’t need the curry feature. I would’ve had to always write ((((foo) 100) 20) 3) or whatever the procedure-writer predicted I was gonna need to write.

        That’s why this is awesome.

        Now to the bonus episode. The define-curry I made is great when defining new procedures but what about all the backlog of existing procedures? Like + and print and list. I don’t wanna be bothered to re-define all of them with define-curry, I want to be able to use them and curry them as they are. That’s why I made 🍜 (yeah, combinators and operators can be or contain emoji in Chicken Scheme).

        I just prefix any function with 🍜 and it gains one level of arbitrary arity curry. (🍜 list 1 1 2 3 5) becomes a procedure that waits for more arguments to add to the list, so

        ((🍜 list 1 1 2 3 5) 8 13 21 34)

        (1 1 2 3 5 8 13 21 34).

        This is worse than the define-curry I made at the top of the post in the sense that it only gives me one level of calls / parens. If I need more levels, I need to add more 🍜.

        ((🍜 (🍜 list 1 1 2 3 5) 8 13) 21 34)

        (1 1 2 3 5 8 13 21 34).

        On the other hand, one part of the 🍜 combinator that is better than my define-curry is that it can handle procedures that themselves are already arbitrary-arity, like list and + and string-append. The define-curry only works with procedures that have a specific number of arguments. (In the case of the foo example, three arguments and it always adds three numbers.) Also, again, that it works on already existing procedures, not just newly defined ones.

        1. 3

          This is a cool post on multiple levels. As an ocaml fan, it’s fun reading about currying in Scheme. And kudos for 🍜 as an identifier! Functional programming, food, and puns: three of the good things in life.

          1. 2

            It feels like The Little Schemer for 2021.

        2. 2

          I don’t understand why the ramen emoji was chosen when there’s a perfectly good curry with rice emoji 🍛

          1. 1

            Because I didn’t know about it! Post now updated to use 🍛, thank you!♥

            Trying to making that change over SSH (which I failed to do, I had to get up and go to the desktop) reminded me that it’s probably better to use some other identifier for this combinator. Maybe just a letter, k or h or c or something. I originally wanted to make read-syntax, some special kind of parentheses or something for this.