1. strong typing and error handling

Maybe I'm shooting myself in the foot here, but....

One of the things in Eu that I really like is the rule-like
variable typing that let us set boundaries for a variable.
But it seems to me that the absense of an error-handler makes
this close to useless because when I try to load a value into
a variable that is outside it's boundaries, it exits the app
with an error message. Thus I need to have my app check anyway
when putting values into vars to prevent my app from exiting,
so when I have to check var boundaries myself, what does the
option to set boundaries when defining a var does for me ?

Or do I mis something and IS it possible to capture boundary
overflow (or underflow) in a simple way so I can write a simpe
error-handler ?

Hans Peter Willems

new topic     » topic index » view message » categorize

2. Re: strong typing and error handling

On 27 Jun 2003, at 7:55, Peter Willems wrote:

> 
> 
> Maybe I'm shooting myself in the foot here, but....
> 
> One of the things in Eu that I really like is the rule-like
> variable typing that let us set boundaries for a variable.
> But it seems to me that the absense of an error-handler makes
> this close to useless because when I try to load a value into
> a variable that is outside it's boundaries, it exits the app
> with an error message. Thus I need to have my app check anyway
> when putting values into vars to prevent my app from exiting,
> so when I have to check var boundaries myself, what does the
> option to set boundaries when defining a var does for me ?
> 
> Or do I mis something and IS it possible to capture boundary
> overflow (or underflow) in a simple way so I can write a simpe
> error-handler ?

You set your own type, which Eu will execute whenever you assign 
something to the var. Inside the typecast code, you check it's bounds. There 
is info on user-defined typecasting in Eu's help docs, but i don't know how to 
tell you where they are.

Scroll down to this line in String.e for an example:

global type string_type(object x)

Kat

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

3. Re: strong typing and error handling

On Fri, 27 Jun 2003 07:55:08 +0000 (06/27/03 17:55:08)
, Peter Willems <peter at integratedmoves.com> wrote:

>
>
> Maybe I'm shooting myself in the foot here, but....
>
> One of the things in Eu that I really like is the rule-like
> variable typing that let us set boundaries for a variable.
> But it seems to me that the absense of an error-handler makes
> this close to useless because when I try to load a value into
> a variable that is outside it's boundaries, it exits the app
> with an error message. Thus I need to have my app check anyway
> when putting values into vars to prevent my app from exiting,
> so when I have to check var boundaries myself, what does the
> option to set boundaries when defining a var does for me ?
>
> Or do I mis something and IS it possible to capture boundary
> overflow (or underflow) in a simple way so I can write a simpe
> error-handler ?
>

You can almost do this, so long as you don't mind not having access to any 
meta-data.

 procedure logerr(sequence msg, object data)
   printf(2, "Type Failure: %s\n", {msg})
   pretty_print(2, data, {3})
 end procedure

 global type Customer(object x)

  if not sequence(x) then
	logerr("Customer Type must be a sequence.", x)
      return 1 -- Return to app
  end if

  if length(x) != 5 then
	logerr("Customer Type must have 5 fields.", x)
      return 1 -- Return to app
  end if

  ...etc...

  return 1
 end type


So long as you always return non-zero from a type definition, your 
application won't crash with a 'type' error.

If you don't mind it crashing when an assignment is made you do this...

 sequence vTypeDefCrash
 vTypeDefCrash = {0}

 procedure SetTypeDefCrash( object NewVal)
  if sequence(NewVal) then
    if length(vTypeDefCrash) > 1 then
       vTypeDefCrash = vTypeDefCrash[2..length(vTypeDefCrash)]
       return
    end if  else
    vTypeDefCrash = NewVal & vTypeDefCrash
  end if
 end procedure

 global type Customer(object x)

  if not sequence(x) then
	logerr("Customer Type must be a sequence.", x)
      return vTypeDefCrash[1]
  end if

  if length(x) != 5 then
	logerr("Customer Type must have 5 fields.", x)
      return vTypeDefCrash[1]
  end if

  ...etc...

  return 1
 end type
 So that by default it would crash except when you don't want it to crash 
during a certain part of you code...

  SetTypeDefCrash(1) -- Turn on crash avoidance
  . . . -- critical code
  SetTypeDefCrash("") -- Restore it to whatever it was.

Unfortunately, you can't tell the user what line of code this was on, or 
the name of the variable, or even what source file it was in. --

cheers,
Derek Parnell

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

4. Re: strong typing and error handling

--- Peter Willems <peter at integratedmoves.com> wrote:
> 
> 
> Maybe I'm shooting myself in the foot here, but....
> 
> One of the things in Eu that I really like is the
> rule-like
> variable typing that let us set boundaries for a
> variable.
> But it seems to me that the absense of an
> error-handler makes
> this close to useless because when I try to load a
> value into
> a variable that is outside it's boundaries, it exits
> the app
> with an error message. Thus I need to have my app
> check anyway
> when putting values into vars to prevent my app from
> exiting,
> so when I have to check var boundaries myself, what
> does the
> option to set boundaries when defining a var does
> for me ?
> 
> Or do I mis something and IS it possible to capture
> boundary
> overflow (or underflow) in a simple way so I can
> write a simpe
> error-handler ?

You can use type() to trap invalid assignments, but 
unfortunately there's no reasonable way to _fix_ the
invalid data and continue on.  

When encountering bad data, your choices are: 
1. end the program - at least you have the option to 
log the error and perhaps clean up files, etc before 
ending. 
2. ignore the bad data, and let the program forge
ahead until the bad data fails to pass some built-in 
type checking, or causes data corruption - whichever 
comes first.

Since type() can only return TRUE or FALSE, and cannot
modify the data being checked, it's usefulness 
is about 10% of what it would be if it had been
designed correctly.

Because type() is nothing more than a function called 
automatically _on assignment_, we should be able to
use it to FIX most errors and return a correct data
value. We might even call, from within the type()
function, a routine to notify the user about the bad 
data, and have them re-input the correct data. Sadly,
we don't have those options, so you may just as well 
go ahead and write do the type checking yourself. 

And if we can have a function which is automatically
called on assignment, why can we not also have a
function which is automatically called on reference?

Regards

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

5. Re: strong typing and error handling

Until such time as Euphoria has pass-by-reference, there is a nasty
workaround for types that will only be used for a few variables--its
impractical for programs with hundereds of variables. Let's assume we want
to have variables that will reject a sequence, but modify any atom to coerce
its value to an integer between 1 and 10.

-- this code needs to be written only once
function coerce(object x)
    if atom(x) then
        x=floor(x)
        if x<min then x=1 end if
        if x>max then x=10 end if
    end if
    return x
end function

-- the code from here on is repeated for EACH variable
integer SET_A

type a_object(object x)
   object y
   y=coerce(x)
   if not equal(x,y) then call_proc(set_a,{y}) end if
   return integer(x)
end type

a_object a

procedure set_a(object x)
    a=x
end procedure

SET_A=routine_id("set_a")


This is a huge amount of overhead to simulate pass by reference, but it does
work.  I wish Rob would relent on pass by refernece for types at
least --preferably for all routines.  Wouldn't we all prefer to code the
above as:

type int1to10(by_ref object x)
    if sequence(x) then return 0 end if
    x=floor(x)
    if x<1 then x=10 end if
    if x>10 then x=10 end if
    return 1
end type

int1to10 a,b,c,d,e

For the OpenEU team, I would suggest two keywords that would  be allowable
only before a type specifier in a parameter list: by_ref and by_val (by_val
for documentation: pass by value would and should be the default -- VB
defaulting to ByRef is really, really bad).

-- Mike Nelson

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

6. Re: strong typing and error handling

On Fri, 27 Jun 2003 18:56:33 +1000, Derek Parnell
<ddparnell at bigpond.com> wrote:

WOW, Derek you blew my fuse...
>
>
>On Fri, 27 Jun 2003 07:55:08 +0000 (06/27/03 17:55:08)
>, Peter Willems <peter at integratedmoves.com> wrote:
>
>>
>> Maybe I'm shooting myself in the foot here, but....
>>
>> One of the things in Eu that I really like is the rule-like
>> variable typing that let us set boundaries for a variable.
>> But it seems to me that the absense of an error-handler makes
>> this close to useless because when I try to load a value into
>> a variable that is outside it's boundaries, it exits the app
>> with an error message. Thus I need to have my app check anyway
>> when putting values into vars to prevent my app from exiting,
>> so when I have to check var boundaries myself, what does the
>> option to set boundaries when defining a var does for me ?
>>
>> Or do I mis something and IS it possible to capture boundary
>> overflow (or underflow) in a simple way so I can write a simpe
>> error-handler ?
>>
>
>You can almost do this, so long as you don't mind not having access to =
any=20
>meta-data.
>
> procedure logerr(sequence msg, object data)
>   printf(2, "Type Failure: %s\n", {msg})
>   pretty_print(2, data, {3})
> end procedure
>
> global type Customer(object x)
>
>  if not sequence(x) then
>	logerr("Customer Type must be a sequence.", x)
>      return 1 -- Return to app
>  end if
>
>  if length(x) !=3D 5 then
>	logerr("Customer Type must have 5 fields.", x)
>      return 1 -- Return to app
>  end if
>
>  ...etc...
>
>  return 1
> end type
>
>
>So long as you always return non-zero from a type definition, your=20
>application won't crash with a 'type' error.

Yes, Got that.
>
>If you don't mind it crashing when an assignment is made you do this...
>
> sequence vTypeDefCrash
> vTypeDefCrash =3D {0}
>
> procedure SetTypeDefCrash( object NewVal)
>  if sequence(NewVal) then
>    if length(vTypeDefCrash) > 1 then
>       vTypeDefCrash =3D vTypeDefCrash[2..length(vTypeDefCrash)]
Help!
>       return
>    end if  else
>    vTypeDefCrash =3D NewVal & vTypeDefCrash
Ditto!
>  end if
> end procedure
>
I want to understand here, but I don't

> global type Customer(object x)
>
>  if not sequence(x) then
>	logerr("Customer Type must be a sequence.", x)
>      return vTypeDefCrash[1]
>  end if
>
>  if length(x) !=3D 5 then
>	logerr("Customer Type must have 5 fields.", x)
>      return vTypeDefCrash[1]
>  end if
>
>  ...etc...
>
>  return 1
> end type
> So that by default it would crash except when you don't want it to =
crash=20
>during a certain part of you code...
>
>  SetTypeDefCrash(1) -- Turn on crash avoidance
>  . . . -- critical code
>  SetTypeDefCrash("") -- Restore it to whatever it was.
>
Are you trying to push() and pop() error handling status?

>Unfortunately, you can't tell the user what line of code this was on, or=
=20
>the name of the variable, or even what source file it was in. --
>
>cheers,
>Derek Parnell

Pete

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

7. Re: strong typing and error handling

----- Original Message -----
From: "Pete Lomax" <petelomax at blueyonder.co.uk>
To: "EUforum" <EUforum at topica.com>
Subject: Re: strong typing and error handling


>
>
> On Fri, 27 Jun 2003 18:56:33 +1000, Derek Parnell
> <ddparnell at bigpond.com> wrote:
>
> WOW, Derek you blew my fuse...

Sorry about that.  Here is a working example of the sort of thing one can
do...

------------
include misc.e

sequence vTypeDefCrash vTypeDefCrash = {0}
sequence vTypeDefMsg vTypeDefMsg = {""}
integer vTypeDefErrs vTypeDefErrs = 0

global procedure ShowTypeDefErr(sequence msg, object data)
    printf(2, "Type Failure: %s\n", {msg})
    if length(vTypeDefMsg[1]) > 0 then
        printf(2, "%s\n", {vTypeDefMsg[1]})
    end if
    pretty_print(2, data, {3})
    puts(2,'\n')
    vTypeDefErrs += 1
end procedure

global procedure SetDebugMsg(sequence Msg)
    vTypeDefMsg[1] = Msg
end procedure

global procedure SetTypeDefCrash( object NewVal)
  vTypeDefErrs = 0
  if sequence(NewVal) then
    if length(vTypeDefCrash) > 1 then
       vTypeDefCrash = vTypeDefCrash[2..length(vTypeDefCrash)]
       vTypeDefMsg = vTypeDefMsg[2..length(vTypeDefMsg)]
       return
    end if
  else
    vTypeDefCrash = NewVal & vTypeDefCrash
    vTypeDefMsg = {""} & vTypeDefMsg
  end if
end procedure

global function TypeDefErr()
    return vTypeDefErrs
end function

global type Customer(object x)

  if not sequence(x) then
    ShowTypeDefErr("Customer Type must be a sequence.", x)
    return vTypeDefCrash[1]
  end if

  if length(x) != 5 then
    ShowTypeDefErr("Customer Type must have 5 fields.", x)
    return vTypeDefCrash[1]
  end if

  return 1
 end type


Customer x


  SetTypeDefCrash(1) -- Turn on crash avoidance
  SetDebugMsg("Test #1")
  -- This should not crash.
  x = 0

  SetDebugMsg("Test #2")
  -- This should not crash.
  x = {1,1,1,1}

  -- See if there were any errors found
  if TypeDefErr() > 0 then
    printf(1, "Number of Errors = %d\n", TypeDefErr())
  end if

  SetTypeDefCrash("") -- Restore it to whatever it was.

  -- Program should crash this time.
  x = {1,1,1,1}

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

Derek

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

8. Re: strong typing and error handling

On Fri, Jun 27, 2003 at 09:03:04AM -0700, Mike Nelson wrote:
> 
<snip> 
> 
> For the OpenEU team, I would suggest two keywords that would  be allowable
> only before a type specifier in a parameter list: by_ref and by_val (by_val
> for documentation: pass by value would and should be the default -- VB
> defaulting to ByRef is really, really bad).
> 
> -- Mike Nelson
> 

I'm not sure where things stand on the pass-by-reference front ... iirc there
was talk about it but i don't know what the result is.

As for types specificly, you will be able to create sequences (and arrays) of
a specific type (a sequence of integers, a 30 length array of user_type) and
use "bag" to get a mix of types. These will internally be checked per element
instead of the entire thing (as you'd have to do currently in RDSEu). Its
not hard to imagine this being extended to user-defined types, I suppose.

jbrown

-- 
 /"\  ASCII ribbon              | http://www.geocities.com/jbrown1050/
 \ /  campain against           | Linux User:190064
  X   HTML in e-mail and        | Linux Machine:84163
 /*\  news, and unneeded MIME   | http://verify.stanford.edu/evote.html

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

Search



Quick Links

User menu

Not signed in.

Misc Menu