module specifier in es6 import and export - module

I'm confused about what the module specifier in these statements refer to:
export {bar} from "foo";
import {bar} from "foo";
What does "foo" refer to? It can't be a file since it would be something like "./foo". If it's not a file, I assume it's an ID. How is the ID defined?
I'm exporting from a js file, but the import would be part of an inline html script (type="module") in the firefox browser.
The browser version (and browser settings) have been verified to work with es6 modules.
Thanks in advance.

ES6 does not specify what the module specifier refers to.
It is indeed just that: an identifier. Nothing more.
It is left to the environment to resolve these identifiers to an actual module. A loader might interpret them as relative file paths, as global ids, as npm module names, as anything else.
In browsers, <script type="module"> took some time to specify, but it's here finally. A module specifier of "foo" is currently invalid, a browser will ignore that module as it doesn't know what to do with it. It will need something that resolves to an URL to load. Jake Archibald wrapped it up succinctly:
"Bare" import specifiers aren't currently supported. Valid module
specifiers must match one of the following:
A full non-relative URL. As in, it doesn't throw an error when put
through new URL(moduleSpecifier).
Starts with /.
Starts with ./.
Starts with ../.
Other specifiers are reserved for future-use, such as importing built-in
modules.

Related

How does import find the file path in Kotlin?

I've read the Kotlin doc (https://kotlinlang.org/docs/packages.html), and I understood that, when importing a package, the package name does not need to match the folder's path that stores the package (unlike what happens in Java).
I don't have issues creating a package and importing it into other classes.
What I'd like to understand, is how the compiler can find the file to import?
For example:
if a file import animals.mammals.cats.* :
import animals.mammals.cats.*
...
the entities to import do not need to be stored in the file /animals/mammals/cats.kt, as long as the package name is "animals.mammals.cats":
package animals.mammals.cats
...
This Kotlin file could be stored in src/animals/kittens for example.
In other words, how import can locate the file/s to load since the package name does not help?
Thanks!
TL;DR: the compiler is given the paths to all files to compile and to all dependencies, and therefore knows about all available packages and the declarations they contain.
First, note that the import statement itself is not really the most important. It's just a convenient syntax to avoid having to specify the package everywhere throughout the file. But technically you don't need to import anything to be able to use declarations from outside the current file - you can just use their fully qualified name (a.k.a FQN) which is the package name + . + the name of the declaration.
Now, on to your question. When you run the compiler, you provide the paths to the complete set of files to be compiled at the same time: you compile a module, not a single file. Therefore, it has access to all declarations in all those files and maintains its own data structures about the available classes and top-level functions, and all symbols in general. So it can store and find declarations using just their FQN. (DISCLAIMER: I'm no expert and I don't actually know how it's done internally, but I'm just guessing that conceptually it's like storing a big mapping between FQN and the information about the corresponding declaration.)
If the declaration you use is not in the set of files being compiled, it must be in one of your dependencies. You can tell the compiler about the available dependencies by specifying the list of jars containing their already compiled classes. This list of all classes available at compile time is called the compile classpath. This is why the tool you use to build your project (for instance, Gradle or your IDE) needs to know about those dependencies, so it can put their declarations on the compile classpath when calling the compiler for you. Then, just like declarations that are being compiled, the ones from the compile classpath can be easily looked up by the compiler (the path has been given to the compiler as an argument).
Now, when you actually run your compiled program, at least on the JVM, the classes required must be placed on the runtime classpath - a set of classes given to the java program. Finding those declarations while the program runs is done by classloaders. There are multiple classloaders, organized in a hierarchy, but there is no need to go into details here. Basically, each time a class is used for the first time while your program is running, one classloader will be asked to load that class into memory. There are different implementations of classloaders, but one of the most common is the URLClassLoader which is given the URLs of some jars that contain classes, and knows how to read classes from these jars into memory on-demand.

Julia custom module scope of variables

I am starting writing my first custom module in Julia.
What I am doing is writing all the files in a folder, then import them in a ModuleName.jl file and eventually writing a test program which executes a precompiled main() function which calls my custom module (I like keeping a modular style of programming).
The problem is that I think I am missing something on the use of using and import keywords. In my test file I have the following lines:
push!(LOAD_PATH,"./ModuleNameFolder")
using ModuleName
I thought that functions of ModuleName if loaded with using could be called without explicit ModuleName.myfunct(), but only through myfunct() while this is not the case. If I omit the ModuleName the compiler throws an UndefVarError.
What am I doing wrong? I would like to bring all the functions of my custom module on the main scope
Welcome to Julia.
What do you mean by precompiled main() function? Tests in Julia are normally set on a specific file that is run automatically at each push of your code on the repository that you use to host the code.
Any how, try include ./ModuleName followed by using .ModuleName (note the dot). And remember to export the objects in ModuleName that you want to make available directly.
Have a look on my tutorial: https://syl1.gitbook.io/julia-language-a-concise-tutorial/language-core/11-developing-julia-packages

Defining global variable for Browserify

I'm using SpineJS (which exports a commonjs module) and it needs to be available globally because I use it everywhere, but It seems like I have to do Spine = require('spine') on every file that uses Spine for things to work.
Is there any way to define Spine once to make it globally available?
PS: I'm using Spine as an example, but I'm in general wondering about how to do this with any other library.
Writing Spine = require('spine') in each file is the right way to do.
Yet, there are several possibilities by using the global or window object (browserify sets the global object to window, which is the global namespace):
in spine.js: global.Spine = module.exports
in any other .js file bundled by browserify: global.Spine = require('spine')
in a script tag or an .js file referenced by the .html file, after the spine.js file: window.Spine = require('spine')
First of all, for your example David is correct. Include all dependencies in every module you need it in. It's very verbose, but there is no compile time magic going on which alleviates all sorts of anti patterns and potential future problems.
The real answer.
This isn't always practical. Browserify accepts an option called insertGlobalVars. On build, each streamed file is scanned for identifiers matching the key names provided and wraps the module in an IIFE containing arguments that resolve each identifier that is not assigned within the module. This all happens before the dependency tree is finalized, which allows you to use require to resolve a dependency.
TLDR
Use insertGlobalVars option in Browserify.
browserify({
insertGlobalVars: {
spine: function(file, dir) {
return 'require("spine")';
}
}
});
For every file scanned, if an identifier spine exists that's not assigned, resolve as require("spine").

What does it mean for Scheme library to be *loaded*? When are Scheme libraries *loaded*?

I am studying the Revised7 Report on the Algorithmic Language Scheme. My question is on section 5.6 Libraries.
In this section, it says:
When a library is loaded, its expressions are executed in textual order. If a library's definitions are referenced in the expanded form of a program or library body, then that library must be loaded before the expanded program or library body is evaluated. This rule applies transitively. If a library is imported by more than one program or library, it may possibly be loaded additional times.
What is this supposed to mean? Does it mean that a library is loaded only if an imported identifier is actually being referenced or already when the library is part of an import set of an expanded program or library? If the same library is being referenced by two other library imported by the same program, is the library loaded twice or just once?
As the loading of a library may have side-effects due to the execution of its expressions, the answers to these questions seem important to me. Also, do share the two libraries that import a third library its internal global variables?
I have done some experiments with chibi-scheme: Per program, chibi-scheme loads every library only once and even if none of its exported identifiers are actually referenced. In fact, this looks like a sensible and easily implementable thing to me.
P.S.: There is another point where I think the specification is a bit vague: What happens if, in a program, an import set imports an identifier named import? Does it mean that an immediately following line (import ...) is interpretated as a command or definition (depending on what the imported identifier import stands for) or still as an import set?
P.P.S.: What is even the reason for allowing more than one import declaration in a top-level program?
Let me attempt to answer each of your questions one-at-a-time. Also, if it would help, here is a link to the meta-language used to implement libraries in chibi scheme.
A library is loaded when it is imported via an import statement.
If a library's definitions are referenced in the expanded form of a program or library body, then that library must be loaded before the expanded program or library body is evaluated.
This just means that the library must be loaded before its definitions are referenced (or it would be an error, since the definitions would not be found).
If a library is imported by more than one program or library, it may possibly be loaded additional times.
This is implementation-dependent, so your library code should not make assumptions that it will only be loaded once.
What happens if, in a program, an import set imports an identifier named import?
Most likely, the new import identifier would shadow or replace the import, so that any import statements in the same scope would no longer work as expected. This might be implementation-dependent - if import is implemented as a special form then it would not be overridden by a newly introduced identifier.

Rebol, extensions and function naming

I am working on some extensions for Rebol 3 (posix/fann/math).
To avoid global namespace pollution, I am exporting the functions with a simple prefix source identifier. For example: POSIX-FORK for fork, or POSIX-NANOSLEEP for nanosleep.
Is there any better approach or official Rebol naming convention?
That's a pretty standard naming convention for Rebol exports, though they should be lowercase in the code of course. The all uppercase thing is just a naming convention when referring to functions in chat clients or web sites that can't show code like this. You generally don't uppercase any words in Rebol code unless they are used for something else.
However, if you want to avoid global namespace pollution, declare your extension module with the options: [private] header. That will make it so the exports of your module are only imported by modules or scripts that request them explicitly with import or the needs header. This especially goes for modules or extensions that export low-level C-like APIs, which are best only imported by the modules that implement the high-level wrappers. It's good to remember that the module part of the extension is a full Rebol module, and it is often best to put your high-level wrapper code there and not export the C-like functions at all, keeping them for internal use.
An additional trick is that when you are exporting constants or enum values, it is best to put them in an object in your module and export the object instead. That way you don't export to the global namespace and you can protect the words from modification.
Another trick is to not export stuff at all and have people import your module using the import function. Unless you mark your module's words as hidden they will still be available even if they're not exported. This is a little inconvenient in most cases though, so it's better to use a private module instead. You can also export your high-level API and not export your low-level API, so the low-level API is available to import if someone wants to use it.
Check here for a more thorough answer about how modules and extensions are used: How are words bound within a Rebol module?