Functional programming 不从LISP/Scheme返回任何内容

Functional programming 不从LISP/Scheme返回任何内容,functional-programming,scheme,lisp,racket,map-function,Functional Programming,Scheme,Lisp,Racket,Map Function,基本上,我想使用map在列表中进行选择,如 (define tbl '(a b c d)) (map (lambda (item 'c) (if (eq? item 'c) item (...what in else?) ))) 我想要的结果是 '(c) 我试着将else部分留空,它抱怨需要else部分。 我试过了 (display "foo") 作为另一部分,我得到了 (#<void> #<void> c #<void>) (##c#) 很接近

基本上,我想使用map在列表中进行选择,如

(define tbl '(a b c d))
(map (lambda (item 'c) (if (eq? item 'c) item (...what in else?) )))
我想要的结果是

'(c)
我试着将else部分留空,它抱怨需要else部分。 我试过了

(display "foo") 
作为另一部分,我得到了

(#<void> #<void> c #<void>)
(##c#)
很接近

有没有什么方法可以用map来获取'(c)?我知道递归的方法,但我想知道map是否也能做到这一点。如果不是“(c),则至少(##c#),但不使用display hack实现void类型返回值


您想使用,而不是-因为输出列表的元素可能比输入列表的元素少。所有由
display
返回的
#
值都存在,因为
map
将始终在输出列表中包含结果,即使对于我们不感兴趣的元素也是如此

(define tbl '(a b c d))

(filter (lambda (item) (eq? item 'c)) tbl)
=> '(c)
相等地,并且稍微短一点:

(filter (curry eq? 'c) tbl)
=> '(c)
map
用于在不丢弃元素的情况下对输入列表中的每个元素执行操作。另一方面,
filter
用于选择输入列表中的一些元素,对于给定谓词,这些元素的计算结果为
#t
,而
filter
在大多数方案解释器中可用,如果不可用,则可以导入或使用

仅仅使用
map
(可以使用
map
apply
remove*
等方法对其进行黑客攻击)是无法获得
(c)
,但这不是想法,不是吗;如果出于某种原因,您必须只使用
映射
,并且不介意返回带有占位符的列表,这里有两个备选方案:

(map (lambda (item) (if (eq? item 'c) item '%)) tbl) ; placeholder in else part
=> '(% % c %)

(map (lambda (item) (when (eq? item 'c) item)) tbl)  ; when has implicit #<void>
=> '(#<void> #<void> c #<void>)
使用
map
plus:

对于更改,不使用
映射的解决方案
-改为使用:

当然,您可以始终只使用标准程序实现自己版本的
过滤器
,这也可以在所有RxRS解释器中移植:

(define (filter pred? lst)
  (cond ((null? lst)
         '())
        ((not (pred? (car lst)))
         (filter pred? (cdr lst)))
        (else
         (cons (car lst)
               (filter pred? (cdr lst))))))

(filter (lambda (item) (eq? item 'c)) tbl)
=> '(c)

您没有提到您的方案版本/环境。假设您只有最基本的方案,那么实施以下内容就足够简单:

(define (choose-if pred list)
  (let choosing ((list list) (rslt '()))
    (if (null? list)
        (reverse rslt)
        (choosing (cdr list)
                  (if (pred (car list))
                      (cons (car list) rslt)
                      rslt)))))
然后是相关的:

(define (choose item list)
  (choose-if (lambda (elt) (eq? item elt)) list))

(define (choose-if-not pred list)
  (choose-if (lambda (elt) (not (pred elt))) list))
和使用:

> (choose 'c '(a b c d))
(c)
您还可以选择使用低级基本体,如:

(define (choose item list)
  (remq #f (map (lambda (elt) (eq? item elt)) list)))

简单的“标准”技巧是

返回
(c)
apply-append。。。map
组合在Common Lisp中称为
mapcan
(“mapcan”表示“映射并连接”):

MIT方案也有这个功能

apply append
将其参数列表的一个级别展平,
(apply append'((a)((c)())
=
(append'(a)()'(c)'))
-->
(ac)
。由于空列表消失,因此它对于使用
map
删除元素非常有用。如果您有一个可用的过滤器(它不在,但在),则可以实现与过滤器相同的效果

它也可以用于其他效果,例如加倍:

[2]> (mapcan #'(lambda(x)(if (evenp x) (list x x))) '(1 2 3 4))
(2 2 4 4)

另外,
mapcan
被称为list monad的“bind”(参数翻转),而
(apply append…
被称为其“join”操作。事实上,对于任何单子,对于列表也是如此
bind mf==join(map fm)

这也是Haskell列表理解的基础:


Prelude>[y | xBy the way:作为参数传递给
map
lambda
必须接收一个参数,您传递了两个参数,但这不起作用:
(项'c)
你用的是什么解释器?我猜是Racket,但请确认@Óscar López,是的,它是Racket,但我希望解决方案可以是带有
lambda的generalUse
过滤器
,这在我所知道的任何解释器中都能用。@Óscarópez MIT方案说:
;未绑定变量:filter
。建议阅读以获得更好的理解站立
map
filter
程序:另一种方法是(filter(cut eq?'c)tbl)如果您的实现缺少curry函数,但支持SRFI-26。对于任何想深入挖掘的人,map和filter都可以使用fold来实现。
:又一个
nil
的碎片,在Scheme中被打破。这是一个多么令人恐惧的集群。“不知何故,我更喜欢(CDR(ASSQ密钥a-LIST))”--Ashwin Ram更一般的回答:过滤是标准程序,大多数实现都支持它,而不仅仅是Racket。那些没有过滤的IMLPement你可以加载它。我认为我们有多个答案,这样每个答案都可以显示它对给定问题的独特看法。我知道你想提供最好的全方位ng对OP的回答,但我不认为我们必须在这里有一个完整的答案,所以…你的答案是:“使用过滤器而不是地图,或者用地图生成占位符”。我的答案显示了一个带有map和append的解决方案。GoZoner的答案显示了删除原语的用法。每个答案都应该是独立的,IMHO。现在它很混乱。其他答案的意义是什么?现在它们有点多余,现在…:)只是我的2CT球拍等价于
mapcan
append map
> (choose 'c '(a b c d))
(c)
(define (choose item list)
  (remq #f (map (lambda (elt) (eq? item elt)) list)))
(define (choose item list)
   (remp (lambda (elt) (not (eq? item elt))) list))
(apply append (map (lambda(x)(if (eq? x 'c) (list x) '())) '(a b c d)))
;Value 12: (c)
[1]> (mapcan #'(lambda(x)(if (eq x 'c) (list x))) '(a b c d))
(C)
[2]> (mapcan #'(lambda(x)(if (evenp x) (list x x))) '(1 2 3 4))
(2 2 4 4)
Prelude> [y | x<-[1,2,3,4], even x, y<-[x,x]]
[2,2,4,4]