X-Git-Url: https://thelambdalab.xyz/gitweb/index.cgi?a=blobdiff_plain;f=src%2Fscheme-library.scm;h=8740e15e209325eb4b1d1e0f7b08b61675443ea1;hb=455f839be6ce83f0131de3cc6d3449e9e6b85ca3;hp=85580fdb65540e5d45e05175bd6cfb4ddf92487e;hpb=3055ae2e3d57ec91a4187a6c5cf8f05357d60810;p=scheme.forth.jl.git diff --git a/src/scheme-library.scm b/src/scheme-library.scm index 85580fd..8740e15 100644 --- a/src/scheme-library.scm +++ b/src/scheme-library.scm @@ -2,17 +2,190 @@ ;; Standard Library Procedures and Macros ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; MISC +;; MISC ESSENTIAL PROCEDURES + +(define list + (lambda args args)) + +(define map + (lambda (proc l) + (if (null? l) + '() + (cons (proc (car l)) (map proc (cdr l)))))) + +(define join-lists + (lambda (l1 l2) + (if (null? l1) + l2 + (cons (car l1) (join-lists (cdr l1) l2))))) + +; Append an arbitrary number of lists together +(define append + (lambda lists + (if (null? lists) + () + (if (null? (cdr lists)) + (car lists) + (join-lists (car lists) (apply append (cdr lists))))))) + -(define (not x) (if x #f #t)) +;; DERIVED FORMS -(define (list . args) args) +;; define -(define (caar l) (car (car l))) -(define (cadr l) (car (cdr l))) -(define (cdar l) (cdr (car l))) -(define (cddr l) (cdr (cdr l))) -(define (cadar l) (car (cdr (car l)))) +(define-macro (define args . body) + (if (pair? args) + (list 'define (car args) (join-lists (list 'lambda (cdr args)) body)) + 'no-match)) + +;; not + +(define-macro (not x) + (list 'if x #f #t)) + +;; let + +(define-macro (let args . body) + (join-lists + (list (join-lists (list 'lambda (map (lambda (x) (car x)) args)) body)) + (map (lambda (x) (car (cdr x))) args))) + +;; quasiquote/unquote (one nesting level only) + +((lambda () + (define (qqhelper l) + (if (null? l) + l + (let ((head (car l)) + (tail (cdr l))) + + (if (pair? head) + (if (eq? (car head) 'unquote) + (list 'cons (car (cdr head)) (qqhelper tail)) + (if (eq? (car head) 'unquote-splicing) + (list 'join-lists (car (cdr head)) (qqhelper tail)) + (list 'cons (list 'quasiquote head) (qqhelper tail)))) + (if (symbol? head) + (list 'cons (list 'quote head) (qqhelper tail)) + (list 'cons head (qqhelper tail))))))) + + (define-macro (quasiquote arg) + (if (not (pair? arg)) + (list 'quote arg) + (qqhelper arg))))) + +;; begin + +(define-macro (begin . sequence) + `((lambda () ,@sequence))) + +;; caddr etc. + +(define-macro (caar l) `(car (car ,l))) +(define-macro (cadr l) `(car (cdr ,l))) +(define-macro (cdar l) `(cdr (car ,l))) +(define-macro (cddr l) `(cdr (cdr ,l))) +(define-macro (caaar l) `(car (car (car ,l)))) +(define-macro (caadr l) `(car (car (cdr ,l)))) +(define-macro (cadar l) `(car (cdr (car ,l)))) +(define-macro (caddr l) `(car (cdr (cdr ,l)))) +(define-macro (cdaar l) `(cdr (car (car ,l)))) +(define-macro (cdadr l) `(cdr (car (cdr ,l)))) +(define-macro (cddar l) `(cdr (cdr (car ,l)))) +(define-macro (cdddr l) `(cdr (cdr (cdr ,l)))) +(define-macro (cadddr l) `(car (cdr (cdr (cdr ,l))))) + +;; let* + +(define-macro (let* args . body) + (if (null? args) + `(let () ,@body) + `(let (,(car args)) + (let* ,(cdr args) ,@body)))) + +;; while + +(define-macro (while condition . body) + (let ((loop (gensym))) + `(begin + (define (,loop) + (if ,condition + (begin ,@body (,loop)))) + (,loop)))) + +;; cond + +((lambda () + (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 + +((lambda () + (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 + +((lambda () + (define (expand-or-expressions expressions) + (let ((first (car expressions)) + (rest (cdr expressions))) + (if (null? rest) + first + `(if ,first + #t + ,(expand-or-expressions rest))))) + + (define-macro (or . expressions) + (if (null? expressions) + #f + (expand-or-expressions expressions))))) + +;; FUNCTIONAL PROGRAMMING + +(define (fold-left proc init l) + (if (null? l) + init + (fold-left proc (proc init (car l)) (cdr l)))) + +(define (reduce-left proc init l) + (if (null? l) + init + (if (null? (cdr l)) + (car l) + (fold-left proc (proc (car l) (car (cdr l))) (cdr (cdr l)))))) ;; NUMBERS @@ -118,18 +291,6 @@ (define (null? arg) (eq? arg '())) -(define (fold-left proc init l) - (if (null? l) - init - (fold-left proc (proc init (car l)) (cdr l)))) - -(define (reduce-left proc init l) - (if (null? l) - init - (if (null? (cdr l)) - (car l) - (fold-left proc (proc (car l) (car (cdr l))) (cdr (cdr l)))))) - (define (+ . args) (fold-left pair+ 0 args)) @@ -195,6 +356,11 @@ (define (integer? x) (= x (round x))) (define (exact? x) (fixnum? x)) (define (inexact? x) (flonum? x)) +(define (number? x) + (if (fixnum? x) #t + (if (flonum? x) #t + (if (ratnum? x) #t #f)))) + ;; LISTS @@ -203,23 +369,9 @@ (define (iter a count) (if (null? a) count - (iter (cdr a) (+ count 1)))) + (iter (cdr a) (fix:+ count 1)))) (iter l 0)) -; Join two lists together -(define (join l1 l2) - (if (null? l1) - l2 - (cons (car l1) (join (cdr l1) l2)))) - -; Append an arbitrary number of lists together -(define (append . lists) - (if (null? lists) - () - (if (null? (cdr lists)) - (car lists) - (join (car lists) (apply append (cdr lists)))))) - ; Reverse the contents of a list (define (reverse l) (if (null? l) @@ -227,97 +379,8 @@ (append (reverse (cdr l)) (list (car l))))) -;; LIBRARY SPECIAL FORMS - -; let - -(define (let-vars args) - (if (null? args) - '() - (cons (caar args) (let-vars (cdr args))))) - -(define (let-inits args) - (if (null? args) - '() - (cons (cadar args) (let-inits (cdr args))))) - -(define-macro (let args . body) - `((lambda ,(let-vars args) - ,@body) ,@(let-inits args))) - -; while - -(define-macro (while condition . body) - (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 -(define-macro (backwards . body) - (cons 'begin (reverse body))) - ; Test for the while macro. (define (count) (define counter 10) @@ -330,15 +393,43 @@ (define (sum n) (define (sum-iter total count maxcount) - (if (> count maxcount) + (if (fix:> count maxcount) total - (sum-iter (+ total count) (+ count 1) maxcount))) + (sum-iter (fix:+ total count) (fix:+ count 1) maxcount))) (sum-iter 0 1 n)) ; Recursive summation. Use this to compare with tail call ; optimized iterative algorithm. (define (sum-recurse n) - (if (= n 0) + (if (fix:= n 0) 0 - (+ n (sum-recurse (- n 1))))) + (fix:+ n (sum-recurse (fix:- n 1))))) + + +;; MISC + +(define (license) + (display +"This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see http://www.gnu.org/licenses/. +")) + +(define (welcome) + (display +"Welcome to scheme.forth.jl! + +Copyright (C) 2016 Tim Vaughan. +This program comes with ABSOLUTELY NO WARRANTY; for details type '(license)'. +Use Ctrl-D to exit. +"))