Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Intellij idea 无法在没有扩展错误的情况下执行Clojure宏_Intellij Idea_Clojure_Metadata_Cursive - Fatal编程技术网

Intellij idea 无法在没有扩展错误的情况下执行Clojure宏

Intellij idea 无法在没有扩展错误的情况下执行Clojure宏,intellij-idea,clojure,metadata,cursive,Intellij Idea,Clojure,Metadata,Cursive,我正在编写一个宏,它查看给定符号上的元数据并删除任何非关键字的条目,即关键字名称不以:开头 (meta (var X)) ;; Here's the metadata for testing... => {:line 1, :column 1, :file "C:\\Users\\Joe User\\AppData\\Local\\Temp\\form-init11598934441516564808.clj", :name X, :ns #object[cl

我正在编写一个宏,它查看给定符号上的元数据并删除任何非关键字的条目,即关键字名称不以:开头

(meta (var X))  ;; Here's the metadata for testing...
=>
{:line 1,
 :column 1,
 :file "C:\\Users\\Joe User\\AppData\\Local\\Temp\\form-init11598934441516564808.clj",
 :name X,
 :ns #object[clojure.lang.Namespace 0x12ed80f6 "thic.core"],
 OneHundred 100,
 NinetyNine 99}
我想删除entryeanetyine,剩下的元数据保持不变。 因此,我有一些代码可以工作:

它起作用了。第一百九十九条的条目已从X的元数据中删除

然后我把它编码成一个宏。上帝保佑雷普

(defmacro DelMeta! [S]  
  `(let [Hold# (meta (var ~S))] ;; Hold onto a copy of S's metadata.
     (map                       ;; Scan through the copy looking for keys that DON'T start with ":"
       (fn [[kee valu]]
         (if                    ;; If we find metadata whose keyname does not start with a ":"
           (not= \: (first (str kee)))
           (reset-meta! (var ~S) (dissoc (meta (var ~S)) kee))  ;; remove it from S's metadata.
           )
         )
       Hold#        ;; Loop through the copy of S's metadata so as to not confuse things.
       )
     )
  )
使用defmacro定义宏时不会出错。 宏上的macroexpand-1,例如

(macroexpand-1 '(DelMeta! X))
展开为正确的代码。在这里:

(macroexpand-1 '(DelMeta! X))
=>
(clojure.core/let
 [Hold__2135__auto__ (clojure.core/meta (var X))]
 (clojure.core/map
  (clojure.core/fn
   [[thic.core/kee thic.core/valu]]
   (if
    (clojure.core/not= \: (clojure.core/first (clojure.core/str thic.core/kee)))
    (clojure.core/reset-meta! (var X) (clojure.core/dissoc (clojure.core/meta (var X)) thic.core/kee))))
  Hold__2135__auto__))
但是

实际上,在REPL处使用实数参数调用宏会清除最不可理解的错误消息:

(DelMeta! X)  ;;Invoke DelMeta! macro with symbol X.

Syntax error macroexpanding clojure.core/fn at (C:\Users\Joe User\AppData\Local\Temp\form-init11598934441516564808.clj:1:1).
([thic.core/kee thic.core/valu]) - failed: Extra input at: [:fn-tail :arity-1 :params] spec: :clojure.core.specs.alpha/param-list
(thic.core/kee thic.core/valu) - failed: Extra input at: [:fn-tail :arity-n :params] spec: :clojure.core.specs.alpha/param-list
哦,全能而智慧的克洛尤里戈兹,我恳求你的怜悯。
我的罪在哪里?

这里不需要宏。此外,您还误解了Clojure关键字的性质,以及Clojure变量与局部变量的复杂性

通过在let块中使用局部变量而不是Var来保持简单:

(ns tst.demo.core
  (:use tupelo.core tupelo.test))

(dotest
  (let [x  (with-meta [1 2 3] {:my "meta"})
        x2 (vary-meta x assoc :your 25 'abc :def)
        x3 (vary-meta x2 dissoc 'abc )]
    (is= x  [1 2 3])
    (is= x2 [1 2 3])
    (is= x3 [1 2 3])

    (is= (meta x)  {:my "meta"})
    (is= (meta x2) {:my "meta", :your 25, 'abc :def})
    (is= (meta x3) {:my "meta", :your 25}))
我们看到x,x2和x3的值是常数。这就是元数据的目的。第二组测试显示了使用vary meta对元数据的影响,这是更改值的最佳方式

当我们使用Var时,它不仅是一个全局值,而且就像C中指针的双间接寻址。请看这个问题:

这个答案还澄清了字符串、符号和关键字之间的区别。这很重要

考虑一下这个代码

(def ^{:my "meta"} data [1 2 3])
(spyx data)
(spyx-pretty (meta (var data)))
结果是:

data => [1 2 3]

(meta (var data)) => 
    {:my "meta",
     :line 19,
     :column 5,
     :file "tst/demo/core.cljc",
     :name data,
     :ns #object[clojure.lang.Namespace 0x4e4a2bb4 "tst.demo.core"]}

(is= data [1 2 3])
(is= (set (keys (meta (var data))))
  #{:my :line :column :file :name :ns})
因此,我们根据需要将key:my添加到元数据中。我们怎样才能改变它?对于Var,使用函数alter meta

因此,我们向元数据映射添加了2个新条目。一个有关键字:your as key,值为25,另一个有符号abc as key,值为:def a关键字

我们也可以使用altermeta!要从元数据映射中远程密钥/val对,请执行以下操作:

(alter-meta! (var data) dissoc 'abc )
(is= (set (keys (meta (var data))))
  #{:ns :name :file :your :column :line :my})
关键字vs符号vs字符串

源文件中的字符串文字在每一端都有双引号,但它们不是字符串中的字符。同样,源文件中的关键字文字也需要一个前导冒号来标识它。但是,字符串的双引号和关键字的冒号都不是该值名称的一部分

因此,您无法通过冒号识别关键字。您应该使用这些函数来标识不同的数据类型:

以上内容来自于。因此,您真正想要的代码是:

(defn remove-metadata-symbol-keys
  [var-obj]
  (assert (var? var-obj)) ; verify it is a Var
  (doseq [k (keys (meta var-obj))]
    (when (not (keyword? k))
      (alter-meta! var-obj dissoc k))))
有一个样本:

(def ^{:some "stuff" 'other :things} myVar [1 2 3])
(newline) (spyx-pretty (meta (var myVar)))

(remove-metadata-symbol-keys (var myVar))

(newline) (spyx-pretty (meta (var myVar)))
结果:

(meta (var myVar)) => 
{:some "stuff",
 other :things,          ; *** to be removed ***
 :line 42,
 :column 5,
 :file "tst/demo/core.cljc",
 :name myVar,
 :ns #object[clojure.lang.Namespace 0x9b9155f "tst.demo.core"]}


(meta (var myVar)) =>   ; *** after removing non-keyword keys ***
{:some "stuff",
 :line 42,
 :column 5,
 :file "tst/demo/core.cljc",
 :name myVar,
 :ns #object[clojure.lang.Namespace 0x9b9155f "tst.demo.core"]}

以上代码都是使用运行的。

这里不需要宏。此外,您还误解了Clojure关键字的性质,以及Clojure变量与局部变量的复杂性

通过在let块中使用局部变量而不是Var来保持简单:

(ns tst.demo.core
  (:use tupelo.core tupelo.test))

(dotest
  (let [x  (with-meta [1 2 3] {:my "meta"})
        x2 (vary-meta x assoc :your 25 'abc :def)
        x3 (vary-meta x2 dissoc 'abc )]
    (is= x  [1 2 3])
    (is= x2 [1 2 3])
    (is= x3 [1 2 3])

    (is= (meta x)  {:my "meta"})
    (is= (meta x2) {:my "meta", :your 25, 'abc :def})
    (is= (meta x3) {:my "meta", :your 25}))
我们看到x,x2和x3的值是常数。这就是元数据的目的。第二组测试显示了使用vary meta对元数据的影响,这是更改值的最佳方式

当我们使用Var时,它不仅是一个全局值,而且就像C中指针的双间接寻址。请看这个问题:

这个答案还澄清了字符串、符号和关键字之间的区别。这很重要

考虑一下这个代码

(def ^{:my "meta"} data [1 2 3])
(spyx data)
(spyx-pretty (meta (var data)))
结果是:

data => [1 2 3]

(meta (var data)) => 
    {:my "meta",
     :line 19,
     :column 5,
     :file "tst/demo/core.cljc",
     :name data,
     :ns #object[clojure.lang.Namespace 0x4e4a2bb4 "tst.demo.core"]}

(is= data [1 2 3])
(is= (set (keys (meta (var data))))
  #{:my :line :column :file :name :ns})
因此,我们根据需要将key:my添加到元数据中。我们怎样才能改变它?对于Var,使用函数alter meta

因此,我们向元数据映射添加了2个新条目。一个有关键字:your as key,值为25,另一个有符号abc as key,值为:def a关键字

我们也可以使用altermeta!要从元数据映射中远程密钥/val对,请执行以下操作:

(alter-meta! (var data) dissoc 'abc )
(is= (set (keys (meta (var data))))
  #{:ns :name :file :your :column :line :my})
关键字vs符号vs字符串

源文件中的字符串文字在每一端都有双引号,但它们不是字符串中的字符。同样,源文件中的关键字文字也需要一个前导冒号来标识它。但是,字符串的双引号和关键字的冒号都不是该值名称的一部分

因此,您无法通过冒号识别关键字。您应该使用这些函数来标识不同的数据类型:

以上内容来自于。因此,您真正想要的代码是:

(defn remove-metadata-symbol-keys
  [var-obj]
  (assert (var? var-obj)) ; verify it is a Var
  (doseq [k (keys (meta var-obj))]
    (when (not (keyword? k))
      (alter-meta! var-obj dissoc k))))
有一个样本:

(def ^{:some "stuff" 'other :things} myVar [1 2 3])
(newline) (spyx-pretty (meta (var myVar)))

(remove-metadata-symbol-keys (var myVar))

(newline) (spyx-pretty (meta (var myVar)))
结果:

(meta (var myVar)) => 
{:some "stuff",
 other :things,          ; *** to be removed ***
 :line 42,
 :column 5,
 :file "tst/demo/core.cljc",
 :name myVar,
 :ns #object[clojure.lang.Namespace 0x9b9155f "tst.demo.core"]}


(meta (var myVar)) =>   ; *** after removing non-keyword keys ***
{:some "stuff",
 :line 42,
 :column 5,
 :file "tst/demo/core.cljc",
 :name myVar,
 :ns #object[clojure.lang.Namespace 0x9b9155f "tst.demo.core"]}

上面的代码都是用运行的。

我开始写答案,但停了下来,因为不清楚您到底想实现什么。一些提示:我没有得到相同的异常,相反,我得到一个异常,告诉我“kee”不存在——如果你想使用它,你想使用kee和valu。阅读变量捕获,例如在中。第二,当您想要的只是副作用时调用map,使用doseq可以更清楚地表示副作用。但主要的问题是,为什么您首先要使用非关键字元数据?这里的map是错误的,doseq也是错误的,因为两个更新会相互碰撞。在里面
不要使用reduce或into/for在功能上构建一个新的地图,然后设置一次。我发现结尾行非常有趣。hahaI开始写答案,但停了下来,因为不清楚你到底想实现什么。一些提示:我没有得到相同的异常,相反,我得到一个异常,告诉我“kee”不存在——如果你想使用它,你想使用kee和valu。阅读变量捕获,例如在中。第二,当您想要的只是副作用时调用map,使用doseq可以更清楚地表示副作用。但主要的问题是,为什么您首先要使用非关键字元数据?这里的map是错误的,doseq也是错误的,因为两个更新会相互碰撞。相反,使用reduce或into/for在功能上构建一个新的地图,然后设置一次。我发现结尾行非常有趣哈兰·汤普森:你以前回答过我的问题,我想我希望你在这里再次这样做。你做到了!600字!:非常感谢你。让我仔细检查一下,试一下你们的样品,然后再给你们回复。金星队,欧比万。读一下。几个月前,我花了一段时间摸索符号->变量->价值链。我经常想象Clojure在幕后使用某种双重间接手段。谢谢你的确认。我对Clojure的入门知识不包括“keys”函数或“keyword”函数。让我玩一下,我会回答更多的问题,或者希望不会艾伦·汤普森:你以前回答过我的问题,我想我希望你在这里再次这样做。你做到了!600字!:非常感谢你。让我仔细检查一下,试一下你们的样品,然后再给你们回复。金星队,欧比万。读一下。几个月前,我花了一段时间摸索符号->变量->价值链。我经常想象Clojure在幕后使用某种双重间接手段。谢谢你的确认。我对Clojure的入门知识不包括“keys”函数或“keyword”函数。让我玩一下,我会回答更多的问题,或者希望不会