Closed interval maybe a mistake?
In my current experience, the expression 0..5 means that [0,1,2,3,4,5] doesn't seem to work as well as [0,1,2,3,4], so the half-closed interval $[a, b)$ might be better?
I'm afraid it would be a huge breaking change.
What about the math version: [0..5] for [0,1,2,3,4,5] and [0..5[ for [0,1,2,3,4] (if the syntax is possible)
The other option would be to use the Python equivalent [0:5]
Indeed, and I find some interesting uses of range:
> [1, 2, 3, 4][0 .. -1]
[1, 2, 3, 4]
> [1, 2, 3, 4][0 .. 0] # not an empty range
[1]
> [1, 2, 3, 4][0 .. -4]
[1]
> [1, 2, 3, 4][0 .. -5]
[]
You could also use Ruby syntax by adding another dot, but i can see how that would be confusing.
> [0..5]
[0,1,2,3,4,5]
> [0...5]
[0,1,2,3,4]
Another idea is having ..= and ..< to be more explicit, but it may look too ugly/verbose
> [0..=5]
[0,1,2,3,4,5]
> [0..<5]
[0,1,2,3,4]
The other option would be to use the Python equivalent
[0:5]
I agree with this.
Revisiting some old issues. Are you still in favor of this syntax for excluded last value?
I'm just a casual observer who thinks Berry is really neat, but IMHO Python's a[start:stop:step] slice syntax strikes a nice balance between expressiveness and complexity. Especially with support for negative numbers.
This may be possible. Considering:
# if operator : has the following rules:
a : b # => range(a, b) if `a`, `b` is integer
a : b # => range(a.lower(), a.upper(), b) if `a` is a range, then update its step!
# examples:
1 : 10 : 2 # => range(1, 10, 2)
Revisiting some old issues. Are you still in favor of this syntax for excluded last value?
It doesn't seem like a big deal?
My main concern is still with loops. The majority of the loops in my code is the following:
var l
# populate l
for idx: 0..size(l)-1
# do something
end
This compiles as follows:
; line 2
0000 LDNIL R0
; line 4
0001 GETGBL R1 G16
0002 GETGBL R2 G12
0003 MOVE R3 R0
0004 CALL R2 1
0005 SUB R2 R2 K1
0006 CONNECT R2 K0 R2
0007 CALL R1 1
0008 EXBLK 0 #000C
0009 MOVE R2 R1
000A CALL R2 0
000B JMP #0009
000C LDCONST R1 K2
000D CATCH R1 1 0
000E RAISE 2 R0 R0
; line 6
000F RET 0
The main problems are:
CONNECTcreates a temporaryrange()object that is later garbage collected- the loop exits with an exception, which is a heavy construct
I understand that using an iterator and an instance solves the general case, but I end up often writing the following instead:
var l
# populate l
var idx = 0
while idx < size(l)
# do something
idx += 1
end
The compiled code is much shorter and faster:
; line 3
0000 LDNIL R0
; line 5
0001 LDCONST R1 K0
; line 6
0002 GETGBL R2 G12
0003 MOVE R3 R0
0004 CALL R2 1
0005 LT R2 R1 R2
0006 JMPF R2 #0009
; line 8
0007 ADD R1 R1 K1
0008 JMP #0002
; line 9
0009 RET 0
Hence I would be in favor of doing a alternative construct for simple loops with 1 increments:
var l
# populate l
for idx: 0:size(l)
# do something
end
I'm also concerned by the readbility especially if you don't add a space: for idx:0:size(l) would be hard to read.
Any thoughts or alternative syntax?