immutable icon indicating copy to clipboard operation
immutable copied to clipboard

Add an isImmutable function

Open hughfdjackson opened this issue 11 years ago • 7 comments

It's possible that an .immutable flag would be contained in data. For instance:

var myRecord = {
  id: '3232',
  payload: { ... },
  immutable: true
}

As a user, I want to be sure whether or not this is an actual immutable object, or simply data.

Acceptance: An isImmutable predicate function is created, that confirms that: *get, has, assoc and dissoc methods are available;

  • the immutable flag is set.

hughfdjackson avatar Jun 16 '13 09:06 hughfdjackson

isImmutable is a problematic predicate, since primitives and frozen objects are immutable, just not the spawn of this library.

hughfdjackson avatar Jun 16 '13 10:06 hughfdjackson

A test case to make it obvious what the semantics of, for the pleasure of mr @ljharb

var a = require('assert')
var im = require('..')

describe('immutable', function(){

    describe('isImmutable', function(){
        it('should return true on immutable objects', function(){
            a.equal(im.isImmutable(im.object()), true)
            a.equal(im.isImmutable(im.array()), true)
        })

        it('should return false on data that has an immutable flag', function(){
            var fake = { immutable: true }
            a.equal(im.isImmutable(fake), false)
            a.equal(im.isImmutable(fake), false)
        })

        it('should require get, set, has, assoc and dissoc to be functions, along with an immutable flag', function(){
            var noop = function(){}
            var convincingFake = { immutable: true, get: noop, set: noop, assoc: noop, dissoc: noop, has: noop }

            a.equal(im.isImmutable(convincingFake), true)
        })

        it('should return false on all js primitives', function(){
            a.equal(im.isImmutable(null), false)
            a.equal(im.isImmutable(undefined), false)
            a.equal(im.isImmutable('foo'), false)
            a.equal(im.isImmutable(1), false)
            a.equal(im.isImmutable(true), false)
        })
    })
})

hughfdjackson avatar Jun 16 '13 17:06 hughfdjackson

Candidate names:

  • im.is
  • im.isImmutableCollection
  • im.instance
  • im.isInstance
  • im.spawns
  • im.produces

hughfdjackson avatar Jun 16 '13 19:06 hughfdjackson

Seems like im.is or im.isInstance makes the most sense to me. PS, in your test, the convincingFake should be returning false, right?

ljharb avatar Jun 17 '13 16:06 ljharb

@ljharb : convincingFake is meant to be convincing - in that it's an object that adheres to the interface required of an immutable object.

I want to make sure that two modules requiring immutable can interop with each other perfectly (and therefore can't use instanceof), so ducktyping on an 'interface' is the only way I could think of.

hughfdjackson avatar Jun 17 '13 16:06 hughfdjackson

ah, ok that makes perfect sense then

ljharb avatar Jun 17 '13 17:06 ljharb

Am going with isImmutableCollection, since that's the best description of the interface I can come up with.

Can always be aliased later :D

hughfdjackson avatar Jun 20 '13 20:06 hughfdjackson