ENOSIG Discussie (threads)


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: scheme vraagje: is (accumulate cons nil sequence) zinvol?


On Thu, Sep 09, 2004 at 09:41:36AM +0200, Jan Nieuwenhuizen wrote:
> Lionel Elie Mamane writes:

>>     write (lambda (x) (accumulate cons nil x)) . This
>>     non-curryfication is IMHO one of the most irritating "features" of
>>     Lispy languages.

> I'm not familiar with caml like languages, could you explain what it
> is you find irritating?

Yeah, sure.

1) (One of) the point(s) in using functional languages (for me) is
   that one can pass around functional values just as "normal"
   values. Write higher-level functions, combinators, that abstract
   powerful programming constructs and patterns and make them easy to
   use, while typing few characters.

   Joost has shown a few of these "classical" combinators in his
   "scheme intro".

2) Brevity (taken reasonably) is a positive feature of a language.


The feature I'm talking about is the syntax that if f is a function
that takes n arguments, then (f a) is a function that takes (n-1)
arguments and behaves as
 (lambda (x_0 ... x_{n-2}) (f a x_0 ... x_{n-2}))
. Mathematically, this makes use of the natural isomorphism between
A^(B*C) (the functions that take two arguments, the first in B, the
second in C, returning something in A) and (A^C)^B (the functions that
take an argument in B and return something in A^C, namely a function
that takes something in C and returns something in A).

Seen from this point of view (the "curryfied" point of view), writing
(lambda (x) (f a x)) is actually "just" an unnecessary complicated
equivalent of (f a). Just like (lambda (x) (f x)) is ... just f,
(lambda (x) (f a x)) is just (f a). (This is called eta-reduction, by
the way.)


Let's look at an example: let's suppose I want to increment every
element of the list l. Without curryfication, I have to write
something like

  (map (lambda (x) (+ 1 x)) l)

with curryfication, I would write:

  (map (+ 1) l)

which is much shorter and much more readable. Here you see that
actually, curryfication conflicts with a feature of Lispy languages:
variable number of arguments. The thing that lets you write (+), (+
1), (+ 1 2) or (+ 1 2 3 4) and these all have an (integer) value,
while in ML (+) is a function (of two arguments), (+ 1) is a function
of one argument, (+ 1 2) is an integer and (+ 1 2 3 4) is not
correct: It is the same as (3 3 4), i.e. using an integer as a
function.


Now, I want to increment every element of an element in a list of
lists:

 (map (lambda (x) (map (lambda (x) (+ 1 x)) x)) l)

vs

 (map (map (+ 1 x)) l)


For a list of lists of integers, compute the sums of the half of the
elements (where +3 is the function that takes three arguments and
returns their sum):

 (map (lambda (x) (fold_left (lambda (x y) (+3 x y)) x)) l)

vs

 (map (fold_left (+3 2) 0) l)



This "partial application" of functions to create new functions is
actually very common (at least, I tend to make use of it a lot). A lot
of "small" functions one wants are an already existing function, with
some of its arguments already chosen/bound.

Am I making sense now?

<<inline: signature.asc>>


Follow-ups:

Gerelateerd:


[ Date Index] [ Thread Index]