How can one avoid collisions with contents of extensions?

In the main adventure code, I have the following statements:

Inclusion relates a thing (called X) to a thing (called Y) when Y is part of X. The verb to include (it includes, they include, it included, it is included) implies the inclusion relation.
I know that these exact statements also exist in an extension I’m using. This is, of course, causing a compiler error. I know I’m going to run into such collisions in other instances, as well. Is there a technique that I can use to avoid such clashes without removing the noted statements fro either the extension or the adventure code? I don’t see any scoping mechanism (in Inform7) that is obvious.

Why would you need to include them in both places? It’s like writing the same function in every C++ source and header file.

Also, there’s an existing relation that does exactly the same thing (incorporation). Just use the verb incorporate instead of include.

The direct answer is, you write a section like this:

Chapter 2a (for use without Extension Name by Extension Author)
[Declare the Inclusion relation here.]

This code is compiled when the extension is not used, and skipped when it is used. So the relation gets declared exactly once.

Really this is only needed when you’re writing an extension which may or may not be used with another extension. In your game code, you know which extensions you’re using.

Thanks. I am writing an extension for geocaches that contains the “decoy” code on which I’ve recently been working, plus the definition of a geocache and a logbook. I actually am considering including an extension reference which may or may not be present on the users computer. If it is not, I’ll supply some code that will have the basic features needed to support my extension. Zarfs solution is the one needed in this instance. I seem to remember seeing this in the manual, but could not find it again when I went looking for it.

It’s a shame that inform7 does not embody the OOD concept of “encapsulation” and “exposure” of specific interfaces for extensions. When one uses an extension, one should not need to review the extension for potential conflicts with the internal code of the extension. In most object-oriented languages, extensions are usually intended as a method of “abstract icing out” a complex portion of the code to make the task of programming the main code easier. Not having the noted features make extensions far less easy to use.

Historically, encapsulation in IF programming languages has turned out to be a terrible idea. There is no implementation detail, no matter how internal, that somebody will not eventually need to access. I7 attempts to expose everything, and we get a lot more questions on how to access poorly-exposed elements than on how to hide elements.

Namespacing is another matter entirely.

Thanks, zarf. I understand your viewpoint on encapsulation. However; this means that some sort of “style-guide” is rather important, so that the issues relating to element access is minimized. Learning by example is a rather poor way of getting better. With a few rather excellent coders, this could be seen as somewhat akin to the blind leading the blind.

Would like to hear more on your views relating to namespacing.

Draconis;

Thanks for pointing out “incorporation”. I was copying an Emily Short snippet of code that defined “include”.
Why she had that, I don’t know, because your suggestion works fine.

Not sure I have a lot to say other than the Python rule of thumb, “namespaces are great.” If you search for “namespace” on the suggestion forum (inform7.uservoice.com/) you’ll see some suggestions. It’s also come up on this forum in past years.

If I7 had namespaces, basing them on the section hierarchy is an obvious move.

It seems reasonable for everything to default to global (the current behavior). You’d then want to be able to define terms that are only visible in their own section, unless “imported” elsewhere. (One can come up with plausible syntax for declaring this stuff.)

It’s not as trivial as it is in (say) Python. (Python has only a couple of ways to define a symbol, and all symbols are handled consistently throughout the language. I7… is messier.) You’d want to be namespace actions, properties, definitions, relations, sentence verbs, phrases, etc, etc… Referring to all these consistently in I7 code is tricky.

Also, in many cases, it’s not obvious where a term is defined. You could have “Foo is a room” in one section and “Foo is lighted” in another section; these are parallel declarations as far as the compiler is concerned. (If that example isn’t clear, consider that you might never say “Foo is a room”. It suffices for a game to say “Foo is east of the Kitchen”, and there might be several of those declarations.)

Since Inform 7 is already so much like Haskell, perhaps we could borrow a phrase from it:

Include Epistemology by Eric Eve (Qualified)

And then:

A subject is a kind of person. A subject has an issue called the illness. [...]

A conversational-topic is a kind of subject (from Epistemology).

If something is imported qualified, then the ‘(from Whatever)’ qualification is also required for tokens that come from this extension. This is a more natural-language-esque version of the familiar FooModule.Class phrase found in most OO languages.

Alternatively:

Include Epistemology by Eric Eve (Qualified as E)

Toxicology is a subject (From E)

Of course, parenthesis have a special meaning in I7’s syntax in various ways; maybe the only way to do this is with some other syntax for the ‘qualifier’ token.

For namespaces, the obvious syntax would be:

Book - Knowledge Mechanics (Encapsulated and for use with Epistemology by Eric Eve)

And then all tokens defined inside the section can only be referenced inside it; the namespace outside of it stays ‘clean.’ The way I’d most likely see people use it is to have something like:

Chapter - Things and Stuff (For use with Extension by Someone)

[definitions for exposed things]

Section - Internals (Encapsulated)

This is slightly awkward in some cases, but it would serve most purposes I think. In a game like Counterfeit Monkey which has a huge repository of objects in its code, for example, just encapsulating all those objects can help prevents bugs.

Thanks, Sequitur.
I’ll look into this approach.

I didn’t want to get too deep into suggested syntax. There are complications, as I said.

However, I must reiterate that “encapsulation” (as you phrase it) is a terrible idea. If a term is hidden away, there must be a way to tunnel in and refer to it.

Well, the syntax examples are really meant to give shape to the proposed semantics; I find that it makes it clearer to imagine how it would present itself to users of a future version of Inform. As for ‘tunneling into’ the internals of an extension, you could support something like:

Expose the insides of the Section - Blood and Guts (In Extension by Someone)

To be quite honest, while my conventional programmer instincts quiver a bit at the cluttered global namespace in I7, given what I7 is actually meant to accomplish,I don’t think the expose-everything approach is a problem. But maybe some control over namespaces might interest extension authors; some complex extensions end up exposing a lot of guts that typical users of the extension don’t need to deal with, which in turn ends up cluttering the Index. It might also be useful to people working on very large projects or projects that use loads of extensions that might be using the same name for two different things; right now this makes the extensions outright incompatible (Barring using sections to patch away the offending code).

Qualifying extension namespaces (Haskell-style) makes more sense to me than enclosing the namespace of sections in the code, actually.

I don’t think Sequitur’s “Encapsulation” is unilaterally preventing access (or, it shouldn’t, anyway). Instead, all I would expect from an Encapsulated declaration is that anything inside it is automatically Qualified (as per the earlier definitions) from the perspective of external code. So you can still muck with stuff inside if you really want to, but it won’t happen by accident when you meant to refer to some completely other thing.

Sequitur’s “Expose the insides” is roughly equivalent to Haskell’s “import” or SML/NJ’s “open” declaration, which takes a namespace and dumps everything in that namespace (including nested namespaces, intact) into the current namespace. Using this at top-level is bad karma, but sometimes it makes your life a lot easier.

The only problem I see with Sequitur’s proposal (interpreting Encapsulation as above) is that nested namespaces will get unpleasant. Referring to an Encapsulated section of an extension imported as Qualified inside another Qualified extension will look… pretty unfortunate. I don’t really have a recommendation for this.

Gents;

I would not consider myself to be an advanced user, such as yourselves. However; I am VERY pleased to see that there are some forward-looking individuals who obviously understand the impact of not have some separation of “namespaces” in at least a future version of Inform7. I’ll be watching closely, because someone may well raise a technique that could be used as a partial solution even with the current Inform7 version.

My humble opinion is that any language, which has “extensions”, needs to have a way of exposing only those methods and objects that are documented as being for the use of the end-user. To do otherwise, puts a significant responsibility on an end-user to fully understand the extension code and to steer clear of conflicts. Philosophically; that would seem totally at odds with the typical reason for using an extension. The end-user does not want to be required to have that depth of knowledge in order to use an extension. Even if the end-user had that level of knowledge, they would likely choose to write their own extension, rather than try understand another authors extension code.

Well, what we’ve converged on is the convention that the internals of an extension should have long unwieldy names, which the game author is unlikely to collide with. But of course this is imperfect and imperfectly carried through. Namespaces would be better.

So, since we’re digging into this, here’s why namespacing in I7 is harder than it looks.

First reason, I already mentioned. While most language constructs have a clear point of definition, objects can be created by inference. So at one point in the code you say “The player carries the scissors” and at another point you say “The scissors are plural-named.” One declares a relation, the other declares a property, but neither can be pinned down as the place the scissors are defined. If one of those lines is in a private namespace, do we get one object or two? If one, is it private or not? (Another example: “The Kitchen is east of the Bathroom”, “The Kitchen is above the Basement.”)

Bigger problem: I7 has a lot of ways to declare entities. In theory, inside a private namespace, all of the following declarations should generate a private term:

PrivClass is a kind of thing.
PrivKOV is a kind of value.
The PrivKOVs are priv-blue, priv-red, priv-green.
Definition: a thing is priv-def if …
A thing has a number called the priv-property.
To priv-phrase: …
To priv-phrase (Z - thing) with (col - PrivKOV): …
Priv-relating relates one thing (called the priv-relation) to one thing.
The verb to priv-verb oneself with (…) implies the priv-relating relation.
The verb to be priv-distant from (…) implies the priv-relating relation.

So far so good, but it gets weird when you try to stick the “(from whatever)” qualifier on. Particularly when you stick it onto a multi-word term.

X is a PrivClass (from Namespace). [Straightforward.]
Now the player carries all priv-def (from Namespace) things. [Starting to get awkward.]
Let Y be the priv-relation (from Namespace) of X. [Enh.]
Let N be the priv-property (from Namespace) of X. [Ditto.]
Now Z priv-verbs oneself with (from Namespace) Y. [This is bad.]
Now the player carries everything priv-distant from (from Namespace) Y. [Also bad.]
Priv-phrase X with priv-blue (from Namespace) (from Namespace). [Both “priv-blue” and “priv-phrase” have to be qualified! Argh!]

Lest you think these examples are contrived: the easiest way to blow up Inform (at least the current version) is to say “A thing has a number.” This conflicts with half-a-dozen standard rules. (Second easiest: “A thing has a room called the location.” This compiles but causes several Going rules to be interpreted wrong, thus breaking player movement.)

These are exactly the sort of cases that namespacing should solve. So, at a minimum, both properties and property verbs must be namespaceable (separately!) Which brings in all the icky grammatical cases above.

It’s possible that we can dodge this whole cannonball by allowing the user to import entities by section. Perhaps

Chapter - Secret Closet (friendly to Namespace)

…and then everything defined inside Namespace is available in this chapter.

However, I’m not convinced this is sufficient. I also don’t know what’s best-practice in language design for this sort of thing. (Do you put the “qualified” / “encapsulated” flag in the extension, or on the line that imports the extension? Or should both options be available? How does section nesting play into this? Do we need an “…unfriendly to…” flag as well?)

In my head the Qualified statement would go in the line that imports the extension; without it, the names from the extension would spill over into the global namespace (I.e., the current default behaviour, unchanged). With it, they would be qualified. This is basically the same way Haskell solved its own problem with extensions trampling one another’s namespace; in Haskell, you can import a particular library…

import qualified XMonad.StackSet as W

And then names from that library can be invoked with the familiar dot syntax people are used to from OO languages, so the RationalRect function from that library, instead of being thrown into the normal namespace, gets called W.RationalRect.

Looking at my xmonad.hs file for this example has actually shown me another tidbit which might be interesting to Inform:

import XMonad.Layout.NoBorders hiding (Never)

What this does is import the library, but the Never that’s defined in that library isn’t brought into the namespace of the importing file at all; this could be used to quickly handle collisions without fuss, for example:

Include Epistemology by Eric Eve.

Include Some Other Extension by Someone Else. (Hiding subject)

You could also support the exact opposite:

Include Some Extension by Someone. (Exposing only widgets, devouring, to belong, the belonging relation, and the Widget Repository.)

That presumes that everything in the namespace has a distinct, writable name. Would you say “(Exposing to be priv-distant from, to priv-phrase () with ())”?

A namespace (currently, the single global namespace) is not a list of symbols, but a list of phrase templates which are sometimes distinguished only by context. I worry that they don’t all have obvious names.

(I was also worried about objects with commas in the name, but that at least is forbidden by the compiler.)

Well, you could give us a way to refer to phrases by name, and in the process gives us functions as a first-class value…

(I am not entirely serious.)

In seriousness, Inform’s syntax does make it hard to handle those namespace issues; but I think the semantics of namespaces, at least, is workable?

Already in the language. (You may give the phrase a name at the point where it’s defined.) But since this is optional, it doesn’t universally solve the problem.