{"size": 1502, "ext": "js", "max_stars_repo_path": "src/02-reflection/16-symbols-extension.js", "max_stars_repo_name": "davefancher/js-metaprogramming", "max_stars_repo_stars_event_min_datetime": "2021-09-17T15:38:36.000Z", "max_stars_repo_stars_event_max_datetime": "2021-10-04T04:11:16.000Z", "max_issues_repo_path": "src/02-reflection/16-symbols-extension.js", "max_issues_repo_name": "davefancher/js-metaprogramming", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "src/02-reflection/16-symbols-extension.js", "max_forks_repo_name": "davefancher/js-metaprogramming", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": 2, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 26.8214285714, "max_line_length": 82, "alphanum_fraction": 0.5792276964}
// We can take advantage of symbols to provide our own extensibility points in our
// code. I've successfully used this technique to provide a rough equivalent of
// C#'s extension methods in JavaScript thus enabling incredibly useful features
// such as functional pipelining.

// Consider the following:

const attachSymbol =
    target =>
        fn => {
            const sym = Symbol();

            Reflect.defineProperty(
                target,
                sym,
                {
                    enumerable: false,
                    writable: false,
                    configurable: false,
                    value: fn
                }
            );

            return sym;
        };

// The attachSymbol function is a curried function that allows us to specify
// an object to extend with a function attached by a Symbol. Using this function
// generally looks like this:

const attachSymbolToObjectPrototype =
    attachSymbol(Object.prototype);

// We'd then attach a function like this:

const PIPE =
    attachSymbolToObjectPrototype(
        function (fn) {
            return fn(this);
        });

// We've now attached a Symbol we're calling PIPE to Object.prototype and are free
// to start using it.

({
    firstName: "Dave",
    lastName: "Fancher"
})
    [PIPE](o => ({
        fname: o.firstName,
        lname: o.lastName,
        time: new Date()
    }))
    [PIPE](o => `[${o.time.toISOString()}] ${o.lname}, ${o.fname}`)
    [PIPE](s => s.toUpperCase()); //?
