Discussion:
Why is it allowed to deduce from undefined?
(too old to reply)
ceving
2023-11-10 08:21:41 UTC
Permalink
The following looks like a contradiction to me:

(if (if #f #f) #t #f) ;; => #t
(equal? (if #f #f) #t) ;; => #f

Why does Scheme allowed this? And why is it anything other than division by zero?
Maciek Godek
2023-11-10 09:40:27 UTC
Permalink
Post by ceving
(if (if #f #f) #t #f) ;; => #t
(equal? (if #f #f) #t) ;; => #f
Why does Scheme allowed this? And why is it anything other than division by zero?
I don't think this behaviour would be consistent across the implementations,
(and I don't think it's well-defined)

The reason this might work on some implementations is that they define
a special value called "undefined", which is "silent" when it's supposed to be displayed in the REPL.
(I know that Guile does that)

It can also be occasionally true that (eq? (if #f #f) (if #f #f)).

Of course, this value isn't equal to #t, which is why the second equality is #f.
But this isn't any more surprising than, say

(if 5 #t #f) ;; => #t
(equal? 5 #t) ;; => #f

because in Scheme every value other than #f is considered "true" in the context of "if"
(and since this special "unspecified" value is different from #f, it is also considered "true")

BTW When it comes to "division by zero", then it is also an ambiguous phrase:

(/ 2 0) ===>!error
(/ 2.0 0) ===> +inf.0
(/ 0.0 0) ===> +nan.0
(/ -2.0 0) ===> -inf.0
(/ 2 0.0) ===> +inf.0
(/ 2 -0.0) ===> -inf.0
(/ 2.0 -0) ===> +inf.0
ceving
2023-11-10 10:17:29 UTC
Permalink
some implementations [...] define a special value called "undefined"
in Scheme every value other than #f is considered "true"
I think this is the problem. Undefined must not be a value or any function which gets passed an undefined value must throw an error. Maybe this can be solved if the evaluation of "undefined" throws an error?

A value "undefined" can be either true or false, because it is not defined. If it behaves sometimes like true and sometimes like false, it gets spooky. It must not behave at all.
Maciek Godek
2023-11-10 11:07:19 UTC
Permalink
Post by ceving
some implementations [...] define a special value called "undefined"
in Scheme every value other than #f is considered "true"
I think this is the problem. Undefined must not be a value or any function which gets passed an undefined value must throw an error.
I don't think it's mentioned anywhere in any RnRS.

R5RS says this: |If the value of an expression is said to be ``unspecified,'' then the expression must evaluate to some object without signalling an error, but the value depends on the implementation; this report explicitly does not say what value should be returned."
Post by ceving
Maybe this can be solved if the evaluation of "undefined" throws an error?
Some implementations that I tested produce a warning or an error when you're trying to use a one-armed if in the context that requires a value to be produced.
Post by ceving
A value "undefined" can be either true or false, because it is not defined. If it behaves sometimes like true and sometimes like false, it gets spooky. It must not behave at all.
I haven't ever seen it behaving as #f anywhere. And indeed, the standard says:
"Of all the standard Scheme values, only #f counts as false in conditional expressions"
so if this value is distinct from #f, it cannot behave as #f.

(I know that Kawa makes a deviation there, and allows another value to be false in the context of "if",
namely the #!null value - which makes sense given its JVM interop, and which I personally found convenient,
although I realize that different people's opinions on that matter will vary)
ceving
2023-11-10 11:33:00 UTC
Permalink
Post by Maciek Godek
R5RS says this: |If the value of an expression is said to be ``unspecified,'' then the expression must evaluate to some object without signalling an error,
I am wondering why it has been defined this way.

I would say the opposite should be right: it must signal an error.
Tristan Wibberley
2024-03-02 12:52:27 UTC
Permalink
Post by ceving
Post by Maciek Godek
R5RS says this: |If the value of an expression is said to be ``unspecified,'' then the expression must evaluate to some object without signalling an error,
I am wondering why it has been defined this way.
I would say the opposite should be right: it must signal an error.
First, I'm a newbie with Scheme, so I don't know all the names and nuances.

You're thinking of pure functional languages. In Scheme, which has a
certain imperative essence, (if...) can give *unspecified* and you can
signal an error in that condition. It's like 'Control.Monad.when' in
Haskell or 'if' in C, except that it also allows you to use it like 'if'
in Haskell if you want to.

That makes (if...) useful for inserting conditional actions in a
sequence of them.

You can always give a second argument if you are slow and steady enough.

You can write a strict (if...) that requires two arguments but you must
use a macro, I think, rather than (define...). I think you can force all
(if...) uses in your files to be so strict if you want to make sure
you've done that everywhere but I'm not so sure scheme makes it hard to
subsequently liberalise.

Tristan Wibberley
2024-03-02 12:17:02 UTC
Permalink
Post by ceving
(if (if #f #f) #t #f) ;; => #t
(equal? (if #f #f) #t) ;; => #f
Why does Scheme allowed this? And why is it anything other than division by zero?
In Guile:
*There seems to be a common object available with the name
"*unspecified*" which 'if' uses for an unspecified branch.

* It's 'equal?' to itself as well as 'eq?' and 'eqv?' - I didn't try
others.

* It's distinct from both end-of-list and #f.

I would expect division by zero only should 'if' be defined at least in
part by division.

--
Tristan
Loading...