;; Sample pre-defined Scheme operations on numbers

(define my*
  (lambda (x y)
    (if (= x 0)
	0
	(+ y (my* (- x 1) y)))))


;; Sample pre-defined Scheme operations on characters

(define mychar-whitespace?
  (lambda (x)
    (or (char=? x #\space)
	(char=? x #\tab)
	(char=? x #\newline))))

;; Sample pre-defined Scheme operations on lists

(define myappend
  (lambda (x y)
    (if (null? x)
	y
	(cons (car x) (myappend (cdr x) y)))))

(define (myappend x y)
    (if (null? x)
	y
	(cons (car x) (myappend (cdr x) y))))

(define mylength
  (lambda (x)
    (if (null? x)
	0
	(+ 1 (mylength (cdr x))))))

(define mymap
  (lambda (f x)
    (if (null? x)
	'()
	(cons (f (car x)) (mymap f (cdr x))))))

;; s-lists operations
;;
;; Following grammar:
;;
;; <s-list> ::= ()
;;             |    (<symbol-expression> . <s-list>)
;; <symbol-expression> ::= <symbol> | <s-list>
;;

(define s-list?
  (lambda (lst)
    (if (null? lst)
	#t
	(and
	 (list? lst)
	 (symbol-expression? (car lst))
	 (s-list? (cdr lst))))))

(define symbol-expression?
  (lambda (se)
    (or (symbol? se)
	(s-list? se))))

;; Inlining grammar/program:
;; 
;; <s-list> ::= ()
;;             |    (<symbol>|<s-list> . <s-list>)
;;

(define s-list?
  (lambda (lst)
    (if (null? lst)
	#t
	(and
	 (list? lst)
	 (or (symbol? (car lst)) (s-list? (car lst)))
	 (s-list? (cdr lst))))))

;; Following Kleene-star grammar:
;;
;; <s-list> ::= ({<symbol>|<s-list>}*)
;;

(define s-list?
  (lambda (lst)
    (andmap (lambda (x) (or (symbol? x) (and (list? x) (s-list? x)))) lst)))

;; The former procedure only works on lists, i.e. (s-list? 4) will produce an error.
;;  This is a corrected version:

(define s-list?
  (lambda (lst)
    (and (list? lst)
	 (andmap (lambda (x) (or (symbol? x) (s-list? x))) lst))))


;; Exercise 1.15 (1,2,3,9)

(define duple
  (lambda (n s)
    (if (= n 0) 
	'()
	(cons s (duple (- n 1) s)))))

(define invert
  (lambda (lst)
    (if (null? lst)
	'()
	(cons (list (car (cdr (car lst))) 
		    (car (car lst)))
	      (invert (cdr lst))))))

(define invert
  (lambda (lst)
    (map (lambda (lst) (list (cadr lst) (car lst))) lst)))

(define filter-in
  (lambda (pred lst)
    (if (null? lst)
	'()
	(if (pred (car lst))
	    (cons (car lst) (filter-in pred (cdr lst)))
	    (filter-in pred (cdr lst))))))

(define down
  (lambda (lst)
    (if (null? lst)
	'()
	(cons (list (car lst))
	      (down (cdr lst))))))

;; Exercise 1.16.1

(define up ... )

;; Well-formed lambda-calculus expression

(define lambda-expression? ... )
