【问题标题】:Clojure: Convert a string to a function [duplicate]Clojure:将字符串转换为函数[重复]
【发布时间】:2020-11-22 06:59:09
【问题描述】:

以下作品:

((resolve (symbol "first")) [1 2 3])
;; => 1

为什么这样想是不对的,

((read-string "first") [1 2 3])
;; => nil

应该有效,但它没有? (我得到nil。)

【问题讨论】:

    标签: clojure


    【解决方案1】:

    (resolve (symbol "first")) 的返回值可能是应用于参数的 Var clojure.core/first

    (read-string "first") 的返回值是符号 first,它也适用于参数。但是将符号用作函数具有不同的含义。参数应该是一个map,返回值相当于(get a-map the-symbol)

    任何实现clojure.lang.IFn 的类型都可以在函数位置。使用符号作为带有向量参数的函数返回 nil 而不是失败的原因在于 implementation details of IFn for the Symbol 类型(在这种特殊情况下为 arity 1):

    public Object invoke(Object obj) {
        return RT.get(obj, this);
    }
    

    RT.get() 检查obj 是否实现了ILookup,如果是则调用ILookup.valAt()。 Clojure 向量确实实现了ILookup,但它们实现了expect an integer as the provided key and return nil for anything else

    public Object valAt(Object key, Object notFound){
        if(Util.isInteger(key))
            {
            int i = ((Number) key).intValue();
            if(i >= 0 && i < count())
                return nth(i);
            }
        return notFound;
    }
    
    public Object valAt(Object key){
        return valAt(key, null);
    }
    

    【讨论】:

      【解决方案2】:

      胡安是对的:

      (resolve (symbol "first"))    => <#clojure.lang.Var #'clojure.core/first>
      (read-string "first")         => <#clojure.lang.Symbol first>
      

      我们可以验证:

      (ns tst.demo.core
        (:use tupelo.core tupelo.test))
      
      (dotest
        (let [first-var (var clojure.core/first)
              first-sym (symbol "first")]
          (is= 1   (first-var [1 2 3])) ; automatically converted from a var => funciton by Clojure
          (is= nil (first-sym [1 2 3]))))
      

      另请参阅this answer,了解有关 Clojure Var 对象的双重间接的更多信息。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-10-27
        • 2016-09-06
        • 1970-01-01
        • 2017-07-22
        相关资源
        最近更新 更多