HotKeyIt wrote:We need a #Warn to get an error for variables, so why not do the same for objects?
I presume you're referring to the "uninitialized variable" warnings. Using the value of an uninitialized variable isn't considered to be an error in most cases; the warning is just a tool for debugging. ("Uninitialized" variables really are initialized, just not by the script itself.) This doesn't apply in the same way to objects - When you invoke
x.y, you're asking for something to be done with the object contained by x. If x doesn't contain an object, what you're asking for simply can't be done.
Invoking an object is an operation, like calling a function or double-dereferencing. Invalid double-derefs and dynamic calls also cause exceptions.
Coco wrote:I think it's better to do IsObject(obj.a) / if obj.a is 'object' rather than assuming it as one and invoking it,
I agree. Invoking an object which doesn't exist shouldn't be treated as a valid thing to do.
HotKeyIt wrote:I fully agree it is a useful feature, but definitely it shouldn't be the default behavior and will be a pain for every beginner.
Errors and invalid operations which leave no trace are a pain for everyone.
Another example, as you see 1 line is now at least 4 lines
Both your 1 line code and your 4 line code assume
obj is an object. Therefore, you could easily write it in one line with only a minor change from your original code:
Code: Select all
if !obj["item","value"], obj["item","value"]:="default"
This is also more symmetrical (using the same syntax for both operations), so I would prefer to write it this way in the first place.
; Now we are forced to duplicate the code
That is one way, but
very rarely the only option. It's often not even the easiest.
I think it would be best to have it optionally and let user decide whether to throw an exception but set ErrorLevel by default.
I had already decided against implementing that sort of "error switch" in general. Encouraging users to be lazy causes more problems down the track. Treating things as valid with an optional warning is better, but only where convenience outweighs the potential debugging headaches.
Furthermore, general operations within expressions should
not set ErrorLevel.
Another example, here I need to take the same action when a file is old or it does not exist:
FileGetTime() doesn't throw an exception in the current alpha. I don't see why your old code wouldn't continue to work.
Also I think the error should show which object could not be invoked, otherwise it is not very helpful, e.g.: obj.item.sub.1.name.
That isn't technically possible, because there is no object; that's the point. You probably mean "which part of the expression", but that also isn't technically possible at the moment. I think I initially designed it to display the target value (which is not an object), but since the value is generally an empty string (which gives exactly the same result as now), I thought it better to omit that code.
Can anyone show a few examples where it would be useful for a beginner? So something where it is really important to use catch?
It is not "really important to use catch". It is important to validate what you're doing before you do it. It is better to avoid causing errors than to react to them. It is important to avoid introducing hard-to-detect bugs (e.g. by ignoring errors or pretending they are valid).
RobertL wrote:Also may extend IsObject to support Variadic, like IsObject(A,B,C) to determine if all params are object within one call.
IsObject already behaves like that. It can't be used in the manner you are thinking of because A, B and C each need to be fully evaluated before IsObject is called. For example,
IsObject(x.y, x.y.z) will cause an error if x.y is not an object, because x.y.z is evaluated before IsObject is called.
Note: The current behaviour is not necessarily final. I am simply not convinced that it should be changed.