scheme - 可以在 if/cond 中使用 let 吗?
问题描述
我经常发现自己想要使用列表中的当前元素,而不是总是需要在其上运行一个过程来获取它,例如使用elem
而不是(car sequence)
每次我想引用序列中的当前元素时。这有效......除非序列为空,所以我不能把它放在检查let
之前null
。这是我试图做的“模式”:
(define (filter sequence)
; return a list of only those items where the filter predicate returns true
(cond ((null? sequence) nil)
; now that we know we have an active sequence, I want to short-hand 'elem' and 'rest'
(let (elem car sequence)
(rest cdr sequence))
(display elem)))
但后来我得到一个错误说let: bad syntax
。有没有办法以某种方式完成上述模式?
Upate:也许最好的方法就是let
通过简单的检查将 a 放在顶部if
?就像是:
(define (filter sequence)
(let ((elem (if (null? sequence) nil (car sequence)))
(rest (cdr sequence)))
(cond ((null? sequence) nil)
(display elem))))
解决方案
[这是我昨晚开始写的 coredump 答案的附录(我认为这是正确的答案),所以我会把它留给后代。]
从您的代码开始:
(define (filter sequence)
(cond ((null? sequence) nil)
(let (elem car sequence)
(rest cdr sequence))
(display elem)))
这里至少存在三个问题:首先,您搞砸了 的语法cond
,即(部分)
(cond (<test> <expr> ...)
...
(else <expr> ...))
因此,要修复此问题,您需要添加一个显式else
子句:
(define (filter sequence)
(cond ((null? sequence) nil)
(else
(let (elem car sequence)
(rest cdr sequence))
(display elem))))
现在的问题(这个问题的错误是cond
由于某种原因掩盖了错误)是你搞砸了 的语法let
,它是(再次,部分地):
(let ((<var> <val>) ...) <expr> ...)
您在这里犯了两个单独的错误:您错过了绑定表单周围的括号,并且表达式根本不在正文中let
。所以,修复那些:
(define (filter sequence)
(cond ((null? sequence) nil)
(else
(let ((elem car sequence)
(rest cdr sequence))
(display elem)))))
car
我们现在得到了最终的错误:对&的调用没有括号cdr
。所以修复那些:
(define (filter sequence)
(cond ((null? sequence) nil)
(else
(let ((elem car sequence)
(rest cdr sequence))
(display elem))))
好吧,现在这仍然不正确,那是因为您错过了对car
and的调用的括号cdr
:
(define (filter sequence)
(cond ((null? sequence) nil)
(else
(let ((elem (car sequence))
(rest (cdr sequence)))
(display elem)))))
这现在有效,但它实际上并没有过滤序列。为此,它需要递归:
(define (filter sequence)
(cond ((null? sequence) nil)
(else
(let ((elem (car sequence))
(rest (cdr sequence)))
(if (null? elem)
(filter rest)
(cons elem (filter rest)))))))
将内部条件提升到cond
:
(define (filter sequence)
(cond ((null? sequence) nil)
((null (car sequence)) (filter (cdr sequence)))
(else (cons (car sequence) (filter (cdr sequence))))))
尽管现在您遇到了多次调用car
&cdr
我认为您想避免的问题。
如果您使用完整的 Racket,一种很好的表达方式是使用匹配,它可以以一种很好的方式结合检查和绑定:
(define (filter sequence)
(match sequence
['() '()]
[(cons '() tail)
(filter tail)]
[(cons head tail)
(cons head (filter tail))]))
推荐阅读
- android - 我不知道如何编辑数据库中的现有值以及如何从 firebase 中提取 id(例如:-MZiVzNSpCBk_4o3GhSn)
- android - 如何访问 BottomNavigationBar Demo 创建的 Fragment
- python - 如何在 aiohttp python 中限制多部分请求中的文件大小?
- widget - 从范围“人力资源:服务门户”读取表“sn_hr_integrations_todo_inbound”的操作被拒绝
- javafx - JavaFX 添加图像视图
- php - PHP `mysqli_multi_query` 无法返回值
- java - 如何在 MySQL 中为嵌套类使用创建表
- android - 在 Flutter 中使用 TabBarView 和 DraggableScrollableSheet
- amazon-web-services - 为 Elastic Beanstalk 允许 https
- angular - Angular Firestore 身份验证在 IE11 上不起作用