Formatting predefined functions
parent
48a07bfa6c
commit
a150c649c7
|
@ -334,7 +334,8 @@ y
|
|||
|
||||
**Internal Definitions.** When a *BODY* begins with a sequence of `define` constructs, they are known as "internal definitions" and are interpreted a little differently from top-level definitions. Specifically, they work like [letrec](https://wizardforcel.gitbooks.io/sicp-in-python/content/21.html#letrec) does.
|
||||
|
||||
\> *First, bindings are created for all the names defined by the `define` statements, initially bound to undefined values. >* Then the values are filled in by the defines.
|
||||
* First, bindings are created for all the names defined by the `define` statements, initially bound to undefined values.
|
||||
* Then the values are filled in by the defines.
|
||||
|
||||
As a result, a sequence of internal function definitions can be mutually recursive, just as `def` statements in Python that are nested inside a function can be:
|
||||
|
||||
|
@ -355,17 +356,174 @@ As a result, a sequence of internal function definitions can be mutually recursi
|
|||
|
||||
**Predefined Functions.** There is a large collection of predefined functions, all bound to names in the global environment, and we'll simply illustrate a few here; the rest are catalogued in the [Revised(4) Scheme](http://people.csail.mit.edu/jaffer/r4rs_toc.html) Report. Function calls are not "special" in that they all use the same completely uniform evaluation rule: recursively evaluate all items (including the operator), and then apply the operator's value (which must be a function) to the operands' values.
|
||||
|
||||
\> ***Arithmetic:** Scheme provides the standard arithmetic operators, many with familiar denotations, although the operators uniformly appear before the operands: >
|
||||
\>
|
||||
\>
|
||||
\> ``` > >>> ; Semicolons introduce one-line comments. > >>> ; Compute (3+7+10)*(1000-8) // 992 - 17 > >>> (- (quotient ( *(+ 3 7 10) (- 1000 8))) 17) > 3 > >>> (remainder 27 4) > 3 > >>> (- 17) > -17 >
|
||||
\> `> > > > Similarly, there are the usual numeric comparison operators, extended to allow more than two operands: > > > > >` > > >>> (< 0 5) > > #t > > >>> (>= 100 10 10 0) > > #t > > >>> (= 21 (* 7 3) (+ 19 2)) > > #t > > >>> (not (= 15 14)) > > #t > > >>> (zero? (- 7 7)) > > #t > > > > `> > > > `not`, by the way, is a function, not a special form like `and` or `or`, because its operand must always be evaluated, and so needs no special treatment. > > > * **Lists and Pairs:** A large number of operations deal with pairs and lists (which again are built of pairs and empty lists): > > > >` > >>> (cons 'a 'b) > (a . b) > >>> (list 'a 'b) > (a b) > >>> (cons 'a (cons 'b '())) > (a b) > >>> (car (cons 'a 'b)) > a > >>> (cdr (cons 'a 'b)) > b > >>> (cdr (list a b)) > (b) > >>> (cadr '(a b)) ; An abbreviation for (car (cdr '(a b))) > b > >>> (cddr '(a b)) ; Similarly, an abbreviation for (cdr (cdr '(a b))) > () > >>> (list-tail '(a b c) 0) > (a b c) > >>> (list-tail '(a b c) 1) > (b c) > >>> (list-ref '(a b c) 0) > a > >>> (list-ref '(a b c) 2) > c > >>> (append '(a b) '(c d) '() '(e)) > (a b c d e) > >>> ; All but the last list is copied. The last is shared, so: > >>> (define L1 (list 'a 'b 'c)) > >>> (define L2 (list 'd)) > >>> (define L3 (append L1 L2)) > >>> (set-car! L1 1) > >>> (set-car! L2 2) > >>> L3 > (a b c 2) > >>> (null? '()) > #t > >>> (list? '()) > #t > >>> (list? '(a b)) > #t > >>> (list? '(a . b)) > #f >
|
||||
\> `> > > * **Equivalence:** The `=` operation is for numbers. For general equality of values, Scheme distinguishes `eq?` (like Python's `is`), `eqv?` (similar, but is the same as `=` on numbers), and `equal?` (compares list structures and strings for content). Generally, we use `eqv?` or `equal?`, except in cases such as comparing symbols, booleans, or the null list: > > > >` > >>> (eqv? 'a 'a) > #t > >>> (eqv? 'a 'b) > #f > >>> (eqv? 100 (+ 50 50)) > #t > >>> (eqv? (list 'a 'b) (list 'a 'b)) > #f > >>> (equal? (list 'a 'b) (list 'a 'b)) > #t >
|
||||
\> `> > > * **Types:** Each type of value satisfies exactly one of the basic type predicates: > > > >` > >>> (boolean? #f) > #t > >>> (integer? 3) > #t > >>> (pair? '(a b)) > #t > >>> (null? '()) > #t > >>> (symbol? 'a) > #t > >>> (procedure? +) > #t >
|
||||
\> `> > > * **Input and Output:** Scheme interpreters typically run a read-eval-print loop, but one can also output things under explicit control of the program, using the same functions the interpreter does internally: > > > >` > >>> (begin (display 'a) (display 'b) (newline)) > ab >
|
||||
\> `> > > > Thus, `(display x)` is somewhat akin to Python's > > > > > `print(str(x), end="")` > > > > and `(newline)` is like `print()`. > > > > For input, the `(read)` function reads a Scheme expression from the current "port". It does _not_ interpret the expression, but rather reads it as data: > > > >` > >>> (read) > >>> (a b c) > (a b c) >
|
||||
\> `> > > * **Evaluation:** The `apply` function provides direct access to the function-calling operation: > > > > >` > > >>> (apply cons '(1 2)) > > (1 . 2) > > >>> ;; Apply the function f to the arguments in L after g is > > >>> ;; applied to each of them > > >>> (define (compose-list f g L) > > ... (apply f (map g L))) > > >>> (compose-list + (lambda (x) (* x x)) '(1 2 3)) > > 14 > > > > `> > > > An extension allows for some "fixed" arguments at the beginning: > > > > >` > > >>> (apply + 1 2 '(3 4 5)) > > 15 > > > > `> > > > The following function is not in [Revised(4) Scheme](http://people.csail.mit.edu/jaffer/r4rs_toc.html), but is present in our versions of the interpreter (_warning:_ a non-standard procedure that is not defined this way in later versions of Scheme): > > > >` > >>> (eval '(+ 1 2)) > 3 >
|
||||
\> `> > > > That is, `eval` evaluates a piece of Scheme data that represents a correct Scheme expression. This version evaluates its expression argument in the global environment. Our interpreter also provides a way to specify a specific environment for the evaluation: > > > > >` > > >>> (define (incr n) (lambda (x) (+ n x))) > > >>> (define add5 (incr 5)) > > >>> (add5 13) > > 18 > > >>> (eval 'n (procedure-environment add5)) > > 5 > > > > ```
|
||||
* **Arithmetic:** Scheme provides the standard arithmetic operators, many with familiar denotations, although the operators uniformly appear before the operands:
|
||||
|
||||
```
|
||||
>>> ; Semicolons introduce one-line comments.
|
||||
>>> ; Compute (3+7+10)*(1000-8) // 992 - 17
|
||||
>>> (- (quotient (* (+ 3 7 10) (- 1000 8))) 17)
|
||||
3
|
||||
>>> (remainder 27 4)
|
||||
3
|
||||
>>> (- 17)
|
||||
-17
|
||||
```
|
||||
|
||||
    Similarly, there are the usual numeric comparison operators, extended to allow more than two operands:
|
||||
|
||||
```
|
||||
>>> (< 0 5)
|
||||
#t
|
||||
>>> (>= 100 10 10 0)
|
||||
#t
|
||||
>>> (= 21 (* 7 3) (+ 19 2))
|
||||
#t
|
||||
>>> (not (= 15 14))
|
||||
#t
|
||||
>>> (zero? (- 7 7))
|
||||
#t
|
||||
|
||||
```
|
||||
|
||||
    `not`, by the way, is a function, not a special form like `and` or `or`, because its operand must always be evaluated, and so needs no special treatment.
|
||||
|
||||
* **Lists and Pairs:** A large number of operations deal with pairs and lists (which again are built of pairs and empty lists):
|
||||
|
||||
```
|
||||
>>> (cons 'a 'b)
|
||||
(a . b)
|
||||
>>> (list 'a 'b)
|
||||
(a b)
|
||||
>>> (cons 'a (cons 'b '()))
|
||||
(a b)
|
||||
>>> (car (cons 'a 'b))
|
||||
a
|
||||
>>> (cdr (cons 'a 'b))
|
||||
b
|
||||
>>> (cdr (list a b))
|
||||
(b)
|
||||
>>> (cadr '(a b)) ; An abbreviation for (car (cdr '(a b)))
|
||||
b
|
||||
>>> (cddr '(a b)) ; Similarly, an abbreviation for (cdr (cdr '(a b)))
|
||||
()
|
||||
>>> (list-tail '(a b c) 0)
|
||||
(a b c)
|
||||
>>> (list-tail '(a b c) 1)
|
||||
(b c)
|
||||
>>> (list-ref '(a b c) 0)
|
||||
a
|
||||
>>> (list-ref '(a b c) 2)
|
||||
c
|
||||
>>> (append '(a b) '(c d) '() '(e))
|
||||
(a b c d e)
|
||||
>>> ; All but the last list is copied. The last is shared, so:
|
||||
>>> (define L1 (list 'a 'b 'c))
|
||||
>>> (define L2 (list 'd))
|
||||
>>> (define L3 (append L1 L2))
|
||||
>>> (set-car! L1 1)
|
||||
>>> (set-car! L2 2)
|
||||
>>> L3
|
||||
(a b c 2)
|
||||
>>> (null? '())
|
||||
#t
|
||||
>>> (list? '())
|
||||
#t
|
||||
>>> (list? '(a b))
|
||||
#t
|
||||
>>> (list? '(a . b))
|
||||
#f
|
||||
```
|
||||
|
||||
* **Equivalence:** The `=` operation is for numbers. For general equality of values, Scheme distinguishes `eq?` (like Python's `is`), `eqv?` (similar, but is the same as = on numbers), and `equal?` (compares list structures and strings for content). Generally, we use `eqv?` or `equal?`, except in cases such as comparing symbols, booleans, or the null list:
|
||||
|
||||
```
|
||||
>>> (eqv? 'a 'a)
|
||||
#t
|
||||
>>> (eqv? 'a 'b)
|
||||
#f
|
||||
>>> (eqv? 100 (+ 50 50))
|
||||
#t
|
||||
>>> (eqv? (list 'a 'b) (list 'a 'b))
|
||||
#f
|
||||
>>> (equal? (list 'a 'b) (list 'a 'b))
|
||||
#t
|
||||
```
|
||||
|
||||
* **Types:** Each type of value satisfies exactly one of the basic type predicates:
|
||||
|
||||
```
|
||||
>>> (boolean? #f)
|
||||
#t
|
||||
>>> (integer? 3)
|
||||
#t
|
||||
>>> (pair? '(a b))
|
||||
#t
|
||||
>>> (null? '())
|
||||
#t
|
||||
>>> (symbol? 'a)
|
||||
#t
|
||||
>>> (procedure? +)
|
||||
#t
|
||||
```
|
||||
|
||||
* **Input and Output:** Scheme interpreters typically run a read-eval-print loop, but one can also output things under explicit control of the program, using the same functions the interpreter does internally:
|
||||
|
||||
```
|
||||
>>> (begin (display 'a) (display 'b) (newline))
|
||||
ab
|
||||
```
|
||||
|
||||
    Thus, `(display x)` is somewhat akin to Python's
|
||||
|
||||
    ```print(str(x), end="")```
|
||||
|
||||
    and `(newline)` is like `print()`.
|
||||
|
||||
    For input, the `(read)` function reads a Scheme expression from the current "port". It *does not* interpret the expression, but rather reads it as data:
|
||||
|
||||
```
|
||||
>>> (read)
|
||||
>>> (a b c)
|
||||
(a b c)
|
||||
```
|
||||
|
||||
* **Evaluation:** The apply function provides direct access to the function-calling operation:
|
||||
|
||||
```
|
||||
>>> (apply cons '(1 2))
|
||||
(1 . 2)
|
||||
>>> ;; Apply the function f to the arguments in L after g is
|
||||
>>> ;; applied to each of them
|
||||
>>> (define (compose-list f g L)
|
||||
... (apply f (map g L)))
|
||||
>>> (compose-list + (lambda (x) (* x x)) '(1 2 3))
|
||||
14
|
||||
```
|
||||
|
||||
    An extension allows for some "fixed" arguments at the beginning:
|
||||
|
||||
```
|
||||
>>> (apply + 1 2 '(3 4 5))
|
||||
15
|
||||
```
|
||||
|
||||
    The following function is not in [Revised(4)](http://people.csail.mit.edu/jaffer/r4rs_toc.html) Scheme, but is present in our versions of the interpreter (*warning*: a non-standard procedure that is not defined this way in later versions of Scheme):
|
||||
|
||||
```
|
||||
>>> (eval '(+ 1 2))
|
||||
3
|
||||
```
|
||||
|
||||
    That is, eval evaluates a piece of Scheme data that represents a correct Scheme expression. This version evaluates its expression argument in the global environment. Our interpreter also provides a way to specify a specific environment for the evaluation:
|
||||
|
||||
```
|
||||
>>> (define (incr n) (lambda (x) (+ n x)))
|
||||
>>> (define add5 (incr 5))
|
||||
>>> (add5 13)
|
||||
18
|
||||
>>> (eval 'n (procedure-environment add5))
|
||||
5
|
||||
```
|
||||
|
||||
### 3.6.2 The Logo Language
|
||||
|
||||
|
|
Loading…
Reference in New Issue