views:

1682

answers:

4

I'd like to implement the following logic:

function setMyValue (myVar:int = undefined):void
{
    if (myVar == undefined)
    {
     /* Generate a value for myVar */
    }
    else
    {
     /* Use the supplied value for myVar */
    }
}

So if the value is supplied, use it. If not, generate it. Seems simple enough.

Problem is that AS3 doesn't like this. 'undefined' gets coerced into '0', so myVar is never undefined. I've tried variations with NaN, null, etc, but nothing has worked. The only kludge I can think of offhand is to supply some 'magic number' to use as default, but that's ugly. Anyone know a better solution?

Thanks!

+2  A: 

Is the generated value a const? If it is, why not simply have this as the default value?

Problem is that AS3 doesn't like this. 'undefined' gets coerced into '0', so myVar is never undefined.

Yes, because, this is the default initialization value for int (for string and Object this'd be null).

The other option is to loosely type the parameter as an Object or keep it unspecified (by using a *) and later on typecast it to int if it is non-null.

function setMyValue (myVar:Object = null):void
{
    if (myVar == null)
    {
        /* Generate a value for myVar */
    }
    else
    {
        int value = myVar as int;
        /* Use the supplied value for myVar */
    }
}
dirkgently
Appreciate the quick response. The generated value isn't a const; it needs to be generated at the time the method is called. I guess my question would be is loose-typing this way any cleaner than using a magic number? Doing it the way you suggest would mean I'd need to scrub the data to ensure I'm not being handed an illegal value (string/Number/Microphone). At least using the magic number a developer would know the required data type. I would just think there must be a cleaner way to do this.
Wikiup
BTW, I loved you in "Long Dark Tea Time..." ;c)
Wikiup
A: 

You are actually better off using NaN and doing this:

function setMyValue (myVar:int = NaN):void
{
    if ( isNaN( myVar ) )
    {
        /* Generate a value for myVar */
    }
    else
    {
        /* Use the supplied value for myVar */
    }
}

That is both more technically accurate and it is also more stable. It will also allow you to strongly type at compile-time.

Christopher W. Allen-Poole
+4  A: 

UPD (from my comment): It is certainly not a good practice to pick some magic number to indicate value absence, unless you can be completely sure this magic number would not appear as a result of some arithmetics (which generally is true). So the best approach here is either to use a wider type than int (e.g. Number), or pass some flag (Boolean value) to function, as well as int, to indicate actual value absence. Choice should depend on whether you want to emphasize the importance of fact that passed value is integral.


If you feel comfortable with expanding argument type, then you should use NaN and do this:

function setMyValue (myVar : Number = NaN) : void
{
    if ( isNaN(myVar) )
    {
        /* Generate a value for myVar */
    }
    else
    {
        /* Use the supplied value for myVar */
    }
}

That is both more technically accurate and it is also more stable. It will also allow you to strongly type at compile-time and would not cause weird bugs as in case of using Object.

Note that this will not work with int as one of the answers suggests. int has only numerical values, and NaN will get coerced to 0. You will need to use Number type.

If you're worried about performance - don't be. Using Number instead of int or uint is generally OK.


UPD: If you want to explicitly mark that argument should be integral just use additional flag and exact type - it would be much clearer.

function setMyValue (isIntValueSupplied : Boolean = false, intValue : int = 0) : void
{
    if ( isIntValueSupplied )
    {
        /* Generate or use a default value of intValue */
    }
    else
    {
        /* Use the supplied value for intValue */
    }
}


Another option is to define your own type with additional value, e.g. MaybeInt, which holds integer value and a flag (whether it was actually initialized or not). That way you would clearly signal that value should be integral or no-value. However, this approach may be a bit bulky.

dragonfly
This is certainly getting closer, as at least I'll know that it's a number coming through the param (which I can then re-cast to an int/uint), but it goes to much the same problem as my concern with dirkgently's response. Is it really cleaner to typecast to the wrong data type? Perhaps I'm simply asking for something that can't be done in a truly clean way. BTW, this has nothing to do with performance per se. I'm simply trying to establish a best practice approach to this issue. Thanks for the help!
Wikiup
@Wikiup: It is certainly not a good practice to pick some magic number to indicate value absence, unless you can be completely sure this magic number would not appear as a result of some arithmetics (which generally is true). So the best approach here is either to use a wider type than `int` (e.g. `Number`), or pass some flag (`Boolean` value) to function, as well as `int`, to indicate actual value absence. Choice should depend on whether you want to emphasize the importance of fact that passed value is integral.
dragonfly
I think your comment provides a far better "best practice" solution than your original answer. I agree that magic numbers are seldom a good idea (that was, after all, the point of my original posting). function setMyValue(useSuppliedValue:Boolean = false, suppliedValue:int = 0), while wordier, seems to provide a less ambiguous format for the method; this strikes me as a pretty solid answer. If you want to edit your answer and write it up as such, I'll happily check 'answer' and credit you with the rep points. :c) Many thanks!
Wikiup
(re: my previous. I don't mean to be coy or cagey about checking the 'answer' button. I'm very new to stack overflow and don't know the etiquette for these things. Seems to me that the answer should read correctly before I give it my thumbs up. Is that right?)
Wikiup
@Wikiup: Thanks for advising to update the answer. Did so.
dragonfly
A: 

My solution was to simply use this

if(myUint == new uint){ is undefined, act appropriately; }
Shaun Doudican