相当于 Python 范围函数的 OCaml 习惯用法是什么?
我想创建一个从 1 到 n 的整数列表。 我可以在 Python 中使用 range(1, n+1)
来完成此操作,在 Haskell 中使用:take n (iterate (1+) 1)
来完成此操作。
正确的 OCaml 习惯用法是什么?
I want to create a list of integers from 1 to n
. I can do this in Python using range(1, n+1)
, and in Haskell using: take n (iterate (1+) 1)
.
What is the right OCaml idiom for this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
我不知道有什么习语,但这里有一个使用中缀运算符的相当自然的定义:
或者, 推导语法扩展(为上述内容提供语法
[i .. j]
)可能会包含在 OCaml 的“社区版本”,因此这可能会成为惯用语。 不过,如果您是该语言的新手,我不建议您开始使用语法扩展。There is no idiom that I know of, but here is a fairly natural definition using an infix operator:
Alternatively, the comprehensions syntax extension (which gives the syntax
[i .. j]
for the above) is likely to be included in a future release of the "community version" of OCaml, so that may become idiomatic. I don't recommend you start playing with syntax extensions if you are new to the language, though.这适用于基础 OCaml:
This works in base OCaml:
使用 Batteries Included,您可以编写
--
运算符根据第一个值到第二个值。--^
运算符类似,但枚举半开区间(1--^10
将枚举从 1 到 9)。With Batteries Included, you can write
The
--
operator generates an enumeration from the first value to the second. The--^
operator is similar, but enumerates a half-open interval (1--^10
will enumerate from 1 through 9).给你:
请注意,这不是尾递归。 现代 Python 版本甚至有一个惰性范围。
Here you go:
Note that this is not tail-recursive. Modern Python versions even have a lazy range.
从上面跟随亚历克斯·考文垂,但更短。
Following on Alex Coventry from above, but even shorter.
如果您打算模拟
range
的惰性行为,我实际上建议使用Stream
模块。 就像是:If you intend to emulate the lazy behavior of
range
, I would actually recommend using theStream
module. Something like:OCaml 有用于范围模式匹配的特殊语法:
要创建范围,您可以使用
Core
< /a>:OCaml has special syntax for pattern matching on ranges:
To create a range, you can use
Core
:想出了这个:
Came up with this:
游戏有点晚了,但这是我的实现:
然后您可以像 python 函数一样使用它:
当然,我认为最好的答案是简单地使用 Core,但如果您只需要一个函数并且您'我们试图避免使用完整的框架。
A little late to the game here but here's my implementation:
You can then use it very much like the python function:
naturally I think the best answer is to simply use Core, but this might be better if you only need one function and you're trying to avoid the full framework.
为了好玩,这里有一个非常类似于 Python 的
range
实现,使用惰性序列:因此您可以通过以下方式获取从 1 到
n
的整数列表:它还提供了其他 Python类似的行为,例如默认从 0 开始简洁地计数:
...或向后计数:
For fun, here's a very Python-like implementation of
range
using a lazy sequence:So you can get a list of integers from 1 to
n
by:It also gives other Python-like behaviours, such as concisely counting from 0 by default:
...or counting backwards:
如果您使用
open Batteries
(这是标准库的社区版本),您可以通过List.range 1执行
(注意range(1,n+1)
`To nTo
之前的反引号)。更通用的方法(也需要电池)是使用 List.init n f ,它返回一个包含 (f 0) (f 1) ... (f (n-1)) 的列表。
If you use
open Batteries
(which is a community version of the standard library), you can dorange(1,n+1)
byList.range 1 `To n
(notice the backquote beforeTo
).A more general way (also need batteries) is to use
List.init n f
which returns a list containing (f 0) (f 1) ... (f (n-1)).这是我使用 Base.Sequence 的版本
用法示例:
Here is my version using Base.Sequence
Example usages:
如果您不需要“step”参数,实现此功能的一种简单方法是:
If you don't need a "step" parameter, one easy way to implement this function would be:
就我个人而言,我使用 OCaml 的 range 库来实现此目的。
Personally I use the range library of OCaml for that.
这里的很多答案都描述了从 A 到 B 获取列表的严格评估或惰性方法,有时是通过步骤 C。然而,Python 的
range
有一个关键方面尚未涵盖:在 Python 3.x 中,检查范围中的成员资格是 O(1) 操作,而检查列表(或惰性序列)中的成员资格是 O(n) 操作。如果我们将范围实现为抽象类型,则可以实现一个 mem 函数,该函数以 O(1) 的方式检查范围中的成员资格。
A lot of answers here describe either strictly evaluated or lazy ways to get a list from A to B, and sometimes by a step C. However, there is one critical aspect of Python's
range
that has not been covered: in Python 3.x checking for membership in a range is an O(1) operation, while checking for membership in a list (or a lazy sequence) is an O(n) operation.If we implement ranges as an abstract type, we can implement a
mem
function which checks for membership in a range in an O(1) fashion.