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)

这一功能可能对我在脑海中考虑的具体用例很有用。这个功能可以在数据驱动的关系数据建模领域特定数据结构语言中定义简短的语法,以明确的外键映射,其中#{:attr1 :attr2}可以用作{:attr1 :attr1, :attr2 :attr2}的快捷方式。

3 个答案

0

我认为在Clojure中这样做非常不可能,但您可以为您的变量添加任何元数据,然后从这个元数据中引导它们。

感谢您迅速回复以及您的坦诚回答。
0
by

我同意这可能是有意义的,至少 keys 看起来与 getassoccontains? 在向量和映射中都是很好的配对。

如果您想为 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}
by
是的,那些通用的域/值范围功能没有在语言的内核中实现,这确实不是我的用例的障碍。感谢您提供实现。
0
by

如果有人的兴趣,我刚发现 Racket 通过 字典 接口实现了类似的想法,该接口为哈希表和向量提供 dict-keysdict-values(但不在集合中)。

...