3 ms·
> The author makes a bunch of tenuous assumptions; that lambda calculus is all about currying My first thought exactly. Lisp is based on lambda calculus and it
by dreamcompiler 4y ago
> The author makes a bunch of tenuous assumptions; that lambda calculus is all about currying
My first thought exactly. Lisp is based on lambda calculus and it doesn't do automatic currying. Multiline lambdas require block delimiters more sophisticated than whitespace; hence they don't work in Python. It's no more complicated than that.
- shrimpx 4y agoI think if you really tried you could make it work but there are a lot of ugly and unique tradeoffs to work through. Something like this could work: foo((lambda x, y: for i in range(x): y += i return y), 20 )
- kazinator 4y agoIt could work like this: foo (lambda x, y::, 20) # :: means body of lambda follows :: # optional, if there is only one lambda and line has no argument lines for i in range (x): y += i return y The lambda bodies immediately follow the line. If the line has arguments, those follow the lambdas: if foo(lambda x::, list) < bar(lambda y::, list): :: # lambda x return x + x :: # lambda y return 2 * y return list # then statement of if
- kazinator 4y agoThe def keyword followed by a colon could be used as the marker for the continuation material that supplies the multi-line lambada bodies. Perhaps the double colon would be unnecessary: just make the expression optional, and if it's missing then there has to be an "outboard" body. if foo(lambda x:, list) < bar(lambda y:, list): def: # lambda x return x + x def: # lambda y return 2 * y return list # then statement of if
- kazinator 4y agoWhat Lisp doesn't do is partial application: returning a function of N-M arguments when you only apply M arguments to one that needs N. Languages which do that have issues representing very useful software engineering tools: optional arguments, variadic arguments and keyword arguments. Currying is related to partial application; it refers to a technique for representing multivariate functions using only functions of one argument. E.g. to obtain some f(x, y, z) we instead make it f(x)(y)(z), where f is a one-argument function applied to (x). That yields an anonymous one-argument function that is applied to (y), and that again yields a one-argument function applied to (z), which finally calculates f(x, y, z). Whereas partial application is this: we already have a bona fide three-argument f(x, y, z), and the ability to call it with all three arguments at once. But for some reason, we call it as f(x)(y)(z). Now f needs 3 arguments but is called with just one, (x). So an anonymous two-argument function is produced which, if given two arguments will combine those with the one that was given and call f. Alas, that function is given only one argument, so it returns another one-argument function. When that one is given an argument, it all unwraps, and f ends up being called. These anonymous functions are understood to be produced because our notation is understood to have implicit partial application semantics. Under currying, things aren't implicit; f(x) is written as a one-argument function, which will have a lambda term in it. There is nothing to be implicit about in terms of application: all functions have one argument.
- Ferret7446 4y agoThat sounds like semantic wordplay. Functionally, how is currying and partial application different? Given two otherwise identical languages which use either currying or partial application, both languages would run every single program exactly the same way.
- dreamcompiler 4y agoThanks for the clarification. I'm guilty of saying things like "Haskell does automatic currying" when in fact it does automatic partial application. But then again I don't actually know what goes on under the sheets in Haskell. It might in fact convert every multi-argument function to a nested single-argument curry-like lambda form internally, whether it needs to or not. I expect that would be inefficient (because it would cons up a lot of unnecessary functions), but it's possible. Does Haskell only do partial application when it actually needs to, or does it do single-argument curry-ish partial application of every function regardless?