I am a HC'er from way back.
But it seems like the "correct" way is to throw an error in all cases, simply as a matter of purity and consistency. That legacy stacks might break is a point, but then, how would they break? In other words, how could this arise? Likely a user entered an invalid card reference somewhere, or a card was deleted. The old way is that the code notes the result (or does not), does something with that condition (or not) and either continues or throws its own error notification. By continues, I mean fails to access a card and ignores that case. But if the process always stops dead if a "normal" error is now built in, legacy code would only break where it did not matter if accessing a non-existent card made no difference at all. So would that be unreconcilable in all cases, that is, might the user find himself in a trap he could not extricate from? That is the reason for leaving the old way alone. Craig Newman -----Original Message----- From: Mark Waddingham <m...@livecode.com> To: How to use LiveCode <use-livecode@lists.runrev.com> Sent: Fri, Jun 24, 2016 1:09 pm Subject: Re: Go Card Error Handling Thanks Dar and Jacque, That puts it nicely in context. I'd class this behavior, then, as being for 'HyperCard compatibility'. LiveCode does have a slightly different model from HyperCard though, which is why it is perhaps a behavior which should be reviewed at some point. Indeed, it actually suggests there are a few other places where the error behavior for stacks and cards aren't quite right. For example, the engine will try to load a stack from disk if a reference 'stack "mystack"' isn't in memory - in this case *this* is file I/O and such should probably set the result rather than throw an error. When the engine does have a stack in memory, going to a card cannot fail due to file I/O (as all objects in a stack are in memory all the time) and thus a non-existant card should throw an error. Indeed, you can check whether a card exists before accessing it by checking 'the cardNames'. Indeed, this does suggest that *perhaps* the fact that you can do: go stack <named_of_stack_in_memory> Or go stack <stack filename> Suggests that these are two distinct operations and a 'cleaner' model would be perhaps to have: load stack <stack filename> To load a stack from disk which, as it involves file I/O, should set the result. And, furthermore, make: go stack <name_of_stack> Only succeed if the named stack is in memory, if it is not then it should throw an error. I'm minded to think here that there is actually a nice separation here. In any applications there are stackfiles which can be considered to be an intrinsic part of the application, and then all other stackfiles. The former will typically have named references somewhere (usually in the stackfiles property of another stack), or be included in the description of what the application consists of (i.e. the stackfiles which are included with a standalone). The distinction here is between stackfiles for which their non-existence should be considered an application failure (just as if a dynamic library is not present for a native app, the app will usually not work) and stackfiles which the application manipulates (like any other data file). From an error handling point of view, these present two entirely different cases. For operations which you should always expect to succeed *or* can guarantee will succeed by a preceding check in code, the correct error approach is to throw. For operations which could fail and you cannot 'precheck' for failure, the correct error approach is to set the result. To put it slightly more abstractly: An operation should throw an error for all errors which occur as a result of 'system failure' (for some definition of system) which the application has done all it can to ensure it cannot happen. In this case, if you include a set of stackfiles in your standalone application, and one of them fails to load then you can reasonably take this to be an 'exceptional' circumstance - the problem will be due to something you (as a programmer) can in no-way control. (For example, if one of the stackfiles on disk is corrupted). An operation should set the result for all errors which occur which cannot be checked for beforehand - typically this will be because there is a time-of-check to time-of-use problem. In this case, if you have a stackfile which is not considered directly part of the application and is perhaps chosen by the user - or indirectly by the user - then it is impossible to check before you try and load the stackfile that the operation will succeed. Certainly you can check that the stackfile exists before you try to load it using 'there is a file', but since OSes are pre-emptive, in between doing that check and trying to load it, another process could have done something to invalidate the check. Of course, in the above the assumption we are making is that the 'stackfiles which are part of the application' are not amenable to being fettled with by other processes - in the sandboxed model (such as you get on iOS and Android) this is enforced, in unsandboxed worlds you have to squint a bit to convince yourself that this is actually a reasonable thing to assume. (After all, if you go into an installed applications folder on any platform and start deleting arbitrary files from them, you can't really expect them to function at all!). So, anyway, my question has been answered :) Warmest Regards, Mark. -- Mark Waddingham ~ m...@livecode.com ~ http://www.livecode.com/ LiveCode: Everyone can create apps _______________________________________________ use-livecode mailing list use-livecode@lists.runrev.com Please visit this url to subscribe, unsubscribe and manage your subscription preferences: http://lists.runrev.com/mailman/listinfo/use-livecode _______________________________________________ use-livecode mailing list use-livecode@lists.runrev.com Please visit this url to subscribe, unsubscribe and manage your subscription preferences: http://lists.runrev.com/mailman/listinfo/use-livecode