doug-moen / openscad2

better abstraction mechanisms for OpenSCAD
Boost Software License 1.0
25 stars 3 forks source link

Slice Notation #15

Open Neon22 opened 9 years ago

Neon22 commented 9 years ago

I am suggesting you use the python slice syntax IMHO - this solution is more readable. Entirely subjective of course. E.g.

Additionally: seq[start : end : step] from start to end by step -ve values count from end. seq[-1] return last element in seq seq[-1:-8:2] return new list from last element to 8th-from-last by 2's seq[:-2] return all except last two elements of list

Neon22 commented 9 years ago

for the summing example: sum(v) = v==[] ? 0 : v[0] + sum(v[1..]); Proposed sum(v) = if (v) v[0]+sum(v[1:]) else 0;

In python they use reduce() or special functions to operate on lists for the common cases of sum(), count(), len(), min(), max(),...

Neon22 commented 9 years ago

This syntax reverses a list newlist = oldlist[::-1] I.e. [from the beginning : to the end : in reverse order]

doug-moen commented 9 years ago

After looking at your Range and Slice Notation issues together, I would conclude that you prefer the Python syntax simply because you are more used to Python than to OpenSCAD.

In OpenSCAD, [start:step:end] is a range. But you propose seq[start:end:step] for slice notation. This inconsistency is very confusing to an OpenSCAD programmer.

If we keep [start:step:end] as the primary syntax for ranges in OpenSCAD (and fix the bug with empty ranges), then it would make sense to use seq[start:end] and seq[start:step:end] for slices, because that would be consistent.

I argue that [start, start+k .. end] is a better syntax for ranges because it is much clearer what each of the arguments means. This syntax looks very much like the "set builder" notation taught in high school, so it is easily understood by someone with high school math, even if they lack Python experience. By contrast, the Python syntax of range(end), range(start,end), range(start,end,step) is less readable, precisely because there is no visible indication of what the three arguments mean. In range(x,y,z) it is completely arbitrary that 'z' is the step, while in [x,x+z..y] is it quite clear what the roles of x, y and z are without reading the documentation for the 'range' function.

Once you accept the [start..end] syntax for ranges, then seq[start..end] makes the most sense for slice notation, because it is consistent.

Neon22 commented 9 years ago

Firstly - I don't mean to be argumentative - just to present a hopefully reasoned case. I accept fully whatever decision you make.

  1. My knowledge of set builder notation is non-existent. I assume its an American high school teaching method. https://www.google.com/search?q=set+builder+notation&tbm=isch&tbo=u&source=univ&sa=X&ei=PpyZVcygHcHHmwXM0YLIBw&ved=0CDcQsAQ&biw=1428&bih=928
  2. Yes I prefer python syntax but only because it has already determined this is a good seq because it solves several problems neatly and consistently. E.g. list reversal. The specific ordering of start, end, step is well reasoned for languages with optional keyword based arguments. Step is seldom used (so its third). Having step in slice as well as in range - and making them the same order for both - seems like a good idea.

Decision is yours.

doug-moen commented 9 years ago

Reader beware, I went crazy and did an exhaustive survey of range/slice syntaxes.

Set notation is not specifically an American thing. I'm not American anyway. Set theory is the foundation of all other mathematics, so sets are frequently mentioned in math textbooks, technical math papers, and so on. The standard notation for specifying the members of a set is to use curly braces: {...}, with various notations inside the curly braces. I don't think I've ever seen an alternative to this notation, and I've been reading math books all my life. It turns out that Americans use the term "roster notation" for what I have been (perhaps incorrectly) calling set-builder notation. So {1,2,3} is a set containing just the 3 elements, while {1,2,3,...} is the infinite set of integers beginning with 1, {...,-3,-2,-1} are the negative integers, and {1,2,3,...,100} is the integers from 1 to 100.

Since OpenSCAD deals with trigonometry and affine transformations, I figure that anybody who knows this stuff will have encountered set notation, and will likely be familiar with it. I figure that more potential OpenSCAD users would have exposure to standard mathematical set notation than to $my_favourite_programming_language. Of course, maybe I have more than average math exposure and this is biasing me.

Lots of programming languages use start..end for range notation, and it's just an abbreviated form of "roster notation". For example, Perl, Ruby, Haskell, F#, Rust. Haskell uses [2,4..10] for a range with step != 1, so I am borrowing more specifically from Haskell, which is one of the most well known functional languages. Perl 6 uses 2,4...10 to specify a step, which is an upgrade from Perl 5.

Python and PHP use range(start,end,step); there may be other languages like this.

Scala supports [2 to 10 by 2], and many languages support variants on this syntax.

The OpenSCAD notation [2:2:10] seems to be shared by only MATLab and Octave (a MATlab clone).

As for slice notation, a[i:j] seems to be the most common syntax, it goes back to Algol 68. Perl, Ruby, Rust and perhaps some other languages use a[i..j]. Algol 68 actually supported both a[i:j] and a[i..j]. Javascript and probably others have a.slice(start,end).

Python/PHP range notation 'range(start,end,step)' is too confusing as an alternative to [start:step:end]' because the arguments are in a different order. Using range(start,step,end) is confusing to Python/PHP people.

Using a[start:end] for slice notation seems okay, but if you also support a step, then you create confusion, because a[start:step:end] makes sense for OpenSCAD/MATlab, but is confusing for Python users, where a[start:end:step] is used.

I still really like the Ruby/Perl approach of using the same syntax (inspired by "roster" set notation) for both ranges and slices. I still believe that the math community is one of the groups that OpenSCAD should be serving. So [i..j] and a[i..j] is still my preference.

wolf105 commented 8 years ago

I can only agree with Doug-Moen. For me, the best notation is the one that is easiest to read and to learn for a novice, not the easiest and laziest one to write. Notation of the type [i..j] and [from,step,end] fits that bill. To learn to program in OpenSCAD took me only a few hours, but to understand constructs like c= a==b ? 4 : 5; took ages. That isn't easy to learn, in particular since it is just an if .. then .. else construct to be used when conditionally assigning numbers, whereas the if .. else construct assigns shapes. . . silly to make the distinction, just as silly as is distinguishing between functional and imperative language. Nesting above conditional I can construct an if .. then .. else list with as many choices as I like, but debugging it would be a nightmare. That is where OpenSCAD2 comes in! I just can't wait . . .