(+ 3 4)If I wanted to write an arithmetic expression like (a + 10) * (b - 20), I would write:
(* (+ a 10) (- b 20))A function call has a similar syntax. If I want to call the function avg on three variables, I would write:
(avg x y z)Although prefix notation takes some getting used to, it does have an advantage of conciseness when writing out an arithmetic expression involving the same operator. For example, the sum (a + b + c + x + y + z) can be concisely specified as:
(+ a b c x y z)
; add two numbers (+ 3 7) ; the result is 10In imperative languages semi-colons frequently delimit statements, but right parentheses perform this function in Scheme.
(display "The result is ") (display (+ 3 4)) (newline)
I typically use a combination of the trace function and display statements to debug my scheme programs.
gsiYou can now start typing expressions and it will immediately print the result:
(+ 3 4) 7 (/ (+ 8 10 10) 3) 28 / 3 ; Lisp supports rational numbersIf you make a mistake, such as typing an undefined variable, you will see something like:
> a *** ERROR IN (console)@1.1 -- Unbound variable: a 1>Type ,t to get back to the main prompt.
To quit the interpreter you can from the main prompt type any of the following: ,q, (exit), or Ctrl-D.
You may load programs from a file using the load function:
(load "qsort.scm") ; .scm is the common Scheme suffixEach time you load "qsort.scm", it will evaluate all the expressions in "qsort.scm" and update any previously declared bindings with the new results. In particular, previous function definitions will be overwritten with new function definitions, and hence it is unnecessary to exit the scheme interpreter if you want to fix a program. Instead you edit the file and then reload it.
(list 3 8 10) (list "brad" 7 #t (list 5 8) (list 4 3.2 #t)) (list) ; the empty listAs you can see, lists can contain heterogenous values and may be nested. The list keyword can be a bit verbose, and so you can also create lists by quoting them:
'(3 8 10) '("brad" 7 #t (5 8) (4 3.2 #t)) '() ; the empty listThere is one important distinction between creating a list using a quote versus creating a list using the list command. If you use the list command, then all executable expressions will be evaluated, whereas if you use a quote to create the list, then the executable expressions will not be evaluated and instead the individual components of the expression will appear as symbols in the created list. For example:
(list (+ 4 5) (+ 3 8)) ; creates the list '(9 11) '((+ 4 5) (+ 3 8)) ; creates the list '((+ 4 5) (+ 3 8))
----- ----- ----- | | |-->| | |-->| |/| ----- ----- ----- | | | 3 8 10Primitive elements, such as numbers or strings, are often called atoms. You can also create a cons cell consisting of two atoms using the cons command:
(cons 6 8)which will be displayed by the scheme interpreter as (6 . 8). Such a cons cell is often called an improper list. A proper list always ends with a nil (empty) list. In other words, in a proper list, the final cons cell has a null pointer as its second element.
(cons '8 '(10)) ==> (8 10) ; the list consisting of 8 and 10 (append '(10 15) '(8) '(6 10 14)) ==> '(10 15 8 6 10 14)
(car '(8 10 15)) ==> 8 ; the first element of the list (cdr '(8 10 15)) ==> '(10 15) ; the rest of the list (car '()) ==> ERROR ; the empty list has no elements (cdr '()) ==> ERROR ; the empty list has no elements (cdr '(10)) ==> '() ; the empty list '() (first '(8 10 15)) ==> 8 (second '(8 10 15)) ==> 10
(list? (cons 3 '())) ; returns #t
(memq 3 '(6 3 4)) ; returns #t (memq 8 '(6 3 4)) ; returns #fmemq uses the eq? function to compare elements, memv uses the eqv? function to compare elements, and member uses the equal? function to compare elements. Click here for more details about the eq?, eqv?, and equal? functions.
(define a '(("brad" 3) ("nels" 6) ("summer" 10)))You can return the pair associated with a key in an association list by using the assoc function:
(assoc "summer" a) ; returns ("summer" 10)assoc uses the equal? function to check for equality. You can also use assq or assv, which will use the eq? and eqv? functions respectively to check for equality.
(define a 10) (define name "brad")
(let ((a 10) (b 7)) (+ a b)) ; result is 17let can be thought of as introducing a block with the indicated bindings. The bindings are "live" within the let statement and any nested let statements that do not override the binding.
(let ((a 10) (b (* a 5))) ; illegal: b is not allowed to use the value of a ...)because b depends on a having already been evaluated
(let () (display "The result is ") (display (+ 3 4)) (newline) )
(let* ((a 10) (b (* a 5))) ; b is 50 (+ a b)) ; result is 60
(if (< a 0) 0 a)The first argument is a boolean expression that should evaluate to a boolean value. The second and third arguments are the "then" and "else" expressions
(cond ((and (< grade 100) (>= grade 90)) "A") ((> grade 80) "B") ((> grade 70) "C") (else "B"))
(lambda (x) (* x x)) ; a function that computes x2lambda creates an anonymous function object. For it to be useful you usually bind it to a name using either a define or a let statement. For example:
(define x2 (lambda (x) (* x x)))
(letrec ((fact (lambda (n) (if (or (= n 0) (= n 1)) 1 (* n (fact (- n 1))))))) (fact 5)) ; result is 120