Skip to content

Recursive rulesets and extending rulesets #2211

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

Closed
matthew-dean opened this issue Sep 29, 2014 · 6 comments
Closed

Recursive rulesets and extending rulesets #2211

matthew-dean opened this issue Sep 29, 2014 · 6 comments

Comments

@matthew-dean
Copy link
Member

I've just started playing with rulesets, and I had this construction.

//core.less
#library {
  .nav() {
    @list: {
      display: block;
      other: property;
    };
  }
}

I wanted to try overriding the detached ruleset. So far, so good.

//overrides.less
#library {
  .nav() {
    @list: {
      display: inline;
    }
  }
}

Works awesome! BUT... then I thought, "Hmm, what if someone wanted to keep the existing ruleset and just extend it." I knew I couldn't use extend because there was no selector, so I tried this (even though I figured it wouldn't work).

//overrides.less
#library {
  .nav() {
    @list: {
     @list();
      display: inline;
    }
  }
}

At that point, the compiler locked up and was unrecoverable.

Now, granted, I wrote what looks like an obvious recursion loop. Clearly my fault. That said, I'm wondering if there's a way to detect / escape / throw an error when this occurs?

(Follow up ?'s: is there a way to 1. extend a ruleset, 2. reference a ruleset via a namespace like: #library > .nav() > @list(); rather than needing to write #library > .nav() { @list(); }. I didn't see this in the docs.)

@seven-phases-max
Copy link
Member

seven-phases-max commented Dec 12, 2014

Speaking of "override" vs. "cascade" stuff - I'd say to use DR for the first (it's a variable and as any plain variable it overrides) and mixin for the second (mixins cascade).
As for the recursion stuff - I actually would argue if it's a bug. While unconditional selfrecursion probably may be detected and stopped earlier (like it's done for mixins vs. rulesets of the same name - though personally I consider that trick quite artificial too) I don't see any reason why @list inside second definition should be resolved to the first definition (IMHO this would directly violate scope and lazy-loading rules).

In other words:

  • self = self; is not a declarative statement.
  • and function self() {self();} is always an infinite loop in either (declarative or imperative) approach.

@matthew-dean
Copy link
Member Author

As a follow up to this, this is how I solved extending vs. overriding.

//core.less
#library {
  .nav() {
    @list: {
      display: block;
      other: property;
    };
  }
}
// override
#library {
  .nav() {
    @list: {
      override: ruleset;
    };
  }
}
// extend
#library {
  .nav(list) {
    extend: value;
  }
}
// mixins.less
#library {
    .nav(@item) {
        #library.nav();
        @rules: @@item;
        @rules();
    }
}
// rendering
ul {
  #library.nav(list);
}

@matthew-dean
Copy link
Member Author

Even though I found a solution, I still think this should be left open, because the compiler should detect unrecoverable loops and throw an error, not lock up.

@seven-phases-max
Copy link
Member

That's quite neat pattern.
(Before DRs I used something like this, but the method there is obviously limited to a single override).

@matthew-dean
Copy link
Member Author

Thanks, it took me about 30 iterations to come up with that pattern. I'm building it into an OOLESS library, so it will have a production use at some point.

@seven-phases-max
Copy link
Member

Closing as expected behaviour.

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

No branches or pull requests

3 participants