小编Pau*_*ans的帖子

Clojure中s表达式列表的递归

为了设置一些上下文,我正在学习Clojure,并且更普遍地学习Lisp.在我的Lisp之路上,我目前正在研究"Little"系列,以巩固功能编程和基于递归的解决方案的基础.在"The Little Schemer"中,我已经完成了许多练习,但是,我正在努力将其中的一些转换为Clojure.更具体地说,我正在努力将它们转换为使用"recur"以便启用TCO.例如,这里是一个基于Clojure的实现,来自"发生*"函数(来自Little Schemer),它计算出在S表达式列表中出现的原子的出现次数:

(defn atom? [l]
  (not (list? l)))

(defn occurs [a lst]
  (cond
   (empty? lst) 0
   (atom? (first lst))
    (cond
     (= a (first lst)) (inc (occurs a (rest lst)))
     true (occurs a (rest lst)))
   true (+ (occurs a (first lst))
           (occurs a (rest lst)))))
Run Code Online (Sandbox Code Playgroud)

基本上,(occurs 'abc '(abc (def abc) (abc (abc def) (def (((((abc)))))))))将评估为5.显而易见的问题是,如果给出一个S表达式列表太深,这个定义会消耗堆栈帧并且会破坏堆栈.

现在,我理解重构递归函数的选项,以使用累加器参数来启用将递归调用放入尾部位置(以允许TCO),但是如果此选项甚至适用于此类情况,我也在苦苦挣扎.

如果我尝试使用"recur"和使用累加器参数来重构这个,那么这里有多远:

(defn recur-occurs [a lst]
  (letfn [(myoccurs [a lst count]
            (cond
             (empty? lst) 0
             (atom? (first lst))
             (cond
              (= a (first …
Run Code Online (Sandbox Code Playgroud)

lisp recursion tail-recursion clojure the-little-schemer

13
推荐指数
2
解决办法
1719
查看次数

如何避免在Clojure中进行单元测试时手动评估defrecords和defprotocols?

在我的Clojure代码库中,我已经定义了几个协议和几个defrecords.我正在使用clojure.test对我的defrecords中定义的具体函数进行单元测试.

例如,假设我有以下源文件:

在src/foo/protocols.clj中:

(ns foo.protocols)

(defprotocol RequestAcceptability
  (desired-accepted-charset [this]))
Run Code Online (Sandbox Code Playgroud)

在src/foo/types.clj中:

(ns foo.types
  (:use [foo.protocols :only [RequestAcceptability desired-accepted-charset]])

(defrecord RequestProcessor
  [field-1 field-2]
  RequestAcceptability
  (desired-accepted-charset [this]
    ...implementation here...))
Run Code Online (Sandbox Code Playgroud)

在test/foo/types_test.clj中:

(ns foo.types-test
  (:use [clojure.test])
  (:use [foo.protocols :only [RequestAcceptability desired-accepted-charset]])
  (:import [foo.types RequestProcessor]))

(deftest test-desired-accepted-charset_1
  ...test code here...)
Run Code Online (Sandbox Code Playgroud)

我在Emacs中使用Clojure 1.4,Leiningen 2,nrepl.

我面临的烦恼是,当我去运行单元测试时(例如,使用Cc C-,序列),我得到一个ClassNotFoundException:foo.types.RequestProcessor.为了解决这个问题,我正在进行单独评估每个协议和defrecord表单的手动工作.即,我将导航到我的protocols.clj并评估(nrepl的CMx键序列)我的defprotocol形式; 然后我将导航到我的types.clj并评估我的defrecord表单; 然后我终于能够成功运行我的单元测试而没有得到ClassNotFoundException.

当然,在我真正的代码库中,我必须为我的所有协议和defrecords做到这一点,因此它非常繁琐且耗时.另外,如果我只是简单地放入 shell并进行lein测试,我会得到相同的ClassNotFoundException.

有没有更好的办法?

感谢您的时间和帮助.

clojure

5
推荐指数
1
解决办法
360
查看次数

使用clojure.data.xml从Clojure中发出XML.

我需要将Clojure数据结构序列化为XML,但我对如何发布集合感到磕磕绊绊.为了使这更具体,假设我有一个Clojure地图如下:

    (def parking-lot {:parking-lot #{
                         {:car {:color "red", :make "nissan", :year 2003}}
                         {:car {:color "blue", :make "toyota", :year 2001}}
                         {:car {:color "black", :make "honda", :year 2010}}}})
Run Code Online (Sandbox Code Playgroud)

这只是一个带有一个元素的地图,其值是一组"汽车"物品.现在,让我们假设我要序列化此映射以生成以下XML:

    <? xml version="1.0" ?>
    <parking-lot>
      <car color="red" make="nissan" year="2003" />
      <car color="blue" make="toyota" year="2001" />
      <car color="black" make="black" year="2010" />
    </parking-lot>
Run Code Online (Sandbox Code Playgroud)

在网上搜索有关如何在Clojure中最佳解析/发出XML的文档,让我进入了clojure.data.xml库,这就是我正在使用的.

以下是如何使用clojure.data.xml发出一些XML的简单示例:

    REPL> (use 'clojure.data.xml)

        => nil
    REPL> (emit-str (element :parking-lot {}))

        => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
            <parking-lot></parking-lot>"
Run Code Online (Sandbox Code Playgroud)

一个稍微复杂的例子:

    REPL> (emit-str (element :parking-lot {}
              (element :car {:color "yellow" :make "ford" :year …
Run Code Online (Sandbox Code Playgroud)

lisp clojure xml-serialization

2
推荐指数
2
解决办法
1529
查看次数