1. Type - Start Again

Hello,

Playing with Peter Robinson's suggestion I realized that 
many of my existing codes could have been simplified by
his example. 

type customer(sequence x)
	integer x[1] as id
	sequence x[2] as name
	sequence x[3] as address
end type


Type definitions could replace the currently needed
constant id=1
constant name=2
constant address=3
type customer(sequence x)
	if length(x)=3
	and integer(x[id])
	and sequence(x[name])
	and sequence(x[address])
	then
		return 1
	else
		return 0
	end if
end type


(Although he suggested using "." instead of "as".)

Most of the answers replied to his general comment
but I would like to hear your opinion on the 
simplification shown above. What do you think?

Kind regards,

Salix

new topic     » topic index » view message » categorize

2. Re: Type - Start Again

Salix wrote:
> 
> Hello,
> 
> Playing with Peter Robinson's suggestion I realized that 
> many of my existing codes could have been simplified by
> his example. 
> 
> }}}
<eucode>
> type customer(sequence x)
> 	integer x[1] as id
> 	sequence x[2] as name
> 	sequence x[3] as address
> end type
> </eucode>
{{{

> 
> Type definitions could replace the currently needed
> }}}
<eucode>
> constant id=1
> constant name=2
> constant address=3
> type customer(sequence x)
> 	if length(x)=3
> 	and integer(x[id])
> 	and sequence(x[name])
> 	and sequence(x[address])
> 	then
> 		return 1
> 	else
> 		return 0
> 	end if
> end type
> </eucode>
{{{

> 
> (Although he suggested using "." instead of "as".)
> 
> Most of the answers replied to his general comment
> but I would like to hear your opinion on the 
> simplification shown above. What do you think?
> 
> Kind regards,
> 
> Salix

Looks nice, but the parser will have a terrible time with this...
I'd suggest either:
* replacing "type" by "structure" and leave types as they currently are;
* use a slightly different notation, the idea being to have a prefix, so that
the parser knows what he is doing:
type customer(sequence x)
    member id: integer
    member name: sequence 
    member address: sequence 
-- some optional code that would return a boolean, describing some axtra
consistency constraint
end type


This way we would extend types to _also_ include heterogeneous sequences,
without altering their current functionality.

CChris

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

3. Re: Type - Start Again

Salix wrote:
> 
> }}}
<eucode>
> type customer(sequence x)
> 	integer x[1] as id
> 	sequence x[2] as name
> 	sequence x[3] as address
> end type
> </eucode>
{{{

> 
> I would like to hear your opinion on the 
> simplification shown above. What do you think?
> 
I can accept that, with some qualifications (see below)

Peter Robinson wrote:
> Once you accept a declarative shorthand for boolean expressions, 
> the following is equally intuitive:-
>
> type ten_ints( sequence x )
>     length(x) = 10 – insert any boolean expression you want
> end type
>
> Since type blocks are just a series of boolean expressions, why not ASSUME 
> that in a declarative syntax?
But they are not. Types can be very useful in debugging, eg if I notice that my
program has crashed because something has set bCFwd[31][2] to -7, then I can find
where that happened by using a type, with any of:
if x[31][2]=-7 then return 0 end if
  if x[31][2]=-7 then ?9/0 end if
  if x[31][2]=-7 then trace(1) end if


Currently types, like functions and procedures, have implicit <locals> and
<code> sections. I can accept this be changed to <fields> <locals> <code>.
But I would not be happy with a change that meant type definitions could no
longer hold local vars and code.

CChris wrote:
> Looks nice, but the parser will have a terrible time with this...
It all seems pretty straightforward to me:
-- in type/routine definition (pseudocode)
    if <rtn type>=E_Type and <param type>=T_Sequence then
        -- process (optional) fields section:
        while isType() do
            nextToken()
            if tok[ID]!=<parameter> then
                -- complete first local var specially, since we accidentally
                -- just "ate" the sequence/integer/etc token [if needbe]
                exit
            end if
            expect "["
               ...
        end while
     end if
     -- existing handling for <locals> and <code> follows

In the same way that <locals> must be defined before <code>, keep it simple by
ruling that <fields> must be defined before <locals>.

The scope of id,name,address etc is a far trickier problem, imo. The only thing
I could suggest is have a look at the $ handling, however while mycustomer[name]
is fine, mycustomer[f(name)] would not be... Also, in

type address(sequence x)
    sequence x[1] as addr1
    sequence x[2] as addr2
end type
type customer(sequence x)
    integer  x[1] as id
    sequence x[2] as name
    address  x[3] as addr
end type
    ...
    .. mycustomer[<xxx>][<yyy>] ..
    ...

Then id,name,addr would be valid for <xxx>, but addr1 and addr2 would only be
valid for <yyy> if <xxx> was (?the literal constant?) addr, and of course all
invalid elsewhere on that line (barring another customer var subscript).

Oh (and this was going to be a short post), is this going to be annoying?
procedure showName(object x)
    if customer(x) then
        puts(1,x[name])
                 ^ invalid

Of course when someone comes and optimises their code it must still work:
procedure showName(object x)
integer cx
    cx=customer(x)
    if cx then
        puts(1,x[name])

Now /that/ is something a human sees well but gives a parser nightmares smile

This is also getting perilously close to puts(1,x[name]) implementing late
binding, but for that you would need to declare customer as an OO class.

In fact on that note......  smile smile

> This way we would extend types to _also_ include heterogeneous sequences, 
I would imagine that
type x(sequence of <type> y)

means it cannot have a fields section, a simple "and not <someflag>" after the
E_Type test above. Of course you cannot have a fields section on a type declared
as integer, atom, or object (assuming we get the ret 0 fix) either.

Regards,
Pete

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

4. Re: Type - Start Again

Pete Lomax wrote:
> 
> Salix wrote:
> > 
> > }}}
<eucode>
> > type customer(sequence x)
> > 	integer x[1] as id
> > 	sequence x[2] as name
> > 	sequence x[3] as address
> > end type
> > </eucode>
{{{

> > 
> > I would like to hear your opinion on the 
> > simplification shown above. What do you think?
> > 
> I can accept that, with some qualifications (see below)
> 
> Peter Robinson wrote:
> > Once you accept a declarative shorthand for boolean expressions, 
> > the following is equally intuitive:-
> >
> > type ten_ints( sequence x )
> >     length(x) = 10 – insert any boolean expression you want
> > end type
> >
> > Since type blocks are just a series of boolean expressions, why not ASSUME 
> > that in a declarative syntax?
> But they are not. Types can be very useful in debugging, eg if I notice that
> my program has crashed because something has set bCFwd[31][2] to -7, then I
> can find where that happened by using a type, with any of:
> }}}
<eucode>
>   if x[31][2]=-7 then return 0 end if
>   if x[31][2]=-7 then ?9/0 end if
>   if x[31][2]=-7 then trace(1) end if
> </eucode>
{{{

> 
> Currently types, like functions and procedures, have implicit <locals> and
> <code>
> sections. I can accept this be changed to <fields> <locals> <code>.
> But I would not be happy with a change that meant type definitions could no
> longer hold local vars and code.
> 
> CChris wrote:
> > Looks nice, but the parser will have a terrible time with this...
> It all seems pretty straightforward to me:
> }}}
<eucode>
>     -- in type/routine definition (pseudocode)
>     if <rtn type>=E_Type and <param type>=T_Sequence then
>         -- process (optional) fields section:
>         while isType() do
>             nextToken()
>             if tok[ID]!=<parameter> then
>                 -- complete first local var specially, since we accidentally
>                 -- just "ate" the sequence/integer/etc token [if needbe]
>                 exit
>             end if
>             expect "["
>                ...
>         end while
>      end if
>      -- existing handling for <locals> and <code> follows
> </eucode>
{{{


That's the first ... section which worries me a little because of some corner
cases.

> In the same way that <locals> must be defined before <code>, keep it simple by
> ruling that <fields> must be defined before <locals>.
> 

Agreed.

> The scope of id,name,address etc is a far trickier problem, imo. 

Nope, they have the same scope as the type they appear in, but should not be
used as indexes for the type they are defined for. The dot syntax appears to be
just fine. Using ':' like for a namespace is tempting, but would create nasty
collisions, so I'd prefer using the dot. Remember I'm an heretic from the
procedural religion.

> The only thing
> I could suggest is have a look at the $ handling, however while
> mycustomer[name]
> is fine, mycustomer[f(name)] would not be... Also, in
> 
> }}}
<eucode>
> type address(sequence x)
>     sequence x[1] as addr1
>     sequence x[2] as addr2
> end type
> type customer(sequence x)
>     integer  x[1] as id
>     sequence x[2] as name
>     address  x[3] as addr
> end type
>     ...
>     .. mycustomer[<xxx>][<yyy>] ..
>     ...
> </eucode>
{{{


Could you make it simpler by omitting the numbers, since they are defined by the
statement # they appear in?

This would lead to:
type address(sequence x)
    fields
        sequence addr1
        sequence addr2
    end fields
    <optional normal routine body here>
end type
type customer(sequence x)
    fields
        integer id
        sequence name
        address addr
    end fields
end type
    ...
    if equal(mycustomer[<xxx>][customer.name],"Pete") then ...
    ...

assuming mycustomer is a "sequence of customer", or a "customer list", which I'd
prefer as closer to the coder's intent.

> Then id,name,addr would be valid for <xxx>, but addr1 and addr2 would only
> be valid for <yyy> if <xxx> was (?the literal constant?) addr, and of
> course all invalid elsewhere on that line (barring another customer var
> subscript).
> 
> Oh (and this was going to be a short post), is this going to be annoying?
> }}}
<eucode>
> procedure showName(object x)
>     if customer(x) then
>         puts(1,x[name])
>                  ^ invalid
> </eucode>
{{{

> Of course when someone comes and optimises their code it must still work:
> }}}
<eucode>
> procedure showName(object x)
> integer cx
>     cx=customer(x)
>     if cx then
>         puts(1,x[name])
> </eucode>
{{{

> Now /that/ is something a human sees well but gives a parser nightmares smile
> 

Use x[customer.name], and the parser will be happy, won't he? Plus, if you use
the wrong constant, you can get an error (customer.name may be 2 and
supplier.name may be 4).
The extra typing is a problem. To alleviate it, we'd have to be sure that x is a
variable defined to be from a specific type with fields, and then forgetting the
explicit "customer." would cause it to be assumed. If the condition is not met,
then I'm not sure whether to throw an error. Could be the best thing to do. If
you use a dotted constant with the wrong type, then it may be assumed that you
know what yu are doing, so no error should occur. Probably a warning, just in
case you didn't know what you were doing.

> This is also getting perilously close to puts(1,x[name]) implementing late
> binding,
> but for that you would need to declare customer as an OO class.
> 
> In fact on that note......  smile smile
> 
> > This way we would extend types to _also_ include heterogeneous sequences, 
> I would imagine that
> }}}
<eucode>
> type x(sequence of <type> y)
> </eucode>
{{{

> means it cannot have a fields section, a simple "and not <someflag>" after
> the E_Type test above. Of course you cannot have a fields section on a type
> declared
> as integer, atom, or object (assuming we get the ret 0 fix) either.
> 

Agreed for both points.

CChris

> Regards,
> Pete

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

5. Re: Type - Start Again

Hello all

I'd be absolutely delighted if a solution were implemented that allowed typing
and aliasing of data within a sequence. To me, such improvements would merely
enhance Euphoria's sequences, not detract from them.
However, the suggested solutions don't address the issue of nested data. I am
one of the apparently few people who want to constrain nested data (beyond the
first dimension), and the same sort of idea arose in the discussion of "sequence
of integer". I do believe a consistent approach to similar issues is more likely
to preserve the clean design of the language. (If it's impossible, so be it). I
can see how something like "sequence of sequence of integer" quickly becomes
non-intuitive, and you have the question of where to draw the line. Natural
language doesn't convey multiple dimensions well. My own suggestion was therefore
aimed at a more visual representation through brackets.
As I intimated in my post, I am happy for the contributors to make the decisions
- I just wanted to raise the issues at a more general level, so that more
generalised solutions could be considered.
Cheers
Peter Robinson

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

6. Re: Type - Start Again

Peter Robinson wrote:
> 
> However, the suggested solutions don't address the issue of nested data.
Looks to me like it does. Can you expand a bit more on what is missing?

Regards,
Pete

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

7. Re: Type - Start Again

Hi

These seem to me to be variations that deserve consideration. The general domain
is approaches to constraining data internal to sequences in the same way that
Euphoria allows typing of data external to an object. I deliberately restricted
the cases to syntax within a type block. The aliasing idea is separate - excluded
here.

Case 1: Fixed heterogeneous sequences - typical entity objects, like the
customer object discussed. I've also omitted any implementation-specific syntax
that was discussed.

Salix assumed that my example like:-

type customer( sequence x )
   integer x[1] id
   sequence x[2] name
   sequence x[3] address
end type

implied length(x) = 3. It's a reasonable asumption, but I actually didn't intend
it one way or the other.

Discussion between Pete and CChris, including aliasing, suggested that the
x[num] part is superfluous, since the index is implied by ordering.

Comment1: If you don't want to alias the subscripts, you're left with no
identifier at all. Looks odd / unclear / ambiguous to me.
Comment 2: If you leave out the index number, the number is implied, but may be
hard for the eye to pick up if the sequence has several members.
Comment 3: Is "field" a good Euphorian word?

Case 2: Homogenous sequences
Sequence of uniform type in n dimensions. Goal to avoid / simplify looping
syntax.I suggested:-

-- 1-dimensional sequence, all integers i.e. sequence of integer
type list( sequence x )
   integer x[]
end type

-- This is a more Euphorian alternative, but doesn't generalise well to > 1
dimension
type list( sequence x )
   integer x[1..$]
end type

-- which suggests
type semi_loose_entity( sequence x )
   integer x[1]
   sequence x[2..$]
end type

-- > 2-dimensions - highlighting visual hierarchy idea
type matrix( sequence x )
   sequence x[]   -- 1st dimension all sequences
   integer  x[][] -- 2nd dimension all integers
end type

I think that gives the picture. It didn't look to me that all these variations
were considered. Maybe some were rejected out of hand.

Since I started all this, I'm happy to do any documentation of any outcome or
assist otherwise if I can, but I can't devote time to studying the interpreter
code in depth.

Cheers
Peter Robinson

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

8. Re: Type - Start Again

Peter Robinson wrote:
> 
> Hi
> 
> These seem to me to be variations that deserve consideration. The general
> domain
> is approaches to constraining data internal to sequences in the same way that
> Euphoria allows typing of data external to an object. I deliberately
> restricted
> the cases to syntax within a type block. The aliasing idea is separate -
> excluded
> here.
> 
> Case 1: Fixed heterogeneous sequences - typical entity objects, like the
> customer
> object discussed. I've also omitted any implementation-specific syntax that
> was discussed.
> 
> Salix assumed that my example like:-
> 
> type customer( sequence x )
>    integer x[1] id
>    sequence x[2] name
>    sequence x[3] address
> end type
> 
> implied length(x) = 3. It's a reasonable asumption, but I actually didn't
> intend
> it one way or the other.
> 

It looks like we'd need an extra keyword to mean "no other field may follow" or
"other fields may follow". My own preference would be for a terminal "stop"
keyword to mean that the sequence should only contain the fields listed above.
Perhaps "end all_fields" is better than "stop end fields". I have very weak
preferences there, but something should probably be added.

> Discussion between Pete and CChris, including aliasing, suggested that the
> x[num]
> part is superfluous, since the index is implied by ordering.
> 
> Comment1: If you don't want to alias the subscripts, you're left with no
> identifier
> at all. Looks odd / unclear / ambiguous to me.

The idea I had was to make declaring fields as close as possible from declaring
a variable. Hence each field must have a name, since each variable must have a
name. Since aliases may collide between different structures, then, inside an
index specification:
* If the sequence is of a fielded type, and the unqualified alias is a known
field, use this binding, else error;
* If the field name is prefixed by a type name and a dot, then use the binding
if the alias is known for the type of the conaining sequence, or if it has a
unique offset, else error;
* If an unqualified field name is used in conjunction with a sequence not of a
fielded type, then use the common value if there's any, else error.

Since a field declaration is syntactically identical to a local variable
declaration, it needs some kind of block separation to differentiate. There may
be either fields or local variables, or both.


> Comment 2: If you leave out the index number, the number is implied, but may
> be hard for the eye to pick up if the sequence has several members.

Is it easier to read an index or to follow a list of "type name" lines? imho the
latter. Note that numeric indexes are allowed, though not recommended.

> Comment 3: Is "field" a good Euphorian word?

What is the loose evaluation function to be used to tag a keyword as more
euphorian than another? I thought being short and expressive helped. "fields"
looks good, why not "items" or "parts". What would you advocate?

> 
> Case 2: Homogenous sequences
> Sequence of uniform type in n dimensions. Goal to avoid / simplify looping
> syntax.I
> suggested:-
> 
> -- 1-dimensional sequence, all integers i.e. sequence of integer
> type list( sequence x )
>    integer x[]
> end type
> 
> -- This is a more Euphorian alternative, but doesn't generalise well to > 1
> dimension
> type list( sequence x )
>    integer x[1..$]
> end type
> 
> -- which suggests
> type semi_loose_entity( sequence x )
>    integer x[1]
>    sequence x[2..$]
> end type
> 
> -- > 2-dimensions - highlighting visual hierarchy idea
> type matrix( sequence x )
>    sequence x[]   -- 1st dimension all sequences
>    integer  x[][] -- 2nd dimension all integers
> end type
> 
> I think that gives the picture. It didn't look to me that all these variations
> were considered. Maybe some were rejected out of hand.
> 

I'm afraid that anything that looks too clearly like C will be rejected out of
hand. I am not among the C haters, and have learned to appreciate C as I get more
frustrated with the verrbosity and rigidity of EUphoria in some areas. But there
are some on this list.

> Since I started all this, I'm happy to do any documentation of any outcome or
> assist otherwise if I can, but I can't devote time to studying the interpreter
> code in depth.
> 
> Cheers
> Peter Robinson

CChris

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

9. Re: Type - Start Again

CChris wrote:
> 
> Peter Robinson wrote:
> > -- > 2-dimensions - highlighting visual hierarchy idea
> > type matrix( sequence x )
> >    sequence x[]   -- 1st dimension all sequences
> >    integer  x[][] -- 2nd dimension all integers
> > end type
> > 
> > I think that gives the picture. It didn't look to me that all these
> > variations
> > were considered. Maybe some were rejected out of hand.
> > 
> 
> I'm afraid that anything that looks too clearly like C will be rejected out
> of hand. I am not among the C haters, and have learned to appreciate C as I
> get more frustrated with the verrbosity and rigidity of EUphoria in some
> areas.
> But there are some on this list.

There are? I've never noticed anyone who really hated C here...

I don't know about this exact syntax -- I like the first part but not the second
so much. I think it would be nice to have a built-ins similar to integer() and
atom() and sequence() that check an entire level of a sequence which kind of
seems like what is being suggested.

And then you can define your own types and then compose the type definitions
into more complicated types. Of course, then it kind of goes back to Pete's and
Rob's suggestions of inserting that syntax into the argument list of a type
definition.

--
A complex system that works is invariably found to have evolved from a simple
system that works.
--John Gall's 15th law of Systemantics.

"Premature optimization is the root of all evil in programming."
--C.A.R. Hoare

j.

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

10. Re: Type - Start Again

Peter Robinson wrote:
> 
> Case 1: Fixed heterogeneous sequences
> 
> Salix assumed that my example like:-
> 
> type customer( sequence x )
>    integer x[1] id
>    sequence x[2] name
>    sequence x[3] address
> end type
> 
> implied length(x) = 3. It's a reasonable asumption, but I actually didn't
> intend
> it one way or the other.
Fair enough. If you wanted to enforce a customer record only ever had 3 fields
then use the obvious if length(x)!=3 then return 0, otherwise elements 4..$ can
exist and are untyped.
> 
> Discussion between Pete and CChris, including aliasing, suggested that the
> x[num]
> part is superfluous, since the index is implied by ordering.
I have no particular bias for [1],[2] or fields .. end fields notation.

> Case 2: Homogenous sequences
> 
> -- 1-dimensional sequence, all integers i.e. sequence of integer
> type list( sequence x )
>    integer x[]
> end type
I was thinking of using
type list(sequence of integer x)
end type


> -- which suggests
> type semi_loose_entity( sequence x )
>    integer x[1]
>    sequence x[2..$]
> end type
Hmmm, not sure about that. After sle[idx]=x, if idx is a fixed literal integer
constant (such as a field name) then the compiler will be able to limit type
checking to the single modified element, but if idx is a var then the compiler
cannot do the same level of optimisation, needing either extra code somewhere
(key point being, where would that code be, exactly?) or it may be easier and
quicker just to type-check the whole thing.

> -- > 2-dimensions - highlighting visual hierarchy idea
> type matrix( sequence x )
>    sequence x[]   -- 1st dimension all sequences
>    integer  x[][] -- 2nd dimension all integers
> end type
> 
Seems to me this, and the previous example, would be better coded as:
type vector(sequence of sequence ss)
end type
type speeds(sequence of integer si)
end type
type matrix(sequence x)
  vector x[1] v
  speeds x[2] s
end type

To me this has a clear advantage that when modifying the elements of a type
matrix var, the work vars you need have a read-made named type, which in turn
means the compiler can omit type checking completely:
procedure swap(matrix m, integer a, integer b)
vector v
  v=m[v][a]
  m[v][a]=matrix[v][b]
  m[v][b]=v
end procedure

Which is a pretty neat trick, considering you would still have full type-safety
on user defined types. (First person to say C++ already does this gets a kick)

> Since I started all this, I'm happy to do any documentation of any outcome 
> or assist otherwise if I can, but I can't devote time to studying the 
> interpreter code in depth.

On may travels the other day (looking for something else entirely), I came
across this by Derek Parnell:
http://www.openeuphoria.org/cgi-bin/esearch.exu?thread=1&fromMonth=8&fromYear=8&toMonth=A&toYear=8&keywords=%22Last+Element+Reference%22

Same deal for the next stage: Articulate and concise, irrefutable and conclusive
would probably work best. Also plenty of concrete examples -
if they're not right, and convincing, it won't fly.

Regards,
Pete

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

11. Re: Type - Start Again

Pete Lomax wrote:

> Peter Robinson wrote:
>> 
>> However, the suggested solutions don't address the issue of nested data.
> Looks to me like it does.

So does it look to me, too.

> Can you expand a bit more on what is missing?

I wonder why he does not answer this question.

Regards,
   Juergen

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

Search



Quick Links

User menu

Not signed in.

Misc Menu