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

Attachment: pgpv1znJwsAKS.pgp
Description: PGP signature

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

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