Skip to content

Instantly share code, notes, and snippets.

@rjgotten
Last active August 29, 2015 14:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rjgotten/8cc02413f761c544c321 to your computer and use it in GitHub Desktop.
Save rjgotten/8cc02413f761c544c321 to your computer and use it in GitHub Desktop.
Using detached rulesets as lambda delegates without scoping issues; in reply to: https://gist.github.com/seven-phases-max/5280eacdf3d591f35163
// @mixin
// Loops over all items in the specified list and for each item executes
// a special `.\\` mixin declared by the specified ruleset. The ruleset
// and mixin combination is used to emulate a lambda function delegate.
// @param {List} list
// The list over which to loop.
// @param {Ruleset} lambda
// A ruleset that may define the `.\\` mixin that is used to process the
// individual list items. The mixin should correspond to the
// following signature:
// `.\\(@item, @index, @list) { }`
// where `@item` is the current list item; `@index` is the current
// list item's index and `@list` is the original list.
.foreach( @list, @lambda ) {
// Enclose all nested variables and mixins and do not allow them to
// leak back up to parent scope. This prevents problems with nested
// calls to the mixin.
& {
@n : length(@list);
// A catch-all declaration which ensures that the `.\\` mixin will
// always have a compatible signature available to be called, also
// when the `@lambda` ruleset didn't emit one.
.\\(@item, @index, @list ){}
.iterate(0);
.iterate(@index) when (@index < @n) {
@item : extract(@list, @index + 1);
// Comment items are skipped over.
// See the `.is-comment` declaration below.
.is-comment(@item);
// Need an isolated scope again for each individual item.
// A sequence of mixin calls would leak scope into another
// again.
& when not (@is-comment) {
@lambda();
// Call the special `.\\` mixin. The previously defined
// catch-all declaration ensures that this always succeeds.
.\\(@item, @index, @list );
}
.iterate(@index + 1);
}
// Works around a problem where comments are erroneously seen as
// members of list variables in older versions of the LESS
// compiler.
.is-comment(@item) {
@n : length(@item);
._();
._() when (@n > 1), (isstring(@item)) { @is-comment : false; }
._() when (default()) {
@single : replace( ~"@{item}", "\/\/.*", "");
@multi : replace( ~"@{item}", "\/\*.*", "");
.__();
.__() when (@single = ~""), (@multi = ~"") { @is-comment : true; }
.__() when (default()) { @is-comment : false; }
}
}
}
}
@import "foreach";
.mixin(@args...) {
.foreach(@args, { .\\(@arg, @index, @list) {
box-shadow+: @arg black;
}});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment