#324 Namespaced Facets

tompalmer Wed 30 Jul 2008

I want to start a separate thread on namespaced facets. I still haven't thought through the syntax for defining them. Probably something in build.fan, but here are my thoughts on how to use them.

I think @action is better than @swankyAction for the common case, and for the uncommon case of collisions, I think @swanky::action is better than @swankyAction, too. It's more consistent.

Also, @whatever should resolve to "podName::whatever".intern as an expression in any context. For example (modified from the language docs):

// get a blah::description string
obj.type.facet(@description)

// check if an object implements the blah::simple facet
obj.type.facet(@simple, false) == true

The following would return the same (again presuming the blah pod is resolved for the symbol/string):

// get a blah::description string
obj.type.facet("blah::description")

// check if an object implements the blah::simple facet
obj.type.facet("blah::simple", false) == true

It think that these rules are simple, easy to learn, and make facets a lot more versatile and pleasant.

brian Wed 30 Jul 2008

I'm all all for trying to figure out a design (but skeptical we'll find a design I like).

One issue with generic symbols is that sys might end up defining a bunch of common ones. Since these are effectively global variables, conflicts would occur often and you would end up having to fully qualify a lot of the time.

tompalmer Wed 30 Jul 2008

Well, sys defines a lot of common class names, too, and that's okay. The difference now is that you always have to qualify everywhere else, and people will probably cut corners and not learn the policy for a while, either.

I think newcomers will expect namespaced facets and be surprised that they are all global. (And I've seen here support for namespaced and/or typed facets from Cedric, Stephen, and "BillBurke". No negatives from third parties yet.)

By the way, my current focus is back to facets, and I recommend that @whatever always imply namespacing (so no globals), just like classes are effectively always namespaced (once a pod/build gets in the picture). Classes need defined before use. I don't see why facets need to play by different rules.

At present, I also don't want to try to unify the map/facet syntax. I think @whatever="something" is okay. And I've given up on typed facets still, too. Just automatic namespacing of strings is all.

But even though my current focus is facets, I think easy namespaced strings/symbols would have other uses. For instance, even in Java, for sparse settings people sometimes use maps (here's an example from SAX) instead of direct fields on classes. For similar use cases in Fan, people could use Maps, too, but instead of ugly inconsistently namespaced strings, people could just use @symbols that are automatically and pleasantly namespaced.

Anyway, don't want to distract. My main opinion is just that always namespaced facets really makes Fan more cohesive, consistent, and simpler overall. I think it's also what people will expect.

tompalmer Thu 31 Jul 2008

Can I call for a survey if people are willing to answer? Ignoring the details of how it would work, who votes namespaced (by pod) facets, and who votes global facet names like today? (I understand the results aren't binding or even scientific. I'm just curious.)

So again, namespaced or global?

jodastephen Thu 31 Jul 2008

I believe some form of namespacing is essential. Clashes will be impossible to resolve otherwise.

I also prefer to have the ability to restrict the value by type.

cgrinds Thu 31 Jul 2008

Namespaced

JohnDG Thu 31 Jul 2008

I believe some form of namespacing is essential. Clashes will be impossible to resolve otherwise.

There will be clashes early on, but third-party libs will quickly learn. You'll see JUnitTest instead of Test, for example.

Just like in C world.

alexlamsl Thu 31 Jul 2008

Just like in C world.

Isn't that a Bad Thing? The reason why we introduce namespace in later languages?

andy Thu 31 Jul 2008

I'm open to namespacing if we find something that works well.

cbeust Thu 31 Jul 2008

Just like in C world.

You say that as if it's a good thing :-)

Java has a troubled history regarding this problem. Initially, people embedded namespaces inside identifiers (e.g. JUnitTest). Then static classes became popular, and it became JUnit.Test.

Static imports came along, so we switched to importing JUnit and just referring to Test, but then a few people complained that we were losing in readability, so people ended up either not using static imports or reverting back to JUnitTest. Full circle.

JohnDG Thu 31 Jul 2008

You say that as if it's a good thing :-)

It's neither good nor bad. What's the difference between net.nbrain.test.JitMock.newMock and JitMock.newMock, or, even more cautiously, NBrainJitMock.newMock?

Namespaces embedded in the names of functions/classes/facets are no different than language-supported namespaces, except there's more typing (or auto-completing) involved in the former. That's really what it comes down to: the fundamental difference is not clashing (after the community adapts) but typing.

So in my view, namespaces are not a fundamental issue, but rather an issue of convenience. Which means Fan can get facet namespaces or not, and I'm mostly fine with either outcome (maybe a slight preference for namespaces if the implementation is really nice).

tompalmer Fri 1 Aug 2008

Thanks for some feedback. My main motive is that C-ish @swankyAction (vs. @action or qualified @swanky::action) isn't consistent with other Fan namespacing. And normal Fan namespacing is better than C. My most recent versions of my proposal are just about as close as I can get to current Fan while making them namespaced. I'm really trying super hard to make it a small step.

brian Fri 1 Aug 2008

I agree that facets aren't consistent with namespaced types - but that is because they aren't types (today at least).

Adding namespace aware facets involves solving two problems. The declaration side:

@fluxViewMimeType="x-directory"
internal class DirView : View {}

And the flip side is the client side:

Type.findByFacet("fluxViewMimeType", file.mimeType.toStr, true)

Any namespace aware solution has to solve both problems. Solving the declaration case is pretty easy. But you can't solve that problem, then force people to do this:

Type.findByFacet("flux::ViewMimeType", file.mimeType.toStr, true)

The important distinction is that today only types are namespace aware. So that gives you two choices to solve this problem:

  1. make facets a new kind of type (Java's design)
  2. make facets some new kind of namespace aware language construct

Neither of those options is very appealing to me since they complicate the language in a pretty significant way. And the only problem solved here is to save some typing (assuming people use conventions). There might also be value in reflective capabilities for IDEs - although that can solved with pod meta-data orthogonally to this discussion.

Between 1 and 2, I think option 2 is the more complex solution. That is because creating a new language construct which is namespace aware is a big deal. We have to add new reflection capability for the compiler to use. And we have to overload the using statement in an new way. And most importantly we have to introduce some new literal syntax for the client side use case.

Option 1 is less complex because qualified names, unqualified names, and using statements already work against types. And we also have the client side solved via type literals:

Type.findByFacet(ViewMimeType#, file.mimeType.toStr, true)

The reason I don't like using types is that it will litter the type namespace with a bunch of new type identifiers. Consider all the prime nouns sys would end up importing (especially over time).

So I agree that globally scoped facets suck. But the alternative seems to suck more - they complicate the language, and the only gain is really to save typing. Not that I want to discount saving typing (I'm pretty obsessive about that myself), but I'm having trouble justifying the trade off.

But maybe there is an alternative design I'm not seeing? For example if the new construct was more general purpose than just facets I could accept the additional complexity. Tom I think that is what you've been trying to do by creating a more general purpose symbol feature. I like that approach, but does Fan really need symbols?

So to clarify my position - I don't consider namespace aware facets a huge problem to solve. I consider it an annoying aspect of the language, but not a critical flaw. However I'm all for namespace facets if we can add them elegantly without adding a lot of complexity to the language.

Login or Signup to reply.