1. Argument for "foreach"

I know I have mentioned this before but I trully believe that a foreach
statement would benefit Euphoria greatly and I have proof this time! smile

Many, many times we Euphorians have to type:

object element
for i=1 to length(list) do
    element = list[i]
    -- Code goes here
end for


to loop through every element of a list or string to perform checking on it. In
doing this we need to declare an extra variable (element) for the data we wish to
check, in the loop create the looping variable, and assign the new indexed value
to the other variable (yes, we can do list[i] but it's inefficient and looks
horrid in nested loops ex. element[i][j][k]). Instead of this a foreach statement
would greatly simplify things. We could instead write:

foreach element in list do
    -- Code goes here
end for

That's 33 keystrokes (+2 for shifts on '(' and ')') less than before and the
scope is more explicit (element is only available for use in the loop). This may
not seem like a lot but if you write this code frequently it could make a big
difference.

For this element should be read-only just like variables used with for and
element should be an object. Ideally, the interpreter would optimize this to
simply iterate through every element of the sequence but it could be added
quickly as a syntactic substitute for what we do already. One issue would be how
to treat atoms when used as list; should it error or set element to that one
value?


I went through some of my programs and checked to see exactly how many of my for
loops would be replaced with foreach if it was added. Here's the results from the
programs I last worked on (taken from my ConTEXT history):

lispkit.ex - Simple LISP interpreter

FOREACH
3
FOR
1

rmcomments.ex - Removes comments from file

FOREACH
2
FOR
1

diceroller.ex - A dice program for my friend's RPG group

FOREACH
0
FOR
1

EuDoc.ex - The "driver" for EuDoc

FOREACH
3
FOR
0

EuDoc.e - The main data-mangling routines for EuDoc

FOREACH
9
FOR
1

(Note: EuDoc.e might be off. I think I accidently counted 1 or 2 loops that
modify "element" which foreach would not allow)
(Note: Two of the "for"s are technically inaccurate since they looped backwards
and foreach element in reverse(list) would have taken care of it in hindsight)

As you can see for big files like EuDoc.e that's 297 characters less that I
wouldn't have to type. I should also note that In the grand scheme of things it
might not seem like that much but one could make the same argument with list[$]
versus list[length(list)] (which was an excellent idea BTW).

Of course there are good reasons not to implement foreach such as it makes the
language more complex, people will forget that element is read-only, it's not
worth the extra statement, it's not really that much work now, etc.


The previous discussion on "foreach" is here:

http://www.listfilter.com/cgi-bin/esearch.exu?thread=1&fromMonth=6&fromYear=A&toMonth=8&toYear=A&keywords=%222.6+feature+request:+foreach%22


The Euphoria Standard Library project :
    http://esl.sourceforge.net/
The Euphoria Standard Library mailing list :
    https://lists.sourceforge.net/lists/listinfo/esl-discussion

new topic     » topic index » view message » categorize

2. Re: Argument for "foreach"

I was going to say that for a language that has a flexible sequence as its main
data type that foreach would make a lot of sense, but I already said it in the
thread that you posted. blink

You could always write a foreach routine that takes a routine ID:
procedure foreach(object list, integer rid)
    -- define your called procedure so that it takes an object and an index
    for i = 1 to length(list) do
        call_proc(rid, {list[i], i})
    end for
end procedure -- foreach

You could also define a function called map that does the same thing but calls a
function and returns a modified sequence instead:
function map(object list, integer rid)
    sequence out
    
    out = list -- allocate enough memory to start
    
    -- define your called function so that it takes an object and an index
    for i = 1 to length(list) do
        out[i] = call_func(rid, {list[i], i})
    end for

    return out
end function -- map

There are other sequence operations that I would like to see built in, like
sum(), but what can you do?

--
"Any programming problem can be solved by adding a level of indirection."
--anonymous
"Any performance problem can be solved by removing a level of indirection."
--M. Haertel
j.

new topic     » goto parent     » topic index » view message » categorize

3. Re: Argument for "foreach"

Jason Gade wrote:
> 
> I was going to say that for a language that has a flexible sequence as its
> main
> data type that foreach would make a lot of sense, but I already said it in the
> thread that you posted. blink
> 
> You could always write a foreach routine that takes a routine ID:
> }}}
<eucode>
> procedure foreach(object list, integer rid)
>     -- define your called procedure so that it takes an object and an index
>     for i = 1 to length(list) do
>         call_proc(rid, {list[i], i})
>     end for
> end procedure -- foreach
> </eucode>
{{{

> You could also define a function called map that does the same thing but calls
> a function and returns a modified sequence instead:
> }}}
<eucode>
> function map(object list, integer rid)
>     sequence out
>     
>     out = list -- allocate enough memory to start
>     
>     -- define your called function so that it takes an object and an index
>     for i = 1 to length(list) do
>         out[i] = call_func(rid, {list[i], i})
>     end for
> 
>     return out
> end function -- map
> </eucode>
{{{

> There are other sequence operations that I would like to see built in, like
> sum(), but what can you do?
> 

I've been trying to understand benefit of translating/compiling routines
into *.dll or *.so files. Wouldn't these types of routines benefit most
from being tanslated/compiled and wrapped? And once wrapped, could they
be called as easily as the euphoria source code above?
  I have been
studying the examples in Euphoria documentation and demo files - all
seems very obscure to me, hence I am eager to see Jeremy's wrapper hit
the contribution page.
 


Ken Rhodes
100% MicroSoft Free
SuSE Linux 10.0
No AddWare, SpyWare, or Viruses!
Life is Good  smile

new topic     » goto parent     » topic index » view message » categorize

4. Re: Argument for "foreach"

Kenneth Rhodes wrote:
> 
> Jason Gade wrote:
> > 
> > I was going to say that for a language that has a flexible sequence as its
> > main
> > data type that foreach would make a lot of sense, but I already said it in
> > the
> > thread that you posted. blink
> > 
> > You could always write a foreach routine that takes a routine ID:
> > }}}
<eucode>
> > procedure foreach(object list, integer rid)
> >     -- define your called procedure so that it takes an object and an index
> >     for i = 1 to length(list) do
> >         call_proc(rid, {list[i], i})
> >     end for
> > end procedure -- foreach
> > </eucode>
{{{

> > You could also define a function called map that does the same thing but
> > calls
> > a function and returns a modified sequence instead:
> > }}}
<eucode>
> > function map(object list, integer rid)
> >     sequence out
> >     
> >     out = list -- allocate enough memory to start
> >     
> >     -- define your called function so that it takes an object and an index
> >     for i = 1 to length(list) do
> >         out[i] = call_func(rid, {list[i], i})
> >     end for
> > 
> >     return out
> > end function -- map
> > </eucode>
{{{

> > There are other sequence operations that I would like to see built in, like
> > sum(), but what can you do?
> > 
> 
> I've been trying to understand benefit of translating/compiling routines
> into *.dll or *.so files. Wouldn't these types of routines benefit most
> from being tanslated/compiled and wrapped? And once wrapped, could they
> be called as easily as the euphoria source code above?
>   I have been
> studying the examples in Euphoria documentation and demo files - all
> seems very obscure to me, hence I am eager to see Jeremy's wrapper hit
> the contribution page.

I don't know as I've never done it. I don't think that it would gain you much
for such short routines as above. I imagine that routines with > 10-15 lines and
which are heavily used by your program would benefit the most.

Plus, like Rob replied to my optimization post, you would lose some
troubleshooting information from ex.err.

Remember to debug and profile before you try to optimize!

--
"Any programming problem can be solved by adding a level of indirection."
--anonymous
"Any performance problem can be solved by removing a level of indirection."
--M. Haertel
j.

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu