是否有Clojure'的惰性函数的完整列表;什么是核心模块?
在与Clojure合作一段时间后,我对它的懒惰有了一些了解。我知道像map这样的常用API是否是懒惰的。然而,当我开始使用一个不熟悉的API(比如OpenAPI)时,我仍然感到怀疑是否有Clojure'的惰性函数的完整列表;什么是核心模块?,clojure,Clojure,在与Clojure合作一段时间后,我对它的懒惰有了一些了解。我知道像map这样的常用API是否是懒惰的。然而,当我开始使用一个不熟悉的API(比如OpenAPI)时,我仍然感到怀疑 是否有任何文档显示Clojure核心模块的惰性API的完整列表?您可以通过打开Clojure代码找到返回惰性序列的函数 搜索“返回一个懒人” 我不知道他们的任何策划名单 经验法则是:如果它返回一个序列,它将是一个惰性序列,如果它返回一个值,它将强制求值 当使用新函数、宏或特殊表单时,请读取docstring。大多数开
是否有任何文档显示Clojure核心模块的惰性API的完整列表?您可以通过打开Clojure代码找到返回惰性序列的函数 搜索“返回一个懒人” 我不知道他们的任何策划名单 经验法则是:如果它返回一个序列,它将是一个惰性序列,如果它返回一个值,它将强制求值 当使用新函数、宏或特殊表单时,请读取docstring。大多数开发环境都有一个键来显示docstring,或者至少导航到源代码(在那里您可以看到docstring),并且总是有 在打开的情况下: 敞开 宏 用法:(带开放绑定和正文) 绑定=>[name init…] 在名称绑定到值的try表达式中计算主体 以及一个finally子句,该子句在每个 按相反顺序命名 我们可以看到,使用open调用的结果是使用final close对表达式求值。所以我们知道,这并不是懒惰。然而,这并不意味着你不需要用开放的心态去思考内心的懒惰,恰恰相反
(with-open [r (io/reader "myfile")]
(line-seq r))
这是一个常见的陷阱<代码>行序列返回一个延迟序列!这里的问题是,延迟序列将在文件关闭后实现,因为当使用open退出的作用域时,文件将关闭。因此,您需要在退出具有打开作用域的前完全处理惰性序列
我的建议是,不要试图将你的程序视为具有“惰性位”和“即时位”,而是要记住,当涉及io或副作用时,你需要注意事情发生的时间以及应该发生的事情。深入了解Timothy Pratley关于搜索doc的建议:
让我们一起玩吧
您的repl拥有查找惰性函数列表所需的一切
首先,有一个clojure.repl/doc
宏,它将文档打印到repl中
不幸的是,我们不能简单地获得它的字符串,但我们总是可以将*out*
重新绑定为StringWriter
,然后获取它的字符串值
那么,我们要从clojure.core
名称空间中获取所有符号,获取它们的文档,将它们全部写入字符串,并找到每个包含“returns a lazy”的符号。下面是帮助:clojure.core/ns publics
,将公共名称映射返回给他们的变量:
user> (take 10 (ns-publics 'clojure.core))
([primitives-classnames #'clojure.core/primitives-classnames]
[+' #'clojure.core/+']
[decimal? #'clojure.core/decimal?]
[restart-agent #'clojure.core/restart-agent]
[sort-by #'clojure.core/sort-by]
[macroexpand #'clojure.core/macroexpand]
[ensure #'clojure.core/ensure]
[chunk-first #'clojure.core/chunk-first]
[eduction #'clojure.core/eduction]
[tree-seq #'clojure.core/tree-seq])
所以我们只需要从那里获取所有密钥并查找他们的文档。
让我们为此制作一个宏:
user> (defmacro all-docs []
(let [names (keys (ns-publics 'clojure.core))]
`(binding [*out* (java.io.StringWriter.)]
(do ~@(map #(list `doc %) names))
(str *out*))))
#'user/all-docs
这正是我所说的,让所有公众的文件串
现在我们只需处理它:
user> (def all-doc-items (clojure.string/split
(all-docs)
#"-------------------------"))
#'user/all-doc-items
user> (nth all-doc-items 10)
"\nclojure.core/tree-seq\n([branch? children root])\n Returns a lazy sequence of the nodes in a tree, via a depth-first walk.\n branch? must be a fn of one arg that returns true if passed a node\n that can have children (but may not). children must be a fn of one\n arg that returns a sequence of the children. Will only be called on\n nodes for which branch? returns true. Root is the root node of the\n tree.\n"
现在只需过滤它们:
user> (def all-lazy-fns (filter #(re-find #"(?i)returns a lazy" %) all-doc-items))
#'user/all-lazy-fns
user> (count all-lazy-fns)
30
user> (println (take 3 all-lazy-fns))
(
clojure.core/tree-seq
([branch? children root])
Returns a lazy sequence of the nodes in a tree, via a depth-first walk.
branch? must be a fn of one arg that returns true if passed a node
that can have children (but may not). children must be a fn of one
arg that returns a sequence of the children. Will only be called on
nodes for which branch? returns true. Root is the root node of the tree.
clojure.core/keep-indexed
([f] [f coll])
Returns a lazy sequence of the non-nil results of (f index item). Note,
this means false return values will be included. f must be free of
side-effects. Returns a stateful transducer when no collection is
provided.
clojure.core/take-nth
([n] [n coll])
Returns a lazy seq of every nth item in coll. Returns a stateful
transducer when no collection is provided.
)
nil
现在,您可以随意使用这些所有懒惰的FN
。我认为您对Clojure中的懒惰概念有点困惑。没有惰性函数,只有惰性序列。另外,与open
完全不是一个函数;这是一个宏。考虑到这些信息,使用open
的是否是一个惰性函数的问题毫无意义。
user> (def all-lazy-fns (filter #(re-find #"(?i)returns a lazy" %) all-doc-items))
#'user/all-lazy-fns
user> (count all-lazy-fns)
30
user> (println (take 3 all-lazy-fns))
(
clojure.core/tree-seq
([branch? children root])
Returns a lazy sequence of the nodes in a tree, via a depth-first walk.
branch? must be a fn of one arg that returns true if passed a node
that can have children (but may not). children must be a fn of one
arg that returns a sequence of the children. Will only be called on
nodes for which branch? returns true. Root is the root node of the tree.
clojure.core/keep-indexed
([f] [f coll])
Returns a lazy sequence of the non-nil results of (f index item). Note,
this means false return values will be included. f must be free of
side-effects. Returns a stateful transducer when no collection is
provided.
clojure.core/take-nth
([n] [n coll])
Returns a lazy seq of every nth item in coll. Returns a stateful
transducer when no collection is provided.
)
nil