TP
Torsten Paul
Sat, Nov 2, 2019 3:55 AM
I'm looking at making array (and string) handling more
flexible by adding slicing.
This would use the range syntax [begin:step:end] but
the interpretation of values is different from actual
ranges. Specifically negative values produce indexes
counted from the end of the array.
In addition I'm trying to add a way to express that
the range/slice is supposed to be a half-open interval.
So far the way Swift is doing that seems to fit best.
Translated to OpenSCAD syntax, this would looks like:
[begin:<end] or [begin:step:<end].
(Please don't suggest [begin:end) - that's not going
to happen even though it's tempting. ;-)
Examples using a = [0,1,2,3,4,5,6,7,8,9];
echo(skip_first = a[1:]);
// ECHO: skip_first = [1, 2, 3, 4, 5, 6, 7, 8, 9]
echo(skip_last_inclusive = a[:-2]);
// ECHO: skip_last_inclusive = [0, 1, 2, 3, 4, 5, 6, 7, 8]
echo(skip_last_exclusive = a[:<-1]);
// ECHO: skip_last_exclusive = [0, 1, 2, 3, 4, 5, 6, 7, 8]
For more examples, see the description on github:
https://github.com/openscad/openscad/pull/3115
ciao,
Torsten.
I'm looking at making array (and string) handling more
flexible by adding slicing.
This would use the range syntax [begin:step:end] but
the interpretation of values is different from actual
ranges. Specifically negative values produce indexes
counted from the end of the array.
In addition I'm trying to add a way to express that
the range/slice is supposed to be a half-open interval.
So far the way Swift is doing that seems to fit best.
Translated to OpenSCAD syntax, this would looks like:
[begin:<end] or [begin:step:<end].
(Please don't suggest [begin:end) - that's not going
to happen even though it's tempting. ;-)
Examples using a = [0,1,2,3,4,5,6,7,8,9];
echo(skip_first = a[1:]);
// ECHO: skip_first = [1, 2, 3, 4, 5, 6, 7, 8, 9]
echo(skip_last_inclusive = a[:-2]);
// ECHO: skip_last_inclusive = [0, 1, 2, 3, 4, 5, 6, 7, 8]
echo(skip_last_exclusive = a[:<-1]);
// ECHO: skip_last_exclusive = [0, 1, 2, 3, 4, 5, 6, 7, 8]
For more examples, see the description on github:
https://github.com/openscad/openscad/pull/3115
ciao,
Torsten.
P
Parkinbot
Tue, Nov 5, 2019 9:37 PM
Very good idea to introduce a syntax for array slicing!
echo(skip_last_exclusive = a[:<-1]);
// ECHO: skip_last_exclusive = [0, 1, 2, 3, 4, 5, 6, 7, 8]
But to be honest: The sequence [:<- looks very cryptic and C-like. Also,
introducing and distinguishing between two interval types is too much
complication in my opinion. MATLAB style is much clearer, and you don't need
to distinguish interval types. It uses the reserved word 'end'.
echo(skip_last_exclusive = a[:end-1]); // Matlab style
// ECHO: skip_last_exclusive = [0, 1, 2, 3, 4, 5, 6, 7, 8]
Well, as 'end' is not a reserved word in OpenSCAD, what about '$' or better
'$end'? The latter might not break too much code, as using dynamic scope
variables is not encouraged, and cases, where '$end' is declared and used as
'variable', can be easily detected.
The usage is straight forward:
echo(skip_last = a[:$end-1]);
// ECHO: skip_last = [0, 1, 2, 3, 4, 5, 6, 7, 8]
echo(second_last = a[$end-1:$end-1]);
// ECHO: second_last = [8]
echo(last_two = a[$end-1:$end]); // alternative: last_two = a[$end-1:]
// ECHO: last_two = [8, 9]
In any case this syntax is intuitive, and you don't have to introduce and
distinguish a second (counter intuitive) interval type.
--
Sent from: http://forum.openscad.org/
Very good idea to introduce a syntax for array slicing!
> echo(skip_last_exclusive = a[:<-1]);
> // ECHO: skip_last_exclusive = [0, 1, 2, 3, 4, 5, 6, 7, 8]
But to be honest: The sequence [:<- looks very cryptic and C-like. Also,
introducing and distinguishing between two interval types is too much
complication in my opinion. MATLAB style is much clearer, and you don't need
to distinguish interval types. It uses the reserved word 'end'.
echo(skip_last_exclusive = a[:end-1]); // Matlab style
// ECHO: skip_last_exclusive = [0, 1, 2, 3, 4, 5, 6, 7, 8]
Well, as 'end' is not a reserved word in OpenSCAD, what about '$' or better
'$end'? The latter might not break too much code, as using dynamic scope
variables is not encouraged, and cases, where '$end' is declared and used as
'variable', can be easily detected.
The usage is straight forward:
echo(skip_last = a[:$end-1]);
// ECHO: skip_last = [0, 1, 2, 3, 4, 5, 6, 7, 8]
echo(second_last = a[$end-1:$end-1]);
// ECHO: second_last = [8]
echo(last_two = a[$end-1:$end]); // alternative: last_two = a[$end-1:]
// ECHO: last_two = [8, 9]
In any case this syntax is intuitive, and you don't have to introduce and
distinguish a second (counter intuitive) interval type.
--
Sent from: http://forum.openscad.org/
G
gasstationwithoutpumps
Fri, Nov 8, 2019 4:43 AM
Why not use the Python conventions for slices? They will already be familiar
to a large fraction of the programmers who use OpenSCAD, and they are easy
to remember. Putting in something that looks like the Python slice but has
a subtly different semantics is probably a bad idea.
Sent from: http://forum.openscad.org/
Why not use the Python conventions for slices? They will already be familiar
to a large fraction of the programmers who use OpenSCAD, and they are easy
to remember. Putting in something that looks like the Python slice but has
a subtly different semantics is probably a bad idea.
-----
gasstationwithoutpumps.wordpress.com
www.thingiverse.com/gasstationwithoutpumps/things
--
Sent from: http://forum.openscad.org/
DM
Doug Moen
Fri, Nov 8, 2019 5:45 PM
On Fri, Nov 8, 2019, at 4:43 AM, gasstationwithoutpumps wrote:
Why not use the Python conventions for slices?
There are two inconsistencies between the Python syntax for slices, and the OpenSCAD syntax for ranges.
One inconsistency is where the 'end' value is located:
Python slice:
a[start:end:step]
OpenSCAD range:
[start:step:end]
The other inconsistency is that Python uses half-open ranges, and OpenSCAD uses closed ranges, for the same syntax.
Eg, Python a[0:10] selects elements 0-9 (the first 10 elements), vs OpenSCAD [0:9] is a 10 element range from 0 to 9 inclusive.
Using these two incompatible conventions in the same language is a recipe for confusion.
On Fri, Nov 8, 2019, at 4:43 AM, gasstationwithoutpumps wrote:
Putting in something that looks like the Python slice but has
a subtly different semantics is probably a bad idea.
I agree with this.
In the OpenSCAD2 design document, I proposed to introduce a new syntax for ranges and slices, which would not be confusing to either OpenSCAD or Python programmers.
The original OpenSCAD2 proposal was based on Haskell syntax, but it had some limitations, so what I actually ended up implementing in Curv is:
start .. end
start .. end by step
for a range, and
a[start .. end]
a[start .. end by step]
for a slice. I also adopted the Swift notation for half-open ranges:
start ..< end
start ..< end by step
The word 'by' is a keyword in Curv. This syntax has no visual ambiguity about which field is the 'step' value. The '..' operator is found in many programming languages, and it means a closed range, not a half-open range. So this syntax has no ambiguity about closed vs half-open.
There is a design flaw in OpenSCAD range syntax. [0:len(a)-1] is a common idiom for a range containing all of the array indexes of 'a'. However, if 'a' has zero length, then instead of the empty range, you get [0:-1], which is a two element range equivalent to [-1,0]. I think this is a bug that should be fixed, but instead of fixing the bug, this behaviour has been deprecated for many years. It looks to me that the bug will not be fixed, for backward compatibility reasons. If that's the case, then introducing a new range syntax is the only way to get a version of ranges in which this bug is fixed. That was another reason why OpenSCAD2 originally proposed to introduce the '..' range syntax.
Doug Moen
On Fri, Nov 8, 2019, at 4:43 AM, gasstationwithoutpumps wrote:
> Why not use the Python conventions for slices?
There are two inconsistencies between the Python syntax for slices, and the OpenSCAD syntax for ranges.
One inconsistency is where the 'end' value is located:
Python slice:
a[start:end:step]
OpenSCAD range:
[start:step:end]
The other inconsistency is that Python uses half-open ranges, and OpenSCAD uses closed ranges, for the same syntax.
Eg, Python a[0:10] selects elements 0-9 (the first 10 elements), vs OpenSCAD [0:9] is a 10 element range from 0 to 9 inclusive.
Using these two incompatible conventions in the same language is a recipe for confusion.
On Fri, Nov 8, 2019, at 4:43 AM, gasstationwithoutpumps wrote:
> Putting in something that looks like the Python slice but has
> a subtly different semantics is probably a bad idea.
I agree with this.
In the OpenSCAD2 design document, I proposed to introduce a new syntax for ranges and slices, which would not be confusing to either OpenSCAD or Python programmers.
The original OpenSCAD2 proposal was based on Haskell syntax, but it had some limitations, so what I actually ended up implementing in Curv is:
start .. end
start .. end by step
for a range, and
a[start .. end]
a[start .. end by step]
for a slice. I also adopted the Swift notation for half-open ranges:
start ..< end
start ..< end by step
The word 'by' is a keyword in Curv. This syntax has no visual ambiguity about which field is the 'step' value. The '..' operator is found in many programming languages, and it means a closed range, not a half-open range. So this syntax has no ambiguity about closed vs half-open.
There is a design flaw in OpenSCAD range syntax. [0:len(a)-1] is a common idiom for a range containing all of the array indexes of 'a'. However, if 'a' has zero length, then instead of the empty range, you get [0:-1], which is a two element range equivalent to [-1,0]. I think this is a bug that should be fixed, but instead of fixing the bug, this behaviour has been deprecated for many years. It looks to me that the bug will not be fixed, for backward compatibility reasons. If that's the case, then introducing a new range syntax is the only way to get a version of ranges in which this bug is fixed. That was another reason why OpenSCAD2 originally proposed to introduce the '..' range syntax.
Doug Moen
TP
Torsten Paul
Sat, Nov 9, 2019 11:32 AM
On 08.11.19 18:45, Doug Moen wrote:
On Fri, Nov 8, 2019, at 4:43 AM, gasstationwithoutpumps wrote:
Putting in something that looks like the Python slice but has
a subtly different semantics is probably a bad idea.
I don't. It's a very sensible thing to look at what other
languages do and learn from them. But not evolving OpenSCAD
because some other language is different would mean there's
nothing to change anymore, ever.
As already highlighted by Doug, OpenSCAD historically has
a different definition of ranges compared to python. That's
a fact that can't be changed.
So we can't just use the python slicing because we don't
really want that inconsistent behavior inside the OpenSCAD
language itself.
I'm not convinced that introducing a second range notation
is really the best way to go. If we we decide to do so, we
might want to support it for both ranges and slices anyway
so that decision can be left for later.
Just to point that out again. Slices and Ranges only look
the same. They do NOT behave the same!
a = [0, 1, 2, 3, 4];
a[2:1:-2] is a slice that returns the elements 2,3
The range [2:1:-2] is always an empty range
I'll probably drop the half-open definition for now as there
seems to be no good idea yet how to handle it. I do like the
[3:<5] specification, but the discussion on IRC pointed to
an issue that comes up with ranges going backward. If step
is negative, the '<' is at least slightly strange [-5:-1:<-3].
There was the suggestion to use [-5:-1:!-3] to mean "not the
end value" but I'm not sure yet we can actually parse that.
So maybe it's better to just decouple both topics.
On 04.11.19 19:12, Jordan Brown wrote:
BTW, would [>2:5] yield 3,4,5?
Would these < and > modifiers work on ranges too?
No, so far I have never seen the need to have ranges open
at the beginning. The half-open declaration should work for
both slices and ranges, if we find a way how to express that.
On 05.11.19 22:37, Parkinbot wrote:
echo(skip_last = a[:$end-1]);
// ECHO: skip_last = [0, 1, 2, 3, 4, 5, 6, 7, 8]
I'm not sure that's better. If the argument is that ranges
and slices are different, that does not change with using
$end.
It does have the benefit of being more verbose and explicit
but $end does not have any meaning for ranges. So we are
back to having different behavior. The only way to have
same behavior always would be to drop the "count from end"
notation completely. But I think this is useful enough to
be added, even if it makes ranges and slices different.
ciao,
Torsten.
On 08.11.19 18:45, Doug Moen wrote:
> On Fri, Nov 8, 2019, at 4:43 AM, gasstationwithoutpumps wrote:
>> Putting in something that looks like the Python slice but has
>> a subtly different semantics is probably a bad idea.
>
> I agree with this.
I don't. It's a very sensible thing to look at what other
languages do and learn from them. But not evolving OpenSCAD
because some other language is different would mean there's
nothing to change anymore, ever.
As already highlighted by Doug, OpenSCAD historically has
a different definition of ranges compared to python. That's
a fact that can't be changed.
So we can't just use the python slicing because we don't
really want that inconsistent behavior *inside* the OpenSCAD
language itself.
I'm not convinced that introducing a second range notation
is really the best way to go. If we we decide to do so, we
might want to support it for both ranges and slices anyway
so that decision can be left for later.
Just to point that out again. Slices and Ranges only look
the same. They do *NOT* behave the same!
a = [0, 1, 2, 3, 4];
a[2:1:-2] is a slice that returns the elements 2,3
The range [2:1:-2] is always an empty range
I'll probably drop the half-open definition for now as there
seems to be no good idea yet how to handle it. I do like the
[3:<5] specification, but the discussion on IRC pointed to
an issue that comes up with ranges going backward. If step
is negative, the '<' is at least slightly strange [-5:-1:<-3].
There was the suggestion to use [-5:-1:!-3] to mean "not the
end value" but I'm not sure yet we can actually parse that.
So maybe it's better to just decouple both topics.
On 04.11.19 19:12, Jordan Brown wrote:
> BTW, would [>2:5] yield 3,4,5?
> Would these < and > modifiers work on ranges too?
No, so far I have never seen the need to have ranges open
at the beginning. The half-open declaration should work for
both slices and ranges, if we find a way how to express that.
On 05.11.19 22:37, Parkinbot wrote:
> echo(skip_last = a[:$end-1]);
> // ECHO: skip_last = [0, 1, 2, 3, 4, 5, 6, 7, 8]
I'm not sure that's better. If the argument is that ranges
and slices are different, that does not change with using
$end.
It does have the benefit of being more verbose and explicit
but $end does not have any meaning for ranges. So we are
back to having different behavior. The only way to have
same behavior always would be to drop the "count from end"
notation completely. But I think this is useful enough to
be added, even if it makes ranges and slices different.
ciao,
Torsten.
R
Robin2
Sat, Nov 9, 2019 5:13 PM
would mean there's
nothing to change anymore, ever.
tp3 wrote
> would mean there's
> nothing to change anymore, ever.
Why would that be a bad thing?
...R
--
Sent from: http://forum.openscad.org/
TP
Torsten Paul
Sat, Nov 9, 2019 5:42 PM
On 09.11.19 18:13, Robin2 wrote:
would mean there's
nothing to change anymore, ever.
Why would that be a bad thing?
Because I believe that OpenSCAD can't stay alive in it's
current form if it does not improve. And I don't want to
see it dead.
ciao,
Torsten.
On 09.11.19 18:13, Robin2 wrote:
> tp3 wrote
>> would mean there's
>> nothing to change anymore, ever.
>
> Why would that be a bad thing?
Because I believe that OpenSCAD can't stay alive in it's
current form if it does not improve. And I don't want to
see it dead.
ciao,
Torsten.
R
Robin2
Sun, Nov 10, 2019 12:24 PM
Because I believe that OpenSCAD can't stay alive in it's
current form if it does not improve. And I don't want to
see it dead.
If by "dead" you mean "unused" then I agree with you.
However the question of "improve" must start from a list of "what's wrong" -
and the present code does all that I require.
...R
--
Sent from: http://forum.openscad.org/
tp3 wrote
> Because I believe that OpenSCAD can't stay alive in it's
> current form if it does not improve. And I don't want to
> see it dead.
If by "dead" you mean "unused" then I agree with you.
However the question of "improve" must start from a list of "what's wrong" -
and the present code does all that I require.
...R
--
Sent from: http://forum.openscad.org/