Discobooleans and other False Tales of True Type Safety
-
I think it was originally, but that got switched, IIRC, when someone accidentally posted something with an email address or the like. Probably, @PJH could confirm.
It got changed around the time the edit windows got shortened:
[postgres@sofa ~]$ psql -d discourse -c "select uh.updated_at, subject, username, previous_value, new_value > from user_histories uh > join users u on u.id=acting_user_id > where subject ILIKE '%edit%' > order by uh.updated_at asc;" updated_at | subject | username | previous_value | new_value ----------------------------+--------------------------------+----------+----------------+----------- 2014-06-25 15:06:52.932303 | edit_history_visible_to_public | dhromed | t | false 2014-06-25 15:56:02.054118 | ninja_edit_window | dhromed | 300 | 60 2014-06-25 15:56:17.116687 | post_edit_time_limit | dhromed | 525600 | 1440 ...
-
I like how we have
t
andfalse
.
-
-
I am shamed to admit out legacy product uses the strings "Yes", "Y" and "true" all as truth values : (
-
!Yes == true
?
-
We have a method we pass boolean strings to determine if they are actually true or false.
No "!Yes", just either "No", "N", "False", or "no"
-
We allow 'no', 'off', and 'disabled'. IIRC no 'false' or '0', but I don't recall whether they are case sensitive. They probably are.
-
We have a method we pass boolean strings to determine if they are actually true or false.
My quills are twitching like crazy; sounds like a real shit system design
@PleegWat said:We allow 'no', 'off', and 'disabled'.
Yep, still twitching…
@PleegWat said:IIRC no 'false' or '0'
@PleegWat said:I don't recall whether they are case sensitive. They probably are.
Again,
-
-
For markup languages, a small set of valid strings is not that bad a way of doing it, as marked-up data is usually meant to be human-readable. But if you're allowing more than a couple of valid T and F values, then you're Doing It Wrong™ ;)
-
My quills are twitching like crazy; sounds like a real shit system design
Unfortunately this is one of those places where it's best just to contain the bad logic as much as possible instead of crawling through to change stuff.
-
A wise choice, I'm sure ;)
-
Go allows you to have multiple named boolean types.
-
That is just what is that? Why would you even do that?
-
With booleans, it's not as useful, but you could do things like define a String method on an integer type and use it to describe flags or making a type that is equivalent to a pointer to an int32 have a Write method that computes some 32-bit hash.
Basically, any type can be a named type with its own methods.
-
Why would you even do that?
Type safety. Paging @antiquarian.
Basically, any type can be a named type with its own methods.
I would have described it more like a consequence of the equality operator. But then I haven't worked deeply with the sorts of languages that care that deeply about deep types. Deep. Deep. That's fun to type.
-
But then I haven't worked deeply with the sorts of languages that care that deeply about deep types.
So you work with the languages with derp types instead? :D
-
It's the equality operator for interface types. Interfaces keep track of the concrete type of their contents as well as the actual contents, so x == y for interfaces checks both the type and the value.
That means, for example, if you have a type where nil is a valid value and you put nil of that type into an interface variable, x == nil will return false because the nil interface has a nil type as well as a nil value.
-
Type safety. Paging @antiquarian.
I got nothing. Segregating floats that represent weight from floats that represent velocity makes sense, but truth is truth (unless we're on the Problem of Evil thread).
-
But toolbarVisible is not the same as sidebarVisible.
Doesn't it make sense to have type-safe boolean enums?
-
If you're going to have type safe types, it seems less WTFy to not cherry pick which types that applies to, even if it means that @ben_lubar is going to call you out on it.
-
As far as I'm concerned, type safety is all-or-nothing. Half-assed type safety? TDEMSYR
-
I like how we have t and false.
Postgres is actually very lenient on various input formats for booleans. I never saw it print it out like this though.
I'm giving Discodevs far too much credit by assuming booleans, am I?
-
but truth is truth
But not all two state elements really mean "truth". Consider "On"/"Off" vs. "In/Out" vs. "True/False". All could be represented by enums with two defined states, though the last one should probably use a built in Boolean type. Alas many systems use a Boolean type for all of them!
-
Alas many systems use a Boolean type for all of them!
And why not? If you have something that can only have two states, the most applicable model is a Boolean.
-
I don't think you should use a boolean type for in/out.
-
Well… maybe, maybe not. Depends on the application.
-
Well… maybe, maybe not. Depends on the application.
If the application is "the hokey cokey", you might need to add "shake it all about" as an option at some point.
-
-
-
So would you define the in/out boolean as nullable?
Needs to be an enum:
enum InOrOut IN, OUT, JUST_THE_TIP;
-
Good question.
Another potential type that could be represented by a bool is, of course, FILE_FOUND
-
```
enum InOrOut
IN,
OUT,
JUST_THE_TIP;:giggity: <!-- Emoji'd by MobileEmoji 0.2.0-->
-
But not all two state elements really mean "truth". Consider "On"/"Off" vs. "In/Out" vs. "True/False". All could be represented by enums with two defined states, though only the last one should probably use a built in Boolean type. Alas many systems use a Boolean type for all of them!
FTFYBoolean should be reserved for True/False. For anything else, make a new enum.
And why not? If you have something that can only have two states, the most applicable model is a Boolean.
BURN THE HERETIC!
Needs to be an enum:
enum InOrOut IN, OUT, JUST_THE_TIP, IS_IT_IN_YET; ```</blockquote>
-
And why not? If you have something that can only have two states, the most applicable model is a Boolean.
data CanHaz a = Haz a | ButIEatedIt
-
t and f is how PostgreSQL's displays booleans.
Of course, previous_value (which is a string) was likely fetched from the table, while new_value (also a string) is inserted directly by Discourse.
Then again, that's just a guess.
-
So is it kinda like overriding Object.equals() in Java? Speaking off complete ignorance here.
-
Of course, previous_value (which is a string) was likely fetched from the table, while new_value (also a string) is inserted directly by Discourse.
I'm still wondering what kind of dickweedery made them use a string in the first place. Maybe someone was worried because they saw
true
andfalse
in code instead and thought Postgres won't be able to handle it?postgres=# create temp table booleans (val boolean); CREATE TABLE postgres=# insert into booleans(val) VALUES('t'); INSERT 0 1 postgres=# insert into booleans(val) VALUES('false'); INSERT 0 1 postgres=# insert into booleans(val) VALUES('YES'); INSERT 0 1 postgres=# insert into booleans(val) VALUES('n'); INSERT 0 1 postgres=# insert into booleans(val) VALUES('1'); INSERT 0 1 postgres=# select * from booleans; val ----- t f t f t (5 rows)
Mistaken, of course...
-
...you mean other than previous_value and next_value storing numbers in the other two rows returned? Or did you mean in the actual users table?
-
If you have something that can only have two states, the most applicable model is a Boolean.
Sometimes. There are two conditions I think have to be satisfied: (i) there has to be very little chance of adding a third value, and (ii) there has to be an almost unambiguous mapping from "true/false" to your semantic meanings.I'll give an example that fails both. I have a function
output_thing(Thing thing, Format format)
that will print outthing
in either plain text or with fancy Unicode characters (welcome to the 90s baby!). For me, Format is an enumeration, but under that description it could be a bool. But what doestrue
mean? ASCII or Unicode? I mean, I could argue it makes a little more sense to mean Unicode because "should I do this fancier thing" seems a more natural question than "should I use the basic version" in this example, but I'm not sure everyone would agree and it may just be because I added Unicode later. So it fails the first criteria. It also fails the second, because I lied above; I added a third output format, HTML. If I had chosen a bool initially, I'd have had to completely change the type; with an enumeration, I just added a third option.(I think the in/out example also fails criteria (i). I don't think there's a clear mapping of those to true/false in most cases.)
-
...you mean other than previous_value and next_value storing numbers in the other two rows returned? Or did you mean in the actual users table?
D'OH! The damned thing confused me so much I thought this is describing the columns themselves, only now have I read the query properly.
Hey, gimme a break, I saw the JSON this thing produces, I expect idiocy first now. They lost my benefit of a doubt a long time ago.
-
-
I like how the "go to the quoted post" links all take you back to the song of the day thread, but to completely random posts.
EDIT: And the "expand/collapse" button just gives me "Loading...".
-
That is just what is that? Why would you even do that?
Sounds sensible in any strongly-typed language. Compiler can stop you if you're mixing bools-- like assigning a user-set option to a hardware-configuration option.
-
Don't see how that's any better than using enums. Unless, of course, the language doesn't have enums.
-
If you're going to have type safe types, it seems less WTFy to not cherry pick which types that applies to, even if it means that @ben_lubar is going to call you out on it.
Yes. I've made this bitch about C# before, as you might recall. People seem to have trouble with the concept of "strongly typed" and assume that the way C/C++ does it is the best way. But the thing is: C/C++ have a ton of weird cases where they do conversions for you (like char -> byte), and that's exactly the opposite of what you want in a strongly-typed language.
-
Don't see how that's any better than using enums.
Maybe it's not, but I also don't see any reason it should be disallowed.
-
Sounds sensible in any strongly-typed language. Compiler can stop you if you're mixing bools-- like assigning a user-set option to a hardware-configuration option.
I suppose. But making a boolean value called
maybe
which is neither equal totrue
norfalse
? It should be calledfile_not_found
!
-
Did this thread get discosorted in the move? Because post <a href="/t/abc/8647/5">#5</a> is a direct response to post <a href="/t/abc/8647/22">#22</a> now.
I believe #22 was the one I missed on my initial Jeffing.
-
It's more like if
Object.equals
simply compared the types and fields and was final.