diff options
Diffstat (limited to 'CHICKEN.html.markdown')
| -rw-r--r-- | CHICKEN.html.markdown | 519 | 
1 files changed, 519 insertions, 0 deletions
| diff --git a/CHICKEN.html.markdown b/CHICKEN.html.markdown new file mode 100644 index 00000000..bb2f91f0 --- /dev/null +++ b/CHICKEN.html.markdown @@ -0,0 +1,519 @@ +--- +language: "CHICKEN" +filename: CHICKEN.scm +contributors: +  - ["Diwakar Wagle", "https://github.com/deewakar"] +--- + + +CHICKEN is an implementation of Scheme programming language that can +compile Scheme programs to C code as well as interpret them. CHICKEN +supports R5RS and R7RS (work in progress) standards and many extensions. + + +```scheme +;; #!/usr/bin/env csi -s + +;; Run the CHICKEN REPL in the commandline as follows : +;; $ csi + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; 0. Syntax +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Single line comments start with a semicolon + +#| Block comments +   can span multiple lines and... +   #| can be nested +   |# +|# + +;; S-expression comments are used to comment out expressions +#; (display "nothing")    ; discard this expression  + +;; CHICKEN has two fundamental pieces of syntax: Atoms and S-expressions +;; an atom is something that evaluates to itself +;; all builtin data types viz. numbers, chars, booleans, strings etc. are atoms +;; Furthermore an atom can be a symbol, an identifier, a keyword, a procedure +;; or the empty list (also called null) +'athing              ;; => athing  +'+                   ;; => +  ++                    ;; => <procedure C_plus> + +;; S-expressions (short for symbolic expressions) consists of one or more atoms +(quote +)            ;; => + ; another way of writing '+ +(+ 1 2 3)            ;; => 6 ; this S-expression evaluates to a function call +'(+ 1 2 3)           ;; => (+ 1 2 3) ; evaluates to a list  + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; 1. Primitive Datatypes and Operators  +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Numbers +99999999999999999999 ;; integers +#b1010               ;; binary ; => 10 +#o10                 ;; octal  ; => 8 +#x8ded               ;; hexadecimal ; => 36333 +3.14                 ;; real +6.02e+23 +3/4                  ;; rational + +;;Characters and Strings +#\A                  ;; A char +"Hello, World!"      ;; strings are fixed-length arrays of characters + +;; Booleans +#t                  ;; true +#f                  ;; false + +;; Function call is written as (f x y z ...) +;; where f is a function and x,y,z, ... are arguments +(print "Hello, World!")    ;; => Hello, World! +;; formatted output +(printf "Hello, ~a.\n" "World")  ;; => Hello, World. + +;; print commandline arguments +(map print (command-line-arguments))  + +(list 'foo 'bar 'baz)          ;; => (foo bar baz) +(string-append "pine" "apple") ;; => "pineapple" +(string-ref "tapioca" 3)       ;; => #\i;; character 'i' is at index 3 +(string->list "CHICKEN")       ;; => (#\C #\H #\I #\C #\K #\E #\N) +(string->intersperse '("1" "2") ":") ;; => "1:2" +(string-split "1:2:3" ":")     ;; => ("1" "2" "3") + + +;; Predicates are special functions that return boolean values +(atom? #t)                ;; => #t + +(symbol? #t)              ;; => #f + +(symbol? '+)              ;; => #t + +(procedure? +)            ;; => #t + +(pair? '(1 2))            ;; => #t + +(pair? '(1 2 . 3))        ;; => #t + +(pair? '())               ;; => #f + +(list? '())               ;; => #t + + +;; Some arithmetic operations + +(+ 1 1)                   ;; => 2 +(- 8 1)                   ;; => 7 +(* 10 2)                  ;; => 20 +(expt 2 3)                ;; => 8 +(remainder 5 2)           ;; => 1 +(/ 35 5)                  ;; => 7 +(/ 1 3)                   ;; => 0.333333333333333 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; 2. Variables +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; You can create variables with define +;; A variable name can use any character except: ()[]{}",'`;#\ +(define myvar 5) +myvar        ;; => 5 + +;; Alias to a procedure +(define ** expt) +(** 2 3)     ;; => 8 + +;; Accessing an undefined variable raises an exception +s            ;; => Error: unbound variable: s + +;; Local binding +(let ((me "Bob")) +  (print me))     ;; => Bob + +(print me)        ;; => Error: unbound variable: me + +;; Assign a new value to previously defined variable +(set! myvar 10)  +myvar             ;; => 10 + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; 3. Collections +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Pairs +;; 'cons' constructs pairs,  +;; 'car' extracts the first element, 'cdr' extracts the rest of the elements +(cons 'subject 'verb)       ;; => '(subject . verb) +(car (cons 'subject 'verb)) ;; => subject +(cdr (cons 'subject 'verb)) ;; => verb + +;; Lists +;; cons creates a new list if the second item is a list +(cons 0 '())         ;; => (0) +(cons 1 (cons 2  (cons 3 '())))    ;; => (1 2 3) +;; 'list' is a convenience variadic constructor for lists +(list 1 2 3)    ;; => (1 2 3) + + +;; Use 'append' to append lists together +(append '(1 2) '(3 4)) ;; => (1 2 3 4) + +;; Some basic operations on lists +(map add1 '(1 2 3))    ;; => (2 3 4) +(reverse '(1 3 4 7))   ;; => (7 4 3 1) +(sort '(11 22 33 44) >)   ;; => (44 33 22 11) + +(define days '(SUN MON FRI)) +(list-ref days 1)      ;; => MON +(set! (list-ref days 1) 'TUE) +days                   ;; => (SUN TUE FRI) + +;; Vectors +;; Vectors are heterogeneous structures whose elements are indexed by integers +;; A Vector typically occupies less space than a list of the same length +;; Random access of an element in a vector is faster than in a list +#(1 2 3)                     ;; => #(1 2 3) ;; literal syntax +(vector 'a 'b 'c)            ;; => #(a b c)  +(vector? #(1 2 3))           ;; => #t +(vector-length #(1 (2) "a")) ;; => 3 +(vector-ref #(1 (2) (3 3)) 2);; => (3 3) + +(define vec #(1 2 3)) +(vector-set! vec 2 4) +vec                         ;; => #(1 2 4) + +;; Vectors can be created from lists and vice-verca +(vector->list #(1 2 4))     ;; => '(1 2 4) +(list->vector '(a b c))     ;; => #(a b c) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; 4. Functions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Use 'lambda' to create functions. +;; A function always returns the value of its last expression +(lambda () "Hello World")   ;; => #<procedure (?)>  + +;; Use extra parens around function definition to execute  +((lambda () "Hello World")) ;; => Hello World ;; argument list is empty + +;; A function with an argument +((lambda (x) (* x x)) 3)           ;; => 9 +;; A function with two arguments +((lambda (x y) (* x y)) 2 3)       ;; => 6 + +;; assign a function to a variable +(define sqr (lambda (x) (* x x))) +sqr                        ;; => #<procedure (sqr x)> +(sqr 3)                    ;; => 9 + +;; We can shorten this using the function definition syntactic sugar +(define (sqr x) (* x x)) +(sqr 3)                    ;; => 9 + +;; We can redefine existing procedures +(foldl cons '() '(1 2 3 4 5)) ;; => (((((() . 1) . 2) . 3) . 4) . 5) +(define (foldl func accu alist) +  (if (null? alist) +    accu +    (foldl func (func (car alist) accu) (cdr alist)))) + +(foldl cons '() '(1 2 3 4 5))   ;; => (5 4 3 2 1) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; 5. Equality +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; For numbers use '=' +(= 3 3.0)                  ;; => #t +(= 2 1)                    ;; => #f + +;; 'eq?' returns #t if two arguments refer to the same object in memory +;; In other words, it's a simple pointer comparison. +(eq? '() '())              ;; => #t ;; there's only one empty list in memory +(eq? (list 3) (list 3))    ;; => #f ;; not the same object +(eq? 'yes 'yes)            ;; => #t +(eq? 3 3)                  ;; => #t ;; don't do this even if it works in this case +(eq? 3 3.0)                ;; => #f ;; it's better to use '=' for number comparisons +(eq? "Hello" "Hello")      ;; => #f + +;; 'eqv?' is same as 'eq?' all datatypes except numbers and characters +(eqv? 3 3.0)               ;; => #f +(eqv? (expt 2 3) (expt 2 3)) ;; => #t +(eqv? 'yes 'yes)           ;; => #t + +;; 'equal?' recursively compares the contents of pairs, vectors, and strings, +;; applying eqv? on other objects such as numbers and symbols.  +;; A rule of thumb is that objects are generally equal? if they print the same. + +(equal? '(1 2 3) '(1 2 3)) ;; => #t +(equal? #(a b c) #(a b c)) ;; => #t +(equal? 'a 'a)             ;; => #t +(equal? "abc" "abc")       ;; => #t + +;; In Summary: +;; eq? tests if objects are identical +;; eqv? tests if objects are operationally equivalent +;; equal? tests if objects have same structure and contents + +;; Comparing strings for equality +(string=? "Hello" "Hello") ;; => #t + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; 6. Control Flow +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Conditionals +(if #t                     ;; test expression +  "True"                   ;; then expression +  "False")                 ;; else expression +                           ;; => "True" + +(if (> 3 2) +  "yes" +  "no")                    ;; => "yes" + +;; In conditionals, all values that are not '#f' are treated as true. +;; 0, '(), #() "" , are all true values +(if 0 +  "0 is not false" +  "0 is false")            ;; => "0 is not false" + +;; 'cond' chains a series of tests and returns as soon as it encounters a true condition +;; 'cond' can be used to simulate 'if/elseif/else' statements +(cond ((> 2 2) "not true so don't return this") +      ((< 2 5) "true, so return this") +      (else "returning default"))    ;; => "true, so return this" + + +;; A case expression is evaluated as follows: +;; The key is evaluated and compared with each datum in sense of 'eqv?', +;; The corresponding clause in the matching datum is evaluated and returned as result +(case (* 2 3)              ;; the key is 6 +  ((2 3 5 7) 'prime)       ;; datum 1 +  ((1 4 6 8) 'composite))  ;; datum 2; matched! +                           ;; => composite + +;; case with else clause +(case (car '(c d)) +  ((a e i o u) 'vowel) +  ((w y) 'semivowel) +  (else 'consonant))       ;; =>  consonant + +;; Boolean expressions +;; 'and' returns the first expression that evaluates to #f +;; otherwise, it returns the result of the last expression +(and #t #f (= 2 2.0))                ;; => #f +(and (< 2 5) (> 2 0) "0 < 2 < 5")    ;; => "0 < 2 < 5" + +;; 'or' returns the first expression that evaluates to #t  +;; otherwise the result of the last expression is returned +(or #f #t #f)                        ;; => #t +(or #f #f #f)                        ;; => #f + +;; 'when' is like 'if' without the else expression +(when (positive? 5) "I'm positive")  ;; => "I'm positive" + +;; 'unless' is equivalent to (when (not <test>) <expr>) +(unless (null? '(1 2 3)) "not null") ;; => "not null" + + +;; Loops +;; loops can be created with the help of tail-recursions +(define (loop count) +  (unless (= count 0) +    (print "hello")  +    (loop (sub1 count)))) +(loop 4)                             ;; => hello, hello ... + +;; Or with a named let +(let loop ((i 0) (limit 5)) +  (when (< i limit) +    (printf "i = ~a\n" i) +    (loop (add1 i) limit)))          ;; => i = 0, i = 1.... + +;; 'do' is another iteration construct +;; It initializes a set of variables and updates them in each iteration +;; A final expression is evaluated after the exit condition is met +(do ((x 0 (add1 x )))            ;; initialize x = 0 and add 1 in each iteration +  ((= x 10) (print "done"))      ;; exit condition and final expression +  (print x))                     ;; command to execute in each step +                                 ;; => 0,1,2,3....9,done + +;; Iteration over lists  +(for-each (lambda (a) (print (* a a))) +          '(3 5 7))                  ;; => 9, 25, 49 + +;; 'map' is like for-each but returns a list +(map add1 '(11 22 33))               ;; => (12 23 34) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; 7. Extensions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; The CHICKEN core is very minimal, but additional features are provided by library extensions known as Eggs. +;; You can install Eggs with 'chicken-install <eggname>' command. + +;; 'numbers' egg provides support for full numeric tower. +(require-extension numbers) +;; complex numbers +3+4i                               ;; => 3+2i +;; Supports fractions without falling back to inexact flonums +1/3                                ;; => 1/3 +;; provides support for large integers through bignums +(expt 9 20)                        ;; => 12157665459056928801  +;; And other 'extended' functions +(log 10 (exp 1))                   ;; => 2.30258509299405 +(numerator 2/3)                    ;; => 2 + +;; 'utf8' provides unicode support +(require-extension utf8) +"\u03BBx:(\u03BC\u0251.\u0251\u2192\u0251).xx" ;; => "λx:(μɑ.ɑ→ɑ).xx" + +;; 'posix' provides file I/O and lots of other services for unix-like operating systems +;; Some of the functions are not available in Windows system, +;; See http://wiki.call-cc.org/man/4/Unit%20posix for more details + +;; Open a file to append, open "write only" and create file if it does not exist +(define outfn (file-open "chicken-hen.txt" (+ open/append open/wronly open/creat))) +;; write some text to the file +(file-write outfn "Did chicken came before hen?")  +;; close the file +(file-close outfn) +;; Open the file "read only" +(define infn (file-open "chicken-hen.txt" open/rdonly)) +;; read some text from the file +(file-read infn 30)         ;; => ("Did chicken came before hen?  ", 28) +(file-close infn) + +;; CHICKEN also supports SRFI (Scheme Requests For Implementation) extensions +;; See 'http://srfi.schemers.org/srfi-implementers.html" to see srfi's supported by CHICKEN +(require-extension srfi-1)         ;; list library +(filter odd? '(1 2 3 4 5 6 7))     ;; => (1 3 5 7) +(count even? '(1 2 3 4 5))         ;; => 2 +(take '(12 24 36 48 60) 3)         ;; => (12 24 36) +(drop '(12 24 36 48 60) 2)         ;; => (36 48 60) +(circular-list 'z 'q)              ;; => z q z q ... + +(require-extension srfi-13)        ;; string library +(string-reverse "pan")             ;; => "nap" +(string-index "Turkey" #\k)        ;; => 3 +(string-every char-upper-case? "CHICKEN") ;; => #t +(string-join '("foo" "bar" "baz") ":")    ;; => "foo:bar:baz" + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; 8. Macros +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; A 'for .. in ..' iteration like python, for lists +(define-syntax for +  (syntax-rules (in) +                ((for elem in alist body ...) +                 (for-each (lambda (elem) body ...) alist)))) + +(for x in '(2 4 8 16) +     (print x))          ;; => 2, 4, 8, 16 + +(for chr in (string->list "PENCHANT") +     (print chr))        ;; => P, E, N, C, H, A, N, T + +;; While loop +(define-syntax while +  (syntax-rules () +                ((while cond body ...) +                 (let loop () +                   (when cond +                     body ... +                     (loop)))))) + +(let ((str "PENCHANT") (i 0)) +  (while (< i (string-length str))     ;; while (condition) +         (print (string-ref str i))    ;; body  +         (set! i (add1 i))))            +                                       ;; => P, E, N, C, H, A, N, T + +;; Advanced Syntax-Rules Primer -> http://petrofsky.org/src/primer.txt +;; Macro system in chicken -> http://lists.gnu.org/archive/html/chicken-users/2008-04/msg00013.html + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; 9. Modules +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Also See http://wiki.call-cc.org/man/4/Modules + +;; The 'test' module exports a value named 'hello' and a macro named 'greet' +(module test (hello greet) +  (import scheme) + +  (define-syntax greet +    (syntax-rules () +      ((_ whom)  +       (begin +         (display "Hello, ") +         (display whom) +         (display " !\n") ) ) ) ) + +  (define (hello) +    (greet "world") )  ) + +;; we can define our modules in a separate file (say test.scm) and load them to the interpreter with +;;         (load "test.scm") + +;; import the module +(import test) +(hello)                ;; => Hello, world ! +(greet "schemers")     ;; => Hello, schemers ! + +;; We can compile the module files in to shared libraries by using following command, +;;         csc -s test.scm +;;         (load "test.so") + +;; Functors +;; Functors are high level modules that can be parameterized by other modules +;; Following functor requires another module named 'M' that provides a function called 'multiply' +;; The functor itself exports a generic function 'square' +(functor (squaring-functor (M (multiply))) (square) +         (import scheme M)  +         (define (square x) (multiply x x))) + +;; Module 'nums' can be passed as a parameter to 'squaring-functor' +(module nums (multiply)  +        (import scheme)     ;; predefined modules +        (define (multiply x y) (* x y)))  +;; the final module can be imported and used in our program +(module number-squarer = (squaring-functor nums))  + +(import number-squarer) +(square 3)              ;; => 9 + +;; We can instantiate the functor for other inputs +;; Here's another example module that can be passed to squaring-functor +(module stars (multiply) +        (import chicken scheme)  ;; chicken module for the 'use' keyword +        (use srfi-1)             ;; we can use external libraries in our module +        (define (multiply x y) +          (list-tabulate x (lambda _ (list-tabulate y (lambda _ '*)))))) +(module star-squarer = (squaring-functor stars)) + +(import star-squarer) +(square 3)              ;; => ((* * *)(* * *)(* * *)) + +``` +## Further Reading +* [CHICKEN User's Manual](http://wiki.call-cc.org/man/4/The%20User%27s%20Manual). +* [R5RS standards](http://www.schemers.org/Documents/Standards/R5RS) + + +## Extra Info + +* [For programmers of other languages](http://wiki.call-cc.org/chicken-for-programmers-of-other-languages) +* [Compare CHICKEN syntax with other languages](http://plr.sourceforge.net/cgi-bin/plr/launch.py) | 
