随笔分类 - Scheme
摘要:默认的Racket是要对函数参数进行求值的, 例如(f 1 (+ 1 2))里面,(+ 1 2)要先求值为3,变为(f 1 3)再进行下一步操作.因此, Racket若按照SICP使用define关键字来定义延时计算的关键函数delay和cons-stream是不可行的, 需要用宏来定义,绕过求值....
阅读全文
摘要:(define (range n) (define (recur n) (if (= n -1) '() (cons n (recur (- n 1))))) (recur (- n 1)))(define (flatten a)...
阅读全文
摘要:目前尚不清楚实质,但已经能够从形式上理解它的某些好处,有个很简单的连乘函数可以说明:为了展示究竟发生了什么,我包装了下乘法函数,将其变为mul.我们将比较product和xproduct的区别.;包装乘法函数(define (mul x y) (display x) (display " * ") (display y) (newline) (* x y));常规版(define (product ls) (let f ((ls ls)) (cond ((null? ls) 1) ((= (car ls) 0) 0) (else (mul (...
阅读全文
摘要:> (define a '(1 2 3))> (define b (cons a '()))> b((1 2 3))> (set-car! (car b) 100)> b((100 2 3))> a(100 2 3)>从上面可以看到,(car b)和a是同一对象.这个实在是有些危险啊.如何让a和b能够相互独立呢?下面这个函数返回的list各成员和最初传入的list各成员又是相互独立的:;反序 (1 2 3) -> (3 2 1)(define (rvs x) (let recur ((x x)(res '())) (if
阅读全文
摘要:;反序 (1 2 3) -> (3 2 1)(define (rvs x) (let recur ((x x)(res '())) (if (null? x) res (recur (cdr x) (cons (car x) res)))));长度 (1 2 3) -> 3(define (len x) (let recur ((x x)(y 0)) (if (null? x) y (recur (cdr x) (+ y 1)))));合并列表 (x ...) (y ...) -> (x ... y ...)(define...
阅读全文
摘要:> (define (f x) x)> (define (g x) (let rec((x x)) x))> (define a '(1 2 3))> (f a)(1 2 3)> (eq? a (f a))#t> (eq? a (g a))#t> (define b (g a))> (set-car! b 10)> a(10 2 3)> 可见,g函数的定义中,named let并未深拷贝x的值,它只是建立传入参数的引用而已.那这也说明,如果一个函数所有参数在递归过程中都会发生改变,那么一般没必要用named let.又如:;切
阅读全文
摘要:用到的元素有9个:define,if,null?,cons car,cdr,lambda,let,named let,其实let 和 named let可以去掉.但那样会带来性能和可读性下降的问题.排序类型选的是经典的快速排序.;筛选函数(define (filter f x) (let recur ((x x)) (if (null? x) '() (if (f (car x)) (cons (car x) (recur (cdr x))) (recur (cdr x))))));三元合并函数,形如'(1 2) ...
阅读全文
摘要:重写过程中,发现这种做法能加深对递归的理解,而且reduce还体现了函数式编程是如何通过参数传递来实现命令式编程中的状态改变的.(define (imap f x . y) (if (null? y) (let recur ((x x)) (if (null? x) '() (cons (f (car x)) (recur (cdr x))))) (let recur ((x x) (y y)) (if (null? x) '() (cons...
阅读全文
摘要:procedure:(applyprocarg1...args)Procmust be a procedure andargsmust be a list. Callsprocwith the elements of the list(append (listarg1...)args)as the actual arguments.(define (f x y z) (+ x y z));等效:(f 1 2 3)(apply f '(1 2 3))(apply f 1 '(2 3))(apply f 1 2 '(3));将发生错误:;(apply f '(1)
阅读全文
摘要:named let和递归,闭包联系十分密切.而且还是提高性能的重要手段.先来看一个make-list函数的模拟,最原始的写法大概是:(define (imake-list n member) (if (= 1 n) (cons member '()) (cons member (imake-list (- n 1) member))))这种写法的毛病在于:1.递归过程中,member变量可能需要在全局作用域中查找,比局部作用域查找要慢.2.member是一个固定的参数,然而递归过程在不断重复将它传入imake-list.这个时候你需要 named let,完美...
阅读全文
摘要:说明,这是r5rs的用法.(letrec (( ) ...) ) 假设(( ) ...)是变量定义块V,是执行块B.letrec最常见的用法就是用于绑定函数对象,让V里面定义的所有变量可以在运行时相互引用,不受位置前后的限制.比如:> (letrec ((x (lambda () (+ y y))) (y 100)) (+ (x) y))300这说明运行(+ (x) y)时,函数对象x可以读取y对象的值,尽管y在x之后才绑定的. 这一点letrec很像顶层的运作模式:> (define x (lambda () (+ y y)))> (define y 100)> (+
阅读全文
摘要:查了半天没有找到scheme中判断数据类型的函数,索性自己写了个type?,发现闭包和递归有着微妙的联系.本例中,自由变量是types,外层let初始化了types的值,内层let里的(set! types rest)则是在不断缩小types.直至为null.;let内嵌lambda,可以构成闭包;expr ...部分即可对freevar进行各种修改值的操作(define function (let ((freevar value) ...) (lambda (var ...) expr ... )))(define type? (let ((types (list ...
阅读全文
摘要:想法源自:http://stackoverflow.com/questions/141642/what-limitations-have-closures-in-python-compared-to-language-x-closuresPython 2.7 的闭包中的自由变量(co_freevars)只读的.Python需要某些技巧来"变相修改"自由变量:>>> def add(n): freevar=[n] def closure(): freevar[0]+=1 return freevar[0] return closure>>>
阅读全文
摘要:(define funcname (lambda (arg1 ... argn) exp1 ... expn))(define (funcname arg1 ... argn) exp1 ... expn)举例:#lang racket(define (addx x) (lambda (y) (+ y x)))(define addx8 (addx 8))(define addx9 (addx 9))(addx8 100)(addx9 100)(define addy (lambda (x) (lambda (y) (+ y x))))(define addy8 (a...
阅读全文

浙公网安备 33010602011771号