Different shades of false

classic Classic list List threaded Threaded
22 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Different shades of false

Alen Ladavac
Hi all,

In the original Lua, 0 was logically true, because the only logically false
value was nil. That made sense. But since the introduction of the boolean
type in Lua 5, there is a slight mess in what is actually logically false,
causing me to reconsider on the idea of 0 being logically true.

Both nil and false are logically false now. But they are different, i.e
false~=nil . This is a bit awkward because you can't be sure about what does
"if foo then..." mean. Furthermore, this:

if tab[key] then
  print "key exists in the table"
else
  print "key does not exist in the table"
end

does not work any more, because tab[key] could exist, yet hold the value of
false. So you _have_ to write it like "if tab[key]~=nil then..."

With the current behavior, this convenience is non existant, so I fail to
see what is the reasoning behind 0 still being true? Since there are already
two different values of logical false, why not add two more and have 0 and
"" logically false as well?

For interfacing with C programs, and for general convenience of the
scripting user, we are considering patching the lua in our app, to have zero
and empty string mean the same thing (logically) as false as nil currently
do. Does anyone see why would that be a bad idea?

Thanks,
Alen


Reply | Threaded
Open this post in threaded view
|

Re: Different shades of false

Javier Guerra Giraldez
On Thursday 02 March 2006 9:32 am, Alen Ladavac wrote:
> In the original Lua, 0 was logically true, because the only logically false
> value was nil. That made sense. But since the introduction of the boolean
> type in Lua 5, there is a slight mess in what is actually logically false,
> causing me to reconsider on the idea of 0 being logically true.

i don't feel too strongly about this, but if anythng, i would prefer it to be
the other way around: the boolean type should have only one value: true.  
false would be a synonymous with nil.

--
Javier

attachment0 (207 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Different shades of false

DarkGod
In reply to this post by Alen Ladavac
> > In the original Lua, 0 was logically true, because the only logically false
> > value was nil. That made sense. But since the introduction of the boolean
> > type in Lua 5, there is a slight mess in what is actually logically false,
> > causing me to reconsider on the idea of 0 being logically true.
> i don't feel too strongly about this, but if anythng, i would prefer it to be
> the other way around: the boolean type should have only one value: true.  
> false would be a synonymous with nil.

I'm using Lua4 in my game, butI felt the need for "true" and "false".
I hacked the parser a bit to make false a synomyn of nil(and true of 1 but thats
because I need it that way) and it works really nice.
I, too, have trouble understanding why nil ~= false ?
Reply | Threaded
Open this post in threaded view
|

Re: Different shades of false

Gavin Kistner
In reply to this post by Alen Ladavac
On Mar 2, 2006, at 7:32 AM, Alen Ladavac wrote:

> In the original Lua, 0 was logically true, because the only  
> logically false
> value was nil. That made sense. But since the introduction of the  
> boolean
> type in Lua 5, there is a slight mess in what is actually logically  
> false, causing me to reconsider on the idea of 0 being logically true.
> [...snip...]
> For interfacing with C programs, and for general convenience of the
> scripting user, we are considering patching the lua in our app, to  
> have zero
> and empty string mean the same thing (logically) as false as nil  
> currently
> do.

To help the discussion, I think there are two, separate, arguments here:
1) I'm confused that there are two non-truth type/values, and
2) I'd like Lua to match C for easier interfacing.


My personal view on these:
1) On the one hand, it seems arbitrary to say that four non-truth  
values is better than two. From a purist standpoint, it would make  
sense, I think, to insist on exactly one.

On the other hand, false is obviously not true, and (I think) nil is  
likewise obviously not true. So if you were going to pare it down,  
you'd need to get rid of one or the other. I, personally, don't want  
to get rid of either. So I think we're stuck with more than one non-
truth value.

So, then...why not go hog wild? If we've got two, let's shoot for one  
'false' value for each primitive type. nil, false, 0, "", and (for  
consistency) {}. Now it's easy to tell if a value is 'empty', but  
harder to tell if it's present than before. Which use case is more  
common? Which paradigm are the majority of Lua scripters more likely  
to expect? (C users lean one way, Ruby users another...and who knows  
which way new users lean.) Even _if_ the current situation makes it  
harder to perform the more common tasks, is the confusion and  
compatibility break the the change would effect worth the benefits?

Further, the concepts of truth/non-truth and present/empty are  
intertwined, but separate. Do you really want to collapse them  
together? There are cases where it would be convenient to test a  
value for emptiness by treating it directly as a truth value. More  
often (for me) I prefer the distinctness. If you want a catch-all,  
how about writing an 'empty()' function that wraps it all up for you,  
testing the type/value pairs that you like?


2) I can see how this would be convenient, if your C programs are  
using 0 or "" to mean 'false'. In my company, there is a group of  
people who write C(++), and a group who use the Lua bindings they  
provide. Though I coded in C 10 years ago, I no longer have to deal  
with it, so I personally have no need for Lua to ape C. (In fact, I'd  
rather it didn't.) Further, the Lua bindings abstract values and  
methods from the C++ side, so an appropriate Lua binding (for me) is  
not to have raw access to values in the engine, but to provide lua-
like wrappers for them. This includes things like providing table-
arrays that start at 1 (and not 0), and would include provide proper  
Lua boolean representations for values that may be stored differently  
in C++.


So, I'm generally arguing to keep things the way they are, with a  
huge dash of "discuss how it affects the usability of the language  
before deciding".
Reply | Threaded
Open this post in threaded view
|

Re: Different shades of false

Alen Ladavac
In reply to this post by DarkGod
From: "DarkGod" <[hidden email]>
> I, too, have trouble understanding why nil ~= false ?

It's not hard to understand that. This is perfectly orthogonal. Values of
different types are always different. The question is different: If you have
two logically false values of different types, then why not have one for
each type.

Alen

Reply | Threaded
Open this post in threaded view
|

Re: Different shades of false

Alen Ladavac
In reply to this post by Javier Guerra Giraldez
Javier:
>i don't feel too strongly about this, but if anythng, i would prefer it to
>be
>the other way around: the boolean type should have only one value: true.
>false would be a synonymous with nil.

That too is a very valid approach. But seeing the idea of two different
falses being already accepted, it leads me to think that nil is losing
ground as a logical value. In this situation, as usage of "foo ~= nil" to
test for nonexistence is required already (i.e. "if foo" has lost its
initial meaning), seems like adding more "falses" makes no harm.

Alen

Reply | Threaded
Open this post in threaded view
|

Re: Different shades of false

Alen Ladavac
In reply to this post by Gavin Kistner

> 1) On the one hand, it seems arbitrary to say that four non-truth
> values is better than two.

A friend of mine said wisely that it might not be better, but it certainly
is not worse.  :) As having two of them is really non orthogonal to start
with.

> From a purist standpoint, it would make  sense, I think, to insist on
> exactly one.

But if nil is not that value, you'd be in serious problems as lua relies on
the notion of not having runtime errors due to nils, and nil not being true
saves it there. One solution would be to banish "false" from the boolean
type.

> On the other hand, false is obviously not true, and (I think) nil is
> likewise obviously not true. So if you were going to pare it down,  you'd
> need to get rid of one or the other. I, personally, don't want  to get rid
> of either. So I think we're stuck with more than one non- truth value.

Why not getting rid of false altogether? Isn't that much more orthogonal
than the current situation? (I mean, I'd rather seek orthogonality in the
other direction, but I'm interested to know whether you have some reasons
for this.)

> So, then...why not go hog wild? If we've got two, let's shoot for one
> 'false' value for each primitive type. nil, false, 0, "", and (for
> consistency) {}.

You are right. Empty table should be considered as well, for consistency.

> Now it's easy to tell if a value is 'empty', but  harder to tell if it's
> present than before.

It is not any harder. It is equally as hard, because false is already
deceiving you. I'd just like to point this out by requiring foo~=nil to be
used for presence, as just foo is not correct starting with lua 5.

> 2) I'd like Lua to match C for easier interfacing.

Really, this has more to embedded scripting in general than with C. I'm
confident that everyone perfectly understand the concept of 0=false, 1=true,
and that it is natural for that to be used in configuration scripts and
similar. In all our previous projects, both in-game console commands and
configuration scripts support a notion of booleans as 0/1. People are used
to type some_config_var=1 or =0. If =0 started to _enable_ stuff, we'd have
a lot to explain to the users. Duck-and-cover kind of explaining. ;)

One addition to this argumentation that now becomes obvious to me: As I see
it, if we want orthogonality, then it is either (a) add one falseness for
each type or (b) remove false from boolean type. Now, removing false from
boolean gives a weirdness of not be able to verify whether a boolean
variable is present. In this line, I only see more arguments for (a).

Alen


Reply | Threaded
Open this post in threaded view
|

Re: Different shades of false

Adam D. Moss
Alen Ladavac wrote:
> Why not getting rid of false altogether?

I guess because nil and false just aren't the same
thing with different types.  For comparison purposes
they pretty much serve the same function, but as table
values (and keys!) they're semantically very different
things, not just differently typed.

(I use 'false' values in tables where a 'nil's implicit
removal of the corresponding key would not mean what I want -
particularly in configuration management where setting
an option to false is different from setting it to nil,
where the latter case simply says that this configuration
option doesn't exist and is therefore undefined/defaulted.)

--adam
Reply | Threaded
Open this post in threaded view
|

RE: Different shades of false

Dolan, Ryanne Thomas (UMR-Student)

Exactly.  The only problem with nil/false is that people use these values incorrectly.  nil is by no means synonomous with false, so it makes sense that nil ~= false.  Being false and not defined are two very different states.

And the proposal that all types should have true/false values seems strange to me, as anything with true/false evaluations is by definition a boolean, which Lua of course already has.  Would it make sense at all if "" == 0?

So long as you take the convention that nil means something like "undefined" then everything makes sense the way it is.

assert (bar ~= nil);

if bar == true then
   print "true";
else
   print "false";
end;


-----Original Message-----
From: [hidden email] on behalf of Adam D. Moss
Sent: Thu 3/2/2006 10:59 AM
To: Lua list
Subject: Re: Different shades of false
 
Alen Ladavac wrote:
> Why not getting rid of false altogether?

I guess because nil and false just aren't the same
thing with different types.  For comparison purposes
they pretty much serve the same function, but as table
values (and keys!) they're semantically very different
things, not just differently typed.

(I use 'false' values in tables where a 'nil's implicit
removal of the corresponding key would not mean what I want -
particularly in configuration management where setting
an option to false is different from setting it to nil,
where the latter case simply says that this configuration
option doesn't exist and is therefore undefined/defaulted.)

--adam



winmail.dat (4K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Different shades of false

Romulo Bahiense
Dolan, Ryanne Thomas (UMR-Student) wrote:
> Exactly.  The only problem with nil/false is that people use these values incorrectly.  nil is by no means synonomous with false, so it makes sense that nil ~= false.  Being false and not defined are two very different states.

I agree. To me, this discussion is just like the one with NULL's in
RDBMS (1). NULL is not a value, it represents unknow, undetermined, not
present etc. It is not 0, it is not "", it is not false (in systems that
support boolean natively), it is not 0.0 nor it is ASCII NULL.

And to get worse, a table couldn't be checked for emptiness because it
may have a metatable which, incidentally, may have __index and
__newindex defined. It may be "physically" empty, but who knows what
those methods will return?

Consider:

userOptions = {}

groupOptions = {
     sendEmail = true;
}

setmetatable(userOptions,{__index=groupOptions})

if userOptions.sendEmail then
   mail.send{to = ..., subject = ..., ...}
end


Note that userOptions has no value inside it (no key, no value) but it
is not empty. It's "parent" metatable has the values. Also note that
'nil' is different from 'false', because 'false' would mean the user
don't want to receive e-mails, while 'nil' means he/she just don't care.


This discussion remembers me of some posts from The Daily WTF, where
now-and-then some smart guy declares something like:

enum Bool = (TRUE,FALSE,MAYBE)

--rb

1. Except, of course, to the fact that in Lua, nil==nil, while in some
RDBMS, NULL <> NULL.
Reply | Threaded
Open this post in threaded view
|

Re: Different shades of false

Tobias Käs
In reply to this post by Dolan, Ryanne Thomas (UMR-Student)
Dolan, Ryanne Thomas (UMR-Student) wrote:

>Exactly.  The only problem with nil/false is that people use these values incorrectly.  nil is by no means synonomous with false, so it makes sense that nil ~= false.  Being false and not defined are two very different states.
>
>And the proposal that all types should have true/false values seems strange to me, as anything with true/false evaluations is by definition a boolean, which Lua of course already has.  Would it make sense at all if "" == 0?
>  
>
You are contradicting yourself here ;-)
At one point you say nil ~= false because they have different meanings.
At the other point you argue "" == 0 incase 'if' treats them the same.

If you stand by the first argument, you would consequently have to say
"" ~= 0
If you stand by the second argument, you would have to say nil == false

As already has been pointed out, nil and false being different has some
advantages for tables.
So if you say "undefined" evaluates to "false" in the context of an 'if'
(even though they are not the same), you could as well say "empty"
should evaluate to "false" in the same context.

Since the ambiguity already exists it wouldn't make things much more
worse I guess ;-)
Though in the end it probably is just a matter of taste which you prefer.

>So long as you take the convention that nil means something like "undefined" then everything makes sense the way it is.
>  
>

Reply | Threaded
Open this post in threaded view
|

Re: Different shades of false

Dolan, Ryanne Thomas (UMR-Student)
I guess my wording was ambiguous.  Sorry if I confused anyone.

I did not mean to suggest that "" == 0 should evaluate true.  I posed the question "Would it make sense at all if "" == 0?" to suggest that if changes were made to Lua such that "" == false and 0 == false, then "" == 0 would be a logical consequence, which doesn't make any sense at all (to me).  Indeed, I think "" == 0 makes a lot less sense than false == nil, and I am very glad that neither expression is true in Lua.

I just wanted to clarify that I am siding with the first argument and didn't mean to bring up the second.  Thanks for catching my mistake!

On Thu, 2006-03-02 at 21:00 +0100, Tobias Käs wrote:
Dolan, Ryanne Thomas (UMR-Student) wrote:

>Exactly.  The only problem with nil/false is that people use these values incorrectly.  nil is by no means synonomous with false, so it makes sense that nil ~= false.  Being false and not defined are two very different states.
>
>And the proposal that all types should have true/false values seems strange to me, as anything with true/false evaluations is by definition a boolean, which Lua of course already has.  Would it make sense at all if "" == 0?
>  
>
You are contradicting yourself here ;-)
At one point you say nil ~= false because they have different meanings.
At the other point you argue "" == 0 incase 'if' treats them the same.

If you stand by the first argument, you would consequently have to say 
"" ~= 0
If you stand by the second argument, you would have to say nil == false

As already has been pointed out, nil and false being different has some 
advantages for tables.
So if you say "undefined" evaluates to "false" in the context of an 'if' 
(even though they are not the same), you could as well say "empty" 
should evaluate to "false" in the same context.

Since the ambiguity already exists it wouldn't make things much more 
worse I guess ;-)
Though in the end it probably is just a matter of taste which you prefer.

>So long as you take the convention that nil means something like "undefined" then everything makes sense the way it is.
>  
>


Reply | Threaded
Open this post in threaded view
|

Re: Different shades of false

Ben Sunshine-Hill
On 3/2/06, Ryanne Thomas Dolan <[hidden email]> wrote:
>  I guess my wording was ambiguous.  Sorry if I confused anyone.
>
>  I did not mean to suggest that "" == 0 should evaluate true.  I posed the
> question "Would it make sense at all if "" == 0?" to suggest that if changes
> were made to Lua such that "" == false and 0 == false, then "" == 0 would be
> a logical consequence, which doesn't make any sense at all (to me).  Indeed,
> I think "" == 0 makes a lot less sense than false == nil, and I am very glad
> that neither expression is true in Lua.

Worse yet, given Lua's willingness to go between numbers and their
string representations, if 0==false, then it would be best to define
that "0"==false. (And that "0e-3" be false, although "0f-3" would be
true.) Yikes.

Ben
Reply | Threaded
Open this post in threaded view
|

Re: Different shades of false

Adam D. Moss
In reply to this post by Tobias Käs
Tobias Käs wrote:
> At the other point you argue "" == 0 incase 'if' treats them the same.

I'm not sure that's what Ryanne is saying, but it doesn't
really matter. :)

> So if you say "undefined" evaluates to "false" in the context of an 'if'
> (even though they are not the same), you could as well say "empty"
> should evaluate to "false" in the same context.

I think the point there is that the argument seems to be going
around that 'if there are already two ways to say false, then
why not four or more?'.  But (other good counterarguments aside!)
there aren't two ways to say false; there's one way to say false
and one way to say undefined, where for IMO *overwhelming* practical
and Lua-historical reasons the latter is also considered not-true
in a boolean expression.

Some people would like to see other specific values of other
particular types evaluate to not-true in a boolean expression,
for convenience in their particular application domain or to
match their favourite other-language.  There might be some good
practical arguments in that direction, of which 'it might not
be better, but it certainly is not worse' isn't really one. :D

Pragmatically I'm not really interested in other values
coercing to false but if it's cheap to implement then the idea
doesn't completely horrify me.  A few weeks ago someone asked
for a __toboolean sort of metamethod; combined with Lua 5.1's
per-type metatables this could give people whatever boolean
coercions they consider tasteful.  Again not too impressed
by the idea but it's a direction to consider.

--adam
Reply | Threaded
Open this post in threaded view
|

RE: Different shades of false

Marius Gheorghe
In reply to this post by Alen Ladavac
> > So, then...why not go hog wild? If we've got two, let's
> shoot for one
> > 'false' value for each primitive type. nil, false, 0, "", and (for
> > consistency) {}.
>
> You are right. Empty table should be considered as well, for
> consistency.

As the {} denotes a table constructor, each time it is used it creates a new
table. This may:
a) impose implementation complications/run-time penalties as either each
table instance would have to carry an 'empty' flag with it or a check for
emptiness would have to be performed on each test;
b) create additional semantic inconsistencies as: {} ~= {} but '' == '',
false == false, nil == nil and 0 == 0.

I vote for keeping nil and false the way they are.

Marius Gheorghe

Reply | Threaded
Open this post in threaded view
|

Re: Different shades of false

Holger Stenger
In reply to this post by Ben Sunshine-Hill
Ben Sunshine-Hill wrote:
> Worse yet, given Lua's willingness to go between numbers and their
> string representations, if 0==false, then it would be best to define
> that "0"==false. (And that "0e-3" be false, although "0f-3" would be
> true.) Yikes.

Automatic conversion of strings to numbers occurs only for arithmetic
operations. In other contexts 0 and "0" are different, like equality
tests or table indexing. If this were to change, it would be a real
nightmare (for me at least).

Regards,
Holger Stenger

Reply | Threaded
Open this post in threaded view
|

Re[2]: Different shades of false

Alen Ladavac
In reply to this post by Adam D. Moss
adam wrote:
> Pragmatically I'm not really interested in other values
> coercing to false but if it's cheap to implement then the idea
> doesn't completely horrify me.

First of all, yes, its cheap and simple. It took me much more to even
write the original post, than it took my coleague to implement this.
:)

Also, I get you why removing false while keeping true is evil. In your
config example, you _must_ use ~=nil. I argumented that reasoning in a
previous post in this thread. But my conclusion on that is not to keep
the things as they are, but to extend them for better orthogonality.

to comment on the other posts....

Those notes about {} ~= {} was certainly one of the kind of ideas that
I was trying to solicit. That was very useful, and gives strong
arguments why this should not apply to tables.

Still, about the case with numbers and strings, it looks to me like a
lot of people are getting it wrong. I'm not saying that it should be
false == 0. Quite on the contrary. The important thing here is that
false ~= nil, yet they both make an if statement take the else route.
So, we have two different types (yes, nil is a type, at least it was
the last I checked the spec), both taking an if statement down the
else route, so the original orthogonality is broken. And backwards
compatibility is broken as well. I propose to add more orthogonality
while not breaking any (sensibly correct) code, by adding one
logically false value for each type where it makes sense. (Note that
this does _not_ make 0 == false, or something like that.)

Sticking to the backwards compatibility here doesn't seem to make
sense. The moment boolean type was introduced, all previous scripts
that used "if table[key]" were broken, if a boolean value was entered
there. Adding more orhogonality here is not going to break anything
more. It is rather more likely to unveil hidden bugs.

Alen


Reply | Threaded
Open this post in threaded view
|

Re: Different shades of false

Adrian Sietsma
In reply to this post by Holger Stenger
i was initially unsure about lua's use of 0==true, but now i use it a lot :

conditional formulae :
a = b or a -- would fail if b==0 and 0==false
a = a + (b or default_inc) -- ditto

will fail if 0 == false, as will many other similar constructs i use.


tables with flags :

t[v] = nil : flag not defined
t[v] = false : flag defined but not set
t[v] = true : flag defined and set.


think also re metetables :
t[v] = false
if (t[v]) then --no mt __index lookup

t[v] = nil
if(t[v]) then -- metatable __index is called


function returns :

local ret, err
repeat ret, err = f() -- return false to break, nil, err on error
until not ret

assert(ret ~= nil,err) -- false return is not an error


ps i did some testing a while back :
if t[v] then ....
appears to be faster if t[v] == false than if t[v] == nil, probably because
of the metatable lookup invoked for nil.

in short - i like it the way it is
nil and false are not synonymous; anything else is true.

Adrian

Reply | Threaded
Open this post in threaded view
|

Re[2]: Different shades of false

Gunnar Zötl
In reply to this post by Dolan, Ryanne Thomas (UMR-Student)
Hiya,

I absolutely agree with nil and false being two different beasts, and
I use them for different purposes, and so does lua. false is a value,
whereas nil is not. I would not want to copy the php mess, where

0 == "0" == "" == false == undef == any string consisting of only a
sequence of zeros...

They f***ed up so badly with this that they even had to introduce a
new comparison operator to clean up the mess :-( Threating nil akin to
false in some contexts, as lua does, is a compromise between a clean
and a comfortable handling of the nil value. If you're confused by
this, the correct solution is to not use nil when you mean false, and
vice versa.

just my 2 cents,

Gunnar


Reply | Threaded
Open this post in threaded view
|

Re: Different shades of false

Philippe Lhoste
In reply to this post by Alen Ladavac
Alen Ladavac wrote:

> In the original Lua, 0 was logically true, because the only logically false
> value was nil. That made sense. But since the introduction of the boolean
> type in Lua 5, there is a slight mess in what is actually logically false,
> causing me to reconsider on the idea of 0 being logically true.
>
> Both nil and false are logically false now. But they are different, i.e
> false~=nil . This is a bit awkward because you can't be sure about what does
> "if foo then..." mean. Furthermore, this:
>
> if tab[key] then
>   print "key exists in the table"
> else
>   print "key does not exist in the table"
> end
>
> does not work any more, because tab[key] could exist, yet hold the value of
> false. So you _have_ to write it like "if tab[key]~=nil then..."
>
> With the current behavior, this convenience is non existant, so I fail to
> see what is the reasoning behind 0 still being true? Since there are already
> two different values of logical false, why not add two more and have 0 and
> "" logically false as well?
>
> For interfacing with C programs, and for general convenience of the
> scripting user, we are considering patching the lua in our app, to have zero
> and empty string mean the same thing (logically) as false as nil currently
> do. Does anyone see why would that be a bad idea?

OK, I am late in my reading of the list, but I wanted to answer anyway,
before reading the existing answers...
The habit of using 0 or NULL or '\0' as false in C is, IMHO, not very good.
Sure, the while (*p) or if (p && p->Foo()) idioms are short and some may
find them expressives, but I definitively choose to allow (in my code)
such form only for variables typed as boolean (and prefixed with the b
letter: bEndReached or such).

So, even in Lua, I always test if x ~= nil then, in C if (*p == '\0') or
if (p != NULL). It seems cleaner this way, consistent with strong typing
(at least in C/C++/Java) or strong discipline about typing.

Just my 2€c.

--
Philippe Lhoste
--  (near) Paris -- France
--  http://Phi.Lho.free.fr
--  --  --  --  --  --  --  --  --  --  --  --  --  --
12