Re: Problems with structures & Re: structures

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

>I'll admit, it was late when I wrote my version of your questionnaire, and
I
>probably shouldn't have sent it off without thinking more clearly about it.
>For that, I apologize.

>However, this does not change the fact that there is more to being
>anti-structure than disliking C. There are a whole host of sticky problems
>structures face in Euphoria. I invite you to read my earlier posts for
>detailed, specific examples.

Ok, fair. I was confusing you with the original author which I responded to,
which did make the statement about C. (I expected a fairly offended
response, so I assumed the only reponse I got, was from the person in
question)
I also agree, there are people wanting structures without considering the
issues with the actual implementation.

Lastly for your information, I got you other mail later, and when getting
you reponse, I was already writing a response about the issues you brought
up. May I, in that light, also notice that your problem with structures are
not structures themselves, but implementation issues ? (since only those are
used as arguments by you)

And considering those implementation issues you thought: its not elegant.

And you know what ? You're right. The approach you assumed isnt elegant at
all.

How many of you arguments would survive *my* approach ?
The approach Ive explained before. (however, Im getting a little use to
repeating myself, and I will repeat that idea as well.)

Before I start, a little side-note:

> "Compile"-time field-reference checks in Euphoria -- as
>depicted here -- are impossible.

This only counts for your approach.
Not for mine, where structures are not a new datatype and are not treated
differently except internally.

If you can think of any issue not dealt with, please share with me..

My method:
-----------------------

First of all, no new datatype. Its a sequence. Its still is. Its a sequence
with a type check function just as before. In other words, its coverts
example code B to example code A.

Example code A
-----------------------

    constant
        SUIT = 1,
        VALUE = 2,
        INIT_CARD = {repeat (' ',9),0}

    type card (object x)
        if sequence (x) and length(x) = 2 then
            return string_9 (x[1]) and integer (x[2])
        else
            return 0
        end if
    end type

    card my_card
    my_card = INIT_CARD

-----------------------
Example code B
-----------------------

    structure card
        string_9 suit = repeat (' ',9)
        integer value = 0
    end structure

    card my_card

----------------------

A simple preproccesor could even do this without off course a couple of
benefits.
But what, other than translating example code B to example code A the above
during compile-time, do I want ?

    ---->>     I want to restrict the use of the associated constants. They
should only be able to be used when slicing a variable declared of that
type/structure. Example:


            ? my_card[suit]      -- legal
            ? suit                        -- illegal
            ? my_card[1]        -- legal
            ? my_card[1..2]    -- legal
            ? my_card[suit..value]    -- legal
            ? my_card            -- legal
            ? value            -- illegal
            var_x = suit + 1 -- illegal
            my_card[var_x]     -- legal, but useless, since you cant assign
suit + 1 to var_x
            my_vard[suit+1] -- legal, but would crash

So withing the '[' and ']' when slicing the associated variable, is the only
legal place for the constant to be used.

Thats it. Thats all I want. Thats all I need.
What would happen with any custom type in a normally declared sequence ?
Nothing.
So what would happen with a structure in a sequence ? Nothing. It would not
be checked.
Are the constants available when you assign the structure to a normally
declared sequence for use with that sequence ? No.

This has two advantages: you can pass sequences to a routine when it expects
a structure. It will try to match or generate an type-check error if it does
not match. The other advantage is, that for each library you can choose
wether or not you want to use structures.

If you want to custom declare the constants, etc. You are free to do so. And
things will work as expected.

Also notice, that for me the dot syntax is out of the question. We already
have a slicing syntax and i see no reason to add another syntax. It would
complicate things.

Another (a bit irrelevant) advantage is that with converting a library that
doesnt use structures to a library that does use structures. Simply change
the declerations, and replace the long list of constants with the structure
definition (almost equal). After which, the same code will run much faster,
be better maintainable, etc. yet it does not impact any program using that
library.

Also to prove the speed advantage...
I recall from Roberts post a long long long time ago (it might be different
nowadays.. for the newer version.. Robert, please corrent or elaborate if
appropiate) but Euphoria is a stack-based interpreter. On its *own* stack
(it does not use the standard stack, since its of fixed lenght) it begins
with the machine addres of the machine code to execute a certain 'action'
followed by the arguments. For a simple addition and storage, it would be
something in the line of: { addres of code to perform addition with two
integers, addres of integer1, addres of integer2 }. Sequences are internally
stored as a block of data, containing the length (for quick lookup), all the
integers, and *pointers* to all sequences and atoms inside that sequence. So
a lookup like: x[2][3][4] makes it go to the addres of x, scan to position 2
(length-check performed), go to the addres found there, scan to position 3
(lenght-check), go to the addres found there, scan to position 4 and you've
finally looked up your value. What if the length of each sequence and
subsequence was known (fixed) at compile-time ? It could allocate one huge
block at once for the whole structure. And replacing [1][2][3][4] with a
direct memory addres to the value, since that addres is *fixed*.

This has one dis-advantage/issue not yet discussed. Which next to the
inconsistency of the 'initialization' are the only issues I can come up
with...    smart pointer-arithmic simerlar to what is happening now is
impossible. A different approach could be possible. But Robert would need to
'invent' / 'create' a new system for this, or sacrifice speed and maintain
the original system. (this would force us to lookup the addres of nested
values in run-time rather than in compile-time)

Also a last note. The system using 'of' (sequence my_seq of card)... well Im
am admitting it would be handy, just not in that way. I call it arrays. A
fixed-dimension and optionally fixed-length sequence containing elements all
of the same type. Something handled a little badly currently as well. Again
example code A should replace example code B.

Example Code A
------------------------

    card my_seq[20]

-----------------------
Example Code B
-----------------------

    type specific_for_card_of_20 (object x)
        if sequence (x) and length (x) = 20 then
            for index = 1 to 20 do
                if not card (x[index]) then
                    return 0
                end if
            end for
            return 1
        else
            return 0
        end if
    end type

    specific_for_card_of_20 my_seq

--------------------
But I'll admit it. Arrays I want for the speed. Arrays offered in such way
the speed advantage is as high as I claim (a structure lookup could be as
fast as using a direct atom/integer.. same for array lookups) would also
have the issue of smart pointer arithmics. We would need a new approach to
do gain the same advantages. Although may I note that esspecially with
structures and arrays, pointer arithmics are less important and fast input /
output to file/memory/builtin/dll of those are much much more important,
than with sequences. ANd there might even be a way for the interpreter to
choose the most appropiate method: emulating and maintaining the normal
pointer arithmic, or field-resolving and new (worse) pointer arithmic.

Anyways, Robert, could you tell us, if sequences were implemented, in such
way that the field were lookup up in compile-time (or *calculated* in
real-time, rather than looked-up in real-time), how much of the current
pointer arithmic would still be possible ?

Just to try to get an idea if its feasable.


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

Visit the Elevator:
http://www.xs4all.nl/~nieuwen

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

Search



Quick Links

User menu

Not signed in.

Misc Menu