Proposal for range ( [i:j:k] ) improvement

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

Proposal for range ( [i:j:k] ) improvement

runsun
Current range syntax:

    [ i: j ]
    [ i: j: k ]
Proposed additional syntax:

    a) [ :j ] ---- i can be skipped if i==0

    b) [ i: array ]  ---- j can be an array or string . For example:
       
        arr = ["a","b","c","d"];
        [ for ( i=[ :arr ] ) i ]; ==> [0,1,2,3]
        [ for ( i=[ :2:arr ] ) i ]; ==> [0,2]    

    c)  ^ array  (or some other syntax like [arr;] [ %arr ] etc ... )
        to give both index and item:

        [ for ( i,x = ^arr ) str( i,"=",x) ] ==> [ "0=a", "1=b", "2=c" ]
Compare the proposed

   for ( i=[:a] )

to the current usage

   for ( i=[0:len(a)-1] )

it is much quicker and easier to write and read.


 
$ Runsun Pan, PhD
$ libs: scadx, doctest, faces(git), offline doc(git), runscad.py(2,git), editor of choice: CudaText ( OpenSCAD lexer); $ Tips; $ Snippets
Reply | Threaded
Open this post in threaded view
|

Re: Proposal for range ( [i:j:k] ) improvement

QuackingPlums
Sounds like we could do with a foreach statement:

foreach (i in array)
   doSomething();
Reply | Threaded
Open this post in threaded view
|

Re: Proposal for range ( [i:j:k] ) improvement

Chow Loong Jin
On Thu, Jul 16, 2015 at 12:35:04AM -0700, QuackingPlums wrote:
> Sounds like we could do with a foreach statement:
>
> *foreach* (i *in* array)
>    doSomething();

We already have such a thing:

for (v = array)
    doSomething ();

You can't use this when you actually need the array index though.

--
Kind regards,
Loong Jin

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

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Proposal for range ( [i:j:k] ) improvement

QuackingPlums
Chow Loong Jin wrote
We already have such a thing:

for (v = array)
    doSomething ();
I did not know that! How long has this form been supported?

Chow Loong Jin wrote
You can't use this when you actually need the array index though.
True. I can't resist the temptation to slip into programming good practice at this point, despite (I know, I know!) the fact that OpenSCAD isn't a programming language.
Reply | Threaded
Open this post in threaded view
|

Re: Proposal for range ( [i:j:k] ) improvement

Chow Loong Jin
On Thu, Jul 16, 2015 at 01:25:48AM -0700, QuackingPlums wrote:
> Chow Loong Jin wrote
> > We already have such a thing:
> >
> > for (v = array)
> >     doSomething ();
>
> I did not know that! How long has this form been supported?

I dunno, I first started using OpenSCAD with 2014.04, and it already had that
feature.

> Chow Loong Jin wrote
> > You can't use this when you actually need the array index though.
>
> True. I can't resist the temptation to slip into programming good practice
> at this point, despite (I know, I know!) the fact that OpenSCAD isn't a
> programming language.

Well, there are still some good practices to follow, such as not hardcoding
precalculated values everywhere.

--
Kind regards,
Loong Jin

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

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Proposal for range ( [i:j:k] ) improvement

Neon22
we can get both:

a = ["a","b","c","d"];
for (i=a)
    echo(i);
for (i=[0:len(a)-1])
    echo(i, a[i]);

ECHO: "a"
ECHO: "b"
ECHO: "c"
ECHO: "d"
ECHO: 0, "a"
ECHO: 1, "b"
ECHO: 2, "c"
ECHO: 3, "d"
Going back to @runsun proposal:
Current range syntax:

        [ i: j ]
        [ i: j: k ]

Proposed additional syntax:

        a) [ :j ] ---- i can be skipped if i==0

        b) [ i: array ]  ---- j can be an array or string . For example:
           
            arr = ["a","b","c","d"];
            [ for ( i=[ :arr ] ) i ]; ==> [0,1,2,3]
            [ for ( i=[ :2:arr ] ) i ]; ==> [0,2]    

        c)  ^ array  (or some other syntax like [arr;] [ %arr ] etc ... )
            to give both index and item:

            [ for ( i,x = ^arr ) str( i,"=",x) ] ==> [ "0=a", "1=b", "2=c" ]
    ... [show rest of quote]

Proposed to return just the array indices. Not the values.
   
for ( i=[:a] )
current:
   
for ( i=[0:len(a)-1] )

Proposed to return two values index and value. (i=index, x=value).
   
for ( i,x = ^arr ) 
current (where the value is a new variable in this scope and not  reused).
   
for ( i=[0:len(a)-1]) {
             value = arr[i];
             }

I note that in Python there is a special function "enumerate" that returns a tuple of (index, value). Of course this works in Python because tuples are consts of arrays and can be accessed in a loop like this:
for (i,x) in enumerate(arr):
   ...
which visually indicates that the enumerate will return two values and how they will be mapped to i and x.
Personally I find Python's slicing, range, tuple, array, dictionary design to be very clean, clear and well designed.

For OpenSCAD I liekd someone's proposal to use "in" to explicitly indicate that the argument was an array.
E.g.
 for (i in arr)  vs for (i=arr)
Maybe this variant coudl be used to differntiate between indices or values from the array ?
Reply | Threaded
Open this post in threaded view
|

Re: Proposal for range ( [i:j:k] ) improvement

runsun
Neon22 wrote
I note that in Python there is a special function "enumerate" that returns a tuple of (index, value). Of course this works in Python because tuples are consts of arrays and can be accessed in a loop like this:
for (i,x) in enumerate(arr):
   ...
which visually indicates that the enumerate will return two values and how they will be mapped to i and x.
Personally I find Python's slicing, range, tuple, array, dictionary design to be very clean, clear and well designed.
Part of my idea is indeed inspired by Python. Another slicing feature of python that I like is the reversed indexing:

   a=['a','b','c']
   a[-1] ===> 'c'
   a[:-1] ===> ['a','b']
   a[-2:] ===> ['b','c']

IMHO It's one of the features that earn Python the reputation of "elegant". It'd certainly be nice if we can adopt this, too.

For OpenSCAD I liekd someone's proposal to use "in" to explicitly indicate that the argument was an array.
E.g.
 for (i in arr)  vs for (i=arr)
Maybe this variant coudl be used to differntiate between indices or values from the array ?
Wouldn't it be a little confusing, 'cos the index doesn't actually "in" the arr ?
$ Runsun Pan, PhD
$ libs: scadx, doctest, faces(git), offline doc(git), runscad.py(2,git), editor of choice: CudaText ( OpenSCAD lexer); $ Tips; $ Snippets
Reply | Threaded
Open this post in threaded view
|

Re: Proposal for range ( [i:j:k] ) improvement

MichaelAtOz
Administrator
In reply to this post by runsun
<quote author="runsun">

Proposed additional syntax:

    a) [ :j ] ---- i can be skipped if i==0
Just lazy. ;)

Compare the proposed

   for ( i=[:a] )

to the current usage

   for ( i=[0:len(a)-1] )

it is much quicker and easier to write and read.
I don't mind that, where you still use 0:, so where 'a' is a string or vector, its len()-1 is used.

   for (i=[0:vector]) ...
Admin - email* me if you need anything,
or if I've done something stupid...
* click on my MichaelAtOz label, there is a link to email me.

Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work.
Obviously inclusion of works of previous authors is not included in the above.


The TPP is no simple “trade agreement.” Fight it! http://www.ourfairdeal.org/ time is running out!
Reply | Threaded
Open this post in threaded view
|

Re: Proposal for range ( [i:j:k] ) improvement

doug.moen
In reply to this post by runsun
Runsun said:
Compare the proposed

   *for ( i=[:a] ) *

to the current usage

   *for ( i=[0:len(a)-1] )*

it is much quicker and easier to write and read.

I don't mind if an operation for returning the indices of an array is added to OpenSCAD.
However, the syntax [:a] is pretty inscrutable, and I'm bit disturbed that the array a is used in an integer context and interpreted as meaning 'len(a)-1'. That's weird.

How about an ordinary function instead?
In Perl, this is 'keys(a)'.
I can't remember seeing this operation in other languages.
However, 'indices(a)' or 'indexes(a)' would also make sense.

   for( i = indices(a) ) ...

Runsun also said:
>         [ for ( i,x = ^arr ) str( i,"=",x) ] ==> [ "0=a", "1=b", "2=c" ]

I'm not seeing the value of this. I think it's clearer to write
    [ for ( i = arr ) str( i,"=",arr[i]) ]

In the case where 'arr' is a really long expression, you can do this:
    [ let(a=arr) for(i=a) str(i,"=",a[i]) ]

Doug.

On 16 July 2015 at 03:13, runsun <[hidden email]> wrote:
Current range syntax:


>     [ i: j ]
>     [ i: j: k ]

Proposed additional syntax:


>     a) [ :j ] ---- i can be skipped if i==0
>
>     b) [ i: array ]  ---- j can be an array or string . For example:
>
>         arr = ["a","b","c","d"];
>         [ for ( i=
*
> [ :arr ]
*
>  ) i ]; ==> [0,1,2,3]
>         [ for ( i=
*
> [ :2:arr ]
*
>  ) i ]; ==> [0,2]
>
>     c)  ^ array  (or some other syntax like [arr;] [ %arr ] etc ... )
>         to give both index and item:
>
>         [ for
*
> ( i,x = ^arr )
*
>  str( i,"=",x) ] ==> [ "0=a", "1=b", "2=c" ]

Compare the proposed

   *for ( i=[:a] ) *

to the current usage

   *for ( i=[0:len(a)-1] )*

it is much quicker and easier to write and read.






-----

$  Runsun Pan, PhD

$ -- OpenScad_DocTest ( Thingiverse ), faces , Offliner

$ -- hash parameter model: here , here

$ -- Linux Mint 17.1 Rebecca x64  + OpenSCAD 2015.03.15/2015.04.01.nightly




--
View this message in context: http://forum.openscad.org/Proposal-for-range-i-j-k-improvement-tp13184.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.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: Proposal for range ( [i:j:k] ) improvement

runsun
doug.moen wrote
How about an ordinary function instead?
In Perl, this is 'keys(a)'.
I can't remember seeing this operation in other languages.
However, 'indices(a)' or 'indexes(a)' would also make sense.

   for( i = indices(a) ) ...
In fact, since we don't have this [:arr] yet, a function is exactly what
I do in my own lib. Here is the test output of my range(...) function:

range ( i,j,k,cycle,returnitems )=array ( tested:54 ) (mode:12)
| // 1 arg: starting from 0
|
| 0> range(5)= [0, 1, 2, 3, 4]
| 1> range(-5)= [0, -1, -2, -3, -4]
| 2> range(0)= []
| 3> range([])= []
|
| // 2 args:
|
| 4> range(2,5)= [2, 3, 4]
| 5> range(5,2)= [5, 4, 3]
| 6> range(-2,1)= [-2, -1, 0]
| 7> range(-5,-1)= [-5, -4, -3, -2]
|
| // Note these are the same:
|
| 8> range(3)= [0, 1, 2]
| 9> range(0,3)= [0, 1, 2]
| 10> range(-3)= [0, -1, -2]
| 11> range(0,-3)= [0, -1, -2]
| 12> range(1)= [0]
| 13> range(-1)= [0]
|
| // 3 args, the middle one is interval. Its sign has no effect
|
| 14> range(2,0.5,5)= [2, 2.5, 3, 3.5, 4, 4.5]
| 15> range(2,-0.5,5)= [2, 2.5, 3, 3.5, 4, 4.5]
| 16> range(5,-1,0)= [5, 4, 3, 2, 1]
| 17> range(5,1,2)= [5, 4, 3]
| 18> range(8,2,0)= [8, 6, 4, 2]
| 19> range(0,2,8)= [0, 2, 4, 6]
| 20> range(0,3,8)= [0, 3, 6]
|
| // Extreme cases:
|
| 21> range()= [] // Give nothing, get nothing
| 22> range(0)= [] // Count from 0 to 0 gets you nothing
| 23> range(2,2)= [] // 2 to 2 gets you nothing, either
| 24> range(2,0,4)= [] // No intv gets you nothing, too
| 25> range(0,1)= [0]
| 26> range(0,1,1)= [0]
| // When interval > range, count only the first:
| 27> range(2,5,4)= [2]
| 28> range(2,5,-1)= [2]
| 29> range(-2,5,-4)= [-2]
| 30> range(-2,5,1)= [-2]
|
|  range( obj )
|
| // range( arr ) or range( str ) to return a range of an array
| // so you don"t have to do : range( len(arr) )
|
| > obj = [10, 11, 12, 13]
|
| 31> range(obj)= [0, 1, 2, 3]
| 32> range([3,4,5])= [0, 1, 2]
| 33> range("345")= [0, 1, 2]
| 34> range([])= []
| 35> range(")= []
|
|  range( ... cycle= i,-i,true...)
|
| // New 2014.9.7:
| // cycle= +i: extend the index on the right by +i count
| // cycle= -i: extend the index on the right by -i count
| // cycle= true: same as cycle=1
|
| 36> range(4,cycle=1)= [0, 1, 2, 3, 0] // Add first to the right
| 37> range(4,cycle=-1)= [3, 0, 1, 2, 3] // Add last to the left
| 38> range(4,cycle=true)= [0, 1, 2, 3, 0] // true=1
|
| 39> range(2,5,cycle=1)= [2, 3, 4, 2] // Add first to the right
| 40> range(2,5,cycle=2)= [2, 3, 4, 2, 3] // Add 1st,2nd to the right
| 41> range(2,5,cycle=-1)= [4, 2, 3, 4] // Add last to the left
| 42> range(2,5,cycle=-2)= [3, 4, 2, 3, 4]
| 43> range(2,5,cycle=true)= [2, 3, 4, 2] // true=1
|
| 44> range(2,1.5,8,cycle=2)= [2, 3.5, 5, 6.5, 2, 3.5]
| 45> range(2,1.5,8,cycle=-2)= [5, 6.5, 2, 3.5, 5, 6.5]
| 46> range(2,1.5,8,cycle=true)= [2, 3.5, 5, 6.5, 2]
|
|  range(obj,cycle=i,-1,[-1,1],true...)
|
| > obj = [10, 11, 12, 13]
| 47> range(obj,cycle=1)= [0, 1, 2, 3, 0]
| 48> range(obj,cycle=[-1,1])= [3, 0, 1, 2, 3, 0]
| 49> range(obj,cycle=2)= [0, 1, 2, 3, 0, 1]
| 50> range(obj,cycle=-1)= [3, 0, 1, 2, 3]
| 51> range(obj,cycle=-2)= [2, 3, 0, 1, 2, 3]
|
|  range( obj, returnitems=true,false )
|
| // When using obj, can set returnitems=true to return items.
|
| 52> range([3,4,5],returnitems=true)= [3, 4, 5]
| 53> range(obj,cycle=[-1,1],returnitems=true)= [13, 10, 11, 12, 13, 10]
$ Runsun Pan, PhD
$ libs: scadx, doctest, faces(git), offline doc(git), runscad.py(2,git), editor of choice: CudaText ( OpenSCAD lexer); $ Tips; $ Snippets
Reply | Threaded
Open this post in threaded view
|

Re: Proposal for range ( [i:j:k] ) improvement

G. Wade Johnson
On Fri, 17 Jul 2015 11:24:48 -0700 (MST)
runsun <[hidden email]> wrote:

> doug.moen wrote
> > How about an ordinary function instead?
> > In Perl, this is 'keys(a)'.
> > I can't remember seeing this operation in other languages.
> > However, 'indices(a)' or 'indexes(a)' would also make sense.
> >
> >    for( i = indices(a) ) ...
>
> In fact, since we don't have this [:arr] yet, a function is exactly
> what I do in my own lib. Here is the test output of my *range(...)*
> function:

I like range(arr) better than [:arr].

> > range ( i,j,k,cycle,returnitems )=array ( tested:54 ) (mode:12)
> > | // 1 arg: starting from 0
> > |
> > | 0> range(5)= [0, 1, 2, 3, 4]
> > | 1> range(-5)= [0, -1, -2, -3, -4]
> > | 2> range(0)= []
> > | 3> range([])= []
> > |
> > | // 2 args:
> > |
> > | 4> range(2,5)= [2, 3, 4]
> > | 5> range(5,2)= [5, 4, 3]
> > | 6> range(-2,1)= [-2, -1, 0]
> > | 7> range(-5,-1)= [-5, -4, -3, -2]
> > |
> > | // Note these are the same:
> > |
> > | 8> range(3)= [0, 1, 2]
> > | 9> range(0,3)= [0, 1, 2]
> > | 10> range(-3)= [0, -1, -2]
> > | 11> range(0,-3)= [0, -1, -2]
> > | 12> range(1)= [0]
> > | 13> range(-1)= [0]
> > |
> > | // 3 args, the middle one is interval. Its sign has no effect
> > |
> > | 14> range(2,0.5,5)= [2, 2.5, 3, 3.5, 4, 4.5]
> > | 15> range(2,-0.5,5)= [2, 2.5, 3, 3.5, 4, 4.5]
> > | 16> range(5,-1,0)= [5, 4, 3, 2, 1]
> > | 17> range(5,1,2)= [5, 4, 3]
> > | 18> range(8,2,0)= [8, 6, 4, 2]
> > | 19> range(0,2,8)= [0, 2, 4, 6]
> > | 20> range(0,3,8)= [0, 3, 6]
> > |
> > | // Extreme cases:
> > |
> > | 21> range()= [] // Give nothing, get nothing
> > | 22> range(0)= [] // Count from 0 to 0 gets you nothing
> > | 23> range(2,2)= [] // 2 to 2 gets you nothing, either
> > | 24> range(2,0,4)= [] // No intv gets you nothing, too
> > | 25> range(0,1)= [0]
> > | 26> range(0,1,1)= [0]
> > | // When interval > range, count only the first:
> > | 27> range(2,5,4)= [2]
> > | 28> range(2,5,-1)= [2]
> > | 29> range(-2,5,-4)= [-2]
> > | 30> range(-2,5,1)= [-2]
> > |
> > |  range( obj )
> > |
> > | // range( arr ) or range( str ) to return a range of an array
> > | // so you don"t have to do : range( len(arr) )
> > |
> > | > obj = [10, 11, 12, 13]
> > |
> > | 31> range(obj)= [0, 1, 2, 3]
> > | 32> range([3,4,5])= [0, 1, 2]
> > | 33> range("345")= [0, 1, 2]
> > | 34> range([])= []
> > | 35> range(")= []
> > |
> > |  range( ... cycle= i,-i,true...)
> > |
> > | // New 2014.9.7:
> > | // cycle= +i: extend the index on the right by +i count
> > | // cycle= -i: extend the index on the right by -i count
> > | // cycle= true: same as cycle=1
> > |
> > | 36> range(4,cycle=1)= [0, 1, 2, 3, 0] // Add first to the right
> > | 37> range(4,cycle=-1)= [3, 0, 1, 2, 3] // Add last to the left
> > | 38> range(4,cycle=true)= [0, 1, 2, 3, 0] // true=1
> > |
> > | 39> range(2,5,cycle=1)= [2, 3, 4, 2] // Add first to the right
> > | 40> range(2,5,cycle=2)= [2, 3, 4, 2, 3] // Add 1st,2nd to the
> > right | 41> range(2,5,cycle=-1)= [4, 2, 3, 4] // Add last to the
> > left | 42> range(2,5,cycle=-2)= [3, 4, 2, 3, 4]
> > | 43> range(2,5,cycle=true)= [2, 3, 4, 2] // true=1
> > |
> > | 44> range(2,1.5,8,cycle=2)= [2, 3.5, 5, 6.5, 2, 3.5]
> > | 45> range(2,1.5,8,cycle=-2)= [5, 6.5, 2, 3.5, 5, 6.5]
> > | 46> range(2,1.5,8,cycle=true)= [2, 3.5, 5, 6.5, 2]
> > |
> > |  range(obj,cycle=i,-1,[-1,1],true...)
> > |
> > | > obj = [10, 11, 12, 13]
> > | 47> range(obj,cycle=1)= [0, 1, 2, 3, 0]
> > | 48> range(obj,cycle=[-1,1])= [3, 0, 1, 2, 3, 0]
> > | 49> range(obj,cycle=2)= [0, 1, 2, 3, 0, 1]
> > | 50> range(obj,cycle=-1)= [3, 0, 1, 2, 3]
> > | 51> range(obj,cycle=-2)= [2, 3, 0, 1, 2, 3]
> > |
> > |  range( obj, returnitems=true,false )
> > |
> > | // When using obj, can set returnitems=true to return items.
> > |
> > | 52> range([3,4,5],returnitems=true)= [3, 4, 5]
> > | 53> range(obj,cycle=[-1,1],returnitems=true)= [13, 10, 11, 12,
> > 13, 10]
>
>
>
>
>
> -----
>
> $  Runsun Pan, PhD
>
> $ -- OpenScad_DocTest ( Thingiverse ), faces , Offliner
>
> $ -- hash parameter model: here , here
>
> $ -- Linux Mint 17.1 Rebecca x64  + OpenSCAD
> 2015.03.15/2015.04.01.nightly
>
>
>
>
> --
> View this message in context:
> http://forum.openscad.org/Proposal-for-range-i-j-k-improvement-tp13184p13212.html
> Sent from the OpenSCAD mailing list archive at Nabble.com.
>
> _______________________________________________
> OpenSCAD mailing list
> [hidden email]
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


--
Do unto others 20% better than you would expect them to do unto you, to
correct for subjective error.                      -- Linus Pauling

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

Re: Proposal for range ( [i:j:k] ) improvement

Neon22
in python you can access a dictionaries items, values, and keys like so:
arr = {1: 11, 2:22, 3:33}
arr.items()   returns   [(1, 11), (2, 22), (3, 33)]
arr.values() returns    [11, 22, 33]
arr.keys()    returns   [1, 2, 3]