3 ms·
This is great feedback and a decision that I didn't take lightly. I ultimately decided that the mental cost of remembering a new API would outweigh the potenti
by leebyron 12y ago
This is great feedback and a decision that I didn't take lightly.
I ultimately decided that the mental cost of remembering a new API would outweigh the potential for accidental return value mis-management.
It's hard to make a decision like this sans-data, so I had to make a gut call. I'm really interested to hear feedback of issues encountered in-practice due to this. Of course, if I'm wrong about this (and there's always a reasonable chance I am!) then I would seriously consider changing the method names in a future major version.
- optymizer 12y agoHow about just adding aliases to existing methods, e.g. plus() and add()?
- ScottBurson 12y agoYou've clearly put a massive amount of work into this API, which I applaud. One trick I use in FSet that you might want to copy is default values for maps. This is particularly handy when the range type of the map is another collection: you can make the default value be the appropriate kind of empty collection, making it unnecessary for code that accesses the map to check for a null value. In Java, for example: FMap<Foo, FSet<Bar>> m = new FHashMap.withDefault(FHashSet.emptyMap()); // now I can do: for (Bar b : m.get(x)) ... // without worrying about whether 'm' contains an entry for 'x'.
- leebyron 12y agoGreat feature. Immutable.js supports something similar but at the access site: var m: Im.Map<string, Im.Set<string>> = Im.Map(); console.log(m.get('foo')); // maybe undefined console.log(m.get('foo', Im.Set())); // never undefined typescript (and soon, flow) checks that the second arg to .get() is a Value type. Flow has the concept of non-nullable types, which will eventually let us type the return value of `get(key: K): V?` differently from `get(key: K, otherwise: V): V`
- pimlottc 12y agoBut it's not the same API. There is a clear and plain specification on what each of those operations do, and the methods on these objects do not do them. I get what you're thinking about re-using what the programmer already knows but this only poisons the well by adding confusion to their existing knowledge. "Push adds a value to a list, oh wait, except it depends what type of list". It is much easier to remember that "foo always does 'a'" and "bar always does 'b'" rather than "foo does 'a' for some things but does 'b' for others", it's why we create functions and objects with different behaviors instead of nesting lots of if statements. New objects with new behaviors should use new language.
- jonahx 12y agoI think there are two opposing forces: the first, as you say, pushes us away from re-using the same names, because that can cause confusion; the second, however, pushes us to re-use existing knowledge through metaphor. This second force is ubiquitous in natural language, but common also in programming language where operators like "+" and "[]" are re-used in different contexts without practical ambiguity, and with the benefit of transfer of knowledge through metaphor. So I think your conclusion -- "New objects with new behaviors should use new language" -- is a bit too strong. On the other hand, in this particular case, the context is very close (array behavior) and the only difference is the immutablity, so confusion is a valid practical concern.
- pimlottc 12y agoI agree with you, context is important here. I think you can "borrow" some of the metaphor with different but suggestive names or patterns. But you shouldn't reuse a well-known name if your implementation is not faithful to the original associations. I really think specific language/word choice is under-appreciated in programming.