Skip to content

Instantly share code, notes, and snippets.

@Havvy
Last active December 18, 2015 00:55
Show Gist options
  • Save Havvy/5549451b8971688ce42e to your computer and use it in GitHub Desktop.
Save Havvy/5549451b8971688ce42e to your computer and use it in GitHub Desktop.

Import with args

Summary

A method by which the programmer can import a module multiple times, each time differing on a dynamic value while still delivering on the static property guarantee.

Example

Note that the current way would still be preferred for this example, but that there are many cases where the proposed way would be better. The reason that the current way is better for this example is that it should be possible to make multiple counters with the same initial value. But the example is to show syntax, not to show good code. If you have a better example, please let me know.

Current

Counter.js

export default function (initialValue) {
    let counter = initialValue;

    return {
        increment: function () {
            counter += 1;
            return counter;
        },

        decrement: function () {
            counter -= 1;
            return counter;
        }
    };
};

UsesCounter.js

import Counter from "./counter";

const myCounter = Counter(10);
console.log(myCounter.increment());
console.log(myCounter.decrement());

Proposed

Counter.js

import args from this;

const initialValue = args[0];
let counter = initialValue;

export function increment () {
    counter += 1;
    return counter;
}

export function decrement () {
    counter -= 1;
    return counter;
}

UsesCounter.js

import * as myCounter from "./counter"(10);

console.log(myCounter.increment());
console.log(myCounter.decrement());

Mechanism

import args from this

Add this as an allowed token instead of just a string for the module name.

The this value will hold an array of the arguments passed to the module as its default argument. If no arguments are passed, the default argument will be an empty array.

import * from "./module"(args)

When importing from a module (but not this), the programmer may elect to pass arguments to the module. The modules are given as an argument list as if calling a function after the name of the module.

If a module is imported multiple times with different arguments, then they are considered different modules. If a module is imported multiple times with the same arguments, then they are considered the same module.

Rationale

A lot of modules are functions that are a function that returns an object.

A module is also somewhat like a function in that it executes code and then returns its exports to those who invoked the module via import.

We can collapse indentation a bit and increases the static knowledge of codebases by letting modules take arguments.

Furthermore, if the module has circular dependencies, this lets the circular dependency resolution of ES6 modules work as intended alongside arguments.

Variants & Extensions

Structural Equality arguments checking

Because JavaScript only has referential equality, passing in an object or array will always give you a new module unless you get the object/array from some other module.

It may make sense to do structural equality checking for objects, arrays, regexps, and dates, but it would be something JS does not have access to do elsewhere, unless added elsewhere (which would be valuable in and of itself).

Allow destructuring in import statements.

import [arg0, arg1, ...restArgs] from this;

Pretty much its own can of worms. Could be useful but non-orthogonal if only constrained to the default argument for import this. Makes importing arguments a single line of code instead of having a second destructuring line.

Use with instead of function call syntax

import myCounter from "./Counter" with 10;

Constrains the argument to a single value, but looks prettier. Would definitely want deep equality checking since people are going to use objects more often with this syntax. e.g.

import foo from "./Foo" with {bar, baz};

Also gives a use to the with keyword in strict code.

Module keyword

Instead of import args from this do module (args...) { ... }.

Doesn't have to be the keyword module explicitly.

Would allow all the function argument binding rules to apply.

Would only be allowed as the first form on the page, not counting use pragmas.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment