Skip to content

Instantly share code, notes, and snippets.

@hjdivad
Created January 7, 2014 23:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hjdivad/8308522 to your computer and use it in GitHub Desktop.
Save hjdivad/8308522 to your computer and use it in GitHub Desktop.

Literals vs Properties in CPs

Something that's currently very annoying about CPs is that whether arguments are literals or properties is something that must be decided at macro-design time, rather than at macro-use time.

Consider for instance Ember.computed.equal. It would be nice to be able to use the same macro for creating CPs that compare against literal values as well as against properties.

This is quite easy to do with composable computed properties. As long as equal is changed to treat all arguments as properties, it simply takes an Ember.computed.literal cp to support literal values again.

Some examples:

var equal = Em.computed.equal,
      // "literal"
      l = Em.computed.literal;

equal(l('Jaime Lannister'), l('Jaime Lannister'));  // "Jaime Lannister" === "Jaime Lannister"
equal('name', l('Jaime Lannister'));  // get("name") === "Jaime Lannister"
equal('name', 'otherName');  // get("name") === get("otherName")

Backwards Compatibility

Unfortunately this approach creates a backwards compatibility problem as the semantics of the following code changes:

equal('name', 'Jaime Lannister');  // get("name") === get("Jaime Lannister")

Proposed Solution

We add Ember.computed.literal and Ember.computed.property, both under the feature flag composable-computed-properties, and the feature flag macros-default-to-properties.

The implementation would simply convert all non-CP arguments to literal CPs when macros-default-to-properties was disabled, provided that composable-computed-properties was enabled.

Upgrade Path

The upgrade path would be fairly simple. Users could enable macros-default-to-properties to discover parts of their code that needed changing. Then, they could write code like the following:

var equal = Em.computed.equal,
      l = Em.computed.literal;

// this would break with `macros-default-to-properties` disabled
equal('name', 'Jaime Lannister');
// so we change it to this
equal('name', l('Jaime Lannister');

Even with macros-default-to-properties disabled, users could gain the benefits of literal/property agnosticism with the following:

var equal = Em.computed.equal,
      p = Em.computed.property;

// This would still work with `macros-default-to-properties` disabled
equal('name', p('otherName'));
@hjdivad
Copy link
Author

hjdivad commented Jan 7, 2014

As pointed out by @rwjblue this should be managed by a feature flag rather than a flag in Ember.ENV.

@jamesarosen
Copy link

I will gladly ensure Ember-CPM follows this scheme once it's firmly established in an Ember release.

@hjdivad
Copy link
Author

hjdivad commented Jan 7, 2014

Updated to use a feature flag, and fixed a minor error in the last example.

@hjdivad
Copy link
Author

hjdivad commented Jan 7, 2014

It occurs to me that Em.computed.property is just another name for Em.computed.alias. The name is a bit nonobvious as the pair to Em.computed.literal. Anybody have thoughts on whether it's worth having Em.computed.property = Em.computed.alias?

@twokul
Copy link

twokul commented Jan 10, 2014

@hjdivad I think alias is enough. I agree that naming is somewhat non-obvious but I would say alias is fairly well-known thing and there's no need for property.

@wagenet
Copy link

wagenet commented Jan 10, 2014

What do you think of having the current behavior stay as is and specifying that a thing is bound instead? (This was suggested by @stefanpenner.)

@mike-north
Copy link

Really great stuff here guys. I've been working on composable computed property macros in the ember-cpm project, and as I get deeper and deeper in to writing more macros, the need for an Ember.literal has become more and more important.

So, here it is: https://github.com/TrueNorth/ember-literal

Code review is taking place here: https://github.com/jamesarosen/ember-cpm/pull/84 , but I'm thinking it's best to put Ember.literal in its own addon so that it can be leveraged by other projects without introducing the extra code of the other ember-cpm macros. I welcome any and all feedback, both in terms of where this code should most appropriately live, and in terms of the implementation/tests/use cases.

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