- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
据说clojure中的每个集合都是“顺序的”,但是只有list和cons实际上是seqs:
user> (seq? {:a 1 :b 2})
false
user> (seq? [1 2 3])
false
user> (class (rest {:a 1 :b 2}))
clojure.lang.PersistentArrayMap$Seq
user> (:b (rest {:a 1 :b 2}))
nil
user> (:b (filter #(-> % val (= 1)) {:a 1 :b 1 :c 2}))
nil
最佳答案
Clojure google小组对此进行了讨论;例如,请参见今年2月的线程map semantics。我会随意使用我在消息中对下面的线程提出的观点,同时添加一些新观点。
在继续解释为什么我认为“ sequate seq”设计是正确的设计之前,我想指出一个自然的解决方案,用于您确实希望输出与输入类似但又不明确的情况关于它的信息以contrib库algo.generic中的函数fmap
的形式存在。 (但是,出于默认原因,核心库设计是一个好的原因,我认为默认情况下使用它不是一个好主意。)
总览
我认为,关键的观察结果是诸如map
,filter
等序列操作在概念上分为三个独立的方面:
对他们的输入进行某种迭代的方式;
将函数应用于输入的每个元素;
产生输出。
显然,如果我们能够处理1.和3,则2.毫无问题。所以让我们来看一下。
迭代
对于1.,请考虑最简单,最高效的迭代集合的方法通常不涉及分配与集合相同的抽象类型的中间结果。将函数映射到向量上的分块seq上比将函数映射到产生对每个subvec
的“视图向量”(使用next
)(使用next
)的seq上的性能要好得多。但是,后者是我们可以在Clojure风格的向量上对next
进行性能优化的最佳方法(即使存在RRB trees,当我们需要适当的子向量/向量切片操作来实现有趣的效果时,这也很棒)算法,但是如果我们使用遍历实现dissoc
,则遍历的速度会很慢。
在Clojure中,专门的seq类型维护遍历状态和额外的功能,例如(1)用于排序映射和集合的节点堆栈(除了更好的性能之外,与使用disj
/ subvec
遍历相比,它具有更大的big-O复杂性!) ,(2)当前索引+逻辑,用于将叶子数组包装在矢量块中;(3)遍历“连续”用于哈希图。通过这样的对象遍历集合比通过dissoc
/ disj
/ take
遍历任何尝试都快。
但是,假设在将函数映射到向量时我们愿意接受性能下降。好吧,让我们现在尝试过滤:
(->> some-vector (map f) (filter p?))
(->> some-sorted-set (filter p?) (map f) (take n))
map
可以用
filter
重新排序,但不能用
filter
重新排序。
map
隐式转换为seq是可以的,那么
seq
也可以。其他序列函数也可以使用类似的参数。一旦我们对所有(或几乎所有)参数都进行了说明,很明显
seq
返回专门的
map
对象也是有意义的。
seq
和
into
并考虑
seq
和
into
自身如何制作有用的原语的方法要好得多,例如
map
是的,Clojure可以选择公开有用的原语,然后让用户编写它们。这使我们
into
和
into
从一个集合中生成一个集合,同时又使我们可以自由地自由地进入当生成一个集合(或其他集合类型)无法获得任何价值的时候进入
clojure.core.reducers/map
阶段。 , 视情况可以是)。
(into #{})
和朋友产生的中间对象仅生成“描述符”对象,该对象维护有关在精简精简器的情况下需要执行哪些计算的信息。因此,计算的各个阶段可以合并。
(require '[clojure.core.reducers :as r])
(->> some-set (r/map f) (r/filter p?) (into #{}))
f
,但这只是说“ reducers管道在这里结束;请以集合的形式产生结果”的一种方式。我们还可以要求使用不同的集合类型(也许是结果的向量;请注意,将
(reduce + 0)
映射到集合上可能会产生重复的结果,并且在某些情况下我们可能希望保留它们)或标量值(
seq
) 。
seq
使用最快的方法进行迭代;
seq
样式的操作,因为我们要在累积输出的同时非常快速地进行迭代;
map
是一个很好的原始语言;
filter
和
into
在选择处理seq时,可以避免性能损失而没有上升空间,得益于懒惰等,但仍可以用于生成
关于clojure - 为什么Clojure集合不直接实现ISeq接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23189051/
在Joy of Clojure,第 2 版,第 217 页,我们读到: You may have noticed that we've been using our own function xseq
我想将 Java 函数的映射传递给 Clojure。这些函数使用实现 IFn 接口(interface)的 Java 匿名类。我还需要实现 ISeq 接口(interface)来传递列表。 ISeq
public interface ISeq extends IPersistentCollection { Object first(); ISeq next(); ISeq more()
我有一堆 Scala 类(如 Lift 的 Box、Scala 的 Option 等),我想要在 Clojure 中用作 Clojure ISeq。 我如何告诉 Clojure 如何将这些类放入 IS
我正在从 Java 程序调用 Clojure 库并返回 ISeq。 我如何在 Java 中遍历它?看起来这应该是直截了当的,但是查看库我无法弄清楚如何从 ISeq 中获取 Java 迭代器。 最佳答案
我的 Meteor 项目 Handlebars 助手: Handlebars.registerHelper('isEq', function(v1, v2, options){ if(v1 =
我有以下 clojure 代码(尝试从 redis 写入/获取条目): (ns hello.core2) (ns h hello.core2 (:require [taoensso.carmine :
我正在尝试打开一个文本文件并将其拆分为 Clojure 中的整数值列表。我每次都会收到此错误代码,但我不知道为什么。我是 Lisp 开发的新手(我的意思是我大约两个小时前就开始了),所以我可能问了一个
我正在尝试实现 Land of Lisp's Dice of Doom game我得到一个 Don't know how to create ISeq from: clojure.lang.Persi
我正在试验 clojure 宏,想知道我可能做错了什么? 我有一个简单的例子,尝试基于 map 动态创建函数。 例如: (def units {:cm 100 :mm 1000
我正在尝试了解新的 defprotocol、reify 等。 我有一个从 XPath 调用返回的 org.w3c.dom.NodeList,我想将其“转换”为 ISeq。 在Scala中,我实现了隐式
我有以下 Clojure 代码,但我不确定它为什么不起作用: (defn match (x y &optional binds) (cond ((eql x y) (values binds
我试图将代码分成 2 个文件,每个文件都有自己的命名空间。关注此 tutorial . 但我收到此错误: 线程“main”中的异常 java.lang.IllegalArgumentException
我是 Clojure 和 Lisp 的新手,但到目前为止很喜欢。我目前正在尝试了解 lazy-seq 和 Clojure 定义无限序列的能力。我有以下代码: (defn geometric ([]
在“Clojure in Action”(第 63 页)中处理以下示例: (defn basic-item-total [price quantity] (* price quantity))
我是一名优秀的程序员,十分优秀!