在Scheme中实现“Pythonic”地图:坏主意?

问题描述 投票:0回答:2

在Scheme中,函数

(map fn list0 [list1 .. listN])
有一个限制,即列表必须具有相同数量的元素。来自Python,我错过了Python列表推导式的自由,它看起来很像上面的
map
,但没有这个限制。

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

例如,令

num
10
lst
(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) 

两个问题:

  • 作为一个Scheme新手,我是否忽略了`map`限制的重要原因?
  • 类似“my-map”的东西是否已经存在于Scheme或SRFI中?我确实查看了 srfi-42,但要么不是我要找的,要么就是,但并不明显。
scheme list-comprehension map-function
2个回答
6
投票

首先,请注意

map
允许空列表,但当然,如果有一个空列表,那么所有列表都应该为空。

其次,看一下map

srfi-1版本——它与R5RS版本的具体区别如下:

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

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

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

我的猜测是,Scheme 与 Python 的不同之处在于,当您习惯该语言时,

lambda
表达式变得越来越可读。

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

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

0
投票

您提到查看 SRFI-42,但表示如何像 Python 列表理解一样使用它并不明显。所以,一个演示(使用Gauche,但它得到一些流行的方案实现的支持):

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))
© www.soinside.com 2019 - 2024. All rights reserved.