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

[FEATURE property-brace-expansion-improvement] Potential improvement as per #4605 #4617

Merged

Conversation

gordonkristan
Copy link
Contributor

I love the property brace expansion introduced in 1.4, but on several occasions I've entered properties with an incorrect syntax. So when @zzarcon mentioned expanding the functionality, I took a stab at it.

Property brace expansion will now work properly with any number of braces in any location, provided that the braces are surrounded by periods and only contain a comma separated list of valid property names (no whitespace).

You can look at the code for examples, but here's the gist:

'foo.{bar,baz}.@each' => 'foo.bar.@each', 'foo.baz.@each'
'{foo,bar}.{spam,eggs}' => 'foo.spam', 'foo.eggs', 'bar.spam', 'bar.eggs'
'{foo}.bar.{baz}' => 'foo.bar.baz'

As far as the algorithm to do the expansion goes, I'm 100% positive that there's a more efficient way. But this way is fairly short and relatively easy to understand, which I think trumps efficiency in this case. However, I'd be glad to improve the algorithm (or anything else) if requested.

@zzarcon
Copy link

zzarcon commented Mar 28, 2014

Amazing man! this is exactly what I want, I think that with the new property brace expansion the dependent keys will be more declaratives and less verbose.

👍 for you!

@stefanpenner
Copy link
Member

@hjdivad you did the initial implementation of our current expansion can you +1/-1 ?

@stefanpenner
Copy link
Member

also this should be labeled [FEATURE <something related to the feature>] with the appropriate feature.json and feature.md additions.

@gordonkristan
Copy link
Contributor Author

How exactly would I put this behind a feature flag? It improves (replaces) existing stable functionality, so I can't disable it without disabling the old functionality too. Should I include both implementations and have it choose the correct one at runtime?

if (part.indexOf(',') >= 0) {
properties = duplicateAndReplace(properties, part.split(','), index);
}
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it not be simpler to splice new entries rather than duplicateAndReplace?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did the implementation rather quickly, just to test the waters. I'll go ahead and improve the implementation a bit and put it behind a feature flag.

@hjdivad
Copy link
Member

hjdivad commented Apr 2, 2014

@gordonkristan yeah exactly; if feature then newImpl else oldImpl.

I'm 👍 on the feature. I'm slightly confused about the implementation, but maybe there's some good reason why it can't just use splice?

@gordonkristan gordonkristan changed the title [Proposal] Possible improvement to property brace expansion as per #4605 [FEATURE property-brace-expansion-improvement] Potential improvement as per #4605 Apr 2, 2014
@gordonkristan
Copy link
Contributor Author

I updated the code to put it behind feature flags. However, I'm a little confused on how I could use splice to achieve what I want. Right now, here's my logic:

The parts array that comes from splitting the original string could look something like this:

['a.', 'b,c', '.d.', 'e,f']

So when I'm iterating the parts, I get to the second element of the array. From that point, I need to duplicate the array because the property can't be properly formed until I expand the last element of the array as well. So I have no choice but to turn the above array into the following, and then continue iterating until I get to the last element which also needs expanding.

['a.', 'b', '.d.', 'e,f']
['a.', 'c', '.d.', 'e,f']

I could use splice on the original array, but I would still need to duplicate it at least once to get the second array.

So that's my reasoning for using the duplicateAndReplace method. (BTW, that process could easily be done using strings instead of arrays, but I found using arrays easier.) If I'm missing something obvious, just let me know. :)

@GetContented
Copy link

@gordonkristan

I think this is the intended algorithm, partially thought out, to give you the gist:

- say initialString = 'foo.{bar,baz,jo}.harry.{bit,bop}'
- set segments =  initialString.split('.') then delete '{' and '}' => ["foo", "bar,baz,jo", "harry", "bit,bop"]
- expandedItemsCollectorArray = []
- loop over segments as segment
  -- segmentItems = segment.split(',')
  -- duplicate the items in expandedItemsCollectorArray so there are segmentItems.count many copies of the entire set (or if there are none, just add them), otherwise:
  -- loop over segmentItems as segmentItem with index
    --- splice each segmentItem to the end of each expandedItemsCollectoarArray with a dot in front

And if you used a regexp or two, you could avoid all the splits.

@gordonkristan
Copy link
Contributor Author

@JulianLeviston I think that's pretty much what I'm doing, only I'm just replacing the item in the array rather than using splice. I'm looping over segments just as you do and I'm looping over segmentItems just as you do. So it's definitely got the same run complexity.

@GetContented
Copy link

Apologies! :) It seemed simpler to my brain for some reason hehe... nevermind then... :)

@hjdivad
Copy link
Member

hjdivad commented Apr 2, 2014

@gordonkristan ah good point about needing to do duplication either way. You are right, the simplification I was thinking about with splice is not correct. Your implementation seems fine to me.

@rwjblue
Copy link
Member

rwjblue commented Jul 13, 2014

@gordonkristan - Could you rebase?

@hjdivad - Am I understanding your last comment correctly as a +1?

@gordonkristan
Copy link
Contributor Author

I rebased, so I think it's ready to merge now.

deepEqual(expected.sort(), foundProperties.sort());
});

if (!IMPROVEMENT_ENABLED) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you have to explicitly write if (!Ember.FEATURES.isEnabled('property-brace-expansion-improvement')) { here, as otherwise this won't work with the defeatureify tool ...

cc @rjackson

stefanpenner added a commit that referenced this pull request Jul 13, 2014
[FEATURE property-brace-expansion-improvement] Potential improvement as per #4605
@stefanpenner stefanpenner merged commit b9fa1d1 into emberjs:master Jul 13, 2014
@tomdale
Copy link
Member

tomdale commented Aug 15, 2014

This was go'ed for 🚀 at the core team meeting. We would like to add some documentation to the guides that warns people about how easy it is to add a combinatorial explosion of dependencies.

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

Successfully merging this pull request may close these issues.

9 participants