实现“Pythonic”方案中的地图:坏主意?

发布于 2024-11-08 23:51:16 字数 750 浏览 0 评论 0原文

在Scheme中,函数(map fn list0 [list1 .. listN])带有列表必须具有相同数量元素的限制。来自 Python,我缺少 Python 列表推导式的自由,它看起来很像上面的 map,但没有这个限制。

我很想实现一个替代的“my-map”,它允许不同大小的列表,迭代所有列表的前 N ​​个元素,其中 N 是最短列表的长度。

例如,令 num10lst(1 2 3)。使用 my-map,我希望编写如下表达式:

(my-map + (circular-list num) lst)))

并得到:

(11 12 13)

相比,我更容易阅读此内容

(map + (lambda (arg) (+ num arg)) lst)

与更传统的或

(map + (make-list (length lst) num) lst) 

两个问题

  • :作为一个方案新手,我是否忽略了对“map”限制的重要原因?
  • 方案或 SRFI 中是否已存在诸如“my-map”之类的内容?我确实查看了 srfi-42,但要么不是我要找的,要么就是,但并不明显。

In Scheme, the function (map fn list0 [list1 .. listN]) comes with the restriction that the lists must have the same number of elements. Coming from Python, I'm missing the freedom of Python list comprehensions, which look a lot like map above, but without this restriction.

I'm tempted to implement an alternative "my-map", which allows for lists of differing size, iterating through the first N elements of all lists, where N is the length of the shortest list.

For example, let num be 10 and lst be (1 2 3). With my-map, I hope to write expressions like:

(my-map + (circular-list num) lst)))

And get:

(11 12 13)

I have an easier time reading this than the more conventional

(map + (lambda (arg) (+ num arg)) lst)

or

(map + (make-list (length lst) num) lst) 

Two questions:

  • As a Scheme newbie, am I overlooked important reasons for the restriction on `map`?
  • Does something like `my-map` already exist in Scheme or in the SRFIs? I did take a look at srfi-42, but either it's not what I'm looking for, or it was, and it wasn't obvious.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

天涯沦落人 2024-11-15 23:51:16

首先,请注意 map 确实允许空列表,但当然,如果有一个空列表,那么所有列表都应该为空。

其次,查看 srfi-1 版本的 地图——它与R5RS版本的具体区别如下:

此过程从 R5RS 规范扩展而来,允许参数长度不等;当最短列表用完时它终止。

第三,大多数Scheme 程序员会非常喜欢

(map (lambda (arg) (+ num arg)) lst)

我的猜测是Scheme 与Python 的不同之处在于,随着您习惯该语言,Scheme 使得lambda 表达式变得越来越可读。

最后,有一些实现带有某种形式的列表理解。例如,在 Racket 中你可以这样写:

(for/list ([arg lst]) (+ num arg))

First, note that map does allow empty lists, but of course if there's one empty list then all of them should be empty.

Second, have a look at the srfi-1 version of map -- it is specifically different from the R5RS version as follows:

This procedure is extended from its R5RS specification to allow the arguments to be of unequal length; it terminates when the shortest list runs out.

Third, most Scheme programmers would very much prefer

(map (lambda (arg) (+ num arg)) lst)

My guess is that Scheme is different from Python in a way that makes lambda expressions become more and more readable as you get used to the language.

And finally, there are some implementations that come with some form of a list comprehension. For example, in Racket you can write:

(for/list ([arg lst]) (+ num arg))
喜爱皱眉﹌ 2024-11-15 23:51:16

您提到查看SRFI-42,但说它不是很明显如何像使用 Python 列表理解一样使用它。因此,演示(使用 Gauche 但它受 一些流行的Scheme实现):

gosh$ (import (scheme base) (srfi 42))
gosh[r7rs.user]$ (define num 10)
num
gosh[r7rs.user]$ (define lst '(1 2 3))
lst
gosh[r7rs.user]$ (list-ec (: i lst) (+ i num))
(11 12 13)

如果你想一次迭代多个列表,在最短的地方停止,就像评论中的 Python 示例 [f(x, y) for x, y in zip(x_list, y_list)] 一样,它看起来像:

(list-ec (:parallel (: x x-list) (: y y-list)) (f x y))

You mentioned looking at SRFI-42, but said it wasn't obvious how to use it like you would a Python list comprehension. So, a demonstration (using Gauche but it's supported by a number of popular Scheme implementations):

gosh$ (import (scheme base) (srfi 42))
gosh[r7rs.user]$ (define num 10)
num
gosh[r7rs.user]$ (define lst '(1 2 3))
lst
gosh[r7rs.user]$ (list-ec (: i lst) (+ i num))
(11 12 13)

If you want to iterate over multiple lists at once, stopping at the shortest, like the Python example [f(x, y) for x, y in zip(x_list, y_list)] from a comment, it'd look like:

(list-ec (:parallel (: x x-list) (: y y-list)) (f x y))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文