什么是方案相当于元组解包?

时间:2010-11-18 22:58:53

标签: list scheme racket iterable-unpacking

在Python中,我可以这样做:

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

...并且a将为1,b将为2.假设我在Scheme中有一个列表'(1 2)。有没有办法与let做类似的事情?如果它有所作为,我正在使用Racket。

6 个答案:

答案 0 :(得分:25)

在球拍中,您可以使用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定义为“元组”,因为多个值在(大多数)方案实现中不是第一类值。

答案 1 :(得分:8)

一个简单的习惯用法是 应用 lambda 一起使用 ,例如:

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

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

答案 2 :(得分:7)

您正在寻找的内容(至少在Lisp-world中)的一般术语是 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的destructuring-bind作为一个方案宏。

答案 3 :(得分:4)

我认为这就是你要找的东西:

查看let-valueslet+

答案 4 :(得分:0)

如果您不想引入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))

答案 5 :(得分:0)

这是一个简单的destructuring-bind宏,用于具有case-lambda的方案(例如球拍或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程序,其中允许的语法随上下文而变化。计划应该比这更好。这种将百合花引导到这样的宏上的冲动是压倒性的。如果您也无法为函数定义更改语法,那么也不要在此处更改该语法。拥有正交语法很重要。