8

I am working on a set implementation in JavaScript currently. This should kind of simulate generics as known from Java or C#. I need a mutable version of that (allows for adding/removing set values) and an immutable one.

My constructor signature looks like this:

new GenericSet( 'number', [ 10, 20, 30 ] );

,

 // mutable set of mixed values (allows to add further values via "add")
 new MutableGenericSet( '*', [ 'foo', 42, {}, /./ ] );

or

// DataValues.prototype.equals will be used by the set for determining equality.
new GenericSet( { type: DataValue, valueComparison: 'equals' }, [ dv1, dv2, dv3 ] );

Just GenericSet or one set implementation per type?

Initially, my main purpose for this was to have sets of values of one type. E.g. a DataValuesSet which would only accept data Values. I could then define interfaces with functions that require a DataValuesSet instance. I could not use inheritance (and guess that would be bad anyhow), so I would use composition and have a GenericSet / MutableGenericSet instance internally.

An alternative approach would be to always take GenericSet and implement and use GenericSet.requireSetOfType( type ) which would throw an error if the set's type was not the required one. My concern with doing it this way is that my interface definitions would look less explicit.

Take

/**
 * @param DataValuesSet dataValues
 */
function printDataValues( dataValues ) {
    if( !( dataValues instanceof DataValuesSet ) ) {
        throw Error( '...' );
    }
    // ...
}

vs.

/**
 * @param GenericSet<DataValue>
 */
function printDataValues( dataValues ) {
    // Throws error if dataValues is not a set or it it is a set with values of wrong type.
    GenericSet.requireSetOfType( dataValues, DataValue );
    // ...
}

perhaps using @param GenericSet(DataValues) dataValues for documenting the second choice would be alright? Does anyone see any further implications with the second approach or are there any alternative suggestions? To me the, second one looks more intuitive and my concern with the first one is that I would just create more overhead with constructors while I can not see any clear advantage right now.

  • 6
    Why would generics matter in a language like JS which is weakly typed? – Yazad Apr 23 '15 at 23:28
  • 1
    This isn't possible in a language like JavaScript, which is both weakly and dynamically typed. Just use a typed JS variant like TypeScript. – gardenhead Mar 4 '17 at 2:10
3

I used to try solving these sorts of problems with JavaScript, which only served to complicate implementations of... Well... Anything. If you don't want to use something like Typescript, document what you expect. If people ignore your documentation they enter uncharted territory.

Don't try to force a round peg into a square hole that anyone can mold into a round hole. That's JavaScript. Embrace it. Don't fight it, baby. Document it, and just get back to writing code.

|improve this answer|||||
0

I would say that the first example is more readable. It does not imply that an error is thrown for the incorrectly typed set. It says that this function takes a DataValueSet. Being explicit in your code adds clarity.

GenericSet.requireSetOfType obfuscates the intent of the type check in the print function. It looks like it is checking for items with type DataValue.

|improve this answer|||||
  • Readability doesn't seem to be a strong enough argument for me here. You could make the documentation perfectly clear in either case by using DataValuesSet vs. GenericSet<DataValue>. Perhaps instead of GenericSet.requireSetOfType naming the function GenericSet.assertSetOfType or similar would be clearer indeed. – Daniel A. R. Werner Mar 4 '17 at 16:56
0

Given on the options, you present, I would prefer the first solution, because it is more readable than the second one. But, if you really want to do a JS-style solution, make a builder-function, whether the objects are from the same type or should be of mixed type (MakeStrictCollectionvs MakeMixedCollection). In the builder function, you could test, whether the type of every member of your given collection is from the same type or not and throw an error or return an object from each constructor, which has an additional type attribute "type":"strict" vs "type":"mixed".


Besides that:

You should take a look at Typescript, which may be, what you are looking for. And there is a package, which seem to suit your needs having generic collections.

|improve this answer|||||
  • -1 For MakeStrictCollection vs MakeMixedCollection. In regard to the code examples above, the printDataValues function would change to verify that the given object was instanceof StrictCollection and that its type was DataValues. GenericSet.requireSetOfType could be exactly that - hence, your suggestion seems to be merely an implementation detail to the GenericSet approach. – Daniel A. R. Werner Mar 4 '17 at 17:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.