for-loop over byte ranges gives type error on try.ceylon-lang.org
ePaul opened this issue · 3 comments
Wrong behavior
Try to iterate over a range of bytes with a for-loop:
for (b in 0.byte..3.byte) {
print(b);
}
Try it!
Trying to run this on try.ceylon-lang.org gives this error:
undefined — Runtime error:
undefined — --- TypeError: $1i.compare is not a function
Script ended with no output
Expected behavior
Running this code should print
0
1
2
3
Analysis
From the error message, it looks like some part of the compiler is trying to convert this into a classic increment-comparison loop. But bytes in Ceylon have no total ordering, and thus also no comparison operators or compare
functions.
Should the ..
operator complain about the type not having total ordering? Or how should it work?
The ..
operator is syntax sugar for ceylon.language::span
, which only requires that its arguments be of a type satisfying Enumerable
, and (per its docs)
An Enumerable type is characterized by each element having well-defined
offset
andneighbour()
functions.
Bytes don't have a total ordering in Ceylon because they aren't specifically signed or unsigned, and offset
and neighbour
are defined in terms of modular arithmetic, wrapping around.
I tried the code in the OP above on the JVM, and it gives the results shown under "Expected behavior" above. I also compiled it to JS using ceylon compile-js
, and the code above compiled to
var $3=(0).$_byte,$2=(3).$_byte,$4=$3.compare($2),$5=$4===m$1.smaller()?'successor':'predecessor';for(var $6=m$1.eorl$($4);$6($2,$3);$3=$3[$5]){
m$1.print($3);
}
Ah, so the problem is not on the loop condition, but already when trying to figure out whether to do an upwards or downwards iteration, which doesn't apply for a recursive Enumerable type like Byte. I guess that first comparison should call $3.offset($2) < 0
?