2024 Clojure状态调查中分享你的想法!

欢迎!请查看关于页面以了解更多关于这个网站的信息。

+1
集合

Clojure的一个非常出色的特性是它将集合视为函数,这意味着我们可以对其进行调用

({:a 1, :b 2} :a) => 1
(#{:a :b} :a) => :a
([:a :b :c] 1) => :b

但是,能够独立于特定类型查询这些函数的定义域值域会更好

当前,keysvals函数实现了这一点,但仅限于Map。我认为将其函数更通用一些,以便接受集合和向量,如以下示例所示是个好主意。

(keys  #{:a :b}) => (:a :b)
(vals #{:a :b}) => (:a :b)
(keys [:a :b :c]) => (0 1 2)
(vals [:a :b :c]) => (:a :b :c)

我认为这个特性在以下特定情况下可能很有用,即定义一个在面向数据的数据建模 DSL 中明确的远程键映射的更简短的语法,其中#{:attr1 :attr2}可以用作{:attr1 :attr1, :attr2 :attr2}的快捷方式。

3 个答案

0

我认为在Clojure中这样做是非常不可能的,但你可以在你的变量中添加任何您想要的元数据,然后从那里引导事物。

感谢您快速的回复和诚实的答案。
0

我同意,这也许是有道理的,至少keysgetassoccontains?似乎在向量和映射中搭配得相当好。

如果您想在领域特定语言(DSL)中实现此功能,您可以自己实现。

(defprotocol FiniteFn
  (inputs [this] "Returns a set of all valid inputs to this fn")
  (outputs [this] "Returns a set of all valid outputs of this fn"))

(extend-protocol FiniteFn
  clojure.lang.IPersistentMap
  (inputs [m] (set (keys m)))
  (outputs [m] (set (vals m)))
  clojure.lang.IPersistentVector
  (inputs [xs] (set (range (count xs))))
  (outputs [xs] (set xs))
  clojure.lang.IPersistentSet
  (inputs [s] s)
  (outputs [s] s))

(inputs {:a 1}) => #{:a}

(inputs [:a :b]) => #{0 1}

(outputs {:a 1 :b 1}) => #{1}
是的,那些通用领域/范围函数没有在语言核心中实现,这确实不会成为我使用的障碍。感谢您提供实现。
0

如果有人感兴趣的话,我刚刚发现Racket正在使用Dictionary界面实现类似的想法,该界面在哈希表和向量上提供dict-keysdict-values(但不提供在集合上)。

...