Open PureFox48 opened 3 years ago
Excluding the fact that it can break existing code, I find it not really elegant mainly because it is some kind of method chaining...
What's bad with method chaining?
@mhermier
Excluding the fact that it can break existing code
How can it do that?
I thought that it wasn't recommended to inherit from built-in classes (apart from Sequence
) so, even if it works, you shouldn't be doing it anyway.
I find it not really elegant
Well, it's always more elegant to use built-in syntax but, personally, I don't find the use of methods instead unattractive.
But anyway, however it's done, what about the general principle of these proposed changes. Do you think they're worthwhile or not?
There is nothing wrong with method chaining, the problem is that the lack of a method chaining operator, make the things "ugly".
If we have an operator for method chaining, lets say ;
then the example become something like:
var a = 0
// ....
for (i in 1..a;ascending = true) System.write("%(i), ")
// no output as 'a' is less than '1' and the range is locked to ascending
for (j in 10..a;step = 2;ascending = false) System.write("%(j), ")
// would print 10, 8, 6, 4, 2, 0 as the range would be descending anyway
There is an ambiguity of priority that needs to be solved probably with parenthesis but this makes setters/getters all unified and allow to tune the chained object one the go.
@PureFox48 I thought the method you added was changing some existing behavior, my bad if you added new names.
@mhermier
I don't dislike your idea of using ;
as a method chaining operator and it's what I would have suggested myself if we were to change the language syntax rather than just adding extra methods.
However, it's clearly a more far reaching idea and, even if we had it, we'd presumably still need to add new methods to the Range class in the first place.
I've been thinking some more about the issues raised here (which for me, at least, are a constant thorn in the flesh) and have come up with what I think is a more elegant solution (clearer, less parentheses) than using instance methods.
Suppose instead we give the Range class two constructors:
Range.asc (start, end, step)
Range.desc(start, end, step)
where :
start
is the start point of the range (inclusive)
end
is the end point of the range (also inclusive)
step
is the step value (a positive integer).
Range.asc
and Range.desc
would always produce ascending or descending ranges, respectively. If start
and end
were the wrong way around, the constructors would simply return empty ranges.
Although these constructors wouldn't support exclusive ranges explicitly, they are of course easy to simulate by adjusting the end point appropriately.
An instance getter (step
) would also be needed to return the step value.
So the earlier examples would now look like this:
for (i in Range.asc(0, 10, 2)) System.write("%(i), ")
// would print 0, 2, 4, 6, 8, 10
var a = 0
// ....
for (i in Range.asc(1, a, 1)) System.write("%(i), ")
// no output as 'a' is less than '1' and the range is locked to ascending
for (j in Range.desc(10, a, 2)) System.write("%(j), ")
// would print 10, 8, 6, 4, 2, 0
System.print((1..6).step) // 1
I did wonder about making the end point exclusive as this would be more consistent with existing APIs such as Random.int
and with what some other languages do (c.f. Python). However, arguably inclusive ranges are more intuitive for users particularly for descending ranges.
The present syntax for constructing ranges using the ..
and ...
operators would be unaffected and would therefore continue to work the same way it always has.
No particular opinion. Seems plain boring, but don't know it is a good or bad thing though.
Seems plain boring
It's a good thing :)
It implies that it doesn't take much learning.
Although ranges in Wren are good they could, IMHO, be made better in two respects.
Firstly, there should be a way to specify the step which currently is always one. For example:
To avoid potential confusion, I think the step should always be positive whether the range is ascending or descending.
Secondly, an occasional bug in my own code is that I'm sometimes surprised (when the start or end point of the range is variable) that the range is iterating in a different direction to what I intended! It would be useful if there were a way to 'lock' a range to always iterate in a particular direction so that it would be empty if the boundary points evaluated to being the wrong way around. So we'd then have something like this:
Incidentally, the proposed method names here (
by
,asc
anddesc
) are just ones which immediately come to mind - I'm not particularly wedded to any of them.Now, I know that you can always use a
while
rather than afor
statement to get around these problems - and I do - though I then sometimes forget to increment the 'control' variable and end up in an infinite loop :)I've also written library classes which wrap a range and then change the way the iteration works though, as this is a rather clunky solution, I don't use them much.
Other languages often have built-in (and sometimes rather cryptic) syntax to deal with steps and iteration direction though I see no need for this in a resolutely object-oriented language such as Wren. Additional methods would be fine.
As always, I look forward to comments.