【问题标题】:What is scheme's equivalent of tuple unpacking?什么是方案相当于元组拆包?
【发布时间】:2011-05-12 08:30:34
【问题描述】:

在 Python 中,我可以这样做:

t = (1, 2)
a, b = t

...a 为 1,b 为 2。假设我在 Scheme 中有一个列表 '(1 2)。有什么方法可以用let 做类似的事情吗?如果它有所作为,我正在使用 Racket。

【问题讨论】:

    标签: list scheme racket iterable-unpacking


    【解决方案1】:

    在球拍中你可以使用match

    (define t (list 1 2))
    (match [(list a b) (+ a b)])
    

    和相关的东西,比如match-define:

    (match-define (list a b) (list 1 2))
    

    match-let

    (match-let ([(list a b) t]) (+ a b))
    

    这适用于列表、向量、结构等。对于多个值,您可以使用define-values

    (define (t) (values 1 2))
    (define-values (a b) (t))
    

    let-values。但请注意,我不能将 t 定义为“元组”,因为在(大多数)方案实现中,多个值不是一等值。

    【讨论】:

    • 这行得通,但我正在寻找使用let 的东西,而这个defines 它。我想我可以编写一个宏,将这样的定义拼接到local
    • 嗯,有match-let(更新了一个例子),但一个简单的match 也可以。 (您的问题使它看起来像您想要定义。)此外,您始终可以在本地范围内使用定义。
    • 第一个例子没有运行(在我的脑海里没有意义)
    • 您应该使用racket 语言。单击我提供的链接以查看参考文档。
    【解决方案2】:

    一个简单的习惯用法是将 applylambda 一起使用,而您将使用 ,比如:

    (define t '(1 2))
    (apply (lambda (a b)
              ;; code that would go inside let
            )
            t)
    

    优点是它适用于任何实现。当然这只能用于简单的情况,但有时这就是你所需要的。

    【讨论】:

      【解决方案3】:

      您正在寻找的东西的通用术语(至少在 Lisp 世界中)是 destructuring,实现它的宏称为 destructuring-bind。在 Common Lisp 中,它是这样工作的:

      (destructuring-bind (a b c) '(1 2 3)
        (list a b c)) ;; (1 2 3)
      

      它也适用于多个“级别”的嵌套:

      (destructuring-bind (a (b c) d) '(1 (2 3) 4)
        (list a b c d)) ;; (1 2 3 4)
      

      看起来有一个 nice implementation 的解构绑定作为方案宏。

      【讨论】:

        【解决方案4】:

        我想这就是你要找的:

        查看let-valueslet+

        【讨论】:

        • 感谢您发布此信息!唯一的问题是let-values 没有完全 完成我想要它做的事情,而且我似乎无法让使用let+ 所需的库工作。也就是说,这个“Python 程序员计划”网站肯定会派上用场。
        • 好吧,如果你遇到其他问题,至少你有一个很酷的新网站可以挖掘。看看它,希望你能找到如何为let+ 设置环境。干杯。
        【解决方案5】:

        这是一个简单的destructuring-bind 宏,用于带有case-lambda 的方案(例如Racket 或Chez 方案):

        (define-syntax bind
           (syntax-rules ()
              ((_ arg pat def body)
                 (apply
                    (case-lambda
                       [pat body]
                       [x def] )
                    arg ))))
        

        这是促使我编写此宏的示例。将默认值放在正文之前使代码可读:

        (define (permutations l)
           ;
           (define (psub j k y)
              ;
              (define (join a b)
                 (bind a (ah . at) b
                    (join at (cons ah b)) ))
              ;
              (define (prec a b z)
                 (bind b (bh . bt) z
                    (prec (cons bh a) bt
                       (psub (cons bh j) (join a bt) z) )))
              ;
              (if (null? k)
                 (cons (reverse j) y)
                 (prec (list) k y) ))
           ;
           (psub (list) (reverse l) (list)) )
        

        以下是在各种方案中计算长度为 9 的排列的基准:

        0m0.211s Chez Scheme
        0m0.273s Bigloo
        0m0.403s Chicken
        0m0.598s Racket
        

        翻译成 GHC Haskell 的速度比 Chez Scheme 快 5 倍。 Guile 比这些方案中的任何一个都慢。

        除了易于利用现有的case-lambda 代码之外,我喜欢这个宏如何接受与函数定义参数列表完全相同的语法。我喜欢简单的方案。我已经足够大,可以记住在穿孔卡片上编程 Fortran,其中允许的语法随上下文而变化很大。 Scheme应该比这更好。像这样在宏上建立百合花的冲动是压倒性的。如果您也不能证明更改函数定义的语法是合理的,那么也不要在此处更改该语法。拥有正交语法很重要。

        【讨论】:

          【解决方案6】:

          如果您不想引入 match 依赖项,这在 Racket 中有效:

          从列表中:

          (let-values ([(a b c) (apply values '(1 2 3))])
            (+ a b c))
          

          或直接来自值表达式:

          (let-values ([(a b c) (values 1 2 3)])
            (+ a b c))
          

          【讨论】:

            猜你喜欢
            • 2016-12-21
            • 2013-11-21
            • 1970-01-01
            • 1970-01-01
            • 2023-03-15
            • 2021-10-01
            • 2011-03-22
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多