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

Please provide a way to merge lists #2467

Closed
rjgotten opened this issue Feb 23, 2015 · 10 comments
Closed

Please provide a way to merge lists #2467

rjgotten opened this issue Feb 23, 2015 · 10 comments

Comments

@rjgotten
Copy link
Contributor

While there are extract and length functions available, there is currently no function available to merge two lists together. This is not equivalent to simply listing two list-type variables in succession, which produces a list of lists. E.g.

.join-test( a b c ; 1 2 3 );
.join-test(@first, @second) {
  @joined : @first @second;
 length : length(@joined);
}

// OUTPUT:
length : 2;

Using a @param... rest parameter or the special @arguments variable and passing in two lists similarly produces (or atleast; seems to produce) a list of lists. These three cases are all behaving as expected, ofcourse: it should be possible to assemble lists of lists.

However, this leaves us without a way to concatenate lists or to concatenate elements to existing lists. As the LESS language heavily relies on tail recursion for iteration, I'd expect there to be a common supported pattern to aggregate head values into one joined list as is common with list manipulation in functional languages (with or without the use of list comprehension).

I'm thinking of something like the following:

.map(@list, @ruleset) {
  @n : length(@list);

  .iterator(0);
  .iterator(@i, @aggregator...) when (@i < @n) {
     @item : extract(@list, @i+1);

     // ( ... Insert some arbitrary logic mapping `@item into `@mapped` ... )
     @mapped : ??? 

     // Use a 'join' function to concatenate the mapped item to the existing list 
     // and iterate further.
     .iterator(@i+1, join(@aggregator, @mapped));
   }
  }

 .iterator(@i, @aggregator...) when (@i = @n) {
    // After having run the entire list, perform some action with the
    // mapped result, e.g. passing it off to a detached ruleset via
    // the calling scope's closure.
    & {
      @mapped_list : @aggregator;
      @ruleset();
    }
  }
}

There is a +: syntax available for merging CSS properties into lists as well. An alternative over a join function would be to widen that syntax to include variable support. Somehow that does not feel quite right though.

@seven-phases-max
Copy link
Member

Since the plugin subsystem is here and fully functional I wonder if we consider a stuff like this to be added instantly to the core anymore. A plugin providing these functions is rather easy to code, I mean of course this stuff can get into the core if considered to be very useful eventually, but shouldn't built-in-function-requests approach from now-on be something like "find some function useful/important? implement it yourself via plugin and let it preach on its own"? :)

@rjgotten
Copy link
Contributor Author

Good point.
Provided you want to go with a custom function, rather than a language operator, ofcourse.

@matthew-dean
Copy link
Member

@seven-phases-max I think that's a good point. It was @cloudhead's thought that 99% of what was needed was implemented by version 1.3, basically. We could start slimming down the core and actually move more pieces to plugins to keep something that executes quickly for more people, and let the other 1% pick and choose what pieces they need in their Less file. Express (and many other frameworks) went the route of separating pieces out of core once they had a reliable plugin system.

I think @rjgotten's recent pull request actually takes us a big leap forward in that direction (although I'd like to see browser support). (Also, ironic since this is your feature request, @rjgotten 😉 )

So something like this could eventually ship with Less, but not be loaded automatically by Less, as in:

@import (plugin) "less-lists";

So, I too would like things to move more in that direction, as it gives us more proofs-of-concept to make the plugin system more robust.

@rjgotten
Copy link
Contributor Author

(Also, ironic since this is your feature request, @rjgotten 😉 )

Yeah, I had the compiler's source open to study how to add custom functions to fullfill my own feature request. Then I had a 'what the hell; why not...' moment, going with the flow and rolling out a first proof-of-concept for that @import (plugin) feature.

And then I realized I didn't need this as an explicit feature request anymore. ^_^

@matthew-dean
Copy link
Member

So, should we close this, as it sounds like you'll take the plugin approach?

@seven-phases-max
Copy link
Member

I wonder if we need to add support as plugin label (or do we need another one?) so later its state would be more evident...

@matthew-dean
Copy link
Member

Or "Implement as plugin" (or something shorter?)

I like this. I think we can close open issues faster if we can be can simply ask: "Is this necessary for 99% of Less users". If not, it should be a plugin.

@matthew-dean
Copy link
Member

And I also like the idea of optional (but included) plugins. So, plugins maintained by core team.

@rjgotten
Copy link
Contributor Author

So, should we close this, as it sounds like you'll take the plugin approach?

Yes. Unless ofcourse you want to tack on a 'implement as plugin' label.

@seven-phases-max
Copy link
Member

OK, to not spin out all that bureaucracy, just closing.

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