clarification on namespaces

# zwetan (18 years ago)

making some tests in Tamarin and Flash I realize that having a "dynamic way" to use namespace could be usefull

as I see it now namespaces need to be explicitely opened

use namespace xyz;

but what about the cases where someone would want to autoselect one among a bunch of namespaces, in short to be able to do

use namespace eval("choice")

my use case is the following: the need to autoselect a namespace depending on the operating system, if the Flash player run on Windows use the win32 namespace, if the tamarin VM run on Macintosh use the mac namespace, etc.

concrete example (tested in Flash and a modified Tamarin)

package system {

/* Class: Reflection
   Provide basic reflection mecanisms on the language.
 */
public class Reflection
    {
    public namespace notimplemented;
    public namespace flash;
    public namespace redtamarin;

    private static var _current:Namespace = notimplemented;

    private static function init():void
        {
        switch( Environment.host )
            {
            case HostID.Flash:
            case HostID.Apollo:
            _current = flash;
            break;

            case HostID.RedTamarin:
            _current = redtamarin;
            break;

            case HostID.Tamarin:
            case HostID.Unknown:
            default:
            _current = notimplemented;
            }
        }

    notimplemented static function getClassName( o:*, path:Boolean

= false ):String { return ""; }

    flash static function getClassName( o:*, path:Boolean = false ):String
        {
        import flash.utils.getQualifiedClassName;
        var str:String = getQualifiedClassName( o );

        if( !path && (str.indexOf( "::" ) > -1) )
            {
            str = str.split( "::" )[1];
            }

        return str;
        }

    redtamarin static function getClassName( o:*, path:Boolean =

false ):String { import avmplus.Reflection;

        if( !path )
            {
            return Reflection.findClassName( o );
            }

        return Reflection.findQualifiedClassName( o );
        }

    public static function getClassName( o:*, path:Boolean = false ):String
        {
        return _current::getClassName( o, path );
        }

    init();
    }

}

the situation is that Flash declare native function for "reflection" in flash.utils.* and RedTamarin ( a small project where I try to add some native function to Tamarin) declare native function for "reflection" in the avmplus.Reflection class

the goals is to have a public reflection API in the system.Reflection class if the host support it you have reflection either in the "flash" or "redtamarin" namespace, if not it default to stub functions in the "notimplemented" namespace.

the hackish workaround is working, but imho it's not ideal main problems are:

  • compiling for Flash, you need to define a "fake" avmplus package because of the the import in the redtamarin namespace
  • you can explicit declare a namespace before compiling ex: use namespace flash but if you do that you'll need to change this one line depending on the host you compile for
  • I didn't really find another way to select dynamically at runtime a namespace other than declaring namespaces in the class directly, namespace at package level can not be switched dynamically apparently.

ok this was before I read some notes in the M0 release :)

so here my questions:

in es4/buildins/Namespace.es " // FIXME: we might need a static make-a-user-namespace // function here for dynamic namespaces. Not a ctor! "

I do agree, being able to select a namespace dynamically would be of great help for some particular cases, cf my use case.

in es4/doc/JD_NOTES " BUGS

  • importing a non-existing package is not an error "

indeed, this can cause problems when the underlying native API is not the same for different hosts, to compile you need to define fake/stubs packages and/or classes, not ideal...

note that my goal is to be able to provide a set of packages and classes that can target different hosts depending on their native capacity, but for this to be elegant somehow I would like to be able to select dynamically which namespace gonna be used at runtime is something is planed in that sens with the final ES4 spec ?

maybe I missed a simpler way to do it, but I wish I could use a namespace like that

package { public namespace A; }

package { public namespace B; }

package test {

public class Something { A static function hello():String { //... }

   B static function hello():String
      {
      //...
      }

}

//main entry point package { var ns:Namespace = new Namespace( "A" ); //this can not be done afaik use namespace ns; //this can not be done afaik import test.Something; trace( Something.hello() ); //namespace A used }

# Peter Hall (18 years ago)

I think it's a fairly fundamental requirement that attributes are constants. However dynamic you want to make it, you need some fixed points somewhere.

However, you can use a dynamic qualifier to access a property in a namespace, by using a Name object.

var name:Name = new Name("www.memorphic.com", "foo"); obj[name];

Peter

# Lars T Hansen (18 years ago)

Nit: The way I currently understand the spec the first argument to the Name constructor if called with two arguments must be a namespace value, not a string, but this introduces no particular problems:

namespace memorphic = "www.memorphic.com"; ... var name : Name = new Name(memorphic, "foo"); obj[name];

# Peter Hall (18 years ago)

On 6/11/07, Lars T Hansen <lth at acm.org> wrote:

Nit: The way I currently understand the spec the first argument to the Name constructor if called with two arguments must be a namespace value, not a string, but this introduces no particular problems:

is it necessary to use the pragma? Surely you create a new Namespace()... otherwise it does introduce a problem..

Peter

# Lars T Hansen (18 years ago)

"namespace" is not a pragma, it just creates a new namespace object with some identity. You can pass these around as values:

namespace ns1, ns2;

var x = ns1; new Name(x, "foo")

you can't use namespace values in declarations, so "x var int y = 37" won't do, but IIRC you can use them in expressions, eg x::y. From the reference implementation:

namespace ns = "foo"; ns [user-defined namespace foo]

var v = ns v [user-defined namespace foo]

ns var x = 10 x [stack] [] ERROR EvalError: uncaught exception: ReferenceError: unresolved lexical reference {multiname: [ns public '']::x } (near builtins/Error.es:83.47-83.47)

ns::x

10

v::x

10

# Peter Hall (18 years ago)

Ah ok. I was under the impression that you couldn't do:

if( condition ){ namespace ns1 = "foo"; else{ namespace ns1 = "bar"; }

And, in any case, if your URI came from an external source, you'd have to use new Namespace() in order to use it.

Peter