lilypond-devel
[Top][All Lists]
Advanced

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

Re: reading material?


From: Julian Squires
Subject: Re: reading material?
Date: Mon, 22 Mar 2004 14:41:44 -0500
User-agent: Mutt/1.4.1i

On Mon, Mar 22, 2004 at 12:51:12PM -0600, Douglas A Linhardt wrote:
> Agreed.  We're off target.  And I'm not trying to start a flame war.
> I really don't want to start an argument.  I just want to I promise
> not to post any more to this thread (unless, of course I change my
> mind ;) ).

Please don't take any of my comments on this as being flames in any way,
either.  But I can't resist a good language debate.

> > First-class means first-class citizens, that is, objects of that type
> > can be used in all language constructs just like other objects.  For
> > example, a function that returns a function in Scheme is natural,
> > 
> >  (define (iterate func k)
> >    "Produce the function x -> FUNC(FUNC .. (x) .. ) "
> >    (if (> k 0)
> >        (lambda (x) (func ((iterate func (1- k)) x)))
> >        (lambda (x) x)))
> > 
> >  (define to-6th-power (iterate sqr 3))

...

> The C++ solution is both natural and elegant.  Two example solutions
> follow, the first not using templates, the second using templates.  By
> the way, my favorite reference for using the Standard Template
> library, as well as things like these functor classes, is Nicolai M.
> Josuttis, "The C++ Standard Library", 1999.

Frankly, I would suggest that after studying some of these languages
more, particularly ocaml, haskell, and common lisp, you might have a
different attitude.

What you did idiomatically in 34 lines, he did idiomatically in 7 lines,
counting whitespace and comments.  Also, his version has no problems if
the function takes a string instead of an int, for example.  And, if it
were written in ocaml, like so:

let rec iterate f k =
    if k == 0 then fun x -> x
    else iterate (fun x -> f x) (k - 1)
    ;;

let sqr x = x * x;;
let laugh x = x ^ "ha";;

Then one can do:

let pow_8 = iterate sqr 3;;
let guffaw = iterate laugh 5;;

Printf.printf "%d %s\n" (pow_8 2) (guffaw "bwa");;

and yet, (guffaw 2) or (pow_8 "bwa") will be detected as an error at
compile time, not run-time.

Now imagine you'd like to iterate (really, composite) functions with
various type signatures.  Or partially apply a function, like:

let nonsense prefix suffix = prefix ^ "bar" ^ suffix;;
let n = nonsense "foo";;

Printf.printf "%s\n" (n "baz");;

These are just a few things among many that are much more arduous to do
in C++, certainly more lengthy, when one's time is better spent on
better tasks than housekeeping.

[Let's hope all that code is correct, I haven't checked it carefully...
hopefully you get the point. ;-)]

Arguments like these can go on forever, but truly, (and I feel sad for
saying this, as I'll explain momentarily,) I recommend some of Paul
Graham's essays:
    http://www.paulgraham.com/avg.html
or    
    http://www.paulgraham.com/icad.html

I give the caveat that when I came across the first, I was highly
skeptical, and though I still don't agree entirely with what Graham is
saying, it wasn't until I spent a while writing some serious code in a
few languages more expressive than C++ that I finally conceded that he
has a point.

I still have to write a lot of C++ at work, but at least now I know
better than to propose it when I have the choice.

Cheers.

-- 
Julian Squires




reply via email to

[Prev in Thread] Current Thread [Next in Thread]