[Edu-sig] more re scheme.py

Kirby Urner pdx4d@teleport.com
Sun, 08 Oct 2000 19:46:13 -0700


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