hughfdjackson / immutable

neatly packages immutable equivalents to JavaScript's Objects and Arrays.
101 stars 7 forks source link

Rename methods that return a new datastructure to not imply mutation #20

Closed hughfdjackson closed 11 years ago

hughfdjackson commented 11 years ago

As a user, I want it to be clear that my code is intended for use with/is using immutable datastructures. I also don't want to have external code pass me a mutable object which my code will subsequently treat as immutable because it ducktypes identically.

I would also like these method names to be terse enough to be used consistently throughout a codebase.

Acceptance:

Suggestions:

var o = im.object({ x: 3 })

// adding
var o2 = o.merge({ y: 3 })
var o2 = o.union({ y: 3 })
var o2 = o.plus({ y: 3 })
var o2 = o.assoc({ y: 3 })
var o2 = o.mix({ y: 3 })
var o2 = o.add({ y: 3 })
var o2 = o.fuse({ y: 3 })

// removing
var o3 = o2.minus('y')
var o3 = o2.omit('y')
var o3 = o2.dissoc('y')
var o3 = o2.without('y')
var o3 = o2.sub('y')
jkroso commented 11 years ago

for adding the only one I like is assoc since all the others kind of imply the method could be doing something more clever. eg. {a:1}.plus({a:2}) could be expected to return either {a:3} or {a:2}.

I feel the same about the removing methods so I think dissoc is best

hughfdjackson commented 11 years ago

My personal thoughts on this are:

Adding

Reasons for rejecting the others:

Removing

+1 omit or without

jkroso commented 11 years ago

actually with/without could be good too

hughfdjackson commented 11 years ago

@jkroso: I love assoc/dissoc, but I'm worried that it won't hold water with the wider market, which is half the battle with a slightly non-idiomatic lib like this, i think.

hughfdjackson commented 11 years ago

also, with/without would be fantastic, except that with cannot be used with dot syntax in es3 environments. Thats why it was missed off the original list, sadly

jkroso commented 11 years ago

true merge is typicaly a mutating function though

hughfdjackson commented 11 years ago

There's the rub, i guess; to me it sounds less mutating than most verbs, but I could be alone in that.

jkroso commented 11 years ago

its not a bad name. can always add with/without aliases for people who don't care about es3. I usually don't

jkroso commented 11 years ago

omit reads like emit so probably not a good option.

hughfdjackson commented 11 years ago

that's a consideration; but it is a terse and accurate discription; without suffers a little on the length side of things. mmm APIs; how complex they are - and yet how important.

RE: with/without for ES5ers, that's quite tempting. It is annoying to attempt to extend compatibility backwards and realise that you have to do a project-wide search and replace for an identifierName though

hughfdjackson commented 11 years ago

A late-comer option: include/exclude

jkroso commented 11 years ago

hmm... lets vote. +1 assoc/dissoc from me. I think its worth the new language

hughfdjackson commented 11 years ago

a slightly unsure +1 assoc/dissoc from me too. ;)

robotlolita commented 11 years ago

I really like merge/without.

Though I still believe that union/disjunction describes the process perfectly, the latter isn't actually a nice API name though.

You can always conj/disj though ;3

jkroso commented 11 years ago

union is from set theory. to me it would suggest {a:1}.union({a:2}) // => {}

jkroso commented 11 years ago

my bad I was thinking of intersection but still union is not an obvious name

hughfdjackson commented 11 years ago

I think that neatly goes to show why union might be a barrier to adoption ;)

robotlolita commented 11 years ago

@jkroso Well, Objects are basically Set (String, a) data structures, so set theory concepts fit neatly. Might not be obvious what to expect if you don't know or don't remember set theory, though =/

hughfdjackson commented 11 years ago

@killdream conj looks like a concat/push/cons op to me - i.e. adding something sequential, not associating w/ an associative array

jkroso commented 11 years ago

@killdream the problem though is what is the set. the key value pairs, the keys, or the values.

robotlolita commented 11 years ago

@hughfdjackson it does everything in clojure. The name is basically combine, but the semantics of this combination depend on the data structure they're applied to.

hughfdjackson commented 11 years ago

@killdream us not being in clojure is almost exactly the crux of the debate ;) what would be clear en mass in javascript, and not a barrier to picking up? my hunch is 'not conj'

hughfdjackson commented 11 years ago

From @mcameron: haz/haznot, chain/unchain. To my mind, these look like presence tests and something related to method chains respectively.

joeloverton commented 11 years ago

I am fond of 'without' - I think you need to find an opposite of that which isn't 'with'. It might be a present participle you're after. 'without' is a preposition, and many participles can also be used as prepositions: e.g. 'given', 'provided', 'assuming', 'barring', or perhaps even 'setting', 'having'...

I think there's something about using present participles which implies non-mutation, so I reckon that's where you need to look for your answer.

joeloverton commented 11 years ago

Again, the fact that omit reads like emit could be solved by using 'omitting', which to me signifies an absence of mutation

robotlolita commented 11 years ago

I like omitting, but I prefer without. Which reminds me: nouns are much more declarative and pure-looking than verbs. People are used to verbs for actions and things that create effects somewhere, whereas nouns are how you describe computations. e.g.: 2 plus 3, rather than add 3 to 2.

hughfdjackson commented 11 years ago

@joeloverton One of the issues that I didn't throw in the ticket above initially (which I have now) is the need to balance the non-mutation sounding-ness of the method name with something terse enough to use all the time; I'm hoping that immutable will make immutable-by-default a pleasure to use. I think there's a significant difference between:

var o = im.object({}).set({ x: 3 })
var o2 = o.set({ y: 3 })

and

var o = im.object({}).setting{ x: 3 })
var o2 = o.setting({ y: 3 })

(ignoring the entirely contrived example for a mo; i hope :D).

Looking at my own code, adding is far more common than removal, so a longer method name for removal may be a viable option.

You're right that that tense does sound more immutable, though.

hughfdjackson commented 11 years ago

After a few days of pondering (plus riding boris bikes), I've resolved to go for assoc/dissoc.

I can't find a word that satisfies @joeloverton's suggestion of opposite of without that isn't with in any elegant way; nor any suitable noun, as per @killdream's suggestion.

Assoc/dissoc have the following advantages:

Disadvantages:

Migration: