On Thu, Dec 27, 2012 at 2:33 PM, Erik de Bruin <e...@ixsoftware.nl> wrote:
> Frank, > > I did read your blog, I'm not that stubborn ;-) > Good to hear, I was beginning to suspect you are ;-) > I think you're addressing an edge case (passing 'undefined') to make > your point, but that is fine as it helps focus me on getting the > optimal solution. I say optimal, not perfect, for a reason, which is: > Sorry, but I don't get your point. Even if you think I discovered an edge case that might not make such a big difference in practice, what speaks * against* my solution? - It resembles the original ActionScript semantics - It is easy to understand (look for the number of actual parameters, and if there are not enough of them, ...) - It is easy to generate and doesn't need any more generated code than your solution - It is more efficient than your solution - Mike already implemented it > > As long as we're talking edge cases, I noticed your blog also invokes > one to make it's point, namely using an untyped parameter. Your > function signature is "insult(s = 'fool')". Only when the parameter > you're setting a default for is untyped will it's value be > 'undefined', which you are testing for in your blog. In all cases= > where you declare a type for the parameter ("insult(s:String = > 'fool')"), the value assigned to it when you pass 'undefined' is the > initial for that type, i.e 'null' for String and Object, NaN for > Number, 0 for int, false for Boolean, etc.. > > I'm not sure how your solution provides for this? Mine doesn't either, > mind you, but I gave up perfection for simplicity very early in this > thread ;-) > It does not. I consider this case another problem. That's why I used an untyped parameter to demonstrate how ActionScript handles default parameter values. In ActionScript, it is simply not allowed to stuff a wrong value into a typed parameter or variable. And it is not allowed to leave out a required (= non-optional) parameter. However, there are some cases where implicit type conversion (coercion) takes place. Your example of a parameter of type String that is passed undefined is an example of coercion and has nothing to do with default parameter values. It is the same as assigning undefined to a local variable of type String: the variable is null afterwards. Only that the "assignment" happens in the function call. So far, we do not perform any type checking at run-time. Why? Because we rely on the compiler refusing to compile in case of type errors. So we wouldn't add any code inside the function that checks whether parameter sactually contains a String, because we expect the calling code to have been type-checked. In the same sense, we should not add code inside the function to check for undefined and then assign the initial value for the type (here: null), because a variable of type String should never be undefined in the first place. Instead, this coercion should be generated in the *calling* code! Why? Because if 90% of the calling code can be statically proven to use the correct type (ruling out the value undefined for a String), always doing a dynamic check for undefined at run-time would be waste and inefficient. Note that TypeScript, too, refrains from generating any JavaScript code that does type checking; all type checking is done at compile time. Coercion of a literal value like undefined to a String can simply be done at compile time. However, in case of complex untyped values used as typed values, we'd have to do type *coercions* at run-time. E.g. imagine we have some veryComplicatedFunction():*, and an ActionScript expression of foo(veryComplicatedFunction()), we'd have to translate it to foo(coerceToString(veryComplicatedFunction())). If we plan to implement type coercions like in ActionScript (at least somewhere in the future), here is another argument against checking a parameter for undefined to assign its default value: once we have implemented coercion, the function body would not "see" undefined, but null, and could not distinguish it from a null explicitly given by the caller. And handing in null for a String parameter with a default value of 'foo', I dare say, is no longer an edge case and thus should behave like in "real" ActionScript. Using the arguments.length approach, the called function can tell the difference and behave correctly. Last but not least, what about coercion if the function is called directly from JavaScript? Well, then, we have a problem, anyway, because we also do not type-check. We could either mimic ActionScript's ExternalInterface for code meant to be called from JavaScript and add type checking and coercion code there (in a wrapper function), or live with possible errors at run-time for a simpler and more efficient solution. Sorry I had to say all that, please please nobody cite XKCD's "someone's wrong on the internet" again! ;-) Greetings -Frank-