Added (length)
[scheme.forth.jl.git] / scheme-library.scm
index 5ee0b49..484f500 100644 (file)
 (define (cddr l) (cdr (cdr l)))
 (define (cadar l) (car (cdr (car l))))
 
 (define (cddr l) (cdr (cdr l)))
 (define (cadar l) (car (cdr (car l))))
 
+; Return number of items in list
+(define (length l)
+  (define (iter a count)
+    (if (null? a)
+      count
+      (iter (cdr a) (+ count 1))))
+  (iter l 0))
+
 ; Join two lists together
 (define (join l1 l2)
   (if (null? l1)
 ; Join two lists together
 (define (join l1 l2)
   (if (null? l1)
@@ -33,8 +41,8 @@
     ()
     (append (reverse (cdr l)) (list (car l)))))
 
     ()
     (append (reverse (cdr l)) (list (car l)))))
 
-;; LIBRARY FORMS
 
 
+;; LIBRARY SPECIAL FORMS
 
 ; let
 
 
 ; let
 
 ; while
 
 (define-macro (while condition . body)
 ; while
 
 (define-macro (while condition . body)
-              (define loop (gensym))
-              `(begin
-                 (define (,loop)
-                   (if ,condition
-                     (begin ,@body (,loop))))
-                 (,loop)))
+              (let ((loop (gensym)))
+                `(begin
+                   (define (,loop)
+                     (if ,condition
+                       (begin ,@body (,loop))))
+                   (,loop))))
+
+; cond
+
+(define (cond-predicate clause) (car clause))
+(define (cond-actions clause) (cdr clause))
+(define (cond-else-clause? clause)
+  (eq? (cond-predicate clause) 'else))
+
+(define (expand-clauses clauses)
+  (if (null? clauses)
+    (none)
+    (let ((first (car clauses))
+          (rest (cdr clauses)))
+      (if (cond-else-clause? first)
+        (if (null? rest)
+          `(begin ,@(cond-actions first))
+          (error "else clause isn't last in cond expression."))
+        `(if ,(cond-predicate first)
+           (begin ,@(cond-actions first))
+           ,(expand-clauses rest))))))
+
+(define-macro (cond . clauses)
+              (if (null? clauses)
+                (error "cond requires at least one clause.")
+                (expand-clauses clauses)))
+
+; and
+
+(define (expand-and-expressions expressions)
+  (let ((first (car expressions))
+        (rest (cdr expressions)))
+    (if (null? rest)
+      first
+      `(if ,first
+         ,(expand-and-expressions rest)
+         #f))))
+
+(define-macro (and . expressions)
+              (if (null? expressions)
+                #t
+                (expand-and-expressions expressions)))
+
+; or
+
+(define (expand-or-expressions expressions)
+  (if (null? expressions)
+    #f
+    (let ((first (car expressions))
+          (rest (cdr expressions))
+          (val (gensym)))
+      `(let ((,val ,first))
+         (if ,val
+            ,val
+            ,(expand-or-expressions rest))))))
+
+(define-macro (or . expressions)
+              (expand-or-expressions expressions))
+
 
 ;; TESTING
 
 
 ;; TESTING