在方案列表中检测#<unspecified>

Detecting #<unspecified> in Scheme list

我有一个 return 值列表的函数。其中一些值本身可能是空列表,而另一些则不是。但是,在每个列表的末尾,存在一个 #<unspecified> 值。我知道当函数没有 return 任何东西时,这个值是 returned。

我想要 trim 这个值以及其他空列表。

我的清单是这样的:
(() () MD- MC+. #<unspecified>)

我打算对此列表应用过滤功能。 我要应用的标准是 null?.
但是,当它应用于 #<unspecified> 值时,它给了我错误。如何从列表中删除 #<unspecified> 值?

应用过滤功能后此列表的输出应为: (MD- MC+)

我该怎么做?

在 Guile 中,您可以使用 unspecified? 来测试未指定的值。所以,你可以写一个过滤函数,比如null-or-unspecified?,如下:

(define (null-or-unspecified? x)
  (or (null? x) (unspecified? x)))

return没有值和return没有指定值是有区别的。您可以使用 values 到 return 没有值:

> (values)
> 

如果 RnRS 标准说 return 值未指定,这意味着不同的实现可以自由 return 他们喜欢的任何值。实际上,它意味着“不要使用值 returned。您使用的实现已选择创建一个名为未指定值的具体值。它被打印为 #<unspecified>。而不是删除未指定的值从列表中,我建议您首先弄清楚价值来自哪里。

您的列表不是正确的列表,而是虚线列表。 filterfoldmap、...等所有高阶函数都要求列表正确,因此无法使用此类列表。

我想知道您坚持使用该列表的原因是否是因为生成该列表的过程中存在错误。通常如果你有一个递归过程..

(define (list-add1 lst)
  (if (pair? lst) 
      (cons (add1 (car lst)) (list-add1 (cdr lst)))))

现在,每个策划者都会立即看出这与:

(define (list-add1 lst)
  (if (pair? lst) 
      (cons (add1 (car lst)) (list-add1 (cdr lst)))
      'UNDEFINED-IMPLEMENTATION-SPECIFIED-VALUE))

并且在使用时您会将适当的列表更改为虚线列表:

(list-add1 '(1 2 3)) ; ==> (2 3 4 . UNDEFINED-IMPLEMENTATION-SPECIFIED-VALUE)

解决方法是修复使虚线列表处理 if 的两个分支的过程。例如。

(define (list-add1 lst)
  (if (pair? lst) 
      (cons (add1 (car lst)) (list-add1 (cdr lst)))
      '()))

(list-add1 '(1 2 3)) ; ==> (2 3 4)

当然,如果不是这种情况,您可以通过将最终值保留在其自身的 cons 中或删除它来将点缀转换为正确的:

(define (dotted->proper lst keep-value)
  (cond ((pair? lst) (cons (car lst) (dotted->proper (cdr lst) keep-value)))
        ((null? lst) '())
        (keep-value (cons lst '()))
        (else '())))

(dotted->proper '(1 2 . 3) #f) ; ==> (1 2)
(dotted->proper '(1 2 . 3) #t) ; ==> (1 2 3)

Guile 和 Chicken 有特殊的谓词 unspecified?。您可以像这样过滤列表:

(filter (compose not unspecified?) lst)

Racket 具有 void 函数和 void? 谓词。

也可以自己定义unspecified?:

(define unspecified (begin))
(define (unspecified? v)
    (eq? unspecified v)
)