Search code examples
schemeguile

Detecting #<unspecified> in Scheme list


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?


Solution

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