Detecting #<unspecified> in Scheme list

人盡茶涼 提交于 2019-12-11 03:13:16

问题


I have a function which return a list of values. Some of these values may be empty lists themselves, while some are not. However, at the end of every list, there is a #<unspecified> value present. I understand that this value is returned when the function does not return anything.

I want to trim this value, along with other null lists.

My list is like this:
(() () MD- MC+. #<unspecified>)

I intend to apply a filter function to this list. The criteria that I will be applying is null?.
However, when this is applied to the #<unspecified> value, it gives me false. How can I remove the #<unspecified> value from the list?

The output of this list after applying the filter function should be: (MD- MC+)

How do I do this?


回答1:


Your list is not a proper list but a dotted list. All higher order functions like filter, fold, map, ... require the lists to be proper so such list cannot be used.

I'm wondering if perhaps the reason you are stuck with such list is because of a bug in the procedure that produced the list. Usually if you have a recursive procedure..

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

Now, every schemer sees right away that this is the same as:

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

And that when used you will change a proper list into a dotted list:

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

The fix is to fox the procedure that makes the dotted list to handle both branches of if. eg.

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

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

Of course if thats not the case, you can transform a dotted to proper by either keeping the final value in its own cons or dropping it:

(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)



回答2:


In Guile, you can use unspecified? to test for an unspecified value. So, you can write a filter function, say null-or-unspecified?, as follows:

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



回答3:


There is a difference between returning no values and returning an unspecified value. You can use values to return no values:

> (values)
> 

If the RnRS standard says that a return value is unspecified it means that different implementations are free to return whatever value they like. Pratically it means "don't use the value returned. The implementation, you use, have chosen to make a concrete value named the unspecified value. It is printed #<unspecified>. Rather than removing the unspecified value from the list, I recommend you figure out where the value come from in the first place.




回答4:


Guile and Chicken have special predicate unspecified? for it. You can filter your list like that:

(filter (compose not unspecified?) lst)

Racket has void function and void? predicate.

Also you can define unspecified? by yourself:

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


来源:https://stackoverflow.com/questions/28910911/detecting-unspecified-in-scheme-list

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!