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-

Reply via email to