t = (1, 2)
a, b = t
...那么 a 将是 1,b 将是 2。假设我有一个列表 '(1 2)
在 Scheme 中。是否有任何方法可以使用 let
来实现类似的操作?如果有不同,请注意,我正在使用 Racket。
t = (1, 2)
a, b = t
...那么 a 将是 1,b 将是 2。假设我有一个列表 '(1 2)
在 Scheme 中。是否有任何方法可以使用 let
来实现类似的操作?如果有不同,请注意,我正在使用 Racket。
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
定义为“元组”,因为在(大多数)Scheme实现中,多个值不是一等值。
一个简单的惯用语是在你需要使用 let 的地方使用apply与lambda,例如:
(define t '(1 2))
(apply (lambda (a b)
;; code that would go inside let
)
t)
这种方法的优点是它可以在任何实现上运行。当然,这只能用于简单的情况,但有时这就是你所需要的。
你所寻找的通用术语(至少在Lisp世界中)是解构,实现它的宏称为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)
看起来有一个很好的scheme宏,实现了destructuring-bind。
这里提供了更多信息。
let-values
并不完全符合我想要的功能,而且我似乎无法让需要使用let+
的库正常工作。话虽如此,这个“面向Python程序员的Scheme”网站肯定会很有用。 - Jason Bakerlet+
的方法。干杯! - icyrock.com这是一个简单的destructuring-bind
宏,适用于具有case-lambda
(例如Racket或Chez Scheme)的scheme:
(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)) )
0m0.211s Chez Scheme
0m0.273s Bigloo
0m0.403s Chicken
0m0.598s Racket
将代码转换成 GHC Haskell 的速度比 Chez Scheme 快 5 倍。Guile 比任何一个 Scheme 实现都要慢得多。
除了易于利用现有的 case-lambda
代码之外,我喜欢这个宏接受与函数定义参数列表完全相同的语法。我喜欢 Scheme 的简洁性。我已经老到足以记得在打孔卡上编程 Fortran,那时允许的语法随上下文而变化。Scheme 应该比那更好。对于像这样的宏进行改进的冲动是不可抑制的。如果您不能证明在函数定义中改变语法也是必要的,那么在这里也不要改变语法。拥有正交的语法很重要。
从列表中:
(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))
let
的东西,而这个是用defines
定义的。我想我可以编写一个宏,将这样的定义插入到local
中。 - Jason Bakermatch-let
(附有一个示例),但是简单的match
也可以。 (您的问题使它看起来像您想要定义。)此外,您始终可以在本地作用域中使用定义。 - Eli Barzilayracket
语言。点击我提供的链接查看参考文档。 - Eli Barzilay