【问题标题】:Is there a more elegant way to input a map as a list of pairs from stdin in Clojure?有没有一种更优雅的方法可以将地图作为来自 Clojure 中标准输入的对列表输入?
【发布时间】:2019-11-12 04:32:37
【问题描述】:

目前,作为编码练习的一部分,我编写了以下代码,以将一组空格分隔的对从标准输入(作为受信任的源)读取到一个映射中,其中 nbElevators 是先前定义的:

(let [elevators (into {} (doall (repeatedly nbElevators #(do [(read) (read)]))))]

有没有更好的方法来做到这一点?

  • 我不喜欢 #(do,但没有这个,Clojure 不断将 repeatedly 解释为尝试将向量调用为函数,而不是将向量的外观视为表示单一形式的函数它返回一个向量。这看起来很奇怪,因为表达式作为函数体是有效的(例如,(defn foo [] 2) 有效),但 (repeatedly 5 2) 无效,(repeatedly 5 #(2)) 也无效 - 即使 (repeatedly 5 (fn [] 2)) 有效,这意味着读取器宏中有一个漏洞。我在这里错过了什么语法吗?

  • 可以避免doall 吗?有没有办法自动缓存或指定输入,以便在延迟评估序列时读取文件中的正确位置?

【问题讨论】:

    标签: clojure


    【解决方案1】:

    对于第一点,请记住在 Clojure(以及一般的 lisps 和 afaik)中,()s 具有一组特殊的含义。除非宏在评估之前重新排列事物,否则(f a) 意味着将使用a 作为参数调用f。这不是宏中的“漏洞”。我认为如果#(2) 没有 尝试调用2 会更令人惊讶。这与函数调用工作方式的一贯性质背道而驰。

    你可以看到 #() 使用特殊形式 quote 扩展为:

    (quote #(2))
    => (fn* [] (2))  ; fn* is the actual special form that fn delegates to
    
    (quote #(vector %))
    => (fn* [p1__1632#] (vector p1__1632#))  ; % is translated to a generated symbol
    

    这显示了问题所在。

    就个人而言,为了清楚起见,我会在那里使用(fn [] [(read) (read)])。这更冗长,但正如我将在最后提到的那样,通常可以对代码进行一些清理,这样就不会出现问题。

    当然,如果这有助于清晰,整个匿名函数也可以变成一个实际的独立函数。


    如果您希望严格执行 repeatedly 调用,我会使用 vec 而不是 doall 并将惰性列表强制转换为向量。老实说,doall 没有太多用处,vec 无法处理。空间使用上的差异可能很小,但我从未发现它很重要。

    但在这种情况下,两者都不是必需的。 into 将严格强制 repeatedly 返回的集合。地图并不懒惰,因此无论如何都需要立即对其进行评估。



    我会使用 ->> 宏来拆分它,所以它不会那么长:

    (let [elevators (->> (repeatedly nbElevators (fn [] [(read) (read)]))
                         (into {}))])
    

    (fn [] . . .) 位甚至可以使参数被线程化,但我不认为这也可以理解,即使它会导致更短的行。

    这也可以通过使用@amolloy 提到的hash-map“构造函数”来重写。它需要一个 var-arg 列表并将它们视为对。这使您无需自己配对键/值:

    (apply hash-map (repeatedly (* 2 nbElevators) read))
    

    【讨论】:

    • 谢谢!我有点误解了,因为我认为 #(x) 相当于 (fn [] x) 而不是 (fn [] (x))
    • @MarkGreen 仅供参考,请尝试评估(quote #(vector 1))。你可以看到#() 扩展成什么。
    猜你喜欢
    • 1970-01-01
    • 2014-12-19
    • 2014-02-07
    • 1970-01-01
    • 1970-01-01
    • 2023-02-23
    • 1970-01-01
    • 1970-01-01
    • 2021-02-21
    相关资源
    最近更新 更多