Good introduction to functional programming with Python? 
Author Message
 Good introduction to functional programming with Python?

Can someone recommend a decent introduction to functional programming in
Python? I haven't found any suitable intro, and I'd like to learn more
about map(), apply(), lambda, and the like. I understand the syntax, but
I'd like to learn something of the functional programming context these
commands come from.

Thanks in advance.

Rick



Tue, 10 Jun 2003 12:49:27 GMT  
 Good introduction to functional programming with Python?
[Richard P. Muller]

Quote:
> Can someone recommend a decent introduction to functional programming
> in Python?

I doubt it, but if you want to learn FP I strongly recommend checking out
the freely available Haskell material:

    http://www.haskell.org/

Quote:
> I haven't found any suitable intro, and I'd like to learn more
> about map(), apply(), lambda, and the like.

Haskell will teach you that.  You can come back and apply what you learned
in python then -- although some people will cluck at you <wink>.

Quote:
> I understand the syntax, but I'd like to learn something of
> the functional programming context these commands come from.

If you want to learn French, don't go to Manchester.  Functional programming
features are not central to Python -- its support for them is spotty, clumsy
and unlikely to get fancier.  Learn FP in a context where it's natural!  And
Haskell is the most Pythonic of all languages that have nothing in common
with Python.

like-two-halves-of-a-single-twisted-soul-ly y'rs  - tim



Tue, 10 Jun 2003 14:05:46 GMT  
 Good introduction to functional programming with Python?

Quote:
> [Richard P. Muller]
> > Can someone recommend a decent introduction to functional programming
> > in Python?

> I doubt it, but if you want to learn FP I strongly recommend checking out
> the freely available Haskell material:

>     http://www.*-*-*.com/

http://www.*-*-*.com/
for better support for some Haskell-like functional programming in
Python, including the key Haskell semantic idea, lazy evaluation.

Haskell is my favourite FP language, and it does have some nice
surface similarities with Python (use of whitespace, the list
comprehension idea), but it differs deeply from Python in two
key issues (which are NOT really central to FP...):

    a. lazy evaluation is always the default semantics
    b. very strict (and elegant) static typing

Python evaluates eagerly by default (like almost all languages!),
and its typing is always dynamic.

If one wants to broaden one's mind, looking at the world from a
very different angle than Python's, then Haskell makes a LOT of
sense.  A 'triangulation' is best done by choosing two 'base
points' that are not TOO close to each other, and nobody would
accuse Haskell and Python of being too close, given [a] & [b].

Incidentally, while haskell.org is a great site, I would strongly
suggest that books are by far the best way to learn Haskell.

Hudak's "Haskell School of Expression" (Cambridge University Press)
may well wow you if you're into multimedia & such; Thompson's more
traditional "Craft of Functional Programming" 2nd ed (Addison
Wesley) is workmanlike, thorough, and clear.  From there you
can move on to Fethi's and Lapalme's "Algorithms: a Functional
Programming Approach" (Addison-Wesley) and Okasaki's "Purely
Functional Data Structures", and finally HAVE a good grasp of
FP the Haskell way (Okasaki's work actually focuses on ML, with
Haskell equivalents in an appendix, so you'll be getting a small
apercu of non-lazy FP thrown in for free:-).

On the other hand, if one's focus is on understanding how best
to apply FP *in a Python setting*, this FP curriculum may prove
too round-about -- the conceptual detours through static typing
and "laziness as a way of life", in particular, are surely
scenic and mind-broadening, but not specifically relevant.  There
are faster and more direct ways...

Quote:
> > I haven't found any suitable intro, and I'd like to learn more
> > about map(), apply(), lambda, and the like.

> Haskell will teach you that.  You can come back and apply what you learned
> in Python then -- although some people will cluck at you <wink>.

> > I understand the syntax, but I'd like to learn something of
> > the functional programming context these commands come from.

> If you want to learn French, don't go to Manchester.  Functional
programming
> features are not central to Python -- its support for them is spotty,
clumsy
> and unlikely to get fancier.  Learn FP in a context where it's natural!
And
> Haskell is the most Pythonic of all languages that have nothing in common
> with Python.

There must indeed be some Pythonic 'aura' to Haskell, I guess, given
the somewhat surprising correlation between liking Haskell and liking
Python among people who've tried both.  But points [a] and [b] above
are BIG technical differences, and not centrally relevant to FP.

There ARE functional programming languages with dynamic typing AND
eager (strict) evaluation models like Python.  A 'pure' FP with these
characters is up-and-coming Erlang -- but I would not necessarily
suggest it here, because its central semantic concern is with issues
of parallelism and concurrency, which have relatively little to do
with the issue.  A NON-pure language one SHOULD consider for its
didactical strength is Scheme.  Abelson's and Sussman's "Structure
and Interpretation of Computer Programs" will teach one Scheme in
a strongly FP-oriented setting, and it's a great book on its own --
I consider SICP as one of the main conceptual motivation to learn
a little Scheme, just as Kernighan and Pike's "The Practice of
Programming" is motivation enough to learn some C, or Fowler's
"Refactoring" motivates one to pick up 'just enough Java to get by'.

Scheme's syntax will feel pretty alien, what with all the darned
parentheses, but, with Abelson and Sussman at hand, one soon
gets past that and focuses on really deep and fascinating concerns.

http://www.*-*-*.com/
and very good implementation, with all the t{*filter*}s and a lot
of equally-free didactical support, good for any Win32 box, Mac,
or Unixoid.  (Not that Haskell's and Erlang's implementations
are any less free, cross-platform, and good-quality, but, IMHO,
Rice's Scheme has characteristics that make it even better).

Alex



Tue, 10 Jun 2003 16:50:56 GMT  
 Good introduction to functional programming with Python?

Quote:
> There must indeed be some Pythonic 'aura' to Haskell, I guess,
> given the somewhat surprising correlation between liking Haskell
> and liking Python among people who've tried both.

Indeed. I am very surprised how often Haskell is mentioned on the
Python's list, given quite different paradigms of these languages.

Elegance of design of a language? Significant layout? :-)

I am making a library for embedding the CPython interpreter in Haskell
programs (Glasgow Haskell only), to be prepared if I ever need to
make a scriptable program.

Handling basic Python objects already works. Includign conversion of
Haskell functions to Python bound method objects, with "self" being
a CObject, whose finalizer frees the dynamically created C function
pointer and thus removes implicit references to free variables of
the original function closure... Exceptions from either language
are going to be propagated through both languages, with appropriate
wrapping and unwrapping. Unfortunately data structures with cycles
across languages will not be freed.

--

 \__/
  ^^                      SYGNATURA ZASTPCZA
QRCZAK



Wed, 11 Jun 2003 04:28:30 GMT  
 Good introduction to functional programming with Python?
[Alex Martelli]

Quote:
> There must indeed be some Pythonic 'aura' to Haskell, I guess,
> given the somewhat surprising correlation between liking Haskell
> and liking Python among people who've tried both.

[Marcin 'Qrczak'  Kowalczyk]

Quote:
> Indeed. I am very surprised how often Haskell is mentioned on the
> Python's list, given quite different paradigms of these languages.

> Elegance of design of a language? Significant layout? :-)

My vote:  both languages place extreme emphasis on being *readable*.  Listen
to a Scheme True Believer ragging on a Haskeller for all the "unnecessary"
syntactic sugar in Haskell, then go back in the c.l.py archives and watch
the same folks ragging on Python for the same thing. Languages' detractors
often stumble into key similarities years before the supporters figure it
out <wink>.

prophecy-is-remembering-the-past-ly y'rs  - tim



Wed, 11 Jun 2003 10:37:22 GMT  
 Good introduction to functional programming with Python?
[Alex Maretlli]

Quote:
> Haskell is my favourite FP language, and it does have some nice
> surface similarities with Python (use of whitespace, the list
> comprehension idea), but it differs deeply from Python in two
> key issues (which are NOT really central to FP...):

>     a. lazy evaluation is always the default semantics
>     b. very strict (and elegant) static typing

> Python evaluates eagerly by default (like almost all languages!),
> and its typing is always dynamic.

> If one wants to broaden one's mind, looking at the world from a
> very different angle than Python's, then Haskell makes a LOT of
> sense.  A 'triangulation' is best done by choosing two 'base
> points' that are not TOO close to each other, and nobody would
> accuse Haskell and Python of being too close, given [a] & [b].

I agree it depends on what the original questioner wants to get out of this.
That I don't know.  Haskell is a pure functional language with a wealth of
supporting material and easy-to-get, easy-to-use free ports, so it's a good
choice if FP is really what he wants.

If it is, then if FP is "about" anything, it's about the art of using
higher-order functions, and I believe mere mortals *need* a strong static
typing system to keep those straight.  Maps returning maps returning maps
... can get hard to follow real fast.

And I think anyone setting out to learn FP without a lazy language is
cheating themself out of a world of beauty:  learning to sling unbounded
streams in a *natural* setting is simply a joy.

If the guy just wants to putz around, though, I'd steer him to Scheme
<wink>.

Quote:
> Incidentally, while haskell.org is a great site, I would strongly
> suggest that books are by far the best way to learn Haskell.

I imagine that depends too on what he wants out of this.  He should start
with the "Gentle Introduction to Haskell" at

    http://www.*-*-*.com/

and take it from there.

Quote:
> Hudak's "Haskell School of Expression" (Cambridge University Press)
> may well wow you if you're into multimedia & such; Thompson's more
> traditional "Craft of Functional Programming" 2nd ed (Addison
> Wesley) is workmanlike, thorough, and clear.

The last is what I recommend to most people:  not too abstract, and very
careful to explicitly declare the types of all identifiers <wink>.

Quote:
> ...
> On the other hand, if one's focus is on understanding how best
> to apply FP *in a Python setting*, his FP curriculum may prove
> too round-about -- ...

FP features in Python were never intended to be more than a minor
convenience, and by all signs will never become more than that.  So I steer
him away from that.  Don't forget that the strongest argument in favor of
listcomps (in Guido's eyes) was that they gave a path to eventually throwing
"map" and "filter" away!

Quote:
> ...
> A NON-pure language one SHOULD consider for its didactical strength
> is Scheme.

Indeed closer to Python in many ways than is Haskell.

Quote:
> Abelson's and Sussman's "Structure and Interpretation of Computer
> Programs" will teach one Scheme in a strongly FP-oriented setting,
> and it's a great book on its own -- ...

Yup!  Pne of the few true programming classics.

Quote:
> http://www.*-*-*.com/
> and very good implementation, with all the t{*filter*}s and a lot
> of equally-free didactical support, good for any Win32 box, Mac,
> or Unixoid.  (Not that Haskell's and Erlang's implementations
> are any less free, cross-platform, and good-quality, but, IMHO,
> Rice's Scheme has characteristics that make it even better).

A caution that this depends on how powerful his computer is:  DrScheme is
too much a resource hog for a satisfying experience on older Windows boxes
(voice of experience).  This is a bit ironic, since Scheme is ported at
least as often as Python to tiny platforms.  You pay through the nose for
"all the t{*filter*}s" that come with DrScheme.  Worth it if you can afford it!
Else he can pick up implementations than run fine even on palmtops; e.g.,
from the links at (sorry, but my mailer will break this line):

http://www.*-*-*.com/
ons/

betting-he's-got-more-advice-than-he-can-use-now-ly y'rs  - tim



Wed, 11 Jun 2003 14:45:59 GMT  
 Good introduction to functional programming with Python?

Quote:
> Can someone recommend a decent introduction to functional programming in
> Python? I haven't found any suitable intro, and I'd like to learn more
> about map(), apply(), lambda, and the like. I understand the syntax, but
> I'd like to learn something of the functional programming context these
> commands come from.

Like wise,  I am trying to get my head around OOP, but all I can find
are basic howto make a class in C++

I understand how to make classes in both Python and C++.  What I want is
help in deciding waht would be a good class and what would not,
preferably in a pythjon contxt, but a generic context would be wonderful
as well.

Hope you can help.  

thanks

--

  Rob Brown-Bayliss
 ---======o======---
  www.ZOOstation.cc



Thu, 12 Jun 2003 02:13:49 GMT  
 Good introduction to functional programming with Python?

    [snip]
We agree on far too much, and dwelling on agreements ain't no
fun, so, let's pick on a difference:

Quote:
> If it is, then if FP is "about" anything, it's about the art of using
> higher-order functions, and I believe mere mortals *need* a strong static
> typing system to keep those straight.  Maps returning maps returning maps
> ... can get hard to follow real fast.

Erlang designers and practitioners seem to disagree: and Erlang is arguably
the FP around which most $$$ turn in today's real-world, what with its use
in Ericsson and Bluetail's acquisition by a Nortel subsidiary.  I have no
real
experience with it, and thus no solid basis on which to judge it, but,
sordid
materialist that I am, I _am_ impressed when hundreds of megabucks are
in play:-).  And Erlang relies on strong dynamic (aka latent) typing, and an
emphasis on concurrency in an FP setting, to (allegedly) reach good levels
of reliability, performance, ease of learning, programmer productivity.

Static typing has its place, but so, it appears, does latent typing, even in
FP.

Quote:
> > or Unixoid.  (Not that Haskell's and Erlang's implementations
> > are any less free, cross-platform, and good-quality, but, IMHO,
> > Rice's Scheme has characteristics that make it even better).

> A caution that this depends on how powerful his computer is:  DrScheme is
> too much a resource hog for a satisfying experience on older Windows boxes
> (voice of experience).  This is a bit ironic, since Scheme is ported at
> least as often as Python to tiny platforms.  You pay through the nose for
> "all the t{*filter*}s" that come with DrScheme.  Worth it if you can afford

it!

Thanks for the warning!  The oldest machine on which I had tried Rice
Scheme's had a Pentium-133 and 32M RAM, and they seemed to run fine
there -- with older boxes yet, a smaller implementation is no doubt better!

Alex



Wed, 11 Jun 2003 16:17:49 GMT  
 Good introduction to functional programming with Python?

Quote:

> Like wise,  I am trying to get my head around OOP, but all I can find
> are basic howto make a class in C++

> I understand how to make classes in both Python and C++.  What I want is
> help in deciding waht would be a good class and what would not,
> preferably in a pythjon contxt, but a generic context would be wonderful
> as well.

To some extent, only experience can really help you in deciding what
would be a good class and what not. And as they say: true judgement
comes from experience; experience comes from poor judgement. There's no
cookbook for OOP, no 10 golden rules that you can blindly follow.
Still, there's a lot of material out there with the experience of other
people. And if I would have to recommend just one, I'd suggest you try
"Object Oriented Software Construction" by Bertrand Meyer, Prentice
Hall, ISBN 0-13-629155-4. It doesn't once mention Python, but when it
comes to OO, it is, in my oppinion, one of the better books out there.

Regards,
Jan



Thu, 12 Jun 2003 20:05:20 GMT  
 Good introduction to functional programming with Python?

Quote:

> > Can someone recommend a decent introduction to functional programming in
    [snip]
> Like wise,  I am trying to get my head around OOP, but all I can find
> are basic howto make a class in C++

OOP is _much_ more 'central' to Python than FP; thus, a good grasp
of it is proportionally more important.  'Howto' is easy, but you're
right in implying it's not as important as 'using it WELL'.

Quote:
> I understand how to make classes in both Python and C++.  What I want is

Good; so, the easy part is out of the way.

Quote:
> help in deciding waht would be a good class and what would not,
> preferably in a pythjon contxt, but a generic context would be wonderful

It can help to think of classes as coming in *two* kinds: one models
directly a type of 'objects' that you have identified while thinking about
the domain for which you want to provide solutions ('domain analysis');
the other one is a 'purely utilitarian' device, which just takes advantage
of some OO language mechanism.

The split is not as sharp as this would seem to imply, but this way of
presenting it may still help.  We could call the former kind 'semantic'
or 'problem-space' classes/objects, and the latter 'utility' or 'solution-
space' ones (many classes in real-world programs exhibit both aspects:
_some_ semantic correspondence to domain analysis, _some_ aspects
that are 'purely utilitarian').

Don't think of 'semantic' classes as 'good', and 'utility' ones as 'bad':
they're _both_ 'good' if, and only if, they help you solve your problems
with clarity and ease!  These are general programming issues, only
tangentially related to classes, but well worth emphasizing...:

    Semantic classes will be 'good' if they model those aspects of your
    problem-domain which you need to handle, to the level of detail and
    'faithfulness' which *you actually need* -- a model/program is always
    a _simplification and abstraction_ of the world (the map is not the
    territory)... eschew 'too-close' modeling for its own sake!

    Utility classes will be 'good' if they come in handy, with just the
right
    amount of 'mechanism' for your actual needs.  *Do the simplest thing
    that can possibly work*, in each case -- ready to 're-factor' things as
    the program evolves, often in an 'exploratory' way, to keep simplicity
    and elegance as you converge towards solutions.

    Don't put in extra complexity 'just in case', because *you ain't gonna
    need it* often enough that the effort won't pay for itself.  (Unless
    you are releasing a _framework_, or at least a module/library for
    general use, rather than a specific program; in this case, balancing
    generality, flexibility/reusability, and simplicity, can be even more
    of a design challenge:-).

And coming to classes (remember classes? it's a post about classes)...
it's hard to do them justice within the confines of one post, but, let me
start with some general considerations, and an example to clarify.

Classes let you *group*, "under one roof" so to speak, aspects of
_state_ ("data") and/or aspects of _behavior_ ("code").  In any given
case, unless you have some interest in effecting such a grouping, it's
quite unlikely that a class is the best approach for you in that case;
if you do have such interest, a class is likely to be 'right' -- unless
some other type of object (an already existing one, which you can
find in the Python library or some other available module/package)
meets some specific needs even better.

A simple case is when you just want to group some data items and
give each of them a name -- no specific 'behavior', just some state
with associate naming.  Tuples and lists let you do the grouping,
but the 'names' of the several items are just numeric indices -- often,
this is not the clearest, most readable approach.  Dictionaries would
let you 'name' items by supplying string keys -- the syntax is not
ideal if constant-strings are all you're using as names.  A class with
no behavior (methods) can easily be the best, simples approach here.

For example, suppose our program will need to model CD's.  A CD
object has several attributes -- depending on our purposes, we may
want to model some appropriate subset of them; for example, a
"title", a "price" in Euros, and a sequence of "tracks" (each of which
has its own attributes, say a "title" and a "duration" in seconds).

If we used tuples or lists, we might conventionally agree that the
first item is the title, the second one the price, the third one the
sequence of tracks (each with two items, title then duration).

For example, a Czech CD I bought this summer could be modeled
according to these conventions as (truncating the list of tracks!):
acd = ["Hity Papa Offenbacha", 5.00,
    [["Barkarola", 264], ["Piscu Heleny", 95], ["Pariduv Soud", 247]]]
or similarly with tuples instead of lists.  The problem with this is
that any given task, such as, say, "find the title of the longest
track", becomes not-very-readable and hardly-maintainable...:

def titleLongest(acd):
    tracks = acd[2]
    longest = 0
    for i in range(1,len(tracks)):
        if tracks[i][1] > tracks[longest][1]:
            longest = i
    return tracks[longest][0]

All of those '[2]', '[1]', '[0]' should feel unnerving -- strong hints
that our chosen representation is sub-optimal; and further, our
functions become *strongly* coupled to the physical way we've
chosen to lay out our data!  If we refactor the data representation,
we'll have LOTS of work ahead, redoing all of our functions -- what
an *unpleasant* prospect!

A dictionary may be a bit better...:

acd = {'title':"Hity Papa Offenbacha", 'price':5.00, 'tracks':
    [ {'title':"Barkarola", 'duration':264},
       {'title':"Piscu Heleny", 'duration':95},
       {'title':"Pariduv Soud", 'duration':247} ] }

The repetitiveness of the construction is unpleasant, but let's
see if the code using this representation is more readable...:

def titleLongest(acd):
    tracks = acd['tracks']
    longest = 0
    for i in range(1,len(tracks)):
        if tracks[i]['duration'] > tracks[longest]['duration']:
            longest = i
    return tracks[longest]['title']

Well, yes; at least, this code DOES suggest a little bit of what
we're doing.  But, could classes help...?

class CD:
    pass

class Track:
    pass

acd = CD()
acd.title = "Hity Papa Offenbacha"
acd.price = 5.00
acd.tracks = []

atrack = Track()
atrack.title = "Barkarola"
atrack.duration = 264
acd.tracks.append(atrack)

atrack = Track()
atrack.title = "Piscu Heleny"
atrack.duration = 95
acd.tracks.append(atrack)

atrack = Track()
atrack.title = "Pariduv Soud"
atrack.duration = 247
acd.tracks.append(atrack)

The construction is *quite* unpleasantly wordy.  But what about
the using-code?

def titleLongest(acd):
    tracks = acd.tracks
    longest = 0
    for i in range(1,len(tracks)):
        if tracks[i].duration > tracks[longest].duration
            longest = i
    return tracks[longest].title

Ah, yes, that's better... actually, thanks to the clarity afforded
by the named-attribute syntax, a sightly different approach
suggests itself:

def titleLongest(acd):
    longest = acd.tracks[0]
    for track in acd.tracks[1:]:
        if track.duration > longest.duration
            longest = track
    return longest.title

By looping on the tracks directly, rather than on an index to
them, we achieve a further worthwhile simplification.  It's true
that this approach *could* be taken even with the first of our
proposed representations, but...:

def titleLongest(acd):
    longest = acd[2][0]
    for track in acd[2][1:]:
        if track[1] > longest[1]
            longest = track
    return longest[0]

...the lack of names really kills us here!  This is hardly better
than the form we started out with, and _is_ rather opaque.

Pity about the wordy initialization code... anything we can do
about *that* one...?

Why, sure!  How do you like, for example:

acd = CD(title="Hity Papa Offenbacha", price=5.00, tracks=Tracks(
    ("Barkarola", 264), ("Piscu Heleny", 95), ("Pariduv Soud", 247) ))

Doesn't this look *just right* -- even better than the first attempt,
which had no naming at all, or the second one, which had names
all over the place, because we have names *right where we want to*...?

So how do we get this beauteous init'ing -- is it painful...?

Naah!  The CD class is too easy for words...:

class CD:
    def __init__(self, **kwds):
        for name,value in kwds.items():
             setattr(self,name,value)

Ain't it pretty?  The __init__ method is automatically called by
Python when we call the class object -- the first argument, which
we always name 'self', is the instance object we're building, then
come the others that were passed in the call to the class-object.

Here, we're using the '**somedictionary' notation to receive
whatever arguments were passed with named-form, and then
the handy idioms of 'iterate over dictionary keys/values' and
'set an object attribute' to smoothly, seamlessly translate them
into attributes of the CD object.

For the Tracks idea, as we don't *want* to make 'a sequence of
tracks' into a class-instance of its own (it's one of those cases
where an existing object type -- here, a list -- matches our needs,
so, let's not multiplicate entitites without necessity), we'll just
use a 'factory function' (fancy name for a function which builds
and returns a new object!-).

class Track:
    def __init__(self, title, duration):
        self.title = title
        self.duration = duration

def Tracks(*tracks):
    return [Track(title,duration) for title,duration in tracks]

The list-comprehension plucks and unpacks each 2-items tuple
from the sequence of arguments, and hands the results to the
Track classobject-call, which in turns uses them in __init__ to
initialize the ...

read more »



Fri, 13 Jun 2003 00:17:09 GMT  
 Good introduction to functional programming with Python?

Quote:

> For example, suppose our program will need to model CD's.  A CD
> object has several attributes -- depending on our purposes, we may
> want to model some appropriate subset of them; for example, a
> "title", a "price" in Euros, and a sequence of "tracks" (each of which
> has its own attributes, say a "title" and a "duration" in seconds).

That's good as far as it goes, but I think you missed the real power of
classes, which is subclassing.

What you really want to do is define a class AudioStorage.  It could be
essentially identical to your CD class, but you could then have
subclasses such as CD, Vinyl, DAT, DDT, mp3s_in_a_tar_file, etc.

The Vinyl sub-class, for examle, might want to keep track of which
tracks are on the A-side and which are on the B-side, and throw an
AudioStorage.offline exception when you try to call its play() method.  
It might also have an rpm attribute, which can take on the values 33,
45, or 78.

The mp3 class might return a URL for its location() method, and the CD
or Vinyl classes might return a string, "Third shelf from the bottom,
near the left end".



Fri, 13 Jun 2003 02:32:42 GMT  
 
 [ 29 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Erlang (was Re: Good introduction to functional programming with Python?)

2. functional.py 0.6 - Functional Programming in Python

3. functional.py 0.7 - Functional programming in Python

4. functional.py - functional programming in Python

5. functional.py 0.7 - Functional programming in Python

6. functional.py 0.6 - Functional Programming in Python

7. functional.py - functional programming in Python

8. Introduction to Socket Programming on Python

9. good niche for functional programming?

10. functional programming / good style

11. Good books for functional programming class

12. Good book for teaching Functional Programming & Lisp

 

 
Powered by phpBB® Forum Software