【问题标题】:Varadic zip in Racket球拍中的 Varadic 拉链
【发布时间】:2020-04-01 13:31:03
【问题描述】:

我在 Racket 中看到了otheranswers 的压缩功能,但它们首先不太正确(zip 应该只压缩到提供的最短序列,以便您可以使用无限流进行压缩) 并且最重要的是不是可变的,因此您一次只能压缩两个流。

我已经想通了

 (define (zip a-sequence b-sequence) (for/stream ([a a-sequence]
                                                  [b b-sequence])
                                       (list a b)))

确实可以正常工作

 (stream->list (zip '(a b c) (in-naturals)))
  => '((a 0) (b 1) (c 2))

但不是可变的。我知道我可以使用define (zip . sequences) 将其定义为可变参数,但我不知道如何构建for/stream 表单。

这必须是一个宏才可行吗?

【问题讨论】:

    标签: stream scheme lisp racket


    【解决方案1】:

    这对你有用吗?

    #lang racket
    
    (define (my-zip . xs)
      (match xs
        [(list x) (for/stream ([e x]) (list e))]
        [(list x xs ...)
         (for/stream ([e x] [e* (apply my-zip xs)])
           (cons e e*))]))
    
    (stream->list
     (my-zip (in-naturals) '(a b c) '(1 2 3 4 5 6)))
    ;;=> '((0 a 1) (1 b 2) (2 c 3))
    

    【讨论】:

    • 哦,这很有趣......是的,看起来它会起作用......所以我确定我在那里看到的内容:如果确切存在,第一个 match 子句将匹配一个列表传递,在这种情况下,您将输出一个列表流,其中每个列表都有一个项目。如果有多个,则第二个将匹配...然后它将采用第一个流x,并且对于其中的每个项目,它将将zip应用于其余部分...。但是e*是什么部分?
    • 另外,虽然我可以看到这个作品,但我很惊讶(list x) 上的匹配适用于不是列表而是无限流的东西
    • 问:虽然我可以看到这项工作,但我很惊讶(列表 x)上的匹配适用于不是列表而是无限流的东西 答:不,我们确实在列表上匹配。如果我们要在无限流上匹配,就会出现错误。注意xs 不是my-zip 的参数,而是一个参数列表。问:e* 部分是什么 答:我认为这可能会有所帮助:(my-zip (in-naturals) '(a b c) '(1 2 3 4 5 6))) = (for/stream ([e (in-naturals)] [e* (stream (list 'a 1) (list 'b 2) (list 'c 3)]) (cons e e*))
    【解决方案2】:

    zip 的常见实现是:

    (require data/collection) ; for a `map` function that works with streams
    
    (define (zip . xs)
      (apply map list xs))
    

    ...如果您更喜欢point-free style,这可以很简单:

    (require racket/function)
    (define zip (curry map list))
    

    这些确实有限制,即它们要求所有输入序列具有相同的长度(包括无限长),但由于它们是惰性计算的,因此它们在任何情况下都可以工作,直到其中一个序列用完,此时会出现错误将被提高。

    (zip (cycle '(a b c))
         (naturals)
         (cycle '(1 2 3))) ; => '((a 0 1) (b 1 2) (c 2 3) (a 3 1) ...
    

    [已更新答案以反映 cmets]

    【讨论】:

    • 这不会产生一个流流,而 OP 想要一个列表流?无论如何,我们只有有限数量的参数,所以list 应该很好。使用“与流一起使用的map”,您的第一个sn-p 就足够了,不是吗?我错过了什么吗?
    • 你是对的,@WillNess!如果有有限数量的可能无限的输入序列,那么第一个 sn-p(连同惰性映射)就足够了。我可能误解了这个问题,暗示 OP 也想支持无限数量的压缩序列。但是现在我正在考虑它,我不确定 Racket 是否能够懒惰地提供 xs 参数——我认为它是提供给 my-stream 的列表而不是流。在这种情况下,后面的 sn-p 毕竟可能不适用于无限流的无限流......
    猜你喜欢
    • 2012-10-14
    • 1970-01-01
    • 2021-02-07
    • 2021-12-21
    • 1970-01-01
    • 2019-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多