Last call for new features

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

This is my last attempt to convience Robert and the rest of the Euphorians,
we need some new features, will any big program be ever _easily_ possible
with Euphoria.

The order is not of importance, rather of implementation: (though I did
number them from 1 to 10)

1) Direct initialization. Simple:

    integer x = 5, y = 6

2) Arrays. Why? We have sequences. Yes, I know, but sometimes I want to be
able to have a sequence of fixed-length.

    type char (integer x)
        return x >= 0 and x <= 255
    end type

    char text[20] -- Allocate room for 20 characters

  Speed benefits: graphics in native Euphoria will now match up with things
like mem_copy () and mem_set (). The dynamic allocation and deallocation is
great, but when I dont need then, they slow everything down with every
slice. Example:

   image[y][x]

    First it checks the boundries for y, then it looks up the pointer it
points to. Then it checks the boundries for x, then it looks up the value
that points to. That value is returned.

    Now the same with arrays. One multiplication, one boundry check, one
value looked up. With hard-typed constants or values, the speed benefit is
even more. For example:

    image[102][203]

    It can then, during pre-proccesing, lookup the exact memory address and
check the boundry. It would be as fast as a normal variable.

    And it off course increases readability, stability, and it saves us a
lot of time. Compare these two:

-- Currently with Euphoria you need to do:

    constant TRUE = 1, FALSE = 0

    type char (integer x)
        return x <= 0 and x >= 255
    end type

    type text (sequence s)
        if length(s) != 20 then
            return FALSE
        end if
        for index = 1 to 20 do
            if not char(s[index]) then
                return FALSE
            end if
        end for
        return TRUE
    end type

    text name
    name = repeat (' ', 20)

-- I want to be able to do:

    type char (integer x)
        return x <= 0 and x >= 255
    end type

    char name[20] = repeat (' ',20)

3) Structures, though no special tricks, just the plain simple and readable:

-- Example of how I would like to see structures implemented

    structure person do
        char name[] = ""
        integer age = -1
    end structure

    Now, I will explain a few things of what you see. First of all, char
name[]. It looks like an array, and it is. But its a non-fixed length array.
(a sequence thus, every says, irritated: yes, true, a sequence, however
still a fixed number of dimensions and one generic type associated to each
*element* of the sequence.

    Secondly, you must have noticed that I initialize all elements of the
structures. This is because its a pain, to initialize a structure yourself.
This is thus the default initialization. However to use the structure, you
must first use it as if it was a type: (actually, it is)

    person client
    client[name] = "Ralf Nieuwenhuijsen"
    client[age] = 16

    Again, like with arrays, structures have the advantage they speed things
up alot. They are more readable. Prevent half of all the scope problems and
enable an easy way to have seperate type-checking-functions for several
elements of a sequence.

4) Length should be assumed when its not used in an slice operation.
Example:

    image[4][10..]

   -- Should read as:

    image[4][10..length(image[4])]

    This also prevents many issues, that arise when you would introduce this
slicing syntax:

    image[10..][10..]

    Crops the image from (10,10) to (end, end)

5) We should be able to assign an sequence to a sequence:

    {x, y, c} = cursor ()

    Even, the & operator should be supported:

    {{x,y}} & text = get_text_and_location ()

    This enables much faster proccesing. Its much more readable. And
prevents the need for extra variables, and thus prevents scope issues.

6) The scope rules. First of all, there is no person on this planet who
started with Euphoria and realized/knew that indirectly half the world
included, when you use include. If I used include, only those global
identifers in that include files should be available to me. When I include
graphics.e but not machine.e, the global routines, constants and variables
of machine.e should not be available to me.

    Overriding of any identifer not defined in my the same include file
should only produce a warning. Thus overriding of constants, variables and
of routines.

    When two files include each other, all global indentifers of both files
should be available to both files. Mutal recursion between two routines from
seperate include files should thus be natively possible, without using
routine pointers thus.

7) Euphoria can be faster. Esspecially IO is not as fast as it can be. A
simple built-in function like "read_textfile ()" (vs read_bitmap) would be
very clean, and fast. Secondly, all input and output that Euphoria does, is
better off handeling natively with atoms, than using standard watcom
routines, and give them converted data. A puts () should have no need to
convert its datatype. A gets () as well. How to achieve that ? By using less
watcom routines and more euphoria libraries. I mean, many 'built-in' things
could just as easily have been Euphoria files. An great example is the
dir95, that is actually better than the one stored in one of the watcom
libraries linked with the interpreter. In other cases, just avoiding
translation of atoms into bytes can be an huge speed gain. I esspecially
mean file IO in this light. Built-in (read: fast) support for ports, wouldnt
hurt any one either. Wait retrace is for example a full machine code piece,
because using the 'constructed' ports routines were just too slow. Another
reason to avoid watcom routines are errors. Things like puts (1, "Hello" & 0
" & " you there") where " you there" is not displayed, since a zero is used
to indicate an end-of-line in C.

8) Rather than short-cirquiting, I would like to see smart support for lazy
routines. Whenever a function does not *set* any local variable (variables
declared in the space of the include file), it should be marked as 'lazy'.
Which means, that, when that function is called, rather than actually
executing the code, a pointer to the code is stored, until the value is
really needed. Example:

    proceduer display_text (sequence text, boolean should_i)
        if should_i then
            for index = 1 to length(text) do
                puts (1, text & '\n')
            end for
        end if
    end procedure

    display_text (read_textfile ("readme.txt"), FALSE)

    It doesnt even attempt to open "readme.txt" since the return value of
the function read_textfile is assigned to 'text' in the procedure
"display_text". However, during run-time the value is not 'looked'-up. If I
say:

    display_text (read_textfile ("readme.txt), TRUE)

    Just before the first puts () statement in "display_text", the function
read_textfile () is called and the file is opened.

    This could be done for Euphoria routines, but also for the built-in
routines, like find () and operational and math operators.  We do not need
to perform a multiplication, when there result will be never used anyway.

    However, this nifty lazy routine system, does not have to complicate
anything for the programmer. The interpreter can determine by itself, when a
function can be safely marked as 'lazy'. All functions that do not *modify*
external variables(variables declared outside of the scope of the function)
can be marked 'lazy' without any possible problem or conflict. Off course it
may not call non-lazy function as well. Those functions that do call
non-lazy routines are non-lazy themselves.

    But if it is supported, why not, give the programmer the freedom ? Yes,
it should be able. But only for those interested in the issues that it may
give you (and the power). Just a special keyword can force either mode:

    lazy function blabla ()
        -- only called when value is read
        -- you can now keep track of the amount of times, the return value
of this function is actually used.
    end function

    .. and ..

    strict function blabla ()
        -- immidiately called
        -- we might not use any external variables, but we do a windows call
for a message (for example), so we want it to be executed immidiately.
    end function

    With all other functions, the interpreter can determine wether or not it
is safe or not. The speed gain will be great for certain programs.

9) Bind and shroud should have NO issue whatsoever. Even at the cost of
run-time speed, may they never ever have any issue. 99% of all programs that
people sell, give and/or spread is binded. The whole point of programming is
making a program. There should be no issue whatsoever.

10) Whenever *possible* routines should be platform-generic. I mean:
mouse-routines, graphics, message-boxes, etc. can have a counterpart on the
other platform....  and there _should_ be one.

Thats all I can come up with. I would love to see more ideas of other users.
So please respond, or post your ideas. (maybe enumeration.. although Im not
sure how I would like to see it implemented). And Robert, of all of the
above points, as I know some (like structures) are supported by many, could
you explain the direction you want Euphoria to take, and why we can or can
not expect the above changes to actually happen ? Also, what will the new
version offer ? And can we pre-register, when you release the alpha version
?

My excues for any language error in the above. Im not a native English
spoken person, however do appriciate comments.

Ralf Nieuwenhuijsen
nieuwen at xs4all.nl
ralf_n at email.com

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

Search



Quick Links

User menu

Not signed in.

Misc Menu