简体   繁体   English

在球拍中使用调度表

[英]using a dispatch table in racket

I am writing a small program to compute simple derivatives of expressions represented in list form ie 2x^2 is represented as (* 2 (exp x 2)) and I have defined the following functions: 我正在编写一个小程序来计算以列表形式表示的表达式的简单导数,即2x^2表示为(* 2 (exp x 2))并且我定义了以下函数:

;; derivative of a constant is 0
(define (diff-constant x E) 0)

;; computes derivative of E with respect to x where E can only be of the form
;; (+ x x ...)
(define (diff-sum x E)
  (cond ((or (not (list? E)) (null? E)) 0)
        ((eq? (car E) x) (+ 1 (diff-sum x (cdr E))))
        (else (diff-sum x (cdr E)))))

;; computes derivative of E with respect to x where E can only be of the form
;; (* x y)
(define (diff-product x E)
  (cond ((and (eq? x (cadr E)) (eq? x (caddr E))) (list '* 2 x))
        ((eq? x (cadr E)) (list (caddr E)))
        ((eq? x (caddr E)) (list (cadr E)))
        (else 0)))

;; computes derivative of E with respect to x where E can only be of the form
;; (expt x y) which is x^y
(define (diff-expt x E)
  (cond ( not (eq? x (cadr E)) 0)
        ((eq? 1 (caddr E)) 0)
        ((eq? 2 (caddr E)) (cadr E))
        (else (list '* (caddr E) (list 'expt x (- (caddr E) 1))))))

I also have a dispatch table defined as: 我还有一个调度表定义为:

;; Dispatch Table of supported operators.
 (define diff-dispatch
   (list (list '+ diff-sum)
         (list '* diff-product)
         (list 'expt diff-expt)
         ))

and I am trying to write a function diff that takes an equation E (in list form) and computes the derivative with respect to x and uses the dispatch table to call the pre-defined functions returning the result 我正在尝试编写一个函数diff ,它采用方程式E (以列表形式)并计算相对于x的导数并使用调度表调用返回结果的预定义函数

here is what I have so far but I can't figure out the rest 这是我到目前为止,但我无法弄清楚其余的

;; Differentiate expression E with respect to x.
(define (diff x E)
  (cond ((number? E) (diff-constant x E))
        ;; insert code here to handle the other base case - variables
        ...
        (else    ; insert code here to lookup the appropriate function in the
                 ; dispatch table based on the operator in the expression,
                 ; then call that function to differentiate the expression
                     (diff-func x E))))))

ex: (diff 'x '(+ x (* xx))) should evaluate to (+ 1 (+ (* 1 (* x)) (* x 1))) (ie 1 + x + x) 例如: (diff 'x '(+ x (* xx)))应评估为(+ 1 (+ (* 1 (* x)) (* x 1))) (即1 + x + x)

In the SICP book there's a whole section explaining in detail how to build a Scheme program for performing symbolic differentiation, take a look at section §2.3 . SICP的书中,有一整节详细解释了如何构建一个用于执行符号区分的Scheme程序,请参阅第2.3节 In particular, be aware that you're missing one case - what happens if the expression to be derived is a variable? 特别要注意的是,你错过了一个案例 - 如果要派生的表达式是一个变量,会发生什么? check the link to make sure that you're on the right track. 检查链接以确保您走在正确的轨道上。

Now, answering the question: it's simple to implement a dispatcher given the table representation used in the code. 现在,回答这个问题:考虑到代码中使用的表格表示,实现调度程序很简单。 Something along these lines will work for obtaining an applying the correct differentiation procedure: 沿着这些方向的东西将有助于获得应用正确的差异化程序:

((cadr             ; obtain the differentiation procedure
  (assoc           ; look for the differentiation procedure
   (car E)         ; obtain the operator in the expression
   diff-dispatch)) ; dispatch table
 x E)              ; apply the procedure with parameters `x` and `E`

Notice that the "trick" for finding the correct procedure to apply lies in the fact that the table is implemented as an association list, and the assoc procedure was designed precisely for finding data in such a list. 请注意,“绝招”寻找正确的过程中的事实表被实现为关联列表,以及适用谎言assoc程序,精确地设计用于在这样的列表中找到数据。 Read more about it in the documentation . 文档中阅读更多相关信息。

To add to Óscar López's answer: in a professional-level Racket program, we want dispatch to go as quickly as we can. 添加到ÓscarLópez的答案:在专业级的球拍计划中,我们希望尽快发送。 If the number of things to test against grows beyond a few items, we probably should use a data structure that supports fast lookup, such as a vector or hash table . 如果要测试的事物数量增长超过几个项目,我们可能应该使用支持快速查找的数据结构,例如向量或散列表 Data representations can matter: lists are not the best or only data structure we should know. 数据表示可能很重要:列表不是我们应该知道的最佳或唯一的数据结构。 SICP's bias towards using linked-list representations for everything is laudable. SICP倾向于使用链接列表表示所有内容是值得称赞的。 But sometimes linked lists are not the right structure. 但有时链表不是正确的结构。

In a hash table-based approach, the set up for the dispatch table stays very similar: 在基于散列表的方法中,调度表的设置保持非常相似:

;; in professional-level Racket (#lang racket)
(define dispatch-table (hash '+ diff-sum
                             '* diff-product
                             ;; ... etc
                             ))

Lookup into the table is a hash-ref away. 查找表是哈希参考

(define op '+)
(hash-ref dispatch-table op)      ;;; => diff-sum

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM