This section lists code examples from the Revised^5 Report on the Algorithmic Language Scheme (r5rs) for which Armpit Scheme does not produce an output that is similar to that in the report. There are 4 main aspects of non-conformance in this release: 1) quasiquote expansion is not fully recursive, 2) macros are 50% hygienic only, 3) "constant" lists, strings and vectors are not immutable, and 4) symbols are case-sensitive.
; 4.2.6 quasiquotation
`(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f) ; -> niet (nested backquote/unquote)
(let ((name1 'x)
(name2 'y))
`(a `(b `name1 ,',name2 d) e)) ; -> nein (nested backquote/unquote)
; 4.3.1 Binding constructs for syntactic keywords
(let-syntax ((when
(syntax-rules ()
((_ test stmt1 stmt2 ...)
(if test
(begin stmt1 stmt2 ...))))))
(let ((if #t))
(when if (set! if 'now))
if)) ; -> error: (data throw 1170) rather than now
(let ((x 'outer))
(let-syntax ((m (syntax-rules () ((_) x))))
(let ((x 'inner))
(m)))) ; -> inner rather than outer
(letrec-syntax
((my-or
(syntax-rules ()
((_) #f)
((_ e) e)
((_ e1 e2 ...)
(let ((temp e1))
(if temp
temp
(my-or e2 ...)))))))
(let ((x #f)
(y 7)
(temp 8)
(let odd?)
(if even?))
(my-or x
(let temp)
(if y)
y))) ; -> error: (core throw temq) rather than 7
; 4.3.2 pattern language
(let ((=> #f))
(cond (#t => 'ok))) ; -> error: (core throw ok) rather than ok
; 6.3 Other Data Types
; 6.3.2 pairs and list
(define (g) '(constant-list))
(set-car! (g) 3) ; -> gives a value rather than error
; (g) -> (3)
; 6.3.3 symbols
; expression below works but returns #f
(eq? 'mISSISSIppi 'mississippi)
(eq? 'bitBlt (string->symbol "bitBlt")) ; -> gives #t
; 6.3.5 strings
(define (g) "***")
(string-set! (g) 0 #\?) ; -> "?**" rather than error
(string-set! (symbol->string 'immutable) 0 #\?) ; -> "?mmutable" rather than error
; 6.3.6 vectors
(vector-set! '#(0 1 2) 1 "doe") ; -> executes rather than giving error
This section lists code examples from the Revised^5 Report on the Algorithmic Language Scheme (r5rs) for which Armpit Scheme produces either the same output as in the report or a result that is considered very close to that in the report.
; 4. Expressions
; 4.1.1 variable references
(define x 28)
x
; 4.1.2 literal expressions
(quote a)
(quote #(a b c))
(quote (+ 1 2))
'a
'#(a b c)
'()
'(+ 1 2)
'(quote a)
''a
'"abc"
"abc"
'145932
145932
'#t
#t
; 4.1.3 procedure calls
(+ 3 4)
((if #f + *) 3 4)
; 4.1.4 procedures
(lambda (x) (+ x x))
((lambda (x) (+ x x)) 4)
(define reverse-subtract
(lambda (x y) (- y x)))
(reverse-subtract 7 10)
(define add4
(let ((x 4))
(lambda (y) (+ x y))))
(add4 6)
((lambda x x) 3 4 5 6)
((lambda (x y . z) z) 3 4 5 6)
; 4.1.5 conditionals
(if (> 3 2) 'yes 'no)
(if (> 2 3) 'yes 'no)
(if (> 3 2)
(- 3 2)
(+ 3 2))
; 4.1.6 assignments
(define x 2)
(+ x 1)
(set! x 4)
(+ x 1)
; 4.2.1 conditionals
(cond ((> 3 2) 'greater)
((< 3 2) 'less))
(cond ((> 3 3) 'greater)
((< 3 3) 'less)
(else 'equal))
(cond ((assv 'b '((a 1) (b 2))) => cadr)
(else #f))
(case (* 2 3)
((2 3 5 7) 'prime)
((1 4 6 8 9) 'composite))
(case (car '(c d))
((a) 'a)
((b) 'b))
(case (car '(c d))
((a e i o u) 'vowel)
((w y) 'semivowel)
(else 'consonant))
(and (= 2 2) (> 2 1))
(and (= 2 2) (< 2 1))
(and 1 2 'c '(f g))
(and)
(or (= 2 2) (> 2 1))
(or (= 2 2) (< 2 1))
(or #f #f #f)
(or (memq 'b '(a b c))
(/ 3 0))
; 4.2.2 binding constructs
(let ((x 2) (y 3))
(* x y))
(let ((x 2) (y 3))
(let ((x 7) (z (+ x y)))
(* z x)))
(let ((x 2) (y 3))
(let* ((x 7) (z (+ x y)))
(* z x)))
(letrec
((even?
(lambda (n)
(if (zero? n)
#t
(odd? (- n 1)))))
(odd?
(lambda (n)
(if (zero? n)
#f
(even? (- n 1))))))
(even? 88))
; 4.2.3 sequencing
(define x 0)
(begin (set! x 5)
(+ x 1))
(begin (display "4 plus 1 equals ")
(display (+ 4 1)))
; 4.2.4 iteration
(do ((vec (make-vector 5))
(i 0 (+ i 1)))
((= i 5) vec)
(vector-set! vec i i))
(let ((x '(1 3 5 7 9)))
(do ((x x (cdr x))
(sum 0 (+ sum (car x))))
((null? x) sum)))
(let loop ((numbers '(3 -2 1 6 -5))
(nonneg '())
(neg '()))
(cond ((null? numbers) (list nonneg neg))
((>= (car numbers) 0)
(loop (cdr numbers)
(cons (car numbers) nonneg)
neg))
((< (car numbers) 0)
(loop (cdr numbers)
nonneg
(cons (car numbers) neg)))))
; 4.2.6 quasiquotation
`(list ,(+ 1 2) 4)
(let ((name 'a)) `(list ,name ',name))
`(a ,(+ 1 2) ,@(map abs '(4 -5 6)) b)
`((foo ,(- 10 3)) ,@(cdr '(c)) . ,(car '(cons)))
`#(10 5 ,(sqrt 4) ,@(map sqrt '(16 9)) 8) ; -> #(10 5 2. 4. 3. 8) for #(10 5 2 4 3 8)
; 5. Program Structure
; 5.2 definitions
; 5.2.1 top level definitions
(define add3
(lambda (x) (+ x 3)))
(add3 3)
(define first car)
(first '(1 2))
; 5.2.2 internal definitions
(let ((x 5))
(define foo (lambda (y) (bar x y)))
(define bar (lambda (a b) (+ (* a b) a)))
(foo (+ x 3)))
(let ((x 5))
(letrec ((foo (lambda (y) (bar x y)))
(bar (lambda (a b) (+ (* a b) a))))
(foo (+ x 3))))
; 6. Standard Procedures
; 6.1 equivalence predicates
(eqv? 'a 'a)
(eqv? 'a 'b)
(eqv? 2 2)
(eqv? '() '())
(eqv? 100000000 100000000)
(eqv? (cons 1 2) (cons 1 2))
(eqv? (lambda () 1) (lambda () 2))
(eqv? #f 'nil)
(let ((p (lambda (x) x)))
(eqv? p p))
(eqv? "" "")
(eqv? '#() '#())
(eqv? (lambda (x) x) (lambda (x) x))
(eqv? (lambda (x) x) (lambda (y) y))
(define gen-counter
(lambda ()
(let ((n 0))
(lambda () (set! n (+ n 1)) n))))
(let ((g (gen-counter)))
(eqv? g g))
(eqv? (gen-counter) (gen-counter))
(define gen-loser
(lambda ()
(let ((n 0))
(lambda () (set! n (+ n 1)) 27))))
(let ((g (gen-loser)))
(eqv? g g))
(eqv? (gen-loser) (gen-loser))
(letrec ((f (lambda () (if (eqv? f g) 'both 'f)))
(g (lambda () (if (eqv? f g) 'both 'g))))
(eqv? f g))
(letrec ((f (lambda () (if (eqv? f g) 'f 'both)))
(g (lambda () (if (eqv? f g) 'g 'both))))
(eqv? f g))
(eq? '(a) '(a))
(eqv? "a" "a")
(eqv? '(b) (cdr '(a b)))
(let ((x '(a)))
(eqv? x x))
(eq? 'a 'a)
(eq? '(a) '(a))
(eq? (list 'a) (list 'a))
(eq? "a" "a")
(eq? "" "")
(eq? '() '())
(eq? 2 2)
(eq? #\A #\A)
(eq? car car)
(let ((n (+ 2 3)))
(eq? n n))
(let ((x '(a)))
(eq? x x))
(let ((x '#()))
(eq? x x))
(let ((p (lambda (x) x)))
(eq? p p))
(equal? 'a 'a)
(equal? '(a) '(a))
(equal? '(a (b) c) '(a (b) c))
(equal? "abc" "abc")
(equal? 2 2)
(equal? (make-vector 5 'a) (make-vector 5 'a))
(equal? (lambda (x) x) (lambda (y) y))
; 6.2 Numbers
; 6.2.5 numerical operations
(complex? 3+4i) ; -> #t
(complex? 3) ; -> #t
(real? 3) ; -> #t
(real? -2.5+0.0i) ; -> #t
(real? #e1e10) ; -> (core throw 2441406), 1e10 is too large for exact
(real? #e5e8) ; -> #t
(rational? 6/10) ; -> #t
(rational? 6/3) ; -> #t
(integer? 3+0i) ; -> #t
(integer? 3.0) ; -> #t
(integer? 8/4) ; -> #t
(max 3 4)
(max 3.9 4)
(+ 3 4)
(+ 3)
(+)
(* 4)
(*)
(- 3 4)
(- 3 4 5)
(- 3)
(/ 3 4 5)
(/ 3)
(abs -7)
(modulo 13 4)
(remainder 13 4)
(modulo -13 4)
(remainder -13 4)
(modulo 13 -4)
(remainder 13 -4)
(modulo -13 -4)
(remainder -13 -4)
(gcd 32 -36)
(gcd) ; -> 0
(lcm 32 -36)
(lcm 32.0 -36) ; -> 2.88e2 (i.e. 288.0)
(lcm) ; -> 1
(rationalize
(inexact->exact .3) 1/10) ; -> 1/3
(rationalize .3 1/10) ; -> 3.33333e-1 (i.e. #i1/3)
(numerator (/ 6 4)) ; -> 3
(denominator (/ 6 4)) ; -> 2
(denominator
(exact->inexact (/ 6 4))) ; -> 2.
(floor -4.3)
(ceiling -4.3)
(truncate -4.3)
(round -4.3)
(floor 3.5)
(ceiling 3.5)
(truncate 3.5)
(round 3.5)
(round 7/2) ; -> 4
(round 7)
; 6.2.6 numerical input and output
(string->number "100")
(string->number "100" 16)
(string->number "1e2")
(string->number "15##") ; -> 1.5e3 for 1500.0
; 6.3 Other Data Types
; 6.3.1 booleans
#t
#f
'#f
(not #t)
(not 3)
(not (list 3))
(not #f)
(not '())
(not (list))
(not 'nil)
(boolean? #f)
(boolean? 0)
(boolean? '())
; 6.3.2 pairs and list
(define x (list 'a 'b 'c))
(define y x)
y
(list? y)
(set-cdr! x 4)
x
(eqv? x y)
y
(list? y)
(set-cdr! x x)
(list? x)
(pair? '(a . b))
(pair? '(a b c))
(pair? '())
(pair? '#(a b))
(cons 'a '())
(cons '(a) '(b c d))
(cons "a" '(b c))
(cons 'a 3)
(cons '(a b) 'c)
(car '(a b c))
(car '((a) b c d))
(car '(1 . 2))
(cdr '((a) b c d))
(cdr '(1 . 2))
(define (f) (list 'not-a-constant-list))
(define (g) '(constant-list))
(set-car! (f) 3)
(list? '(a b c))
(list? '())
(list? '(a . b))
(let ((x (list 'a)))
(set-cdr! x x)
(list? x))
(list 'a (+ 3 4) 'c)
(list)
(length '(a b c))
(length '(a (b) (c d e)))
(length '())
(append '(x) '(y))
(append '(a) '(b c d))
(append '(a (b)) '((c)))
(append '(a b) '(c . d))
(append '() 'a)
(reverse '(a b c))
(reverse '(a (b c) d (e (f))))
(list-ref '(a b c d) 2)
(list-ref '(a b c d)
(inexact->exact (round 1.8))) ; -> c
(memq 'a '(a b c))
(memq 'b '(a b c))
(memq 'a '(b c d))
(memq (list 'a) '(b (a) c))
(member (list 'a) '(b (a) c))
(memq 101 '(100 101 102))
(memv 101 '(100 101 102))
(define e '((a 1) (b 2) (c 3)))
(assq 'a e)
(assq 'b e)
(assq 'd e)
(assq (list 'a) '(((a)) ((b)) ((c))))
(assoc (list 'a) '(((a)) ((b)) ((c))))
(assq 5 '((2 3) (5 7) (11 13)))
(assv 5 '((2 3) (5 7) (11 13)))
; 6.3.3 symbols
(symbol? 'foo)
(symbol? (car '(a b)))
(symbol? "bar")
(symbol? 'nil)
(symbol? '())
(symbol? #f)
(symbol->string 'flying-fish)
(symbol->string 'Martin)
(symbol->string
(string->symbol "Malvina"))
(string->symbol "mISSISSIppi")
(eq? 'JollyWog
(string->symbol
(symbol->string 'JollyWog)))
(string=? "K. Harper, M.D."
(symbol->string
(string->symbol "K. Harper, M.D.")))
(string=? "K. Harper, M.D."
(symbol->string
(string->symbol "K. Harper, M.D.")))
; 6.3.4 characters
#\a
#\A
#\(
#\
#\space
#\newline ; -> linefeed only (no carriage return)
(char>? #\A #\B)
(char>? #\a #\b)
(char>? #\0 #\9)
; 6.3.5 strings
"The word \"recursion\" has many meanings."
(define (f) (make-string 3 #\*))
(define (g) "***")
(string-set! (f) 0 #\?)
; 6.3.6 vectors
'#(0 (2 2 2 2) "Anna")
(vector 'a 'b 'c)
(vector-ref '#(1 1 2 3 5 8 13 21)
5)
(vector-ref '#(1 1 2 3 5 8 13 21)
(let ((i (round (* 2 (acos -1)))))
(if (inexact? i)
(inexact->exact i)
i))) ; -> 13
(let ((vec (vector 0 '(2 2 2 2) "Anna")))
(vector-set! vec 1 '("Sue" "Sue"))
vec)
(vector->list '#(dah dah didah))
(list->vector '(dididit dah))
; 6.4 control features
(procedure? car)
(procedure? 'car)
(procedure? (lambda (x) (* x x)))
(procedure? '(lambda (x) (* x x)))
(call/cc procedure?)
(apply + (list 3 4))
(define compose
(lambda (f g)
(lambda args
(f (apply g args)))))
((compose sqrt *) 12 75) ; -> 3.e1 for 30
(map cadr '((a b) (d e) (g h)))
(map (lambda (n) (expt n n)) '(1 2 3 4 5)) ; -> (1 4 27 256 3125)
(map + '(1 2 3) '(4 5 6))
(let ((count 0))
(map (lambda (ignored)
(set! count (+ count 1))
count)
'(a b)))
(let ((v (make-vector 5)))
(for-each (lambda (i)
(vector-set! v i (* i i)))
'(0 1 2 3 4))
v)
(force (delay (+ 1 2)))
(let ((p (delay (+ 1 2))))
(list (force p) (force p)))
(define a-stream
(letrec ((next
(lambda (n)
(cons n (delay (next (+ n 1)))))))
(next 0)))
(define head car)
(define tail
(lambda (stream) (force (cdr stream))))
(head (tail (tail a-stream)))
(define count 0)
(define p
(delay (begin (set! count (+ count 1))
(if (> count x)
count
(force p)))))
(define x 5)
p
(force p)
p
(begin (set! x 10)
(force p))
(call/cc
(lambda (exit)
(for-each (lambda (x)
(if (negative? x)
(exit x)))
'(54 0 37 -3 245 19))
#t))
(define list-length
(lambda (obj)
(call/cc
(lambda (return)
(letrec ((r
(lambda (obj)
(cond ((null? obj) 0)
((pair? obj)
(+ (r (cdr obj)) 1))
(else (return #f))))))
(r obj))))))
(list-length '(1 2 3 4))
(list-length '(a b . c))
(call-with-values (lambda () (values 4 5))
(lambda (a b) b))
(call-with-values * -)
(let ((path '())
(c #f))
(let ((add (lambda (s)
(set! path (cons s path)))))
(dynamic-wind
(lambda () (add 'connect))
(lambda ()
(add (call/cc
(lambda (c0)
(set! c c0)
'talk1))))
(lambda () (add 'disconnect)))
(if (< (length path) 4)
(c 'talk2)
(reverse path)))) ; -> (connect talk1 disconnect connect talk2 disconnect)
; 6.5. eval
(eval '(* 7 3) (scheme-report-environment 5)) ; -> 21 (superset)
(let ((f (eval '(lambda (f x) (f x x))
(null-environment 5))))
(f + 10)) ; -> 20 (same as scheme-report-environment)
(interaction-environment)
; 6.6 input and output
; no examples provided in r5rs
This section lists Armpit Scheme derived expression types (macros) corresponding to those described in Section 7.3 of the Revised^5 Report on the Algorithmic Language Scheme (r5rs). Differences between these definitions and those in r5rs are briefly described.
; armpit scheme working version - difference with r5rs is 1 vs 2 vars before ...
(define-syntax cond
(syntax-rules (else =>)
((_ (else result1 ...))
(begin result1 ...))
((_ (test => result))
(let ((temp test))
(if temp (result temp))))
((_ (test => result) clause1 ...)
(let ((temp test))
(if temp
(result temp)
(cond clause1 ...))))
((_ (test)) test)
((_ (test) clause1 ...)
(let ((temp test))
(if temp
temp
(cond clause1 ...))))
((_ (test result1 ...))
(if test (begin result1 ...)))
((_ (test result1 ...) clause1 ...)
(if test
(begin result1 ...)
(cond clause1 ...)))))
; armpit scheme working version - difference with r5rs is 1 vs 2 vars before ...
(define-syntax case
(syntax-rules (else)
((_ (key ...)
clauses ...)
(let ((atom-key (key ...)))
(case atom-key clauses ...)))
((_ key
(else result1 ...))
(begin result1 ...))
((_ key
((atom ...) result1 ...))
(if (memv key (quote (atom ...)))
(begin result1 ...)))
((_ key
((atoms ...) result1 ...)
clause1 ...)
(if (memv key (quote (atoms ...)))
(begin result1 ...)
(case key clause1 ...)))))
(define-syntax and
(syntax-rules ()
((_) #t)
((_ test) test)
((_ test1 test2 ...)
(if test1 (and test2 ...) #f))))
(define-syntax or
(syntax-rules ()
((_) #f )
((_ test) test)
((_ test1 test2 ...)
(let ((x test1))
(if x x (or test2 ...))))))
; armpit scheme working version - difference with r5rs is 1 vs 2 vars before ...
(define-syntax let
(syntax-rules ()
((_ ((name val) ...) body1 ...)
((lambda (name ...) body1 ...)
val ...))
((_ tag ((name val) ...) body1 ...)
((letrec ((tag (lambda (name ...)
body1 ...)))
tag)
val ...))))
; armpit scheme working version - difference with r5rs:
; 1) 1 vs 2 vars before ...
; 2) new case for single binding (not caught by (bd1 bd2 ...))
(define-syntax let*
(syntax-rules ()
((_ () body1 ...)
(let () body1 ...))
((_ (binding1) body1 ...)
(let (binding1) body1 ...))
((_ (binding1 binding2 ...) body1 ...)
(let (binding1)
(let* (binding2 ...) body1 ...)))))
; armpit scheme working version - difference with r5rs:
; 1) 1 vs 2 vars before ...
; 2) "generate_temp_names" replaced by #t
; 3) (x y ...) changed to (x . y)
(define-syntax letrec
(syntax-rules ()
((_ ((var1 init1) ...) body ...)
(letrec #t
(var1 ...)
()
((var1 init1) ...)
body ...))
((_ #t
()
(temp1 ...)
((var1 init1) ...)
body ...)
(let ((var1 #t ) ...)
(let ((temp1 init1) ...)
(set! var1 temp1) ...
body ...)))
((_ #t
(x . y)
temp
((var1 init1) ...)
body ...)
(letrec #t
y
(newtemp . temp)
((var1 init1) ...)
body ...))))
(define-syntax begin
(syntax-rules ()
((begin exp ...)
((lambda () exp ...)))))
; this form is not cooperating -> (apply error: #t)
(define-syntax begin
(syntax-rules ()
((begin exp)
exp)
((begin exp1 exp2 ...)
(let ((x exp1))
(begin exp2 ...)))))
; armpit scheme working version - difference with r5rs:
; 1) added case with no commands
; 2) changed "step" to #t
; 3) replaced step ... with . step
(define-syntax do
(syntax-rules ()
((_ ((var init . step) ...)
(test expr ...))
(do ((var init . step) ...)
(test expr ...)
()))
((_ ((var init . step) ...)
(test expr ...)
command ...)
(letrec
((loop
(lambda (var ...)
(if test
(begin
(if #f #f )
expr ...)
(begin
command ...
(loop (do #t var . step) ...))))))
(loop init ...)))
((_ #t x) x)
((_ #t x y) y)))