I’m curious, what was the design decision that mad...
# announcements
j
I’m curious, what was the design decision that made
1..4
return you a list, but
4..1
doesn’t return anything. One would expect
4..1
equals
(1..4).reversed()
.
👍 3
d
janvladimirmostert: I would suspect to avoid confusion when the parameters (1 and 4) are not constants.
👍 1
If you use .. you expect to get an ascending sequence
j
@diesieben07 actually, I’m not expecting an ascending sequence, the expectation is to get a sequence containing the range whether it’s ascending or descending
d
well, that's not what the operator does though.
j
could probably override it to first check if a > b, then do a rangeTo otherwise return a rangeDownTo
h
@diesieben07 In R
base::seq(5,1)
gives a descending sequence, so I’d think not everyone is expecting an ascending sequence. I would not either. I agree with @janvladimirmostert about the expected behavior.
👍 1
d
Well, my expectations are different then 😄
e
@diesieben07 Is right. Kotlin is not Python. You have to be explicit on whether you want ascending (
..
or
rangeTo
) or descending (
downTo
) sequence. More here: https://kotlinlang.org/docs/reference/ranges.html
h
The javadocs just state that it
creates a range from this value to the specified other value
, so if
this
is greater than
other
the resulting sequence should start with
this
to fulfill its contract.
j
I could probably just do this:
Copy code
operator fun Any.rangeTo(b: Any) = if (this > b) getAscendingRange(a,b) else getDescendingRange(a,b)
😄
e
You can. But I would not recommend. It is very hard to debug the practical algorithms with this Python-style definition, as incorrect input parameters would lead to subtle bugs.
For example, when you write
1..i
in your code you usually know it has to be ascending and you don’t want it to do anything when
i
is zero or negative
It is just pragmatism in action
j
coming from a Python background 7 years ago, I would argue, if you put
1..-2
in there, you would expect a list
[1, 0, -1, -2]
otherwise it should throw an exception if it’s expecting the second parameter to be bigger than the first.
Currently it “fails” silently.
e
That is what you expect most of the time in practise. If you want to something to be done
n
times, then you expect
(1..n).forEach { ... }
to be not doing anything when
n == 0
☝️ 2
That is just the most common expected behavior. It is also a safe bet for
n < 0
.
This lets you avoid extra check in most practical code I’ve seen, but it always Ok to add extra check when you need it.
j
luckily Kotlin is flexible enough that I can override it for our purposes
e
If the “flexible” behaviour, almost any piece of practical code would always have to add an extra check.
j
indeed, but in this specific project, we don’t mind things going into the negative, so no checks needed
e
Of course, you can always override it (that is Kotlin)
👍 1
For redability, though, I’d suggest to introduce your own infix function for that (instead of redefining
rangeTo
operator)
But, that is all domain-specific. If that is all you need in your domain, then redefining
rangeTo
is also Ok.
j
Since Kotlin is not Scala, I’m guessing at no stage in the future will Kotlin allow defining custom operators?
infix
pyRangeTo
is probably good enough, makes code more readable
👍 1
e
There are no plans to support custom operators in the near future. The example of Scala is educating enough to discourage all future language designers from doing that.
❤️ 2
👍 3
j
i’ve seen that feature abused so badly that code becomes unreadable 😄
Some day we might see a “Project Lombok”-like project for Kotlin that allows custom operators written by Scala devs who now have to write Kotlin 🧌