![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
On 22-4-2012 12:40, Warp wrote:
> Orchid Win7 v1<voi### [at] dev null> wrote:
>>> For instance,
>>> I still don't understand what currying *really* is about, and every time
>>> I try to suggest "is like this?" the answer is "not really".
>
>> 1. You can take a 5-argument function, pass it 2 argument, and get a
>> 3-argument function as the result.
>
> But that's the thing: It sounds so trivial as to defy sense. Why give
> a particular name to such a trivial thing? It's like calling the act of
> taking a 3-dimensional vector and expanding it to a 4-dimensional one
> "potatoing", or taking two integers and adding them together "bananaing",
> or taking a class and adding another class as its member "orangeing".
> Why give an obscure name to such a trivial operation?
>
> But then when one starts asking questions like "so it's like giving
> default values to function parameters?" or "so it's like writing another
> function with less parameters that calls the first function by giving it
> some default values as the rest of the parameters?", the answer is something
> like "not really".
My answers to why currying is important is that
- if you have currying, you have function application. if you have a one
input function and you supply that input you reduce it to a zero
argument function a.k.a. a constant. If you think about it that way the
distinction between a value and a function gets blurred.
- I think that one of the main reasons to give it a name is that when
the concept was invented you suddenly had (non-exotic) functions that
could take functions as argument and return yet another function. In
short it is when functions transformed from recipes to objects.
When you have done OO languages for some time you might not see the
point anymore, that does not mean that at one point in time you made the
mental transition yourself.
--
tip: do not run in an unknown place when it is too dark to see the
floor, unless you prefer to not use uppercase.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp escreveu:
> clipka <ano### [at] anonymous org> wrote:
>> So yes: Currying *is* like writing a function that takes fewer
>> arguments, calling the original one and supplying (unchangeable)
>> defaults for the missing arguments.
>
> I think that the difference is that the new function is not static,
> but it's generated dynamically. (In other words, what you end up is a
> new function which fixes some of the parameters of the original function,
> but the values to which they are fixed is determined at runtime rather
> than at compile time.)
>
> This means, if I understand correctly, that you could for example create
> such functions in a loop (or, as we are talking about functional languages,
> in a recursive manner), which is quite difficult to achieve with static,
> compile-time functions. (I suppose you could try to emulate this in a
> statically typed language with no lambda functions, but you would need
> some kind of stack or something where the fixed parameter values are
> stored.)
>
> There are probably even deeper implications.
currying comes from Haskell Curry, the mathematician behind many further
lambda calculus concepts.
Here's the thing about the lambda calculus, which is at the kernel of
haskell the language: all the functions are one-argument functions that
return other one-argument functions. So, multiple argument functions
are actually just syntatic sugar for convenience. And yes, clearly
syntatic sugar is a good thing, as any competent C++ template writer can
attest.
Surely writing a function and letting the compiler handle all the
partial applications is much saner than writing yourself functions for
each possible partial application case. And no, I don't think in
haskell such functions are dynamically generated. Like I said, the
concept of one-argument functions is at the very heart of haskell: the
compiler breaks all functions down into one-argument functions, at
compile time.
Then again, in languages with default and keyword arguments you do not
need to worry about that, only to remember the argument names. Argument
position, names or order, though, can still shoot everyone in the foot.
--
a game sig: http://tinyurl.com/d3rxz9
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Am 25.04.2012 10:07, schrieb Invisible:
> On 25/04/2012 06:08 AM, Darren New wrote:
>> On 4/23/2012 1:05, Invisible wrote:
>>>> There are lots of languages that let you can pass a function as an
>>>> argument.
>>>
>>> Heh. I bet most of them are scripting languages though. :-P
>>
>> Not really. Arguably, even C allows it, C++, C# allows a delegate which
>> is essentially the same thing, and yes, bunches of interpreted languages.
>
> C and C++ have function pointers. It's dubious whether functions are
> "first class", but certainly you can pass them as arguments.
>
> C# presumably allows /everything/.
>
> Java allows you to use the reflection API to create an object that
> represents a function method, and to invoke that method. Alternatively
> you can use anonymous inner classes. (The fact that this feature even
> /exists/ tells you how badly Java programmers want anonymous functions.)
>
> Pascal? Forget it.
Turbo Pascal? Definitely yes, as I mentioned before!
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
nemesis <nam### [at] gmail com> wrote:
> Here's the thing about the lambda calculus, which is at the kernel of
> haskell the language: all the functions are one-argument functions that
> return other one-argument functions. So, multiple argument functions
> are actually just syntatic sugar for convenience.
But what's the advantage in having only one-argument functions?
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>> Pascal? Forget it.
>
> Turbo Pascal? Definitely yes, as I mentioned before!
OK, but that's not really the classic Pascal of old.
The same probably goes for Delphi, which [I gather] is a further
extension of Turbo Pascal.
In a similar was, AMOS BASIC has local variables, named functions and
procedures, separate compilation, and a whole chock-load of features. In
fact, so many features that it hardly counts as "BASIC" any more; it's
more like a brand new language with a superficial resemblance to BASIC...
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
On 25/04/2012 09:01 PM, Warp wrote:
> nemesis<nam### [at] gmail com> wrote:
>> Here's the thing about the lambda calculus, which is at the kernel of
>> haskell the language: all the functions are one-argument functions that
>> return other one-argument functions. So, multiple argument functions
>> are actually just syntatic sugar for convenience.
>
> But what's the advantage in having only one-argument functions?
If you're writing a mathematical theory about which computations are
possible, then only having to worry about 1-arg functions makes the
theory simpler. That's why the lambda calculus does it that way.
If you're trying to write a real program to run on a real computer,
that's another matter.
It's useful to be able to quickly throw together a new function by just
writing a partial call to an existing one. The easiest way to implement
that is to consider every function to be a 1-arg function.
Aside from a couple of other conveniences, it also allows you to process
functions of variable numbers of arguments in a uniform way: Keep adding
arguments, one at a time, until it's full.
There's nothing deeply fundamental or sacred about 1-arg functions. They
just have a couple of useful properties, that's all.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp escreveu:
> nemesis <nam### [at] gmail com> wrote:
>> Here's the thing about the lambda calculus, which is at the kernel of
>> haskell the language: all the functions are one-argument functions that
>> return other one-argument functions. So, multiple argument functions
>> are actually just syntatic sugar for convenience.
>
> But what's the advantage in having only one-argument functions?
seemingly, automatic currying.
--
a game sig: http://tinyurl.com/d3rxz9
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Orchid Win7 v1 <voi### [at] dev null> wrote:
> On 25/04/2012 09:01 PM, Warp wrote:
> > nemesis<nam### [at] gmail com> wrote:
> >> Here's the thing about the lambda calculus, which is at the kernel of
> >> haskell the language: all the functions are one-argument functions that
> >> return other one-argument functions. So, multiple argument functions
> >> are actually just syntatic sugar for convenience.
> >
> > But what's the advantage in having only one-argument functions?
> If you're writing a mathematical theory about which computations are
> possible, then only having to worry about 1-arg functions makes the
> theory simpler. That's why the lambda calculus does it that way.
I can believe that. However, what I was really asking was what's the
advantage of having only one-argument functions in a practical programming
language.
> It's useful to be able to quickly throw together a new function by just
> writing a partial call to an existing one.
That seems to be a very specialized case. There are tons of other
combinations (eg. in terms of the number of parameters to a function,
among many other things) that can be equally useful.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>> There is commutativity for the identity element, but it is not needed to
>> be commutative.
>
> A monoid is /defined as/ having a two-sided identity.
I had hoped to prove that the associativity of # implies the
two-sidedness of any identity element. Instead, somebody showed me a
counter-example:
If we define # as
∀ x, y ∈ S, x # y = y
then every element of S is trivially a left-identity, and no
right-identity exists. Miraculously, this operator is also associative:
x # y # z
(x # y) # z = y # z = z
x # (y # z) = x # z = z
So it seems it /is/ perfectly possible for a semigroup to have one or
more one-sided inverses - it's just that they all have to be /the same/
side. A monoid, on the other hand, is /defined as/ having a two-sided
inverse, as I originally asserted.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>> If you're writing a mathematical theory about which computations are
>> possible, then only having to worry about 1-arg functions makes the
>> theory simpler. That's why the lambda calculus does it that way.
>
> I can believe that. However, what I was really asking was what's the
> advantage of having only one-argument functions in a practical programming
> language.
Sure, I get that. I was just adding a point of context.
>> It's useful to be able to quickly throw together a new function by just
>> writing a partial call to an existing one.
>
> That seems to be a very specialized case. There are tons of other
> combinations (eg. in terms of the number of parameters to a function,
> among many other things) that can be equally useful.
You'll notice that Haskell programmers are very particular about the
order in which a function takes its arguments - because, as you say, you
can only partially apply the functions IN ORDER.
Haskell has one sole exception to this: Binary operators can be curried
in any order. So (5/) and (/5) are both valid functions (and, you'll
notice, have different meanings).
If it's /really/ a problem, it's utterly trivial to write a tiny little
lambda function to set one of the arguments in the middle of the
argument list. Currying is just a handy short-cut in that instance.
As I say, the only "really powerful" thing about currying is the ability
to polymorphically handle multi-argument functions. Other than that,
it's just a handy short-cut.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |