NetLogo does have its include mechanism as a first step towards modularity.
The documentation says that it is still experimental – like the double underscores in the keyword also suggest. The documentation also indicates that all files share one namespace.
In fact, included files can also refer to names introduced in any other file included in the model.
This would be a big problem for true modularity.
From issue #2386 in the github repository, it appears there has been work on namespaces going on, but I could not find a specification of what it would look like.
From scratch, I have the following ideas that also confine the use of names.
These might overlap or extend the ideas already under discussion.
the construct import [name filename] (e.g. import [econ "economics.nlogom"]) imports a module and assigns a local name to its namespace
inside the module, names are unqualified
when imported, all names are qualified by the the import name plus a colon (e.g. econ:revenue), as for extensions
there is no indirect importing, not even by multiple levels of qualifiers
it is not allowed to set a new value for an imported name; hence, values are under control of their module, but can be read outside their module
breeds-own variables can only be defined in the module that defines the breed
patches-own can only be defined in one module – this is tricky
the interface tab of the model, should not refer to qualified names – if necessary, encapsulate them in (command or reporter) procedures of the model
The role of colons in the language does change slightly.
As far as I could find, at least in the example models, this does not introduce any conflicts, however.
There might be an issue when modules are imported multiple times under different names.
In Python, they are just aliases to the same elements. NetLogo could follow this.
Along the same lines, cyclic imports can be solved.
Thank you for the detailed suggestions! As you deduced from GitHub, we are currently in the process of implementing a module system for NetLogo, the first iteration of which is scheduled to be shipped with the upcoming release of NetLogo 7.1. Although the syntax and specification of the first iteration has already been finalized internally, we welcome your feedback once it’s released!
Thank you for this clarification. This is very much in line with other languages (and more than I proposed…)
Where should NetLogo find the module to be imported?
Do we need to register a module before it can be imported?
Is there another dialog to specify modules?
I hope modules are stored separate from the model. Otherwise reuse would be difficult.
Are there plans for some form of (minimal) encapsulation, as in my ideas above?
With the new system, this “functionality” will go away. Only terms that have been explicitly imported into (or defined in) the current file will be visible.
There’s an export keyword. So in this module:
to-report apples
report 3
end
to-report grapes
report green-grapes + red-grapes
end
to-report green-grapes
report 4
end
to-report red-grapes
report 1
end
export [ apples grapes ]
only apples and grapes would be importable into other modules.
We plan on supporting three possible sources:
File locations relative to root of the project (i.e. relative to the .nlogox file; not absolute paths)
Modules globally installed through the Library Manager (an expansion of the current Extension Manager, so that NetLogo packages can be installed in the same easy way)
Modules installed in the local package repository
The idea behind #3 is that you might be developing some modules and not want to publish them to the Library Manager, whether because they’re private, or in-development, or whatever, so you can store the modules in a centralized place on your machine and still have them accessible to all of your different NetLogo projects without having to repeatedly copy the files into each project.
Yes, the current design involves a dialog for helping with importing the correct version of the correct library from the correct source under the correct name. I believe that modules that are being imported through relative paths will not need to be registered in the dialog.
Indeed. They will be separate from the .nlogox file by default, but the plan is to have a menu option to easily export your whole project as a single, self-contained file, which can make it much easier to share complete projects with others and to easily open the full project in NetLogo Web.
That’s impressive! Most of this will address the want for modularity.
There might still be difficult issues with scopes of names. For example, if we define agent properties (“own” variables) in a module but don’t export them, how are they shown in a turtle/link/patch monitor? And similarly for globals and the globals monitor.
If a module imports another module, and both introduce new globals, the globals monitor could become a real nightmare. [Well, my draft does not address this either…]
For names of modules, I would definitely distinguish the filename (usually case sensitive, might contain non-identifier characters) and the module name (in NetLogo not case sensitive, with some restrictions on allowed characters). So, in my opinion, the filename should be a string for NetLogo.
When specifying the filename separately, the standard should be relative path names, but absolute path names would be possible (though not portable, therefore not recommended).
And more more suggestion: for modules, could you introduce a file extension that clearly indicates netlogo (something like .nlogom rather than .nls)?
if we don’t do any export, would the default be to export nothing or to export everything?
given the general structure of NetLogo code, I would prefer putting exports before procedures (like breeds and variables) rather than at the end of the code
or can we add a separate export statement to each procedure?
in fact, having multiple export statements helps in maintaining code
if exporting a breed, what happens if we export only the plural or only the singular form?
is it allowed to export names that were imported from yet another module?