List Scheme/Racket:一个函数,它将一个列表分成两个元素列表,一个匹配某个谓词,另一个不匹配';不匹配
我希望在Scheme中创建一个函数,该函数接受谓词和元素列表,然后输出两个单独的列表。一个是原始列表中与给定谓词匹配的元素,另一个是与给定谓词不匹配的元素 我认为我现在的代码应该隔离那些与谓词匹配的代码,并输出它们的列表,但代码不会工作List Scheme/Racket:一个函数,它将一个列表分成两个元素列表,一个匹配某个谓词,另一个不匹配';不匹配,list,scheme,lisp,racket,predicate,List,Scheme,Lisp,Racket,Predicate,我希望在Scheme中创建一个函数,该函数接受谓词和元素列表,然后输出两个单独的列表。一个是原始列表中与给定谓词匹配的元素,另一个是与给定谓词不匹配的元素 我认为我现在的代码应该隔离那些与谓词匹配的代码,并输出它们的列表,但代码不会工作 (define tear (lambda (pred xs) (cond[(null? xs) '()] [(list? (car xs))(cons((tear (pred (car xs)))(tear (pred (cdr
(define tear
(lambda (pred xs)
(cond[(null? xs) '()]
[(list? (car xs))(cons((tear (pred (car xs)))(tear (pred (cdr xs)))))]
[(pred (car xs))(cons((car xs)(tear (pred (cdr xs)))))]
[else tear (pred (cdr xs))])))
(tear number? '(1 2 3 a b c))
我的编译器上的结果输出为:
tear: arity mismatch;
the expected number of arguments does not match the given number
expected: 2
given: 1
arguments...:
#f
context...:
/home/jdoodle.rkt:2:4: tear
Command exited with non-zero status 1
非常感谢您提供的任何帮助/信息。让我们逐步修复您的代码。添加缩进和空白以使其可读:
(define tear
(lambda (pred xs)
(cond
[(null? xs)
'()]
[(list? (car xs))
(cons ((tear (pred (car xs))) (tear (pred (cdr xs)))))]
[(pred (car xs))
(cons ((car xs) (tear (pred (cdr xs)))))]
[else
tear (pred (cdr xs))])))
(tear number? '(1 2 3 a b c))
我看到的第一个问题是将括号放在函数调用的内部(围绕参数),而不是外部。您可以使用cons
和对tear
的递归调用来执行此操作。例如,在tear(pred(cdr-xs))
中,您应该将第一个paren移动到函数之前。请记住,表达式中的括号几乎总是表示形式为(函数参数…
)的函数调用
应重写为(cons(ab))
(cons A B)
应重写为(撕裂(Pred-Xs))
(撕裂Pred-Xs)
应重写为撕裂(Pred-Xs)
(撕裂Pred-Xs)
(define tear
(lambda (pred xs)
(cond
[(null? xs)
'()]
[(list? (car xs))
(cons (tear pred (car xs)) (tear pred (cdr xs)))]
[(pred (car xs))
(cons (car xs) (tear pred (cdr xs)))]
[else
(tear pred (cdr xs))])))
(tear number? '(1 2 3 a b c))
;=> (1 2 3)
(tear number? '(1 2 "not a number" 3 4))
;=> (1 2 3 4)
但是,当存在嵌套列表时,它仍然会做一些奇怪的事情:
(tear list? (list '(1 2 3) "not a list" '(4 5)))
;=error> (() ())
为了保持一致,它应该将两个列表放入一个列表中:((1 2 3)(4 5))
。为此,只需删除第二个cond
案例:
(define tear
(lambda (pred xs)
(cond
[(null? xs)
'()]
[(pred (car xs))
(cons (car xs) (tear pred (cdr xs)))]
[else
(tear pred (cdr xs))])))
(tear number? '(1 2 3 a b c))
;=> (1 2 3)
(tear list? (list '(1 2 3) "not a list" '(4 5)))
;=> ((1 2 3) (4 5))
现在它似乎只做了你想要的一半。您希望它返回两个列表:一个用于通过的元素,另一个用于失败的元素。它目前只返回第一个列表
您应该做的第一件事是记录它如何返回这两个列表。因为总是正好有两个,所以可以将它们作为多个值返回
;; tear returns two values:
;; - a list of the elements of `xs` that passed `pred`
;; - a list of the elements of `xs` that failed `pred`
使用多个值有两个部分:返回和接收。使用(值ab)
返回它们,并使用(让值([(ab)…])
匹配结果,如递归调用的结果
这意味着像这样的每个递归调用都应该
(let-values ([(A B) (tear ....)])
(values (f .... A ....)
???))
将其应用于代码:
;; tear returns two values:
;; - a list of the elements of `xs` that passed `pred`
;; - a list of the elements of `xs` that failed `pred`
(define tear
(lambda (pred xs)
(cond
[(null? xs)
(values '()
???)]
[(pred (car xs))
(let-values ([(A B) (tear pred (cdr xs))])
(values (cons (car xs) A)
???))]
[else
(let-values ([(A B) (tear pred (cdr xs))])
(values A
???))])))
现在,使用示例来填充?
孔
应返回两个空列表:(撕裂编号?')
()
应返回完整列表和空列表:(撕裂编号?'(12))
(12)(
应返回空列表和完整列表:(撕裂编号?'(a b))
()(a b)
?
孔,第二个示例对应于第二个孔,依此类推
这告诉我们第一个孔应该用'()
填充,第二个孔应该用B
填充,第三个孔应该用(cons(car xs)B)
填充
让我们一步一步地修复代码。添加缩进和空白以使其可读:
(define tear
(lambda (pred xs)
(cond
[(null? xs)
'()]
[(list? (car xs))
(cons ((tear (pred (car xs))) (tear (pred (cdr xs)))))]
[(pred (car xs))
(cons ((car xs) (tear (pred (cdr xs)))))]
[else
tear (pred (cdr xs))])))
(tear number? '(1 2 3 a b c))
我看到的第一个问题是将括号放在函数调用的内部(围绕参数),而不是外部。您可以使用cons
和对tear
的递归调用来执行此操作。例如,在tear(pred(cdr-xs))
中,您应该将第一个paren移动到函数之前。请记住,表达式中的括号几乎总是表示形式为(函数参数…
)的函数调用
应重写为(cons(ab))
(cons A B)
应重写为(撕裂(Pred-Xs))
(撕裂Pred-Xs)
应重写为撕裂(Pred-Xs)
(撕裂Pred-Xs)
(define tear
(lambda (pred xs)
(cond
[(null? xs)
'()]
[(list? (car xs))
(cons (tear pred (car xs)) (tear pred (cdr xs)))]
[(pred (car xs))
(cons (car xs) (tear pred (cdr xs)))]
[else
(tear pred (cdr xs))])))
(tear number? '(1 2 3 a b c))
;=> (1 2 3)
(tear number? '(1 2 "not a number" 3 4))
;=> (1 2 3 4)
但是,当存在嵌套列表时,它仍然会做一些奇怪的事情:
(tear list? (list '(1 2 3) "not a list" '(4 5)))
;=error> (() ())
为了保持一致,它应该将两个列表放入一个列表中:((1 2 3)(4 5))
。为此,只需删除第二个cond
案例:
(define tear
(lambda (pred xs)
(cond
[(null? xs)
'()]
[(pred (car xs))
(cons (car xs) (tear pred (cdr xs)))]
[else
(tear pred (cdr xs))])))
(tear number? '(1 2 3 a b c))
;=> (1 2 3)
(tear list? (list '(1 2 3) "not a list" '(4 5)))
;=> ((1 2 3) (4 5))
现在它似乎只做了你想要的一半。您希望它返回两个列表:一个用于通过的元素,另一个用于失败的元素。它目前只返回第一个列表
您应该做的第一件事是记录它如何返回这两个列表。因为总是正好有两个,所以可以将它们作为多个值返回
;; tear returns two values:
;; - a list of the elements of `xs` that passed `pred`
;; - a list of the elements of `xs` that failed `pred`
使用多个值有两个部分:返回和接收。使用(值ab)
返回它们,并使用(让值([(ab)…])
匹配结果,如递归调用的结果
这意味着像这样的每个递归调用都应该
(let-values ([(A B) (tear ....)])
(values (f .... A ....)
???))
将其应用于代码:
;; tear returns two values:
;; - a list of the elements of `xs` that passed `pred`
;; - a list of the elements of `xs` that failed `pred`
(define tear
(lambda (pred xs)
(cond
[(null? xs)
(values '()
???)]
[(pred (car xs))
(let-values ([(A B) (tear pred (cdr xs))])
(values (cons (car xs) A)
???))]
[else
(let-values ([(A B) (tear pred (cdr xs))])
(values A
???))])))
现在,使用示例来填充?
孔
应返回两个空列表:(撕裂编号?')
()
应返回完整列表和空列表:(撕裂编号?'(12))
(12)(
应返回空列表和完整列表:(撕裂编号?'(a b))
()(a b)
?
孔,第二个示例对应于第二个孔,依此类推
这告诉我们第一个孔应该用'()
填充,第二个孔应该用B
填充,第三个孔应该用(cons(car xs)B)
填充
这里有另一种方法,你可以使用;这就引入了递归调用 上面,我们利用了球拍的优势。下面我们将展示如何定义
partit