racket - Racket 的 findf 和 for/first 函数有什么区别?

标签 racket

Racket 有一个 findf 函数,可让您查找列表中的第一个匹配元素...

(findf even? '(1 2 3 4))

但是,它还有一个 for/first 函数,它似乎具有相同的功能,尽管语法更复杂......

(for/first ([n '(1 2 3 4)] #:when (even? n)) n)

两者之间有什么区别,鉴于 findf 看起来更短,为什么我要使用 for/first

谢谢

最佳答案

不同之处在于 for/firstfor 类似,因此您拥有 Racket for 的全部功能。可用语法:

> (for/first ([i '(1 2 3)]
              [j "abc"]
              #:when (odd? i)
              [k #(#t #f)])
    (list i j k))
'(1 #\a #t)

要使用 findf 实现相同的效果,您必须预先生成整个列表:

> (findf (λ (x) (odd? (first x)))
         (for/list ([i '(1 2 3)]
                    [j "abc"]
                    [k #(#t #f)])
           (list i j k)))
'(1 #\a #t)

对于搜索单个列表,您是正确的,使用 findf 可能是正确的函数。它很简单并且可以满足您的需要。但如果您想搜索更复杂的列表或需要创建内联的列表,for/first 更好。


这里有一些更简单的示例,向您展示 for/first 的强大功能(以及 for)。

假设您有两个变量,一个数字列表和一个字母字符串,您希望将它们一对一配对并返回数字为偶数的第一对变量。

(define numbers (range 1 27)) ; numbers 1 to 26
(define alphabet "abcdefghijklmnopqrstuvwxyz")

使用findf,您需要首先将字符串转换为字符列表,然后将两个列表压缩成对,然后创建一个 lambda(匿名函数)来检查给定的对是否存在有偶数。

(findf (lambda (pair) (even? (first pair)))
      (map list numbers (string->list alphabet)))

使用for/first,需要为每个序列分配一个标识符,然后在#:when子句中引用该数字标识符来检查该数字是否为甚至。 (for 并行迭代每个序列,在字符串上调用 string->list,并且仅在 #:when 时评估正文> 返回 true。)

(for/first ([num numbers]
            [str alphabet]
            #:when (even? num))
  (list num str))

就字符数而言,它们大致相等(94 到 102),但就清晰度而言,我认为 for/first 的作用更明显:获取两个集合,同时迭代两者,仅在数字为偶数时评估主体,并返回一个列表。

如果我们想返回第一对数字为偶数且大于 10 的值怎么办?在这里我们开始看到事情变得笨拙。

(findf (lambda (pair)
         (let ([num (first pair)])
           (and (even? num)
                (> num 10))))
       (map list numbers (string->list alphabet)))

对比

(for/first ([num numbers]
            [str alphabet]
            #:when (even? num)
            #:when (> num 10))
  (list num str))
;; or
(for/first ([num numbers]
            [str alphabet]
            #:when (and (even? num)
                        (> num 10)))
  (list num str))

每个 for 变体(for/firstfor/list 等)对主体的作用略有不同,但迭代逻辑是相同的,允许作者准确表达他们的意图,而无需重新实现该逻辑。

关于racket - Racket 的 findf 和 for/first 函数有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67826639/

相关文章:

scheme - 有没有办法在方案中使用 cons 来制作 lat?

scheme - 当 'cond' 被省略时,Scheme 'else' 子句中会发生什么?

Racket 简单AE定义类型

racket - 通过宏绑定(bind)自引用

haskell - Scheme/Racket有枚举操作吗?

scheme - 计划和 Racket 中的案例和报价

scheme - 反转整数

scheme - 来自 Racket 的产卵或系统

lisp - 如何在 DrRacket 中运行 Metacircular Evaluator

list - 以 "overlapped"的方式向列表添加值