0

Is there anyway to check if a function return nothing in Scheme?

For example:

(define (f1)
  (if #f #f)
)

or

(define (f2) (values) )

or

(define (f3) (define var 10))

How can I check if f return nothing?

Thanks in advance.

Sang
  • 4,049
  • 3
  • 37
  • 47
  • Related: http://stackoverflow.com/q/28910911/124319 – coredump Nov 19 '15 at 08:15
  • @coredump- thank you for providing link. I did see that thread before, but it seem to only work with my case only when the function returns `#`. I've added `f3`'s definition, it returns nothing instead of `#` – Sang Nov 19 '15 at 11:48
  • 1
    The F3 case is undefined behavior because `define` cannot be used as an expression: it can only appear at top-level body (for details, see http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-14.html#node_sec_11.2). [This answer](http://stackoverflow.com/a/18802081/124319) is relevant, as well as [this one](http://stackoverflow.com/questions/15504117/type-of-define-expression-in-scheme/15504315#15504315) (they are about racket, but they are valid for guile too) – coredump Nov 19 '15 at 13:32
  • @coredump- thank you. They are exactly what I need – Sang Nov 19 '15 at 14:07

2 Answers2

1

Yes. You can wrap the call in something that makes a list of the values. eg.

(define-syntax values->list 
  (syntax-rules ()
    ((_ expression) 
     (call-with-values (lambda () expression) 
                       (lambda g (apply list g))))))

(apply + 5 4 (values->list (values))) ; ==> 9
(null? (values->list (values)))       ; ==> #t

Your procedure f2 does return exactly one value and it's undefined in the report (Scheme standard). That means it can change from call to call and the result of (eq? (display "test1") (display "test2")) is unknown.

Implementations usually choose a singleton value to represent the undefined value, but you can not depend on it. Implementations are free to do anything. eg. I know that in at least one Scheme implementations this happens:

(define test 10)
(+ (display 5) (set! test 15))
; ==> 20 (side effects prints 5, and test bound to 15)

It would be crazy to actually use this, but it's probably useful in the REPL.

Sylwester
  • 47,942
  • 4
  • 47
  • 79
  • thank you for the answer. I did check and your function worked with `(values->list (values))`, `(values->list (if #f #f)` and `(values->list (display "smt"))`. But it did not work with `(values->list (define var 10))`. I am using `guile` version `2.0.11` – Sang Nov 19 '15 at 11:39
  • thank to your answer, and I know that `(if #f #f)` actually return a `#`, not nothing. So that I edited my answer to add `f3`, it returns result of a `define` statement. – Sang Nov 19 '15 at 11:46
  • @user3909241 As I wrote in my answer only `(values)` return no answer and all procedures that return undefined values does indeed return a value and you cannot portably know what value it would be. `(if #f #f)` can return `#t` in some strange implementation and still be according to the standard since the spec leaves it to the implementation. – Sylwester Nov 19 '15 at 15:25
1

In GNU Guile the function for checking this is unspecified?:

(unspecified? (if #f #f)); returns #t
(unspecified? '()); returns #f
wedesoft
  • 2,781
  • 28
  • 25