1. Try/Catch

I'm wondering how try/catch/finally might be implemented in Euphoria.

I've only looked briefly at the interpreter, and not much at all at the C code generator, so I apologize if some of this is nonsense.

First, instead exiting on an error, RTFatal() would have to have set some sort of flag.

Because the implementation would have to work with the C version of Euphoria as well as the interpreter, the most straight-forward thing to do would be to implement new opcodes.

So let's assume there were a new opcode, ON_ERROR address that would jump to address if the error flag was set. This opcode would need to be inserted after any call that could potentially call RTFatal. This means opcodes as mundane as ATOM_CHECK and as complex as SWITCH_RT, but certainly not every opcode.

It would also have to be inserted after the return from any non-trivial user routine, since something as simple as an atom declaration could generate a runtime error.

While the implementation in Euphoria would be fairly straight-forward, along the lines of:

procedure opON_ERROR() 
    -- jump to address following opcode if fatal_error_flag is set 
    if fatal_error_flag then 
        pc = Code[pc+1] 
    else 
        pc += 2 
    end if 
end procedure 

For the sake of speed, I'll assume that ON_ERROR would be implemented as "real" code and not a subroutine, along the lines of:

    if (fatal_error_flag) goto L_CATCH_22; 

so to make things a bit more efficient, the code to clear the error flag should probably be another opcode called CLEAR_ERROR, implemented at the top of the catch block. I'd imagine would be as simple as

    _fatal_error_flag = 0; 

Of course, there's always the possibility that an error might happen outside of a try/catch block. There are a couple ways this could be handled. One option would be to add a new opcode, along the lines of RETURNF, but only returning if the error flag was set.

Another option would be to have ON_ERROR jump to an actual RETURNF automatically placed at the end of the routine. On returning to the calling routine, the error would be detected by an ON_ERROR opcode that would automatically be generated.

In the case of a forward reference, Euphoria wouldn't know if the routine could potentially throw an error. By default, it could insert an ON_ERROR after any forward references.

At the finally portion of the try/catch/finally block, things get a bit more dicey. That's because finally is guaranteed to be executed, even if there is no error.

There are a number of different ways that finally can be triggered:

  • Exiting the try block without error.
  • An error in the try or catch block.
  • An error in the catch block.
  • Exiting the try or catch block with a return.
  • Exiting the try or catch block with a goto.

For example, if a return is encountered deep inside a bunch of nested try/catch/finally blocks, all the finally blocks need to be called before exiting the routine. The catch is that the finally can't be called via a standard jump, because it has to return to the next instruction. That means implementing an equivalent to BASIC's GOSUB.

In the interpreter, this could be done via a stack. In standard C setjmp and longjmp() look like they'll do the trick.

So from a very cursory look, it seems feasible that try/catch/finally could be coded in Euphoria - both the interpreter and the C version - fairly efficiently, without too many changes to the code. I'd also guess that it could be an option - a with try-catch would generate code that would throw errors, and without try-catch would generate "classic" Euphoria code.

Thoughts?

new topic     » topic index » view message » categorize

2. Re: Try/Catch

dcuny said...

I'm wondering how try/catch/finally might be implemented in Euphoria.

Raymond Chen is always worth a read:
http://blogs.msdn.com/b/oldnewthing/archive/2005/01/14/352949.aspx
http://blogs.msdn.com/b/oldnewthing/archive/2004/04/22/118161.aspx
(whatever gets implemented should address those concerns, and when that bloke says that something is hard, you really should pay attention)

dcuny said...

First, instead exiting on an error, RTFatal() would have to have set some sort of flag.

I would think that you need some kind of stack unwind.

dcuny said...

At the finally portion of the try/catch/finally block, things get a bit more dicey.

All excellent arguments for not adding finally (an awful, stupid, confusing concept) to Euphoria.

If the main point of exception handling is to separate error handling code from the main logic, what is wrong with putting such things in a separate routine?

procedure cleanup() 
    <such code> 
end procedure 
 
try 
   ... 
   cleanup() 
catch 
   ... 
   cleanup() 
   throw(...) 
end try 

or am I missing something?

It makes me madder than hell to think of such a horrible backward construct being added to Eu, if two simple calls would do.

Of course if you are not re-throwing an exception, which I would have thought is more likely anyway, or are prepared to use a simple flag/return value, <such code> can and should just go after the end try.

dcuny said...

In standard C setjmp and longjmp() look like they'll do the trick.

I randomly stumbled over a possibly interesting snippet from Michael Anderson:
http://stackoverflow.com/questions/10586003/try-catch-statements-in-c
(last post but one) though (as I said) a stack unwind based approach might be better/easier.

Of course the other burning question is why someone might want exception handling:

  • to write good quality robust code, but without the messiness of error code handling
  • to use badly written unstable garbage, and get away with it.

Personally, I genuinely prefer the messiness of error code handling, as it is easier to follow and easier to debug, and of course I worry that (most) people will think they are getting something which is actually really hard to do right, for free.

Pete

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

3. Re: Try/Catch

I don't see Raymond offer a viable alternative to try/catch, only an argument that it's not perfect.

How is this helpful? sad

petelomax said...

I would think that you need some kind of stack unwind.

I think you misunderstand. I meant to state the very obvious - RTFatal currently stops code execution, and that behavior would have to be altered in order to handle exceptions.

I'd suggested that opcodes be put in place to check the return status from a routine that might set a fatal condition.

You can't simply perform a call stack unwind because traditional try/catch blocks can potentially be nested.

Plus, you need to handle the exception at the local level, where the exception took place. How is unwinding to a prior call helpful, if a local resource needs to taken care of? The prior call can't see into the routine with an exception.

petelomax said...

All excellent arguments for not adding finally (an awful, stupid, confusing concept) to Euphoria.

Please explain your issue with finally.

For handling system resources, it's essential that they be released correctly. finally guarantees that this will have the opportunity to happen.

How is this bad thing?

petelomax said...

If the main point of exception handling is to separate error handling code from the main logic, what is wrong with putting such things in a separate routine?

The point of structured exception handling is to handle exceptions in a structured manner.

One huge problem with calling cleanup() is that it hasn't got access to the local variables. How do you close a resource in cleanup() when you don't have the handle to it? How do you save the user's current work when #cleanup() can't see the data structure the user was working on?

How can you handle the exception at a level the exception didn't happen on?

petelomax said...

It makes me madder than hell to think of such a horrible backward construct being added to Eu, if two simple calls would do.

That's a big "if".

Often, to simple calls won't do. How you you pass the context of the current call to your cleanup() routine? Having try/catch scoped to a block inside the offending call solves that problem.

petelomax said...

Of course if you are not re-throwing an exception, which I would have thought is more likely anyway, or are prepared to use a simple flag/return value, <such code> can and should just go after the end try.

I'm not sure I follow you here. Whether you re-throw an exception depends entirely on what the exception was, and how it should be handled.

petelomax said...

...though (as I said) a stack unwind based approach might be better/easier.

That's assuming that stack unwinding is appropriate. I've already noted why this may not be appropriate:

  • The context of the exception is lost, so it can't be handled.
  • Structured exception handling can be structure, so unwinding the call stack wouldn't work
petelomax said...

Of course the other burning question is why someone might want exception handling

Because exceptions need to be handled.

Halting isn't a robust way of handling exceptions.

petelomax said...
  • to write good quality robust code, but without the messiness of error code handling

You've lost me here. try/catch is error handling. Euphoria currently hasn't got solid error handling. If something slips past your tests, the current error handler hasn't got access to the context, and can't recover or have access to the local data.

If you're going to suggest that any data that needs to be recovered should have been stored in global variables, that's basically ignoring the point of structured programming.

petelomax said...
  • to use badly written unstable garbage, and get away with it.

Why you assume this to be the case?

petelomax said...

Personally, I genuinely prefer the messiness of error code handling, as it is easier to follow and easier to debug, and of course I worry that (most) people will think they are getting something which is actually really hard to do right, for free.

What "error code handling" are you referring to? Prior to adding crash_routine to Euphoria, there was no error handling in Euphoria - it simply crashed by design.

The current crash_routine isn't error handling, because the error isn't actually handled - Euphoria then goes on to halt. And Robert fought against even adding that much.

The reality is that no one can write fool proof code. But without some sort of way to handle exceptions, Euphoria users can't write robust code, because Euphoria isn't designed to be robust, it's designed to be fragile and not handle exceptions.

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

4. Re: Try/Catch

Hallo

I'am not sure if i understand the discussion...

But having something like this (like in Pascal) would be more than 'really nice'...

http://www.freepascal.org/docs-html/ref/refch17.html

I think this code is really readable and matches Euphoria's Coding Style.

For sure the language needs to be expanded and we need to know the kind of the exception, maybe Euphoria can't reach this level...

But from my point of view, any errorhandling (no matter how simple) is better than just chrashing.

Andreas

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

5. Re: Try/Catch

I prefer Go's handling of errors compared to exceptions as performed in other languages.

Routines which can fail on recoverable errors return an error code. Similar to Euphoria, Go can return multiple values from functions, cf "get" and "value" in Euphoria.

For unrecoverable errors, Go has "panic".

For cleaning up resources, Go has "defer" which defers the execution of a piece of code until the subroutine exits.

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

6. Re: Try/Catch

andi49 said...

But having something like this (like in Pascal) would be more than 'really nice'...

This is essentially the same as try/catch.

- David

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

7. Re: Try/Catch

jaygade said...

I prefer Go's handling of errors compared to exceptions as performed in other languages.

This looks roughly akin to BASIC - On Error Continue, where an Err value is set, but the code doesn't fail. The main difference seems to be that Go returns an Error object, while BASIC has a global value.

However, in Euphoria, there's no such thing as a recoverable error. So in that sense, it's sort of the opposite of how Euphoria handles errors: Euphoria halts, while Go continues, but informs you that an error occurred.

From that perspective, I think it would be a hard sell. That is, it fundamentally alters how Euphoria behaves. On the other hand, try/catch/finally wouldn't actually alter Euphoria's behavior - if you chose not to use them, exceptions would still be fatal.

jaygade said...

For cleaning up resources, Go has "defer" which defers the execution of a piece of code until the subroutine exits.

This seems akin to finally. The main difference is that is that finally can be embedded inside of other try/catch loops.

- David

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

8. Re: Try/Catch

Euphoria has recoverable errors, you just have to check for them. "Get()" and "value()" are the best examples of that. Checking if a file exists is another.

Unrecoverable errors are ones where your program is wrong and is in an undefined state, so crashing is the correct behavior.

Edit: The nice thing about "defer" in Go code is that it puts the release of the resource close to the allocation of the resource, instead of at the bottom of a section of code.

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

9. Re: Try/Catch

A bit more detail on Go's error handling in Euphoria.

In Euphoria, as soon as an error is reached, the code halts. End of game, that's it.

Let's imagine Euphoria with Go's error handling.

Returning multiple values would require some major changes to Euphoria, so (for the sake of discussion), let's imagine that it's essentially the same as BASIC, and the error result it returned in a global variable. So you could do something like:

... 
someRoutine(a, b, c) 
if error then 
   -- handle the error 
end if 

Now, if you didn't check for the error condition, Euphoria would happily ignore all errors. Since would break a code model that people currently depend on, you'd probably need something along the lines of BASIC's on error continue, which tells BASIC not to halt on errors. So let's imagine that there was a routine called on_error_continue(flag) which accepted a true/false value. So you could write:

-- a typed variable 
atom x = 0 
 
-- don't halt on errors 
on_error_continue(1) 
 
-- do something that causes an exception 
x = "assigning strings to atoms fails!" 
 
if error then 
   printf(1, "The error was %s\n", {error_text}) 
end if 

This would be more or less backward compatible. Is this what you had in mind?

For me, this is considerably less good than try/catch. The reason is perhaps a bit counter-intuitive: I don't know where my code is going to encounter an error. And in Euphoria, the error is likely to be an indexing error of some sort:

s1[i][j] = s2[k][j] 

So unless I check the condition of error after every operation, I've got a good chance of performing a couple more operations before I notice things have gone wonky.

With try/catch, my code immediately jumps to the catch clause before more things can go awry.

Now, you could argue that since Euphoria doesn't do pass by reference, data won't be corrupted until the return from the function. (Unless, of course, you're using global variables).

Go's defer is slick, but I think it would be a hard sell. Doing something like this doesn't really have an analog in Euphoria:

func f() { 
    defer func() { 
        if r := recover(); r != nil { 
            fmt.Println("Recovered in f", r) 
        } 
    }() 
    fmt.Println("Calling g.") 
    g(0) 
    fmt.Println("Returned normally from g.") 
} 

Here, you've got an anonymous function potentially being pushed onto the stack for execution on exit of func(). This is entirely unlike how Euphoria works.

Another example from Go:

func c() (i int) { 
    defer func() { i++ }() 
    return 1 
} 

The function c() will push an variable number of anonymous functions (only known at runtime) onto the defer stack to be executed on exit of c(). And the parameters to these functions are dynamically evaluated before they are pushed onto the defer stack.

It's very slick, but it would require major changes to Euphoria.

I can't see this happening. While it could be coded in the interpreted version, getting something similar for the C compiler is another matter.

- David

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

10. Re: Try/Catch

dcuny said...
petelomax said...

I would think that you need some kind of stack unwind.

I think you misunderstand. I meant to state the very obvious - RTFatal currently stops code execution, and that behavior would have to be altered in order to handle exceptions.

I'd suggested that opcodes be put in place to check the return status from a routine that might set a fatal condition.

Well, most things can run out of memory and all variables can be unassigned, so that's at least 80% of all opcodes. That strategy will make programs nearly twice as big and half as fast.
Anyway, when you get what I mean by stack unwind, I am sure you will agree it is quite essential.

dcuny said...

You can't simply perform a call stack unwind because traditional try/catch blocks can potentially be nested.

Plus, you need to handle the exception at the local level, where the exception took place. How is unwinding to a prior call helpful, if a local resource needs to taken care of? The prior call can't see into the routine with an exception.

You have to unwind the stack to the context where the exception handling code can execute:

function fdiv(atom a, atom b) 
    return a/b 
end function 
function g(atom c, atom d) 
    return fdiv(c,d) 
end function 
function h(atom e, atom f) 
    return fdiv(e,f) 
end function 
procedure p() 
    try 
        ? g(i,j) 
    catch 
        puts(1,"error in g(i,j)") 
    end try 
end procedure 
procedure q() 
    try 
        ? h(k,l) 
    catch 
        puts(1,"error in h(k,l)") 
    end try 
end procedure 

When you execute/resume at the exception handling code (puts) in p()/q(), the context/call stack must be unwound to that of p/q, not left as it was in fdiv. There may well be a saved context that the exception handler can examine, but the actively running context/stack frame as the exception handling code executes cannot be one from a completely different routine. In Eu, I doubt there is any way round the fact that by the time the puts is executed, a,b,c,d,e, and f may all have been deallocated.

dcuny said...
petelomax said...

All excellent arguments for not adding finally (an awful, stupid, confusing concept) to Euphoria.

Please explain your issue with finally.

I do not like anything which looks like it is doing something else. If I see return x, or throw(blah), then I expect it to do just that, not nip down and execute some other block of code first, or worse, have a return 1 quietly overridden by a return 2 in the finally block.

dcuny said...

For handling system resources, it's essential that they be released correctly. finally guarantees that this will have the opportunity to happen.

How is this bad thing?

I don't understand. Is proper, obvious, clear and straightforward code not going to be executed?
What "guarantee" are you offering that is not already there?
Are you intending to have filtering such that handlers only deal with certain exceptions and implicitly re-throw any not explicitly dealt with?

dcuny said...
petelomax said...

If the main point of exception handling is to separate error handling code from the main logic, what is wrong with putting such things in a separate routine?

The point of structured exception handling is to handle exceptions in a structured manner.

One huge problem with calling cleanup() is that it hasn't got access to the local variables.

How do you close a resource in cleanup() when you don't have the handle to it?

cleanup(handle), or as below

dcuny said...

How do you save the user's current work when #cleanup() can't see the data structure the user was working on?

cleanup(data_structure_the_user_was_working_on), or as below

dcuny said...

How can you handle the exception at a level the exception didn't happen on?

I have no idea what that means. You handle exceptions in the exception handling code, after the call stack has been appropriately unwound to the correct/calling level.
In the above example, the puts() occurs in p() or q(), and not in fdiv() where the error actually happened.

dcuny said...
petelomax said...

It makes me madder than hell to think of such a horrible backward construct being added to Eu, if two simple calls would do.

That's a big "if".

Often, to simple calls won't do.

How you you pass the context of the current call to your cleanup() routine?

cleanup(context), or as below

dcuny said...

Having try/catch scoped to a block inside the offending call solves that problem.

petelomax said...

Of course if you are not re-throwing an exception, which I would have thought is more likely anyway, or are prepared to use a simple flag/return value, <such code> can and should just go after the end try.

I'm not sure I follow you here. Whether you re-throw an exception depends entirely on what the exception was, and how it should be handled.

If you are prepared to use the odd control flag and/or result variable, you can write all your cleanup code locally, and you don't need a cleanup() with umpteen parameters.

dcuny said...
petelomax said...

Of course the other burning question is why someone might want exception handling

Because exceptions need to be handled.

Halting isn't a robust way of handling exceptions.

petelomax said...
  • to write good quality robust code, but without the messiness of error code handling

You've lost me here. try/catch is error handling. Euphoria currently hasn't got solid error handling.
What "error code handling" are you referring to?

try/catch is exception handling. Euphoria has always had perfectly good error code handling, by which I mean open() returns -1, get() returns GET_FAIL, or that you can test for divide by zero first.

Hopefully some parts of what I am saying are helpful, and not too antagonistic.

Pete

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

11. Re: Try/Catch

jaygade said...

Euphoria has recoverable errors, you just have to check for them. "Get()" and "value()" are the best examples of that. Checking if a file exists is another.

No, these aren't errors.

But for the sake of clarity: Euphoria doesn't have recoverable exceptions.

Again, this is typical:

s1[i][j] = s2[k][i] 

It happens often in Euphoria, and there's no nice way to recover from it.

jaygade said...

Unrecoverable errors are ones where your program is wrong and is in an undefined state, so crashing is the correct behavior.

The idea that a program should crash is baffling to me. While it may be a theoretically correct behavior, it's not a desired behavior.

Consider the following use case: A user has created a file using a text editor that can save in formats X, Y and Z. The user has been working on multiple documents for the last half an hour, and are getting ready to save them. Unfortunately, there's a trivial bug in the editor, where the length of the filename is miscalculated as 1 character too long.

The user tries to save a file they've been editing in format X.

Which of the following behaviors would the user desire:

  • The program should crash and the user's data should be lost, protecting the user from potentially corrupted data.
  • The program should crash, but save the files as TMPnnn.zzz which the program will find when it loads again.
  • The program should inform the user that there's a problem saving in format X, but continues to run and allows them to save it in format Y or X.

I can guarantee you option 1 is not the "correct" behavior, either as a user, or a developer.

The second option - save data - is more desirable. But as a user and a developer, I can assure you that I don't want my program to crash on errors. I want it to recover as gracefully as possible. As currently designed, Euphoria doesn't do this, and that's not good.

Arguing Euphoria is saving me from data in an "unknown" state, but that's not entirely accurate. Euphoria has enough information to inform me of what the state of the data is (I can determine the type of error, and where it happened). I should be able to take advantage of this information to decide what the proper course of action, not have some "one size fits all" crash behavior.

As currently written, Euphoria doesn't have an exception recovery mechanism. It has a callback that can be executed on an exception, but it can't recover from that exception.

jaygade said...

Edit: The nice thing about "defer" in Go code is that it puts the release of the resource close to the allocation of the resource, instead of at the bottom of a section of code.

Yes, it's very cool. However, it doesn't map well to Euphoria's IL code model.

- David

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

12. Re: Try/Catch

Hi, Pete.

I appreciate your detailed explanation. I think we're talking about different things, so let me focus on those before muddying the waters:

petelomax said...

Euphoria has always had perfectly good error code handling, by which I mean open() returns -1, get() returns GET_FAIL, or that you can test for divide by zero first.

This is not error handling. open() has a defined behavior of returning a value.

By "error", I mean exactly that: a runtime error, where RTFatal is called, and intentional shutdown of Euphoria is executed.

Consider the following code:

s1[i][j] = s2[j][k] 

If i, j or k is out of range, this is a runtime error in Euphoria.

In a similar vein, the following is not error handling, either:

if i <= length(s1) and j <= length(s1[i]) and j <= length(s2) and k <= length(s2[k]) then 
    s1[i][j] = s2[j][k] 
else 
    -- do something else 
end if 

An "error" happens when code executes and triggers an exception/error.

By "error handling", I mean "take action to recover from a exception, and continue normal execution", not "perform some save routine, and then shut down."

See the use case in my prior post for an explanation why I don't consider shutting down to be a preferred action.

petelomax said...

cleanup(handle), or as below

I'm not sure what cleanup is defined as doing. Is this something you're proposing, or is already in Euphoria?

- David

PS: I just use italics for emphasis, not irritation. smile

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

13. Re: Try/Catch

dcuny said...

This is not error handling.

if i <= length(s1) and j <= length(s1[i]) and j <= length(s2) and k <= length(s2[k]) then 
    s1[i][j] = s2[j][k] 
else 
    return false  -- oh dear, give up 
end if 

I get it. You are using "error" to mean "fatal error" whereas I am using the phrase "error code" to mean exactly that kind of long-winded and tedious code, which to be fair can itself be a source of unwanted errors. Wanting something neater is fine.

dcuny said...

"take action to recover from a exception, and continue normal execution"

Sure. But we ought to be cautious about over-selling this as some easy panacea. There will be cases where the long-winded and tedious approach turns out to be simpler, in the long run. We must still give a user an adequate warning about saving a possibly corrupt document even if it is annoying. Doing and saying nothing can be even more annoying than an abrupt crash. If there is a nasty bug that causes our program to quietly go bananas in the field, we still need to know about it. And so on.

dcuny said...
petelomax said...

cleanup(handle), or as below

I'm not sure what cleanup is defined as doing. Is this something you're proposing, or is already in Euphoria?

Oh, I just meant any-named user-defined routine with whatever parameters you might want or need containing common code factored out from the try and catch blocks.

dcuny said...

PS: I just use italics for emphasis, not irritation. smile

I thought you were having a dig at my use of italics when I first read that blink

Pete

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

14. Re: Try/Catch

petelomax said...

I get it. You are using "error" to mean "fatal error" whereas I am using the phrase "error code" to mean exactly that kind of long-winded and tedious code, which to be fair can itself be a source of unwanted errors. Wanting something neater is fine.

Excellent! smile

petelomax said...

Sure. But we ought to be cautious about over-selling this as some easy panacea. There will be cases where the long-winded and tedious approach turns out to be simpler, in the long run. We must still give a user an adequate warning about saving a possibly corrupt document even if it is annoying. Doing and saying nothing can be even more annoying than an abrupt crash. If there is a nasty bug that causes our program to quietly go bananas in the field, we still need to know about it. And so on.

Actually, try/catch gives you more control, because you can see what the error is, and decide what you want the program to do.

If the try/catch/finally is too complex, another option is to go a more limited route, adding these into the function block:

function foo() 
    -- normal function 
catch sequence error 
    -- catch block 
finally 
    -- finally block 
end function 

It's less flexible than full try/catch/finally blocks. For example, you wouldn't be able to nest try/catch/finally blocks in your code. But it would be a lot simpler to code, and give most of the benefits.

Lua actually provides an even simpler mechanism: pcall() is used to wrap any call that might have an error. But that won't work in Euphoria, because it sees an "=" in an argument list as an equality test, not as an assignment:

-- the parameter to foo() is a comparison in Euphoria 
foo( a = sin(x) ) 

-- the parameter to foo() is an assignment in C 
foo( a = sin(x) ) 

- David

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

15. Re: Try/Catch

Even if Euphoria will be able to resume from fatal errors, the programmers are still required to write the code for it, and still have to think about any possible situation or bug in their code. This makes the code much bigger and much more complex. Of course, still, many errors will be missed, since no one can think about any possible bug or situation on any possible hardware.

The best method to deal with errors is what open() does by returning -1, without needing to check each line of code for fatal error (what QuickBasic did).

But for division-by-zero or out of bound errors... I prefer to use a crash_routine() instead of writing endless and tedious code for this kind - which anyway might work differently on old or new hardware, etc.

I've never seen a professional program works without crashing, on any hardware and situation. So from this point of view - why bother too much...?

One thing I would like to have in Euphoria: fatal error from functions such as current_dir() is ridicules, it should return -1 or "X:." or "." or any value that tells me an error had happened - there is no real reason to crash the program just because it cannot find the current dir! even if it is a system problem.

to sum up: fatal error handling in many cases is useless. but making more and more routines returning an error value (such as current_dir() to return ".") is really really great, and this is how DOS functions actually work usually.

I agree with David though that it's really frustrating for the developer and the user to lose the whole document just because of out-of-bound error while searching a word...! yet these things happening even in the most professional programs because of so many reasons (system, hardware,...). No doubt that a program must be used and debugged for a long time before it can be stable.

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

16. Re: Try/Catch

dcuny said...

I'm wondering how try/catch/finally might be implemented in Euphoria.

In order to further the conversation, here is a paper that has some interesting things to say about exception handling.

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

17. Re: Try/Catch

I'd like any I/O routine to return at least a Boolean value for success/fail, without triggering a fatal error. examples:
ok = puts(fn, "...")
ok = seek(fn, 256)
ok = close(fn)
etc.

It's more code to write, but it's essential. This way I can deal with I/O operations and access to databases immediately. Any user I/O routine must also return this value. This is how DOS I/O functions actually work (except the "critical error" and the Ctrl+C that should have been 'a bit' more friendly in DOS).

Division-by-zero and out-of-bound are up to the programmer to test - as if..then condition and any other part of the code.

Readable, modular and simple code works. Hardware, system and viruses problems are always there to crash or freeze the program anyway.

Last, there is no error handler that can replace a good, simple and maintainable code. Sadly, even professionals are tending to write messy, inconsistent, and undocumented code.
I don't see why an error handler should be a substitute for good coding.

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

18. Re: Try/Catch

DerekParnell said...

In order to further the conversation, here is a paper that has some interesting things to say about exception handling.

Blimey, I knew things could get messy, but that's just insane. Not compensation stacks per se, but the mess they were intended to deal with. If 1,300 bugs in 27 applications (and the rest, given the lengths the authors go to stress false negatives and unchecked exceptions) tells me anything, it is that we are not looking at something we should want to replicate, whether or not someone has designed a clever mop. Even less when the inventors of said mop concede it could go horribly wrong and isn't really any better than disciplined if-close or much simpler logging.

My choice quotes:

that paper said...

While try-catch-finally is conceptually simple, it has the most complicated execution description in the language specification [Gosling et al. 1996] and requires four levels of nested “if ”s in its official English description. In short, it contains a large number of corner cases that programmers often overlook.

that paper said...

In addition to exceptions, finally clauses also interfere with return, break and continue statements in a similar manner.

Some suggested simplifications:

  • Any try/catch construct in Eu traps ALL exception types.
    (Said constructs can of course be nested to any depth, eg my_application/database/raw_io.)
  • Any and all resignalling, if desired, must be explicitly coded.
  • Lastly (I bet you can guess this one) ditch "finally".
    (There is already a perfectly viable alternative in the form of delete_routine().)

Also, I came up with an analogy that might be appropriate, which expresses some of my documentation-level concerns:
Exception handling is a bit like a skiing accident - you get air lifted to hospital, patched up, given time to heal, and eventually shown the door. These things happen as fast as they can, but to be honest it is not a particularly clever way to get a free cup of tea. You've probably only got one ski boot, half a ski, and your salopettes have been incinerated. If you want to try going skiing again, then that's up to you. What never ever happens is that you get an air lift back to the middle of the ski slope to continue your skiing run from where you left off. But at least you're not dead, which you would inevitably be without the help of the medics, and the same for exception handling.

Pete

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

19. Re: Try/Catch

Shian_Lee said...

I don't see why an error handler should be a substitute for good coding.

I don't recall anyone suggesting try/catch could "substitute for good coding".

- David

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

20. Re: Try/Catch

I think we need to be clear that there are three different things here:

  • Error codes return from functions;
  • Ensuring resources are properly cleaned up; and
  • Handling exceptions

While they are related, they aren't the same thing.

Exception handling isn't the same as a routine returning an error code. That's a good thing, and I won't argue against it. But it's a different sort of discussion.

The issue of releasing resources is what finally is all about. The cited paper seems to be suggesting something along the lines of how Go handles resources, by pushing deferred cleanup onto a stack.

Conceptually, finally could be implemented in Euphoria without try/catch, by extending the function/procedure block to include the clause:

function foo() 
   object resource = -1 
 
   -- grab the resource 
   resource = request_resource() 
 
   -- do more stuff 
 
finally 
   if resource != -1 then 
      -- release resource 
   end if 
 
end function 

It feels a bit sloppy to put the cleanup in the finally block, but it does allow you multiple exits with the guarantee that the cleanup code gets called.

It's certainly possible to do something more clever - such as what Go does - while staying in the bounds of how Euphoria executes. Certainly, there are some interesting alternatives.

Things get a bit complex when it starts interacting with try/catch, but it's not an impossible situation to code for.

Hopefully this sort of things gets handled when the dtor of the object gets called, so it's a bit of an exception.

Except, of course, that Euphoria doesn't have proper dtors, which makes it interesting to try to wrap libraries like wxWidgets.

It's been suggested that a QBasic approach could be used. The advantage of try/catch is that the code jumps to the catch block as soon as an error is raised. This means that you don't have to litter your code with exceptions.

This isn't going to replace checking return codes from functions like open(). After all, these aren't exceptions.

- David

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

21. Re: Try/Catch

dcuny said...

I think we need to be clear that there are three different things here:

  • Error codes return from functions;
  • Ensuring resources are properly cleaned up; and
  • Handling exceptions

While they are related, they aren't the same thing.

Agreed in full.

dcuny said...

Exception handling isn't the same as a routine returning an error code. That's a good thing, and I won't argue against it. But it's a different sort of discussion.

Well, it can get kind of blurry. To use the earlier example,

dcuny said...

This isn't going to replace checking return codes from functions like open(). After all, these aren't exceptions.

Except that they are, in other languages like Java. Even worse, some builtin routines in Euphoria fail silently. (E.g. if the filesystem is full, you won't see a return code from puts() warning you that the data you just tried to write was lost. Perhaps there's not much you can do in that case anyways, but it's the principle that counts!) So there's plenty of room for argument that existing routines should have their behavior modified to throw exceptions.

My position is, as a matter of principle, when the language can get away with returning an error code from a routine to signal something, it should do so. If it's something that can't be reasonably handled by a routine returning an error code, that's when it's time to consider throwing an exception....

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

22. Re: Try/Catch

jimcbrown said...

My position is, as a matter of principle, when the language can get away with returning an error code from a routine to signal something, it should do so. If it's something that can't be reasonably handled by a routine returning an error code, that's when it's time to consider throwing an exception....

I feel the same.

If possible, current procedures, such as puts(), may or may-not return error status; this will not break existing code. for example:

puts(fn, "...") -- can be used for demos, simple programs, anything...
ok = puts(fn, "...") -- can be used for more critical data.

About exception handling: before adding such a huge headache to Euphoria, it's better to consider carefully the need for it, and the way that most programmers will use it eventually.

Personally, I'm not sure that I can think about a good example for using an error handler. And cleaning up code can be done in many ways, depends on the situation.

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

23. Re: Try/Catch

dcuny said...
  • Ensuring resources are properly cleaned up; and

...

The issue of releasing resources is what finally is all about. The cited paper seems to be suggesting something along the lines of how Go handles resources, by pushing deferred cleanup onto a stack.

...

It feels a bit sloppy to put the cleanup in the finally block, but it does allow you multiple exits with the guarantee that the cleanup code gets called.

...

Except, of course, that Euphoria doesn't have proper dtors, which makes it interesting to try to wrap libraries like wxWidgets.

To solve the cleaning up resources issue, have a look at delete_routine() that was added in OE4. It does allow you add a destructor routine to an existing object, or rather it creates a new object of the same value with the destructor routine attached.

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

24. Re: Try/Catch

PeteE said...

To solve the cleaning up resources issue, have a look at delete_routine() that was added in OE4. It does allow you add a destructor routine to an existing object, or rather it creates a new object of the same value with the destructor routine attached.

Cool! I'll look into it, thanks.

- David

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

25. Re: Try/Catch

dcuny said...

Conceptually, finally could be implemented in Euphoria without try/catch, by extending the function/procedure block to include the clause:

I haven't read to the end of this thread yet, but conceptually, finally has been implemented in euphoria:

 
function cleanup_foo(sequence stuff) 
    close( stuff[1] ) 
    defrob( stuff[2] ) 
    return 0 
end function 
 
function foo() 
    integer fn = open(...) 
    sequence frob = frob:new() 
    sequence finally = delete_routine( {fn, frob}, routine_id("cleanup_foo") ) 
    --- ... do stuff.... 
    if blah then 
        return 0 -- cleanup_foo(finally) is called here 
    end if 
    --- .... more stuff... 
    return 1 -- cleanup_foo(finally) called here 
end function 
 

Of course, you could simply put the cleanup stuff directly on the resources (and #open()# can do this for you).

man:std_machine.html#_5773_delete_routine

Matt

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

26. Re: Try/Catch

dcuny said...

I don't recall anyone suggesting try/catch could "substitute for good coding".

Behave. I have also expressed precisely that concern earlier in this thread.

Unless we are very clear about this, it is not could or should, but will.

I know you want a fix yesterday, but this is a very real concern and if we do not address it head-on now, then when?

If we just play copy-cat with these "better" languages, what makes you think we won't see 1,300++ bugs per 27 apps?

Don't panic. I am not saying "do nothing", but "get it right".

Pete

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

27. Re: Try/Catch

mattlewis said...

I haven't read to the end of this thread yet, but conceptually, finally has been implemented in euphoria:

The primary issue I've got with that approach is that the context (in the local call) can be lost - especially if you're trying to change the state on something and returning a value.

But in truth, finally isn't my main concern. As others have pointed out, there are interesting approaches taken by other languages that are worth exploring.

- David

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

28. Re: Try/Catch

petelomax said...

Behave. I have also expressed precisely that concern earlier in this thread.

Yes, and it was quite eloquently stated, too:

petelomax said...

Of course the other burning question is why someone might want exception handling:

  • to write good quality robust code, but without the messiness of error code handling
  • to use badly written unstable garbage, and get away with it.

Personally, I genuinely prefer the messiness of error code handling, as it is easier to follow and easier to debug, and of course I worry that (most) people will think they are getting something which is actually really hard to do right, for free.

I've already clarified that exception handling is not the same as error code handling.

As for what I'd written, what I meant to have written was:

dcuny in an alternate universe said...

I don't recall anyone promoting try/catch is suggesting it could "substitute for good coding".

I hope this is more clear. There was no intent to ignore what you'd written earlier.

But did you pay attention to what you're written?

Frankly, it was inflammatory and insulting.

- David

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

29. Re: Try/Catch

dcuny said...

There was no intent to ignore what you'd written earlier.

Apology accepted. tongue

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

30. Re: Try/Catch

dcuny said...
mattlewis said...

I haven't read to the end of this thread yet, but conceptually, finally has been implemented in euphoria:

The primary issue I've got with that approach is that the context (in the local call) can be lost - especially if you're trying to change the state on something and returning a value.

I wouldn't advocate doing that, either. The stuff gets cleaned up automatically whenever it goes away.

dcuny said...

But in truth, finally isn't my main concern. As others have pointed out, there are interesting approaches taken by other languages that are worth exploring.

Definitely. Nevertheless, it's important, I think, to point out that capability, which is a bit outside of the normal IL code paradigm. It's really part of euphoria's garbage collection system, which uses refcounting.

Matt

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

31. Re: Try/Catch

I really don't follow this conversation.

Exception handling is similar to 'goto', just hundred times worse.

Strangely, I don't remember 'exception handling', nor 'goto', existing in PLC programming language (PLC=Programmable Logic Controller). Maybe it's because PLC programming has to deal directly with human lives, while computer programming do not.
I wouldn't put someone's life in the hands of 'exception handler' nor 'goto'.

Exceptions must be treated as error codes returned from routines. Division-by-Zero or Out-of-Bound will occur with or without the presence of Try/Catch in Euphoria, since it's a programmer's fault - not a machine fault.

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

32. Re: Try/Catch

Woke up this morning with a head full of this stuff, in particular the "propagate" idea below, so here goes nuttin:

Draft Technical Spec

Some knowledge of the existing compiler internals is assumed. I have tried to keep this Phix/OpenEuphoria agnostic, and quite deliberately as simple as possible.

A new construct is to be added to the language:

try 
   <block> 
catch <e_name> 
   <block> 
end try 

In addition there will also be a new builtin, throw(atom code).

The call stack frame has a new machine-word-sized field, ehndlr. At startup, in the top-level frame ehndlr is set to 0 (likewise for new threads). Call statements propagate ehndlr as follows:

    ==0 -->  0 
    !=0 --> -1 

The try statement saves the old value then sets it to the machine address of the catch statement. Hopefully a bog-standard local unnamed temporary integer variable can be used for this purpose. That original value must be restored immediately on entry to the catch statement, and on any exit from the try block, including exit/break/continue etc. It is worth noting that a return statement pops the call stack and effectively discards the current ehndlr, thus avoiding the 'exit' issue, even for several nested try statements in the same routine. Obviously a throw statement within a try block should be caught by the immediately following catch statement and needs no ehndlr updates whatsoever. Otherwise, the restoration of ehndlr during normal execution stands out as the most fiddly task, in terms of updates to the compiler, and probably requires a new control flag(/var_id) that is saved/restored at many points during parsing. An exit that jumps out of more than one nested try statement may pose additional challenges, but nothing worse than the exit statement itself already does.

The catch statement traps any exception within the try block or any routines it invokes that is not first caught by another nested try/catch statement. Any exceptions that must be re-thrown must be done so manually. As shown next, on entry the value for <e_name> will be in e/rax.

The existing final exception handler needs something like the following new code added to it:

if ehndlr!=0 then 
    <create content for e_name, ref left in e/rax> 
  ::unwind 
    if ehndlr==-1 then 
        retaddr := unwind 
        return (ie standard dealloc, frame discard, etc) 
    end if 
    mov e_e/rax,e/rax 
    mov e_e/rip,ehndlr 
    mov e/rax,EXCEPTION_CONTINUE_EXECUTION  -- (at catch statement) 
    ret 
end if 
<existing code to generate ex.err> 

Sorry, but I have no idea what the equivalent C/Linux code would be like. Obviously, the ability to resume execution depends on the severity of the fault. For example, if the stack is toast, so is your app.

The exception variable is automatically declared (as a sequence) and is most likely to be just 'e' in actual code. Unlike "for i", there is no reason to have e available after the catch, as should no exception occur it would be unassigned anyway.

At a bare minimum, the sequence e contains an exception code and address, but could also hold a routine number/name, and source code line number. The content may differ between interpreted and compiled applications, and the catch code block should be written to cope accordingly.

The throw routine can be trivially implemented as a fatal error, the only technical difficulty would be getting the code parameter into e instead of #80000003 or whatever.

A new error code is required should throw() be invoked when there is no active handler in the current call stack.

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

33. Re: Try/Catch

petelomax said...

In addition there will also be a new builtin, throw(atom code).

Why an atom and not an object? It could be useful to put lots of stuff in there.

petelomax said...

The call stack frame has a new machine-word-sized field, ehndlr. At startup, in the top-level...

Ugh...sorry, the implementation details lost me. Could you describe how all this would look to a euphoria programmer who knows nothing about the underlying implementation of euphoria?

Matt

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

34. Re: Try/Catch

petelomax,

Please explain me briefly, using simple words, why exception handling became norm in computer programming.

You see, logically it seems to be such a backward technique for programming. Many "exceptions", such as "Drive-not-Ready" are just a Boolean variable that indicates the status of specific hardware; Why then, and how come, this simple Boolean variable turned into a "football game", with Throw, Catch, etc?

If the operating system treats "exceptions" as a simple Boolean flag - why my program must treat it as a football game with many players?

I'm asking you this question because you must know much better then me. It might be a stupid question from others point of view, but I really want a logical and short answer, with practical example(s) - if you don't mind.

I could not imagine an "exception" in industrial PLC programming. A digital sensor can tell only TRUE or FALSE - your program does what ever it wants with this info. An analog sensor can only supply a value within a known range, and again, your program will take it or leave it.
In PLC, "exception" can mean only one thing: The whole factory is on fire, and it's time to call the fire department; i.e. it's not something that the PLC has to deal with.

Why then "some sensors", i.e. some routines, must trigger "exception" in computer programming(?!?) what is the logical reason for this?

Thank you in advance.

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

35. Re: Try/Catch

Shian_Lee said...

Please explain me briefly, using simple words, why exception handling became norm in computer programming.

The obvious example is the web browser. Imagine, say, amazon.com: there is text in various fonts, colours and sizes, lines, icons, pictures, zoom-able pictures, videos, bar charts, bullet points, shrinking and expanding sections, hyperlinks, buttons, etc. Other sites have word documents, pdfs, powerpoint presentations, excel spreadsheets, and so on, all of which can be displayed directly in the browser. You can also add client-side javascript, html5, css and more of the like to the bucket. That is a lot of things that you and I have no control over, that can go wrong in a multitude of different ways.

In my own programs, I almost always use long-handed and tedious error code (aka return value) handling. But I have to accept there is a real and imperfect world out there.

Pete

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

36. Re: Try/Catch

mattlewis said...
petelomax said...

In addition there will also be a new builtin, throw(atom code).

Why an atom and not an object? It could be useful to put lots of stuff in there.

Maybe for version 2. Can we not just get an int (full 32-bit) working first?

mattlewis said...
petelomax said...

The call stack frame has a new machine-word-sized field, ehndlr. At startup, in the top-level...

Ugh...sorry, the implementation details lost me. Could you describe how all this would look to a euphoria programmer who knows nothing about the underlying implementation of euphoria?

OK, the same document with all the hidden back-end magic ripped out:

Draft Technical Spec

A new construct is to be added to the language:

try 
   <block> 
catch e 
   <block> 
end try 

In addition there will also be a new builtin, throw(atom code).

The catch statement traps any exception within the try block or any routines it invokes that is not first caught by another nested try/catch statement. Any exceptions that must be re-thrown must be done so manually.
Edit: Unlike other languages there is only one (non-optional) catch clause.

The exception variable, e in the above, though it can take any valid name that does not already exist in the immediately surrounding scope, is automatically declared as a sequence.

The sequence e always contains at least an exception code and address, but could also hold a routine number/name, and source code line number. The content beyond the first two elements may differ between interpreted and compiled applications, and the catch code block should be written to cope accordingly.

Obviously the application will terminate immediately (just like 9/0) should throw() be invoked when there is no active handler (try/catch construct) in the current call stack.

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

37. Re: Try/Catch

petelomax said...
Shian_Lee said...

Please explain me briefly, using simple words, why exception handling became norm in computer programming.

The obvious example is the web browser. Imagine, say, amazon.com: there is text in various fonts, colours and sizes, lines, icons, pictures, zoom-able pictures, videos, bar charts, bullet points, shrinking and expanding sections, hyperlinks, buttons, etc. Other sites have word documents, pdfs, powerpoint presentations, excel spreadsheets, and so on, all of which can be displayed directly in the browser. You can also add client-side javascript, html5, css and more of the like to the bucket. That is a lot of things that you and I have no control over, that can go wrong in a multitude of different ways.

In my own programs, I almost always use long-handed and tedious error code (aka return value) handling. But I have to accept there is a real and imperfect world out there.

Pete

This doesn't actually answer the question. The analogy is a very good one (showing why/how popular things are not necessary the best way), but not how they became popular in the first place.

To directly answer the question, exception handling became more common because, from the end-user's point of view, it's easier.

It is a lot easier for a novice programmer to come up with a functional program, without having to deal with the complexities of properly handling errors, by abusing try/catch.

That said, I think try/catch does have its place, just like goto. But also like goto, it can be abused. At some point though, it becomes counter-productive to protect other people's feet from their own shooters.

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

38. Re: Try/Catch

jimcbrown said...

This doesn't actually answer the question. The analogy is a very good one

True/thanks, and ... SLAPS FOREHEAD... there is another I have used quite a bit, by which I mean a lot:

x = s[i] 

(as one of many many similar examples) can be implemented as either:

if not assigned(i) then error(...) end if 
if not assigned(s) then error(...) end if 
x = s[i] 

or

x = s[i] 

and when an exception occurs, figure out the cause -- the latter is, for obvious reasons, significantly faster, in all the non-fatal-error cases!
(in truth, in practice, at the low-level asm level, due to occasional dependencies and/or AGI stalls, it is not always the case, so I often tried both and chose the faster.)


It is perhaps telling that I've done that all over the shop in the back end, because I had to for performance, but never once though it would be a good idea in hll...

Oh yes, I am expecting some juicy comments on that one.

It is quite simply because I prize so highly that very same fast fail mentality that dcuny and others despise.

Pete

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

39. Re: Try/Catch

petelomax said...
mattlewis said...
petelomax said...

In addition there will also be a new builtin, throw(atom code).

Why an atom and not an object? It could be useful to put lots of stuff in there.

Maybe for version 2. Can we not just get an int (full 32-bit) working first?

I have 63-bit integers. I don't need a 32-bit integer. grin

petelomax said...
mattlewis said...
petelomax said...

The call stack frame has a new machine-word-sized field, ehndlr. At startup, in the top-level...

Ugh...sorry, the implementation details lost me. Could you describe how all this would look to a euphoria programmer who knows nothing about the underlying implementation of euphoria?

OK, the same document with all the hidden back-end magic ripped out:

Thanks. That all sounds pretty reasonable. Though I still disagree on the argument for throw(). I think this should be fairly straightforward for interpreted code. Not sure how you get this in the translator.

Matt

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

40. Re: Try/Catch

jimcbrown said...
petelomax said...
Shian_Lee said...

Please explain me briefly, using simple words, why exception handling became norm in computer programming.

The obvious example is the web browser. Imagine, say, amazon.com: there is text in various fonts, colours and sizes, lines, icons, pictures, zoom-able pictures, videos, bar charts, bullet points, shrinking and expanding sections, hyperlinks, buttons, etc. Other sites have word documents, pdfs, powerpoint presentations, excel spreadsheets, and so on, all of which can be displayed directly in the browser. You can also add client-side javascript, html5, css and more of the like to the bucket. That is a lot of things that you and I have no control over, that can go wrong in a multitude of different ways.

In my own programs, I almost always use long-handed and tedious error code (aka return value) handling. But I have to accept there is a real and imperfect world out there.

Pete

This doesn't actually answer the question. The analogy is a very good one (showing why/how popular things are not necessary the best way), but not how they became popular in the first place.

To directly answer the question, exception handling became more common because, from the end-user's point of view, it's easier.

It is a lot easier for a novice programmer to come up with a functional program, without having to deal with the complexities of properly handling errors, by abusing try/catch.

That said, I think try/catch does have its place, just like goto. But also like goto, it can be abused. At some point though, it becomes counter-productive to protect other people's feet from their own shooters.

Thank you.

These answers are really ambiguous for me. Honestly, I don't feel that I got an answer at all.

Once I've programmed a PLC with maybe hundreds of INPUTs and OUTPUTs. That PLC controlled many engines, sensors, and machines with huge power, in the tyres industry.
In these machines, something goes wrong almost all the time. Also, these machines are depending on each other's proper operation, in a similar way to a web browser.
Since PLC works in a very logical way, I found it very simple to write the program; I just needed time. Most decisions in a PLC program are taken only based on Boolean flags, which makes the program very clear.

I don't know why computer program has to break its own logic and fall into a dangerous game of throw and catch. In more critical programs, such as PLC programs, this considered to be the most non-robust behaviour.

Programming a PLC is different then programming computer, in a way that the program must work; and if it doesn't: you call the programmer back to finish his work. Machines don't understand bugs, and improper behaviour of machine can cause a big accident.

Pete gives an example of x = y[z]. Out-of-bound and not initialise variables happen anyway, with or without exception handler. This is the main difference between PLC programming and computer programming; In PLC programming the programmer must take responsibility for his mistakes ("bugs"), while in computer programming bugs are part of any program.

I used error handling in QuickBasic many times before, because QuickBasic don't supply returned error codes - it simply crashes.

Using error handlers in QuickBasic was the worst experience from that language. And at those days QuickBasic worked on DOS(!).
Fatal error such as "Illegal function call" is a bug that I, the programmer must fix - not a pathetic error handler that sends the user back to the main menu after two hours of hard work.

Fatal error such as "Drive-not-Ready" are the most ridiculous; Drive not ready - so what??? In PLC programming if a digital sensor tells me that the tank is not empty then my program simply waits until the timer stops, and then turns on a red light on the control panel. that's it. simple.

Computer is a machine. And it may be connected to other machines. Checksums, error codes, and branching statements are much more solid and robust programming behaviour, for truly critical operations. That's why there is no "fatal error" in PLC, since PLC should never stop its operation. There might be an adjustable watchdog that continuously test the proper operation of the PLC (similar to computer BIOS chip), and stops the PLC in case of improper operation - but PLCs are built to be reliable and robust.

From my personal experience error handler is the hardest to write and the most fragile programming method. It also forces the programmer to use it - as in QuickBasic - even if he really wishes to avoid it.

I really don't understand the answers since my experience proves the opposite...

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

41. Re: Try/Catch

Shian_Lee said...

Thank you.

These answers are really ambiguous for me. Honestly, I don't feel that I got an answer at all.

The results of popularity contests are often baffling.

Shian_Lee said...

Once I've programmed a PLC ... In these machines, something goes wrong almost all the time.

I've worked with PLCs as well. I feel your pain.

Shian_Lee said...

I don't know why computer program has to break its own logic and fall into a dangerous game of throw and catch. In more critical programs, such as PLC programs, this considered to be the most non-robust behaviour.

Uh, trapping and handling faults (the PLC verion of try-catch) is actually very common. I speak from experience here, but don't just take my word for it: http://www.plctalk.net/qanda/showthread.php?t=68857

Shian_Lee said...

Programming a PLC is different then programming computer, in a way that the program must work; and if it doesn't: you call the programmer back to finish his work. Machines don't understand bugs, and improper behaviour of machine can cause a big accident.

This is the main difference between PLC programming and computer programming; In PLC programming the programmer must take responsibility for his mistakes ("bugs"), while in computer programming bugs are part of any program.

Again, speaking of experience, some complex PLC programs can have bugs that remain hidden for years until some obscure set of complex conditions are triggered. Just because it runs on a PLC is no exception - software is software, and complex software is never bug free, PLC or otherwise.

Shian_Lee said...

That's why there is no "fatal error" in PLC, since PLC should never stop its operation. There might be an adjustable watchdog that continuously test the proper operation of the PLC (similar to computer BIOS chip), and stops the PLC in case of improper operation - but PLCs are built to be reliable and robust.

PLCs do have "fatal errors", they're just called faults. If a major fault is unhandled, the PLC cpu will stop and someone will need to reset the PLC (the equivalent of a cold reboot). Again, don't just take my word for it: http://www.plctalk.net/qanda/showthread.php?t=68857

And yes, I know from experience that PLCs have faulted and stopped in the middle of an important hours-long operation - and then someone has to reset it and try and pick up where things were left off. It's a lot of extra work when this happened, no one wants it to happen, there's a lot of incentive to make sure it doesn't happen, but it still happens.

Shian_Lee said...

I really don't understand the answers since my experience proves the opposite...

I don't understand where your experience comes from.

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

42. Re: Try/Catch

jimcbrown said...

I don't understand where your experience comes from.

My experience comes from working 10 hours a day since I was 14 years old.

And I still think that your last answer is avoiding my question.

Any sane human being knows that ANY machine, including PLC, can fail. And in the PLC area there are many methods and backups for this case, yet accidents happen, and yet many programmers and electricians are careless.

I am offering here to consider error handling from a different point of view. Take it or leave it.

Excuse me of being rude, but I wonder where your experience comes from.

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

43. Re: Try/Catch

Shian_Lee said...
jimcbrown said...

I don't understand where your experience comes from.

My experience comes from working 10 hours a day since I was 14 years old.

Relevance?

Shian_Lee said...

And I still think that your last answer is avoiding my question.

I don't know how to make it any clearer - try/catch became popular among novice programmers because it appeared to be easier.

If that doesn't answer your question, please restate it.

Shian_Lee said...

Any sane human being knows that ANY machine, including PLC, can fail. And in the PLC area there are many methods and backups for this case, yet accidents happen, and yet many programmers and electricians are careless.

I am offering here to consider error handling from a different point of view.

You seemed to be saying that in PLC programming, one was not suppose to use a concept like try-catch in PLCs.

Shian_Lee said...

I don't know why computer program has to break its own logic and fall into a dangerous game of throw and catch. In more critical programs, such as PLC programs, this considered to be the most non-robust behaviour.

That's why there is no "fatal error" in PLC, since PLC should never stop its operation.

I just pointed out that this is wrong, and PLC programming often makes use of the try-catch concept (albeit under a different name).

Shian_Lee said...

Take it or leave it.

Excuse me of being rude, but I wonder where your experience comes from.

From actually working with PLC code.

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

44. Re: Try/Catch

Let's stop this nonsense.

You have two basic ways:
1. exception handler.
2. error codes from routines.

That's all I can think about. Choose your way.

Time for Taekwondo now.

Bye and thank you.

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

45. Re: Try/Catch

I've been a controls engineer for decades.

RSLogix 5000 for Allen-Bradley Logix line of PLCs (or PACs - Programmable Automation Controller) has a special folder called "Controller Fault Handler". This is for special code that, surprisingly enough, is for CATCHING major faults (i.e. not if a sensor isn't acting correctly, but if, say, a whole input module is dead), then handling the fault in an, hopefully, orderly fashion, such as shutting the machine down gracefully if possible.

Siemens does the same thing with special Function Blocks

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

46. Re: Try/Catch

mattlewis said...
petelomax said...
mattlewis said...
petelomax said...

In addition there will also be a new builtin, throw(atom code).

Why an atom and not an object? It could be useful to put lots of stuff in there.

Maybe for version 2. Can we not just get an int (full 32-bit) working first?

Though I still disagree on the argument for throw().

I concede. Once I thought of it, catch e ... throw(e) is a fairly compelling argument.

Here is a first stab at defining what an exception innards might look like (with something of a Phix bias)

catch e

The following constants can be used to examine the contents of an exception

  1. E_CODE (atom) hardware and operating system exceptions usually have bit #800000000 set, user exceptions can be any atom value.
  2. E_ADDR (atom) a machine address indicating where the exception ocurred
  3. E_RTN (integer) equivalent to routine_id(), an index to the symbol table identifying the routine (optional)
  4. E_LINE (integer) the source code line matching E_ADDR in E_RTN (optional)
  5. E_NAME (string) the human-readable name of E_RTN (optional/may be integer)


Only the first two elements are guaranteed to be present. Further user-defined elements may also be present. There is no upper limit to the length of an exception or the amount of detailed information it can contain, however the first five elements have predefined meanings.

throw(object e, object e6={})

if e6!={} then e must be atom and throw(e,e6) is equivalent to throw({e,-1,-1,-1,-1,e6}), modified as below.
if e is an atom, throw(e) is equivalent to throw({e,-1,-1,-1,-1}), modifed as below.
if e is a string, throw(e) is equivalent to throw({0,-1,-1,-1,-1,e}), "" (probably Phix only, and same as throw(0,"string")).
Otherwise e must be a sequence containing at least the first two elements, E_CODE and E_ADDR, type safe as above and any user-defined data in e[6..$].

  • if e[E_ADDR] is -1 it is replaced with the return address from the throw() call.
  • if e[E_RTN] is -1 it is replaced with a routine number from the current call stack.
  • if e[E_LINE] is -1 and e[E_ADDR] was -1, then the (new) value of e[ADDR]-1 is mapped to a line number in e[E_RTN] and stored in e[E_LINE].
  • if e[E_NAME] is -1 and e[E_RTN] was -1, the name is retrieved from the symbol table, however (in Phix) that will be a meaningless ttree index when interpreting and a proper string only when compiled.

Note that for hardware and operating system exceptions, e[E_ADDR] may correspond to a machine instruction emitted for the source code line, or the first byte of the next line, or somewhere deep in the heart of say kernel32.dll, or part of the internal workings of c_func, and therefore (in early versions at least) e[E_LINE] may be quite wrong. Such cases will need to be fixed on an ad hoc basis, either by subtracting 1 from e[E_ADDR] for selected e[E_CODE], emitting a judicious nop instruction, or hunting about in the call stack for the first thing that makes sense. If all such efforts are in vain, the runtime reserves the right to give up and return a two-element sequence. In short, you should not become over-reliant on the optional values e[E_LINE] and e[E_NAME]. You can however populate a throw() statement with made-up values.


mattlewis said...

I think this should be fairly straightforward for interpreted code. Not sure how you get this in the translator.

Let me know if you have any ideas, I'd prefer not to introduce unsurmountable incompatibilities.

Pete

edit (one month later): just noticed I missed out the constant E_USER=6.

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

47. Re: Try/Catch

evanmars said...

I've been a controls engineer for decades.

RSLogix 5000 for Allen-Bradley Logix line of PLCs (or PACs - Programmable Automation Controller) has a special folder called "Controller Fault Handler". This is for special code that, surprisingly enough, is for CATCHING major faults (i.e. not if a sensor isn't acting correctly, but if, say, a whole input module is dead), then handling the fault in an, hopefully, orderly fashion, such as shutting the machine down gracefully if possible.

Siemens does the same thing with special Function Blocks

Since you are an engineer, let's be honest. How many controllers are out there? How many of them are truly able to deal with failures? How many programmers are actually care about it?
How many electricians are connecting the controller to the E-stops as recommended?

I've seen a big machine, made in Germany, where many, actually all, the E-stops were connected in serial - not parallel. Again: made in Germany. And with no external power supply for double safety.

We all are saving money, time and... disappointments. After all, even if the controller part is perfect - in case of emergency stop there's no way to release the hand/head of the worker from the conveyor-belt since the designers of the machine 'forgot' to supply manual reverse.

I've never used any exception handler in controller, and among the other programmers I knew, I'm considered to be very cautious.

At least we still have Euphoria 3.1.1 to enjoy the real thing. And we can kill the exceptions by calling DOS interrupts directly where needed. Machines love DOS.

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

48. Re: Try/Catch

Shian_Lee said...

[...]

I've never used any exception handler in controller, and among the other programmers I knew, I'm considered to be very cautious.

At least we still have Euphoria 3.1.1 to enjoy the real thing. And we can kill the exceptions by calling DOS interrupts directly where needed. Machines love DOS.

Hi

what is your problem?

You do not like excetpion handlers? So, don't use it. That's all.
Don't like 'goto'? Don't use it..
Don't like 'OOP'? Don't use it.

For PLC's there is now CodeSys V3, used by over 300 mostly small to medium manufacturer, on the market since about 5 years.
It does support OOP and exception handling. But you do not have to use it!. You can still program like in the 80's
Even S7 from Siemens support this.

Giving people the freedom of choice is very important (from my point of view).

Go to the PC side (mean Desktop Computer). FPC (FreePascalCompiler) supports OOP and Exceptions and Standard Errorhandling.

But again, you do not have to use it...
You can still program like 30 years before, it works...
FPC gives you the choice.
It also supports a DOS Compiler.

Most of this is also true for FreeBasic, even Phyton (ok, no dos) etc.

Euphoria is really nice, and easy to use but a little evolution want hurt it.

Giving the People the choice to choose what they want is is really important.

Andreas

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

49. Re: Try/Catch

dcuny said...

I'm wondering how try/catch/finally might be implemented in Euphoria.

Setting aside, for the moment, the examination of any compelling reasons to implement this concept into the language, I suggest a much more simpler approach - maybe a more Euphoric approach I think.


  • A new procedure (let's call it 'trap_ex' for now) that takes one parameter - either the name of a routine, or a routine_id. This procedure registers an exception handler. The handler (the routine it identifies) would be a function that gets control when the run time Euphoria (back-end) calls RTFatal(). These would always be non-recoverable exceptions, meaning that after the handler has finished, the application will be terminated. Control does not return to the application.
  • Make RTFatal() callable from user written code. This effectively implements the 'throw' concept.
  • Routines that have been registered by trap_ex() will be added to a chain of such routines. RTFatal() will call each in reverse order of registration until the first of these functions return a non-zero integer. Then any further routines in the chain are not called and the application terminates immediately.
  • A new procedure (let's call it 'untrap_ex' for now) that takes one parameter - either the name of a routine, or a routine_id. This procedure deregisters an exception handler. The handler (the routine it identifies) is removed from the RTFatal() call chain.
  • RTFatal() should be enhanced to provide better exception data to the registered handlers.
new topic     » goto parent     » topic index » view message » categorize

50. Re: Try/Catch

DerekParnell said...
dcuny said...

I'm wondering how try/catch/finally might be implemented in Euphoria.

Setting aside, for the moment, the examination of any compelling reasons to implement this concept into the language, I suggest a much more simpler approach - maybe a more Euphoric approach I think.

The concept is sound and it'd be easier to implement. What's not to like?

DerekParnell said...

Control does not return to the application.

The issue here would be, in dcuny's original example, that there is still no way to handle 'x = s[i]' effectively without having the program (eventually) crash. This is still an improvement (as least you have a last-ditch chance to save any unsaved data), but you can't deal with unexpected exceptions and pick off from where you left off. Maybe that's a good thing.

Still, I don't think it'd be technically hard to make it so that, if all trap handlers return the OK result, to return control to the following statement or something... maybe one could specify a goto label along with the trap handler routine id, that would only be used if the trap was triggered within scope of that label. So, we can make this more flexible. (Not saying that we should, necessarily, just that we can if it is decided that that would be the way to go.)

DerekParnell said...
  • Make RTFatal() callable from user written code. This effectively implements the 'throw' concept.

We already have crash() for that. Or do you mean a resume_trapped_ex() which could only be called from inside the trap handler?

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

51. Re: Try/Catch

jimcbrown said...

What's not to like?

Haha ... I'm sure someone will object. Human nature I guess.

jimcbrown said...
DerekParnell said...

Control does not return to the application.

The issue here would be, in dcuny's original example, that there is still no way to handle 'x = s[i]' effectively without having the program (eventually) crash. This is still an improvement (as least you have a last-ditch chance to save any unsaved data), but you can't deal with unexpected exceptions and pick off from where you left off. Maybe that's a good thing.

The thing here is that the example is not an exception, in my opinion. If the causes an error, then I'd regard it as a case of invalid data. In which case, 'data validation before usage' is a better approach.

I regard exceptions as those things that originate from outside the control of an application and that cannot be effectively anticipated by it. That's why the application should terminate, possibly after doing some damage control/mitigation first.

Data errors can be best dealt with by validating data coming into the application at the earliest practical point it enters the application.

Uninitialized or incorrectly initialized variables should be discovered during testing. One certainly should find those mistakes before your customers do. Unittests to the rescue!

jimcbrown said...
DerekParnell said...
  • Make RTFatal() callable from user written code. This effectively implements the 'throw' concept.

We already have crash() for that. Or do you mean a resume_trapped_ex() which could only be called from inside the trap handler?

Ah... I forgot about crash(). That would do nicely - one less thing to implement. smile

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

52. Re: Try/Catch

DerekParnell said...
  • A new procedure (let's call it 'trap_ex' for now) that takes one parameter - either the name of a routine, or a routine_id. This procedure registers an exception handler. The handler (the routine it identifies) would be a function that gets control when the run time Euphoria (back-end) calls RTFatal(). These would always be non-recoverable exceptions, meaning that after the handler has finished, the application will be terminated. Control does not return to the application.

Sounds like crash_routine().

Matt

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

53. Re: Try/Catch

OK, to set the tone, for me three things are certain: death, taxes and when I see (in C++)

int main(int argc, char **argv) { 
  try { 
  } 
  catch (...) { 
  } 
} 

Then I know that I am facing some seriously badly written and almost completely untested garbage code.
Obviously for some small part, fair enough, but the whole app? - alarm bells.

I have stated that I prefer long-winded and tedious error code handling over exceptions.

Yet I'm proposing designs for the latter - why?

  1. It's not really my place to deny others
  2. There are real user experience benefits
  3. There are valid cost benefits (crappy code is part of that)
  4. There are even performance gains to be had (and hits to suffer)
  5. If you don't like it you don't have to use it


DerekParnell said...

These would always be non-recoverable exceptions .. Control does not return to the application.
a chain of such routines

Not making much sense to me so far.

DerekParnell said...

Haha ... I'm sure someone will object. Human nature I guess.

You know me too well.

DerekParnell said...

The thing here is that the example is not an exception, in my opinion.

granted.

DerekParnell said...

I regard exceptions as those things that originate from outside the control of an application and that cannot be effectively anticipated by it. That's why the application should terminate, possibly after doing some damage control/mitigation first.

That might be a better definition of exception, but I don't get that the only response to things beyond your control is to die.

Pete

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

54. Re: Try/Catch

DerekParnell said...

I regard exceptions as those things that originate from outside the control of an application and that cannot be effectively anticipated by it. That's why the application should terminate, possibly after doing some damage control/mitigation first.

Imagine I've got a program that generates a .wav file as output. I find that someone's written a library that generates .wav files from a sequence.

Hurrah! Only there's the possibility that perhaps the developer didn't do adequate range checking. If we use your definition of exceptions, I've got a couple options:

  1. I can read through the library, making sure that it traps all possible errors, or
  2. I can write my own library, just in case, or
  3. I can choose not to use Euphoria

While in theory I can anticipate range errors, this is tricky in practice.

I'd rather be using a language that allows me to gracefully recover from exceptions, than one that crashes.

As pointed out, if you chose not to use that feature... you still get an immediate failure.

- David

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

55. Re: Try/Catch

Just thought of a slightly outside-the-box example: SETI

You collect truly vast amounts of data, inevitably some of it garbage/static.
You have two algorithms:
A: a truly beautiful, well written and robust bit of code with full error checking
B: a dirty and bug ridden horror that does the job >99% of the time and fails catastrophically on the rest, but is maybe 10x faster

The best solution is clearly to throw everything at B, and the things it crashes on at A.

Of course you could even deliberately hack an A to obtain the desired properties of B on purpose.

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

56. Re: Try/Catch

dcuny said...

A bit more detail on Go's error handling in Euphoria.

In Euphoria, as soon as an error is reached, the code halts. End of game, that's it.

Let's imagine Euphoria with Go's error handling.

Returning multiple values would require some major changes to Euphoria, so (for the sake of discussion), let's imagine that it's essentially the same as BASIC, and the error result it returned in a global variable. So you could do something like:

... 
someRoutine(a, b, c) 
if error then 
   -- handle the error 
end if 

Now, if you didn't check for the error condition, Euphoria would happily ignore all errors. Since would break a code model that people currently depend on, you'd probably need something along the lines of BASIC's on error continue, which tells BASIC not to halt on errors. So let's imagine that there was a routine called on_error_continue(flag) which accepted a true/false value. So you could write:

-- a typed variable 
atom x = 0 
 
-- don't halt on errors 
on_error_continue(1) 
 
-- do something that causes an exception 
x = "assigning strings to atoms fails!" 
 
if error then 
   printf(1, "The error was %s\n", {error_text}) 
end if 

This would be more or less backward compatible. Is this what you had in mind?

For me, this is considerably less good than try/catch. The reason is perhaps a bit counter-intuitive: I don't know where my code is going to encounter an error. And in Euphoria, the error is likely to be an indexing error of some sort:

s1[i][j] = s2[k][j] 

So unless I check the condition of error after every operation, I've got a good chance of performing a couple more operations before I notice things have gone wonky.

With try/catch, my code immediately jumps to the catch clause before more things can go awry.

Now, you could argue that since Euphoria doesn't do pass by reference, data won't be corrupted until the return from the function. (Unless, of course, you're using global variables).

Go's defer is slick, but I think it would be a hard sell. Doing something like this doesn't really have an analog in Euphoria:

func f() { 
    defer func() { 
        if r := recover(); r != nil { 
            fmt.Println("Recovered in f", r) 
        } 
    }() 
    fmt.Println("Calling g.") 
    g(0) 
    fmt.Println("Returned normally from g.") 
} 

Here, you've got an anonymous function potentially being pushed onto the stack for execution on exit of func(). This is entirely unlike how Euphoria works.

Another example from Go:

func c() (i int) { 
    defer func() { i++ }() 
    return 1 
} 

The function c() will push an variable number of anonymous functions (only known at runtime) onto the defer stack to be executed on exit of c(). And the parameters to these functions are dynamically evaluated before they are pushed onto the defer stack.

It's very slick, but it would require major changes to Euphoria.

I can't see this happening. While it could be coded in the interpreted version, getting something similar for the C compiler is another matter.

- David

What you wrote here is English, but I don't understand any of it.

Where does "on error continue" come in?

someroutine(a, b, c) 

is a procedure which doesn't return any values. So there is no "if error" available.

Euphoria is capable of returning multiple values by design, so I don't understand this post.

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

57. Re: Try/Catch

dcuny said...

The idea that a program should crash is baffling to me. While it may be a theoretically correct behavior, it's not a desired behavior.

Consider the following use case: A user has created a file using a text editor that can save in formats X, Y and Z. The user has been working on multiple documents for the last half an hour, and are getting ready to save them. Unfortunately, there's a trivial bug in the editor, where the length of the filename is miscalculated as 1 character too long.

The user tries to save a file they've been editing in format X.

Which of the following behaviors would the user desire:

  • The program should crash and the user's data should be lost, protecting the user from potentially corrupted data.
  • The program should crash, but save the files as TMPnnn.zzz which the program will find when it loads again.
  • The program should inform the user that there's a problem saving in format X, but continues to run and allows them to save it in format Y or X.

I can guarantee you option 1 is not the "correct" behavior, either as a user, or a developer.

A bug in the editor should result in a crash, and the developer should correct the bug. If possible, the reason for the bug should be communicated to the user, but regardless if an incorrect result can occur then the user is better served by a crash then by the output of incorrect data.

Of course, the class of errors represented by an illegal filename would be classified as a recoverable error, not necessarily an irrecoverable one. It's a situation which depends on user input and should be checked by code so...

I'm not sure that your example is valid.

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

58. Re: Try/Catch

Why Go gets exceptions right, and C++ and Java get them wrong: http://dave.cheney.net/2012/01/18/why-go-gets-exceptions-right

In Euphoria, the same technique can be used by returning a sequence or object instead of a concrete atom or integer.

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

59. Re: Try/Catch

dcuny said...
DerekParnell said...

I regard exceptions as those things that originate from outside the control of an application and that cannot be effectively anticipated by it. That's why the application should terminate, possibly after doing some damage control/mitigation first.

Imagine I've got a program that generates a .wav file as output. I find that someone's written a library that generates .wav files from a sequence.

Hurrah! Only there's the possibility that perhaps the developer didn't do adequate range checking. If we use your definition of exceptions, I've got a couple options:

  1. I can read through the library, making sure that it traps all possible errors, or
  2. I can write my own library, just in case, or
  3. I can choose not to use Euphoria

While in theory I can anticipate range errors, this is tricky in practice.

I'd rather be using a language that allows me to gracefully recover from exceptions, than one that crashes.

As pointed out, if you chose not to use that feature... you still get an immediate failure.

- David

I don't understand. Your program takes input, uses a library which returns incorrect output, and so you should provide some random or guessed output regardless? If the library is bad, then the application should crash and you should provide feedback to the library developer. If he or she is unavailable then you should no longer use that library, or else correct it on your own.

These issues should certainly be identified by testing prior to deployment.

If your program RECEIVES incorrect input, then it should detect it and report it back to the user.

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

60. Re: Try/Catch

Summary:

Inputs to a program must be checked for validity or corruption. Bad input should result in an error condition which should be handled as early in the program as possible.

Logic errors in a program should result in a crash and should never escape developer testing; however if they do then a crash report should be sent back to the developer. In such case, the program should produce no usable incorrect output to the user.

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

61. Re: Try/Catch

jaygade said...

A bug in the editor should result in a crash, and the developer should correct the bug. If possible, the reason for the bug should be communicated to the user, but regardless if an incorrect result can occur then the user is better served by a crash then by the output of incorrect data.

So it's better that I lose all my data, and be protected from an exception I could possible recover from?

What if the data were a 15 minute recording?

From a UI perspective, a program crashing is never the correct thing to do.

jaygade said...

I'm not sure that your example is valid.

So an example that happened to me isn't valid?

- David

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

62. Re: Try/Catch

dcuny said...
jaygade said...

A bug in the editor should result in a crash, and the developer should correct the bug. If possible, the reason for the bug should be communicated to the user, but regardless if an incorrect result can occur then the user is better served by a crash then by the output of incorrect data.

So it's better that I lose all my data, and be protected from an exception I could possible recover from?

What if the data were a 15 minute recording?

From a UI perspective, a program crashing is never the correct thing to do.

If the developer wrote bad code, then yes, that is the correct behavior.

dcuny said...
jaygade said...

I'm not sure that your example is valid.

So an example that happened to me isn't valid?

- David

It did seem contrived. If it happened to you, then the one to blame for the fault is the developer, not the language.

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

63. Re: Try/Catch

jaygade said...

It did seem contrived.

It wasn't, but thanks for doubting me just in case.

jaygade said...

If it happened to you,

If it happened to me? Again, thanks for saying you don't believe me.

jaygade said...

...then the one to blame for the fault is the developer, not the language.

And since I was the developer, thanks again.

It's nice to be treated with such condescension.

- David

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

64. Re: Try/Catch

petelomax said...
  1. It's not really my place to deny others
  2. There are real user experience benefits
  3. There are valid cost benefits (crappy code is part of that)
  4. There are even performance gains to be had (and hits to suffer)
  5. If you don't like it you don't have to use it

This. Especially #5.

+1000

On the other hand, if you want Euphoria to be your own private language, by all means don't implement features common to other languages, and then tell people that Euphoria is superior because it lacks these features. And be sure to cast aspersions on their coding skills while you're at it.

- David

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

65. Re: Try/Catch

mattlewis said...

Sounds like crash_routine().

Yes ... sounds like ... and with a little bit of change could do the job.

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

66. Re: Try/Catch

dcuny said...

Imagine I've got a program that generates a .wav file as output. I find that someone's written a library that generates .wav files from a sequence.

Hurrah! Only there's the possibility that perhaps the developer didn't do adequate range checking. If we use your definition of exceptions, I've got a couple options:

  1. I can read through the library, making sure that it traps all possible errors, or
  2. I can write my own library, just in case, or
  3. I can choose not to use Euphoria

While in theory I can anticipate range errors, this is tricky in practice.

I'd rather be using a language that allows me to gracefully recover from exceptions, than one that crashes.

As pointed out, if you chose not to use that feature... you still get an immediate failure.

Ok, so don't use Euphoria.

However, there comes a point at which one must simply trust the code written by others. You do it already ... how do we know what machine code the C compiler actually generates ... perhaps it could generated incorrect stuff? So with this hypothetical library, it is not designed to fail so if it does, either get it fixed or stop using it. But let's say it failed and your code actually got control at the point of failure ... what sensible thing can your program do to carry on? Basically it boils down to --- don't call the library routine with that same data. You call it with different data but what data? And why would different data not also potentially cause a failure again? Your trust in this failing library must now extended to any call you make to it, thus effectively invalidating the use of the library for anything.

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

67. Re: Try/Catch

petelomax said...
DerekParnell said...

I regard exceptions as those things that originate from outside the control of an application and that cannot be effectively anticipated by it. That's why the application should terminate, possibly after doing some damage control/mitigation first.

That might be a better definition of exception, but I don't get that the only response to things beyond your control is to die.

My argument goes something like this ...
Your application was trying to do something useful. Something unanticipated and outside of your program's control caused things to stuff up. So what is you program going to do so it can succeed in doing that useful thing? Now I'm not talking about logic errors in your code, or invalid data being presented to your program, or error codes that can be returned by functions you call. I'm talking about exceptions - rare events that for the most part you can safely avoid writing special code to handle.

The Euphoria run-time component has many potential calls to RTFatal() and the vast majority would be triggered by bad data or bad coding. Things that appropriate testing should be discovering. They occur when the application is demonstrably doing the wrong thing and the code needs to be corrected. Failing the application is not a bad course of action with these.

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

68. Re: Try/Catch

dcuny said...

So it's better that I lose all my data, and be protected from an exception I could possible recover from?

Of course it isn't better, but that isn't the argument being put forward, is it?

Let's take just a few scenarios and you can explain what recovery is about.

  • You attempt to save the file you've been editing for the last hour, and the editor traps an exception and pops up a dialog window with "** Unable to save file - Retry or Cancel".
  • You attempt to save the file you've been editing for the last hour, and the editor writes out random bytes instead and doesn't say a thing. The screen still shows your correct text. This continues a few times until the eventually editor traps an exception and pops up the dialog box with "Invalid character found in file - Retry or Cancel."
  • You attempt to save the file you've been editing for the last hour, and the computer's power fails. You manage to power it up again and start the editor but it traps an exception and pops up a dialog window with "** Unable to open file - Retry or Cancel".
  • You attempt to save the file you've been editing for the last hour, and the editor saves it correctly. You continue editing for a few more hours, pressing Ctrl-S every so often and it is all going well. Finally, sleep beacons and you close the file. The editor catches an exception - after incorrectly deleting your file on disk, and pops up a dialog window with "** Closing the file failed - Retry or Cancel".

Ok, so I went a bit crazy with these examples. They are all theoretically possible and it could seem that exception handling isn't helping much. I think that putting up examples is not helping either argument. What we need is a compelling argument for why recovery should be an option after an exception occurs - and what exactly do we mean by recovery?

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

69. Re: Try/Catch

petelomax said...

OK, to set the tone, for me three things are certain: death, taxes and when I see (in C++)

int main(int argc, char **argv) { 
  try { 
  } 
  catch (...) { 
  } 
} 

Then I know that I am facing some seriously badly written and almost completely untested garbage code.
Obviously for some small part, fair enough, but the whole app? - alarm bells.

I've done this before, though not often. It provides a way to perform a last-ditch 'save all the ciritical data now!' method.

petelomax said...

I have stated that I prefer long-winded and tedious error code handling over exceptions.

If I had the chance, I'd do both. The former lets me do proper validation and is often faster - but it can't deal with the unexpected, hence the need to use the latter.

petelomax said...
DerekParnell said...

These would always be non-recoverable exceptions .. Control does not return to the application.
a chain of such routines

Not making much sense to me so far.

There's precedent for this in other languages. It's tough to catch and stop a ThreadAbortException in Java. And while OOM exceptions can be caught, it's pretty hard to continue as normal if one of those get thrown...

petelomax said...
DerekParnell said...

The thing here is that the example is not an exception, in my opinion.

granted.

That example should obviously be a recoverable error. If it were a function (x = slice(s, i) then it's possible to signal an error by the return value or something, the same method that open() uses when it can't open a file. But Euphoria provides no way to recover from the error in the original example. This is the root of the problem.

petelomax said...
DerekParnell said...

I regard exceptions as those things that originate from outside the control of an application and that cannot be effectively anticipated by it. That's why the application should terminate, possibly after doing some damage control/mitigation first.

That might be a better definition of exception, but I don't get that the only response to things beyond your control is to die.

I've seen code in Java where Throwables are thrown and caught for purposes unrelated to error handling. For example, there's a method that returns an integer, but someone wnated to modify it to return a string in some cases. So when a string has to be returned, a new Throwable is thrown with the return value embedded in it, and the caller catches the Throwable and extracts the string from it. (While this is one way to accomplish the desired result, there are better ways to do it.)

I have no problems with Derek's definition of exceptions, but that limits its usage to things like OOM or other issues that are fundamentally hard to deal with in a sane way. Throwables and the try/catch framework can be used for more trivial issues (like open() not being able to open a file) that can be effectively anticipated by the application. In fact, as in my example above, they can be used for purposes entirely unrelated to error handling altogether.

dcuny said...

While in theory I can anticipate range errors, this is tricky in practice.

I'd rather be using a language that allows me to gracefully recover from exceptions, than one that crashes.

Certainly, an editor that gracefully handled an unanticipatible exception by warning the user and giving the user a chance to save all their data would look a lot more professional that one that simply threw up a GP fault and vanishes along with all that user's hard (and unsaved) work.

jaygade said...

A bug in the editor should result in a crash, and the developer should correct the bug. If possible, the reason for the bug should be communicated to the user, but regardless if an incorrect result can occur then the user is better served by a crash then by the output of incorrect data.

This is part of the Unix philosopy - broken programs deserve to break. (Example at http://lwn.net/Articles/414467/ )

But when data is lost, it looks really unprofessional. In one case, it even lead to enough unhappiness that the threat of a lawsuit was thrown around: http://photo.net/wedding-photography-forum/00brg3

On the other hand, the output of incorrect data in software has lead not only to big lawsuits but even to people dying: http://www.law.berkeley.edu/journals/btlj/articles/vol5/Levy/html/text.html

jaygade said...

Of course, the class of errors represented by an illegal filename would be classified as a recoverable error, not necessarily an irrecoverable one. It's a situation which depends on user input and should be checked by code so...

I'm not sure that your example is valid.

I don't understand. Your program takes input, uses a library which returns incorrect output, and so you should provide some random or guessed output regardless? If the library is bad, then the application should crash and you should provide feedback to the library developer. If he or she is unavailable then you should no longer use that library, or else correct it on your own.

These issues should certainly be identified by testing prior to deployment.

If your program RECEIVES incorrect input, then it should detect it and report it back to the user.

Well, this happened to dcuny while he was actively developing and testing his editor, prior to the deployment of even an alpha version. If try/catch makes it easier for developers to eat their own dog food, I don't see why that'd be a bad thing.

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

70. Re: Try/Catch

DerekParnell said...
dcuny said...

Imagine I've got a program that generates a .wav file as output. I find that someone's written a library that generates .wav files from a sequence.

Hurrah! Only there's the possibility that perhaps the developer didn't do adequate range checking. If we use your definition of exceptions, I've got a couple options:

  1. I can read through the library, making sure that it traps all possible errors, or
  2. I can write my own library, just in case, or
  3. I can choose not to use Euphoria

While in theory I can anticipate range errors, this is tricky in practice.

I'd rather be using a language that allows me to gracefully recover from exceptions, than one that crashes.

As pointed out, if you chose not to use that feature... you still get an immediate failure.

Ok, so don't use Euphoria.

Why the heck did we add goto then? Adding a new feature like try-catch isn't forcing new users to use it.

Refusing to add it, however, is the same as forcing new users - who may have perfectly valid reasons to want it - to not use it.

In situations where I've had to gracefully recover from an Euphoria app, I've writen a nanny program and have it watch the other app. If the other app crashes, the nanny program restarts it so it can pick up where it left off.

DerekParnell said...

However, there comes a point at which one must simply trust the code written by others.

Agreed. I've seen issues in the past where java.exe itself crashed, blowing the entire app in smoke. At a certain point, there's not a whole lot you can do about it...

On the flip side, why make it worse by forcing us to trust people when we don't necessarily have to? Keeping the number of people who have trusted access to your passwords is a good security practice. Adding try/catch so we don't have to trust the author of a random library as much to prevent our app from crashing in a production environment likewise seems like a good idea.

DerekParnell said...

My argument goes something like this ...
The Euphoria run-time component has many potential calls to RTFatal() and the vast majority would be triggered by bad data or bad coding. Things that appropriate testing should be discovering. They occur when the application is demonstrably doing the wrong thing and the code needs to be corrected. Failing the application is not a bad course of action with these.

I think this is unacceptable if it happens in a production environment. The more code there is, the harder it is to test everything.

That doesn't mean you don't try, of course, but remember the adage: all software has bugs. Not "all software that hasn't been thoroughly and appropriately unit tested has bugs" but "all software has bugs".

On the flip side, this means software using try/catch also has bugs and can still crash. try/catch is not a panacea - but I don't see anyone trying to argue that it is.

DerekParnell said...

Your application was trying to do something useful. Something unanticipated and outside of your program's control caused things to stuff up. So what is you program going to do so it can succeed in doing that useful thing? Now I'm not talking about logic errors in your code, or invalid data being presented to your program, or error codes that can be returned by functions you call. I'm talking about exceptions - rare events that for the most part you can safely avoid writing special code to handle.

This I agree with.

DerekParnell said...

Ok, so I went a bit crazy with these examples. They are all theoretically possible and it could seem that exception handling isn't helping much.

By your definition above, I'd argue that these aren't really exceptions - errors, sure, but they're reasonably anticipatible and should be detectable and correctable with an appropriate amount of testing.

DerekParnell said...

What we need is a compelling argument for why recovery should be an option after an exception occurs - and what exactly do we mean by recovery?

Are you talking about after a true exception occurs, or a not-exception like your examples? The difference is important.

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

71. Re: Try/Catch

DerekParnell said...

But let's say it failed and your code actually got control at the point of failure ... what sensible thing can your program do to carry on?

Sometimes crashing is the right thing to do. But if a feature of a big program breaks for some reason (let's assume user input that you didn't anticipate, because that's super common) that doesn't mean the whole thing should die. It might be possible to carry on with other aspects.

Here's a real life example I run into every day. In my day job, I work with a java project that uses JSF / xhtml markup for building web pages. I use Eclipse. Many of my files include other files. I can select an include statement, hit F3 and have the included file opened in the editor. For some reason, every time I do this, I get a dialog pop up and tell me that there was a NullPointerException. But I can click OK and get on with my job.

It's a bit annoying, and obviously someone has done something wrong here. I've never dug too deeply, but I assume it was the extension / plugin writer who wrote the xhtml stuff. I guess I could find another tool to use or try upgrading or whatever. Or at least report the bug. But...meh...I have better things to do (like get my work done) and at least I can keep working, and whatever that error was, it wasn't critical and was definitely recoverable, though it's a class of error that euphoria would crash upon.

Matt

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

72. Re: Try/Catch

andi49 said...
Shian_Lee said...

[...]

I've never used any exception handler in controller, and among the other programmers I knew, I'm considered to be very cautious.

At least we still have Euphoria 3.1.1 to enjoy the real thing. And we can kill the exceptions by calling DOS interrupts directly where needed. Machines love DOS.

Hi

what is your problem?

You do not like excetpion handlers? So, don't use it. That's all.
Don't like 'goto'? Don't use it..
Don't like 'OOP'? Don't use it.

For PLC's there is now CodeSys V3, used by over 300 mostly small to medium manufacturer, on the market since about 5 years.
It does support OOP and exception handling. But you do not have to use it!. You can still program like in the 80's
Even S7 from Siemens support this.

Giving people the freedom of choice is very important (from my point of view).

Go to the PC side (mean Desktop Computer). FPC (FreePascalCompiler) supports OOP and Exceptions and Standard Errorhandling.

But again, you do not have to use it...
You can still program like 30 years before, it works...
FPC gives you the choice.
It also supports a DOS Compiler.

Most of this is also true for FreeBasic, even Phyton (ok, no dos) etc.

Euphoria is really nice, and easy to use but a little evolution want hurt it.

Giving the People the choice to choose what they want is is really important.

Andreas

If you are working for NASA then OOP and exception handler may be welcom in a controller.

Normal people, Normal electricians, Normal factories - using ladder programming.

Nothing is wrong with me, I just live on Earth, while some people are already buying lands on Mars.

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

73. Re: Try/Catch

jimcbrown said...

By your definition above, I'd argue that these aren't really exceptions - errors, sure, but they're reasonably anticipatible and should be detectable and correctable with an appropriate amount of testing.

How does one know? I certainly do not know what actually triggers the exceptions in these examples. I know the message displayed, but not the underlying cause.

But my issue is that if we rely on recoverability code, then we may be unpleasantly surprised when we happen across situations that cannot be always be recovered.

And I didn't even mention what we might try when exceptions happen during the execution of the recovery code.

jimcbrown said...
DerekParnell said...

What we need is a compelling argument for why recovery should be an option after an exception occurs - and what exactly do we mean by recovery?

Are you talking about after a true exception occurs, or a not-exception like your examples? The difference is important.

I said, quite explicitly, that the examples are exceptions, in the sense that the coder used the try-catch paradigm. It actually doesn't matter if they are errors or exceptions, because I was trying to focus on the idea of recover from when things go pear-shaped.

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

74. Re: Try/Catch

mattlewis said...
DerekParnell said...

But let's say it failed and your code actually got control at the point of failure ... what sensible thing can your program do to carry on?

Sometimes crashing is the right thing to do. But if a feature of a big program breaks for some reason (let's assume user input that you didn't anticipate, because that's super common) that doesn't mean the whole thing should die. It might be possible to carry on with other aspects.

User input errors are not exceptions, in my way of thinking. User input ought to be validated a soon as practicable upon entering the application.

mattlewis said...

Here's a real life example I run into every day. In my day job, I work with a java project that uses JSF / xhtml markup for building web pages. I use Eclipse. Many of my files include other files. I can select an include statement, hit F3 and have the included file opened in the editor. For some reason, every time I do this, I get a dialog pop up and tell me that there was a NullPointerException. But I can click OK and get on with my job.

It's a bit annoying, and obviously someone has done something wrong here. I've never dug too deeply, but I assume it was the extension / plugin writer who wrote the xhtml stuff. I guess I could find another tool to use or try upgrading or whatever. Or at least report the bug. But...meh...I have better things to do (like get my work done) and at least I can keep working, and whatever that error was, it wasn't critical and was definitely recoverable, though it's a class of error that euphoria would crash upon.

Wow! Not only annoying, but an example of where exception handling is pointless. So someone went to the trouble of catching an exception that has no effect on the job you're doing with the application. Clever.

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

75. Re: Try/Catch

DerekParnell said...
jimcbrown said...

By your definition above, I'd argue that these aren't really exceptions - errors, sure, but they're reasonably anticipatible and should be detectable and correctable with an appropriate amount of testing.

How does one know? I certainly do not know what actually triggers the exceptions in these examples. I know the message displayed, but not the underlying cause.

Looking at your examples, the causes seem obvious.

1) Permissions issue or maybe the OS detected corruption and set the filesystem to read-only.

2) Memory corruption in the editor (likely caused by misuse of a pointer somewhere) could cause this. The illegal character issue is anticipatible in any case (someone else might have edited the file with a hex editor and manualyl inserted illegal characters into the file).

3) Power failure lead to the filesystem not being flushed, so it's in an inconsistent state. This lead to the file becoming corrupt. This situation may not be recoverable, but it can certainly be anticipated.

4) Filesystem is full, when the editor tried to write it re-opened the file for writing (which on some OSes truncates the file to empty, deleting the preexisting data) then failed to write anything to the file due to the fullness issue. Simply offer to write the file to another location, or let the user free up some disk space before retrying....

DerekParnell said...

But my issue is that if we rely on recoverability code, then we may be unpleasantly surprised when we happen across situations that cannot be always be recovered.

That's a different, tangential issue that requires it's own topic to discuss.

I do agree that there are cases where the situation is not recoverable. But why should be deliberately handicap ourselves in unanticipatible but recoverable scenarios?

DerekParnell said...

And I didn't even mention what we might try when exceptions happen during the execution of the recovery code.

Ditto.

DerekParnell said...

What we need is a compelling argument for why recovery should be an option after an exception occurs - and what exactly do we mean by recovery?

I said, quite explicitly, that the examples are exceptions, in the sense that the coder used the try-catch paradigm. It actually doesn't matter if they are errors or exceptions, because I was trying to focus on the idea of recover from when things go pear-shaped.

I think, if we can't get the terminology straight, we're going to confuse ourselves talking about apples vs oranges.

You previously defined exceptions to mean unaniticipatble, unrecoverable events. But exception has also been defined as being an object that gets thrown about in the try-catch paradigm. Lets call the former "unrecoverables" or "unrecoverable exceptions" and the latter "Throwables".

So, IIUC you say that your examples are examples of Throwables. I agree. You also seem to be saying that they are also examples of unrecoverables. While I don't entirely agree, I understand the point you are trying to make, so I'll accept this premise for the sake of argument.

So, you gave examples of Throwables and unrecoverables. What's the correct way to interpret this?

DerekParnell said...

What we need is a compelling argument for why recovery should be an option after an exception occurs

"What we need is a compelling argument for why recovery should be an option after a Throwable is thrown"

OR

"What we need is a compelling argument for why recovery should be an option after an unrecoverable occurs"

I think the answer to the former is self-evident. I don't think a compelling argument for the later exists, as the situation is by definition not recoverable. But the latter also has nothing to do with dcuny's original example and use case which lead him to ask about adding try/catch in the first place!

DerekParnell said...

User input errors are not exceptions, in my way of thinking. User input ought to be validated a soon as practicable upon entering the application.

I agree in principle. Actually getting this right is very hard in practice, hence the popularity of try/catch as a crutch.

DerekParnell said...
mattlewis said...

Here's a real life example I run into every day. In my day job, I work with a java project that uses JSF / xhtml markup for building web pages. I use Eclipse. Many of my files include other files. I can select an include statement, hit F3 and have the included file opened in the editor. For some reason, every time I do this, I get a dialog pop up and tell me that there was a NullPointerException. But I can click OK and get on with my job.

It's a bit annoying, and obviously someone has done something wrong here. I've never dug too deeply, but I assume it was the extension / plugin writer who wrote the xhtml stuff. I guess I could find another tool to use or try upgrading or whatever. Or at least report the bug. But...meh...I have better things to do (like get my work done) and at least I can keep working, and whatever that error was, it wasn't critical and was definitely recoverable, though it's a class of error that euphoria would crash upon.

Wow! Not only annoying, but an example of where exception handling is pointless. So someone went to the trouble of catching an exception that has no effect on the job you're doing with the application. Clever.

Why is Throwable handling pointless here? If the Throwable wasn't caught, the IDE would have crashed and taken down all of Matt's unsaved work with it. I don't see this as the preferred outcome.

From the perspective of the IDE writer, it's easy to anticipate a badly written plugin (perhaps still in beta) crashing and throwing a Throwable. But this can be handled - catch the Throwable and maybe disable/unload the plugin. And pop up a message box so the bug can be reported from the user to the developer of the bad plugin.

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

76. Re: Try/Catch

DerekParnell said...
mattlewis said...

Sometimes crashing is the right thing to do. But if a feature of a big program breaks for some reason (let's assume user input that you didn't anticipate, because that's super common) that doesn't mean the whole thing should die. It might be possible to carry on with other aspects.

User input errors are not exceptions, in my way of thinking. User input ought to be validated a soon as practicable upon entering the application.

Like any entity subject to the laws of physics and mathematics, your users will come up with ways to use your program that you didn't think of. Or maybe some module has an error in it even with handling correct input. It could be yours, it could be someone else's. Consider this:

Suppose you write a library. In all of your public interface, you implement exception handling, and then you return an error to your user instead of crashing or giving them an exception they might or might not be able to handle. When you encounter these, or receive reports from users, you fix the error so something more appropriate happens. Now people who use your code (probably including you!) can use your stuff relatively sure that your code won't crash their program (obviously, C calls, etc., may be exceptions to your exception handling, but you get the idea) if they encounter bugs in your code.

What's bad about this?

You can think up examples where this doesn't or shouldn't apply, but that doesn't invalidate my hypothetical presented above.

DerekParnell said...

Wow! Not only annoying, but an example of where exception handling is pointless. So someone went to the trouble of catching an exception that has no effect on the job you're doing with the application. Clever.

Pointless‽ It stops the program from crashing! There's a module that has an error. Rather than die right there, the rest of the program carries on. Not every situation is like this and should be recovered from, and fail fast is an excellent development paradigm, but saying that all errors should halt the program is sometimes equivalent to hating your users.

Matt

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

77. Re: Try/Catch

jimcbrown said...

"What we need is a compelling argument for why recovery should be an option after a Throwable is thrown"

OR

"What we need is a compelling argument for why recovery should be an option after an unrecoverable occurs"

I think the answer to the former is self-evident. I don't think a compelling argument for the later exists, as the situation is by definition not recoverable. But the latter also has nothing to do with dcuny's original example and use case which lead him to ask about adding try/catch in the first place!

But what's the difference between a recoverable and unrecoverable? What about a bad subscript in a function? Calling routine_id -1? Again, anything that would normally call RTFatal could potentially be recoverable in one circumstance or another. This doesn't stop you from a fast fail development, either, assuming you watch / log these and fix them as you find them.

Note that none of this necessarily assumes try/catch vs what Go does (I remember looking at it a while ago, but I haven't gone back and refreshed my memory and I don't think it matters while we're arguing over the basic principles here).

Matt

DerekParnell said...

User input errors are not exceptions, in my way of thinking. User input ought to be validated a soon as practicable upon entering the application.

I agree in principle. Actually getting this right is very hard in practice, hence the popularity of try/catch as a crutch.

DerekParnell said...
mattlewis said...

Here's a real life example I run into every day. In my day job, I work with a java project that uses JSF / xhtml markup for building web pages. I use Eclipse. Many of my files include other files. I can select an include statement, hit F3 and have the included file opened in the editor. For some reason, every time I do this, I get a dialog pop up and tell me that there was a NullPointerException. But I can click OK and get on with my job.

It's a bit annoying, and obviously someone has done something wrong here. I've never dug too deeply, but I assume it was the extension / plugin writer who wrote the xhtml stuff. I guess I could find another tool to use or try upgrading or whatever. Or at least report the bug. But...meh...I have better things to do (like get my work done) and at least I can keep working, and whatever that error was, it wasn't critical and was definitely recoverable, though it's a class of error that euphoria would crash upon.

Wow! Not only annoying, but an example of where exception handling is pointless. So someone went to the trouble of catching an exception that has no effect on the job you're doing with the application. Clever.

Why is Throwable handling pointless here? If the Throwable wasn't caught, the IDE would have crashed and taken down all of Matt's unsaved work with it. I don't see this as the preferred outcome.

From the perspective of the IDE writer, it's easy to anticipate a badly written plugin (perhaps still in beta) crashing and throwing a Throwable. But this can be handled - catch the Throwable and maybe disable/unload the plugin. And pop up a message box so the bug can be reported from the user to the developer of the bad plugin.

[/quote]

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

78. Re: Try/Catch

jimcbrown said...

From the perspective of the IDE writer, it's easy to anticipate a badly written plugin (perhaps still in beta) crashing and throwing a Throwable. But this can be handled - catch the Throwable and maybe disable/unload the plugin. And pop up a message box so the bug can be reported from the user to the developer of the bad plugin.

Since this bug is already catch in a very elegant way, the user don't even bother to report it; he simply continue his work and this bug will last another few years (as I've seen in many programs).

If the IDE would have crashed, I bet that this plugin would have fixed or removed much quicker. Personally I don't bother to report a bug unless it really bothers me (if the program crashes). And there are so many bugs out there.

As an experienced user, I save and backup my work frequently. I guess any programmer does. Automatic backups are common option in editors, since the developers are realistic after all.

(Don't be offended, I'm just commenting here)

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

79. Re: Try/Catch

mattlewis said...
jimcbrown said...

"What we need is a compelling argument for why recovery should be an option after a Throwable is thrown"

OR

"What we need is a compelling argument for why recovery should be an option after an unrecoverable occurs"

I think the answer to the former is self-evident. I don't think a compelling argument for the later exists, as the situation is by definition not recoverable. But the latter also has nothing to do with dcuny's original example and use case which lead him to ask about adding try/catch in the first place!

But what's the difference between a recoverable and unrecoverable?

You can trap the former and continuie program execution without making the sytem unstable or introducing logic errors (at least in principle), but you can't do this for the latter.

mattlewis said...

What about a bad subscript in a function?

This was dcuny's original example, IIUC. That's obviously recoverable (skip the operation and fall back to the caller so it can give the user of the editor a chance to save his or her data, or something).

mattlewis said...

Calling routine_id -1?

This can be made recoverable. In fact, we could make this have error handling akin to open() - if something went wrong, signal the caller and let the caller deal with it instead of crashing.

mattlewis said...

Again, anything that would normally call RTFatal could potentially be recoverable in one circumstance or another.

Actually, this is the problem - most of the "errors" that trigger RTFatal are often trivially recoverable - it was just RobCraig's decision to make them fatal errors.

mattlewis said...

This doesn't stop you from a fast fail development, either, assuming you watch / log these and fix them as you find them.

Agreed. But supporting try/catch doesn't stop someone from using fail fast development. Just leave out the catches while code is under development/unit testing/etc and then add them in before going into production.

Or, depending on your use case and personal preference, just don't use try/catch at all. It's not like we're turning into Java, where try/catches are required for use in ordinary, everyday events...

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

80. Re: Try/Catch

Shian_Lee said...
jimcbrown said...

From the perspective of the IDE writer, it's easy to anticipate a badly written plugin (perhaps still in beta) crashing and throwing a Throwable. But this can be handled - catch the Throwable and maybe disable/unload the plugin. And pop up a message box so the bug can be reported from the user to the developer of the bad plugin.

Since this bug is already catch in a very elegant way, the user don't even bother to report it; he simply continue his work and this bug will last another few years (as I've seen in many programs).

If the IDE would have crashed, I bet that this plugin would have fixed or removed much quicker. Personally I don't bother to report a bug unless it really bothers me (if the program crashes). And there are so many bugs out there.

On the other hand, the user - after seeing the error crash the IDE - might decide that it's better to move on to another product where this doesn't happen. In any case, forcing users to become assistant developers (by forcing them to write out bug reports) is probably not a best practice... like in Matt's real life example, I'm sure those users have better things to do.

Shian_Lee said...

As an experienced user, I save and backup my work frequently. I guess any programmer does. Automatic backups are common option in editors, since the developers are realistic after all.

Definitely a sound practice.

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

81. Re: Try/Catch

jimcbrown said...

On the other hand, the user - after seeing the error crash the IDE - might decide that it's better to move on to another product where this doesn't happen. In any case, forcing users to become assistant developers (by forcing them to write out bug reports) is probably not a best practice... like in Matt's real life example, I'm sure those users have better things to do.

It's true.

Using third party plug-ins, libraries, and code, is a big problem.

I honestly wonder if there is more then one way, Java's way, to deal with this problem... (maybe somebody knows?)

Personally I assume that any plug-in must be approved by the developer of the program before being included - isn't it the way that many free code developers are dealing with the problem?

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

82. Re: Try/Catch

dcuny said...
petelomax said...
  1. It's not really my place to deny others
  2. There are real user experience benefits
  3. There are valid cost benefits (crappy code is part of that)
  4. There are even performance gains to be had (and hits to suffer)
  5. If you don't like it you don't have to use it

This. Especially #5.

+1000

On the other hand, if you want Euphoria to be your own private language, by all means don't implement features common to other languages, and then tell people that Euphoria is superior because it lacks these features. And be sure to cast aspersions on their coding skills while you're at it.

- David

Note that once you introduce something like exception handling in a language, its not a optional thing. Many situations will force, even the developers that dont like it, to use it.

For example: If the fopen() function throws a exception (instead of a error code) when a file dont exists, all developers are forced do write try/catch blocks to check if everything is OK.

Exception handling is not this holy grail you're selling. The same way code can break with a error, it will break with unhandled exceptions.

I dont like exception handling, and think that its not compatible with anything that uses simplicity as a feature (my personal opinion here).

Sorry my bad english...

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

83. Re: Try/Catch

Shian_Lee said...

Personally I assume that any plug-in must be approved by the developer of the program before being included - isn't it the way that many free code developers are dealing with the problem?

I don't know of any examples where this is the case.

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

84. Re: Try/Catch

elias_maluko said...

Note that once you introduce something like exception handling in a language, its not a optional thing. Many situations will force, even the developers that dont like it, to use it.

I'm not so sure that this is necessarily true. I don't see anyone being forced to use goto.

elias_maluko said...

For example: If the fopen() function throws a exception (instead of a error code) when a file dont exists, all developers are forced do write try/catch blocks to check if everything is OK.

Agreed, this is a bad idea. We should not do this.

What would be even worse is that, instead of throwing something or returning an error code, fopen() crashes your entire program if it can't open a file. Now, that would be really bad, wouldn't it?

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

85. Re: Try/Catch

jimcbrown said...
mattlewis said...

But what's the difference between a recoverable and unrecoverable?

You can trap the former and continuie program execution without making the sytem unstable or introducing logic errors (at least in principle), but you can't do this for the latter.

Well, duh, but my point was that it's not always obvious when an error is one or the other.

jimcbrown said...

Or, depending on your use case and personal preference, just don't use try/catch at all. It's not like we're turning into Java, where try/catches are required for use in ordinary, everyday events...

Totally.

Matt

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

86. Re: Try/Catch

elias_maluko said...

Note that once you introduce something like exception handling in a language, its not a optional thing. Many situations will force, even the developers that dont like it, to use it.

For example: If the fopen() function throws a exception (instead of a error code) when a file dont exists, all developers are forced do write try/catch blocks to check if everything is OK.

I think that for this example, in a hypothetical situation where I was developing try/catch in euphoria, I'd make not handling something like that a warning, not an error. But I would also be very wary of throwing exceptions from built-ins.

Matt

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

87. Re: Try/Catch

mattlewis said...
jimcbrown said...
mattlewis said...

But what's the difference between a recoverable and unrecoverable?

You can trap the former and continuie program execution without making the sytem unstable or introducing logic errors (at least in principle), but you can't do this for the latter.

Well, duh, but my point was that it's not always obvious when an error is one or the other.

Oops. That's a good point.... that's probably a significant factor in causing try/catch overuse/abuse.

mattlewis said...
jimcbrown said...

Or, depending on your use case and personal preference, just don't use try/catch at all. It's not like we're turning into Java, where try/catches are required for use in ordinary, everyday events...

Totally.

Matt

Point taken.

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

88. Re: Try/Catch

Shian_Lee said...

If the IDE would have crashed, I bet that this plugin would have fixed or removed much quicker. Personally I don't bother to report a bug unless it really bothers me (if the program crashes). And there are so many bugs out there.

As I (and others) have noted, Euphoria is basically designed as if the end user were a developer.

So the program crashed? No big deal, read the crash report and fix the program. Hurrah - one less bug in the code.

But our end users shouldn't be treated as if they were testers who "should" report bugs.

As far as end users are concerned, if the program crashes what they "should" do is never use the program again, and warn their friends about how terrible it is.

- David

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

89. Re: Try/Catch

Time for Design by Contract? Sorry, just looking for a third way ... a road less travelled by.

Bugmagnet

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

90. Re: Try/Catch

dcuny said...

As I (and others) have noted, Euphoria is basically designed as if the end user were a developer.

So the program crashed? No big deal, read the crash report and fix the program. Hurrah - one less bug in the code.

But our end users shouldn't be treated as if they were testers who "should" report bugs.

As far as end users are concerned, if the program crashes what they "should" do is never use the program again, and warn their friends about how terrible it is.

- David

I agree.

What I was looking for seems to be more like Design by Contract which offered by Bugmagnet.

Electric equipment usage is based on specifications. If you plug 110V machine into 240V outlet, the machine will not work. As long as you follow specifications it will work.

Specifications are more clear and reliable way to deal with exceptions, at least in the real world.

And I also think that routines must return an error code wherever applicable.

Logical errors in your own program will occur with or without the presents of error handler in Euphoria.

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

91. Re: Try/Catch

bugmagnet said...

Time for Design by Contract? Sorry, just looking for a third way ... a road less traveled by.

I believe Programming by Contract solves a related, but different program. In the example you link to, if a contract fails in the example, Groovy throws an exception. So we're back to the question: How should an exception be handled?

As designed, Euphoria essentially throws an unrecoverable exception in many places - typically an indexing issue - where recovery is often possible.

This is good from a development point of view, in that it doesn't allow bugs to be masked.

Conversely, it's bad from a user point of view, in that users generally don't like to have their work interrupted with a crash.

My specific request is that Euphoria have a mechanism that allows for recovery from an exception - something much different from a crash_routine, which will exists on an exception.

- David

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

92. Re: Try/Catch

Arguments aside, I think the next (small) step, in the investigation process, is for someone to translate eg

puts(1,"started\n") 
--try 
puts(1,9/0) 
--catch 
puts(1,"exception caught\n") 

and then see if they can modify the resulting C code to use setjmp/longjmp and survive.

Then repeat the process with the 9/0 several nested calls deep away, and finally post the C source mods here.

Pete

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

93. Re: Try/Catch

petelomax said...

Arguments aside, I think the next (small) step, in the investigation process, is for someone to translate eg

puts(1,"started\n") 
--try 
puts(1,9/0) 
--catch 
puts(1,"exception caught\n") 

and then see if they can modify the resulting C code to use setjmp/longjmp and survive.

Then repeat the process with the 9/0 several nested calls deep away, and finally post the C source mods here.

Funny you should mention setjmp/longjmp, I've been working on trying to figure out how exactly that would work in a C program. The big problem is that you need to cleanup and call destructors for objects in the functions that are getting jumped over getting to the catch block. Registering a cleanup function is possible with GCC's cleanup variable attribute, but it doesn't work because longjmp ignores them. Then I found libunwind-setjmp which should unwind the stack and call cleanup functions, but my test doesn't seem to be using the right longjmp.

Another option would be to translate to C++ and use try/catch natively. tongue

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

94. Re: Try/Catch

petelomax said...

Arguments aside, I think the next (small) step, in the investigation process, is for someone to translate eg

The biggest problem, to my mind, is stuff that doesn't call RTFatal in a translation, but gives you a machine type error. For instance, we don't do bounds checking in translated code.

Matt

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

95. Re: Try/Catch

[PDF] Implementing exceptions in the C programming language

http://www.adomas.org/excc/exceptions.pdf

This is a demonstration, in C, for try/catch.

_tom

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

96. Re: Try/Catch

PeteE said...

Funny you should mention setjmp/longjmp, I've been working on trying to figure out how exactly that would work in a C program. The big problem is that you need to cleanup and call destructors for objects in the functions that are getting jumped over getting to the catch block.

We know what we need to clean up at the end of a function. We'd just have to know what was still in scope based on different scopes in the function and DeRef it all. Surely not as simple as I make out, of course. blink

PeteE said...

Another option would be to translate to C++ and use try/catch natively. tongue

I've had the same thought.

Matt

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

97. Re: Try/Catch

Shian_Lee said...

If you are working for NASA then OOP and exception handler may be welcom in a controller.

Normal people, Normal electricians, Normal factories - using ladder programming.

Nothing is wrong with me, I just live on Earth, while some people are already buying lands on Mars.

Hi, just one last thing. (It's also offtopic now)

you have not even read the text I wrote. Okay, maybe my english is too bad. And,also my fault, Codesys is sold (distributed, mostly for free or really cheap) under different names (Indralogic,twincat ...)

And no, i do not work for NASA and I'am for sure a 'normal electrician'. And no, i never use ladder programming, i prefer IL and ST. And i do not use OOP or exceptions. But I like to have the choice.

Maybe you find some time and check out this link http://store.codesys.com/codesys-control-for-raspberry-pi-sl.html?___store=en&___from_store=default#Reviews

(And, yes Codesys support all off this.

IL (Instruction list) is an assembler like programming language

ST (Structured text) is similar to programming in PASCAL or C

LD (Ladder diagram) enables the programmer to virtually combine relay contacts and coils

FBD (Function block diagram) enables the user to rapidly program both Boolean and analogue expressions

SFC (Sequential function chart) is convenient for programming sequential processes and flows)

And please don't tell that a Rasberry Pi is a device that you, or your company, can't afford.( buying lands on Mars. )

Andreas

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

98. Re: Try/Catch

Here's a proposal for something more "Euphoria-like", that might address some of the perceived abuses of try/catch. It's modeled roughly off the pcode() ("protected code") call in Lua.

First, the general form, for a procedure:

-- do something dangerous with a function 
if protected_procedure( scary_procedure(a, b, c) ) then 
   -- handle the exception 
end if 

For those paying close attention, this requires some serious gymnastics on the part of the parser. That's because normally, the argument list is processed before the call to the routine. I'll hand-wave this away for the moment, and get on to the next case: calling a function.

The call to pcode() in Lua looks something like this:

error, theta = pcode( sin(x) ) 

This doesn't work well in Euphoria because Euphoria doesn't know if a sequence is coming back as a single value from the function, or a list of parameters from the function.

And there's a subtle point here: assignment should be conditional. If the call to the function resulted in an error, the assignment shouldn't take place, because the result (if any) is likely to be bad.

I think we can kill two birds with one stone here:

-- do something dangerous with a procedure 
if protected_function( {x, y}, scary_function(a, b, c) ) then -- safe version of {x, y} = scary_code(a, b, c) 
   -- handle the exception 
end if 

Where the actual assignment of:

{x, y} = scary_code(a, b, c) 

would only take place if scary_code didn't raise an error.

Behind the scenes, it might generate code that's roughly:

-- set the protected_call flag for the frame 
set_protected_call(1) 
 
-- perform protected code 
__PROTECTED_RESULT = scary_function(a, b, c) 
 
-- clear the protected_call flag for the frame 
set_protected_call(0) 
 
-- assignment is conditional 
if not __ERROR_FLAG then 
   {x, y} = __PROTECTED_RESULT 
end if 
 
-- deref the returned value from the temp 
__PROTECTED_RESULT = 0 
 
-- the user's custom code 
if __ERROR_FLAG then 
   -- handle the exception 
end if 

So when RTFatal executes, it unwinds the call stack until if finds a call frame where the protected_call flag is true.

I won't even suggest how this might work in C.

Is this sufficiently Euphoria-like?

- David

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

99. Re: Try/Catch

I should note that in Lua, pcall{} either returns false, or true plus additional parameters.

From that perspective, you could write:

{error_flag, result1, result2} = protected_function( foo() ) 
if error_flag then 
   -- handle the exception 
end if 

But I liked decoupling the assignment and flag because there's no need for the temporary variable.

Plus, protected_function() would have to figure out if a sequence returned foo was a single value, such as:

s = foo1() -- returns a sequence of characters 
{x, y} = foo2() -- returns a sequence containing x and y 

So protected_function() would have to know what the left hand assignment looked like, so it could know whether to return a new sequence or append to the result. There's nothing in the declaration of the routine that indicates what to do:

{error_code, s} = protected_code( foo1() ) -- has to create a new sequence to hold error_code and result of foo1 
{error_code, x, y} = protected_code( foo2() ) -- has to append error_code to the sequence return by foo2 

I think passing the parameter list of variables to assign is more elegant.

Personally, I still think try/catch is the better route because it's more familiar.

And if you ultimately implement the C++ version using try/catch... it's even more of a no-brainer. grin

- David

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

100. Re: Try/Catch

Andreas,

We like to supply machine with ladder program since it is common knowledge to all electricians. We think what's good for them - not for us.

I'd like to see Euphoria being used by everyone, not only by professionals. I think what's good for anyone - not for me.

Handling exceptions can be done in a more high-level way, which is suitable to the overall usage of Euphoria.
Routines + Specifications that returning error codes may be innovative, clear, and simple programming method for any end user.

Depends on the implementation it may not catch logical/index errors for example, but in my opinion, in case that the programmer is not sure of his own code, adding some if...then to the code has an advantage over presenting a new and complex method of programming in Euphoria.

I'm not arguing here, I just comment my opinion; because as you add more complex programming methods to the language, you ignore the basic concepts of Euphoria which might give a good reason to many users to immigrate to another popular language. (I don't say don't do it - I say do it as innovative as Euphoria itself).

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

101. Re: Try/Catch

Shian_Lee said...

Handling exceptions can be done in a more high-level way, which is suitable to the overall usage of Euphoria.

I'm curious. How do you suggest these exceptions he handled?

I'm assuming that anything that ends up halting Euphoria is an exception.

I can see routines returning error codes, and in many cases they already do.

But a much more typical case is an indexing error, such as:

x = s[length(s)+1] 

What innovation would you suggest for this? Because of the way indexing and slicing are done, I don't see how and error code can be returned, and from what.

- David

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

102. Re: Try/Catch

dcuny said...

But a much more typical case is an indexing error, such as:

x = s[length(s)+1] 

What innovation would you suggest for this? Because of the way indexing and slicing are done, I don't see how and error code can be returned, and from what.

- David


Choose a soft and gracefull fail, and it will do what the filesystem does: extend the sequence and return a {} or a null. Maybe a default exception handler which you can append your exceptions to. I have asked for this for years, there's no reason an interpreter should nuke itself over this. In my opinion, which is useless.

useless

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

103. Re: Try/Catch

David,

Index exceptions can be trapped using innovative 'Specifications' technique - which is able to return error codes in a clear, simple and very high-level way.

In most cases testing the unsafe code using if...then is suffice.

'Specifications' may be applied to a whole module, or a single routine - depends on the implementation.

The exception occurs only at the low level implementation of 'Specifications' - at the high level only error codes are returned.

Edit: beside dealing with exceptions in a plug-in module, 'Specifications' dictate the regular and standard program's flow, using a simple and clear if..error_code..then.

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

104. Re: Try/Catch

dcuny said...
Shian_Lee said...

Handling exceptions can be done in a more high-level way, which is suitable to the overall usage of Euphoria.

I'm curious. How do you suggest these exceptions he handled?

I'm assuming that anything that ends up halting Euphoria is an exception.

Perhaps that should be changed.

dcuny said...

I can see routines returning error codes, and in many cases they already do.

Not all do, however. Remember "sequence found inside character string" for puts() and somesuch?

dcuny said...

But a much more typical case is an indexing error, such as:

x = s[length(s)+1] 

What innovation would you suggest for this? Because of the way indexing and slicing are done, I don't see how and error code can be returned, and from what.

The only reasonable solution I can come up with (outside of pcode or try/catch that is) - add a special index_crash_routine() for this case, and if a handler is defined, call it with the sequence and the index and let it figure out what to return (or alternatively to crash). If no handler is defined, crash. But then you'd probably have to come up with similiar functional_crash_routine()s for each category of errors that can't be handled by a return code.

The easy way out would be to set a global errno and leave the value of x unchanged, but I think it's obvious why no wants to do this.

Looking at the example bugmagnet came up with, that framework would throw a Throwable: https://github.com/andresteingress/gcontracts/blob/master/gcontracts-core/src/main/java/org/gcontracts/PreconditionViolation.java

At least in bugmagnet's example, Design by Contract is used as part of the fail fast philosophy. Which, as I've said before, may be fine in development but not so much in production.

Shian_Lee said...

David,

Index exceptions can be trapped using innovative 'Specifications' technique - which is able to return error codes in a clear, simple and very high-level way.

Using ... Throwables ....

Shian_Lee said...

The exception occurs only at the low level implementation of 'Specifications' - at the high level only error codes are returned.

Not in bugmagnet's example, which states that the two pieces of java code are identical:

<pre> def start() { if (started) { throw new AssertionError("Rocket already started!") } def oldSpeed = speed speed += 10 started = true if (!(started   speed - oldSpeed > 0)) throw new AssertionError("Rocket not }

@Requires({ !started }) @Ensures({ started   speed > 0 }) def start() { speed += 10 started = true } </pre>

Shian_Lee said...

In most cases testing the unsafe code using if...then is suffice.

Right, but that brings us back to the earlier discussion about third party libraries.

Shian_Lee said...

'Specifications' may be applied to a whole module, or a single routine - depends on the implementation.

In Bugmagnet's example (gcontracts), it appears to be necessary for this to be done on each routine individually.

Even if you could specify a specification for an entire module, you would almost always want to add individual specifications to each routine anyways...

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

105. Re: Try/Catch

Continue...

Raw example for 'Specifications':

Routine foo() returns an integer, so, using Specifications to avoid exceptions can look like this:

function foo(sequence s) with spec -999
return length(s[1..$ - 5]) > 2
end function

i = foo(s) -- in case of exception in foo -999 is returned.

(very raw but just for example)

Design by Contract is just a start point - Euphoria developers are clever enough to continue.

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

106. Re: Try/Catch

I would say that:

include foo.e with spec -999

automatically applies 'with spec -999' to all routines in the plug-in module, and for the entire module. i.e. as soon as any routine is called - a module level exception will force it to return -999, which should be validate by the calling module as usual, using if...then.

just a very raw example for Specifications for the whole module.

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

107. Re: Try/Catch

...One thing is quite visible from the examples above - to handle exceptions with Specifications - functions must be used, since functions are able to return error codes. I think that's fair enough and accepted condition and may be implemented and verified this way or another.

Edit: Cleaning up resources is not a simple issue anyway. But defining precisely the behaviour of 'Specifications' can eliminate over-complexity. For example, if Specifications can/cannot be applied to module level exceptions, or to procedures (not functions), etc.

Edit: If Specifications should only be applied to functions, then delete_routine() can solve the problem of clean up.

Adding top level statement such as 'without spec' is also valuable option for debugging the code.

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

108. Re: Try/Catch

eukat said...

Choose a soft and gracefull fail, and it will do what the filesystem does: extend the sequence and return a {} or a null.

I have asked for this for years

I have some reservations about doing it this way. However, in the interests of furthering the discussion, I've implemented this (with the integer value of 0 representing null) in the equal branch: http://scm.openeuphoria.org/hg/euphoria/rev/1d9b443bd04b

Edit: Actually, just the two interpreters (C and Eu backends). I haven't tried to fix up the translator, since as mattlewis pointed out it would be a bit harder (since we're not even always doing the necessary bounds checks in the first place).

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

109. Re: Try/Catch

eukat said...

Choose a soft and graceful fail, and it will do what the filesystem does: extend the sequence and return a {} or a null.

I have asked for this for years

The idea that Euphoria just continues on merrily when it knows there was a logic error seems a fundamentally flawed idea, and I doubt many will accept it.

For things like handling strings, there are sensible defaults. But what's the correct behavior for fetching a non-existent index?

Languages built on .NET have getters and setters, so you can overwrite the default behavior for indexing. But that requires a concept of class, which Euphoria hasn't got.

Lua has an concept of fallback which can be used to extend the functionality of Lua, as well as serve as error handling. Perhaps someone on this forum has some experience with it?

So, for example, you could define what you consider sensible behavior to perform on indexing errors for your code without adversely effecting other people's code.

But even with that, there are still conditions where you would want to throw an exception.

- David

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

110. Re: Try/Catch

dcuny said...
eukat said...

Choose a soft and graceful fail, and it will do what the filesystem does: extend the sequence and return a {} or a null.

I have asked for this for years

The idea that Euphoria just continues on merrily when it knows there was a logic error seems a fundamentally flawed idea, and I doubt many will accept it.

<snip>

So, for example, you could define what you consider sensible behavior to perform on indexing errors for your code without adversely effecting other people's code.

But even with that, there are still conditions where you would want to throw an exception.

- David

This is why i said "choose". In the case you gave of the string being indexed out of bounds, the programmer should know there is no {} in their string. Getting a {} back indicates an error, but i would assume that in indexing by atom in that string, the programmer is looking at each atom for some reason, and would recognise a {}, and perform code accordingly.

If Eu provided a switch for "fail gracefully" or "crash dead", then you choose. I think it beats the programmer wrapping each and every variable access in bounds-checking code (which slows things down), which the compiled Eu intentionally doesn't do (so as to speed things up). For the example you gave.

useless

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

111. Re: Try/Catch

useless_ said...
dcuny said...
eukat said...

Choose a soft and graceful fail, and it will do what the filesystem does: extend the sequence and return a {} or a null.

I have asked for this for years

The idea that Euphoria just continues on merrily when it knows there was a logic error seems a fundamentally flawed idea, and I doubt many will accept it.

This is why i said "choose". In the case you gave of the string being indexed out of bounds, the programmer should know there is no {} in their string. Getting a {} back indicates an error, but i would assume that in indexing by atom in that string, the programmer is looking at each atom for some reason, and would recognise a {}, and perform code accordingly.

If Eu provided a switch for "fail gracefully" or "crash dead", then you choose. I think it beats the programmer wrapping each and every variable access in bounds-checking code (which slows things down), which the compiled Eu intentionally doesn't do (so as to speed things up). For the example you gave.

useless

An index error is a programming error. The programmer needs to know it to fix it. Why not do this:

1) Don't crash the program but return the element nearest the index value
2) Emit a console message warning of the out-of-bounds index

Wouldn't matter if it was in a procedure/function etc

Jim could add this to the interpreter in, like, 5 minutes.

Spock

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

112. Re: Try/Catch

Spock said...

An index error is a programming error. The programmer needs to know it to fix it.

Not necessarily. In the examples given of crashes, where a loop var is the length of a sequence, and inside the sequence the length is shortened, one could argue for the loop var not being cached. This has not been accepted by the developers of the Eu core.

Spock said...

Why not do this:

1) Don't crash the program but return the element nearest the index value

Because that is wrong. If the sequence is a basket, and the table is memory space, and i ask for the item on the table that is simultaneously the last thing in the basket, the answer isn't the last thing in the basket. The most correct answer (to avoid a crash when you have no try/recover) would be a $null, which the programmer can detect as an obvious error, but that's not acceptable in Euphoria either. The next best would be a "", but that isn't acceptable either.

Spock said...

2) Emit a console message warning of the out-of-bounds index

That's fine for the programmer developing the app, but it's not good for the end user. You may as well just crash with that message. There's several ways asked for to get around crashing. None are acceptable to the powers that be. Forcing the programmer to write bound-checks to each and every loop in each and every program isn't user-friendly, and stomps all over the concept of the compiled code intentionally stripping bounds-checking to speed up the crashing. I cannot help but think that DCuny has the same requests he (we, other people, etc) have made since the days of v2.5. We seek improvements to the core that we cannot add as include files. And i fear his (our, etc) requests will be as useless now as then.

useless

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

113. Re: Try/Catch

Shian_Lee said...

function foo(sequence s) with spec -999
return length(s[1..$ - 5]) > 2
end function

So you still have to catch it at the function level.

This seems to me less compelling than try/catch:

  1. No obvious implementation at the compiler level
  2. What happens with a procedure?
  3. try/catch provides a block of code, rather than a return value
  4. Need to invent error code values for each function (clunky when dealing with indexing)
  5. Have to add if/then after every call
  6. Unlike try/catch will not "bubble up" to appropriate level

- David

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

114. Re: Try/Catch

useless_ said...
Spock said...

An index error is a programming error. The programmer needs to know it to fix it.

Not necessarily. In the examples given of crashes, where a loop var is the length of a sequence, and inside the sequence the length is shortened, one could argue for the loop var not being cached. This has not been accepted by the developers of the Eu core.

.. and hopefully never will. In the meantime it remains a programming error.

useless_ said...
Spock said...

Why not do this:

1) Don't crash the program but return the element nearest the index value

Because that is wrong..

Yes, it is wrong but at least the program don't crash. What is right? Unless the programmer specifies the treatment in such a scenario there's no way the computer can figure it out. And if the programmer specifies it then he should really have corrected the bug that lead to that scenario in the first place.

useless_ said...

If the sequence is a basket, and the table is memory space, and i ask for the item on the table that is simultaneously the last thing in the basket, the answer isn't the last thing in the basket. The most correct answer (to avoid a crash when you have no try/recover) would be a $null, which the programmer can detect as an obvious error, but that's not acceptable in Euphoria either. The next best would be a "", but that isn't acceptable either.

If the programmer can detect a $null, he should really be detecting the index error instead since that is where the bug is. What place then for $null ?

useless_ said...
Spock said...

2) Emit a console message warning of the out-of-bounds index

That's fine for the programmer developing the app, but it's not good for the end user. You may as well just crash with that message.

Not so. The warning could advise the user that a serious error has occurred and suggest that they might save any data and shut the program down. A more sophisticated approach could also record a log file to be sent to the programmer.

useless_ said...

There's several ways asked for to get around crashing. None are acceptable to the powers that be. Forcing the programmer to write bound-checks to each and every loop in each and every program isn't user-friendly..

You overstate the problem. The vast majority of loops in a program will be plain enough to not require any such checks.

useless_ said...

I cannot help but think that DCuny has the same requests he (we, other people, etc) have made since the days of v2.5. We seek improvements to the core that we cannot add as include files. And i fear his (our, etc) requests will be as useless now as then.

You sure got that right .. Muahahaha!

If you're up for it you could always write your own core. That's what I'd like to do .. one day.


Spock

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

115. Re: Try/Catch

Spock said...
eukat said...
Spock said...

An index error is a programming error. The programmer needs to know it to fix it.

Not necessarily. In the examples given of crashes, where a loop var is the length of a sequence, and inside the sequence the length is shortened, one could argue for the loop var not being cached. This has not been accepted by the developers of the Eu core.

.. and hopefully never will. In the meantime it remains a programming error.

Actually - speaking as a dev - I don't see a compelling reason for this to be the case.

In Dredge, I implemented a wfor loop construct, which was identical to the for loop except for three things:

It didn't define a loop variable and unscope it at the end of the loop. You had to create one yourself. The benefit of this was that when the loop ended, the last known value of the loop variable would be preserved.

The ending condition was re-evaluated each time. So for example if the length of the sequence was used as the ending condition and the sequence was shortened inside the loop, this would be detected. (The trade-off here is that the ending condition was evaluated every single time, so if the value of the condition didn't change - which would cover the majority of cases of a for loop use - it was less efficient. Also, if one used an ending condition with side effects, those side effects would be triggered on every passof the loop, instead of just once.)

You could write to the loop variable and change its value.

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

116. Re: Try/Catch

dcuny said...
Shian_Lee said...

function foo(sequence s) with spec -999
return length(s[1..$ - 5]) > 2
end function

So you still have to catch it at the function level.

This seems to me less compelling than try/catch:

  1. No obvious implementation at the compiler level
  2. What happens with a procedure?
  3. try/catch provides a block of code, rather than a return value
  4. Need to invent error code values for each function (clunky when dealing with indexing)
  5. Have to add if/then after every call
  6. Unlike try/catch will not "bubble up" to appropriate level

- David

Yes, I do have to catch it in the function level - but only in the low-level implementation. The high-level implementation will only return error codes.

  1. Developer needs to do some deep thinking before implementing new ideas.
  2. Use only functions to deal with exceptions - not procedures.
  3. Return value from function is already part of Euphoria - why introducing a new and complex programming method to the end users? (and overhead is part of any high-level programming technique).
  4. Honestly, David, dealing with exceptions, using any possible method, is an art - it can never be done in a standard way. For example, in Assembly, when Carry Flag is set then what your program is doing?... It's only depends on what the program wants to do. It's like an art.
    So using error codes is the same, it's just that the end-user is already very-very familiar with this simple approach. When you really afraid of a specific indexing situation - place it in a different function which returns your desired error code (object).
  5. if...then is used everywhere anyway. It's less confusing then try/catch. In case I must call a function 1000 times, from too many places, I'll use another procedure or function to call that function, with the proper if..then. I already do it in these cases.
  6. I believe that dealing with returned error code immediately, is a much more reliable/logical technique. It might force some programmer to change their programming habits. Personally I believe that logical approach is more "Euphorian" then complex approach, which might be common in other languages. I don't offer something new to Euphoria: open(), dir(), seek(), etc, already using this approach, and we already using if...then to deal with it very clearly and easily.

p.s. If you felt insulted by me in previous posts... I'm sorry. It surely not your fault, it's all my fault since I'm a bit aggressive (my wife has to remind me that 30 times a day). So sorry.

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

117. Re: Try/Catch

Shian_Lee said...
dcuny said...

So you still have to catch it at the function level.

Yes, I do have to catch it in the function level - but only in the low-level implementation. The high-level implementation will only return error codes.

What is meant here is that one still needs to do manual checking after calling the function - you need to remember to write the if statement to check the return value. If you forget (or more likely, someone rewrites your library to make it faster and part of the rewrite is to remove those checks) then you've possibly introduced logic errors into the program.

(Of course, we could have the language enforce the checking of the specs, akin to the way that it would enforce that a 'try' block must be followed by either a 'catch' block or a 'finally' block. But that's a different discussion.)

Shian_Lee said...

Developer needs to do some deep thinking before implementing new ideas.

I don't think anyone has any reasonable objections to this.

Shian_Lee said...

Use only functions to deal with exceptions - not procedures.

The implication here is that if a procedure has something like a bad subscript, then the netire program crashes. Not nice. Also not consistent.

But, this is easy enough to deal with. For a procedure, you might have a 'spec ignore' in which case an otherwise fatal error would just have the procedure return to the caller without any sort of signal.

If the caller needs a way to know that the procedure suffered an error, then you could do have a 'spec variable NAME = CONSTANT' (e.g. 'spec variable ret = -1'), on which case a fatal error would simply set that variable to the specified constant. The caller could then check the variable to see if there was an error.

Shian_Lee said...

So using error codes is the same, it's just that the end-user is already very-very familiar with this simple approach.

But there's no way to tell what type of error occurred. You just know a fatal error happened. The return value doesn't specify if it was an index error, a slice error, a sequence found inside a character string, or some other error.

Shian_Lee said...

When you really afraid of a specific indexing situation - place it in a different function which returns your desired error code (object).

This isn't always practical.

Shian_Lee said...

if...then is used everywhere anyway.

In bugmagnet's source, one of the points of Design By Contract is to minimize this. Getting rid of if..then required by defensive programming improves readability.

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

118. Re: Try/Catch

There are minus and plus for each technique; exception handler and returned error codes.

Try/Catch has also its minus, for being a complex method, not so "Euphorian" in my opinion.

Both minus and plus of each method should be considered by the developers...

I vote for Simplicity, since it's a core concept of Euphoria programming language.

Edit: I prefer the general approach of open(), which doesn't tell me anything about the real problem (file-not-found/drive-not-exists/etc), because all I care about is if the task is done or not. Simple approach.

My personal programming style never make use of error handling, unless it's really necessary in some very specific situation. Big programs that I wrote (for salary calculation, work management, etc) without using a single error handler, served for many years.

I think that exception handling should be used as less as possible, or not at all, in a well written program. (Personal approach).

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

119. Re: Try/Catch

Again, like in 3 other issues:
Why not ask Robert Craig and his wife about their ideas as they conceived Eu

AND

How do we team up to tackle the issues in stead of bickering??

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

120. Re: Try/Catch

Ekhnat0n said...

Again, like in 3 other issues:
Why not ask Robert Craig and his wife about their ideas as they conceived Eu

Not a bad idea, but he hasn't posted on this forum since December 2010. He seems stay out of development these days, enjoying his retirement I guess.

While RobCraig's opinion would be helpful, it's not definitive. Remember, goto was added to the language even though RobCraig opposed it.

Ekhnat0n said...

AND

How do we team up to tackle the issues in stead of bickering??

Start coding, and posting the new code. The sooner we have code to grit our teeth on, the sooner we can get it finished.

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

121. Re: Try/Catch

Shian_Lee said...

p.s. If you felt insulted by me in previous posts... I'm sorry. It surely not your fault, it's all my fault since I'm a bit aggressive (my wife has to remind me that 30 times a day). So sorry.

Thanks! smile

I know that people are rightfully passionate about Euphoria, which is good.

- David

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

122. Re: Try/Catch

WHAT IF:
like I stated under The Strengths of Euphoria

I myself, assisted by a number of "old hands" would try and convince
Robert and his wife to enter into the discussion?

I am pretty sure we can find support somewhere else though I can't tell you about that issue YET

but I have a solid idea where to find such help

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

123. Re: Try/Catch

Before coding, I believe that a mature strategy must be defined more clearly.

RapidEuphoria.com welcome page:
"Euphoria programming language, Simpler then Basic, More Powerful then C++".

OpenEuphoria.org welcom page:
"Euphoria is a powerful but easy-to-learn programming language. It has a simple syntax and structure with consistent rules, and is also easy to read.".

Once you abandon your own obligation and belief, nobody else will take you seriously any more, and won't rely on your product any more.

While others, as Microsoft, may abandon their own obligations whenever they wish to, since they dominate the market by money, Euphoria simply can't; - doing so, might be the beginning-of-the-end of Euphoria.

I've seen it happening in the real world to entire companies. They started their way with very clear statements and promises for certain qualities - and after many years they had to give up their dream (to close), because they gave up their obligations to themselves and to their customers (slowly, invisibly, but surely).

Obligation to your own Strategy - is not a luxury.


Forked into: OpenEuphoria's Strategy

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

124. Re: Try/Catch

Shian_Lee said...

Once you abandon your own obligation and belief, nobody else will take you seriously any more, and won't rely on your product any more.

I'm not sure I see anything about try/catch that can be seen as "abandoning your own obligation."

Euphoria currently has no mechanism for recovering from exceptions.

Yet this is a feature that is expected from modern programming languages, because it is simply unacceptable for programs to shut down on errors and exceptions. Part of this expectation comes from the fact that other modern programming languages do handle exceptions and recover.

Because this is a reasonable expectation, the question is not if it should be done in Euphoria, but how it should be done.

That's the context of introducting try/catch.

So, what's wrong with other approaches?

Consider your with spec example for a moment:

function foo(sequence s) with spec -999 
    return length(s[1..$ - 5]) > 2 
end function 

In order for this to work, you need the value returned from foo to be one of two types: a valid value, or an error indicator.

Guaranteeing that your error value will never appear in range of acceptable values can be tricky, as anyone who's written code where the eof is indicated by -999 and then had that value appear in the data file can attest. blink

And that ignores that what constitutes an error flag will obviously change from routine to routine.

So at a higher level, you'll end up writing code that includes "magic numbers", which is always bad:

result = foo(s) 
if result = -999 then -- magic number 
    -- handle the error 
end if 
 
result = bar(s) 
if result = 99999 then -- another magic number 
    -- handle the error 
end if 
 
result = frotz(s) 
if equal(result,{-99999}) then -- yet another magic value 
    -- handle the error 
end if 

Obviously, you should define these "magic numbers" as constants. But since they can (potentially) change from routine to routine, how do you identify them?

Also, (as has already been mentioned), this solution only works with procedures, which makes it impractical.

But there's another problem: you have to make an error check after every routine call "just in case", or you'll miss an error condition.

And that isn't "simple."

In contrast, try/catch solves the problem much more elegantly. When an error or exception is encountered, it pops the call stack until an error handler is found, and then attempts to recover from the error.

Importantly, if there is no try/catch, the program behaves exactly as it does today. This means that you aren't forced to use this solution, and old code continues to perform as expected.

Compared with other solutions for recovering from exceptions, try/catch is simple, and flexible and easy to learn - all of which are (according to RDS) core features of Euphoria.

But if someone can come up with a solution that better fits these constraints, I'm all ears.

- David

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

125. Re: Try/Catch

Reply to David:

  1. Using 'spec' with procedures is possible as offered in previous post...
  2. We don't need magic error codes. In 99% I believe that -1 or {} will do.
  3. I already used error codes in DFS.E (DOS File System) for example. You can download it and see how consistent and easy it is. Actually I follow the principles of Euphoria 3.1.1 itself: -1 for FAIL to return a sequence; and Booleans for anything else. As far as I remember. Honestly, there was nothing more easy and clear then this. And that's the way I always work, and Euphoria as well.
  4. Of course, the need for a mature strategy is not about why Try/Catch - it's about how Try/Catch...! And not just for Try/Catch, but for anything else, now, and in the future. HOW is the keyword here.
  5. I have nothing against Try/Catch or ON ERROR GOTO or any other approach. I just believe that hiding Try/Catch in the low level and use error codes in the high level, will keep the language simple as it is. (imagine that 15 more complex and new programming methods will be added to the language... that's getting really really confusing and less simple then it meant to be...).
new topic     » goto parent     » topic index » view message » categorize

126. Re: Try/Catch

Shian_Lee said...

I have nothing against Try/Catch or ON ERROR GOTO or any other approach. I just believe that hiding Try/Catch in the low level and use error codes in the high level, will keep the language simple as it is.

I agree that foreseeable results should return error values, not exceptions.

I also agree that defensive coding is the best approach. Especially with Euphoria, where the sequence is the core datatype.

And relying on try/catch isn't a panacea. If it's triggered, it generally means that some portion of an application failed to execute properly.

That's bad, and needs to be avoided.

By way of analogy: try/catch allows you to keep running on three wheels when a tire has blown out.

- David

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

127. Re: Try/Catch

dcuny said...
Shian_Lee said...

Once you abandon your own obligation and belief, nobody else will take you seriously any more, and won't rely on your product any more.

I'm not sure I see anything about try/catch that can be seen as "abandoning your own obligation."

Euphoria currently has no mechanism for recovering from exceptions.

Yet this is a feature that is expected from modern programming languages, because it is simply unacceptable for programs to shut down on errors and exceptions. Part of this expectation comes from the fact that other modern programming languages do handle exceptions and recover.

Because this is a reasonable expectation, the question is not if it should be done in Euphoria, but how it should be done.

That's the context of introducting try/catch.

So, what's wrong with other approaches?

Consider your with spec example for a moment:

function foo(sequence s) with spec -999 
    return length(s[1..$ - 5]) > 2 
end function 

In order for this to work, you need the value returned from foo to be one of two types: a valid value, or an error indicator.

Guaranteeing that your error value will never appear in range of acceptable values can be tricky, as anyone who's written code where the eof is indicated by -999 and then had that value appear in the data file can attest. blink

And that ignores that what constitutes an error flag will obviously change from routine to routine.

So at a higher level, you'll end up writing code that includes "magic numbers", which is always bad:

result = foo(s) 
if result = -999 then -- magic number 
    -- handle the error 
end if 
 
result = bar(s) 
if result = 99999 then -- another magic number 
    -- handle the error 
end if 
 
result = frotz(s) 
if equal(result,{-99999}) then -- yet another magic value 
    -- handle the error 
end if 

Obviously, you should define these "magic numbers" as constants. But since they can (potentially) change from routine to routine, how do you identify them?

Also, (as has already been mentioned), this solution only works with procedures, which makes it impractical.

But there's another problem: you have to make an error check after every routine call "just in case", or you'll miss an error condition.

And that isn't "simple."

In contrast, try/catch solves the problem much more elegantly. When an error or exception is encountered, it pops the call stack until an error handler is found, and then attempts to recover from the error.

Importantly, if there is no try/catch, the program behaves exactly as it does today. This means that you aren't forced to use this solution, and old code continues to perform as expected.

Compared with other solutions for recovering from exceptions, try/catch is simple, and flexible and easy to learn - all of which are (according to RDS) core features of Euphoria.

But if someone can come up with a solution that better fits these constraints, I'm all ears.

- David

An easy solution to the Magic Number problem is simply to have a dedicated error variable automatically declared for each routine. With each call (func/proc) the var is reset and the 'address' is hidden inside the calling list. The Callee can set the error var by eg, ERR = 1 etc. Upon return the Caller then has the option to check the var (which to it is a private parameter and avoids any 'global' issues).

As for the tedium of having to check the error code each time, we do this already for calls like open() etc.. I think the error treatment of many calls is context dependent (ie, caller driven) and I personally prefer the freedom of being able to specifically choose when to check any error codes.

As for exceptions, I've already suggested defaulting to a safe, though likely incorrect, behaviour and alerting the user or developer in some way. The primary goal in a program should be correctness first and if the program misbehaves it should be stopped to be fixed. If your worried about losing all your precious data crash_routine() could perform an emergency save. Will try/catch (recovering from an exception) guarantee program correctness any more than the above robust error code idea? I strongly doubt it. An indexing exception could be catastrophic to the data and the correct treatment to 'recover' could be as varied as the number of routines that have sequence indexes. There doesn't seem to be any real escape from the proper amount of work needed to deal with these cases.

As for the elegance of try/catch, well, you got me there.

Spock

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

128. Re: Try/Catch

Spock said...

As for the tedium of having to check the error code each time, we do this already for calls like open() etc.. I think the error treatment of many calls is context dependent (ie, caller driven) and I personally prefer the freedom of being able to specifically choose when to check any error codes.

One thing try/catch does better is that if you forget to add a check, then the program crashes - so you get fail fast development. Your version doesn't seem to have that (unless you're suggesting that the interpreter crashes when it detects somehow that ERR is set but the caller doesn't check it).

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

129. Re: Try/Catch

jimcbrown said...
Spock said...

As for the tedium of having to check the error code each time, we do this already for calls like open() etc.. I think the error treatment of many calls is context dependent (ie, caller driven) and I personally prefer the freedom of being able to specifically choose when to check any error codes.

One thing try/catch does better is that if you forget to add a check, then the program crashes - so you get fail fast development. Your version doesn't seem to have that (unless you're suggesting that the interpreter crashes when it detects somehow that ERR is set but the caller doesn't check it).

You misunderstand. An error doesn't crash anything though the bad data that prompted it could cause havoc at a higher level. However, an exceptable situation already has a check inside the internal routine which, in the suggested scheme of things, will default to a 'safe' behaviour instead of crashing. That doesn't solve the program error in the first place but it can alert us to the fact.

So how is try/catch better?

Spock

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

130. Re: Try/Catch

Hi

jimcbrown said...
Spock said...

As for the tedium of having to check the error code each time, we do this already for calls like open() etc.. I think the error treatment of many calls is context dependent (ie, caller driven) and I personally prefer the freedom of being able to specifically choose when to check any error codes.

One thing try/catch does better is that if you forget to add a check, then the program crashes - so you get fail fast development. Your version doesn't seem to have that (unless you're suggesting that the interpreter crashes when it detects somehow that ERR is set but the caller doesn't check it).

I do not say 'copy this' but maybe you have a look at how other programming languages handle this problem.

Pascal (TurboPascal,Delphi,FPC) use, since the beginning, a compiler switch {I-/+} or {$IOCHECKS OFF/ON}

In the old days if {$I+} is set than the compiler generates a Runtime Error and the is program crashing.
If {$I-} is set than only an ErrorCode is set, that you can check with reading 'IOResult' (it's a function internally and it's reset after reading it).

Nowadays {$I-} behaves the same way than 30 years before ;) 'except' you have a 'try' 'except' block. Than it raises a exception.

And even inside the 'except' block you can use {$I-} and {$I+} to prevent raising an exception in your exception handling (mixing both error check and axception handling).

So this concept gives you the choice to use Error Handling via results or Exception Handling or mix both. And this concept proofed to be working over decades.

Just to say that you are not talking about Exceptions 'OR' Error Codes. You can have both.

Andreas

(btw. there is also {$R-/+} and {$q-/+} for range checking and overflow....)

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

131. Re: Try/Catch

Spock said...

You misunderstand.

Okay... I'll give this a shot.

Spock said...

However, an exceptable situation already has a check inside the internal routine which, in the suggested scheme of things, will default to a 'safe' behaviour instead of crashing. That doesn't solve the program error in the first place but it can alert us to the fact.

How? How does it alert us to the fact that the situation occurred?

Spock said...

So how is try/catch better?

If one forgets to use it, then one is alerted to this fact when the relevant situtation occurs.

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

132. Re: Try/Catch

jimcbrown said...
Spock said...

However, an exceptable situation already has a check inside the internal routine which, in the suggested scheme of things, will default to a 'safe' behaviour instead of crashing. That doesn't solve the program error in the first place but it can alert us to the fact.

How? How does it alert us to the fact that the situation occurred?

Because the internal routine responsible instead of calling FatalError (or whatever it is) would emit a console message and return a default value (in the case of a function). As mentioned in an earlier post, a more sophisticated approach could be to also record the error in a log file to be sent to the developer, perhaps by way of a user-defined routine.

Spock

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

133. Re: Try/Catch

Spock said...

Because the internal routine responsible instead of calling FatalError (or whatever it is) would emit a console message and return a default value (in the case of a function).

Ok, this is reasonable. It wouldn't work 100% of the time (e.g. if the program is a console-based text editor and constantly refreshing the screen), but few things do.

Spock said...

As mentioned in an earlier post, a more sophisticated approach could be to also record the error in a log file to be sent to the developer, perhaps by way of a user-defined routine.

Not a bad idea. Perhaps we could even generate an ex.err (or cont.err) when this happens. The program keeps on running, but a record is made.

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

134. Re: Try/Catch

jimcbrown said...

Not a bad idea. Perhaps we could even generate an ex.err (or cont.err) when this happens. The program keeps on running, but a record is made.

With try/catch, you could decide what to do, and if the program should continue.

- David

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

135. Re: Try/Catch

dcuny said...

[With try/catch, you could decide what to do, and if the program should continue.

I think try/catch is on my short list of stuff I want in euphoria. I suspect it looks something like this:

  • Get 4.1 released
  • memstructs (and 64-bit Win32lib / IDE!)
  • try/catch

The next step is probably to start experimenting with the euphoria backend (eu.e) to get something working.

Matt

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

136. Re: Try/Catch

While fixing yet more bugs in Phix, I just realised something: there is a whole subset of non-recoverable exceptions.

Sure, if you've got an index out of bounds or a divide by zero, or in fact most things, recovery is perfectly reasonable.

But if you've got heap or stack corruption, then it's game over. There will have to be some, hopefully rare, non-catchable exceptions.

Just sayin,
Pete

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

137. Re: Try/Catch

petelomax said...

While fixing yet more bugs in Phix, I just realised something: there is a whole subset of non-recoverable exceptions.

Sure, if you've got an index out of bounds or a divide by zero, or in fact most things, recovery is perfectly reasonable.

But if you've got heap or stack corruption, then it's game over. There will have to be some, hopefully rare, non-catchable exceptions.

Just sayin,
Pete

Good catch, Pete.

Try please this thread, 14 years old:
http://openeuphoria.org/forum/35939.wc

Best Regards!
Igor Kachan


kinz

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

138. Re: Try/Catch

I like this stick-in-the-mud statement from 14 years ago:

Rob Craig said...

If exception handling is such a Good Thing, why do I have so many Windows programs on my machine (written in "modern languages" such as C++) crashing with disappointing frequency, and all I get is a message from the O/S: "program X has attempted an illegal operation and will be shut down". These modern programs don't detect their own error, apologize, or bow out gracefully.

Regards, Rob Craig

It's frustrating that such things people wanted from back then, are still not in OE, just because "blah doesn't have it, so i intentionally won't either". Can you imagine how much better OE would be today if OE had simply taken the request list of 15 years ago and put that stuff into OE right away, first thing, OE v1? Yeas folks, it's been 15 years, some of you have gotten married and now have teenage kids now, and OE is still sitting on that statement by Robert Craig (and other statements by other people) way back in the mists of time, pre-smart phone, pre-200GB hdd, pre-multicore Pentiums.

Kat

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

139. Re: Try/Catch

katsmeow said...

I like this stick-in-the-mud statement from 14 years ago:

Rob Craig said...

If exception handling is such a Good Thing, why do I have so many Windows programs on my machine (written in "modern languages" such as C++) crashing with disappointing frequency, and all I get is a message from the O/S: "program X has attempted an illegal operation and will be shut down". These modern programs don't detect their own error, apologize, or bow out gracefully.

Regards, Rob Craig

It's frustrating that such things people wanted from back then, are still not in OE, just because "blah doesn't have it, so i intentionally won't either". Can you imagine how much better OE would be today if OE had simply taken the request list of 15 years ago and put that stuff into OE right away, first thing, OE v1? Yeas folks, it's been 15 years, some of you have gotten married and now have teenage kids now, and OE is still sitting on that statement by Robert Craig (and other statements by other people) way back in the mists of time, pre-smart phone, pre-200GB hdd, pre-multicore Pentiums.

Kat

I was under the impression that we had moved towards a general acceptance of adding try/catch to the language.

However, it is such a big change, that it's hard to implement. (Heck, I think it'd be hard to do in 100% euphoria, changing only the euphoria backend. Nevermind C.)

So, we'll have it one day, just don't hold your breath waiting. I know that's a really terrible answer, but it's not like we can afford to pay someone full time to write this for us.

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

140. Re: Try/Catch

Jim, coincidently, i am listening to Tracy Chapman, a singer, who performed on a small stage i set up in Atlanta ~1986. That was 29 years ago, and the words of the song sound like they were written of the Ferguson murder of 2014, or nearly every day in every city and town today. My point is that waiting patiently accomplishes nothing. People are still asking what they asked for 15 years ago, and near as i can tell, we will still be waiting tomorrow and the following year.

So in OE, before calling any function, write where we are going, to a reserved space. For kicks and giggles, point a variable name at it, maybe that will be useful tomorrow, by someone who discovers OE tonight. Thereby, when there is an error, we will know where we came from, we can back up to a point perhaps we can resume executing, where the error is irrelavant. If nothing else, the error msg can be more illuminating.

It took all of a few seconds to figure how to do this with no speed hit on a 6502 system: watch the cpu's SYNC line, have a latch grab the interesting instructions and/or addys, store them to a section of ram somewhere, then inc the pointer counter. Memory map the whole couple of chips to somewhere, and point a variable at the pointer's output. Presto, you have a log of the previous interesting machine code addresses hit, and you incurred no performance penalty while doing so. My point being: sometimes the old way of doing things, and thinking well outside the box, can do seemingly wonderous things, with no waiting.

Kat

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

141. Re: Try/Catch

katsmeow said...

So in OE, before calling any function, write where we are going, to a reserved space. For kicks and giggles, point a variable name at it, maybe that will be useful tomorrow, by someone who discovers OE tonight. Thereby, when there is an error, we will know where we came from, we can back up to a point perhaps we can resume executing, where the error is irrelavant. If nothing else, the error msg can be more illuminating.

This is already done today - otherwise, we wouldn't be able to provide a call stack for a crash.

And yes, that call stack is viewable through include/euphoria/debug/debug.e

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

142. Re: Try/Catch

jimcbrown said...
katsmeow said...

I like this stick-in-the-mud statement from 14 years ago:

Rob Craig said...

If exception handling is such a Good Thing, why do I have so many Windows programs on my machine (written in "modern languages" such as C++) crashing with disappointing frequency, and all I get is a message from the O/S: "program X has attempted an illegal operation and will be shut down". These modern programs don't detect their own error, apologize, or bow out gracefully.

Regards, Rob Craig

It's frustrating that such things people wanted from back then, are still not in OE, just because "blah doesn't have it, so i intentionally won't either". Can you imagine how much better OE would be today if OE had simply taken the request list of 15 years ago and put that stuff into OE right away, first thing, OE v1? Yeas folks, it's been 15 years, some of you have gotten married and now have teenage kids now, and OE is still sitting on that statement by Robert Craig (and other statements by other people) way back in the mists of time, pre-smart phone, pre-200GB hdd, pre-multicore Pentiums.

Kat

I was under the impression that we had moved towards a general acceptance of adding try/catch to the language.

However, it is such a big change, that it's hard to implement. (Heck, I think it'd be hard to do in 100% euphoria, changing only the euphoria backend. Nevermind C.)

So, we'll have it one day, just don't hold your breath waiting. I know that's a really terrible answer, but it's not like we can afford to pay someone full time to write this for us.

I don't think there was any move towards a general acceptance of try/catch. The problem of programs aborting prematurely could be dealt with in a much simpler fashion using a local builtin error/status code. The change to programs (and Euphoria) would be minimal. It would have helped to sell the idea of try/catch if there had been good examples showcasing genuine advantages (over smart status code). I don't recall seeing any.

Spock

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

143. Re: Try/Catch

Spock said...

It would have helped to sell the idea of try/catch if there had been good examples showcasing genuine advantages (over smart status code). I don't recall seeing any.

This can't be caught with an error code:

a = s[BAD_INDEX] 

Given that Euphoria relies on sequences heavily, this is a problem.

An error of this sort can't be recovered from with error codes.

- David

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

144. Re: Try/Catch

dcuny said...

This can't be caught with an error code:

a = s[BAD_INDEX] 

Given that Euphoria relies on sequences heavily, this is a problem.

An error of this sort can't be recovered from with error codes.

- David

This kind of error should crash. It's an unrecoverable error/probable logic bug by definition.

if BAD_INDEX <= length(s) then 
    a = s[BAD_INDEX] 
else 
    -- handle error condition 
end if 
new topic     » goto parent     » topic index » view message » categorize

145. Re: Try/Catch

dcuny said...
Spock said...

It would have helped to sell the idea of try/catch if there had been good examples showcasing genuine advantages (over smart status code). I don't recall seeing any.

This can't be caught with an error code:

a = s[BAD_INDEX] 

Given that Euphoria relies on sequences heavily, this is a problem.

An error of this sort can't be recovered from with error codes.

- David

It can. I explained this already in an earlier post.

Spock

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

146. Re: Try/Catch

Spock said...

It can. I explained this already in an earlier post.

If you're referring to:

Spock said...

1) Don't crash the program but return the element nearest the index value
2) Emit a console message warning of the out-of-bounds index

Perhaps I should have been more clear with my language.

By "error code", I mean a returned value from call that indicates there was a problem executing the routine. As an example, if an open() routine fails to open a file, it returns an error code instead of a valid handle.

By "recover", I mean that the code stops executing code at the level where the error took place, and returns control to a higher level in the execution stack, which can act on the error condition.

Returning "the element nearest the index value" is only the correct action to take in a very narrow set of conditions.

Likewise, assuming that the end user will be knowledgeable enough to understand a console warning message is very unlikely.

Your solution effectively ignores the error condition, and continues execution despite knowing the result of the operation is in error.

For that reason, it fails to match the criteria.

- David

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

147. Re: Try/Catch

jaygade said...

This kind of error should crash. It's an unrecoverable error/probable logic bug by definition.

That's not necessarily true. It depends on what you're trying to do.

Using try/catch, it's possible for the top-level code determine what the best response should be.

- David

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

148. Re: Try/Catch

dcuny said...

Using try/catch, it's possible for the top-level code determine what the best response should be.

try/catch is probably the best solution. but it's not part of the Euphoria philosophy. it's not part of Euphoria at all. it's not simple. period.

if you implement try/catch for best response, then why using atoms? wouldn't it be much better to use integer, long, double, unsigned/signed, maybe nibble? why not in-line C code? I am not exaggerating - Euphoria has and should keep it's own identity/personality.

I assume that some modern Basic dialect could do the job very well. But with lots of built-ins and options, almost as C...

The idea of Euphoria is to be minimalist, readable and simple - so you'll be able to write reliable code, much more then C or Basic, therefore you don't really need error handler to wrap any block of code for just in case.

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

149. Re: Try/Catch

katsmeow said...

I like this stick-in-the-mud statement from 14 years ago:

Rob Craig said...

If exception handling is such a Good Thing, why do I have so many Windows programs on my machine (written in "modern languages" such as C++) crashing with disappointing frequency, and all I get is a message from the O/S: "program X has attempted an illegal operation and will be shut down". These modern programs don't detect their own error, apologize, or bow out gracefully.

Regards, Rob Craig

Are you seriously suggesting that Euphoria is stuck in the mud because of that "ancient philosopher" Rob Craig, and his ancient ideas?

I believe that Rob's vision is stuck in the mud because of our selfishness and pride.

And without Rob Pythagoras, sorry!, Rob Craig, we wouldn't be here at all.

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

150. Re: Try/Catch

Shian_Lee said...

The idea of Euphoria is to be minimalist, readable and simple - so you'll be able to write reliable code, much more then C or Basic, therefore you don't really need error handler to wrap any block of code for just in case.

Sadly, we DO need to wrap everything we do in error checking. You just cannot do "s = x[y]" because eventually it will crash. You must wrap it in bounds and length tests. Chances are, eventually when munging real life data, 'y' will be greater than length(x), or 'y' will be less than one, or x[y] will be a nested sequence, or 'x' will be "". Something will be wrong, and you must guess what all chances of crashing are, and code against them. You may say that makes for good coding, but i think it certainly isn't simple and minimalist coding.

Kat

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

151. Re: Try/Catch

katsmeow said...
Shian_Lee said...

The idea of Euphoria is to be minimalist, readable and simple - so you'll be able to write reliable code, much more then C or Basic, therefore you don't really need error handler to wrap any block of code for just in case.

Sadly, we DO need to wrap everything we do in error checking. You just cannot do "s = x[y]" because eventually it will crash. You must wrap it in bounds and length tests. Chances are, eventually when munging real life data, 'y' will be greater than length(x), or 'y' will be less than one, or x[y] will be a nested sequence, or 'x' will be "". Something will be wrong, and you must guess what all chances of crashing are, and code against them. You may say that makes for good coding, but i think it certainly isn't simple and minimalist coding.

Kat

+1

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

152. Re: Try/Catch

Shian_Lee said...
katsmeow said...

I like this stick-in-the-mud statement from 14 years ago:

Rob Craig said...

If exception handling is such a Good Thing, why do I have so many Windows programs on my machine (written in "modern languages" such as C++) crashing with disappointing frequency, and all I get is a message from the O/S: "program X has attempted an illegal operation and will be shut down". These modern programs don't detect their own error, apologize, or bow out gracefully.

Regards, Rob Craig

Are you seriously suggesting that Euphoria is stuck in the mud because of that "ancient philosopher" Rob Craig, and his ancient ideas?

I believe that Rob's vision is stuck in the mud because of our selfishness and pride.

And without Rob Pythagoras, sorry!, Rob Craig, we wouldn't be here at all.

I believe Rob is saying that since no other langage or OS has a feature, it should not be in Euphoria either. I feel the other way, that along with sequences, Euphoria should have other rare features, and other useful features.

Kat

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

153. Re: Try/Catch

It's really strange. While I am aware of few bugs related to indexes in my own programs (such as in QE editor, but I've lost its source), in most cases I already knew the length of the sequences and never had to check it. But, from any possible perspective: using length() is 10,000,000 times more sane approach then writing buggy code and let another code catch and throw it.

While I was writing the previous post, using LinuxMint 17.1 64bit, and the last stable version of Firefox, on my very clean and reliable laptop - Firefox just went on flames before I pressed post and I had to rewrite again.
My old QuickBasic program that serves for already 23 years, without any error handler, a quite big organization, never crashes. It's simply not buggy.

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

154. Re: Try/Catch

Shian_Lee said...

... is 10,000,000 times more sane approach then writing buggy code and let another code catch and throw it

No one is advocating intentionally writing buggy code.

Shian_Lee said...

My old QuickBasic program that serves for already 23 years, without any error handler, a quite big organization, never crashes. It's simply not buggy.

With all respect, a web browser is many magnitudes more complex than your QuickBasic program. Additionally, it relies on many library components (graphics rendering, handling plugins, memory management) that are beyond the control of the developer.

Having an attitude that people should be able to write programs that are "simply not buggy" is unrealistic.

- David

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

155. Re: Try/Catch

David,

  1. Kat was talking about wrapping code with try/catch instead of length() and bound checks; which made me thinking that writing buggy code is accepted approach.
  2. With all the respect, Euphoria is not Java or JavaScript or another multi-million investment. Therefore, if you wish to write 'Firefox' then you should consider using one of those monsters. But if you wish to operate a machine, manage a business, etc, then Euphoria has unique features to offer.

By the way, I hate using Firefox and such, but the forum requires "modern" features, which doesn't mean much to me personally.

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

156. Re: Try/Catch

Shian_Lee said...

By the way, I hate using Firefox and such, but the forum requires "modern" features, which doesn't mean much to me personally.

And yet, I use lynx to browse and post on the forum.

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

157. Re: Try/Catch

jimcbrown said...

And yet, I use lynx to browse and post on the forum.

...And yet, 15,000,000 US$ will not fall from the sky tomorrow, and yet the team is slowing down, and yet users are less interested in Euphoria (as far as I feel), and yet you don't ask yourselves why? The answer is simple - you cannot tell 20 programmers, even if they are the best, to work for free and successfully maintain a big project and big community. That's why it could be nice to stop competing with the big monsters, and to focus on realistic and practical targets.

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

158. Re: Try/Catch

Shian_Lee said...

...focus on realistic and practical targets.

But what are those? Anyways, if I judge it worth it to me to work on something like try/catch, I'll probably do so (assuming there isn't some consensus that we definitely shouldn't do that, which I don't think there is).

I'm definitely interested in what people think is an interesting or worthwhile feature to have. I'm a lot less interested in others' estimates of LOE required to get those features. There are some 4.0/1 features that required a heck of a lot of work that I wouldn't want to live without any more. I can definitely imagine a time when try/catch is one of those.

http://imgs.xkcd.com/comics/tasks.png

Matt

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

159. Re: Try/Catch

mattlewis said...

http://imgs.xkcd.com/comics/tasks.png

xkcd said...

In the 60s, Marvin Minsky assigned a couple of undergrads to spend the summer programming a computer to use a camera to identify objects in a scene. He figured they'd have the problem solved by the end of the summer. Half a century later, we're still working on it.

-Greg

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

160. Re: Try/Catch

Unfortunately, nothing is truly practical or realistic these days. The big cooperatives are eating all of us alive.

So, good luck and thanks for the good illustration.

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

161. Re: Try/Catch

dcuny said...
Spock said...

It can. I explained this already in an earlier post.

If you're referring to:

Spock said...

1) Don't crash the program but return the element nearest the index value
2) Emit a console message warning of the out-of-bounds index

Perhaps I should have been more clear with my language.

By "error code", I mean a returned value from call that indicates there was a problem executing the routine. As an example, if an open() routine fails to open a file, it returns an error code instead of a valid handle.

By "recover", I mean that the code stops executing code at the level where the error took place, and returns control to a higher level in the execution stack, which can act on the error condition.

Returning "the element nearest the index value" is only the correct action to take in a very narrow set of conditions.

Likewise, assuming that the end user will be knowledgeable enough to understand a console warning message is very unlikely.

Your solution effectively ignores the error condition, and continues execution despite knowing the result of the operation is in error.

For that reason, it fails to match the criteria.

- David

David,

To recover from, eg, a bad index, either there is recovery code inside try/catch construct or at the caller point. Recovery code is needed somewhere and it makes more sense to have it at the caller point.

How does your try/catch idea correctly know how to recover from a bad index? In 99.99% of cases it won't - unless you place it at the caller point. So why not just have an explicit test there anyway?

Try/catch won't somehow magically give you program correctness.

If the program accesses the error/status code inside the called routine the compiler will insist that the caller check this outside after each call. Or at least issue a warning so that the programmer knows about it. That would solve the issue of knowing where to check for errors.

I think the problem of a bad index is a very poor example to solve using try/catch. So you catch a bad index. Now what?

Spock

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

162. Re: Try/Catch

Shian_Lee said...

try/catch is probably the best solution.

OK, we're in agreement here.

Shian_Lee said...

but it's not part of the Euphoria philosophy. it's not part of Euphoria at all. it's not simple. period.

Following your argument to the logical conclusion, Euphoria should be frozen in stone forever where it is, with only bug fixes.

Shian_Lee said...

why not in-line C code?

You are aware that Euphoria supports in-line assembly, right?

Shian_Lee said...

The idea of Euphoria is to be minimalist, readable and simple - so you'll be able to write reliable code, much more then C or Basic, therefore you don't really need error handler to wrap any block of code for just in case.

Could you find me a quote for that? I accept that's what you want it to be. But as far as I can find, that's not part of the stated Euphoria philosophy. What it does say is that it is:

  • Simpler than Basic
  • More powerful than C++
  • The language is flexible, powerful, and easy to learn.

Euphoria only doesn't claim to be minimal, only simpler. Then again, it also boasts that it's "More powerful than C++".

I don't see where the claim "you don't really need error handler to wrap any block of code for just in case" comes from. Rather, the ReadMe file says (emphasis added):

Euphoria v3.1 Readme said...

Euphoria provides extensive run-time error checking for: out-of-bounds subscripts, uninitialized variables, bad parameter values for library routines, illegal value assigned to a variable, and many more. If something goes wrong you'll get a full error message, with a call traceback and a listing of variable values. With other languages you'll typically get protection faults with useless dumps of machine registers and addresses.

At one time, Euphoria was competing against languages that "get protection faults with useless dumps of machine registers and addresses."

But that's not really the case anymore.

The name Euphoria is an acronym: "End User Programming with Hierarchical Objects for Robust Interpreted Applications".

Without some way of dealing with exceptions, I don't see how Euphoria can claim to be "robust".

Google said...

Robust: ...(of a process, system, organization, etc.) able to withstand or overcome adverse conditions.

Rather, by design Euphoria is fragile. It's exactly equivalent to a C program with ASSERT left on. And there's a reason people don't leave ASSERT in production code.

- David

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

163. Re: Try/Catch

Spock said...

How does your try/catch idea correctly know how to recover from a bad index? In 99.99% of cases it won't - unless you place it at the caller point. So why not just have an explicit test there anyway?

It's not like I'm inventing a new concept here. It's been a standard feature in quite a few programming languages for some time now.

The short answer is: it doesn't know how to recover from a bad index. It know how to recover from a section of code that's been placed in a try block.

Spock said...

Try/catch won't somehow magically give you program correctness.

That's correct. It allows a program a structured way of dealing with exceptions.

Spock said...

If the program accesses the error/status code inside the called routine the compiler will insist that the caller check this outside after each call. Or at least issue a warning so that the programmer knows about it. That would solve the issue of knowing where to check for errors.

That's fine if a routine can return a status. A procedure can't, and neither can indexing.

Issuing a warning is really only useful if a programmer is the one using the program.

Spock said...

I think the problem of a bad index is a very poor example to solve using try/catch.

Why is it a poor example? It's the typical exception in Euphoria.

Spock said...

So you catch a bad index. Now what?

By definition, the code traverses up the call stack until it finds a catch clause to handle it.

Have you looked into how try/catch works before arguing against it?

- David

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

164. Re: Try/Catch

OK chaps. Can I just say that it appears, quite independently of each other, both Matt Lewis and myself have unilaterally decided exception handling should be implemented in OpenEuphoria and Phix respectively, when and if time allows, which is unlikely to be any time soon for either, and of course actually implementing it might very well uncover some really nasty and possibly insurmountable difficulties.

If you don't like it (and I don't, really) then don't use it (and I won't, probably). But (apart from the "yet" bit) it is not my place to tell others they cannot have it smile

Pete

PS to Mr Cuny: the subscript thing is a bit weak, the whole web browser or other big complicated program idea makes for a much stronger case, ie/eg if a video/audio/image file is corrupt, then a blank box with "error:plugin failure" or somesuch is way better than terminating the entire app, and obviously I agree with that wholeheartedly, as I hope would everyone else.

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

165. Re: Try/Catch

dcuny said...
Spock said...

If the program accesses the error/status code inside the called routine the compiler will insist that the caller check this outside after each call. Or at least issue a warning so that the programmer knows about it. That would solve the issue of knowing where to check for errors.

That's fine if a routine can return a status. A procedure can't, and neither can indexing.

Wrong. Any type of call or operation could "return" a status code - via PBR

dcuny said...

Issuing a warning is really only useful if a programmer is the one using the program.

The warning is really useful to the programmer to track down logic errors and useful for the user since they then have the option to gracefully shutdown the system. The warnings could be suppressed for production code. Although, I think a log file could be created as well.

dcuny said...
Spock said...

So you catch a bad index. Now what?

By definition, the code traverses up the call stack until it finds a catch clause to handle it.

So, to recover, you must explicitly write code to handle that case - there is no way around it. try/catch doesn't improve our programming. Doesn't make the code more concise, readable, understandable, stronger. I argue that having the recovery code right by the caller is better than having it anywhere else. A point which you have not (yet) denied.

Therefore, my argument remains: Where is the clear advantage of try/catch over smart status code?

Spock

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

166. Re: Try/Catch

May i request DCuny and other proponents of try/catch make a "project page" like Ryan suggested, with actual real life OE code which uses try/catch, with lots of what_ifs and whys and wherefores and pointers, showing just how this would work?

Kat

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

167. Re: Try/Catch

petelomax said...

OK chaps. Can I just say that it appears, quite independently of each other, both Matt Lewis and myself have unilaterally decided exception handling should be implemented in OpenEuphoria and Phix respectively, when and if time allows, which is unlikely to be any time soon for either, and of course actually implementing it might very well uncover some really nasty and possibly insurmountable difficulties.

Ok, fine.

Spock

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

168. Re: Try/Catch

Spock said...

I argue that having the recovery code right by the caller is better than having it anywhere else. A point which you have not (yet) denied.

Why do you feel this is a point that I need to rebut?

Have you used try/catch?

You can place the recovery code wherever you want, at whatever level you want.

- David

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

169. Re: Try/Catch

petelomax said...

OK chaps. Can I just say that it appears, quite independently of each other, both Matt Lewis and myself have unilaterally decided exception handling should be implemented in OpenEuphoria and Phix respectively, when and if time allows, which is unlikely to be any time soon for either, and of course actually implementing it might very well uncover some really nasty and possibly insurmountable difficulties.

Could you both also make the same decision concerning string execution? Thanks!

Kat

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

170. Re: Try/Catch

katsmeow said...

May i request DCuny and other proponents of try/catch make a "project page" like Ryan suggested, with actual real life OE code which uses try/catch, with lots of what_ifs and whys and wherefores and pointers, showing just how this would work?

Sorry, I sort of assumed that people understood how try/catch worked before arguing against it.

Clearly, that's not been the case.

Hopefully, people doing actual work on this (not me at this point) will be able to do this eventually.

- David

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

171. Re: Try/Catch

katsmeow said...

May i request DCuny and other proponents of try/catch make a "project page" like Ryan suggested, with actual real life OE code which uses try/catch, with lots of what_ifs and whys and wherefores and pointers, showing just how this would work?

Kat

Ok, here's something to think about. Here are the possible causes of a fatal crash i could find from a quick search of source\execute.e. Which ones of these could be redesigned to not necessarily be fatal? Whether or not try/catch is the solution, i think we should discuss how we can find alternatives self-destructing in these situations. (Don't forget to think outside of the box for this!)

RTFatal( sprintf( "'%s' has not been assigned a value", {SymTab[sym][S_NAME]} ) ) 
RTFatal( sprintf("Unknown opcode: %d", op ) ) 
RTFatal("A subscript must be an atom") 
RTFatal("argument list must be a sequence") 
RTFatal("argument to getenv must be a sequence") 
RTFatal("attempt to divide by 0") 
RTFatal("attempt to exit a function without returning a value") 
RTFatal("attempt to slice an atom") 
RTFatal("attempt to subscript an atom\n(assigning to it)") 
RTFatal("attempt to subscript an atom\n(reading from it)") 
RTFatal("Can't get remainder of a number divided by 0") 
RTFatal("cleanup must be an atom") 
RTFatal("Couldn't open ctrace.out") 
RTFatal("crash routine requires a valid routine id") 
RTFatal("device or file name must be a sequence") 
RTFatal("first argument of match() must be a non-empty sequence") 
RTFatal("first argument of match() must be a sequence") 
RTFatal("first argument of match_from() must be a non-empty sequence") 
RTFatal("first argument of match_from() must be a sequence") 
RTFatal("first argument of system() must be a sequence") 
RTFatal("for-loop increment is not an atom") 
RTFatal("for-loop limit is not an atom") 
RTFatal("for-loop variable is not an atom") 
RTFatal("invalid open mode") 
RTFatal("invalid routine id") 
RTFatal("invalid task id") 
RTFatal("lengths do not match on assignment to slice") 
RTFatal("Maximum of 20 user defined delete routines exceeded.") 
RTFatal("min and max times must be atoms") 
RTFatal("min and max times must be greater than or equal to 0") 
RTFatal("no task to run") 
RTFatal("number of executions must be greater than 0") 
RTFatal("repetition count is too large") 
RTFatal("repetition count must be an atom") 
RTFatal("repetition count must not be negative") 
RTFatal("second argument must be {min-time, max-time}") 
RTFatal("second argument of find() must be a sequence") 
RTFatal("second argument of find_from() must be a sequence") 
RTFatal("second argument of match() must be a sequence") 
RTFatal("second argument of match_from() must be a sequence") 
RTFatal("second argument of system() must be an atom") 
RTFatal("slice ends past end of sequence") 
RTFatal("slice length is less than 0") 
RTFatal("slice lower index is less than 1") 
RTFatal("slice lower index is not an atom") 
RTFatal("slice starts past end of sequence") 
RTFatal("slice upper index is not an atom") 
RTFatal("specify the routine id of a procedure, not a function or type") 
RTFatal("subscript must be an atom") 
RTFatal("subscript must be an atom\n(assigning to subscript of a sequence)") 
RTFatal("subscript must be an atom\n(reading an element of a sequence)") 
RTFatal("task min time must be <= task max time") 
RTFatal("true/false condition must be an ATOM") 
RTFatal("variable " & SymTab[a][S_NAME] & " has not been assigned a value") 
RTFatal(sprintf("%s() does not return a value", SymTab[sub][S_NAME])) 
RTFatal(sprintf("call to %s() via routine-id should pass %d arguments, not %d", {SymTab[sub][S_NAME], SymTab[sub][S_NUM_ARGS], length(val[b])})) 
RTFatal(sprintf("index (%d) out of bounds in match_from()", c )) 
RTFatal(sprintf("slice upper index is less than 0 (%d)", upper ) ) 
RTFatal(sprintf("the value returned by %s() must be assigned or used", SymTab[sub][S_NAME])) 
new topic     » goto parent     » topic index » view message » categorize

172. Re: Try/Catch

dcuny said...
katsmeow said...

May i request DCuny and other proponents of try/catch make a "project page" like Ryan suggested, with actual real life OE code which uses try/catch, with lots of what_ifs and whys and wherefores and pointers, showing just how this would work?

Sorry, I sort of assumed that people understood how try/catch worked before arguing against it.

Clearly, that's not been the case.

That's just it, i do want everyone to be on the same page, literally and figuratively. There's a slight hint of cross-communication going on, and details on real-world examples may help.

dcuny said...

Hopefully, people doing actual work on this (not me at this point) will be able to do this eventually.

- David

I cannot think of anyone better suited to do the page than you, at this point. Others may code it (eventually), but you've already written more about it in this thread than a project page about it would need. I think this would help the devs coding it, to have input on how an OE flavor could be put to the functionality.

Kat

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

173. Re: Try/Catch

ryanj said...

Here are the possible causes of a fatal crash. Which ones of these could be redesigned to not necessarily be fatal?

Offhand I'd say all of them, perhaps bar "Unknown opcode: %d", as that rather suggests something pretty dire has just happened. There are also lower-level stack and heap corruptions that absolutely deserve to be fatal, since in the first case you probably can't find the exception handling logic and in the second case it will almost certainly fail pretty soon with a strikingly similar error. Unfortunately such things may be rather difficult to distinguish from run-of-the-mill errors, but when you do know it really is that bad, you gotta be brutal, and no-one should pretend it simply does not happen, especially not the documentation. If you're wanting guaranteed 24/7 operation, you should be thinking failover cluster and monitor app anyway.

ryanj said...

Whether or not try/catch is the solution

Ah, that is quite limiting. You could possibly return meaningless made-up values that make debugging ridiculously difficult for a fair number, but I'm not playing that game.


On the usage front, first thing I'd like to see in any documentation is that something like:

try 
   play_video() 
catch e 
   display_at(40,40,"video not found or corrupt") 
end try 

is fine, and really your only option if play_video() is some third party component you would rather not modify with the nasty habit of bringing down your entire app, whereas:

procedure main() 
    try 
       ... 
    catch e 
       -- do absolutely nothing, not even quietly write to a log file 
    end try 
end procedure 

is just plain wrong, and one day will inevitably bite both you and your users on the behind, because you just effectively made everyone completely and utterly blind.

Pete

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

174. Re: Try/Catch

katsmeow said...

May i request DCuny and other proponents of try/catch make a "project page" like Ryan suggested, with actual real life OE code which uses try/catch, with lots of what_ifs and whys and wherefores and pointers, showing just how this would work?

The syntax is standard across most languages:

try 
   -- code 
catch e 
   -- exception handling 
end try 

On an exception, the code jumps to the start of the most inner catch. If no catch block is in the current routine, the call stack is traversed. If no catch is active at all, the code fails, exactly as it currently does today.

There is no requirement that either the try or catch block actually contain code.

try/catch can be nested:

-- exceptions here are passed up the call stack 
try 
   -- exceptions here are handled by e2 
   try 
      -- exceptions here are handled by e1 
   catch e1 
      -- exceptions here are handled by e2 
   end try 
   -- exceptions here are handled by e2 
catch e2 
   --- exceptions here are passed up the call stack 
end try 
-- exceptions here are passed up the call stack 

Here's an example:

try 
   try 
      -- throw an exception 
      throw("first exception") 
 
      -- this is never reached 
       
   catch e1 
      -- handle the first exception 
      puts(1, e1[EXCEPTION_MESSAGE]) 
 
      -- throw a new exception 
      throw("second exception") 
 
      -- this code is never reached 
 
   end try 
 
   -- this code is never reached 
 
catch e2 
   -- display the second exception here 
   puts(1, e2[EXCEPTION_MESSAGE] 
 
   -- there is no outer catch, so this would halt Euphoria 
   throw("third exception") 
 
end try 

Here's an example of an exception being thrown in deep into a call. The call stack is unwound until the catch at the top level is called:

 
try 
   main() 
catch e 
   -- handles the exception 
   puts(1, "Ooops: " * e[EXCEPTION_MESSAGE]) 
end try 
 
 
procedure main() 
   foo() 
end procedure 
 
procedure foo() 
   -- throw an exception 
   throw("my exception") 
end procedure 
 

An exception is a sequence. It typically contains:

  • The error message text
  • The call stack trace data structure

A routine to convert the call stack data structure into a printable format is usually provided.

Any call to RTFatal would throw an exception.

User-defined exceptions can the thrown via throw().

I don't believe there was much demand for finally. Since the implementation makes things considerably more complex, I suggest we leave it out of this iteration.

I think this describes most of the behavior or try/catch, but not really any of the implementation details.

- David

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

175. Re: Try/Catch

David,

According to your explanation of Try/Catch syntax and behaviour - it has no place in Euphoria - it behaves like 'stoned goto'.

Spock's smart error code which is available to the caller is the real thing. I would say that using only functions for retrieving the smart error code is even more mature. No need to wrap the whole program/plug-in with error handler. If it's that bad - then get rid of it.

In martial art sports, you got light-weight, medium, heavy... in think in Taekwondo there about 7 or more different weights (I don't remember at all).
Then what you are suggesting is to take Euphoria (Mosquito-weight) and compete against C++ or Java (Very-Heavy-weight) - for what? for rewriting Firefox? for reinventing the wheel?

Euphoria users don't need that 'goto under L.S.D' called 'Try/Catch' - a simple error code available to the caller is enough for the scale and weight of Euphoria.

No - I don't want Euphoria to be frozen on stone (which is almost is) - I want to revive it. But apparently Euphoria is not going to be simple anymore. And not fun. If it will be at all, since OpenEuphoria strategy is dreamy.

If you want all options to be available in Euphoria - then just use some multi-million $ language. Why waste your time? Tell your costumers that we are living in "modern" time, and that they have to adopt themselves to Java, advs, viruses and fat.

Come on, are you going to wait till stable version 4.5 will be out? Euphoria has no money. face it and move on. there are so many languages out there.

I might do the same - or just go back to where I came from - picking oranges and weeding. It's better then paying for features I've never asked for.

Let's go pick oranges (you live in California, don't you?) - less money, less worries. smile

ps. I'm not sure that Euphoria users must have the 'Eighth Passenger/Alien' named 'eval' in their arsenal as well.

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

176. Re: Try/Catch

Here is how I would program Try/Catch:

if err
> get errno
> set errno-flag
> on errno do
>> err-handling(errno)
>>reset this-errno-flag
>>errno+1
>> while err-flag-field
endif

that's all and treats all errors in numeric flag-order.
err-flag-field should be a bit-variable for saving space

the asm commands
bset
bclr
bchg
are among the fastest you can find

ekhnaton's solution so to say
logic applied all over

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

177. Re: Try/Catch

Shian_Lee said...

According to your explanation of Try/Catch syntax and behaviour - it has no place in Euphoria - it behaves like 'stoned goto'.

try/catch defines the scope of an exception handler. If an exception is thrown within the scope of an catch clause, it stops executing code (because that would lead to incorrect behavior), and jumps to the handler.

There's nothing "stoned" about this.

Shian_Lee said...

Spock's smart error code which is available to the caller is the real thing. I would say that using only functions for retrieving the smart error code is even more mature. No need to wrap the whole program/plug-in with error handler. If it's that bad - then get rid of it.

The "smart error code" only works for a limited set of exceptions, ignores the most common cases, and continues to run code when Euphoria knows that the results will be wrong.

Since incorrect indexes are the most common exception in Euphoria, you're suggesting that we adopt a solution known to leave the majority of use cases in place.

Shian_Lee said...

Then what you are suggesting is to take Euphoria (Mosquito-weight) and compete against C++ or Java (Very-Heavy-weight) - for what? for rewriting Firefox? for reinventing the wheel?

The argument that Euphoria is minimal is your own conclusion.

The claim is that Euphoria is also "More powerful that C++". That "power" doesn't come from having less than C++.

Shian_Lee said...

Euphoria users don't need that 'goto under L.S.D' called 'Try/Catch' - a simple error code available to the caller is enough for the scale and weight of Euphoria.

Except that it doesn't catch the vast majority of exceptions.

Why claim that it behaves like "goto under L.S.D.". Please offer some sort of support for this, because I don't see it. Rather, it behaves in a structured, reliable manner when an exception is thrown.

Shian_Lee said...

No - I don't want Euphoria to be frozen on stone (which is almost is) - I want to revive it. But apparently Euphoria is not going to be simple anymore. And not fun. If it will be at all, since OpenEuphoria strategy is dreamy.

The mindset that Euphoria had to be minimalist is what caused a great many power users - like myself - to abandon it.

I was so frustrated with the glacial pace of Euphoria that I even wrote my own version in C from scratch.

Shian_Lee said...

If you want all options to be available in Euphoria - then just use some multi-million $ language. Why waste your time? Tell your costumers that we are living in "modern" time, and that they have to adopt themselves to Java, advs, viruses and fat.

"More powerful than C++"

And we are living in "modern" times.

Shian_Lee said...

Come on, are you going to wait till stable version 4.5 will be out? Euphoria has no money. face it and move on. there are so many languages out there.

So you're literally telling me to leave?

- David

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

178. Re: Try/Catch

Hello David,

Please look over my handler better.

If you wish to cooperate please do so.
You and Kat and me together can bring U4IA or (almost) AI4U.

ekhnaton

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

179. Re: Try/Catch

dcuny said...

I was so frustrated with the glacial pace of Euphoria that I even wrote my own version in C from scratch.

Really? Where can we find this? I am just curious to peruse the code.

dcuny said...

So you're literally telling me to leave?

No, definitely not. No one is telling you to leave. Welcome back, David. We love you. We need you. Please stay forever. grin

-Greg

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

180. Re: Try/Catch

hi greg,

iirc your name was on my mail-address-list back in 2003/2004 too

remember ekhnaton (ekkie) from the IRC-channel on sorcery?

that was me

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

181. Re: Try/Catch

Ekhnat0n said...

Please look over my handler better.

Will do.

- David

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

182. Re: Try/Catch

dcuny said...

Since incorrect indexes are the most common exception in Euphoria, you're suggesting that we adopt a solution known to leave the majority of use cases in place.

I've been thinking about this. We don't currently do any bounds checking in compiled code. The standard line (since the translator came into being) was that you would debug your code in the interpreter and then port over. Some of the speedup is that the bounds checking isn't done. So these turn into segfaults or other low level memory errors.

So, in translated code, we could ignore this particular type of exception. We could start adding bounds checking everywhere. We could detect when code is directly inside a try block and add bounds checking / exception throwing code. The translator would have to do a lot of checks to determine which functions are called inside of a try block (we already do a lot of iteration, so this isn't the end of the world). Similar issues apply for other translator things where we omit error checking.

Explicit throws seem easier to figure out.

Matt

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

183. Re: Try/Catch

ghaberek said...

Really? Where can we find this? I am just curious to peruse the code.

I'm not sure I could even find the code at this point. I basically decided that it wasn't worth pursuing because I didn't want to compete with Robert, and it wasn't going to convince him to change Euphoria anyway. So it ended up morphing into the core data structure in wxBasic - basically a dynamic growable array.

Robert's code is much cooler than mine was. For example, my interpreter was a stack-based VM, which is guaranteed to run much slower than Euphoria.

If I gained any insight, it was that the core idea behind Euphoria is using bits to indicate the data type. This - and not some concept of minimalism - is what limits the number of data types that you've got. That's why Euphoria only has three datatypes: the first bit indicated if it was a 31 bit integer or a pointer, and the second bit indicated if the 30 bit pointer to an atom, or 30 bit pointer to a structure.

Only having 30 bits means you align all your pointers to 4 byte boundaries, but that's an acceptable loss for the resulting speed gain.

The rest is mostly just details of reference counting - something that's really, really easy to get wrong. But there's nothing magical about it - just attention to details.

That's how I implemented it, anyway. It's been a while since I've looked at the actual Euphoria internals, so the implementation of atoms may be different. But the core limitation remains the same.

- David

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

184. Re: Try/Catch

Robert has given me personally per email
green light 4 bringing U4IA in the 21st century

wkr
antoine

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

185. Re: Try/Catch

Ekhnat0n said...

Hello David,

Please look over my handler better.

If you wish to cooperate please do so.
You and Kat and me together can bring U4IA or (almost) AI4U.

ekhnaton

To be clear, i have not agreed to do anything with Ekhnat0n, in fact i am not accepting any email from him. Do not consider him using my nick as an endorsement on his projects.

Kat

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

186. Re: Try/Catch

katsmeow said...

To be clear, i have not agreed to do anything with Ekhnat0n, in fact i am not accepting any email from him. Do not consider him using my nick as an endorsement on his projects.

Kat

Sorry Kat,

I really had hope you would cooperate on this project.
My sincere apologies for mis-understanding you.

Respectfully,

Antoine

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

187. Re: Try/Catch

Ekhnat0n said...

if err
> get errno
> set errno-flag
> on errno do
>> err-handling(errno)
>>reset this-errno-flag
>>errno+1
>> while err-flag-field
endif

You said this is how you would implement try/catch, but I don't see a correspondence between your code and how try/catch behaves.

Is this an alternative solution for exception handling? Sorry, I'm just not clear what you are proposing here.

Ekhnat0n said...

the asm commands
bset
bclr
bchg
are among the fastest you can find

Euphoria is coded in C, not assembly.

Speed of handling exceptions is generally not critical, since they are, well, exceptions.

On the other hand, the overhead of the implementation is a factor.

- David

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

188. Re: Try/Catch

Hello David,

For ErrNo you can read ExeptNr
thus catching any series of exceptions in a row,
and asm is always fastest, because C is coded in it and interpreted/compiled.

All over my coding for a next generation Euphoria
I do the most important and most used bits in assembler
for the sake of optimum speed.
And Euphoria has the option for doing so.

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

189. Re: Try/Catch

Ekhnat0n said...


And Euphoria has the option for doing so.

This is true, but I'm not very good at assembler, and we currently have three different types of assembly we'd have to write. You think people complain about ifdefs now? smile

Matt

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

190. Re: Try/Catch

I can do any 86 and any 68K assembly as wel as AMD athlon
single or dual core makes no difference imo

That's where having started back in the mid 60's
gives me a nice edge now, agree?

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

191. Re: Try/Catch

Ekhnat0n said...

I can do *86 and any 680 assembly as wel as AMD athlon
single or dual core makes no difference imo

That's where having started back in the mid 60's
gives me a nice edge now, agree?

Nah. We'd still need x86-64 and arm assembly (and actually, there's more than one kind of arm assembly language).

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

192. Re: Try/Catch

any basic-commands in any proglan will be easy to learn
at least for me they will be as they all
need to do more or less the same action logically

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

193. Re: Try/Catch

Ekhnat0n said...

any basic-commands in any proglan will be easy to learn
at least for me they will be as they all
need to do more or less the same action logically

Then please rewrite http://scm.openeuphoria.org/hg/euphoria/file/a130176706bc/source/be_callc.c in all three assembly languages - x86_64 and ARM (we already hav the x86 version, but you can rewrite that too).

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

194. Re: Try/Catch

jimcbrown said...
Ekhnat0n said...

any basic-commands in any proglan will be easy to learn
at least for me they will be as they all
need to do more or less the same action logically

Then please rewrite http://scm.openeuphoria.org/hg/euphoria/file/a130176706bc/source/be_callc.c in all three assembly languages - x86_64 and ARM (we already hav the x86 version, but you can rewrite that too).



>>>Hello Jim,
How urgent is this issue?

As I have hardly any time to spare over the next 4 weeks
due to having started 4 different new franchises
along with finally setting up my own ICT-firm and building the machine to drive it
My mailbox is running wild with requests for all of the franchises.

Would it be soon enough if it would be done by the end of March??
Remember I will have to learn 2 new asm-langs as well!
GRINNNzzzz ROFLMAO
How about announcing it for AprilFoolsDay next??
(It happens to be my dad's Bday. He died in late spring/early summer 1971 of hart-attack)
Regards
>>>Antoine

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

195. Re: Try/Catch

Ekhnat0n said...

Would it be soon enough if it would be done by the end of March??

Yes, that's fine.

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

196. Re: Try/Catch

jimcbrown said...
Ekhnat0n said...

Would it be soon enough if it would be done by the end of March??

Yes, that's fine.

Consider it done

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

197. Re: Try/Catch

Just a question: Why OpenEuphoria dont use libffi( https://sourceware.org/libffi ) for C calls like everybody else?

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

198. Re: Try/Catch

elias_maluko said...

Just a question: Why OpenEuphoria dont use libffi for C calls like everybody else?

I wasn't aware of it, let alone that everybody else used it. Looks like we probably should. Thanks for the pointer.

Matt

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

199. Re: Try/Catch

dcuny said...
Shian_Lee said...

Spock's smart error code which is available to the caller is the real thing. I would say that using only functions for retrieving the smart error code is even more mature. No need to wrap the whole program/plug-in with error handler. If it's that bad - then get rid of it.

The "smart error code" only works for a limited set of exceptions, ignores the most common cases, and continues to run code when Euphoria knows that the results will be wrong.

Since incorrect indexes are the most common exception in Euphoria, you're suggesting that we adopt a solution known to leave the majority of use cases in place.

These claims are extremely confused.

Smart Status Code can be activated in any called routine/operation that might care to throw an error. It is a lot like the error codes of the GO language (which abhors exceptions). The returned code can indicate different levels of severity. The most severe ones will prompt the compiler to insist that the caller handle it. This could mean correcting the bad data OR propagating the error up to the next calling level OR even resetting the status code.

The implication that Exceptions can somehow handle bad indexes better than SSC is just a red herring.

Spock

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

200. Re: Try/Catch

Spock said...
dcuny said...
Shian_Lee said...

Spock's smart error code which is available to the caller is the real thing. I would say that using only functions for retrieving the smart error code is even more mature. No need to wrap the whole program/plug-in with error handler. If it's that bad - then get rid of it.

The "smart error code" only works for a limited set of exceptions, ignores the most common cases, and continues to run code when Euphoria knows that the results will be wrong.

Since incorrect indexes are the most common exception in Euphoria, you're suggesting that we adopt a solution known to leave the majority of use cases in place.

These claims are extremely confused.

Smart Status Code can be activated in any called routine/operation that might care to throw an error. It is a lot like the error codes of the GO language (which abhors exceptions). The returned code can indicate different levels of severity. The most severe ones will prompt the compiler to insist that the caller handle it. This could mean correcting the bad data OR propagating the error up to the next calling level OR even resetting the status code.

The implication that Exceptions can somehow handle bad indexes better than SSC is just a red herring.

Spock

I think I can see how this would work.

Say we do this:

sequence s = "" 
object x = s[1] 

Since it's an invalid index, we return a special value. It's represented by a new builtin constant, ERR_IDX.

? x 

Output:

{{{ ERR_IDX }}}}

So, you can test x to see if the slice was successful, or if an error occured. (Internally, for OE, we'd use one of the remaining unused type codes to represent errors, and the rest of the bits would just be an enum for each kind of error we coudl return.)

We'd also have a global builtin variable, called ErrNo. Everytime a function returns with one of the builtin error constants, or an operation like slicing returns an error constant, ErrNo gets set to the same value.

If a procedure is called and has an error, ErrNo is also set.

These special constants would be designed so that one could assign them to an atom, an integer, or a sequence. So any variable could safely hold one of these values.

That said, I think this is much uglier than try/catch. dcuny, you can take it from here.

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

201. Re: Try/Catch

jimcbrown said...

So, you can test x to see if the slice was successful, or if an error occured.

...

That said, I think this is much uglier than try/catch. dcuny, you can take it from here.

Whether it's ugly or not, it's much more passive, unless there's some equivalent to try / catch blocks that I'm not seeing.

Matt

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

202. Re: Try/Catch

jimcbrown said...
Spock said...
dcuny said...
Shian_Lee said...

Spock's smart error code which is available to the caller is the real thing. I would say that using only functions for retrieving the smart error code is even more mature. No need to wrap the whole program/plug-in with error handler. If it's that bad - then get rid of it.

The "smart error code" only works for a limited set of exceptions, ignores the most common cases, and continues to run code when Euphoria knows that the results will be wrong.

Since incorrect indexes are the most common exception in Euphoria, you're suggesting that we adopt a solution known to leave the majority of use cases in place.

These claims are extremely confused.

Smart Status Code can be activated in any called routine/operation that might care to throw an error. It is a lot like the error codes of the GO language (which abhors exceptions). The returned code can indicate different levels of severity. The most severe ones will prompt the compiler to insist that the caller handle it. This could mean correcting the bad data OR propagating the error up to the next calling level OR even resetting the status code.

The implication that Exceptions can somehow handle bad indexes better than SSC is just a red herring.

Spock

I think I can see how this would work.

Say we do this:

sequence s = "" 
object x = s[1] 

Since it's an invalid index, we return a special value. It's represented by a new builtin constant, ERR_IDX.

? x 

Output:

{{{ ERR_IDX }}}}

No.

Two values are returned. The status code is returned in parallel to the function return. This also means it'll work for procedures etc..

In your example it'd be:

sequence s = "" 
object x = s[1] -- no crash 
? x -- {} 
? ERRNO -- BAD_INDEX 
 

However, I think bad indexes are a poor example (in the context of the topic) since they are programming errors that must be corrected rather than somehow "managed". Certainly, in program development a bad index should cause a crash so I can fix the problem. For program deployment the behaviour will revert to above (with signalling).

Spock

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

203. Re: Try/Catch

mattlewis said...
jimcbrown said...

So, you can test x to see if the slice was successful, or if an error occured.

...

That said, I think this is much uglier than try/catch. dcuny, you can take it from here.

Whether it's ugly or not, it's much more passive, unless there's some equivalent to try / catch blocks that I'm not seeing.

Matt

The "equivalent" is inside the internal routine. So, crash during development, allow with default value in deployment. How would try/catch recover from a bad index? Resume with a default value perhaps?

Spock

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

204. Re: Try/Catch

Spock said...

The "equivalent" is inside the internal routine. So, crash during development, allow with default value in deployment.

Oh, right, forgot about the default value proposal. I really don't like that idea.

Matt

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

205. Re: Try/Catch

mattlewis said...
Spock said...

The "equivalent" is inside the internal routine. So, crash during development, allow with default value in deployment.

Oh, right, forgot about the default value proposal. I really don't like that idea.

Matt

What value would you use instead?

Spock

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

206. Re: Try/Catch

Spock said...
mattlewis said...
Spock said...

The "equivalent" is inside the internal routine. So, crash during development, allow with default value in deployment.

Oh, right, forgot about the default value proposal. I really don't like that idea.

Matt

What value would you use instead?

Spock

There are a couple of other things we could use, such as leaving the variable unchanged, reseting the variable back to being uninitialized, or a new builtin constant that is a value but is not an integer, atom, or sequence (e.g. ERR_IDX). But I think that from Matt's POV, they all share the same problem - whereas, try/catch doesn't.

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

207. Re: Try/Catch

jimcbrown said...
Spock said...
mattlewis said...
Spock said...

The "equivalent" is inside the internal routine. So, crash during development, allow with default value in deployment.

Oh, right, forgot about the default value proposal. I really don't like that idea.

Matt

What value would you use instead?

Spock

There are a couple of other things we could use, such as leaving the variable unchanged, reseting the variable back to being uninitialized, or a new builtin constant that is a value but is not an integer, atom, or sequence (e.g. ERR_IDX). But I think that from Matt's POV, they all share the same problem - whereas, try/catch doesn't.

The best value is the correct value that the programmer intended. If try/catch can magically know what that is then Great! But that just begs the question of why the programmer didn't correct the logic error that led to the exception being raised in the first place!

"they all share the same problem" - not stated what this is
"whereas, try/catch doesn't" - not stated how this is any better

This is just handwaving.

Spock

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

208. Re: Try/Catch

Spock said...

The best value is the correct value that the programmer intended. If try/catch can magically know what that is then Great!

The reason that it knows that is because the programmer has to explicitly set the value in the catch statement - there's no magic to it.

Spock said...

But that just begs the question of why the programmer didn't correct the logic error that led to the exception being raised in the first place!

Err - http://en.wikipedia.org/wiki/Begging_the_question

I'm going to rewrite that as:

said...

But that just asks the question of why the programmer didn't correct the logic error that led to the exception being raised in the first place!

Probably for the same reasons that some callers of open() check the return value to see if it's -1, instead of trying to prove that the file exists and permission to read it is granted before calling open() and then gets().

Spock said...

"they all share the same problem" - not stated what this is

The problem is that whatever value that ends up in the variable, it's not obvious that the variable has now been set to this. It's also not necessarily obvious that this happened at all (that the variable got a "default" value instead of having the operation be successful and getting a real value back).

Spock said...

"whereas, try/catch doesn't" - not stated how this is any better

This doesn't have the issue because one generally sets the variable explicitly in this case. Also, the flow of execution is deliberately interrupted here, which makes it clearer that something went wrong.

Spock said...

This is just handwaving.

Spock

No, it isn't.

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

209. Re: Try/Catch

Spock said...
mattlewis said...
Spock said...

The "equivalent" is inside the internal routine. So, crash during development, allow with default value in deployment.

Oh, right, forgot about the default value proposal. I really don't like that idea.

What value would you use instead?

No value. Substituting some default value would be worse than what we have now.

Matt

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

210. Re: Try/Catch

mattlewis said...
Spock said...
mattlewis said...
Spock said...

The "equivalent" is inside the internal routine. So, crash during development, allow with default value in deployment.

Oh, right, forgot about the default value proposal. I really don't like that idea.

What value would you use instead?

No value. Substituting some default value would be worse than what we have now.

Matt

Do you mean leave the value unchanged? Ok. I'll go along with that. Of course, program correctness has just been killed in either case. Now what? What can you put in the exception handler to improve that?

Spock

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

211. Re: Try/Catch

Spock said...

Do you mean leave the value unchanged? Ok. I'll go along with that. Of course, program correctness has just been killed in either case. Now what? What can you put in the exception handler to improve that?

Whatever the programmer thinks is appropriate, of course. And it (the variable, the operation, etc) might not be anything that the handler even knows about.

I mean...suppose you're using some library, and an exception bubbles up from some operation. Let's say, opening a file. At this point, you tell the user, sorry, couldn't open that, and get on with life.

Matt

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

212. Re: Try/Catch

Spock said...
sequence s = "" 
object x = s[1] -- no crash 
? x -- {} 
? ERRNO -- BAD_INDEX 

This is equivalent to ON ERROR CONTINUE in Basic.

Once Euphoria has identified an exception has taken place, continuing on as if no exception took place is the incorrect behavior.

Returning some default value (zero, null, whatever) is obviously wrong, because ultimately you're going to have to discard that value.

Spock said...

However, I think bad indexes are a poor example (in the context of the topic) since they are programming errors that must be corrected rather than somehow "managed". Certainly, in program development a bad index should cause a crash so I can fix the problem. For program deployment the behaviour will revert to above (with signalling).

That would be fine, except that Euphoria defines these as exceptions.

If you want to argue that it shouldn't do that, fine - but that's a different conversation.

And because Euphoria defines these as exceptions, they aren't poor examples - they are exactly what we're talking about.

I've asked this several times, but not yet gotten an answer: have you ever used try/catch? Based on the objections you continue to raise, I can only assume that you haven't.

- David

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

213. Re: Try/Catch

jimcbrown said...
Spock said...

The best value is the correct value that the programmer intended. If try/catch can magically know what that is then Great!

The reason that it knows that is because the programmer has to explicitly set the value in the catch statement

In 99.99 % (or thereabouts) of cases the programmer will NOT know what that correct runtime value is. Insisting otherwise is completely absurd!

Spock

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

214. Re: Try/Catch

Spock said...

In 99.99 % (or thereabouts) of cases the programmer will NOT know what that correct runtime value is. Insisting otherwise is completely absurd!

You're not going to try to provide a value for a bad index. Rather, you'll try to structure the program so that it can recover from an action that failed because of an exception.

What that recovery is depends on the application. For example, here's the "recovery" on an attempt to open a file that failed because of some exception:

... 
case OPEN_FILE then 
   try 
      open_file(fileName) 
   catch e 
      alert("The file " & fileName & " could not be opened. " & e[EXCEPTION_MESSAGE]) 
   end try 
... 

On the other hand, a developer might simply try to prevent their program from dying by wrapping the top level:

-- handle events until exitProgram is true 
while not exitProgram do 
   -- is there an event to process? 
   if eventInQueue() then 
      try 
         -- handle the event 
         process( getEvent() ) 
      catch e 
         alert(e[EXCEPTION_MESSAGE]) 
      end try 
   else 
      -- release the cpu 
      pause() 
   end if 
end while 

It's up to the developer to decide at what level it is appropriate to try to catch exceptions. Generally, these will be fairly high up - not at the low level that you're focusing on.

- David

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

215. Re: Try/Catch

Spock said...

In 99.99 % (or thereabouts) of cases the programmer will NOT know what that correct runtime value is. Insisting otherwise is completely absurd!

But wouldn't it be worse for us as language developers, who are even farther away from the program than the programmer is? So isn't it even more absurd for us to try to set the runtime value?

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

216. Re: Try/Catch

jimcbrown said...
Spock said...

In 99.99 % (or thereabouts) of cases the programmer will NOT know what that correct runtime value is. Insisting otherwise is completely absurd!

But wouldn't it be worse for us as language developers, who are even farther away from the program than the programmer is? So isn't it even more absurd for us to try to set the runtime value?



I recently stumbled over this discussion and gave my 2 bits worth for the exeption-handling algorhythm.
I hate to read 3 or 4deep quoted posts so can PLEASE both Spock and Jim
summarize their point of view for me?

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

217. Re: Try/Catch

Ekhnat0n said...

I hate to read 3 or 4deep quoted posts so can PLEASE both Spock and Jim summarize their point of view for me?

I would, but dcuny already beat me to it.

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

218. Re: Try/Catch

Hi Jim,

Can you give me the post David did so in as a quote with your answer?

Antoine

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

219. Re: Try/Catch

Ekhnat0n said...

Hi Jim,

Can you give me the post David did so in as a quote with your answer?

Antoine

It's easier to just link to it instead: http://openeuphoria.org/forum/m/126233.wc

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

220. Re: Try/Catch

dcuny said...
... 
case OPEN_FILE then 
   try 
      open_file(fileName) 
   catch e 
      alert("The file " & fileName & " could not be opened. " & e[EXCEPTION_MESSAGE]) 
   end try 
... 

Great simple examples, but both can be done now with an equal amount of if-then. How about another real-world example, somewhat longer, that cannot be done as well with if-then?

Kat

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

221. Re: Try/Catch

dcuny said...
Spock said...

In 99.99 % (or thereabouts) of cases the programmer will NOT know what that correct runtime value is. Insisting otherwise is completely absurd!

You're not going to try to provide a value for a bad index..

Right. Neither Exceptions nor SCC can do this any better than the other. So the comments implying that Exceptions could solve a bad index better than SCC were muddying the waters just a bit, eh? This is what was written:

dcuny said...
Spock said...

I think the problem of a bad index is a very poor example to solve using try/catch.

Why is it a poor example? It's the typical exception in Euphoria.

Spock said...

So you catch a bad index. Now what?

By definition, the code traverses up the call stack until it finds a catch clause to handle it.

Have you looked into how try/catch works before arguing against it?

- David

But of course. Although I never needed to use exceptions in the past that doesn't disqualify me from being able to reason about the subject logically.

dcuny said...

.. For example, here's the "recovery" on an attempt to open a file that failed because of some exception:

... 
case OPEN_FILE then 
   try 
      open_file(fileName) 
   catch e 
      alert("The file " & fileName & " could not be opened. " & e[EXCEPTION_MESSAGE]) 
   end try 
... 

In this instance try/catch has become like a mere proxy for if/then. So my point is that status codes will do just as good a job (at this low level).

dcuny said...

On the other hand, a developer might simply try to prevent their program from dying by wrapping the top level:

-- handle events until exitProgram is true 
while not exitProgram do 
   -- is there an event to process? 
   if eventInQueue() then 
      try 
         -- handle the event 
         process( getEvent() ) 
      catch e 
         alert(e[EXCEPTION_MESSAGE]) 
      end try 
   else 
      -- release the cpu 
      pause() 
   end if 
end while 

It's up to the developer to decide at what level it is appropriate to try to catch exceptions. Generally, these will be fairly high up - not at the low level that you're focusing on.

- David

Because you were referring to things like "[bad indexes are] the typical exception in Euphoria." this is why I was focusing on that low level aspect. For the high level this can still be done with SCC. Only that the traversal path must be manually coded. Still, no tricky stack unwinding is needed. Just return the functions via an error path. Granted. More verbose (what Jim calls 'ugly') but, I think, very robust.

Spock

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

222. Re: Try/Catch

jimcbrown said...
Spock said...

In 99.99 % (or thereabouts) of cases the programmer will NOT know what that correct runtime value is.

But wouldn't it be worse for us as language developers, who are even farther away from the program than the programmer is? So isn't it even more absurd for us to try to set the runtime value?

Well, Matt said "No value" which I realize is actually better than default value. So I'm going with that.

It doesn't really matter what value would have been used - they'll all be wrong anyway. But the function might just be expected to return something.

The point I was making was that solving bad indexes is not made easier with try/catch. But you did suggest that the programmer could "set" the runtime value inside the exception handler but that really would be futile given the difficulty of the problem.

Spock

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

223. Re: Try/Catch

What if we decide on valid value-range (ValMax and ValMin) as arguments for any variable,
to try and prevent as many exceptions as possible and only if those boundaries are passed
an exception-handler should be called, which KNOWS
those boundaries and can react properly to deal with the rare exception.

For the handling itself I refer to my kind of fall-through handling
of errors and exceptions this time with the exact number of the exception being known
to the program (or debugger)

The heuristics for that handler will be known as you saw them in the other fork of this topic already

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

224. Re: Try/Catch

Spock said...
dcuny said...
Spock said...

In 99.99 % (or thereabouts) of cases the programmer will NOT know what that correct runtime value is. Insisting otherwise is completely absurd!

You're not going to try to provide a value for a bad index..

Right. Neither Exceptions nor SCC can do this any better than the other.

dcuny and I part ways here. I think, if the programmer knows what they are doing, providing a value for a bad index works.

Spock said...

So the comments implying that Exceptions could solve a bad index better than SCC were muddying the waters just a bit, eh?

Not at all. There's another problem with SSC that I eluded to earlier.

Spock said...

This is what was written:

Don't forget what I wrote:

jimcbrown said...
said...

But that just asks the question of why the programmer didn't correct the logic error that led to the exception being raised in the first place!

Probably for the same reasons that some callers of open() check the return value to see if it's -1, instead of trying to prove that the file exists and permission to read it is granted before calling open() and then gets().

Spock said...

"they all share the same problem" - not stated what this is

The problem is that whatever value that ends up in the variable, it's not obvious that the variable has now been set to this. It's also not necessarily obvious that this happened at all (that the variable got a "default" value instead of having the operation be successful and getting a real value back).

Spock said...

"whereas, try/catch doesn't" - not stated how this is any better

This doesn't have the issue because one generally sets the variable explicitly in this case. Also, the flow of execution is deliberately interrupted here, which makes it clearer that something went wrong.

Spock said...

Because you were referring to things like "[bad indexes are] the typical exception in Euphoria." this is why I was focusing on that low level aspect. For the high level this can still be done with SCC. Only that the traversal path must be manually coded. Still, no tricky stack unwinding is needed. Just return the functions via an error path. Granted. More verbose (what Jim calls 'ugly') but, I think, very robust.

The extra verbosity is strongly akin to having "the programmer ... corret the logic error that led to the exception being raised in the first place!"

That is, if you can do all the if statements necessary to catch the would-be Throwables in SSC, you could just rewrite the code to not have the same logic errors in the first place... whereas "try/catch allows you to keep running on three wheels when a tire has blown out" as noted by dcuny.

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

225. Re: Try/Catch

To nip the flower in the bud:
LOGIC coding is the only way to code faultless from the beginning,
starting with the innermost action first and when that is perfect
proceed to the surrounding condition(s)
That is the way I learned programming back in the 60's and still do.
My code happens to be almost always errorfree because of this approach

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

226. Re: Try/Catch

Spock said...
dcuny said...

.. For example, here's the "recovery" on an attempt to open a file that failed because of some exception:

... 
case OPEN_FILE then 
   try 
      open_file(fileName) 
   catch e 
      alert("The file " & fileName & " could not be opened. " & e[EXCEPTION_MESSAGE]) 
   end try 
... 

In this instance try/catch has become like a mere proxy for if/then. So my point is that status codes will do just as good a job (at this low level).

Not necessarily. We don't know what open_file() does. But let's assume for now that it's a library function that opens some file format and does some sort of processing on it to make it ready to use.

Perhaps you have a corrupt file in a way that the library doesn't detect. Now you have some kind of error happening inside the library. It's not something going on right there. Maybe it's a bad index, or subscripting an atom. But it's an error that happened as a result of calling open_file().

One of the nice things about try/catch is that it propagates errors back up the call stack, instead of requiring error handling / checking at each level.

Spock said...

Because you were referring to things like "[bad indexes are] the typical exception in Euphoria." this is why I was focusing on that low level aspect. For the high level this can still be done with SCC. Only that the traversal path must be manually coded. Still, no tricky stack unwinding is needed. Just return the functions via an error path. Granted. More verbose (what Jim calls 'ugly') but, I think, very robust.

I would say this is the opposite of robust. It requires the coder to exercise a lot of discipline and good practices. History shows us that this situation is all too rare. If we can come up with a way to make it all happen, but make it easier on the coder to do the right thing, that's what we should do. In this case, it seems clear that try/catch is better than any sort of error code scheme.

Matt

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

227. Re: Try/Catch

Ekhnat0n said...

To nip the flower in the bud:
LOGIC coding is the only way to code faultless from the beginning,
starting with the innermost action first and when that is perfect
proceed to the surrounding condition(s)
That is the way I learned programming back in the 60's and still do.
My code happens to be almost always errorfree because of this approach

No one is arguing this point.

As you note, even your code is only "almost always" error free.

What is being suggested is a mechanism so that users don't suffer potentially catastrophic results for those times when they do encounter exceptions.

The purpose of fail on error has nothing to do with coding "faultless" code. It's there to provide the developer with a mechanism better than "mysterious machine exceptions".

Euphoria v3/1 Reference Manual said...

There are no mysterious machine exceptions - you will always get a full English description of any problem that occurs with your program at run-time, along with a call-stack trace-back and a dump of all of your variable values. Programs can be debugged quickly, easily and more thoroughly.

- David

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

228. Re: Try/Catch

dcuny said...

The purpose of fail on error has nothing to do with coding "faultless" code. It's there to provide the developer with a mechanism better than "mysterious machine exceptions".

Well David, I fulheartedly agree with the above statement.
And because I know I make an error once in a while
I use the mechanism described in the other Try/Catch entry.

I add at all new stages of programming a distinct ErrNo (or ExeptNo) telling me
exactly where I went wrong whenever that happens, so I can correct the code tested immediatly.

Because I do so from the very start of coding I can be fairly sure
that the exeption has to be in my last added lines.
So tracking it will be quit easy, agree?

Antoine

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

229. Re: Try/Catch

Ekhnat0n said...

I add at all new stages of programming a distinct ErrNo (or ExeptNo) telling me exactly where I went wrong whenever that happens, so I can correct the code tested immediatly.

try/catch It doesn't replace good coding practices.

But once the code is released, the end user is no longer the developer.

Users aren't beta testers, and shouldn't be treated as such.

The goal once the program is in production is to protect the user's data, and give them a fault-tolerant experience, as far as possible.

Writing solid code is key to reducing errors.

But there will be exceptions, and it's completely unacceptable to users that their programs crash and display error codes when that happens.

- David

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

230. Re: Try/Catch

mattlewis said...
Spock said...
dcuny said...

.. For example, here's the "recovery" on an attempt to open a file that failed because of some exception:

... 
case OPEN_FILE then 
   try 
      open_file(fileName) 
   catch e 
      alert("The file " & fileName & " could not be opened. " & e[EXCEPTION_MESSAGE]) 
   end try 
... 

In this instance try/catch has become like a mere proxy for if/then. So my point is that status codes will do just as good a job (at this low level).

Not necessarily. We don't know what open_file() does. But let's assume for now that it's a library function that opens some file format and does some sort of processing on it to make it ready to use.

Perhaps you have a corrupt file in a way that the library doesn't detect. Now you have some kind of error happening inside the library. It's not something going on right there. Maybe it's a bad index, or subscripting an atom. But it's an error that happened as a result of calling open_file().

One of the nice things about try/catch is that it propagates errors back up the call stack, instead of requiring error handling / checking at each level.

Spock said...

Because you were referring to things like "[bad indexes are] the typical exception in Euphoria." this is why I was focusing on that low level aspect. For the high level this can still be done with SCC. Only that the traversal path must be manually coded. Still, no tricky stack unwinding is needed. Just return the functions via an error path. Granted. More verbose (what Jim calls 'ugly') but, I think, very robust.

I would say this is the opposite of robust. It requires the coder to exercise a lot of discipline and good practices. History shows us that this situation is all too rare. If we can come up with a way to make it all happen, but make it easier on the coder to do the right thing, that's what we should do. In this case, it seems clear that try/catch is better than any sort of error code scheme.

Matt

If the error code is ORed instead of MOVed then explicit handling is not required at each step. It will simply "bubble up" until it encounters a test written for it. Whole levels could be written without any error checking but the error code will still happily pass through.

Spock

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

231. Re: Try/Catch

Spock said...

If the error code is ORed instead of MOVed then explicit handling is not required at each step. It will simply "bubble up" until it encounters a test written for it. Whole levels could be written without any error checking but the error code will still happily pass through.

What I'm not seeing in your proposal is how it offers something better than try/catch.

If I understand, you are proposing that instead of RTFatal halting Euphoria (as it does now), you're suggesting that some sort of default behavior be taken. For example, this currently throws an exception:

atom a = 1 / 0 -- throws an exception 
? a -- never gets executed 

Instead, (if I understand this) you're suggesting that some sensible behavior be defined instead of halting, and err, errno and errno-flag be set.

For example, division by zero could by default return undefined.

atom a = 1 / 0 -- sets a to undefined, and sets err, errno and errno-flag 
? a -- executes, but a is undefined. possibly sets another errno and errno-flag 

This could result in a cascade of errors, which is why errno-flag has to be ANDed together to determine which bit is set.

In the meantime, the code continues to execute normally, until the result of err is checked.

Is this correct?

- David

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

232. Re: Try/Catch

dcuny said...
Ekhnat0n said...

I add at all new stages of programming a distinct ErrNo (or ExeptNo) telling me exactly where I went wrong whenever that happens, so I can correct the code tested immediatly.

try/catch It doesn't replace good coding practices.

But once the code is released, the end user is no longer the developer.

Users aren't beta testers, and shouldn't be treated as such.

The goal once the program is in production is to protect the user's data, and give them a fault-tolerant experience, as far as possible.

Writing solid code is key to reducing errors.

But there will be exceptions, and it's completely unacceptable to users that their programs crash and display error codes when that happens.

- David



I meant tracking the error myself and correcting it b4 releasing it
Antoine

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

233. Re: Try/Catch

Spock said...

If the error code is ORed instead of MOVed then explicit handling is not required at each step. It will simply "bubble up" until it encounters a test written for it. Whole levels could be written without any error checking but the error code will still happily pass through.

But I don't want it to "happily pass through." I want it to get to the error handling code immediately, which is what try/catch does.

Matt

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

234. Re: Try/Catch

dcuny said...

try/catch It doesn't replace good coding practices.

But once the code is released, the end user is no longer the developer.

Users aren't beta testers, and shouldn't be treated as such.

The goal once the program is in production is to protect the user's data, and give them a fault-tolerant experience, as far as possible.

Writing solid code is key to reducing errors.

But there will be exceptions, and it's completely unacceptable to users that their programs crash and display error codes when that happens.

- David

I fully agree with this. For a program to be truly "robust" it must not nuke itself when a user is running it. I think the developer of a program should be able to design his program to handle errors gracefully. Sometimes, an exception isn't even worth initiating a self-destruct, because it may be part of the program that has nothing to do with important data. I think a developer that can be trusted to write good software can also be trusted to determine which parts of the program can ignore or recover from an exception rather than assuming the worst and blowing up in the user's face.

I vote yes for try/catch. Just one question: what would the value of e returned by catch e be exactly?

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

235. Re: Try/Catch

ryanj said...

I vote yes for try/catch.

Second.

ryanj said...

Just one question: what would the value of e returned by catch e be exactly?

Probably (hopefully?) a sequence containing an error message, maybe an error code (do we have standard error codes?) and stack trace leading up to the error.

Something with similar details to the .NET or Java exception class would be helpful. Possibly even with an "inner" exception object.

-Greg

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

236. Re: Try/Catch

Hi

ryanj said...

I vote yes for try/catch. Just one question: what would the value of e returned by catch e be exactly?

I support this statement.

As an example (and i do not say this should be the same in Euphoria, nor do say how they should be encoded) there are definitions from a other language at the end of the post.

From may point of view try/catch or try/except or whatever it is called is a real Euphorian way for handling errors.
It's a way you really can distinguish from your normal codeflow to the exception codeflow.
The code is much more readable (from my experience).

try 
   -- normal code 
except 
   -- exception code 
end try 
and not mix it up all the way
x=function_call() 
errorchecking() 
if err then 
   errorhandling() 
end if 
 
-- this gives you: 
-- normal code 
-- exception code 
-- normal code 
-- exception code 
etc... 

Example definitions:

EAbort				Abort error 
EAbstractError			Abstract error 
EAccessViolation		Access Violation error 
EArgumentException		Invalid argument passed to a function 
EArgumentOutOfRangeException	Argument out of valid range passed to a function 
EAssertionFailed		Assertion failed error. 
EBusError			Bus error exception 
EControlC			Control-C (abort) was pressed on the console. 
EConvertError			Conversion error. 
EDivByZero			Division by zero error. 
EExternal			External Exception. 
EExternalException		External exception 
EFormatError			Formatting error exception 
EHeapMemoryError		Heap memory error 
EInOutError			Input/Output error 
EInterror			Integer operation error. 
EIntfCastError			Invalid interface cast error. 
EIntOverflow			Integer overflow error. 
EInvalidCast			Invalid typecast error. 
EInvalidContainer		Invalid container error. 
EInvalidInsert			Invalid insert error. 
EInvalidOp			Invalid operation. 
EInvalidPointer			Invalid pointer operation 
EMathError			Mathematical error 
ENoThreadSupport		No Thread support error. 
ENotImplemented			Exception raised in case of a not implemented feature. 
ENoWideStringSupport		Exception raised if no widestring support is available in the executable 
EOSError			Operating system error. 
EOutOfMemory			Out of memory error. 
EOverflow			Float overflow error. 
EPackageError			Package error. 
EPrivilege			Privileged instruction error. 
EPropReadOnly			Read-only property error. 
EPropWriteOnly			Write-only property error. 
ERangeError			Range check error. 
ESafecallException		SafeCall exception 
EStackOverflow			Stack overflow error. 
EUnderflow			Float underflow error 
EVariantError			Variant error. 
Exception			Base class of all exceptions. 
EZeroDivide			Division by zero error. 

Andreas (BTW. in GUI programming, giving the user an errormessage in a console window is an absolute 'nogo' nowadays)

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

237. Re: Try/Catch

dcuny said...
Spock said...

If the error code is ORed instead of MOVed then explicit handling is not required at each step. It will simply "bubble up" until it encounters a test written for it. Whole levels could be written without any error checking but the error code will still happily pass through.

What I'm not seeing in your proposal is how it offers something better than try/catch.

If I understand, you are proposing that instead of RTFatal halting Euphoria (as it does now), you're suggesting that some sort of default behavior be taken. For example, this currently throws an exception:

atom a = 1 / 0 -- throws an exception 
? a -- never gets executed 

Instead, (if I understand this) you're suggesting that some sensible behavior be defined instead of halting, and err, errno and errno-flag be set.

For example, division by zero could by default return undefined.

atom a = 1 / 0 -- sets a to undefined, and sets err, errno and errno-flag 
? a -- executes, but a is undefined. possibly sets another errno and errno-flag 

This could result in a cascade of errors, which is why errno-flag has to be ANDed together to determine which bit is set.

In the meantime, the code continues to execute normally, until the result of err is checked.

Is this correct?

- David

More or less, yes. Some calls will force the user to check errno immediately afterwards. The program could return at that point or handle the error then and there (or somewhere else in that routine). Errors from other calls won't immediately affect the program operation.

A cascade of errors is unlikely or would be very limited. In any case, an error log recording each error is kept for later study so we don't accidentally overwrite a previous error.

SSC might not be "better" than try/catch but is it materially worse? In some ways it might be simpler to implement.

Spock

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

238. Re: Try/Catch

mattlewis said...
Spock said...

If the error code is ORed instead of MOVed then explicit handling is not required at each step. It will simply "bubble up" until it encounters a test written for it. Whole levels could be written without any error checking but the error code will still happily pass through.

But I don't want it to "happily pass through." I want it to get to the error handling code immediately, which is what try/catch does.

Matt

Some calls will force the user to immediately check errno (eg, open(), value()). There is also the immediate default handling of the internal routine.

Spock

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

239. Re: Try/Catch

Spock said...

SSC might not be "better" than try/catch but is it materially worse? In some ways it might be simpler to implement.

I think that many of the points for try/catch have already been made:

  • It is a well-established, understood and accepted way of handling exceptions.
  • It jumps to the exception handler immediately, instead of continuing to execute with possibly bad data.
  • It doesn't guess what values might be good in the case of an exception.
  • It allows the developer to determine at what level the application should attempt to recover.
  • It allows the developer to determine what the recovery behavior should be.
  • It is flexible, allowing the developer to decide where (if at all) exceptions should be trapped.
  • If people choose not to use it, the current behavior of Euphoria is not altered.

Does that answer your question?

- David

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

240. Re: Try/Catch

Spock said...
mattlewis said...
Spock said...

If the error code is ORed instead of MOVed then explicit handling is not required at each step. It will simply "bubble up" until it encounters a test written for it. Whole levels could be written without any error checking but the error code will still happily pass through.

But I don't want it to "happily pass through." I want it to get to the error handling code immediately, which is what try/catch does.

Matt

More or less, yes. Some calls will force the user to check errno immediately afterwards.

How? What's to stop a program from just refusing to check errno at all, e.g. to not even bother to assign the return value of open() to anything?

Spock said...

The program could return at that point or handle the error then and there

So something in the interpreter checks that immediately following the statement that causes the error, there's another statement accessing errno, and if it doesn't do that then we get an ex.err style crash?

This is a lot better.

Spock said...

(or somewhere else in that routine).

This is less better. If we're waiting for the routine to return before generating the ex.err crash, there's still a chance for a cascade of 'returnable' errors.

Also, what if we get an error in top-level code?

Spock said...

Errors from other calls won't immediately affect the program operation.

How do we know which is which? What should be returnable and what shouldn't?

Spock said...

A cascade of errors is unlikely or would be very limited. In any case, an error log recording each error is kept for later study so we don't accidentally overwrite a previous error.

What goes into the error log and how do we access it? I guess we're saying that if the program ends and errno hasn't been cleared, we write out all the errors into ex.err, one by one, giving full filename and line information and call stack trace for each?

Spock said...

SSC might not be "better" than try/catch but is it materially worse?

If the requirement that the next statement immediately handle errno is followed,then the only bit that's worse is that it's a little onerous to have to deal with errors by adding checks on virtually every other statement.

If the requirement is just that the routine has to handle it before it returns, then we still have a chance for a cascade of errors that's higher than try/catch.

Spock said...

In some ways it might be simpler to implement.

Ironically, I think the easiest way to implement this concept is to use try/catch under the hood.....

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

241. Re: Try/Catch

dcuny said...
Spock said...

SSC might not be "better" than try/catch but is it materially worse? In some ways it might be simpler to implement.

I think that many of the points for try/catch have already been made:

  • It is a well-established, understood and accepted way of handling exceptions.

Agreed. I'm not aware of Spock's SSC being used anywhere (though I'd love to see some real life usage examples of it).

dcuny said...
  • It jumps to the exception handler immediately, instead of continuing to execute with possibly bad data.

Agreed. I think Spock's SSC lets some errors continue the program without stopping it. For those errors that would cause the program to stop when unhandled, this doesn't actually happen until the routine returns, IIUC.

The stricter 'next-line' SSC that I speculated about in my previous post doesn't have this problem, however.

dcuny said...
  • It doesn't guess what values might be good in the case of an exception.

Actually, I think Spock already agreed with Matt on the value of the variable being unchanged (so if the variable was unassigned before, then it's still unassigned, etc) - I think this is what would happen in a try/catch situation as well.

The stricter 'next-line' SSC wouldn't have this problem anyways, since one is forced to check for the error (and thus one knows that whatever values you get, they are the default ones, not the real ones) or else a crash immediately occurs.

dcuny said...
  • It allows the developer to determine at what level the application should attempt to recover.

Agreed. SSC is a lot less flexible about this.

dcuny said...
  • It allows the developer to determine what the recovery behavior should be.

Well, if you are manually checking, then the same is true with SSC....

dcuny said...
  • It is flexible, allowing the developer to decide where (if at all) exceptions should be trapped.

Agreed. SSC is a lot less flexible about this.

dcuny said...
  • If people choose not to use it, the current behavior of Euphoria is not altered.

This isn't inherently the case - Spock's SSC says some errors will allow things to continue on, but one could envision a version that said all unhandled errors caused a crash. In that case, the current behavior of Euphoria is still unaltered for those who choose not to use SSC, since - if one isn't checking errno by the next statement - you get a crash right away.

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

242. Re: Try/Catch

dcuny said...
Spock said...

SSC might not be "better" than try/catch but is it materially worse? In some ways it might be simpler to implement.

I think that many of the points for try/catch have already been made:

  • It is a well-established, understood and accepted way of handling exceptions.
  • It jumps to the exception handler immediately, instead of continuing to execute with possibly bad data.
  • It doesn't guess what values might be good in the case of an exception.
  • It allows the developer to determine at what level the application should attempt to recover.
  • It allows the developer to determine what the recovery behavior should be.
  • It is flexible, allowing the developer to decide where (if at all) exceptions should be trapped.
  • If people choose not to use it, the current behavior of Euphoria is not altered.

Does that answer your question?

- David

The only real technical objection in your list is:

  • It jumps to the exception handler immediately, instead of continuing to execute with possibly bad data.

Exception handling can shut down the (sub) program immediately in such a case. If it simply resumed execution it would be no different (as it can't solve the bad data problem). SSC would delay the decision to shut down till later, albeit at the risk of more damage. This is mitigated by it being in a better logical position (program has now returned to original calling point) to attempt a clean up.

Try/catch would therefore seem to have an advantage if the SSC handler couldn't properly clean up. OTOH, try/catch itself must also attempt a difficult clean up if it is to keep the program running.

Spock

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

243. Re: Try/Catch

Spock said...

Try/catch would therefore seem to have an advantage if the SSC handler couldn't properly clean up. OTOH, try/catch itself must also attempt a difficult clean up if it is to keep the program running.

You'll generally wrap the try around a discrete action - load a file, save a file, etc. - so that if some portion throws and exception, you know the data structure you were expecting wasn't created properly, and can't be trusted for use.

- David

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

244. Re: Try/Catch

dcuny said...
Spock said...

Try/catch would therefore seem to have an advantage if the SSC handler couldn't properly clean up. OTOH, try/catch itself must also attempt a difficult clean up if it is to keep the program running.

You'll generally wrap the try around a discrete action - load a file, save a file, etc. - so that if some portion throws and exception, you know the data structure you were expecting wasn't created properly, and can't be trusted for use.

- David

As you pointed out right from the beginning, cleanup() in the exception handler would have a huge job to do. One of my graphics-based programs does a lot of manipulation at the raw byte level. Routinely blocks of RAM are allocated at 50MB per image or operation. One or two routines also access memory that Windows temporarily allocates. Naturally, memory leaks of such magnitude per unit must never happen.

If an exception occurred x levels down in such a situation the clean up required would be just insane. With SSC this clean up will happen automatically as part of each routine's normal exit strategy. So in this aspect it must be superior to try/catch.

jimcbrown said...
dcuny said...
Spock said...

SSC might not be "better" than try/catch but is it materially worse? In some ways it might be simpler to implement.

I think that many of the points for try/catch have already been made:

  • It is a well-established, understood and accepted way of handling exceptions.

Agreed. I'm not aware of Spock's SSC being used anywhere (though I'd love to see some real life usage examples of it).

It's just error codes that have been around forever. Only smarter, less intrusive.

Whatever OE might implement I'm sure I won't regret adding SSC to my own compiler.

Spock

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

245. Re: Try/Catch

Spock said...

As you pointed out right from the beginning, cleanup() in the exception handler would have a huge job to do. One of my graphics-based programs does a lot of manipulation at the raw byte level. Routinely blocks of RAM are allocated at 50MB per image or operation. One or two routines also access memory that Windows temporarily allocates. Naturally, memory leaks of such magnitude per unit must never happen.

If an exception occurred x levels down in such a situation the clean up required would be just insane. With SSC this clean up will happen automatically as part of each routine's normal exit strategy. So in this aspect it must be superior to try/catch.

Not really. We already have delete_routine() which is more that sufficient to deal with this.

Also not a problem if we implement try..catch..finally.

Spock said...
jimcbrown said...

Agreed. I'm not aware of Spock's SSC being used anywhere (though I'd love to see some real life usage examples of it).

It's just error codes that have been around forever.

Not so. There are elements to your version of SSC that are new and unique that I've never seen before. It's a lot more than just "error codes" at this point.

Spock said...

Whatever OE might implement I'm sure I won't regret adding SSC to my own compiler.

Cool! Do you have a name for it yet?

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

246. Re: Try/Catch

Spock said...

With SSC this clean up will happen automatically as part of each routine's normal exit strategy.

...Is there some specific reason why you think that the stack unwind part of try/catch would do anything but exactly the same?

The only slight difference is that you could save a bunch of stuff in e (of catch e fame) that won't disappear until e does.

Pete

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

247. Re: Try/Catch

petelomax said...
Spock said...

With SSC this clean up will happen automatically as part of each routine's normal exit strategy.

...Is there some specific reason why you think that the stack unwind part of try/catch would do anything but exactly the same?

The only slight difference is that you could save a bunch of stuff in e (of catch e fame) that won't disappear until e does.

Take a look at the result of running eudis on some code. There's a lot of cleanup that goes on all the time whenever we exit a scope.

Matt

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

248. Re: Try/Catch

jimcbrown said...
Spock said...

Whatever OE might implement I'm sure I won't regret adding SSC to my own compiler.

Cool! Do you have a name for it yet?

Yeah! That was the first thing I did. I call it Orac.

Spock

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

249. Re: Try/Catch

petelomax said...
Spock said...

With SSC this clean up will happen automatically as part of each routine's normal exit strategy.

...Is there some specific reason why you think that the stack unwind part of try/catch would do anything but exactly the same?

The only slight difference is that you could save a bunch of stuff in e (of catch e fame) that won't disappear until e does.

Pete

Well, maybe I've been mistaken but I thought that all the bits of manually & OS allocated memory (some possibly obtained prior to the original calling point [EDIT: Relevant?]) would require a huge effort to clean up automatically. I will happily accept being proved wrong.

Spock

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

250. Re: Try/Catch

Spock said...
jimcbrown said...
Spock said...

Whatever OE might implement I'm sure I won't regret adding SSC to my own compiler.

Cool! Do you have a name for it yet?

Yeah! That was the first thing I did. I call it Orac.

Spock

Aha! I didn't realize that you were Mr. Toresson! Welcome back!

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

251. Re: Try/Catch

jimcbrown said...
Spock said...
jimcbrown said...
Spock said...

Whatever OE might implement I'm sure I won't regret adding SSC to my own compiler.

Cool! Do you have a name for it yet?

Yeah! That was the first thing I did. I call it Orac.

Spock

Aha! I didn't realize that you were Mr. Toresson! Welcome back!

Sorry Jim. Alexander used it but I actually created it.

Spock

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

252. Re: Try/Catch

Spock said...
jimcbrown said...
Spock said...
jimcbrown said...
Spock said...

Whatever OE might implement I'm sure I won't regret adding SSC to my own compiler.

Cool! Do you have a name for it yet?

Yeah! That was the first thing I did. I call it Orac.

Spock

Aha! I didn't realize that you were Mr. Toresson! Welcome back!

Sorry Jim. Alexander used it but I actually created it.

Spock

Oops. My apologies for my mistake.

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

253. Re: Try/Catch

mattlewis said...

Take a look at the result of running eudis on some code. There's a lot of cleanup that goes on all the time whenever we exit a scope.

Ah. My bad. I didn't realise RETURNF and RETURNP had block scopes embedded in the code. In Phix, opRetf is parameterless; it's all on the stack smile - mind you, thanks for the reminder, I never quite finished my block scope handling sad

Pete

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

254. Re: Try/Catch

Spock said...

Well, maybe I've been mistaken but I thought that all the bits of manually & OS allocated memory (some possibly obtained prior to the original calling point [EDIT: Relevant?]) would require a huge effort to clean up automatically. I will happily accept being proved wrong.

It depends on how you allocate them. There's an optional parameter in allocate() that will free the memory once the returned atom's reference count goes to zero. Other resources can use this, too, e.g., open() can automatically close files for you, too. The memory (all normal euphoria data) used by maps from std/map.e are automatically cleaned up.

This is one of those features of 4.0 that I don't want to live without.

Matt

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

255. Re: Try/Catch

mattlewis said...
Spock said...

Well, maybe I've been mistaken but I thought that all the bits of manually & OS allocated memory (some possibly obtained prior to the original calling point [EDIT: Relevant?]) would require a huge effort to clean up automatically. I will happily accept being proved wrong.

It depends on how you allocate them. There's an optional parameter in allocate() that will free the memory once the returned atom's reference count goes to zero. Other resources can use this, too, e.g., open() can automatically close files for you, too. The memory (all normal euphoria data) used by maps from std/map.e are automatically cleaned up.

This is one of those features of 4.0 that I don't want to live without.

Matt

Automatically freeing allocated memory is pretty cool. It doesn't really solve the problem, though.

If an allocation originates outside the routine (eg, in my fast string allocator or my dib32 library or font library etc.. which are used a lot in my programs) there is now direct exposure to memory leaks should an exception occur when the prgram is using them.

What about external accesses to, eg, Windows routines? Many of these follow the pattern:

Get resource (memory, handle, DC, etc..)
Do something with it
Return resource

The same pattern might occur in a 3rd party dll. Eg, the one I use for wave/sound control.

I can now forget about my planned JIT ASM compiler too.

So: Graphics, Fonts, Sound, ASM, Printing, other Windows ops have now been exposed to memory risks should an exception occur while they are being used.

However, if I only allocate & free the memory inside some routine, making sure not to indadvertently cause a double reference, and if I don't access any Windows stuff or any other DLL stuff, then there will be no problem.

Am I overstating the danger here ?!

Spock

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

256. Re: Try/Catch

Spock said...

Automatically freeing allocated memory is pretty cool. It doesn't really solve the problem, though.

Sure it does.

Spock said...

If an allocation originates outside the routine (eg, in my fast string allocator or my dib32 library or font library etc.. which are used a lot in my programs) there is now direct exposure to memory leaks should an exception occur when the prgram is using them.

So: Graphics, Fonts, Sound, ASM, Printing, other Windows ops have now been exposed to memory risks should an exception occur while they are being used.

Not so. Just make sure that your wrapper for the dib32/font library calls delete_routine() on each pointer that is returned by the library. Then, when an exception occurs, and the objects go out of scope, delete_routine() will clean them up for you.

Spock said...

What about external accesses to, eg, Windows routines? Many of these follow the pattern:

Get resource (memory, handle, DC, etc..)
Do something with it
Return resource

The same pattern might occur in a 3rd party dll. Eg, the one I use for wave/sound control.

Ditto. Just make sure to wrap the "Get resource" part with a delete_routine() that calls the wrapper for the "Return resource" part.

Spock said...

However, if I only allocate & free the memory inside some routine, making sure not to indadvertently cause a double reference, and if I don't access any Windows stuff or any other DLL stuff, then there will be no problem.

Am I overstating the danger here ?!

Yes, I think so.

Spock said...

I can now forget about my planned JIT ASM compiler too.

Not sure how this would be affected.

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

257. Re: Try/Catch

jimcbrown said...
Spock said...

If an allocation originates outside the routine (eg, in my fast string allocator or my dib32 library or font library etc.. which are used a lot in my programs) there is now direct exposure to memory leaks should an exception occur when the prgram is using them.

So: Graphics, Fonts, Sound, ASM, Printing, other Windows ops have now been exposed to memory risks should an exception occur while they are being used.

Not so. Just make sure that your wrapper for the dib32/font library calls delete_routine() on each pointer that is returned by the library. Then, when an exception occurs, and the objects go out of scope, delete_routine() will clean them up for you.

This is also what finally is for: to cleanup the resource regardless of what happens in try or catch.

-Greg

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

258. Re: Try/Catch

Spock said...

Automatically freeing allocated memory is pretty cool. It doesn't really solve the problem, though.

That's just something that's built in and ready to use right now.

Spock said...

If an allocation originates outside the routine (eg, in my fast string allocator or my dib32 library or font library etc.. which are used a lot in my programs) there is now direct exposure to memory leaks should an exception occur when the prgram is using them.

What about external accesses to, eg, Windows routines? Many of these follow the pattern:

Get resource (memory, handle, DC, etc..)
Do something with it
Return resource

You can create any sort of cleanup routine you can imagine and attach that to the resource. Memory is just a simple and obvious thing, so the library does it for you if you ask.

Matt

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

259. Re: Try/Catch

jimcbrown said...

Just make sure to wrap the "Get resource" part with a delete_routine() that calls the wrapper for the "Return resource" part.

Spock said...

However, if I only allocate & free the memory inside some routine, making sure not to indadvertently cause a double reference, and if I don't access any Windows stuff or any other DLL stuff, then there will be no problem.

Am I overstating the danger here ?!

Yes, I think so.

So now I have to carefully go through the whole suite of libraries wrapping both get & release calls and replacing those in the code whereever they were called before. And sift through the allocators to make sure there is no inadvertent double reference. And make sure all future modules follow the same bubble-wrapped pattern.

That's a lot of work to do just to protect my programs being bled by your* exceptions.

There just has to be a better way.

Spock

[* plural]

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

260. Re: Try/Catch

Spock said...
jimcbrown said...

Just make sure to wrap the "Get resource" part with a delete_routine() that calls the wrapper for the "Return resource" part.

So now I have to carefully go through the whole suite of libraries wrapping both get & release calls and replacing those in the code whereever they were called before.

And make sure all future modules follow the same bubble-wrapped pattern.

Only the get calls, and considering that it's the addition of a single statement (if even that) for each get call, I don't see what the big deal here is.

Spock said...

And sift through the allocators to make sure there is no inadvertent double reference.

Err, I don't see why this is necessary.

Spock said...

That's a lot of work to do just to protect my programs being bled by your exceptions.

There just has to be a better way.

Perhaps, but I should point out that SSC has the same problem. That is, whatever that better way is, it applies to SSC and try-catch equally, and without it both suffer equally.

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

261. Re: Try/Catch

Spock said...

So now I have to carefully go through the whole suite of libraries wrapping both get & release calls and replacing those in the code whereever they were called before. And sift through the allocators to make sure there is no inadvertent double reference. And make sure all future modules follow the same bubble-wrapped pattern.

That's a lot of work to do just to protect my programs being bled by your* exceptions.

There just has to be a better way.

[* plural]

Sorry, but this is just silly. Yes, if you want to change the way your program works, you have to change the way it works. If you don't, then it will continue to work the same way. All of this automatic resource releasing is available now. I'm not sure why you're bringing a (still) hypothetical feature into the mix.

Matt

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

262. Re: Try/Catch

jimcbrown said...
Spock said...

That's a lot of work to do just to protect my programs being bled by your exceptions.

There just has to be a better way.

Perhaps, but I should point out that SSC has the same problem. That is, whatever that better way is, it applies to SSC and try-catch equally, and without it both suffer equally.

SSC will continue program execution whenever an event occurs so it means no change is needed to existing programs - apart from a single if/then test at a sub-program boundary if the coder wants to take advantage of it. The coder [me] does have to rewrite important parts of existing libraries [to take advantage of exceptions].

Spock

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

263. Re: Try/Catch

Spock said...

SSC will continue program execution whenever an event occurs so it means no change is needed to existing programs - apart from a single if/then test at a sub-program boundary if the coder wants to take advantage of it.

The same is true of delete_routine() - just manually wrap each get call to each library with delete_routine(). I don't see how this is any harder than placing an if/then around it.

Spock said...

The coder does have to rewrite parts of existing libraries [to take advantage of exceptions].

Not so with try..catch..finally. You don't even have to use delete_routine().

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

264. Re: Try/Catch

jimcbrown said...
Spock said...

SSC will continue program execution whenever an event occurs so it means no change is needed to existing programs - apart from a single if/then test at a sub-program boundary if the coder wants to take advantage of it.

The same is true of delete_routine() - just manually wrap each get call to each library with delete_routine(). I don't see how this is any harder than placing an if/then around it.

Spock said...

The coder does have to rewrite parts of existing libraries [to take advantage of exceptions].

Not so with try..catch..finally. You don't even have to use delete_routine().

I don't think we're understanding each other here. I won't have to change a single line in my libraries in order to use SSC. With try/catch I would - as you just told me I'd have to do wrapping with delete_routine() which I don't believe will be such a trivial task.

Spock

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

265. Re: Try/Catch

Spock said...

But I don't understand your last comment

I don't think we're understanding each other here. I won't have to change a single line in my libraries in order to use SSC.

You can also use delete_routine() without having to change a single line in your libraries. Technically.

Spock said...

With try/catch I would

No, you wouldn't. If you don't understand my explanation then reread ghaberek's post.

Spock said...

as you just told me I'd have to do wrapping with delete_routine() which I don't believe will be such a trivial task.

You don't need to use delete_routine() ... it's optional. You can clean up with try..catch..finally without having to use delete_routine().

Conversely, you can use delete_routine() with try..catch, SSC, and even the existing regime today (crash_routine()). These are two separate things.

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

266. Re: Try/Catch

jimcbrown said...
Spock said...

With try/catch I would

No, you wouldn't. If you don't understand my explanation then reread ghaberek's post.

Spock said...

as you just told me I'd have to do wrapping with delete_routine() which I don't believe will be such a trivial task.

You don't need to use delete_routine() ... it's optional. You can clean up with try..catch..finally without having to use delete_routine().

Conversely, you can use delete_routine() with try..catch, SSC, and even the existing regime today (crash_routine()). These are two separate things.

Ok. I think I got this right:

1 Add delete_routine() to libraries - cleanup happens automatically when atom leaves scope
Or
2 Use try/catch/finally - manually call cleanup routine

Let's say I'm too lazy to do 1 (or it'd be really awkward since my libraries usually return integers (object IDs) not pointers). So how will I know which cleanup routines to call in finally in 2?

Spock

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

267. Re: Try/Catch

Spock said...

SSC will continue program execution whenever an event occurs so it means no change is needed to existing programs - apart from a single if/then test at a sub-program boundary if the coder wants to take advantage of it.

Spock said...

I don't think we're understanding each other here. I won't have to change a single line in my libraries in order to use SSC.

I certainly don't understand. Some examples might help, in fact, can we have a formal design spec for this SSC, please?

jimcbrown said...
Spock said...

With try/catch I would

No, you wouldn't. If you don't understand my explanation then reread ghaberek's post.

I'm also not sure which post that is supposed to refer to.

Pete

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

268. Re: Try/Catch

petelomax said...

I'm also not sure which post that is supposed to refer to.

This one, on this same thread: http://openeuphoria.org/forum/m/127051.wc

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

269. Re: Try/Catch

petelomax said...
Spock said...

SSC will continue program execution whenever an event occurs so it means no change is needed to existing programs - apart from a single if/then test at a sub-program boundary if the coder wants to take advantage of it.

Spock said...

I don't think we're understanding each other here. I won't have to change a single line in my libraries in order to use SSC.

I certainly don't understand. Some examples might help, in fact, can we have a formal design spec for this SSC, please?

SSC are just error codes transmitted up & down calling levels by using a hidden parameter in the calling sequences. They're a lot like Go's error codes but they aren't explicitly declared. They just signal to a caller that something went wrong at a lower level and to take action accordingly.

The compiler will insert the appropriate calls so neither existing programs nor libraries will need to be retro-fitted to take advantage of them.

Anyway, this is all somewhat moot as OE seems set to eventually implement try/catch.

Spock

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

270. Re: Try/Catch

Spock said...

Ok. I think I got this right:

1 Add delete_routine() to libraries - cleanup happens automatically when atom leaves scope
Or
2 Use try/catch/finally - manually call cleanup routine

Let's say I'm too lazy to do 1 (or it'd be really awkward since my libraries usually return integers (object IDs) not pointers). So how will I know which cleanup routines to call in finally in 2?

Spock

That's entirely up to you, isn't it? You'd have to clean up whatever you started, correct?

The finally statement simply affords you that opportunity, and it is entirely optional.

atom x 
 
try 
 
    -- get our resource to work with 
 
    x = get_resource() 
 
    -- do several things with the resource 
    -- that might throw an exception here 
 
    step_1( x ) 
    step_2( x ) 
    step_3( x ) 
    step_4( x ) 
    step_5( x ) 
 
catch e 
 
    -- ERROR HANDLING CODE GOES HERE -- 
 
finally 
 
    -- our resource will always be freed here 
    -- (unless we encounter a fatal error) 
 
    if object( x ) then 
        free_resource( x ) 
    end if 
 
end try 

Now compare that code to this...

 
atom x = get_resource() 
 
if error_code != 0 then 
    -- ERROR HANDLING CODE GOES HERE -- 
    return -- just quit 
end if 
 
step_1( x ) 
 
if error_code != 0 then 
    -- ERROR HANDLING CODE GOES HERE -- 
    goto "cleanup" 
end if 
 
step_2( x ) 
 
if error_code != 0 then 
    -- ERROR HANDLING CODE GOES HERE -- 
    goto "cleanup" 
end if 
 
step_3( x ) 
 
if error_code != 0 then 
    -- ERROR HANDLING CODE GOES HERE -- 
    goto "cleanup" 
end if 
 
step_4( x ) 
 
if error_code != 0 then 
    -- ERROR HANDLING CODE GOES HERE -- 
    goto "cleanup" 
end if 
 
step_5( x ) 
 
if error_code != 0 then 
    -- ERROR HANDLING CODE GOES HERE -- 
    goto "cleanup" 
end if 
 
label "cleanup" 
free_resource( x ) 

I would prefer the first option, but right now I am bound to the second.

-Greg

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

271. Re: Try/Catch

Spock said...

The compiler will insert the appropriate calls so neither existing programs nor libraries will need to be retro-fitted to take advantage of them.

Well, straight away that means SSC cannot handle errors that happen in non-Eu code.

Pete

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

272. Re: Try/Catch

ghaberek said...
Spock said...

Ok. I think I got this right:

1 Add delete_routine() to libraries - cleanup happens automatically when atom leaves scope
Or
2 Use try/catch/finally - manually call cleanup routine

Let's say I'm too lazy to do 1 (or it'd be really awkward since my libraries usually return integers (object IDs) not pointers). So how will I know which cleanup routines to call in finally in 2?

Spock

That's entirely up to you, isn't it? You'd have to clean up whatever you started, correct?

The finally statement simply affords you that opportunity, and it is entirely optional.

Hi Greg,

Thanks for the code example. An important difference between the 2 systems is that the low-level clean up in SSC must always occur since execution is never interrupted - the routine simply completes and returns as normal. So at the top level the "clean up" is of a different kind as the problem now is overshoot rather than premature termination. The top level would be more like:

 
   ERRNO = 0 
 
   integer x = getThing() 
 
   step_1( x ) 
   step_2( x ) 
   step_3( x ) 
   step_4( x ) 
   step_5( x ) 
 
   if ERRNO = REALLYBADERROR then 
      undo( x ) 
      return 
   end if 
 

But like I said to Pete, the point is largely moot anyway as try/catch is going to eventually be added to OE.

Spock

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

273. Re: Try/Catch

petelomax said...
Spock said...

The compiler will insert the appropriate calls so neither existing programs nor libraries will need to be retro-fitted to take advantage of them.

Well, straight away that means SSC cannot handle errors that happen in non-Eu code.

Pete

Won't these still be caught by the internal routines, as they are now? If that's the case ERRNO can be thrown on the Eu side and propagate up the call path normally.

Or am I mistaken about this?

Spock

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

274. Re: Try/Catch

said...

step_5( x )

if error_code != 0 then any action end if

label "cleanup" free_resource( x ) }}}

I would prefer the first option, but right now I am bound to the second.

-Greg

By replacing if error_code != 0 then
by
if error_code then

you will save lots of typing, because IF error_code has any value
it is considered to be TRUE

so if error_code then is a correct statement

Antoine aka Ekhnat0n


Forked into: Please DON'T do that

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

275. Re: Try/Catch

jimcbrown said...
mattlewis said...
jimcbrown said...
mattlewis said...

But what's the difference between a recoverable and unrecoverable?

You can trap the former and continuie program execution without making the sytem unstable or introducing logic errors (at least in principle), but you can't do this for the latter.

Well, duh, but my point was that it's not always obvious when an error is one or the other.

Oops. That's a good point.... that's probably a significant factor in causing try/catch overuse/abuse.

I've thought about it and decided to revise my definition.

An unrecoverable is an error that makes the system so unstable that there's simply no hope of recovery. (E.g. stack corruption, OOM, etc.) Anything not this severe is a recoverable (though perhaps at the risk of introducing logic errors - but one can introduce logic errors that can't be caught out by a Throwable anyways).

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

Search



Quick Links

User menu

Not signed in.

Misc Menu