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

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

Closed
hughfdjackson opened this issue Feb 28, 2013 · 28 comments
Closed

Comments

@hughfdjackson
Copy link
Owner

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:

  • Rename set/delete/remove to more intuitive versions.
  • Have these method names short enough to be used without a second thought (what exactly that means tbd).

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
Copy link

jkroso commented Feb 28, 2013

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
Copy link
Owner Author

My personal thoughts on this are:

Adding

  • 1 merge or mix

Reasons for rejecting the others:

  • add - part of the es6 Set API
  • union - too mathy to have wide appeal
  • plus - too strong an association of aggregating a single value; not adding to a set
  • assoc - not idiomatically javascripty - not sure non-lispers would get it
  • fuse - doesn't fit with most operators; too strong a verb

Removing

+1 omit or without

  • dissoc - same problem as assoc
  • minus/sub - same problem as plus

@jkroso
Copy link

jkroso commented Feb 28, 2013

actually with/without could be good too

@hughfdjackson
Copy link
Owner Author

@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
Copy link
Owner Author

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
Copy link

jkroso commented Feb 28, 2013

true merge is typicaly a mutating function though

@hughfdjackson
Copy link
Owner Author

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

@jkroso
Copy link

jkroso commented Feb 28, 2013

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

@jkroso
Copy link

jkroso commented Feb 28, 2013

omit reads like emit so probably not a good option.

@hughfdjackson
Copy link
Owner Author

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
Copy link
Owner Author

A late-comer option:
include/exclude

@jkroso
Copy link

jkroso commented Feb 28, 2013

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

@hughfdjackson
Copy link
Owner Author

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

@robotlolita
Copy link

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
Copy link

jkroso commented Mar 1, 2013

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

@jkroso
Copy link

jkroso commented Mar 1, 2013

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

@hughfdjackson
Copy link
Owner Author

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

@robotlolita
Copy link

@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
Copy link
Owner Author

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

@jkroso
Copy link

jkroso commented Mar 1, 2013

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

@robotlolita
Copy link

@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
Copy link
Owner Author

@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
Copy link
Owner Author

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

@joeloverton
Copy link

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
Copy link

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

@robotlolita
Copy link

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
Copy link
Owner Author

@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
Copy link
Owner Author

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:

  • They're alien to any common mutating words in js, or any other popular dynamic language that i know of;
  • assoc is short enough to be regularly used; dissoc similarly;
  • Already used in some languages, making the transitions easier;
  • No ducktyping clash with es6;
  • es3 compatible.

Disadvantages:

  • They may scare off some users with their alienyness - they're not idiomatic.
  • They don't inherently imply a lack of mutation; like union or with would.

Migration:

  • If it turns out there's a better wording in the future, a safe migration path can be provided by aliases that share the same API.

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

No branches or pull requests

4 participants