6 ms·
I honestly don't think being able to write 'a < b < c' is worth making the language bigger and causing weirdness and gotchas like this. 'a < b && b < c' isn't t
by m12k 6y ago
I honestly don't think being able to write 'a < b < c' is worth making the language bigger and causing weirdness and gotchas like this. 'a < b && b < c' isn't that much longer and is instantly and unambiguously readable to programmers coming from hundreds of other languages.
- throwaway_pdp09 6y agoI really agree with this. Maths <> programming, so while some notation sharing is good, don't (IMO) take it too far. I don't like it either when languages get too helpful. I was recently doing some python and getting some very odd results. Turned out the index I was using to pull stuff from the list had gone negative (off by one error) so it was getting stuff from the end of the list rather than excepting as most languages would. That is y = [1,2,3] y[-1] <-- unintentionally negative index I'm not saying the ability to index with negatives like this is a bad thing in python, but I seriously question it's value vs the footgun thing. A while ago I was doing some SQL and used an answer off stack overflow. It was a good answer but it tried to be too flipping helpful. IIRC it was doing nontrivial date difference calculations[0]. Rather 'helpfully' if "(date2 - date1) < 0" it would kindly assume you'd given it arguments in the wrong order and silently flip them for you (to "date1 - date2") to get you a positive number, always. This 'helpful' behaviour hid the presence of bad data (date2 should always have been chronologically later than date1 - date1 was interview, date2 was when job started). Moral: keep programming language & library semantics simple. [0] I remember now, it was the number of weekdays (that is, excl. sat/sun) between 2 dates.
- amedvednikov 6y agoYeah this is exactly why negative indexing is a bad idea and why I'm against introducing this in V.
- jaggirs 6y agoNegative indexing (along with the related syntax for slicing) is one of the most usefull python features. Numpy and pandas thrive on it. Just learn the language, python is already one of the easiest languages out there.
- throwaway_pdp09 6y agoI know python. I have rarely found negative indices useful except to pick out the last item of a list, and I've done a decent amount of it, though no numpy/pandas yet. In what way is negative indices particularly useful for these latter two? I have no problem with slicing. You can't get it accidentally wrong because the syntax is visible. Negative indexing vs positive indexing can't generally be distinguished just by looking at the indexing statement, which is where I tripped up.
- ben509 6y agoHow would you feel about: y[end(1)] y[len - 1] Either one then constructs a "reverse index" value, and the actual index is determined by the slicing operation.
- throwaway_pdp09 6y agoBoth of these are idiomatic because they're not built by composition. y[end(1)] is non-composed because AFAICS end(1) is meaningless by itself. Ditto the second although y[len(y) - 1] would be closer to the mark. If you're willing to accept a naive implementation that can be optimised, something like reverse(y)[1] is compositional though inefficient as-is. You could though recognise this overall and optimise it to not reverse the lot before picking out a single item.
- ben509 6y agoAllow me to justify why end(1) and len are meaningful: Suppose indexing (and you can extend this to slicing if these are possible components of a Range type) is polymorphic. list[Index] means to find an element at Index, starting at the beginning list[ReverseIndex] means to find an element at ReverseIndex, starting from the end Int is naturally a subtype of Index. end(Int) would be a constructor for some concrete subtype of ReverseIndex that is distinct from Int. Or len would simply be shorthand for ReverseIndex(0). And ReverseIndex is also defined for the usual int arithmetic, except that it returns new values of ReverseIndex.
- throwaway_pdp09 6y agoInteresting idea. I can see that end(1) would work though it's bringing in a lot of machinery just for a little thing (though if we looked harder that might generalise to other situations enough to make it viable). Alternatively you could do the same with a method I think, something like y.end[1] although y.fromEnd[...] might be more mnemonic. I don't see that y[len - 1] could work in this scheme, but whatever. I like yer thinking!
- lioeters 6y agoI also question the value and cost of syntactic sugar like chained comparison operators, negative indexes, even semantically significant whitespace/indentation. They let the programmer take shortcuts, but unless they're always attentive of their implicit behavior, can be a source of subtle bugs. I say that as a one-time enthusiastic user of CoffeeScript, which felt so refreshing and elegant at first. Over time, especially working with other people's codebases, I came to a personal conclusion that it's not worth the convenience. Syntax sugar can hide logic that would be better explicit. Even if it feels verbose, there's value in being able to see exactly what's happening. An example of the latter that I've heard occasionally, is how error handling is done in Go. Every single function call that can return an error must be explicit handled (as far as I know). There could have been some sugar to make it simpler, but they preferred to keep it verbose. That was the right decision, in my opinion, and other aspects of the language give me the impression that it's a consistent design philosophy.
- MaxBarraclough 6y agoAgreed. It strikes me as an inelegant abuse of notation even when it's used in a maths context, albeit a convenient one. It violates the way we can usually reason about infix operators. a < b is an expression which gives you a booean value, true or false. Why then are we comparing whether it is less than, or greater than, some number? Unlike with addition or multiplication: a < b < c ≠ (a < b) < c also: a < b < c ≠ a < (b < c) instead: a < b < c = ((a < b) ^ (b < c)) The same criticism does not apply to C's chained assignment expressions, a = b = c, but I dislike that for another reason: if the type of b is a narrower type than that of c, you may get an unexpected value assigned to a.
- hmry 6y agoBut in your proposed solution b would be evaluated twice. So you would have to add a new line, think of a new variable name, and so on. if lower < x.calculate_weight() < upper: ... Suddenly turns into x_weight = x.calculate_weight() if lower < x_weight and x_weight < upper: ...
- nitroll 6y agoAnd is that so bad? So often i did stuff like that, then finding I actually need the result of x.calculate_weight() inside the condition, or to debug it or log it in some way. Then it has to be extracted anyway.