SICP,继续传球风格和Clojure的蹦床 [英] SICP, Continuation Passing Style and Clojure's trampoline

查看:209
本文介绍了SICP,继续传球风格和Clojure的蹦床的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在与SICP合作,练习2.29-b让我有机会在继续传递风格的同时,通过手机和分支机会。



短,每个移动具有左和右分支,它们由长度和数字权重或另一移动装置组成。



在第一个相互递归的解决方案之后,很简单,我尝试并成功地实现了一个cps':

 (defn total-weight-cps [mobile] 
(letfn
[branch-weight-cps
[branch kont]
(let [structure(branch-structure branch)]
(if(mobile?(branch-structure branch))
(do(printlnthen (k(traverse-mobile-cps structure identity)))
(do(printlnelsestructure)(kont structure)))))

(traverse-mobile-cps
[mobile kont]
(branch-weight-cps(left-branch mobile)
(fn [left-weight]
b $ b(fn [right-weight](kont(+ left-weight right-weight))))))

(traverse-mobile-cps mobile identity) b

在这一点上,我试图应用蹦床为了保存我的堆栈。但它有以下例外:

  java.lang.ClassCastException:sicp_clojure.2_1_exercises_2_24_2_32 $ total_weight_STAR_ $ traverse_mobile_cps__6694 $ fn__6695 $ fn__6696 $ fn__6697不能转换为java.lang.Number 
Numbers.java:126 clojure.lang.Numbers.add
... / git / sicp-clojure / src / sicp_clojure / 2_1_exercises_2_24_2_32.clj:185 sicp -clojure.2-1-exercises-2-24-2-32 / total-weight * [fn]
core.clj:5801 clojure.core / trampoline
core.clj:5806 clojure.core / trampoline
RestFn.java:439 clojure.lang.RestFn.invoke
... / git / sicp-clojure / src / sicp_clojure / 2_1_exercises_2_24_2_32.clj:186 sicp-clojure.2-1-exercises -2-24-2-32 / total-weight *

使用蹦床的代码, 链接是:

 (defn total-weight * [mobile] 
(letfn
[branch-weight-cps
[分支kont]
(let [structure(branch-structure branch)]
(if(mobile? (branch-structure branch))
(do(printlnthenstructure)(kont(traverse-mobile-cps structure identity)))
(do(printlnelse ))))

(traverse-mobile-cps
[mobile kont]
(branch-weight-cps(left-branch mobile)
- weight]
(branch-weight-cps(right-branch mobile)
(fn [right-weight]#(kont(+ left-weight right-weight)))))) b $ b(trampoline traverse-mobile-cps mobile identity)))

 (def branch11(make-branch 11))
(def branch22(make-branch 2 2))
(def branch36(make-branch 3 6))
(def branch43(make-branch 4 3))

(make mobile 11-43(make-mobile branch11 branch43) )
(def mobile36-22(make-mobile branch36 branch22))

(def branch5m1143(make-branch 5 mobile11-43))
(def branch7m3622 7 mobile36-22))
(def mobile5m1143-7m3622(make-mobile branch5m1143 branch7m3622))

(total-weight * mobile5m1143-7m3622)

解决方案

为什么会爆炸?在我的帖子同样的链接后,我解决了我的实现:

 (defn total-weight * [mobile] 
(letfn
[branch-weight-cps
[branch kont]
(let [structure(branch-structure branch)]
(branch-structure branch))
(fn [](traverse-mobile-cps structure kont))
(fn [](kont structure)))))

traverse-mobile-cps
[mobile kont]
(branch-weight-cps(left-branch mobile)
(fn [left-weight]
(right-branch mobile)
(fn [right-weight]#(kont(+ left-weight right-weight))))))]
(trampoline traverse-mobile-cps mobile identity) ))


I am working with SICP and exercise 2.29-b gave me the opportunity to have fun with the Continuation Passing Style while traversing mobiles and branches.

To make the story short, each mobile has left and right branch, which are composed by a length and either a numeric weight or another mobile. The question asks to find the total weight given a mobile.

After the first mutually recursive solution, quite simple, I tried and successfully implemented a cps' one:

(defn total-weight-cps [mobile]
  (letfn 
    [(branch-weight-cps
      [branch kont]
      (let [structure (branch-structure branch)]
        (if (mobile? (branch-structure branch))
          (do (println "then " structure) (kont (traverse-mobile-cps structure identity)))
          (do (println "else " structure) (kont structure)))))

     (traverse-mobile-cps
      [mobile kont]
      (branch-weight-cps (left-branch mobile)
                         (fn [left-weight]
                           (branch-weight-cps (right-branch mobile)
                                              (fn [right-weight] (kont (+ left-weight right-weight)))))))]

    (traverse-mobile-cps mobile identity)))

At this point, I have tried to apply the trampoline in order to preserve my stack. But it blows with the following exception:

java.lang.ClassCastException: sicp_clojure.2_1_exercises_2_24_2_32$total_weight_STAR_$traverse_mobile_cps__6694$fn__6695$fn__6696$fn__6697 cannot be cast to java.lang.Number
Numbers.java:126 clojure.lang.Numbers.add
.../git/sicp-clojure/src/sicp_clojure/2_1_exercises_2_24_2_32.clj:185 sicp-clojure.2-1-exercises-2-24-2-32/total-weight*[fn]
core.clj:5801 clojure.core/trampoline
core.clj:5806 clojure.core/trampoline
RestFn.java:439 clojure.lang.RestFn.invoke
.../git/sicp-clojure/src/sicp_clojure/2_1_exercises_2_24_2_32.clj:186 sicp-clojure.2-1-exercises-2-24-2-32/total-weight*

The code using trampoline, following the excellent link, is:

(defn total-weight* [mobile]
  (letfn 
    [(branch-weight-cps
      [branch kont]
      (let [structure (branch-structure branch)]
        (if (mobile? (branch-structure branch))
          (do (println "then " structure) (kont (traverse-mobile-cps structure identity)))
          (do (println "else " structure) (kont structure)))))

     (traverse-mobile-cps
      [mobile kont]
      (branch-weight-cps (left-branch mobile)
                         (fn [left-weight]
                           (branch-weight-cps (right-branch mobile)
                                              (fn [right-weight] #(kont (+ left-weight right-weight)))))))]
    (trampoline traverse-mobile-cps mobile identity)))

And finally some sample data:

(def branch11 (make-branch 1 1))
(def branch22 (make-branch 2 2))
(def branch36 (make-branch 3 6))
(def branch43 (make-branch 4 3))

(def mobile11-43 (make-mobile branch11 branch43))
(def mobile36-22 (make-mobile branch36 branch22))

(def branch5m1143 (make-branch 5 mobile11-43))
(def branch7m3622 (make-branch 7 mobile36-22))
(def mobile5m1143-7m3622 (make-mobile branch5m1143 branch7m3622))

(total-weight* mobile5m1143-7m3622)

Why does it blow up?

解决方案

Following the same link in my post, I have solved turning my implementation in:

(defn total-weight* [mobile]
  (letfn
    [(branch-weight-cps
      [branch kont]
      (let [structure (branch-structure branch)]
        (if (mobile? (branch-structure branch))
          (fn [] (traverse-mobile-cps structure kont))
          (fn [] (kont structure)))))

     (traverse-mobile-cps
      [mobile kont]
      (branch-weight-cps (left-branch mobile)
                         (fn [left-weight]
                           (branch-weight-cps (right-branch mobile)
                                              (fn [right-weight] #(kont (+ left-weight right-weight)))))))]
    (trampoline traverse-mobile-cps mobile identity)))

这篇关于SICP,继续传球风格和Clojure的蹦床的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆