Scheme 语言中的 this 函数是做什么的?
What this functions in Scheme language do?
我是新手,语言不是很懂。谁能给我解释一下这个函数的作用吗?
第一个函数:
(define (x l)
(cond
((null? l) 0)
((list? (car l))
(+ (x (car l)) (x (cdr l))))
(else (+ 1 (x (cdr l))))
))
第二个函数:
(define (x l)
(cond
((null? l) 0)
((list? (car l))
(+ (x (car l)) (x (cdr l))))
(else (+ (car l) (x (cdr l)))
))
开头我看懂了,后面的条件我没看懂。有帮助吗?
我会调用你的第二个函数y
。
用伪代码编写,
x [] -> 0
x [a . b] -> x a + x b , if list a
x [a . b] -> 1 + x b , else, i.e. if not (list a)
y [] -> 0
y [a . b] -> y a + y b , if list a
y [a . b] -> a + y b , else, i.e. if not (list a)
例如,
x [2,3] = x [2 . [3]]
= 1 + x [3]
= 1 + x [3 . []]
= 1 + (1 + x [])
= 1 + (1 + 0 )
和
y [2,3] = y [2 . [3]]
= 2 + y [3]
= 2 + y [3 . []]
= 2 + ( 3 + y [])
= 2 + ( 3 + 0 )
看到了吗?第一个在参数列表中计算 something,第二个将它们相加。
当然这两个函数都可以用一些非列表来调用,但是这两个函数都只会导致在第二个子句 (list? (car l))
中尝试获取 (car l)
的错误。
您可能已经注意到两者几乎相同。它们都在树上堆积(折叠)。当汽车是 list?
时,它们都将在空树上评估为 0,并且它们将在 car
和 cdr
上对相同过程的结果求和。当 car
不是列表时,两者不同,第一个是为每个元素加 1,另一个是在加法中使用元素本身。可以像这样写得更紧凑一点:
(define (sum l)
(cond
((null? l) 0) ; null-value
((not (pair? l)) l) ; term
(else (+ (sum (car l)) (sum (cdr l)))))) ; combine
这是一个概括:
(define (accumulate-tree tree term combiner null-value)
(let rec ((tree tree))
(cond ((null? tree) null-value)
((not (pair? tree)) (term tree))
(else (combiner (rec (car tree))
(rec (cdr tree)))))))
您可以根据 accumulate-tree
:
来制定您的两个程序
(define (count tree)
(accumulate-tree tree (lambda (x) 1) + 0))
(define (sum tree)
(accumulate-tree tree (lambda (x) x) + 0))
当然,accumulate-tree
你可以赚到比这更多的钱。它不必变成原子值。
(define (double tree)
(accumulate-tree tree (lambda (x) (* 2 x)) cons '()))
(double '(1 2 ((3 4) 2 3) 4 5)) ; ==> (2 4 ((6 8) 4 6) 8 10)
我是新手,语言不是很懂。谁能给我解释一下这个函数的作用吗?
第一个函数:
(define (x l)
(cond
((null? l) 0)
((list? (car l))
(+ (x (car l)) (x (cdr l))))
(else (+ 1 (x (cdr l))))
))
第二个函数:
(define (x l)
(cond
((null? l) 0)
((list? (car l))
(+ (x (car l)) (x (cdr l))))
(else (+ (car l) (x (cdr l)))
))
开头我看懂了,后面的条件我没看懂。有帮助吗?
我会调用你的第二个函数y
。
用伪代码编写,
x [] -> 0
x [a . b] -> x a + x b , if list a
x [a . b] -> 1 + x b , else, i.e. if not (list a)
y [] -> 0
y [a . b] -> y a + y b , if list a
y [a . b] -> a + y b , else, i.e. if not (list a)
例如,
x [2,3] = x [2 . [3]]
= 1 + x [3]
= 1 + x [3 . []]
= 1 + (1 + x [])
= 1 + (1 + 0 )
和
y [2,3] = y [2 . [3]]
= 2 + y [3]
= 2 + y [3 . []]
= 2 + ( 3 + y [])
= 2 + ( 3 + 0 )
看到了吗?第一个在参数列表中计算 something,第二个将它们相加。
当然这两个函数都可以用一些非列表来调用,但是这两个函数都只会导致在第二个子句 (list? (car l))
中尝试获取 (car l)
的错误。
您可能已经注意到两者几乎相同。它们都在树上堆积(折叠)。当汽车是 list?
时,它们都将在空树上评估为 0,并且它们将在 car
和 cdr
上对相同过程的结果求和。当 car
不是列表时,两者不同,第一个是为每个元素加 1,另一个是在加法中使用元素本身。可以像这样写得更紧凑一点:
(define (sum l)
(cond
((null? l) 0) ; null-value
((not (pair? l)) l) ; term
(else (+ (sum (car l)) (sum (cdr l)))))) ; combine
这是一个概括:
(define (accumulate-tree tree term combiner null-value)
(let rec ((tree tree))
(cond ((null? tree) null-value)
((not (pair? tree)) (term tree))
(else (combiner (rec (car tree))
(rec (cdr tree)))))))
您可以根据 accumulate-tree
:
(define (count tree)
(accumulate-tree tree (lambda (x) 1) + 0))
(define (sum tree)
(accumulate-tree tree (lambda (x) x) + 0))
当然,accumulate-tree
你可以赚到比这更多的钱。它不必变成原子值。
(define (double tree)
(accumulate-tree tree (lambda (x) (* 2 x)) cons '()))
(double '(1 2 ((3 4) 2 3) 4 5)) ; ==> (2 4 ((6 8) 4 6) 8 10)