首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Clojure (和Clojure )中使用eval ed代码中的库函数

如何在Clojure (和Clojure )中使用eval ed代码中的库函数
EN

Stack Overflow用户
提问于 2022-02-20 18:04:41
回答 2查看 105关注 0票数 0

我有一个Clojure文件,我正在将其他库函数导入到:require和:refer在ns声明中。

现在,我想在这个名称空间中对一些代码进行验证,并让它调用这些库。

但是当我调用它时,我会得到一个“无法解析符号”的引用函数。

我猜我必须以某种方式显式地把它传递给eval,但是找不到任何例子。

第二个问题。理想情况下,我希望完全不使用Clojure的普通版本,而是运行Babashka。有没有一种方法可以将库从Clojure环境传递到这个环境中?

更新。代码示例。

代码语言:javascript
复制
(ns clj-ts.card-server
  [:require
  ...
  [patterning.layouts :refer [framed clock-rotate etc]]
  ...
  )

...


(defn one-pattern
  "Evaluate one pattern"
  [data]
  (let [pattern
        (try
          (eval (read-string data))
          (catch Exception e
            (let [sw (new java.io.StringWriter)
                  pw (new java.io.PrintWriter sw) ]
              (.printStackTrace e pw)
              (str "Exception :: " (.getMessage e) (-> sw .toString) ))) )
        ]
...
  )

然后,当使用以下数据参数调用一个模式时

代码语言:javascript
复制
(let [a-round
        (fn [n lc fc]
          (clock-rotate
           n (std/poly
              0 0.5 0.4 n
              {:stroke lc
               :fill fc
               :stroke-weight 3})))
        
        ]
    (a-round 8 (p-color 140 220 180)  (p-color 190 255 200 100) )
    )

我犯了个错误

代码语言:javascript
复制
Caused by: java.lang.RuntimeException: Unable to resolve symbol: clock-rotate in this context
EN

回答 2

Stack Overflow用户

发布于 2022-02-20 18:33:15

我能够eval一个具有引用函数的表单。如下代码所示。

代码语言:javascript
复制
user> (join " " ["foo" "bar"])
Syntax error compiling at (*cider-repl Projects/example:localhost:59334(clj)*:43:7).
Unable to resolve symbol: join in this context
user> (require '[clojure.string :refer [join]])
nil
user> (join " " ["foo" "bar"])
"foo bar"
user> (eval (read-string "(join \" \" [\"foo\" \"bar\"])"))
"foo bar"
user> 

编辑:

eval在绑定到*ns*的“当前”命名空间的上下文中执行计算。我可以想出三种方法来解决你的问题--举下面的例子。我试图匹配我认为您的代码结构是什么。

下面是文件foo.clj的内容,该文件定义了evalit函数,并引用了一个库函数(在本例中,是来自clojure.stringjoin )。

代码语言:javascript
复制
(ns myorg.example.foo
  (:require [clojure.string :refer [join]]))

(defn evalit [s]
  (eval (read-string s)))

我们首先加载这个myorg.example.foo命名空间:

代码语言:javascript
复制
user> (require 'myorg.example.foo)
nil

第一种选择:使用join的完全限定符号如下:

代码语言:javascript
复制
user> (myorg.example.foo/evalit "(clojure.string/join \" \" [\"boo\" \"baz\"])")
"boo baz"

第二种选择:将*ns*临时绑定到包含引用的join的命名空间。注意,在这种情况下,我们可以只使用"join“,而不是完全限定的"clojure.string/join”。但是我们仍然必须为evalit使用完全限定的符号,因为我们从不同的名称空间引用它。

代码语言:javascript
复制
user> (binding [*ns* (find-ns 'myorg.example.foo)]
        (myorg.example.foo/evalit "(join \" \" [\"boo\" \"baz\"])"))
"boo baz"

第三种选择:切换到带有refer‘’ed函数的命名空间。

代码语言:javascript
复制
user> (in-ns 'myorg.example.foo)
#namespace[myorg.example.foo]
myorg.example.foo> (evalit "(join \" \" [\"boo\" \"baz\"])")
"boo baz"

在这里,我们可以使用非限定符号,因为我们在名称空间中有定义和引用。

票数 0
EN

Stack Overflow用户

发布于 2022-02-21 18:38:34

好的。

最后我用https://github.com/babashka/babashka SCI做了这件事

在我的文件中,我基本上接受了我导入的所有函数,并将它们放入这样一个新的映射中

代码语言:javascript
复制
(def patterning-ns
  {'clojure.core
   {
    'clock-rotate clock-rotate
    'poly poly
    ...
   }
  }
)

一旦从其他地方导入的函数名在称为模式-ns的映射中(在clojure.core的命名空间名称下),那么它们在默认情况下对任何使用

代码语言:javascript
复制
(sci/eval-string data {:namespaces patterning-ns })

艾格

代码语言:javascript
复制
(defn one-pattern
  "Evaluate one pattern"
  [data]
  (try
    (let [
          pattern
          (sci/eval-string
           data
           {:namespaces patterning-ns })
          svg (make-svg 400 400 pattern)
          ]
       svg
       )
      )
    (catch java.lang.Exception e
      (let [sw (new java.io.StringWriter)
            pw (new java.io.PrintWriter sw) ]
        (.printStackTrace e pw)
        (println e)
        (str "Exception :: " (.getMessage e) (-> sw .toString) )) )))
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71197250

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档