PDA

View Full Version : Accumulator generator


GnuVince
07-15-2002, 12:09 PM
http://www.paulgraham.com/accgen.html

Can you guys propose solutions in other languages? From what I can see, I can't do it in O'Caml.

kmj
07-15-2002, 12:13 PM
I wonder why the python version didn't use lambda...

jemfinch
07-15-2002, 01:22 PM
The Python version didn't use lambda because (stupidly) the original specification is that the variable has to be rebound to the new value. Python's nested scoping doesn't allow that.

The specification, by the way, is ignorant, and poor programming practice. It was created by a proponent of an imperative, dynamically typed programming to "confound" other languages that don't conform to exactly the same programming religion that Paul Graham espouses.

(All those who are now thinking, "But Lisp is a functional programming language!" stop. Lisp isn't anywhere near a functional programming language. Everything is mutable, and the fact that one of the most outspoken Lisp advocates thinks the function he proposes is useful is indicative of that.)

Anyway, GnuVince, here's the closest you can get to his specification, modulo a few errors in the libraries (I don't feel like looking anything up)


let foo n i = foo := Num.(+) foo i


If you wanted to do it with integers (instead of "number", another unclear and pointless term in the specification) it would look much simpler:


let foo n i = n := (n + i)


Every function in O'Caml is curried. You don't have to bother with even creating a new function via lambda or anything else, you only have to partially apply the function.

Paul Graham's a smart guy, but he's hopelessly blinded by his attachment to Lisp.

Jeremy

vomjom
07-15-2002, 01:25 PM
Originally posted by GnuVince
http://www.paulgraham.com/accgen.html

Can you guys propose solutions in other languages? From what I can see, I can't do it in O'Caml.
Well, I'm just learning O'Caml, but... of course you can do it in O'Caml


# let foo n i = n + i;;
val foo : int -> int -> int = <fun>
# let bar = foo 10;;
val bar : int -> int = <fun>
# bar 22;;
- : int = 32


In fact, I think O'Caml has the least amount of characters for that code (about the same as goo *wink*).

GnuVince
07-15-2002, 01:34 PM
vomjom: in the specifications, you are supposed to accept a number, not an integer. But jemfinch is right, Paul Graham is the biggest language bitch I've seen in a while :) But nonetheless, I like his articles.

Vince

P.S: Thanks for the Num example Jeremy.

vomjom
07-15-2002, 01:46 PM
Originally posted by jemfinch
The Python version didn't use lambda because (stupidly) the original specification is that the variable has to be rebound to the new value. Python's nested scoping doesn't allow that.

The specification, by the way, is ignorant, and poor programming practice. It was created by a proponent of an imperative, dynamically typed programming to "confound" other languages that don't conform to exactly the same programming religion that Paul Graham espouses.
Are you talking about Paul Graham? He's a proponent of _functional_, dynamically typed programming.

(All those who are now thinking, "But Lisp is a functional programming language!" stop. Lisp isn't anywhere near a functional programming language. Everything is mutable, and the fact that one of the most outspoken Lisp advocates thinks the function he proposes is useful is indicative of that.)

Sure it is a functional programming language. Common Lisp functions often mutate their input for performance reasons, but, for these functions, you _still_ are supposed to take the result of the evaluation for assignment. The input will not necessarily transform into the intended output. Programming with that assumption will lead to errors in your code. It thus programs like a functional language.

And yes, the function he proposes _is_ useful. The reason it may not be useful to _you_ is because you probably don't think in that style of programming. In fact, it is _so_ useful that O'Caml returns a function that does what he proposes when you don't give all the arguments.

jemfinch
07-16-2002, 12:05 AM
Originally posted by vomjom
Are you talking about Paul Graham? He's a proponent of _functional_, dynamically typed programming.


No, he's a proponent of Lisp.


Sure it is a functional programming language. Common Lisp functions often mutate their input for performance reasons, but, for these functions, you _still_ are supposed to take the result of the evaluation for assignment. The input will not necessarily transform into the intended output. Programming with that assumption will lead to errors in your code. It thus programs like a functional language.


Oh, you mean some functions transform their input and some don't, just like any other imperative language in existence?

Variables can be rebound. Pointers (list conses) can be reassigned. No basic data structure is immutable by nature. Lisp is not a functional language. Haskell is functional. SML is functional. O'Caml is functional. Mercury is functional. Clean is functional. Lisp isn't functional. Functional data structures in Lisp are the exception, not the rule.

Show me an example of a Lisp function that "mutates its input for performance reasons," and I'll show you a function that's been prematurely optimized. But feel free to show me such a function.

(And try to show me a full-fledged Lisp implementation that's significantly faster than O'Caml for non-trivial tasks given all its imperative "features")


And yes, the function he proposes _is_ useful. The reason it may not be useful to _you_ is because you probably don't think in that style of programming. In fact, it is _so_ useful that O'Caml returns a function that does what he proposes when you don't give all the arguments.

No, you're basing this on a misinterpretation of both the specification and O'Caml. The specification insists that the variable be rebound. O'Caml doesn't allow rebinding of variables. The closest O'Caml gets is references, which is what the example I posted uses.

Currying is useful. But his specification doesn't just insist on currying.

Second, the function is unsafe, non-functional, and serves no real purpose that a pure function couldn't serve just as easily. Show me a situation in which you think a pure function wouldn't serve just as well.

If I don't think in the style of programming that considers such a function useful, I consider that a blessing.

I'm in an argumentative mood right now :)

Jeremy

jemfinch
07-16-2002, 12:07 AM
Originally posted by vomjom

Well, I'm just learning O'Caml, but... of course you can do it in O'Caml


# let foo n i = n + i;;
val foo : int -> int -> int = <fun>
# let bar = foo 10;;
val bar : int -> int = <fun>
# bar 22;;
- : int = 32


In fact, I think O'Caml has the least amount of characters for that code (about the same as goo *wink*).

If this was a solution (it isn't) you could reduce the number of characters even further:


let foo = (+)


:)

Jeremy

Bradmont
07-16-2002, 04:42 AM
I do believe I've just done one in C++, kick me in the brain if I totally misinterpreted the point...

(I've included a whole program to demonstrate its usage)

#include <iostream>
using namespace std;

typedef int & (*accumulator) (int , int * n = NULL) ;

int & accumulatorTemplate(int i, int * n = NULL){
// the idea here is that this function is only ever called with a
// second argument by generateAccumulator. If it is called with
// n != NULL (I did it with a pointer so any int value could be used
// for n), then that value is stored to be the n for the accumulator.
// otherwise, increment storedN by i, and return storedN.
static int storedN;
if (n != NULL) {
storedN = *n;
return storedN;
} else {
storedN += i;
return storedN;
}
}

accumulator generateAccumulator(int n){ // this returns our accumulator
accumulatorTemplate(0, &n);
return accumulatorTemplate;
}

int main(){
accumulator acc = generateAccumulator(5);
cout << acc(5) << endl ;
cout << acc(6) << endl ;
cout << acc(7) << endl;
}


I suppose you could also do it with a functor, I suppose it would actually be better that way, but m'eh. :p

file13
07-18-2002, 12:06 PM
Originally posted by jemfinch

(All those who are now thinking, "But Lisp is a functional programming language!" stop. Lisp isn't anywhere near a functional programming language. Everything is mutable, and the fact that one of the most outspoken Lisp advocates thinks the function he proposes is useful is indicative of that.)


i think you're missing the point. Lisp is procedural when you it to be, functional when you want it to be, oop when you want it to be, access oriented when you want it to be.... Lisp's power is it's flexibility. it's just as as to use loop as it is labels. of course the accumlator generator may not be useful, but it shows how flexible Lisp is. it allows you to think in the paradigm you choice/like the most.

you can achieve the same effect in any language, but it's the way you can achieve that effect in Lisp is what makes it so flexible. to quote Graham from On Lisp:


In principle, of course, any Turing-equivalent programming language can do
the same things as any other. But that kind of power is not what programming
languages are about. In principle, anything you can do with a programming
language you can do with a Turing machine; in practice, programming a Turing
machine is not worth the trouble.

So when I say that this book is about how to do things that are impossible
in other languages, I don’t mean “impossible” in the mathematical sense, but in
the sense that matters for programming languages. That is, if you had to write
some of the programs in this book in C, you might as well do it by writing a Lisp
compiler in C first. Embedding Prolog in C, for example—can you imagine the
amount of work that would take? Chapter 24 shows how to do it in 180 lines of
Lisp.


http://www.paulgraham.com/onlisp.html

:)

jemfinch
07-18-2002, 12:54 PM
Originally posted by file13
i think you're missing the point.


You're missing the point. I'm not talking about Lisp's flexibility. I'm talking about calling it a "functional programming language." It supports several functional programming idioms, but, like Python, it's not a functional programming language. It does too many things non-functionally.

Jeremy

file13
07-18-2002, 01:18 PM
you're the only one who said it was functional.... ;)