From: kff@dentex.tds.kth.se (Karl-Filip Faxen)
Newsgroups: comp.lang.functional
Subject: Re: Why curry? (Re: Why functional languages?)
Date: 6 Oct 92 14:17:24 GMT
Reply-To: kff@dentex.tds.kth.se (Karl-Filip Faxen)
Organization: Royal Institute of Technology, Stockholm, Sweden

In article <TMB.92Oct4181821@arolla.idiap.ch>, tmb@arolla.idiap.ch (Thomas M. Br
euel) writes:
|> 
|> Why _do_ people continue to use curried syntax when they just want a
|> function with several arguments? It's difficult to optimize for the
|> compiler, 

That is not correct (and I should know, I'm writing a Haskell 
compiler :-). First, it is not particularly difficult to generate
good code for calls to curried functions (that is, functions with
types like (a -> b -> c -> d -> e)). Every function is represented
as a lambda-expression (e.g. (\x.\y.\z. e)), and in a compiled graph
reduction implementation (e.g. the G machine and its derivates) the
number of nested lambda bindings around the body of the function 
(3 in this case) gives the precise number of arguments that the 
compiled code for the function needs to in order to execute (partial
applications are represented as a thunk (or closure) containing a 
pointer to the code of the supercombinator and a list of the (still 
to few) arguments it has been applied to). Now, if we have a simple,
first order function application (where the applied function is a 
known supercombinator) we can look up the number of outermost lambdas,
check if the function is applied with the right number of arguments
and call an entrypoint that uses some efficient calling convention.

Thus the curried style of function definition carries no additional
cost in itself; it is calling "unknown" functions that cost, and that
cost is regardless of the syntax used when defining the function.

Second, the tupling style also needs to be optimized, or you have to
allocate the tuples explicitly in the heap and then explicitly
destructure them immediately afterwards. This can of course be done,
but it is not any simpler than the above mentioned optimization for 
curried functions (I think :-). Perhaps some of the SML/NJ implementors
can comment on this?

|> it gives uninformative type signatures (is "'a -> 'a -> 'a"
|> intended to be a function of one argument returning a function, or is
|> it intended to be a function of two arguments returning a "'a"?),

It is both. You are free to apply it to two arguments to get a "'a" in 
one place and apply it to one argument and get a function with type 
"'a -> 'a" that you e.g. map over a "'a list" in another place. I do
these things all the time.

|> it's not what most programmers are used to, 

Sorry about this, but I _have_ to remind you that most programmers are
not used to either Haskell or SML at all, but rather to COBOL, BASIC
and FORTRAN. The question is: What is easiest to get used to, and, once
gotten used to, most productive? And as that is difficult to measure,
this point boils down to a matter of taste, and taste is not to be 
argued about.

|> and it seems to be difficult to indent automatically as well.

In an Emacs mode, perhaps. In a pretty printer, certainly not (I've
written one).

Cheers,
         Karl-Filip

------------------------------------------------------------
Make the frequent case fast, and the fast case frequent!