I'm following the discussions about JS transcoding in the last weeks - I do not feel skilled enough to contribute, but I'd like to thanks you all (and Frank Wienberg in particular) for the detailed explanations - really interesting stuff.
2012/12/28 Erik de Bruin <e...@ixsoftware.nl> > Both solutions have been implemented in FalconJx, I'm moving on. > > EdB > > > > On Fri, Dec 28, 2012 at 1:25 AM, Frank Wienberg <fr...@jangaroo.net> > wrote: > > 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- > > > > -- > Ix Multimedia Software > > Jan Luykenstraat 27 > 3521 VB Utrecht > > T. 06-51952295 > I. www.ixsoftware.nl >