您的位置:首页 > 其它

学习scheme的笔记

2015-08-05 11:19 411 查看
1 . write *.ss file with you editor

reciprocal.ss file:

define reciprocal
(lambda (n)
(if (= n 0)
"oops!"
(/ 1 n))))


2 . start petite and use reciprocal procedure

(load "~/scheme/reciprocal.ss")
> (reciprocal 0)
"oops!"
> (reciprocal 2)
1/2


The expressions below are called procedure applications, because they specify the application of a procedure to a set of arguments.

+ 1/2 1/2) --> 1
(- 1.5 1/2) --> 1.0

(* 3 1/2) --> 3/2
(/ 1.5 3/4) --> 2.0


quote:

we must tell Scheme explicitly to treat a list as data rather than as a procedure application.

We do this with quote.

quote (1 2 3 4 5)) --> (1 2 3 4 5)
(quote ("this" "is" "a" "list")) --> ("this" "is" "a" "list")
(quote (+ 3 4)) --> (+ 3 4)


Because quote is required fairly frequently in Scheme code, Scheme recognizes a single quotation mark ( ’ ) preceding an expression as an abbreviation for quote.

(1 2 3 4) --> (1 2 3 4)
'((1 2) (3 4)) --> ((1 2) (3 4))
'(/ (* 2 -1) 3) --> (/ (* 2 -1) 3)


Just as quoting a list tells Scheme to treat a parenthesized form as a list rather than as a procedure application,

quoting an identifier tells Scheme to treat the identifier as a symbol rather than as a variable.

(quote hello)

car returns the first element of a list, and cdr returns the remainder of the list.

let:

The general form of a let expression is:

let ((var expr) ...) body1 body2 ...)


Scheme treats forms enclosed in brackets just like forms enclosed in parentheses. An open bracket must be matched by a close bracket, and an open parenthesis must be matched by a close parenthesis. We use brackets for let (and, as we’ll see, several other standard syntactic forms) to improve readability, especially when we might otherwise have two or more consecutive open parentheses.

let ([list1 '(a b c)] [list2 '(d e f)])
(cons (cons (car list1)
(car list2))
(cons (car (cdr list1))
(car (cdr list2))))) --> ((a . d) b . e)


Lambda:

The general form of a lambda expression is

(lambda (var ...) body1 body2 ...)

((lambda (x) (+ x x)) (* 3 4)) --> 24
(lambda (x) (+ x x)) --> is a procedure, (* 3 4) is the argument of this procedure

(let ([double (lambda (x) (+ x x))])
(list (double (* 3 4))
(double (/ 99 11))
(double (- 2 7)))) <graphic> (24 18 -10)


Here, we establish a binding for double to a procedure, then use this procedure to double three different values. 说白了,lambda就是一个有一个匿名函数,闭包就是一个有上下文的函数。

As mentioned above, the general form of lambda is a bit more complicated than the form we saw earlier, in that the formal parameter specification, (var …), need not be a proper list, or indeed even a list at all. The formal parameter specification can be in any of the following three forms:

a proper list of variables, (var1 … varn), such as we have already seen,

a single variable, varr, or

an improper list of variables, (var1 … varn . varr).

(let ([f (lambda x x)])
(f 1 2 3 4)) --> (1 2 3 4) #second case

(let ([f (lambda x x)])
(f)) --> () #second case

(let ([g (lambda (x . y) (list x y))])
(g 1 2 3 4)) --> (1 (2 3 4)) #third case

(let ([h (lambda (x y . z) (list x y z))])
(h 'a 'b 'c 'd)) --> (a b (c d)) #third case


Top-Level Definitions:

(define double-any
(lambda (f x)
(f x x)))

(define double-int
(lambda (x)
(+ x x)))


Conditional Expressions :

(define abs
(lambda (n)
(if (< n 0)
((- 0 n)
2)
n)))


closure:

> (define (foo x) (lambda (y) (* x y)))
> (define t2 (foo 2))
> t2
#<procedure>
> (t2 3)
6
> (t2 4)
8
> (define t10 (foo 10))
> t10
#<procedure>
> (t10 2)
20
> (t10 5)
50


currying:

假设你的函数需要两个参数,第一个是映射函数,第二个是具体的数据,你当然可以定义一个函数来一次性接收两个参数.

你也可以使用currying来包装你的函数,让程序one by one的来处理你的参数. 这只是语言的一种特性,每种特性都有利有弊.注意取舍.

> (define (my-map func)
(define (map1 ls)
(if (null? ls)
'()
(cons (func (car ls)) (map1 (cdr ls)))))
map1)
> (define foo (my-map (lambda (x) (* x x))))
> foo
#<procedure>
> (foo '(1 2 3 4 5))
(1 4 9 16 25)


generator:

闭包的一个应用

> (define (make-odd-gen)
(let ((prev-number -1))
(lambda ()
(set! prev-number (+ prev-number 2))
prev-number)))
> (define gen-odd-num1 (make-odd-gen))
> (gen-odd-num1)
1
> (gen-odd-num1)
3
> (gen-odd-num1)
5
> (define gen-odd-num2 (make-odd-gen))
> (gen-odd-num2)
1
> (gen-odd-num2)
3
> (gen-odd-num2)
5


macro:

(define-syntax m-square
(syntax-rules ()
((_ x) (* x x))))


**[S-exp] - evaluate –> [new s-exp] - evaluate –> return value of macro

macro expand**

the macro name is m-square

(_ x) 会匹配这样的s表达式:(m-square s-exp),所以如果输入是: (m-square (+ 1 2)) ,那么x就是 (+ 1 2),

所以最后宏展开会就是:

(* (+ 1 2) (+ 1 2))

> (define-syntax m-square
(syntax-rules ()
((_ x) (* x x))))
> (m-square (+ 1 2))
9
> (m-square (begin (display "oops") (+ 1 2)))
oopsoops9

> (define-syntax arithmetic-if
(syntax-rules ()
((_ test neg zero pos)
(let ((var test))
(cond ((< var 0) neg)
((= var 0) zero)
(else pos))))))
> (arithmetic-if -10 (+ 0 -1) (+ 0 0) (+ 0 1))
test neg zero pos
-1
> (arithmetic-if 10 (+ 0 -1) (+ 0 0) (+ 0 1))
1
> (arithmetic-if 0 (+ 0 -1) (+ 0 0) (+ 0 1))

macro with identifier:
> (define-syntax my-if
(syntax-rules (then else)
((_ test then e1 else e2) (if test e1 e2))
((_ test then e1) (if test e1 #f))
((_ test else e1) (if test #f e1))))
> (my-if #t then 'OK else 'NG)
OK
> (my-if #f then 'OK else 'NG)
NG
> (my-if #f then 'OK)
#f
> (my-if #t then 'OK)
OK
> (my-if #t else 'NG)
#f
> (my-if #f else 'NG)
NG


macro recursion:

> (define-syntax my-and
(syntax-rules ()
((_) #t)
((_ a) a)
((_ a b ...) (if a (my-and b ...) #f))))
> (my-and)
#t
> (my-and 1)
1
> (my-and 1 2)
2
> (my-and #f)
#f
> (my-and 1 #f)
#f
> (my-and 1 2 #f)
#f


Lazy evaluation:

> (define laz (delay (+ 1 2)))
> laz
#<procedure>
> (force laz)
3
> (* 10 (force laz))
30


http://www.geocities.jp/m_hiroi/func/abcscm10.html

https://www.shido.info/lisp/scheme7.html

http://www.scheme.com/tspl4/start.html#./start:h8
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: