RFC: Array/String slicing and half open ranges.

classic Classic list List threaded Threaded
9 messages Options
tp3
Reply | Threaded
Open this post in threaded view
|

RFC: Array/String slicing and half open ranges.

tp3
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.


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
-- Torsten
tp3
Reply | Threaded
Open this post in threaded view
|

Re: RFC: Array/String slicing and half open ranges.

tp3
On 02.11.19 18:13, Jordan Brown wrote:
> Why not only closed intervals?  For integer indices, it
> seems like the only difference between closed and open
> is adding a +1 to the start or -1 to the end. Or are you
> concerned that if end is zero and they want open on the
> right, they'd end up with -1 and trigger the "measure
> from the end" case?

Both actually.

Specifically for the (deprecated) range behavior which
swaps values if the second one is less than the first
value.

v = [];
for (i = [0:len(v) - 1]) {
    echo(i = i);
}
// DEPRECATED: Using ranges of the form [begin:end] with begin value greater than the end value is deprecated.
// ECHO: i = -1
// ECHO: i = 0

You already can get around that using [0:1:len(v) - 1]
though. But [0:<len(v)] does not seem too bad either.

Otherwise it's pretty much simple syntactic sugar, so
it's not super critical to have it. After playing a bit
with this way to specify the range end, I start to like
it. It does give a nice way of reading ranges/slices.

[2:<5] start at index 2 and stop at index less than 5

> Maybe always closed on the left and always open on
> the right, so if you want different you'd +1 on one
> end or the other?

I don't think there's a way to do that without breaking
existing code.

> Adding new syntax is ugly...

Why? We should probably try to not add too ugly stuff,
but I don't think it's wrong to add things at all. I'd
like OpenSCAD to stay very simple to get started, just
as it is now. But it needs quite some more features to
really grow up. I suspect not everyone will need those
features but we want to give it into the hands of people
who can build libraries.

ciao,
  Torsten.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
-- Torsten
Reply | Threaded
Open this post in threaded view
|

Re: RFC: Array/String slicing and half open ranges.

Parkinbot
In reply to this post by tp3
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/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: RFC: Array/String slicing and half open ranges.

gasstationwithoutpumps
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/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: RFC: Array/String slicing and half open ranges.

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

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
tp3
Reply | Threaded
Open this post in threaded view
|

Re: RFC: Array/String slicing and half open ranges.

tp3
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.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
-- Torsten
Reply | Threaded
Open this post in threaded view
|

Re: RFC: Array/String slicing and half open ranges.

Robin2
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/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
tp3
Reply | Threaded
Open this post in threaded view
|

Re: RFC: Array/String slicing and half open ranges.

tp3
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.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
-- Torsten
Reply | Threaded
Open this post in threaded view
|

Re: RFC: Array/String slicing and half open ranges.

Robin2
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/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org