Conditional mixin based on parameter existence

2019-07-20 08:20发布

问题:

Any suggestion how to create a conditional mixin based on parameter existence? For example I need to to verify that all the parameters are passed in order to perform something or not, for example:

.margin (@margintop:0,@marginbottom:0,@marginright:0,@marginleft:0) {

  // if @marginright:0 or @marginleft:0 are passed do that...

  // else...

}

回答1:

1:

In general, when you need to generate different things for different number of arguments passed you don't need to use default argument values at all, e.g.:

.margin(@top, @bottom, @right, @left) {
    /* right and left are passed */
}

.margin(@top, @bottom) {
    /* right and left are not passed */
}

.margin() {
    /* no arguments passed */
}

// etc.

Note that each of these mixins can reuse the others, for example .margin(@top, @bottom) can do something special for the "no right and left case" and then call .margin(@top, @bottom, 0, 0) to perform the main job.

2:

But if you still need these defaults for some reason you can use some special default value that can't be a valid margin, e.g. something like this:

.margin(@top: undefined, @bottom: undefined, @right: undefined, @left: undefined) {
    .test-args();

    .test-args() when (@right = undefined) {
        /* right is not passed */
    }
    .test-args() when (@left = undefined) {
        /* left is not passed */
    }

    .test-args()
        when not(@right = undefined)
        and  not(@left  = undefined) {
            /* right and left are passed */
    }

    // etc.
}

3:

And the third option would be to use variadic arguments and test their count, but this one is the most verbose and dumb I guess:

.margin(@args...) {
    .eval-args(length(@args));  // requires LESS 1.5.+
    .eval-args(@nargs) {
        // default values:
        @top:    not passed;
        @bottom: not passed;
        @right:  not passed;
        @left:   not passed;
    }
    .eval-args(@nargs) when (@nargs > 0) {
        @top:    extract(@args, 1);
    }
    .eval-args(@nargs) when (@nargs > 1) {
        @bottom: extract(@args, 2);
    }
    .eval-args(@nargs) when (@nargs > 2) {
        @right:  extract(@args, 3);
    }
    .eval-args(@nargs) when (@nargs > 3) {
        @left:   extract(@args, 4);
    }

    args: @top, @bottom, @right, @left;
}

Though it may probably have its pros in some special use-cases.