
In a previous post I wrote:
For example, you can define car and cdr of LISP fame:
def car(mylist): if len(mylist)==0: return [] else: return mylist[0]
def cdr(mylist): if len(mylist)==0: return [] else: return mylist[1:]
That's clearly not quite right. Here's car and cdr in action in DrScheme: Welcome to DrScheme, version 101. Language: Textual Full Scheme (MzScheme).
(car '()) car: expects argument of type <pair>; given () (car '(1)) 1 (cdr '(1)) ()
In other words, the car of an empty list is undefined. The car of a 1-member list is that member. The cdr of a 1 member list is the empty list (provided it's a proper list of cons pairs -- but that's another story). So... def car(mylist): return mylist[0] # first member def cdr(mylist): if len(mylist)==1: return [] # returns empty list else: return mylist[1:] # else, rest of list
car((1,)) 1 cdr((1,)) []
You get error messages if your argument to either is an empty list. Then: def Reduce(operator,mylist): if len(mylist)==1: return car(mylist) else: return apply(operator, ( car(mylist), Reduce(operator,cdr(mylist)) ) ) Usage:
Reduce(operator.mul,range(1,11)) 3628800 1*2*3*4*5*6*7*8*9*10 3628800
I'm not saying we should customarily program this way, simply that it's possible to communicate some of the flavor of Scheme by bringing analogous features of Python into the foreground. One could go on to define caaaar, cddddr, cdadar, cdar, cadadr -- the whole set of weird (unpronouncable) words for doing "slice arithemetic". http://www.cs.washington.edu/education/courses/341/99su/lectures/scheme/img0 28.GIF shows ([lambda (x y)(+ (* 2 x) y)] 4 5) evaluating to 13. In DrScheme:
([lambda (x y)(+ (* 2 x) y)] 4 5) 13
In Python:
apply(lambda x,y: 2*x + y, (4,5)) 13
Like in Scheme, in Python you can bind the lambda part to a name:
f = lambda x,y: 2*x + y f(4,5) 13
Alternatively:
def f(x,y): return apply(lambda x,y: 2*x + y,(x,y))
f(4,5) 13
Which is just a rather long-winded way of just saying:
def f(x,y): return 2*x + y
http://www.cs.washington.edu/education/courses/341/99su/lectures/scheme/img0 68.GIF shows a "procedure factory": We go
(filter [lambda (x) (>= x 0)] '(-2 -3 -1 3 1 4)) (3 1 4)
i.e. returns x's >= 0 -- this doesn't seem to work in DrScheme (apparently filter is not a primitive).
(filter [lambda (x) (>= x 2)] '(-2 -3 -1 3 1 4)) (3 4)
returns x's >= 2 So we'd like to define a function which creates other functions with n being whatever number we have to be greater than. In Scheme, that looks like: (define (greater-than-n?? n) (lambda (x) (>= x n))) Then you can say: (define greater-than-2 (greater-than-n?? 2)) ^^^^^^^^^^^^^^^^^^^^ returns a pointer to a procedure and get a procedure, i.e.
((greater-than-2) '(-2 -3 -1 3 1 4)) (3 4)
In Python:
def gt_n(n): return eval('lambda x: x>%s' % n)
gt_2 = gt_n(2) ^^^^^^ returns a pointer to a procedure
gt_2(-1) 0 gt_2(3) 1 filter(gt_2,[-3, -2, 1, 3, 1, 4]) [3, 4]
Thanks to Jeff Cogswell for teaching me the above. Thanks to Greg Badros's lecture notes re Scheme at http://www.cs.washington.edu/education/courses/341/99su/lectures/scheme/ for slide GIFs. Thanks to John Clements, Matthias Felleisen, Robby Findler, Cormac Flanagan, Matthew Flatt, Shriram Krishnamurthi, and Paul Steckler et al for the Dr. Scheme software. http://www.npr.org/ramfiles/wesun/19990404.wesun.07.ram to hear Paul Steckler play that Sunday game program on NPR. Also, listen to Matthias on http://www.cs.rice.edu/CS/PLT/Miscellaneous/matthias-kuhf.mp3 Kirby