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

Public variables on namespaces #1848

Closed
Soviut opened this issue Feb 4, 2014 · 95 comments
Closed

Public variables on namespaces #1848

Soviut opened this issue Feb 4, 2014 · 95 comments

Comments

@Soviut
Copy link

Soviut commented Feb 4, 2014

I realize this isn't a new topic but it I think the time has come to consider implementing public variables on namespaces. Many prominent libraries for LESS (bootstrap, hat, etc.), have emerged, each with dozens of configuration variables which could very well overlap and conflict with each other.

Currently, namespaces support private variables, the only way to get at them is via mixins within the namespace and those mixins can then be used externally; Sort of like a closure:

#ns {
    @size: 10px;
    .box() {
        width: @size;
        height: @size;
    }
}

.icon {
    #ns > .box();
}

Which yields:

.icon {
    width: 10px;
    height: 10px;
}

However, I think it would be very handy to do the following:

#ns {
    @size: 10px;
}

.icon {
    width: #ns > @size;
    height: #ns > @size;
}

As well as update those variables within the namespace:

#ns > @size: 20px;
@goto-bus-stop
Copy link

👍

@lukeapage
Copy link
Member

yes. I am not against them.

We could implement them as they used to be implemented when they were part of less. see #6 !!

@lukeapage
Copy link
Member

though I'd like to see some thought about the syntax. possibly only allowing on #id not .id.

just throwing out some other syntaxes

@#ns>size // could work interpolated e.g. 
@{#ns>size}
#ns > @size
#ns>@size
#ns['size']
#ns[size]
@#ns[size]
#ns[@size]

@goto-bus-stop
Copy link

@{#ns>size} seems to make the most sense to me. Since it kinda has to work with interpolation, using the existing @{} would be the logical way to go… Perhaps @{#ns[size]} or similar could work too but it's not very pretty. (e; actually it's not even that bad.) #ns[@size] is pretty but it's hard to interpolate (.grid-#ns[@grid-size])

@lukeapage
Copy link
Member

yes to b clear I'd suggest the first 2 depending on whether it was an interpolated format or not (e.g.

.grid-@{#ns>size} {
  @width: @#ns>size;
}

the grammer being
@# recognised as a special case and extracting from # until > as a 'namespace' followed by the variable name.

@matthew-dean
Copy link
Member

+1 to @{#ns>size}. Makes sense.

@width: @#ns>size looks potentially more problematic, since you're assuming no white space. I think @{ #ns > size } would be perfectly legal, and more readable, but suddenly gets weird here:

@width: @#ns  >  size;

Especially during interpolation:

.myselector .parent@#ns > childVar > .childEl

@Soviut
Copy link
Author

Soviut commented Feb 4, 2014

The idea of prefixing the namespace with an @ symbol when dealing with a variable seems very strange to me. I personally think the following makes the most sense.

@width: #ns > @size;

You're referencing the namespace with # then using the > accessor to access the @size variable. Without the @ next to the variable I worry that the syntax gets confusing since it starts looking like an element selector.

@lukeapage
Copy link
Member

The idea of prefixing the namespace with an @ symbol when dealing with a variable seems very strange to me. I personally think the following makes the most sense.

I agree but this means it doesn't work in interpolated cases unless you have 2 differing syntaxes.

I don't like @{#ns>size} everywhere because it puts curly brackets in even more places :(

@matthew-dean
Copy link
Member

I don't think it necessarily puts @{} where they wouldn't be already. I actually think both of these could co-exist:

@width: #ns > @size;
@width: @{#ns>size};

The first, like @Soviut says, reads as "within the namespace #ns, reference the @SiZe variable" (and would be semantically in tune with namespaced mixins). The second reads as "within a variable context, reference size from the #ns namespace" (and would be semantically in tune with interpolation).

However, I still feel like @width: #ns > @size may only work because it's written without any surrounding functions or other value data. Compare:

.myElement {
   #gradient > .horizontal(darken(#ns > @color, 10%), #ns > @color);
}
.myElement {
   #gradient > .horizontal(darken(@{#ns > color}, 10%), @{#ns > color});
}

Hmm... it's actually hard to say which feels better. But... much as I've said on other issues, it might still suggest both could be correct? (To summarize, I believe @{} and @ references for vars should be more interchangeable. We already have two syntaxes to reference vars depending on placement, so why not two ways to reference a namespaced var?)

@Soviut
Copy link
Author

Soviut commented Feb 4, 2014

Keep in mind that we should be able to set/override variables within namespaces so we need the syntax to work with that as well.

#ns > @size: 20px;

@matthew-dean
Copy link
Member

Keep in mind that we should be able to set/override variables within namespaces so we need the syntax to work with that as well.

Agreed. Otherwise libraries would wrap vars in namespaces, but you wouldn't be able to "configure" the library.

@seven-phases-max
Copy link
Member

(crosslinking the topic where this feature and the syntax emerged before: #1357, just for reference).

@seven-phases-max
Copy link
Member

Just a thought on #ns > @var vs. @#ns > var

... but this means it doesn't work in interpolated cases unless you have 2 differing syntaxes.

We may to not allow to use that in a selector interpolation at all. Just the same way as we don't allow any functions or arithmetic (or anything else except a simple variable) to be there. After all one can always write:

@var: #ns > @size;
.grid-@{var} {
    // ...
}

Yep, a bit restrictive and makes the selector interpolation case verbose, but if it makes the syntax less confusing in other situations... why not?

@matthew-dean
Copy link
Member

I just had this come up on a project, where I really really needed to namespace my variables, but also wanted to expose them. My solution:

// core library
#namespace {
  .vars() {
    @base-color: red;
  }
}

// custom project
#namespace {
  .vars() {
    @base-color: blue;
  }
}

// core library implementation
.box {
  #namespace > .vars();
  color: @base-color;
}

I'm assuming that one can, by design, do something like the above? The downside, of course, is needing to "import" colors into every scope that needs them available. But, basically, by "setting" variables via a mixin, then calling the mixin name in a scope, it has the desired effect.

Which leads me to the idea that for setting variables, because of inheritance, it doesn't need a special "setting" format. It can be:

#ns {
  @var: this;
}

// later, override
#ns {
  @var: that;
}

//referencing:
.foo {
  bar: #ns > @var;  // only referencing via >, not setting, just like regular namespacing
}

@matthew-dean
Copy link
Member

@seven-phases-max I think your idea is valid, or we could just opt to not switchup the syntax within the interpolation syntax.

#ns {
  @var: red;
}
.@{#ns > @var} {
  foo: bar;
}
.foo {
  bar: #ns > @var;
}

On the one hand, it's possibly one extra @, but at least everyone would know what the heck you were referring to.

@seven-phases-max
Copy link
Member

.box {
  #namespace > .vars();
  color: @base-color;
}

I'm assuming that one can, by design, do something like the above?

I guess yes. I believe it was considered as something dangerous and unintended during -> 1.4.x move mostly because of various variable leaking issues emerged first and its general strangeness at those times. But now it's pretty much "standard" functionality and it's too late to prohibit this even if we'd want to.

@seven-phases-max
Copy link
Member

@matthew-dean

It can be:

#ns {
  @var: this;
}

// later, override
#ns {
  @var: that;
}

Don't forget that first of all the #ns is a a plain CSS ruleset and a mixin too. Making their scope "open" is too breaking change... I think I won't be mistaken to assume that out there they (and we) have a lot of code like:

#something {
    @tmp: 2 + 2px;
    width: @tmp;
}

#something {
    @tmp: 2 + 3px;
    height: @tmp;
}

In this context the second part of the propose, i.e. #ns > @size: 20px; makes me worry too. It's pretty much new concept of scope intrusion (by now we have nothing that can change the scope internals from outside unless it's explicitly intended/written by the "scope author" via mixin parameters or inheriting parent scope variables). I guess we need some extra care and further analysis of possible consequences for that part.

@matthew-dean
Copy link
Member

@seven-phases-max The scope wouldn't be open. It would still only live in the context of the local scope (sort of). I get what you're saying, but I would see namespaced overrides like this...

SCRAP THAT, AN IDEA JUST HAPPENED.

I had examples with >, but then it DID seem confusing, just as you pointed out. So then I started thinking about detached rulesets... So, detached rulesets, which just was merged in (I think) look like this:

@rules: {
  prop1: value1;
  prop2: value2;
}

I love that we now have detached rulesets. I was looking at those and marvelling at what we could do with them. At some point some time ago, looking at the new detached rulesets, I thought, "You know, it would be great if I could extract property values from the ruleset, or even use mixin guards against a specific property value. Maybe I'll suggest that as a feature request".

I just realized that the goals of name-spaced variables, and the idea of referencing properties of a ruleset can actually be the same goal.

@rules: {
  prop1: value1;
  prop2: value2;
}
#something {
  width: @rules[prop1];
}

(When I was thinking about a specific property of a set, it seemed similar to me as a specific attribute of an element, hence I went straight to [], the established CSS syntax.)

So, what I mean is: since detached rulesets already exist, we already have a kind of syntax to assign a set of property / values to a single variable. What's missing is property accessors. With them, we could also do:

.mymixin(@rules) when (@rules[prop1] = value1) { 
  // 
}

What's nice is that it feels a little cleaner in interpolation without dots or >.

.@{var[prop]} {
  this: "feels so much better";
}

For library overrides:

// Theoretical variables.less
@bootstrap: {
  base-color: red;
}
// My project:
@bootstrap[base-color]: blue;
// or, for multiple overrides, just redefine the entire variable, like you would with vars now:
@bootstrap: {
  base-color: blue;
}

What do you guys think of this?

EDIT: Note below that the "ruleset syntax for variables" idea should be attributed to @jonschlinkert, proposed in #1357.

@seven-phases-max
Copy link
Member

That's just "properies are variables!" feature. A "detached ruleset" is still a normal ruleset (just not explicitly named), i.e. if we can write @rules[prop1] then why we can't just #ns[prop1]?
(Note that I'm not against it in general, honestly I actually always wondered why properties were not made "readable" from the very beginning - But it's another big story... And stacking one advanced feature ("readable" properties) on top of another advanced feature ("detached rulesets") looks a bit confusing and overengineered. Though I see how "detached ruleset" can help to solve "open scope" problem - neat spot!).

@matthew-dean
Copy link
Member

Yep, I realize it's double-purposing, but that's exactly the point. The detached ruleset syntax already closely matches a name-spaced variable set suggested by others. Look at this syntax from @jonschlinkert for variables (the proposal he made in #1357).

@palette: {
    primary: #0000E0;
    info: #02d7e1;
    success: #02e10c;
}

This is the exact syntax for detached rulesets. In other words, by solving a problem elsewhere, we've already implemented part 1 of his proposal. Now, it's just a matter of implementing part 2: retrieval. The only difference is that I'm suggesting [] makes a bit more sense to me, since semantically it's a little like attributes, (more so than dots which are classes and Less mixins). But otherwise the approach is the same. I think Jon had the right idea, and I'm noting that we're already very close to that idea.

Accessing properties of other rulesets (non-detached, i.e. not assigned to a variable) is interesting, but I don't think it necessarily follows that we have to do that. Detached rulesets could be a special case.

@Soviut
Copy link
Author

Soviut commented Feb 18, 2014

Attribute accessors do seem to make a lot of sense. The syntax is potentially cleaner than the > notation as well.

@seven-phases-max
Copy link
Member

Another problem is that inside @ruleset they are not variables:

@palette: {
    primary: #0000E0;
    success: lighten(?primary?, 50%); 
}

In that sense more classic stuff seems to be a bit more easy:

#palette { // can be detached as well
    @primary: #0000E0;
    @success: lighten(@primary, 50%); 
}

.usage {
    color: #pallete[success];
}

I don't know how much it is contradictory with selector attributes though...

@matthew-dean
Copy link
Member

Another problem is that inside @ruleset they are not variables:

I feel like you may be creating problems that may not exist. For one, are variables supported in detached rulesets? On the off chance it is or we ever get there, what's wrong with this?

@palette: {
    @primary: #0000E0;
    success: lighten(@primary, 50%); 
}

Then, you could support derived properties:

@palette[@primary]: #330000; // updates both @primary and the derived "success" property

To me, you've made an argument FOR this syntax, since you could create calculated properties, which sounds awesome.

In your second example, the syntax is less graceful or intuitive for interpolated vars. (@{#palette[success]}?) The bigger problem to me, though, is we'd have two syntaxes that look very nearly identical, which sounds like a potential for lots of confusion.

@matthew-dean
Copy link
Member

So, yes, what I'm proposing is that you could use properties AS namespaced variables, but, because they are rulesets, you could ALSO use variables as variables in the ruleset, if we wanted to (or already) permit variables in the ruleset.

@palette: { 
    @primary: #0000E0;
    @success: lighten(@primary, 50%); 
}
.usage {
    color: @pallete[@success];
}

This, however, wouldn't be completely necessary if we don't currently evaluate variables in detached rulesets.

@lukeapage
Copy link
Member

So this was is very similar to the format that was in the original ruby less - read #6

"Setting" "constants" or overriding constants in a "namespace" is another matter. For me the biggest problem is that constants are constants.. changing the constants from one scope in another seems like a big ask for a compiler written around declarative statements.

The technical problem is that less evaluates in one pass and that constants can be introduced by a mixin call - if the contents of that mixin could be overridden at some point, is the value still a constant or does it start becoming a variable - e.g.

# pallette {
  color: red;
}
@normal-var: red;

.class {
  color: @normal-var;
  color2: #pallette[color];
  #palette[color]: green;
  @normal-var: blue;
}
.class2 {
  color: @normal-var;
  color2: #pallette[color];
}

So.. you would think (or I would think) that constants would work the same way.. but its hard to define

#pallette {
  @color: green; // or does this stay the original color?
}
.class {
  color: blue;
  color2: green; // assuming the later variable overrides 
}
.class2 {
  color: red;
  color2: green; // or was this overridden for that scope only so this should be red?
}

and I guess the use-case for setting constants is that without that it is just a grouping mechanism for variables. with setting it allows libraries to group and keep seperate their own constants.

an alternative mechanism for overriding a variable might be..

# pallette {
  @color: red;
}
.class {
  color: #pallette[color];
}
# palette { // must be at the root level
  @color: green;
}

and I guess I prefer that.

One reason I bring this up is that it effects what @matthew-dean is saying about detached rulesets - it would be pretty weird to only half override a detached ruleset assigned to a variable, like I did in the second example, where as it isn't weird to just look up the variable from the last matching namespace with that property in it.

@seven-phases-max
Copy link
Member

@matthew-dean

On the off chance it is or we ever get there, what's wrong with this?

@palette: {
    @primary: #0000E0;
    success: lighten(@primary, 50%); 
}

Nothing. My point is that "detached rulesets" should not be treated as something special. Notice that "detached rulesets" feature introduced no special syntax except @var(). The @var: {...} part of this feature just plain combo of old variable definition + unused-selector {...} statements (the new thing with the DT is only an ability to assign one to another and not the syntax itself, the fact that it has the same syntax as suggested by @jonschlinkert in #1357 is no more than just a coincidence). So I just can't see why @ruleset[property] is better then #ruleset[property] (they are equal for me, in both the property is a plain CSS property having no special meaning and the @ symbol of the first is just standard part of the ruleset variable name just like of any other @variable).

Now here is the problem: if we treat a detached ruleset as some kind of new special namespace (so that only @dtns[property] is valid but no #ns[property] or #ns[@variable] and so on) we almost don't solve the original problem at all.

  1. @ruleset[property] syntax is limited to one level only (so we can't access one dt-namespace nested in another (e.g. this is what supposed to be like #ns > #ns2 > @var etc.).
  2. Normal namespaces can contain both variables and mixins (and so can the detached ruleset) but currently we don't have syntax to directly call a mixin defined within detached ruleset. I.e. #ns > .mixin but no @dtns() > .mixin. So by allowing only @dtns[property] we force ourselves to put variables and mixins into different namespaces. E.g.:

#ns {
    @var: 1;
    .mixin() {
        property: @var;
    }
}

// can call mixin directly:
#ns.mixin();
// but can't access its @var (without prior #ns();)

@dtns: {
    property: 2; // ok, it's a variable for the the outer space but has no use here.
    @var: 3;
    .mixin() {
        property: @var;
    }
}

// can access its property (like variable)
... @dtns[property]
// but can't its @var
// and even if we allow @dtns[@var]
// we still can't access mixin directly:
@ns ? .mixin();

See now? So that's my point: with @dtns[property] syntax we only introduce a new kind of namespace that has its own limitations and solve no problems of the existing namespaces. The fact that the @dtns[property] syntax looks more graceful than #ns[property] or #ns[@variable] does not help too much.
(And if we allow thing like @dtns[@variable] this automatically cancels the argument that #ns[@variable] is less graceful to interpolation).

For one, are variables supported in detached rulesets?

Yes, everything that can be used in a standard ruleset can be used in a detached ruleset (because the dt-ruleset is a standard ruleset too except its "name"). So this code is currently valid (will be in 1.7.0):

@ruleset: {

    @variable: 1;
    property:  2;

    #selector {
        @variable: 3;
        property:  4;
    }

    .mixin(@v) {
        // ...
    }

    .some-mixin-call();

    @another-detached-ruleset: {
        @variable: 5;
        property:  6;
        // and everything of above is valid here too
        // yet again because this is just plain old Less ruleset
    };

    // etc.
};

// .....

.some-mixin-call() {}
.usage {@ruleset();}

So no, I'm not against syntax, I'm against treating the DR feature as a yet another new special kind of namespace (so that instead of one namespace abstraction with problems we'll have two namespace abstractions with problems :)

@SomMeri
Copy link
Member

SomMeri commented Feb 19, 2014

My favourite syntax for reading variables from namespaces is:

  • @width: #ns > @size;

It is simple and seems to me to be the most intuitive, it is almost the same as calling mixins. I do not like @{#ns > variable} much, because we are not interpolating anything here and I do not see much advantage in additional {} in it.

The #ns > @size would also make it easy to extend the syntax to detached rulesets, if we decide so later on:

@detached: {
  @variable: value;
}

@space {
  property: @detached > @variable;
}

or even chain them for much longer:

@detached: {
  #namespace {
    @variable: value;
  }
}

@space {
  property: @detached > #namespace > @variable;
}

@SomMeri
Copy link
Member

SomMeri commented Feb 19, 2014

The biggest use case for namespace variable modification seems to be library configuration.

Going wild with detached rulesets, it would be possible to keep less as declarative language, variables as constants and have library configuration too:

// library
#library(@base-color: green; @base-size: 3) { //default values
  .mixin() {
    color: @base-color;
    size: @base-size;
  }
}

//custom project
@library: { #library(red); } //initialize library, use default size 

div {
  @library > .mixin(); // using mixins and everything from the library
}

The advantage is that then it would be possible to have two "copies" of the same library initialized with two different arguments:

// library as before
#library(@base-color: green; @base-size: 3) { //default values
  .mixin() {
    color: @base-color;
    size: @base-size;
  }
}

//custom project
@library-glowing: { #library(red); } //initialize library, use default size 
@library-gentle: { #library(blue); } //initialize library, use default size 

.section-with-errors div {
  @library-glowing > .mixin();
}

.section-with-stuff div {
  @library-gentle > .mixin();
}

Other then that, i like the the trick shown in this comment, it feels to be "lessy". If it would be combined with variables reading, then it would be possible to do following:

// library
.namespaceConfiguration() {
  @base-color: 1;
}

#namespace {
  .namespaceConfiguration();
  color: @base-color;
}

// core library implementation
.box {
  #namespace >  @base-color;
}

// custom project
.namespaceConfiguration() {
  @base-color: 2;
}

@calvinjuarez
Copy link
Member

What if we extend @{} to allow accessing namespaced variables (e.g. @{#ns var}) and then propose ${} as just the property lookup (e.g. ${#ns prop})? That would mean that we could implement variable accessing without worry of any added ambiguity. A nice side-effect would be that variables will always be accessed with @, which would keep them conceptually distinct from properties.

@matthew-dean
Copy link
Member

@calvinjuarez - You, my friend, are a fucking genius.

You're right, that would effectively make @ = variables, and $ = properties, and they would both match their reduced (non-namespaced) forms of @var and $prop. That would simplify the whole concept tremendously, since we're not adding a "syntax for namespacing", we would just be adding namespacing to existing syntax (although, technically, prop accessing is not added yet).

You win the Internets today. I love this idea.

@calvinjuarez
Copy link
Member

Well, this thread has seen essentially that suggestion before. :P #fullCircle I'll update the gist.

@seven-phases-max
Copy link
Member

@{#ns var}
${#ns prop}

Ok, but what would be a syntax for accessing/defining just selector then? (E.g. @var: ?{#ns div};).

@matthew-dean
Copy link
Member

@seven-phases-max I think that's a separate issue. To quote myself:

I think I probably said somewhere in this thread that perhaps we could solve both [accessing values and selectors], but I think we can keep it simple by having ${} return values, and not references. So at this point I would agree in keeping it simple and not try to solve selector / mixin assignment to variables. That way we won't have any ambiguity, and we won't need to be restrictive about it.

I think @lukeapage had a good comment about not trying to be over-clever with syntax to the point of ambiguity. So if accessing just selector is needed (and I'm not convinced it is), that should be tracked as a separate issue with its own solution.

@matthew-dean
Copy link
Member

Well, this thread has seen essentially that suggestion before

Ha, yes, true. I know Luke had suggested that very thing with variables, but then properties got in and confused things. That is, we started to debate if @{} would access vars and properties, which didn't really make sense either. Later, separately, we brought in the idea of $ for properties, and then that made it into this thread, which was important in order to figure out the balance between the two, but then I was suggesting it for more than one thing, including vars, which seemed a little muddy. It was the reverse problem we had in 2014.

So yes, I didn't mean to suggest it was entirely your idea--there are a lot of brilliant people here--just that you simplified and clarified 3 different threads made over a year with one simple suggestion. In the end, you brought it all together, so I'm giving you credit for that. :-)

@seven-phases-max Just so that I don't totally discard your question, I think at this point I would lean towards selector() over $() (or ${}) for selector references for the sake of clarity.

@seven-phases-max
Copy link
Member

So if accessing just selector is needed (and I'm not convinced it is), that should be tracked as a separate issue with its own solution.

Yes, but if you take $ symbol solely for a property we'll have to invent another one for selectors too... Hence what I'm concerned of: so far $ was also mentioned as a solution syntax for selectors too and it's not quite clear which one is actually in favour. Hence was my question, reserving some syntax for a feature w/o taking into account other features that pretend for exactly the same syntax is a bit...

Technically, originally for the selector stuff, the sketching syntax proposal was something like $(#ns > div) (i.e. function-like call parens), so there's still room for both, but having:

@a: ${#ns > something}; // `something` is a property
@b: $(#ns > something); // `something` is a tag selector

is exactly what goes against those things you quoted above.

@matthew-dean
Copy link
Member

Right. It would go against what I quoted. So I'm saying I'm against it. That is, I would be against $() for selectors, because it would sit too close to ${}.

And, I'm saying assigning selectors to variables seems like much less of a problem. I'm not sure we need it. So the potential future conflict against a desire to write $() seems like a non-issue at this point. I think it's a good direction to not mix returning references and returning values within the same syntax.

@seven-phases-max
Copy link
Member

I'm not sure we need it.

So you mean you don't need a hypothetical each to invoke an arbitrary parametric mixin as its callback? ;)

@matthew-dean
Copy link
Member

Touché. Not necessarily. I think, in that example, the assignment to a variable was just to allow the variable to be passed to the each(), but that's not a requirement. For instance, we don't require :extend() to surround the selector portion with another selector designation before the keyword. In other words, we didn't require:

:extend(selector(#ns > something) all);

Another way to put it, if we have a core function in which we're inputting a selector, we should find a way to pass that selector without specially wrapping it or assigning it to a variable, just for the purpose of passing it into the function. If we do, it's just extra syntax that we've forced ourselves to create.

Yes, the outcome of this issue may shift a few of those other pending issues, but I think that's okay. I think this is the more valuable one to get right.

@calvinjuarez
Copy link
Member

I don't like $() for selector parsing. It very plainly resembles the jQuery convention, which would be fine, except that jQuery's $() works very differently to how (I understand) the selector function is meant to. What Less needs (and what #1421 is about) is a way to assign a CSS selector to a variable, and not to access an existing entity. jQuery's $('.selector'), though, is all about getting an existing entity. So, if you've been in a jQuery file all day, and then you come across this, you're gonna have a conceptual collision.

.selector {
  min-height: 1px;
  width: 100%;
}

@var: $(.selector);

As such, to my mind, the similarity to jQuery is a big reason not to use $() for selector parsing, and instead to define something distinct and fresh.

And speaking of distinct and fresh, I think the only symbols as "safe" as $ would be ^ or |. Both are also only used in CSS attribute selectors and don't (afaik) have a specific meaning in Less yet. Though if not $, I think parse-selector() or a whole other syntax would be better.

@matthew-dean
Copy link
Member

@calvinjuarez Agree for the same reasons. It looks like jQuery, but isn't. But, as I said, my recommendation is that we move that discussion to issue... #2270 ? And narrow the scope of this issue back to accessing within namespaces.

@calvinjuarez
Copy link
Member

👍 sounds good. Sorry about that.

@matthew-dean
Copy link
Member

No need to be sorry. Hey, if at the end, we get something cool done, it's all good. 😄

@rjgotten
Copy link
Contributor

@calvinjuarez
And speaking of distinct and fresh, I think the only symbols as "safe" as $ would be ^ or |.

What about &?

It's already being used as a template token to indicate 'previous selector set' when used inside a selector declaration. Might as well make that go full-circle and create a &(<selector>) function to capture a (list of) selector(s) into a (list of) string(s)...

@matthew-dean
Copy link
Member

@rjgotten Can you move selector access discussion to #2270 or #2481 so that we can finalize this one (namespaced vars)? I think this is otherwise pretty close to ready.

@calvinjuarez
Copy link
Member

@matthew-dean I think #1328 #1421 would be the best place for the selector parsing discussion (or a new, consolidated issue).


For this thread, are there any objections to the following for namespaced variable accessing?

@{#ns var} // and `@{#ns > var}` (w/ `#ns@var` as sugar in the next major version)

Then this can be marked as "ready", and we can move the property access discussion (${#ns prop}) to #2433 (#76, #6).

@matthew-dean
Copy link
Member

No objections to those variants. I also think prepending @ to the var name inside the braces (as in @{#ns @var}) could be optional if it feels more logical to a particular developer. It doesn't change the meaning, so it seems nice as an option, in case they want to see the variable referenced as it was written within the namespace. But if there are objections to that form within this thread, I'm not attached to it. It was brought up at some point.

@chharvey
Copy link
Contributor

chharvey commented Aug 4, 2015

this feature would be very similar to maps in Sass. hopefully the syntax for retrieving a value will be better than map-get().

@matthew-dean
Copy link
Member

Despite this seeming close to final syntax, I think this syntax needs to be revisited, based on discussion in #2767 and less/less-meta#10.

But not a total revisiting. @seven-phases-max's arguments in this thread toward #ns[prop] and @dr[prop] as aligning under a single behavior make sense is we move towards aligning all the behavior of rulesets in terms of scoping.

That is, if you support DR variable access (which aligning ruleset behavior may allow), then @{@dr@var} starts to not make any sense.

And @lukeapage's concerns about mixins introducing constants within scope might be lessened if we make scoping rules a bit more robust.

In short, I would say this should be part of a larger syntax review in 3.0 (as part of the roadmap proposal) to make sure all these pieces together make sense.

@matthew-dean
Copy link
Member

As I mentioned in the comment above, this discussion got reset a bit because of changes that are part of some syntax and behavior clean-up discussions for 3.0. Because the discussion about syntax covers more than just this issue (but consistency with other 3.0 proposals), I'm going to close this issue in favor of the discussion here: less/less-meta#12.

It would be great if anyone involved in this discussion could give their 2 cents on that issue.

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

11 participants