[comp.lang.scheme] scheme for kids

doner@henri.ucsb.edu (John Doner) (10/30/90)

My 13 year old son, who spends lots of time with our computer, has
expressed an interest in learning to program.  I could start him with
BASIC, which I guess is the canonical thing, and which I probably will
eventually show him.  But as an experiment, I decided to show him a
little bit about scheme first, on the theory that this might give him
a better handle on various programming abstractions.  So now I have
a few questions with which I hope some of you can help me:

(1) Is there a scheme implementation for the Apple II?  That's what
they use at his junior high.  (We have a Mac SE/30 at home, running
MacScheme.)

(2) Are there some fun programs he could run, and perhaps modify?
Things that might interest a 13-year old.  Games, for example.

(3) MacScheme offers a minimal set of graphics primitives.  Is more
available?  What in the way of graphics can be done in a "generic"
fashion, i.e., runnable on any sort of dumb terminal?

Any help with these questions, or other suggestions, will be greatly
appreciated.

John E. Doner	       | "The beginner...should not be discouraged if...he
Mathematics, UCSB      | finds that he does not have the prerequisites for
Santa Barbara, CA 93106| reading the prerequisites."
doner@henri.ucsb.edu   |      --Paul Halmos, Measure Theory

gjc@mitech.COM (10/31/90)

All things considered (especially the age of the Apple-II and
the address space limitations) the best you can do as far as
programming languages would be LOGO. There are two versions available,
one from LCSI in Canada and one from Terripin (sp) in MA.

I am more familiar with the Terripin environment, having done a bit
of work in it around 1981, specifically the implementation of LOG, EXP,
and some other functions, in LOGO itself. 
The basic idea is that you get a dual-window environment,
an "echo" area at the bottom in which to type programs and commands
and a "graphics" area in which to view the turtle.
Editing a procedure pops up a special edit window.

There are at least two books of interest which use LOGO in some way.
One of them is called Turtle Geometry.

If you can find a reasonable C compiler then perhaps an implementation
of Scheme such as XSCHEME or SIOD would fit into the 64kbyte address
space. But since you would have to add at least some graphics primitives
to make it interesting you may very well run out of room without
putting a huge amount of work into the project. The 6502 was like that.

-gjc

ted@nmsu.edu (Ted Dunning) (10/31/90)

here is a simple adventure game written in an object oriented style
mostly by the 10 year old that i taught scheme to last summer.

to start the adventure, use (adventure '() gr).  no more documentation
than the following program is available, although i can answer
questions about it.  hope it is interesting to somebody.

;; miscellaneous simple functions

;; remove an item from a list
(define (remove item list)
  (cond ((null? list) list)		;done?
	((eq? item (car list))		;is item at the beginning
	 (remove item (cdr list)))
	(else				;no, remove it from the rest
	 (cons (car list) (remove item (cdr list))))))

(define (first x) (car x))
(define (second x) (cadr x))
(define (third x) (caddr x))
(define (randomth list)
  (nth list (random (length list))))
(define (nth l n)
  (cond ((zero? n) (car l))
	((null? l) '())
	(else (nth (cdr l) (- n 1)))))
    
(define (lookup name table)
  (cond ((null? table) '())
	((eq? name (car (car table))) (cdr (car table)))
	(else (lookup name (cdr table)))))

;adds (name value) to table
(define (acons name value table)
  (cons (cons name value) table))

;; construct a generic object that can't do much
(define (make-object name description method-list)
  (define (get-methods) methods)
  (define methods (let loop ((l `((methods ,@get-methods)
				  (name ,@name)
				  (description ,@description)))
			     (m method-list))
		    (if (null? m) l
			(loop (acons (first m) (second m) l) (cddr m)))))

  (define (us message)
    (let ((binding (assoc message methods)))
      (if binding (cdr binding)
	  (begin
	    (format #t "don't know how to ~a a ~a~%" message name)
	    #f))))

  us)

;; construct a room
(define (make-room name description)
  (define neighbors '())
  (define contents '())

  (define (get-neighbor direction)
    (lookup direction neighbors))
    
  (define (set-neighbor direction room)
    (set! neighbors (acons direction room neighbors)))

  (define (get-contents) contents)

  (define (look)
    (format #t "~%")
    (format #t description)
    (if (not (null? contents))
	(begin
	  (format #t "~%I see ~%")
	  (for-each (lambda (x) (format #t "    ~a~%" (x 'description)))
		    contents))
	(format #t "~%")))

  (define (take what)
    (set! contents (remove what contents)))

  (define (drop what)
    (set! contents (cons what contents)))

  (define us (make-object name description
			  `(get-neighbor ,get-neighbor
			    set-neighbor ,set-neighbor
			    look ,look
			    contents ,get-contents
			    take ,take
			    drop ,drop)))

  us)
  

(define (make-thing name description extra-methods)
  (define (take-object contents room)
    (if (member us ( (room 'contents) ))
	(begin 
	  ( (room 'take) us)
	  (format #t "Got ~a~%" name)
	  (cons us contents))
	(begin
	  (if (member us contents)
	      (format #t "We already have a ~a.~%" (us 'name)))
	  contents)))
	    
  (define (drop-object contents room)
    ( (room 'drop ) us)
    (format #t "Dropped ~a~%" name)
    (remove us contents))

  (define us (make-object name description
			  `(drop ,drop-object
			    take ,take-object ,@extra-methods)))
  us)

(define (make-edible-thing name description extra-methods)
  (define (eat-object contents room)
    (if (member us contents) 
	(let ((message (randomth '("That was good!~%"
				   "I nearly choked!~%"
				   "This is rotten!~%"
				   "This tastes horrible!~%"
				   "How lovely!~%"
				   "It's quite an honor to taste that!~%"
				   "Have you ever eaten one?~%"
				   "I liked that!~%"
				   "Yuck!~%"))))
	  (format #t message)
	  (remove us contents))
	(begin (format #t "can't eat what we don't have!")
	       contents)))

  (define us (make-thing name description `(eat ,eat-object
						,@extra-methods)))

  us)
				 
(define (make-wearable-thing name description extra-methods)
  (define (wear contents room)
    (if (member the-thing contents)
	(let ((message (randomth '("This feels warm!~%"
			       "This ITCHES!!!~%"
			       "It's not as comfortable as my silk pajamas, but it's okay.~%"
			       "This feels dreadful!~%"
			       "I feel much warmer.~%"
			       "It's even better than my ostrich feather jacket!~%"))))
	  (format #t message)
	  (remove the-thing contents))
	(begin
	  (format #t "How do you expect me to wear something I don't even have?!~%")
	  contents)))

  (define the-thing (make-thing name description `(wear ,wear ,@extra-methods)))

  the-thing)

(define (make-inedible-thing name description extra-methods)
  (define (cant-eat contents room)
    (format #t "~%Thank you but I suspect it is poisonous so no thank you!~%")
    contents)

  (define us (make-thing name description `(eat ,cant-eat ,@extra-methods)))

  us)
    
(define (find-object name list)
  (if (null? list) #f
      (if (eq? name ( (car list) 'name)) (car list)
	  (find-object name (cdr list)))))

(define (adventure our-stuff room)
  (format #t "~%What should we do?~%")
  (let ((message (read)))
    (case message
      ((look) ((room 'look))
	      (adventure our-stuff room))
      ((inventory) (if (null? our-stuff)
		       (format #t "We aren't carrying anything~%")
		       (begin
			 (format #t "~%We have~%")
			 (for-each (lambda (x) (format #t "    ~a~%"
						       (x 'description)))
				   our-stuff)))
		   (adventure our-stuff room))
      ((go) (let* ((direction (read))
		   (where-to ((room 'get-neighbor) direction)))
	      (if where-to
		  (begin ( (where-to 'look) )
			 (adventure our-stuff where-to))
		  (begin (format #t "dead end~%")
			 (adventure our-stuff room)))))
      ((quit) 'done)
      (else (let* ((object-name (read))
		   (the-object (or (find-object object-name our-stuff)
			       (find-object object-name
					    ((room 'contents)) )))) 
	      (if the-object
		  (let ((handler (the-object message)))
		    (adventure (if handler (handler our-stuff room) our-stuff)
			       room))
		  (begin (format #t "I don't see a ~a~%" object-name)
			 (adventure our-stuff room))))))))

(define gr (make-room "The Greasy Room"
		      "The walls and floor are all GREASY!!"))
(define hc (make-room "Hall of Clowns"
		      "There are many silly little clowns jumping around"))
(define bs (make-room "The Bookstore"
		      "Many dusty books lie on the shelves and floor"))
(define gm (make-room "The Gold Mine"
		      "In the dark tunnel are many bars of gold"))
(define ws (make-room "The Woolly Socks Room"
		      "There are enormous numbers of humongous woolly socks on the wall"))

(define lr (make-room "Loud Room"
		      "You hear many voices but see no one."))
(define kc (make-room "Kitchen"
		      "There is sometimes food here."))
(define sg (make-room "Secret Garden"
		      "Flowers and Plants surround you."))
(define cb (make-room "Crying Baby Room"
		      "A note says, 'Take care.'"))
(define sea (make-room "Sea of Riches"
		       "Shells line the bottom of the sea and are tossed around by the angry waves."))

(define roses (make-thing 'roses "Beautiful, red roses" '()))

(define soap (make-edible-thing 'soap "A bar of soap, be careful, don't slip on it" '()))

(define wizard-hat (make-wearable-thing 'hat "Here lies a spooky blue wizard's hat" '()))

(define gold (make-thing 'gold "Shining, beautiful gold" '()))

(define pearls (make-wearable-thing 'pearls "Bright, sparkling pearls" '()))

(define calculus-book
  (make-thing 'book "A horrible-looking, thick, blue calculus book labeled 'Used'" '()))

(define shoelaces (make-wearable-thing 'shoelaces "Brown shoelaces" '()))

(define blanket (make-wearable-thing 'blanket "A soft, red, warm blanket" '()))

(define baby (make-thing 'baby "A cute, little crying baby" '()))

(define cake
  (make-edible-thing
   'cake "A five-layer chocolate cake with vanilla icing" '()))

(define t-shirt
  (make-wearable-thing
   't-shirt
   "A red, green, and hot pink t-shirt with something written on it"
   `(read ,(lambda (contents room) (format #t "HAPPY BIRTHDAY, ERIC~%")))))

(define cucumber (make-edible-thing 'cucumber "A green, yummy cucumber" '()))

(define spider-web
  (make-inedible-thing 'spider-web "An old, sticky spider web"
		       `(drop
			 ,(lambda (x y)
			    (format #t "it is tooooo sticky to drop~%") x))))

(define rope (make-wearable-thing 'rope "A thick, stout rope" '()))

(define mouse
  (make-edible-thing 'mouse "A yucky DEAD mouse which looks like it's been dead for 50 days"
		     `(drop
		       ,(lambda(x y)
			  (format #t "you can't drop a mouse, you have to EAT it!!~%")
			  x))))

(define pans (make-thing 'pans "Rusty, black, huge Pans" '()))

( (ws 'set-neighbor) 'west lr)
( (lr 'set-neighbor) 'east ws)
( (bs 'set-neighbor) 'west lr)
( (gm 'set-neighbor) 'south kc)
( (kc 'set-neighbor) 'north gm)
( (sg 'set-neighbor) 'east cb)
( (kc 'set-neighbor) 'south sg)
( (sg 'set-neighbor) 'north kc)
( (cb 'set-neighbor) 'west sg)
( (sg 'set-neighbor) 'west sea)
( (sea 'set-neighbor) 'east sg)

( (gr 'set-neighbor) 'west hc)

( (hc 'set-neighbor) 'east gr)
( (hc 'set-neighbor) 'west ws)
( (hc 'set-neighbor) 'north bs)
( (hc 'set-neighbor) 'down gm)

( (ws 'set-neighbor) 'east hc)

( (bs 'set-neighbor) 'south hc)

( (gm 'set-neighbor) 'up hc)

(for-each (cb 'drop) (list baby blanket calculus-book))
(for-each (ws 'drop) (list shoelaces rope))
(for-each (lr 'drop) (list wizard-hat))
(for-each (hc 'drop) (list cucumber))
(for-each (gm 'drop) (list gold roses))
(for-each (sea 'drop) (list pearls t-shirt))
(for-each (kc 'drop) (list cake pans soap))
(for-each (bs 'drop) (list spider-web))
(for-each (sg 'drop) (list mouse))

--
I don't think the stories are "apocryphal".  I did it :-)  .. jthomas@nmsu.edu

moreno@cs.umn.edu (Andres Moreno) (10/31/90)

I also think that you should look into LOGO.
there's a great deal of literature to help you along:
- A book by Abelson, so you get a feeling for what LOGO is.
- A book by Abelson and Dissesa on "turtle geometry"
- A tryptic by Harvey, dealing with basic computer concepts, from an
  enligthened view point.

Note that the Apple II implementation of LOGO is o.k. (i used it for serious
A.I. programming). Get the official Apple one, not the terrapin LOOG. If you
want to get it for the Mac, you might want to look at the appendix of the
first volume of Harvey's collection, since he does (a somewhat dated) eva-
luation of the options available.

I have found that people that learn BASIC first have to do a great deal of
unlearning to be able to really get a good command of a lisp-like language.
Note that LOGO or SCHEME are natural tools to do quick and nice programs for
science labs or even for a bit of math. ( I found for an assignment the ele-
ments for the group of rigid motions on a tetrahedron with very little work.
if you do it by hand, you'll hate it. If you do it right, you can have LOGO
write the functions for the permutation and then you can play to your heart's
content.)

Cheers, Andres

(I had to post this since I could not reach you via mail -- my mailer didn't
like your address)