fast-check icon indicating copy to clipboard operation
fast-check copied to clipboard

Arbitraries for Symbols

Open sluukkonen opened this issue 3 years ago • 2 comments

🚀 Feature Request

Symbol is one of the native data types in JavaScript, so it would be nice to have some arbitraries for them. It's easy enough to compose them with the existing primitives, but nevertheless, I think it would be nice to have them built-in to fast-check.

I'm thinking that two arbitraries would suffice. One for symbols created with the Symbol constructor and one for globals created with Symbol.for.

Similarly, it would be great if fc.anything() could create them (perhaps with a withSymbol option, similarly to BigInts, Maps and Sets).

Motivation

Right now, I'm writing property tests for an isEquals-type function, and having symbols wired to fc.anything() would make the code cleaner.

sluukkonen avatar Aug 23 '20 15:08 sluukkonen

Would definitely be a good idea!

I see at least 7 missing arbitraries or options:

  • one for unique symbols - one using Symbol()1
  • one for named symbols - one using Symbol.for()
  • support for symbol as keys for record
  • an option in anything to generate symbol
  • an option in dictionary to generate symbol as possible keys
  • an option in anything (or the same as above) to generate objects having symbol as possible keys
  • support for symbol as keys for record - https://github.com/dubzzz/fast-check/issues/240

1 If we use this one when talking about symbols as keys of objects we will never be able to recreate twice the same value. Maybe we should have a flag withUniqueSymbol too 🤔 Today with fc.dedup(fc.anything(), 2) we can create twice the same instance in terms of equality (not === but deeply equal). We would need to think about ways (if feasible) to achieve that with this arbitrary based on Symbol().

dubzzz avatar Aug 24 '20 07:08 dubzzz

One problem with generators for symbols is that they are inherently leaky - generating a symbol consumes space irrecoverably

Having a very large set of symbols generated can bring v8 to its knees

A more severe example of this is when erlang quickcheck was new, they tried to offer a generator that'd make atoms, which are roughly analogous to symbols. The thing is, breaking the one million line will halt an erlang VM, so, they had to take that back out, and start only generating existing ones rather than novel ones

Another is that a lot of Javascript's internals are implemented in terms of symbols now, so if you chose to iterate the global symbol registry, you'd end up firing prototype[@@toPrimitive], or species, or unscopables, which could break the test rig in action and invalidate other results silently, which would be bad.

The way around this would be to use local symbols and .getOwnPropertySymbols, but that would fail to catch things involving the global registry, which is a lot of what people use Symbol for, or to try to manually screen defined symbols, because I don't think vanilla has a way to separate Well Known Symbols from stuff the programmer made up

You can't really just make a list of @@unscopables and so on because the browsers are free to make their own, and do, and there's no guaranteed namespace or naming pattern, nor a method for distinguishing their nativity

StoneCypher avatar Dec 20 '20 19:12 StoneCypher

As a symbol generator does not seem that simple to make re-usable, let's close that ticket for now. It's still feasible on user-land to create such generator if needed and tailor it for the exact needs of the user.

My current idea with the feature was to generate symbols using Symbol(label) and Symbol.for(label) but they might not be that useful for most users. Most users might one to have very precise symbols and not fully random ones.

dubzzz avatar Sep 04 '23 23:09 dubzzz