Re: Euphoria optimizations etc.

new topic     » goto parent     » topic index » view thread      » older message » newer message

>Somehow the readability starts to fall apart.
>In a long and complicated nested loop you'd
>have to keep in mind that certain variables
>were "special". I'd rather see s[i] in the code,
>and know what it means, than see x, and
>have to remember that x was connected to s in a magic way.
>Especially when x itself could be subscripted, and when
>in some cases we still need to explicitly subscript s
>inside the loop.

Yes, after seeing your example I must admit, it is *that* good for
readability.
However, it would allow for something that needs a pretty fancy trick
currently.

Take this for loop:

for i = 1 to lenght (s)
    item = s[i]
        -- Some proccesing
    s[1] = item
end for

Now, what would happen when we decide we want to cut element i out of s.
The lengt of s would change, and we would 1) skip an element 2) create a
run-time error indexing an element at the end that doesnt exist.

This brings me back to a suggestion (an idea stolen from the language ICON)
I made a while ago. The 'each' keyword, which means repeat this statement
for every element in the sequence that follows. Its one statement, like {1,
2, 3} + 1 where the interpreter is in full control over all the loops. This
allows a lot of optimization, not only less and thus more readable code.

Consider these examples:

Reversion:

d = "Each Example"
s = {}
s = prepend (s, each d)
s is now "elpmaxE hcaE"

Or, a positive routine:

d = { 34, 34, -45, 3, 0, 39, -100 }
if each d < 0 then each d = - each d end if
d is now { 34, 34, 45, 3, 0, 39, 100 }

As you see the loop-constructs are tied to the datatype rather than to a
condition.
What happens when we say something like this:

s = "Euphoria"
d = "ICON"
each s = each d
s is now "ICONoria"

So, the statement is executed as long as the arguments are available.
Now, consider the built-in routine find (), it only returns the first found
matching element.
So, here is the new find, that we can use:

global function find (object x, sequence s)
sequence result

    result = {}
    for index = 1 to length(s) do
        if not compare (x, s[index]) then
            result = append(result, index)
        end if
    end for

    return result
end function

However, notice that is finds *all* positions, eventhough we might not use
them all.
Consider this example that uses the new find routine.

-- Getting input
puts (1,"Please enter some text here..")
text = gets (1)

-- Proccesing input and displaying result
puts (1, "The founded positions (maximum 4): \n")
printf (1, "Space number %d was found at position %d \n", {each {1,2,3,4} ,
each find(' ',text) } )

Say, I entered "What's up doc?\n" as input.
It will display:

Space number 1 was found at position 7
Space number 2 was found at position 10

Say, I entered "E u p h o r i a\n" as input
It will display:

Space number 1 was found at position 2
Space number 2 was found at position 4
Space number 3 was found at position 6
Space number 4 was found at position 8

Why only the first four ?
Because each {1,2,3,4} can only *generate* the values {1,2,3,4} afterwhich
not all arguments are available and the interpreter continues with the next
statement.

Although we did not display the rest of the result, they were calculated.
Therefor the new generator syntax, look at the find function now:

global generator find (object x, sequence s)
    for index = 1 to length (s) do
        if not compare (s[index], x) then
            return index
        end if
    end for
end generator

Why is it called a generator ? Because it generates a result on request.
Only on request.

This was the line that called the generator find () :
printf (1, "Space number %d was found at position %d \n", {each {1,2,3,4} ,
each find(' ',text) } )

The line will be executed for the amount of spaces found in text or for the
maximum execution of 4.
This is due to " each {1,2,3,4}  "
The first time it executes, it calls the generator find (). It start at the
top, and initiates the for-loop in that generator. Now, the first space is
found, its returned. And the printf-statement will be executed for the first
time.
However, it will now try to execute again. The "  each {1,2,3,4}  " now
gives 2. But what does it do with the find-generator ? Will it call it again
? No, it will continue execution where it left off.

What happens, when there are only 3 spaces in the the 'text' ? The 4th time
the generator is called, it reaches the end of the generator and thus leaves
it without returning a value. The line is not executed any more.

Like find (), you could imagine an generator called 'for'

generator for (atom a, atom b, atom step)
    while a <= b do
        return a
        a = a + step
    end while
end generator

No more messing with exit, weird-loop constructs, jumping several levels,
etc.
'Each' generates as much results as it can, either out of a sequence, a
sequence result of a function or the produced values of a generator. Now
take a look at this statement:

print (1, for (0,6,2) )

Displays:
0246

printf (1, "%d\n", { for (0,6,2) } )

Displays:
0
2
4
6


Here the a problem exists. What is we want to execute multiple statements a
number of times, using the same mechanism. Indeed another loop-construct
using 'every':

every print (1, for (0,6,2) ) do
    puts (1, '\n' )
end every

And voila, this too diplays the following:
0
2
4
6

Considering this, you must have noticed, the find-generator could be done
much easier:

generator find (object x, sequence s)

    return for (1,lenght(s),1) when not compare (x, each s)

end generator

See, that I here introduced another keyword.
Its the keywords 'when' which is like an if-statement, however, there is
only one small difference.
Its only attached to one statement, is much smaller and, most important,
does evaluate all the arguments of the statement attached:

    if not compare (x, each s) then
        return for(1,length(s), 1)
    end if

Would only call the for-generator every time the two values matched.
The when operator, needs valid arguments of its attached statement, and then
decides wether or not the statement is executed.

And now, the keywords recurse, which is like each, however, it will return
all ATOMS rather than all elements.
If you dont grasp this at once, look at this example of 'each' fist:

s = { { 1, 2, 3 } , { 0, 0, 0 } , { 6, 7, 8 } }
every print (1, each s) do
    puts (1, '\n')
end every

Displays:
{ 1, 2, 3 }
{ 0, 0, 0 }
{ 6, 7, 8 }

every print (1, each  ( each s ) ) do
    puts (1, '\n')
end every

Displays:
1
2
3
0
0
0
6
7
8

every print (1, recurse s) do
    puts (1, '\n')
end every

Displays precizely the same.
An "  each ( each x ) " statement, generates results from generated result.
It gives the atom of an 2D Image for example.
An " each ( each ( each x ) ) " gives the atoms of an 3D Image.

However, there are situations where you want to have it recurse all the way,
no matter how many levels.
This is the default for most math operations in Euphoria for example.
Now look at this example:

recurse x = recurse x + 1

Because math operations can only be implied on atoms, this is the default
already.
If you find the above a bit misleading, consider that it doesnt *generates*
a value, it generates a *pointer* to that value.

But I'm still not done, another keyword: 'all'
It is like each, however it tries all variants.
Look at this statement:

text = "L O L"
printf (1, "%d found at %d" , { all {1,2,3,4} , each find (' ', text ) } )

Displays:
1 found at 2
1 found at 4
2 fount at 2
2 found at 4
3 found at 2
3 fount at 4
4 found at 2
4 found at 4

And I'll end this document with the new recursive reverse generator:

generator reverse (object x)
    if sequence (x) then
        return reverse ( x[ each for(length(x),1,-1) ] )
    else
        return x
    end if
end generator

I'll also promise this is the last time, I mentioned this.
I feel this mail is the first (and thus last) mail where I really was able
to explain which features of ICON I like, and what advantages they give us.

Sorry for the long mail,

Ralf

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu