Live data from Hacker News

I am a horse in the land of booleans

iloveponies.github.io

61–70 of 89 posts

Re: I am a horse in the land of booleans

#61
post #46
post #43

> if does not have a return value in a language like Java. In other words, it is not an expression, but a statement. Because everything in Clojure is an expression, there is no equivalent construct to Java’s if in it. Anyone know the language design rationale behind the way Java does it? It seems much easier to make everything an expression. Ive always disliked that part of Javascript and being forced to use ternary…

If your control structures are expressions then they can lead to code that the maintainers of the language might not want to promote. Remember that language design is not just about being as flexible as possible. If it were we would have stopped with Lisp. Languages are also designed with readability, portability, and simplicity in mind. Imagine if you could write this (nonsense) code in Java: bool a = (while (b) { i…

I've worked extensively with both Java and Clojure, and the latter is far easier to read in my experience.

Re: I am a horse in the land of booleans

#62
post #48

Because Java’s if does not return a value, you cannot say: return if (x This would have been a nice place to make an analogy to the question mark operator, since a java programmer would probably be familiar with it and it allows you to write: return if (x as return x

>>java programmer would probably be familiar with it

And also C, C++, and Objective-C programmers. I'm sure there are more languages that use that operator that I have not mentioned here.

Re: I am a horse in the land of booleans

#63
post #48

Because Java’s if does not return a value, you cannot say: return if (x This would have been a nice place to make an analogy to the question mark operator, since a java programmer would probably be familiar with it and it allows you to write: return if (x as return x

>>java programmer would probably be familiar with it And also C, C++, and Objective-C programmers. I'm sure there are more languages that use that operator that I have not mentioned here.

I have not touched PHP in the last 10 years but if memory serves it also has the ternary operator. Ok, lets try it:

    $ php -a
    Interactive mode enabled
    php > echo 1 == 1 ? "foo" : "bar";
    foo
    php > echo 1 == 2 ? "foo" : "bar";
    bar
Looks like javascript has it too:

    1 == 1 ? "foo" : "bar"
    "foo"
    1 == 2 ? "foo" : "bar"
    "bar"

Re: I am a horse in the land of booleans

#64
post #57
post #52

Earlier quoted context omitted.

i haven't checked it thoroughly, but it looks like all the desired properties of boolean arithmetic are preserved when false = 0 true = [1] (i.e. the equivalence class of all n > 0) && = + || = * spelling it out: || / + (or): 0+0 = 0 0+[1] = [1]+0 = [1] [1]+[1] = [1] && / * (and): 0*0 = 0 0*[1] = [1]*0 = 0 [1]*[1] = [1] where [1] stands for "any nonzero number". (please let me know if i missed anything!) so natural n…

`[1]+[1] = [1]` also doesn't hold for natural numbers if you are programming in a language with integer overflow. Neither does the multiplication `[1]*[1] = [1]`

true! i wondered if i should include that but decided to stick with the "mathematical" naturals since we were talking from a math standpoint

Re: I am a horse in the land of booleans

#65
post #32

Earlier quoted context omitted.

0 is the value integral types get default initialized too, it's the equivalent of default initializing a boolean to false.

But the fact that some types have a reasonable default value doesn’t make the values intrinsically equivalent to Boolean false. Plus, implicit default initialization is itself not necessarily a desirable feature. Especially not the kind that just default initializes to an all-zeroes bit pattern.

default initialization is a desirable feature in most circumstances, and I would argue most languages should be opt-out rather than opt-in.

There are really only two reasons I can think of for not wanting default initialization.

1. performance

2. to catch mistakes on the edges of your system.

A good example of the second is converting incoming data to enumerations. If you're not explicitly checking for it, you can accidentally default initialize to a valid enumeration. This is why I always set the first enumeration to 1 for any language that allows me to. If someone makes that mistake, the missing data causes an error rather than silently doing the wrong thing.

But I can't really think of any reason outside of those two cases where you wouldn't want default initialization.

And my point was that one of the reasons 0 is chosen as false because it's consistent with respect to default initialization of booleans. I realize that isn't the original reason, but today it's a good reason for having the behavior.

Re: I am a horse in the land of booleans

#66
post #3

I’m used to 0 and [] being falsy. Upsides and downsides to Clojure’s choice here?

All of the comments here seem to be addressing the issue of 0 being falsy, and I agree with them - 0 is a perfect 'useful' value that is no different from 1 in many use cases. But no one seems to be addressing the advantage of the empty list/array/collection being treated as falsy, which in my opinion is significant.

The major advantage of empty collections being falsy is that you can kill two birds with one stone - it enables you to reduce your use of nil/null/None dramatically, since empty collections will fail a very idiomatic "if items" check just as well as null. But at the same time, you don't have to depend on users (library or otherwise) being careful to provide an empty list rather than null when they mean 'no value' - if they pass a null then your code will take the exact same shortcut with the exact same simple, idiomatic test. Whereas the alternative is needing to do both the null check AND the empty check any place you cannot trust the users of your function/library/whatever to pass real empty collections rather than nulls, which not only becomes tedious but is quite easy for new programmers to fail to do consistently.

In my own experience, the number of cases where an empty collection implies that data is effectively 'missing' is far greater than the number of cases where an empty list being provided would be semantically different from a null - in both cases "there is nothing there". And being freed to then create and pass around empty lists means that my own code is no longer littered with the necessary guards against Nullness in cases where I am the consumer of my own functions and want to be able to write simple list comprehensions without any guards.

In Clojure this is somewhat less of an issue because, as others have mentioned, it's idiomatic to pass `nil` around in the place of an empty collection, and so it's _generally_ safe to do so where in another language like Python or Javascript the function you're calling might not expect it. But in my opinion there was no real advantage to establishing this convention when it could just as easily have been the other way around, and there would therefore be somewhat less opportunity for inconsistent or inexperienced programmers causing NullPointerExceptions.

Re: I am a horse in the land of booleans

#67
post #8

Earlier quoted context omitted.

0 being falsy makes no sense outside of the C family of programming languages. But there 0 is overloaded both as a number and pointer (it's a bit more complicated though, as the value of the null pointer doesn't need to be zero but assigning 0 to a pointer will assign the null pointer). In languages with more elaborate type systems, you usually have the pointer and number representation separated. 0 has no special me…

>But making zero elements evaluate to falsy is problematic. "" would be falsy as well then. In Python 0, [], and "" are all falsy. In my experience it's only been useful - why do you consider it problematic?

For what it's worth, I am generally in agreement with you, so you're not alone.

I do think it would've been better to have 0, specifically, not be falsy - unlike the other cases, 0 is not 'the absence of any actual data' but rather a special case of the data. I assume Python stuck with tradition on this one mostly because it is so tightly tied to C and UNIX-style scripting that changing it would've been confusing for most early users.

Re: I am a horse in the land of booleans

#68
post #46
post #43

> if does not have a return value in a language like Java. In other words, it is not an expression, but a statement. Because everything in Clojure is an expression, there is no equivalent construct to Java’s if in it. Anyone know the language design rationale behind the way Java does it? It seems much easier to make everything an expression. Ive always disliked that part of Javascript and being forced to use ternary…

If your control structures are expressions then they can lead to code that the maintainers of the language might not want to promote. Remember that language design is not just about being as flexible as possible. If it were we would have stopped with Lisp. Languages are also designed with readability, portability, and simplicity in mind. Imagine if you could write this (nonsense) code in Java: bool a = (while (b) { i…

Of course I'd say this as a lisper, but as long as the return values of everything is intuitive and well defined, I don't see an inherent problem with such form.

Indeed, if anything, if the intention is to communicate that the Boolean value is the result of some process that runs through a while loop, then explicitly saying that in the assignment seems to me to almost be the best way to do it :\

ymmv.

Now deeply nested while/assignment/ifs, that's a bad-pattern, but I'm not inherently convinced that's an expression/statement problem.

Re: I am a horse in the land of booleans

#69

Earlier quoted context omitted.

I'm also used to 0 being false. A possible upside to this is that you can use multiplication and addition as boolean AND and OR, which might not seem that useful, but I remember that BASIC on a ti99/4a had neither AND nor OR, but boolean expressions evaluated to 0 or 1, so you could use this trick. Instead of if x = 5 and y = 7 then goto 10 use if (x = 5) * (y = 7) then goto 10 Good to know when you're 11 years old t…

It sounds like that was only useful because the language actually had no Boolean type (hence no operations for Boolean types). It doesn't really demonstrate that there is value to a "falsey" 0 in a language that already has a perfectly good value for false.

Uh yeah, no kidding, that's why I qualified what I was saying with "possible...", and "which might not seem that useful, but..."

Re: I am a horse in the land of booleans

#70

Earlier quoted context omitted.

"p" makes sense if you know that it stands for "predicate". It's not nearly as arcane as car and cdr. Also can we finally settle on a name for these things now? If car and cdr are too arcane we can do away with them (though I like being able to do caddadadr) but why do we need "first" and "rest" rather than the already established "head" and "tail"? I particularly dislike "rest" since it's a relative term, i.e. in no…

In Clojure, first and rest apply to sequences, which are a logical list abstraction. They apply to lists, but they can also be used on sequential views of indexed vectors, maps, sets, database result sets, files in a dir, lines in a file, and an open world of "things that can be seen in some order". head and tail I suspect are much more tied to linked lists and data structure than the more plain first and rest.

If you are using first and rest, then you are treating whatever sequence you have as a linked list, so you've already lost the plot.
Post reply on HN