Don't use the greater than sign in programming
source link: http://llewellynfalco.blogspot.com/2016/02/dont-use-greater-than-sign-in.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Sunday, February 21, 2016
Don't use the greater than sign in programming
Conditionals can be confusing
(x > 5 && 10 > x) (5 < x && 10 > x) (x > 5 && x < 10) (10 < x && x < 5) (x < 10 && x > 5) (x < 10 && 5 < x)
If you remove the use of the greater than sign then only 2 options remain:
(x < 10 && 5 < x)
which is a stupid option because it implies 10 < 5 and
(5 < x && x < 10)
This is a nice way of expressing "x is between 5 and 10" because it is literally between 5 and 10.
But why is this so expressive?
The Number line
Combinatorics
This problem gets much worse as the conditional grows. For example((-5 < x && x < -1) || (2 < x && x < 4))
Has 15 other possible ways to be expressed if you include the greater than sign and don't make your expressions conform to the number line.
29 comments:
Myk said...
That's a smart trick. I know from my personal coding that any time I start writing the bracket tokens, I'd better look extra closely and probably test what I'm doing because I tend to write a lot of bugs in that kind of code.
Tartley said...
Agreed all over.
FWIW, in Python, you can condense a little bit more by chaining inequalities: "5 < x < 10" means the logical 'and' of "5 < x" and "x < 10". And in common with your article, this also becomes impenetrable with > signs.
rob said...
You might want to fix the "outside" case to use "<=", or change the number line pictures, which seem to imply 5 and 10 are "outside".
Unknown said...
How simple it may seem it is indeed an issue to do it right. Working with integers is still the most easy one although you don't explicitly memtion if you want to include or exclude the boundary values. It becomes even more difficult if you're working with doubles or datetime objects. Then suddenly broken numbers or the time of the day also play part of the equation.
I've seen this go 'horrably' wrong several time, esoecially with datetime objects. Where analists write "from x until y" it is not clear wheather to include x and y or only include x and exclude y. To be clear there are enough ways to solve this but clear communication is the best one...
Unknown said...
How about writing a simple function like between(x1, x2) and replace all of that notation
Unknown said...
Why write a function for such a trivial expression? You will add to the cost of the overall method in which the method between appears. Remember, this will be called for each iteration.
Unknown said...
I think its perfectly fine to write small, "trivial" functions if they improve the expressiveness and readability of your code. Making micro-optimizations such as inlining expressions should probably be left to the compiler, which does a pretty good job at those kinds of optimizations. This allows the programmer to focus on optimizing the parts of the code that really need it, after they've profiled and identified a hot spot.
Unknown said...
> all of that notation
ahahahahaha!!!
Llewellyn Falco said...
> How about writing a simple function like between(x1, x2) and replace all of that notation
You will need 3 parameters in many languages, so between (x1,x2,x3) . so then the question becomes is the middle number the between value? or the first/last?
I do not care about the method overhead. Many languages will have it inlined anyways by runtime and it's a trival amount of time. Much prefer to optimize for readability and change rather than processor time.
> You might want to fix the "outside" case to use "<="
Yes, you are right.
Unknown said...
Using the middle for the `x` has a nice 'symmetry' with the meaning. If I were to do this, I'd call it something other than 'between' to make this more clear; perhaps `is_ordered(l, x, u)`.
Tartley said...
I'm the biggest fan in the world of creating functions to improve the expressiveness and readability of code, but I don't think that in this case it does so. The original expression is so clear and explicit that replacing it with a function call actually obscures important details of the operation such as the boundary conditions (i.e. is it '<' or '<=' for the start and end boundary?) Nothing that can't be figured out, with a quick 'go to definition', but in requiring the reader to do that, you've actually made the code harder to read, not easier.
Mr Bob said...
This comment has been removed by the author.
Greg Jorgensen said...
What is cleaner or easier to read comes down to personal taste. But how to express "all numbers greater than 1" without '>'?
Tartley said...
Personal taste is certainly a factor in some things, but not in everything. It's worth having the discussion. And within a single team, it sometimes helps to have a chat like this so that everyone can converge on a single style. If the decision is controversial, then perhaps it isn't appropriate. But a discussion like this one is often all that's needed for everyone on the team to realise they all feel the same way about it.
Llewellyn Falco said...
But how to express "all numbers greater than 1" without '>'?
1 < allNumbers
Unknown said...
1 < X
Unknown said...
Your "only two options remain" are the same except that you have swapped what is on either side of the &&. Maybe you meant
10 < x && x < 5
for one of them.
Unknown said...
You also can have function/method x.inBetween(low, hi) of between(lo, x, hi) and wrap it in not(). Its far more readable than x < 5 || 10 < x, which is poor-written !(5 <= x && x <= 10).
internot said...
TLDR: use <= operator.
The operator < is *exclusive*, which generally is not what is meant when you say "pick a number between 5 and 10". The number lines also show it as inclusive. In a discrete setting, the expression (2 < x && x < 4) is only true for x=3. More correct would be to use the <= operator. One can use less intuitive inclusive boundaries 1 x || x > 10).
Unknown said...
Programming is very interesting and creative thing if you do it with love. Your blog code helps a lot to beginners to learn programming from basic to advance level. I really love this blog because I learn a lot from here and this process is still continuing.
Love from Pro Programmer
mrjerry said...
nic post...
http://mkniit.blogspot.in
Unknown said...
This comment has been removed by the author.
Unknown said...
This blog awesome and i learn a lot about programming from here.The best thing about this blog is that you doing from beginning to experts level.
Love from Pprogramming
Anonymous said...
For those who want ESLint to disallow the greater-than operator, I created a pull-request (that has been rejected but) that contains the solution in the comments: https://github.com/eslint/eslint/pull/8677
The solution is to add the following rule in your config:
"no-restricted-syntax": [
"error",
{
"selector": "BinaryExpression[operator='>']",
"message": "Expected < instead of >."
},
{
"selector": "BinaryExpression[operator='>=']",
"message": "Expected <= instead of >=."
}
]
Thanks Llewellyn Falco, keep up with the great articles!
Chris
Unknown said...
Your title is against the greater than symbol, but your example where “one of them is wrong” shows the wrong one being done with the less than symbol “(10 < x && x < 5)”. After reading your post I'm not sure you've even made a point against the greater than symbol.
It's a valid symbol and it's practical for math so why not have it?
Mr F said...
I think everyone has different tricks to read maths quicker. For me it's cleaner when I think about X, one condition at a time, so (x > 5 && x < 10) would be better. Because it's how I would express it in speech: "x is greater than 5 and less than 10", not "5 is less than x", I'm concerned about x, not 5.
Earlofthercs said...
Your number line examples include both 5 and 10 as possible answers (making the range equal to or greater than 5 to equal to 10), while your code excludes them - so which is it?
Unknown said...
| (x < 10 && 5 < x)
| which is a stupid option because it implies 10 < 5 an
No, that expression does not imply 10 < 5
StackPointer said...
As a matter of style, I prefer to always have the variable name to the left of the operator. I think it is cleaner even though you can have more variants of the conditional.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK