Lisp是否具有类似Haskell的takeWhile函数的功能?

问题描述

| 我是Common Lisp的新手。在Haskell中,您可以执行以下操作:
Prelude> takeWhile (<= 10) [k | k <- [1..]]
[1,2,3,4,5,6,7,8,9,10]
Lisp有可能吗?不一定有无限列表,而是任何列表。     

解决方法

        您可以使用LOOP:
(setq *l1* (loop for x from 1 to 100 collect x))
(loop for x in *l1* while (<= x 10) collect x)
如果您确实需要将其作为单独的功能:
(defun take-while (pred list)
  (loop for x in list
        while (funcall pred x)
        collect x))
我们在这里:
T1> (take-while (lambda (x) (<= x 10)) *l1*)
(1 2 3 4 5 6 7 8 9 10)
但是如果我们比较一下:
(loop for x in *l1* while (<= x 10) collect x)
(take-while (lambda (x) (<= x 10)) *l1*)
我想我只会坚持循环。 对于无限序列,您可以看一下Series:
T1> (setq *print-length* 20)
20
T1> (setq *l1* (scan-range :from 1))
#Z(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...)
T1> (until-if (lambda (x) (> x 10)) *l1*)
#Z(1 2 3 4 5 6 7 8 9 10)
    ,        这应该做...
(defun take-while (list test)
  (and list (funcall test (car list))
       (cons (car list) (take-while (cdr list) test))))

(take-while \'(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) (lambda (x) (< x 10)))
--> (1 2 3 4 5 6 7 8 9)
但是,此“自然”实现不是尾递归的,对于大列表可能会崩溃。 一个显式的推-逆方法(一种常见模式)可以是
(defun take-while (list test)
  (do ((res nil))
      ((or (null list) (not (funcall test (car list))))
         (nreverse res))
    (push (car list) res)
    (setf list (cdr list))))
递归(但尾递归,因此对于大多数CL实现而言可能是可以的),IMO可以是以下形式:
(defun take-while (list test)
  (labels ((rec (res x)
             (if (and x (funcall test (car x)))
                 (rec (cons (car x) res) (cdr x))
                 (nreverse res))))
    (rec nil list)))
请注意,但是不能保证通用的lisp实现会处理尾部调用优化。     ,        CL-LAZY库实现了对Common Lisp的延迟调用,并提供了惰性响应的随身携带功能。您可以使用Quicklisp进行安装并尝试一下。     ,        某些语言提供了Haskell样式的列表API作为第三方库,支持或不支持无限流。 一些例子: Clojure的序列:需要一段时间 Scala有东西 请记住,
takeWhile
在序列上相对容易实现,并且在Haskell中给出为:
takeWhile _ []          =  []
takeWhile p (x:xs)
            | p x       =  x : takeWhile p xs
            | otherwise =  []
    ,        您可以使用闭包(在Paul Graham的On Lisp中)对普通lisp进行懒惰的评估:
(defun lazy-right-fold (comb &optional base)
  \"Lazy right fold on lists.\"
  (labels ((rec (lst)
             (if (null lst)
                 base
                 (funcall comb
                          (car lst)
                          #\'(lambda () (rec (cdr lst)))))))
    #\'rec))
然后,花费时间变为:
(defun take-while (pred lst)
  (lazy-right-fold #\'(lambda (x f) (
                       (if (test x)
                           (cons x (funcall f))
                           (funcall f)))
                   nil))
    

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...