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 Proposal: if() function #3019

Closed
matthew-dean opened this issue Jan 16, 2017 · 6 comments
Closed

Feature Proposal: if() function #3019

matthew-dean opened this issue Jan 16, 2017 · 6 comments

Comments

@matthew-dean
Copy link
Member

In the course of discussing changes to the contrast() function (which was changed and reverted, but will be changed again for 3.0 - see: #2754 (comment)), it came up that the legacy contrast function was really something of an if/then/else function, with the actual test condition simply one step removed from visibility.

That is, given: contrast(a, b, c, d) this is the test:

if luma(a) < d output b;
else output c;

Therefore, with contrast changing, the proposal on the table is to add, in the future, a generic if() function, with this signature:

if(condition, thenResult, elseResult)

  • condition has the same signature / format as a when condition in Less, with the exception that it cannot contain a comma as a logical OR, as that would denote an argument separator. However, Less now supports the or keyword and it is now the preferred format for a logical OR.

The above statement could then be replaced with something like the usage below:

@color1: #fefefe;
.box {
    color: if(luma(@color1) > 0.43, #333, #999);
}

@seven-phases-max noted that implementation is non-trivial (which I agree), but could be a very valuable addition to Less functions, since you could use it for other purposes besides only testing for a luma() value.

.box {
  font-size: if(unit(@width) = `rem`, 1.2rem, 12px);
}
@matthew-dean
Copy link
Member Author

For an implementer / pull request: I took some time to look at current parsing (which would need to be updated). Even though if() has a regular function signature, you might want to special case if() just so then conditional parsing rules are not added to other functions (and only apply to the first argument of if()). Meaning: in general, all arguments of a function are given the same parsing tests. But it's very unlikely any other function name would need to parse a conditional, and it's not necessary in this case to try to parse a conditional statement for anything other than the first argument.

Tests will need to be added for:

  1. using commas / semi-colons as argument separators in if()
  2. Passing variables / other functions to if()
  3. Nested if() functions

To look at the evaluation of conditionals, you would look at the mixin definition node type in the lib/less/tree folder.

@rjgotten
Copy link
Contributor

rjgotten commented Jan 19, 2017

@matthew-dean
One last thing you may want to add:
When the 2nd and 3rd result parameter are not added to if(), make it return Keyword.True or Keyword.False based on the 1st condition parameter.

That way you could store the boolean result for later use in a mixin guard condition. This has some added value for writing cleaner, less repetitive code in cases where you cannot logic mixins together under one shared guard.

E.g. when you are using one mixin to unlock a different set of other mixins, where you use a kind of partial application by taking parameters from the top mixin and using them to set guard conditions on the unlocked child mixins.

@seven-phases-max
Copy link
Member

That way you could store the boolean result for later use in a mixin guard condition.

That way it's probably better to be a separate wrapper named bool or boolean:
@some: if (a > b); does not look like something obvious.

@matthew-dean
Copy link
Member Author

matthew-dean commented Jan 20, 2017

@rjgotten Yeah, I thought of something like that for repeated conditions on mixins, buuuut I kinda leaned where @seven-phases-max went, which is to just not over-complicate things. An if function (sometimes iif) has a fairly standard structure across a number of languages / environments.

@rjgotten
Copy link
Contributor

a separate wrapper named bool or boolean

I actually like that a lot better as well. ^_^

@seven-phases-max
Copy link
Member

Closing as implemented in #3079 (further improvements -> new ticket).

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

3 participants