我是Haskell的新手,虽然有过以前的Lisp/Scheme体验.现在我正在查看SICP的示例,并尝试在Haskell中实现它们以获得更多的实践经验.在讲座3b中,作者提出了一种象征性地计算衍生物的功能.它包含以下几行:
(define (deriv exp var)
(cond ((constant? exp var) 0)
((same-var? exp var) 1)
; ...
Run Code Online (Sandbox Code Playgroud)
在讲座中,还定义了更多功能:
(define (constant? exp var)
(and (atom? exp)
(not (eq? exp var))))
Run Code Online (Sandbox Code Playgroud)
有没有办法在Haskell中做同样的事情,即检查原子性和符号等价于其他函数?或者更一般的是,Haskell中"反汇编"函数的手段是什么?
任何人都可以给我一个清晰简洁的解释SICP的最后两章(计算机程序的结构和解释),ch4元语言抽象和带寄存器机器的ch5计算吗?
我还想知道这两章的内容是否(和如何)与标准本科编译课程的内容不同.
SICP第3.5.3章 http://mitpress.mit.edu/sicp/full-text/book/book-ZH-24.html#%_sec_3.5.3
在章节中Streams as signals,SICP Implicit style of definition通过反馈循环给出了视听说明.但我想知道如何准确理解图表?什么是真正的优势,是否有任何背景知识?
再举一个例子,不是在Scheme中,而是在Haskell中:
fibs = fix (scanl (+) 0 . (1:))
fibs = fix ((0:) . scanl (+) 1)
Run Code Online (Sandbox Code Playgroud)
我们还可以绘制两者的信号流图.我们如何利用这些图表?
感谢您的建议和信息!
我现在正在阅读SICP,并不真正理解5.5.6词典寻址中描述的词法寻址的必要性.
因为它说"因为我们的语言是词法范围的,所以任何表达式的运行时环境都会有一个与表达式出现的程序的词汇结构相似的结构",我认为在运行中搜索变量的成本是相同的 - 在编译环境中搜索的时间环境.为什么我们懒得实现编译环境?我认为编译环境将具有与程序的词法结构相同的结构,这与运行时环境相同,不是吗?
这个问题可以在这里找到.
在书中,我发现正常订单评估的一个描述是:
"另一种评估模型不会在需要它们的值之前评估操作数.相反,它首先将操作数表达式替换为参数,直到它获得仅涉及原始运算符的表达式,然后执行评估."
我还简要地找到了另一种描述:"完全扩展然后减少".
在练习中,我认为定义p是类似的(lambda () (p)),它永远不会扩展到原始操作符,因此永远不会终止.
然而,另一方面,在搜索到这个问题的一些答案之后,似乎正常的订单评估应该终止,因为它只根据需要评估事物,实际上(p)不会被评估.
所以我认为"扩展"和"评估"之间必然存在一些差异,而解释者在这里做的是评估事物.
究竟有什么区别,或者我错过了哪些观点?
另一个问题:我应该说" (p)被评估为(p)"还是" (p)被扩展为(p)"?
我的问题涉及以下代码:
(define (cons. x y)
(lambda (m) (m x y)))
(define (car. z)
(z (lambda (p q) p)))
Run Code Online (Sandbox Code Playgroud)
我的问题是这个代码实际上是如何工作的.据我所知,利弊.正在返回一个包含其范围内的变量x和y的过程.汽车.然后从cons中获取返回的过程.并将其应用于另一个带有两个参数p和q并返回p的lambda.我的困惑在于第二个lambda,P和Q的值究竟来自哪里?
我对这个例子有疑问
(define (+ x y)
(if (= x 0)
y
(+ (-1+ x) (1+ y))))
Run Code Online (Sandbox Code Playgroud)
-1+和1+有什么问题,当我评估它时我得到了这个结果
但是我写了这个而且它有效
(define (add x y)
(if (= x 0)
y
(+ (- x 1) (+ y 1))))
Run Code Online (Sandbox Code Playgroud) 我在Clojure中实现了一些开始的SICP代码时遇到了意外的NullPointerException.特别是,我想实现1.1.7节中的迭代平方根过程.
这是代码:
(defn square [x] (* x x))
(defn abs [x]
(cond
(< x 0) (- x)
:else x))
(defn average [x y]
(/ (+ x y) 2))
(defn sqrt
([x] (sqrt 1.0 x))
([guess x]
(letfn [(good-enough? [guess]
(< (abs (- (square guess) x)) 0.001))
(improve [guess]
(average guess (/ x guess)))]
(if (good-enough? guess)
guess
(recur (improve guess) x)))))
Run Code Online (Sandbox Code Playgroud)
这适用于足够小的值,例如(sqrt 16).NullPointerException clojure.lang.Numbers.lt (Numbers.java:3693)任何大于约的输入都会出错(square 2718).
有任何想法吗?
使用整个回溯进行更新(前一个是我在repl中获得的):
位于sicp_in_clojure.chapter_one $ sqrt $ good_enough_QMARK ___ …
我正在通过SICP工作 - 一个练习就是实施foreach(doseq).这是一项学术活动.在clojure中,这就是我想出的:
(defn for-each [proc, items]
(if (empty? items) nil
(do
(proc (first items))
(recur proc (rest items)))))
Run Code Online (Sandbox Code Playgroud)
但是,如果do是作弊,我有点模糊,因为do在clojure中是一种特殊的形式,我不认为在SICP中已经引入了类似的东西.有更简约的答案吗?
这是另一个只在最后一个元素上执行proc的尝试:
(defn for-each-2 [proc, items]
(let [f (first items)
r (rest items)]
(if (empty? r)
(proc f)
(recur proc r))))
Run Code Online (Sandbox Code Playgroud) 我正在学习SICP。而且我发现的定义封在SICP是(也许)从其他语言的闭包定义不同。
这是SICP所说的:
创建元素为对的对的能力是列表结构作为表示工具的重要性的本质。我们将此功能称为cons的闭包属性。通常,如果可以使用相同的操作将事物与该对象合并的结果本身进行合并,则用于合并数据对象的操作将满足闭包属性。
我认为这里的闭包更接近于数学中的闭包,而不是我在JavaScript中看到的闭包,这意味着函数可以访问封闭的环境变量。
我错了吗?