Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to Symbols #317

Open
Avaq opened this issue Nov 16, 2019 · 2 comments
Open

Switch to Symbols #317

Avaq opened this issue Nov 16, 2019 · 2 comments

Comments

@Avaq
Copy link
Contributor

Avaq commented Nov 16, 2019

I have suggested this approach in the past (#315 (comment)), but after a recent realization, I think it deserves its own discussion.


The reason for switching to symbols are as follows:

  1. Two conflicting versions of Fantasy Land would automatically not try to interact with each other, because they would have two different symbols. More on this thought (before Symbols existed) here: Reference to a canonical module in values static-land#45 (comment).

  2. Symbols can be used to mutate prototypes of built-ins without stepping on anyone's toes. It seems to me that this is how first class protocols are implemented under-the-hood, and so by using symbols, we are taking a first step towards First-Class Protocols #291. It would allow a library to extend built-in prototypes with Fantasy-Land methods, rather than implementing support for built-in types at the dispatcher level.

  3. Last but not least, my recent realization: Using strings means that code which uses Fantasy Land is vulnerable to the exact same problem that Promise-based code is vulnerable to. I have created a write-up about this vulnerability here: Add "then" to strings which may be used elsewhere minimaxir/big-list-of-naughty-strings#159.

    In summary, code that creates StrMaps like { [userInput]: AnyFunction } and passes it to a fantasy-land compliant map implementation such as Ramda's map or Sanctuary's map with the intent of mapping over the values, will behave differently if the user passes fantasy-land/map as input. The same goes of course for all other algebras and all implementations of those that might get mixed with user-input.

    Using symbols would remove this vulnerability, as users have no way to pass symbols into a typical application from the outside.

Reasons I see against using symbols:

  1. Managing compatibility between libraries might become more difficult. Let's say Fantasy Land 5.0.0 adopts symbols. Now ADT library authors such as myself would have to add fantasy-land as a dependency in order to use the "correct" symbols for interoperability with a dispatcher lib. Then later when Fantasy Land 5.1.0 comes out with some new algebra, the dispatcher library might upgrade to it whilst the ADT library doesn't.

    At this point it might happen that a package manager such as npm installs two distinct versions of Fantasy Land in a project which uses both the dispatcher lib and the ADT lib. Those two distinct installations of Fantasy Land will provide two distinct symbols, and as such, the dispatcher lib will no longer be able to interact with the ADT. This can be avoided in some ways (having Fantasy Land as a peer dependency, or using some automated deduplication strategies), but either way it's not as easy as it was with Strings.

  2. It might take some time before symbols see full adoption. It's a hard-reset for the Fantasy Land community, and for some transition period, libraries would probably need to provide both strings and symbols.


Symbol.for

Instead of using the distinct Symbol constructor, Fantasy Land could use Symbol.for('fantasy-land/map'). Library authors would not need to rely on a fantasy-land package in order to provide interoperability. This would remove benefit 1 and problem 1 from the pros and cons listed above, leaving us with benefit 2 and 3.

@bergus
Copy link
Contributor

bergus commented Nov 16, 2019

I'm on board with this :-) I would advocate for using Symbol.for. If two versions of the spec would conflict, they should simply choose different symbols (for that item, and keep the compatible ones).

As you say, this has been discussed before, not only once but many times: #92 #122 #146 (and more, see links from there). It seems in 2016 the ecosystem was not yet ready for symbols, I believe now it should be.

@davidchambers
Copy link
Member

We should also consider #315, which I hope to return to during the upcoming holiday period. All instances are defined on the type representative, reducing to one the number of “unique” property names that must be specified. Does that have any bearing on this string versus symbol discussion?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants