Exception handling: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
No edit summary
(Corrections)
Line 61: Line 61:
  }
  }


In OFP, "exec" was asynchronous - think spawning another thread. (ArmA will make this slightly more explicit with the command spawn) As such, an exception won't unwind into the caller so that it can be caught and used there. Though firebomb.sqs would preferrably be inlined to begin with, using "call preprocessfile firebomb.sqf" would be getting you the effect you want. Besides, it could go into "he is dead" before firebomb.sqs' first line got executed.
There are several reasons the above code won't work.


There are, however, several things about the piece of code above worthy of criticism. First of all, the handler is a catch(anything) (as ofpscript forces it to be) but the handler assumes it to be a string. {if typeof _exception != "string" throw } as the first command in the handler should properly rethrow the exception so it can be handled even further out. (The last throw might require _exception as a parameter.
First of all, [[exec]] launches scripts asynchronously, like [[spawn]] does. This gives 2 problems. One is that it may enter the "he is dead" part before the bomb script does its first line. Another is that an exception will not (and should not) "unwind" beyond such a boundary; meaning that the script will generate an error as it has gone through all the scopes to the point the spawn/exec command was run without finding a try/catch to match.  


The second, and bigger problem, is that the exception handling is used as a way of returning values. Exceptions ''should'' be used exclusively for runtime handling of error conditions. At least traditionally, this was so because exceptions are rather "expensive" in use, but generally speaking, the only proper reason for such usage is the lack of other suitable ways of returning results.  It's good form, and helps maintainability.
Using something like {call compile preprocessfile "firebomb.sqf"} would avoid those problems, though it might be preferrable to inline them (as opposed to putting it in a file of its own) in this particular case.


Exceptions are most useful when different people work on interacting pieces of code.
Another problem is that the exception handler (catch block) is a catch(anything) (as ofpscript forces it to be) but the handler assumes it to be a string. {if typename _exception != "STRING" throw _exception} as the first command in the handler should properly rethrow the exception so it can be handled even further out. ArmAScript has a tendency to toss out errors when you compare strings to non-strings.


--[[User:MaHuJa|MaHuJa]] 07:29, 23 August 2006 (CEST)
Moving to a less technical problem: The exception handling is used as a way of returning values. Exceptions ''should'' be used exclusively for runtime handling of error conditions. At least traditionally (I don't really know how this is in ArmAscript, but i suspect this holds true), this was so because exceptions are rather "expensive" in use. Either way, keeping away from this style of scripting also makes the resulting scripts more maintainable.
 
Exceptions are most useful when different people work on interacting pieces of code. The clue is that the one who detects the error may not know how the caller code needs the error handled. This is especially true of "library code" which is called from multiple places, perhaps by many users in lots of different missions/addons.
 
--[[User:MaHuJa|MaHuJa]] 07:29, 23 August 2006 (CEST) -- Updated [[User:MaHuJa|MaHuJa]] 10:04, 16 July 2007 (CEST)


[[Category: Scripting Topics|Exception Handling]]
[[Category: Scripting Topics|Exception Handling]]

Revision as of 10:04, 16 July 2007

In Armed Assault exception handling is an implemented system of special scripting commands (try, catch and throw), which allows your scripts to create and to react to exceptions.

Standard construction is:

try {
    //block, that can throw exception
    if (_name == "") then {
        throw "no name"
    } else {
        TitleText [format["Good morning, Captain %1.", _name], "PLAIN DOWN"]
        ~1
        TitleText [_name, "PLAIN DOWN"]
    }
}
catch { //block, that processes an exception if (_exception == "no name") then { echo "Name wasn't entred" TitleText ["And the name isn't", "PLAIN DOWN"] } }

Note: ArmA scripting commands do not create an exception by themselves if they encounter an illegal situation (i.e. you can't use the here described exception handling for error trapping.)

The following would therefore not create a catchable exception: try {a=1/0;} catch {hint "illegal operation";}




Probably is this possible too:

Template:Box File

try {
    TitleText ["Sgt. Detritus: I get bomb to his car ;-)", "PLAIN DOWN"]
    [jeepOne] exec "fireBomb.sqs"
    TitleText ["Sgt. Detritus: He is dead!", "PLAIN DOWN"]
}
catch { if (_exception == "vehicle empty") then { TitleText ["Sgt. Detritus: He have luck, but next time I'll kill him!", "PLAIN DOWN"] } else { TitleText ["Sgt. Detritus: Some strange error appears... " + _exception + "... hmm... another time I'll get him!", "PLAIN DOWN"] }

There are several reasons the above code won't work.

First of all, exec launches scripts asynchronously, like spawn does. This gives 2 problems. One is that it may enter the "he is dead" part before the bomb script does its first line. Another is that an exception will not (and should not) "unwind" beyond such a boundary; meaning that the script will generate an error as it has gone through all the scopes to the point the spawn/exec command was run without finding a try/catch to match.

Using something like {call compile preprocessfile "firebomb.sqf"} would avoid those problems, though it might be preferrable to inline them (as opposed to putting it in a file of its own) in this particular case.

Another problem is that the exception handler (catch block) is a catch(anything) (as ofpscript forces it to be) but the handler assumes it to be a string. {if typename _exception != "STRING" throw _exception} as the first command in the handler should properly rethrow the exception so it can be handled even further out. ArmAScript has a tendency to toss out errors when you compare strings to non-strings.

Moving to a less technical problem: The exception handling is used as a way of returning values. Exceptions should be used exclusively for runtime handling of error conditions. At least traditionally (I don't really know how this is in ArmAscript, but i suspect this holds true), this was so because exceptions are rather "expensive" in use. Either way, keeping away from this style of scripting also makes the resulting scripts more maintainable.

Exceptions are most useful when different people work on interacting pieces of code. The clue is that the one who detects the error may not know how the caller code needs the error handled. This is especially true of "library code" which is called from multiple places, perhaps by many users in lots of different missions/addons.

--MaHuJa 07:29, 23 August 2006 (CEST) -- Updated MaHuJa 10:04, 16 July 2007 (CEST)