SRFI 232: An advanced currying form
Arthur A. Gleckler
(08 Jan 2022 02:21 UTC)
|
Re: SRFI 232: An advanced currying form
Dr. Arne Babenhauserheide
(08 Jan 2022 17:24 UTC)
|
Re: SRFI 232: An advanced currying form
Marc Nieper-Wißkirchen
(08 Jan 2022 18:26 UTC)
|
Re: SRFI 232: An advanced currying form
Wolfgang Corcoran-Mathe
(09 Jan 2022 18:45 UTC)
|
Re: SRFI 232: An advanced currying form
Marc Nieper-Wißkirchen
(09 Jan 2022 21:56 UTC)
|
Re: SRFI 232: An advanced currying form
Wolfgang Corcoran-Mathe
(13 Jan 2022 22:37 UTC)
|
Re: SRFI 232: An advanced currying form Marc Nieper-Wißkirchen (14 Jan 2022 07:24 UTC)
|
Re: SRFI 232: An advanced currying form
Wolfgang Corcoran-Mathe
(18 Jan 2022 19:30 UTC)
|
Re: SRFI 232: An advanced currying form
Marc Nieper-Wißkirchen
(19 Jan 2022 00:44 UTC)
|
Re: SRFI 232: An advanced currying form
John Cowan
(16 Jan 2022 18:29 UTC)
|
Re: SRFI 232: An advanced currying form
Marc Nieper-Wißkirchen
(16 Jan 2022 18:52 UTC)
|
Re: SRFI 232: An advanced currying form
Marc Nieper-Wißkirchen
(16 Jan 2022 19:01 UTC)
|
Re: SRFI 232: An advanced currying form
John Cowan
(20 Jan 2022 06:21 UTC)
|
Re: SRFI 232: An advanced currying form
Wolfgang Corcoran-Mathe
(18 Jan 2022 18:28 UTC)
|
Re: SRFI 232: An advanced currying form
Wolfgang Corcoran-Mathe
(18 Jan 2022 18:38 UTC)
|
Re: SRFI 232: An advanced currying form
Marc Nieper-Wißkirchen
(18 Jan 2022 19:00 UTC)
|
Re: SRFI 232: An advanced currying form
Wolfgang Corcoran-Mathe
(18 Jan 2022 21:22 UTC)
|
Re: SRFI 232: An advanced currying form
Marc Nieper-Wißkirchen
(18 Jan 2022 22:18 UTC)
|
Re: SRFI 232: An advanced currying form
Marc Nieper-Wißkirchen
(19 Jan 2022 07:47 UTC)
|
Re: SRFI 232: An advanced currying form
Marc Nieper-Wißkirchen
(19 Jan 2022 20:55 UTC)
|
Re: SRFI 232: An advanced currying form
Wolfgang Corcoran-Mathe
(24 Jan 2022 23:08 UTC)
|
Re: SRFI 232: An advanced currying form
Marc Nieper-Wißkirchen
(26 Jan 2022 13:29 UTC)
|
Re: SRFI 232: An advanced currying form
Wolfgang Corcoran-Mathe
(31 Jan 2022 21:42 UTC)
|
Re: SRFI 232: An advanced currying form
Dr. Arne Babenhauserheide
(09 Jan 2022 01:35 UTC)
|
Re: SRFI 232: An advanced currying form
John Cowan
(16 Jan 2022 18:15 UTC)
|
Re: SRFI 232: An advanced currying form
Wolfgang Corcoran-Mathe
(09 Jan 2022 18:47 UTC)
|
Am Do., 13. Jan. 2022 um 23:37 Uhr schrieb Wolfgang Corcoran-Mathe <xxxxxx@sigwinch.xyz>: > > I'm re-ordering the quotations in this response to put what seems > like the most important topic first. > > > You can introduce a form that creates procedures taking up to the > > number of formal arguments and always returns a procedure. And it is a > > mistake if more than the number of formal arguments are given. > > > > A second form is needed (and should really be separate) for the second > > case. Here, a procedure is created that takes at least the number of > > formal arguments and always applies the access arguments to the > > result. And it is a mistake if less than the number of formal > > arguments are given. > > Let's consider what these would look like. I'll just call them > λc and λx ("lambda curry" and "lambda extra"). λc is much like the > current lambda*, except that it always returns a procedure and it > raises an exception when applied to too many arguments: > > ;; One list argument for simplicity. > (define fold-c > (λc (kons knil xs) > (fold kons knil xs))) > > (fold-c * 1 '(1 2 3)) => #<procedure> > ((fold-c * 1 '(1 2 3))) => 6 > (fold-c * 1 '(1 3 5) '(2 4 6)) ; exception: arity mismatch I know that this is just an example, but this example already shows another deficiency of the current approach: "fold" can take more than one list argument, making "fold-c" strictly less powerful. > (let ((product-maker (fold-c * 1)) > (sum-maker (fold-c + 0)) > (ns '(2 4 6))) > (list ((product-maker ns)) > ((sum-maker ns)))) > > => (48 12) > > λx, on the other hand, only handles the "extra-arguments case": > > (define sum-div > (λx (ns) > (lambda (d) > (/ (fold + 0 (append extra ns)) d)))) > > (sum-div '(2 4 6) 3) => 4 > (sum-div) ; exception: arity mismatch > (sum-div '(2 4) 4 5) ; exception: arity mismatch > > I'm sorry if these examples seem a bit dumb. Hopefully this is > something like what you had in mind. Assuming these forms are > correct: they're consistent, but I don't like them very much. Having > to apply the thunk returned by λc seems clumsy and pedantic, and makes > the form very tricky to use in compositions; applying the thunk is > also something you'll probably forget to do. λx looks OK, but not > exactly thrilling. I don't want to say that I like the new forms very much, but I like the old lambda* even less. There's certainly room for improvement for lambda-c and lambda-x. > One compromise that I've considered is removing the > extra-argument-passing semantics of lambda*; it's simply an error to > pass surplus arguments, as with λc above. This retains the useful > behavior of lambda* and eliminates what is probably the biggest > source of bugs. There is still the ambiguity of what is returned > when the expected number of arguments is provided, though. (I still > think it makes good practical sense to apply at that point.) > > Opinions? The case of fold, which can take an arbitrary number in its original form, above shows that sometimes you want the invocation of the resulting procedure and that sometimes you don't want the invocation. Thus it is best to be explicit here. The question is what is the best way to make it explicitly. > > > As Scheme nowadays usually supports Unicode, schönfinkel or > > шейнфинкель would be better than curry. But certainly not optimal. :) > > > > I would postpone this discussion (which is bike-shedding at this > > point) until the semantics of the new form(s) have been fixed. > > Fine. Let's hold off on naming. Keep thinking of catchy names, > though. > > > > I agree that I'd like to see useful examples of lambda*, and I believe > > > that the sum/product example given in the SRFI is one, though it's > > > tiny. > > > > I think the sum and product examples are just examples coincidentally > > because the fold procedure happens to take the list as its last > > argument. They would better serve as motivating examples for SRFI 26. > > Perhaps so, and, of course, cut is more flexible. But I think there's > a major brevity advantage to being able to do simple "ordered" partial > application. Consider this short snippet adapted from SICP Section > 2.2.3, as written with lambda*-style currying: > > (compose (map make-pair-sum) > (filter prime-sum?) > (append-map pair-over-interval)) > > With SRFI 26 instead: > > (compose (cut map make-pair-sum <>) > (cut filter prime-sum? <>) > (cut append-map pair-up <>)) > > (What the functions do isn't important here.) This is a simple example > and the difference isn't huge, but I think it's clear that the first > version is easier to read and contains less extraneous information. It's not clear that the first version is easier to read; not for me, at least. I'd prefer (compose (lambda (ls) (map make-pair-sum ls)) ...). Anyway, as we shouldn't redefine map, the above example wouldn't look like that with SRFI 232, but you would have to write something like (compose (map* make-pair-sum) ...) where map* is the lambda*-version of map* exported by some library. But then, lambda* just becomes some implementation detail of that library and we could write down the semantics of map* (and fold* and whatever) directly. What would work better in your example above is an approach where currying/uncurrying does not become a property of the procedure (which leads to the problem that all standard procedures don't do it and you would have to double them) but where it becomes part of the application operation (see also below). It would be something like: (compose (! map make-pair-sum) (! filter prime-sum?) (! append-map pair-up)) Here, ! is cut but with an implicit <...> at the end. Even better would be to overload the syntax (map make-pair-sum ...) (with a literal ellipsis), but this cannot be done portable. (It can be done with Racket's #%app and identifier properties, but we don't have #%app standardized in Scheme.) > > Again, citing ML and Haskell here is not the right thing for Scheme > > because ML and Haskell are strongly typed. > > Yes, there are serious differences and I don't mean to conflate what > those languages do and SRFI 232. I've been referring to them in a > broader, cultural (!) sense: In these languages, partial application > is common and considered ["by whom?"] idiomatic. In Haskell, you must use partial application because all procedures are single-argument procedures. So it seems to be a bit like saying that the use of many parentheses is considered idiomatic in Scheme. > Regardless of the > theoretical background, it's easy to write "curried procedures" in, > say, Haskell without explicit lambda abstraction or fancy syntax. > I suggest that it is nice to be able to do the same in Scheme, though > the foundations of the idiom are very different in a dynamically-typed > language. The reason why it is simple in Haskell is that it is built in the application operator. What SRFI 232 currently tries to do is to put all the work into the procedure creation operator. My above example with "!" shows how it would look if the application operation is modified instead to give partial application. With !, fold* would be simply (define fold* (! fold)) And the definition of ! would be (untested) (define-syntax ! (syntax-rules () ((! proc-expr formal ...) (let ((proc proc-expr) (arg formal) ...) (lambda rest (apply proc arg ... rest)))))) Here, fold* will take any number of arguments but will always return a partial application. > > What would be the semantics of a hypothetical +* in Scheme be? > > Good question. I'm mildly worried about the semantic loophole this > introduces; a +* (or any other "omniadic") procedure would be an > operational paradox, since the point of evaluation would be > completely arbitrary. ("How many arguments does it take before > they're added and the value returned?") The good news is that > there doesn't seem to be a way to express such a procedure with > lambda* (or λc or λx). (define +* (! +)) seems to make sense, though. Marc PS I hope you find this discussion constructive!