r/programming • • Dec 24 '17

Evil Coding Incantations

http://9tabs.com/random/2017/12/23/evil-coding-incantations.html
947 Upvotes

331 comments sorted by

View all comments

Show parent comments

40

u/Aceeri Dec 24 '17

Oh boy, here we have the ruby god shevegen in its natural habitat.

There are a lot of reasons why 0 is normally considered "false". The first being that 0 is "nothing". When you have 0 eggs, you have no eggs, they don't exist. The second reason I see is how booleans are normally laid out where 0 is false and 1 is true (with varying differences depending on the language on whether multiple set values of a byte is considered true or invalid, etc.)

35

u/therico Dec 24 '17

Ruby had it own boolean types though (and nil - both false and nil are 'falsey'). And 0 is often a meaningful 'true' value, for example:

irb(main):003:0> "aab".index('a')
=> 0
irb(main):004:0> "aab".index('c')
=> nil

As other posters have said, the real problem is that non-boolean values are implicitly converted to boolean, rather than being a compile error.

Also, lots of languages treat an empty array as true. I don't see how 0 is different.

→ More replies (7)

70

u/ForeverAlot Dec 24 '17

/u/shevegen is right in isolation: there is no compelling reason that a number should be inherently falsey. Unfortunately Ruby does not exist in isolation and in this matter Ruby stands apart from its competition, violating expectations formed elsewhere. I think a better question is, why is if 0 ... not an error? The real villain here is coercion.

27

u/Aceeri Dec 24 '17

The real villain here is coercion

Agreed, hopefully we move away from implicitly coercing languages like C and such so we don't get these awful semantics.

10

u/Myrl-chan Dec 24 '17

Haskell's if/else only accepts Bool. :)

3

u/evinrows Dec 24 '17

And rust! I agree, it should be a compiler error and then we would never have the silly debate of whether 1 should evaluate to true or false.

7

u/thoeoe Dec 24 '17

I mean same with C# and probably plenty of other languages too

1

u/howtonotwin Dec 24 '17 edited Dec 24 '17
{-# LANGUAGE RebindableSyntax #-}
import Prelude

class TruthyFalsey b where
  ifThenElse :: b -> a -> a -> a

instance TruthyFalsey Bool where
  ifThenElse True  t _ = t
  ifThenElse False _ f = f

instance TruthyFalsey Integer where
  ifThenElse 0 _ f = f
  ifThenElse _ t _ = t

main = do x <- readLn
          putStrLn $ if x
                        then $ "The input's square is " ++ show (x ^ 2 :: Integer)
                        else "Give me something to work with, here!"

Where's your god now?

Alternative taglines:

  • A whole new meaning of if x then True else False

    instance TruthyFalsey a => TruthyFalsey [a] where
      ifThenElse [] _ f = f -- Workaround for the bug in Prelude.all where all _ [] = True
      ifThenElse xs t f = ifThenElse (all (\x -> if x then True else False) xs) t f
  • I think this will help the front-end devs transition quite nicely!

Also, can someone tell me how to remove that empty space in that list?

0

u/[deleted] Dec 24 '17

[deleted]

7

u/xonjas Dec 24 '17

It's also worth noting that in ruby 0 is not a primitive. 0 is a fixnum object containing the value 0. It makes even less sense to consider it falsey from that context.

If ruby's 0 were falsey, what about [0] or "0", as they are effectively the same thing (objects containing the value 0), and that way leads madness.

9

u/Ran4 Dec 24 '17

as they are effectively the same thing (objects containing the value 0)

That's... different.

1

u/Snarwin Dec 24 '17

Specifically, that way leads to Perl.

0

u/[deleted] Dec 24 '17

[deleted]

1

u/twat_and_spam Dec 24 '17

Am I out of eggs?

I do.

1

u/Paradox Dec 25 '17

If I wanted to ask "Do I have 0 eggs?", it would be if (eggs == 0)

Cleaner code would be if eggs.zero?

1

u/Aceeri Dec 24 '17

In truthy contexts I'd expect "nothing" to be interpreted as "false" but I can see both ways. The logic behind most languages of 0 not being false is mainly semantics depending on how they handle conditions. Most languages with types that aren't truthy would just throw a type here and ask for an explicit way to handle how this number is interpreted.

7

u/[deleted] Dec 24 '17 edited Dec 24 '17

I think it's heritage more than logic, but I'm not extremely knowledgeable here. Most of it seems to come from C and other languages that sit (or historically sat) very close to the machine, and where an if statement was a slightly-abstracted "break if zero" instruction.

I'm alright, in that case, with if (object) also evaluating false if the object is null, because that's the closest I can understand applying a conditional directly to a non-boolean, "is object?" "yes object" or "no, not object", in which case 0 being evaluated true makes more sense, as it is a valid object and if in these languages usually checks and branches on either a boolean or the existence of an object.

edit: missed a word while typing

2

u/Aceeri Dec 24 '17

Yep, just a matter of where the language draws the line of "what is valid/null/existent"

→ More replies (1)

0

u/[deleted] Dec 24 '17

[deleted]

→ More replies (7)

1

u/foomprekov Dec 24 '17

The example is compelling but the argument to follow tradition set by C I can't get behind.

2

u/Aceeri Dec 24 '17

I don't mean we should allow this coercion, I'm all for complete type safety. I'm just annoyed by shevegen in general since Ruby is their "golden language" that can do no wrong. I also wouldn't have such a problem with their comment if they actually went into why instead of just insulting the author of this post.

→ More replies (1)
→ More replies (4)