Less.js: Возвращаемые значения Mixin

Созданный на 28 дек. 2011  ·  59Комментарии  ·  Источник: less/less.js

Могу ли я установить возвращаемое значение как цвет? Как в:

.myselector {
   border: 1px solid .custommixin(@colorValue);
}

Просто интересно в ответ на проблему другого пользователя, касающуюся функций цвета: https://github.com/cloudhead/less.js/pull/488

feature request medium priority needs decision stale

Самый полезный комментарий

@distransient Проектирование решений для этого более подробно обсуждалось в: https://github.com/less/less-meta/issues/16.

(Less-meta - это репозиторий для планирования целей более высокого уровня для Less.js, а не для отдельных проблем или отчетов об ошибках.)

Все 59 Комментарий

О, понятно, нет. Но можно сделать ..

.myselector () {
  <strong i="6">@return</strong>: 2px;
}

.class {
  .myselector;
  border: <strong i="7">@return</strong> solid red;
}

довольно некрасиво.

Ну конечно. Было бы неплохо иметь возвращаемое значение для пользовательских функций цвета (и других функций пользовательских значений), когда установлены средства защиты примесей. @return может быть зарезервированной переменной для LESS. Как вы говорите, немного некрасиво, когда миксин просто выполняет только присвоение переменных при его вызове.

Было бы лучше увидеть первый опубликованный мной пример поддержки в какой-то момент. Обоснование состоит в том, что у вас есть вращение, осветление, затемнение и т. Д., Функционирующие как встроенные миксины, поэтому логика для возвращаемых значений уже существует в LESS, это просто открывает дверь для пользовательских миксинов.

Не думаю, что программирование говорит о том, что функциональность - это легко, просто это дало бы людям возможность немного расширить логику.

да, правда, но мне также нравится, как обстоят дела сейчас, где все «функции» - это javascript ..

Не могли ли переменные принимать аргументы так же, как миксины? Например, мой вариант использования:

@boxGlow(<strong i="6">@spread</strong>: 5px, <strong i="7">@color</strong>: #f00): inset 0 0 <strong i="8">@spread</strong> @color;
.myselector {
   box-shadow: 1px 1px 1px #000, @boxGlow(2px, #00f);
}

Это также довольно похоже на JavaScript, где функции находятся в обычных переменных.

@cloudhead : Если бы я потратил какое-то время на реализацию этой функции (я еще не смотрел исходный код Less, поэтому не могу ничего обещать), вы бы хотели добавить его, если код достаточно хорош?

Добавление возможности return к миксинам сохранит сопоставление миксинов с функциями JavaScript, в то же время облегчая вариант использования @jacobrask и @matthewdl . Я задокументировал это немного подробнее в выпуске 637 .

дубликат № 538

упс, это # ​​538

Это было бы очень и очень полезным решением.

Я пытаюсь реализовать динамическое изменение размера изображений (например, [UIImage resizable...] в iOS), и я хотел бы использовать функцию, которая будет возвращать строку URL-адреса, а не пару свойство / значение.

В настоящее время я использую решение @cloudhead .

Просто чтобы связать это красивым бантом, это должно быть включено при добавлении поддержки options.json. Выпуск: # 850

Миксины - это примеси, мы не должны связывать их использование с функциями. Если мы хотим иметь возможность определять пользовательские функции в таблице стилей, это может быть отдельное обсуждение.

Миксины - это примеси, мы не должны связывать их использование с функциями.

Проблема в том, что нельзя запретить использование миксинов в качестве функций. Можно использовать одно как другое, и они (и я :) можем использовать эту способность. Так что де-факто это всего лишь вопрос синтаксического сахара и многословия:

.sum(<strong i="8">@a</strong>, @b) {
    @-: (<strong i="9">@a</strong> + @b);
}

usage {
    width: @-;.sum(20px, 33px);
}

Использование одной и той же «функции» дважды в «той же области»:

// short (since 1.6.2):
usage {
    & {width:  @-;.sum(55px, 77px)}
    & {height: @-;.sum(11px, 99px)}
}

// oldschool (since 1.4.x):
usage {
    .-() {width:  @-;.sum(20px, 33px)}
    .-() {height: @-;.sum(40px, 42px)}
    .-();
}

Есть ли причина изобретать какой-то новый синтаксис «Меньше объявления / определения функции» (отличный от синтаксиса определения миксина) только для того, чтобы не позволять напрямую использовать width: .sum(20px, 33px); ?

Что, что ты там делал? Это что-то вроде Меньше хакерства следующего уровня, лол.

@lukeapage Мне очень жаль, что я не могу понять, в

@ seven-phase-max ваш подход потрясающий, но нет возможности перейти к сумме микширования в результате двухкратного вызова суммы, я ошибаюсь?
Говоря на более универсальном языке, это: foo(bar(1, 2), bar(3, 4))

@axelcostaspena Что ж, с помощью все возможно, это просто вопрос многословия (очевидно, 5 или 6 строк кода не выглядят как практическая замена одинарного лайнера).

меньше функций плагина

Ух ты. Хороший! На самом деле, единственное, что я бы улучшил с точки зрения синтаксиса, если его переместить в ядро, - это превратить внешний блок в @functions и, вероятно, отбросить начальную точку в объявлениях миксинов для согласованности с тем, как эти функции используются в вызовы сайтов (а именно; также без ведущей точки, как настоящие функции Less).

Например

<strong i="10">@functions</strong> {
    foo(@x) {
        return: <strong i="11">@x</strong> * 2;
    }
}

Это по-прежнему оставляет проблему наличия функций / миксинов, назначаемых переменным и передаваемых в качестве параметров, чтобы их можно было использовать в качестве лямбда-делегатов. Но это уже очень хороший способ отделить миксины «вычислений» от миксинов «рендеринга».

Ух ты. Хороший! На самом деле, единственное, что я бы улучшил с точки зрения синтаксиса, если его переместить в ядро, - это превратить внешний блок в @functions и, вероятно, отбросить миксинов для согласованности с тем, как эти функции используются на сайтах вызовов.

Да, мы должны уважать это от @cloudhead :

Миксины - это примеси, мы не должны связывать их использование с функциями.

Определение функции как «.foo» путем помещения ее в «.function» и последующего вызова с «foo» на самом деле не имеет смысла как синтаксис.

@rjgotten Единственное, что я хотел бы сделать для вашего синтаксиса, - это не делать функции множественным числом, даже если в функциональном блоке более одной функции. Кажется, больше Меньше / согласованности CSS.

<strong i="15">@function</strong> {
    foo(@x) {
        return: <strong i="16">@x</strong> * 2;
    }
}

Также, как сахар:

<strong i="20">@function</strong> foo(@x) {
     return: <strong i="21">@x</strong> * 2;
}

Я предполагаю, что эти функции просто добавляются в реестр функций Less как обычные функции JS, которые оценивают выражение Less?

@rjgotten @ matthew-dean: Прекрасный синтаксис, я долго размышлял, как можно "красиво" добавить функции к less. Этот синтаксис кажется ясным, интуитивно понятным и недвусмысленным.

Один вопрос - нужна ли часть return: ?

Однако один вопрос - нужна ли часть возврата?

Хм, как вернуть значение без написания оператора возврата?

Хм, как вернуть значение без написания оператора возврата?

Функция может быть просто выражением.

<strong i="8">@function</strong> foo(@x) { <strong i="9">@x</strong> * 2  }

Это могло бы быть на самом деле чище. Таким образом, в принципе, функция может быть способом абстрагирования выражений, которые оценивают значение, вместо блока пар свойство / значение. Я согласен, свойство return: похоже на взлом языка.

Повторное открытие, поскольку кажется, что мы пересматриваем это как возможность.

@ matthew-dean Или, может быть, нам действительно стоит послушать @cloudhead и создать новый тикет? (Вероятно, это была моя ошибка, связавшаяся здесь вместо того, чтобы создавать новую ... Думаю, я просто пропустил настоящую причину, по которой она была закрыта в прошлый раз) ...

foo(@x) { <strong i="6">@x</strong> * 2 }

О нет:

foo(<strong i="10">@x</strong>, @y) { 
    <strong i="11">@z</strong> * @w; 
    <strong i="12">@z</strong>: pow(<strong i="13">@x</strong>, @y);
    <strong i="14">@w</strong>  pow(<strong i="15">@z</strong>, @y); // wtf, I just missed : here
}

Есть причина, по которой почти в каждом другом языке есть ключевое слово return .

Да, если вы хотите иметь несколько выражений в функции, этот синтаксис не сработает. Вы возражаете против того, чего я не предлагал. Вы спросили, как можно было бы иметь функцию без оператора return, и вот как:

<strong i="6">@function</strong> foo(<strong i="7">@x</strong>, @y) { 
   pow(<strong i="8">@x</strong>, @y) * pow(pow(<strong i="9">@x</strong>, @y), @y)
}

Не уверен в фигурных скобках {} если это просто выражение, но да, это можно сделать. ДОЛЖНО ли это быть сделано - другой вопрос. И да, мы могли бы создать новый выпуск о функциях. Все, что имеет для вас смысл.

В голову пришла другая идея. Я работаю над устаревшим приложением VBScript, и возвращаемое значение присваивается имени функции. Это может иметь больше смысла в контексте «присвоения» значения (если вам нужно несколько выражений), поскольку return: является своего рода расширением концепции оператора возврата. Как в:

<strong i="16">@function</strong> foo(<strong i="17">@x</strong>, @y) { 
    <strong i="18">@z</strong>: pow(<strong i="19">@x</strong>, @y);
    <strong i="20">@w</strong>: pow(<strong i="21">@z</strong>, @y);
    foo: <strong i="22">@z</strong> * @w; 
}

Таким образом, это не «волшебное» свойство, а фактическое присвоение значения функции. @battlesnake @ seven-

И, может быть, оценка одного выражения может быть сахаром? Лучшее из обоих миров? Краткость и гибкость?

<strong i="6">@function</strong> foo(@x) { foo: <strong i="7">@x</strong> * 2;  }
// same as
<strong i="8">@function</strong> foo(@x) { <strong i="9">@x</strong> * 2; }

Как бы мне ни не нравился «автоматический возврат» в Ruby и Groovy, это одно место, где это может быть приятно - при этом я не очень самоуверен в этом отношении, мне просто нравятся несколько ключевых слов, которые есть в LESS. Учитывая время, которое я потратил на отладку кода Grails, когда ошибки были вызваны тем, что кто-то случайно возвратил значение там, где он не хотел, я в некоторой степени согласен с вашими доводами о сохранении какого-либо явного синтаксиса возврата. Мне нравится эта идея VB-синтаксиса (никогда не думал, что скажу эти слова ...).

Разрешение синтаксиса VB и «return» тоже может быть приятным, например, как Delphi поддерживает «имя функции: = значение» и «Result: = value» с Result, являющимся волшебной переменной для возвращаемого значения.

Моим текущим вариантом использования был небольшой безвкусный генератор градиентов "web 2.0":

<strong i="8">@function</strong> web2-control(<strong i="9">@direction</strong>, <strong i="10">@start</strong>, <strong i="11">@end</strong>, <strong i="12">@split</strong>: 50%, <strong i="13">@spread</strong>: 5%) {
    return: linear-gradient(<strong i="14">@direction</strong>, <strong i="15">@start</strong> 0%, <strong i="16">@start</strong> ((@split-@spread)), <strong i="17">@end</strong> ((@split+@spread)), <strong i="18">@end</strong> 100%)
}

.stupid-button {
    background: web2-control(to bottom, white, darken(skyblue, 10%));
    &:hover {
        background: web2-control(to bottom, white, skyblue);
    }
}

Оцените проблему, а не цель кода, ха-ха :)

@battlesnake Забавно, ваш пример с линейным градиентом - это то, о чем я думал как о хорошем

И да, VBScript тоже не мой любимый язык, но хороший художник черпает вдохновение отовсюду. :-)

foo: <strong i="6">@z</strong> * @w; Таким образом, это не «волшебное» свойство, а фактическое присвоение значения функции.

Это все то же «волшебное свойство». Разница в значениях кодов символов между f . o . o и r . e . t ... не будет делать никакого логического сдвига (не считая того, что, если имя функции перекрывается с каким-либо существующим свойством, это становится еще одной проблемой для читателя ... Также учитывайте обязанность переименовать foo to bar каждый раз, когда вы копируете какой-то фрагмент из одной функции в другую. Так что лично я не вижу, что может быть не так с return ... Это просто "установить возвращаемое значение" идентификатор.)

Что касается того, чтобы сделать это необязательным. Хорошо, теперь я понимаю, что вы имеете в виду ... Ну, да, это один из тех ... ах, неважно: просто -1 :)

Мне нужен был тот же стиль линейного градиента для кнопок в любом состоянии, только с измененным цветом или яркостью, поэтому:

<strong i="6">@function</strong> web2-gradient(<strong i="7">@direction</strong>, <strong i="8">@start</strong>, <strong i="9">@end</strong>, <strong i="10">@split</strong>: 50%, <strong i="11">@spread</strong>: 5%) {
    return: linear-gradient(<strong i="12">@direction</strong>, <strong i="13">@start</strong> 0%, <strong i="14">@start</strong> ((@split-@spread)), <strong i="15">@end</strong> ((@split+@spread)), <strong i="16">@end</strong> 100%)
}

<strong i="17">@primary</strong>: red;
<strong i="18">@contrast</strong>: 10%;

<strong i="19">@light</strong>: lighten(<strong i="20">@primary</strong>, @contrast);
<strong i="21">@dark</strong>: darken(<strong i="22">@primary</strong>, @contrast);
<strong i="23">@lighter</strong>: lighten(<strong i="24">@primary</strong>, ((@contrast*2)) );
<strong i="25">@darker</strong>: darken(<strong i="26">@primary</strong>, ((@contrast*2)) );

@button-normal-bg: web2-gradient(to bottom, <strong i="27">@light</strong>, @dark);
@button-hover-bg: web2-gradient(to bottom, <strong i="28">@lighter</strong>, @primary);
@button-down-bg: web2-gradient(to bottom, <strong i="29">@darker</strong>, @primary);

На самом деле я задумался о переходе на Stylus после того, как обнаружил, что не могу создавать функции, возвращающие значение в Less, но у Stylus нет того декларативного ощущения, которое мне нравится в меньшей степени.

Сейчас я больше склоняюсь к синтаксису return: value - но для однострочников мы можем использовать синтаксис OpenSCAD, например:

<strong i="7">@function</strong> square(@x) = <strong i="8">@x</strong> * @x;

Таким образом, мы также делаем возврат явным, используя вместо фигурных скобок = и ; .

Или, чтобы быть более похожим на CSS:

<strong i="15">@function</strong> square(@x) : <strong i="16">@x</strong> * @x;

Использование двоеточия вместо символа равенства.

Это все то же «волшебное свойство».

Эээ, это не так, поскольку return - это выдуманное свойство, а foo определяется пользователем, но хорошо. Я не так привязан к этому. Я просто хотел бы, чтобы это возвращение не выглядело как собственность, и тогда это не так. Но кроме присвоения имени функции у меня нет лучшего предложения.

@battlesnake Я бы

Так что я не знаю. Кажется, что определение синтаксиса для другого многострочного блока, выводящего только одно значение ... Я не знаю, у Less уже есть так много видов блоков. Действительно ли существует много реальных примеров, когда требуется многострочная функция? Многострочный пример все еще можно было решить в одну строку. И, если действительно есть необходимость в создании сложной многострочной функции, не лучше ли это сделать с помощью встроенного плагина? Что касается языка Less, то необходимость в ответе кажется мне плохим предзнаменованием.

Итак, есть ли действительно реальные случаи, когда:
а) вы хотите оценить выражение,
б) это слишком сложно или сложно сделать в одной строке (или путем объединения функций)
в) это не может быть в плагине JS
?

oneliners

Я до сих пор не вижу причин, по которым меня _принуждены_ написать
... (<strong i="8">@a</strong> + <strong i="9">@b</strong> + @c) * (<strong i="10">@a</strong> + <strong i="11">@b</strong> + @c);
вместо нормального:

<strong i="15">@x</strong>: <strong i="16">@a</strong> + <strong i="17">@b</strong> + @c;
return <strong i="18">@x</strong> * @x;

Разве для этого не лучше использовать встроенный плагин?

Вот простой пример, показывающий, насколько легко функции Less могут запускать функции JS для многих сценариев использования (на самом деле всегда, если речь не идет о производительности или некоторых функциях, которых просто нет в самом Less),
(искусственный) Функция Less (формат less-plugin-functions ) для возврата квадрата непрозрачности / альфа-канала цвета:

.function-sqralpha(@c) {
    <strong i="26">@a</strong>: alpha(@c);
    return <strong i="27">@a</strong> * @a;
}

Теперь код, необходимый для того же на JS:

functions.addMultiple({
    sqralpha : function(c) {
        var a = c.alpha; // no docs and no guaranty this internal stays the same, but there's no easy way to reuse built-in Less `alpha()` here
        return new tree.Dimension(a * a); // Dimension? some kind of quantum mechanics?
    }
});

И на самом деле, чем сложнее (в том, что касается вовлечения большего количества разных, промежуточных и исходящих типов с меньшим значением, повторного использования встроенных функций и т. Д.) Функция становится тем труднее писать на JS.

Так что, честно говоря, последние идеи выглядят хм ... Я даже не уверен ... странно? :)

@ matthew-dean: Я думаю, OpenSCAD допускает только однострочные функции, но вы можете получить те же возможности многострочных функций, используя блоки let в OpenSCAD.

Если подумать, синтаксис OpenSCAD для for итерации и для let блоков может быть полезен для LESS, учитывая, что оба языка являются декларативными способами определения геометрии и ее стиля.

@ seven-phase-max Я все еще скептически отношусь к этому и чувствую, что бремя доказательства лежит на многострочных примерах. Тем не менее, return <strong i="5">@x</strong> * @x; выглядит лучше, чем return: <strong i="7">@x</strong> * @x , потому что более логично понятно, что функция получает / возвращает значение, а не присваивается свойству, которое ... что-то делает.

Но оператор return с каждым моментом все меньше и меньше похож на Less.

Что касается этого:

Я до сих пор не вижу причин, по которым меня заставят писать
... (<strong i="14">@a</strong> + <strong i="15">@b</strong> + @c) * (<strong i="16">@a</strong> + <strong i="17">@b</strong> + @c) ;
вместо нормального:

<strong i="21">@x</strong>: <strong i="22">@a</strong> + <strong i="23">@b</strong> + @c;
return <strong i="24">@x</strong> * @x;

Вопрос лучше сформулировать: какова веская причина добавить в язык больше синтаксиса, чтобы просто разделить это выражение на две строки? Бремя должно заключаться в том, чтобы доказать необходимость более подробного синтаксиса с дополнительными ключевыми словами, а не наоборот. В этом нет ничего «нормального», так как его еще нет. И это все еще не близко к реальному примеру. Пример @battlesnake по -прежнему был однострочным выражением.

<strong i="29">@function</strong> {
    web2-control(<strong i="30">@direction</strong>, <strong i="31">@start</strong>, <strong i="32">@end</strong>, <strong i="33">@split</strong>: 50%, <strong i="34">@spread</strong>: 5%): 
        linear-gradient(<strong i="35">@direction</strong>, <strong i="36">@start</strong> 0%, <strong i="37">@start</strong> ((@split-@spread)), <strong i="38">@end</strong> ((@split+@spread)), <strong i="39">@end</strong> 100%);
}

Мне нравится идея функций, но было бы разочарованием, если бы мы добавили в язык что-то более тяжелое, чем было абсолютно необходимо / полезно. У нас уже есть 3 типа блоков, которые «делают что-то»: миксины, классы / идентификаторы, которые могут быть «оценены» и импортированы в область видимости (что делает их чем-то вроде миксинов без параметров, но они несколько отличаются) и отдельные наборы правил. Если вы добавите функциональный блок, все эти определения будут иметь несовместимый синтаксис друг с другом. Примесь не определяется ключевым словом @ но есть функция. Отдельный блок набора правил назначается двоеточием (и должен заканчиваться точкой с запятой), а блок миксина - нет.

Думаю, стоит сделать шаг назад и взглянуть на синтаксис в целом. Синтаксис @function с оператором return может быть приемлемым, но я не вижу логического согласования между всеми частями Less и этого синтаксиса. И есть ли логическое соответствие между функциями Less и функциями плагинов? Мне где-то кажется, что нам не хватает сплоченности. Ты знаешь, что я имею в виду?

То есть просто задумайтесь на мгновение, как это выглядит:

.class {
  prop: val;
}
.class(<strong i="6">@x</strong>, @y) {
  prop: <strong i="7">@x</strong> * @y;
}
<strong i="8">@class</strong>: {
  prop: val;
};
<strong i="9">@function</strong> class(<strong i="10">@x</strong>, @y) {
  return <strong i="11">@x</strong> * @y;
}

Я знаю, что функция должна быть специально определена, чтобы различать другие блоки, но, возможно, в этом проблема. Если функция говорит @function тогда миксин должен сказать @mixin . Добавление всего одного приводит к несовпадению частей оцениваемых блоков. Так что я как бы: -1: если это так.

@ matthew-dean Тогда я немного потерялся. Так как именно

<strong i="6">@function</strong> web2-gradient(<strong i="7">@direction</strong>, <strong i="8">@start</strong>, <strong i="9">@end</strong>, <strong i="10">@split</strong>: 50%, <strong i="11">@spread</strong>: 5%)
    : linear-gradient(<strong i="12">@direction</strong>, <strong i="13">@start</strong> 0%, <strong i="14">@start</strong> ((@split-@spread)), <strong i="15">@end</strong> ((@split+@spread)), <strong i="16">@end</strong> 100%)

вместо

<strong i="20">@function</strong> web2-gradient(<strong i="21">@direction</strong>, <strong i="22">@start</strong>, <strong i="23">@end</strong>, <strong i="24">@split</strong>: 50%, <strong i="25">@spread</strong>: 5%) {
    return: linear-gradient(<strong i="26">@direction</strong>, <strong i="27">@start</strong> 0%, <strong i="28">@start</strong> ((@split-@spread)), <strong i="29">@end</strong> ((@split+@spread)), <strong i="30">@end</strong> 100%);
}

решает все упомянутые вами проблемы? Может, тогда имеет смысл начать с вопроса самого @function , а не {} ?

Я не прокомментировал @function (вы забыли, кто предложил @function выше?;) Сначала просто потому, что мое мнение по этому поводу столь же радикально, как всегда (так что теперь начнется еще одна синтаксическая битва :):

Честно говоря, лично я был бы более доволен либо .function .foo , function foo , function:foo или, наконец, foo:function (странно, но по крайней мере следует за :extend ). Принятие Sassish-способа использования синтаксиса @at-rule для новых "директив" Less, кажется, слишком поздно для Less, даже если потенциально он действительно намного менее конфликтует с CSS, чем все остальное.


но я не вижу логического соответствия между всеми частями Less и этого синтаксиса

? Значит, вы действительно не видите никакого сходства между примерами Less и функциями (независимо от синтаксиса)? Я могу предположить, что многие пользователи вообще не понимают параметрические миксины, думая о них как о некоем примитивном "пакете свойств CSS", но в этом конкретном контексте функции / миксина, хм ...

Так или иначе:
less-plugin-functions выполняет все это в ~ 50 строках кода (если я удалю все хаки, специфичные для плагина), именно потому, что он повторно использует существующий основной код для синтаксического анализа и оценки миксинов. Предоставление всех этих _ существующих и задокументированных_ функций (вы не обязаны использовать) бесплатно.
Итак, учитывая это, теперь я только задаюсь вопросом, как:

.class {
  prop: val;
}
.class(<strong i="55">@x</strong>, @y) {
  prop: <strong i="56">@x</strong> * @y;
}
<strong i="57">@class</strong>: {
  prop: val;
};
<strong i="58">@function</strong> class(<strong i="59">@x</strong>, @y) : <strong i="60">@x</strong> * @y;

может быть потенциально лучше оправдать, скорее всего, более раздутую реализацию (+ новый код синтаксического анализа) для обеспечения более ограниченной функциональности?


И, наконец, для поддержки «согласованности функций / синтаксиса» я полагаю, что переформатированная таблица существующих функций Less в том виде, в каком я их вижу, была бы интересна (на всякий случай):

name   {prop: val}  // a ruleset having some standard CSS selector as a name
<strong i="66">@name</strong>: value;        // variable
<strong i="67">@name</strong>: {prop: val}; // *unnamed* ruleset assigned to a variable as its value

// mixin
.name(<strong i="68">@x</strong>, @y) {
    prop: <strong i="69">@x</strong> * @y;
}

// function (whatever `func` directive)
<func> name(<strong i="70">@x</strong>, @y) {
    return: <strong i="71">@x</strong> * @y; // return property of the function
}

Отсутствие префикса для имен функций будет соответствовать текущему состоянию LESS, т. Е.

color: darken(<strong i="6">@base</strong>, 10%);
background: checkerboard(1em, lighten(<strong i="7">@base</strong>, 20%), white);

Отсутствие префикса для функций JS, в то время как требование префикса для функций, представленных в фактическом коде LESS, кажется несколько отсталым.

Лично я не вижу никакой пользы для многострочных функций, но, возможно, здесь у меня есть момент «кому нужно> 640 КБ ОЗУ».

Если в будущем возникнет очевидная потребность в многострочных функциях, после того, как мы примем синтаксис <strong i="12">@function</strong> name(params) : expression; , мы всегда сможем разрешить это, используя блоки let стиле SCAD:

<strong i="16">@function</strong> multi-line-thing(<strong i="17">@a</strong>, <strong i="18">@b</strong>, @c) :
    let { <strong i="19">@sum</strong> : <strong i="20">@a</strong> + <strong i="21">@b</strong> + @c; <strong i="22">@product</strong> : <strong i="23">@a</strong> * <strong i="24">@b</strong> * @c; <strong i="25">@mean</strong> : <strong i="26">@sum</strong> / 3; }
        <strong i="27">@sum</strong> / <strong i="28">@product</strong> ~", " @mean;

Этот синтаксис по-прежнему будет <strong i="31">@function</strong> name(params) : expression; . Синтаксис expression будет расширен, чтобы разрешить let { assignments } expression .

Переменные в таких блоках ограничиваются только выражением, следующим за блоком, они не попадают в родительскую область.

Таким образом, мы могли бы добавить функции с одним выражением сейчас, но у нас все еще есть возможность расширить их до многострочных в будущем (если будет продемонстрирована необходимость), либо используя функции блочного стиля «рецепт» (с return ) или функции функционального стиля "под-области видимости" (с let ).

Если должен использоваться блочный стиль, мне нравится синтаксис return: value; над синтаксисом return value; - поскольку все, что не является блоком, по-прежнему является парой key: value с return (или, может быть, result ) просто специальное имя ключа в функциях. Явный синтаксис @function затем гарантирует, что return: не рассматривается как имя атрибута CSS.

Все похоже на набор правил, включая функции, которые выглядят точно так же, как миксины. На самом деле, если вкратце, единственными отличительными признаками являются то, что миксины могут устанавливать свойства CSS, а функции должны иметь оператор возврата. (Вы не можете и не должны делать и то, и другое.)

Так почему бы просто не полагаться на это поведение напрямую?

Например

.mixin(<strong i="8">@a</strong>, @b) {
  value : <strong i="9">@a</strong> @b;
}
.func(<strong i="10">@a</strong>, @b) {
  return <strong i="11">@a</strong> @b;
}

Затем позвольте компилятору выяснить на _call site_, вызывает ли он миксин или функцию и вызывает исключение, если одно или другое используется в неподходящем контексте.

В качестве альтернативы, если исключения не для вас:

  • Определите вывод CSS функции, называемой миксином, как пустой набор правил.
  • Определите значение, возвращаемое функцией миксина, как сопоставленный набор правил всех примененных к нему свойств CSS и вложенных наборов правил, оцененных в их конечном состоянии, возвращенных как отдельный набор правил.

Хммм полиморфизм ... в этом есть смысл, я думаю, миксины не могут появляться справа от двоеточия, а функции могут появляться только там. Пока мы гарантируем, что при использовании в неправильном месте возникают ошибки, использование синтаксиса миксина для функций кажется нормальным.

На самом деле, если вкратце, единственными отличительными признаками являются то, что миксины могут устанавливать свойства CSS, а функции должны иметь оператор возврата.

Вот что я имел в виду. Должны ли мы создать новый тип набора правил с другим методом «определения»?

Но ... Я тоже согласен с этим:

Отсутствие префикса для функций JS, в то время как требование префикса для функций, представленных в фактическом коде LESS, кажется несколько отсталым.

Мне всегда казалось, что требование, чтобы к миксину добавлялись префиксы . или # , некрасиво и раздражает. (См. Первую часть: https://github.com/less/less.js/issues/1342.) Также странно произвольно, что только два из трех типов общих селекторов могут быть преобразованы в миксины. Здесь это актуально только в том случае, если мы разрешили миксинам возвращать значения.

Однако есть некоторые доводы в пользу наличия отдельного типа, поскольку переменные функций не должны импортироваться в область действия вызывающего объекта, а функции не должны иметь охранников, так как трудно интуитивно понять, что это могло бы вообще означать. Таким образом, есть и другие отличия, кроме возможности возвращать значения.

Я не обязательно против @function , очевидно, что я поддержал это ранее в теме. Мне просто интересно, как все это сочетается, и я хочу, чтобы мы были осторожны. Заметьте, что моя критика состоит не в том, чтобы отвратить нас от использования чего-либо; чтобы убедиться, что мы задаем все необходимые вопросы и критически мыслим.

Даже CSS иногда нарушает свои собственные правила и содержит такие вещи, как наличие свойства vertical-align вызывающее два совершенно разных поведения. Итак, Less может также создавать новые соглашения. Я просто хочу помочь сделать так, чтобы все новые решения оставались менее простыми, интуитивно понятными, консервативными и краткими.


Я поклонник ограничения однострочными выражениями, но если это кажется слишком произвольным и ограничивающим для других, то многострочная форма, которая кажется наиболее ясной, вероятно, действительно такова:

<strong i="21">@function</strong> {
  foo(@a) {
    return @a;
  }
}
// and
<strong i="22">@function</strong> foo(@a) {
  return @a;
}

Возможно, лучшим аргументом в пользу специального «определения» является то, что, в отличие от миксинов, определение функции не может или не должно появляться несколько раз (в одной и той же области). Так что в этом отношении они больше похожи на @plugin функции. Итак, поскольку свойства достаточно отличаются от миксинов (частные переменные, одно определение, оператор возврата), возможно, совместные миксины просто не сработают.

Почему бы не разрешить буквальный javascript внутри меньше? По сути, это позволит вам использовать все функции javascript внутри CSS для создания функций. Пример:

function abs(a) { return Math.abs(a); }

.test { attribute: abs(-5px); }

Обратите внимание на две вещи:

  1. Функция - это буквальный javascript. Его можно узнать по такому принципу: "function / \ w + / ..." и остановить последним "}". Проблема заключается в том, чтобы определить, где "{" начинается, а где "}" заканчивается. Потому что у нас могут быть внутренние структуры, например if, for и т. Д.
  2. Я не думал о том, как параметр будет передан в функцию. Например, какой javascript получит, если я передам 5 пикселей? А про пропускать меньше функций, вроде abs(convert(5px, pt)) ?

@rentalhost
Прежде всего, встроенные операторы javascript разрешены в реализации less.js :

div {
    <strong i="8">@x</strong>: -10.5;
    width: unit(`Math.abs(@{x})`, px);
}

Во-вторых, Less разработан как надмножество CSS, а CSS имеет очень мало общего с C-подобными языками и, в частности, с JavaScript. Таким образом, прямые операторы JavaScript, такие как function abs(a) {return Math.abs(a);} будут не только сбивать с толку и непоследовательно, но и прямо противоречить_ собственному синтаксису Less / CSS.

Итак, две основные причины, почему код, подобный приведенному выше, никогда не следует рекомендовать для использования, и никогда не следует учитывать JS-подобный синтаксис при разработке синтаксиса Less, очевидны:

  1. Встроенные операторы javascript _require_, лежащая в основе среды JavaScript для компилятора (например, такие операторы никогда не будут поддерживаться в PHP, C # или любых других портах Less. Это в основном портит саму цель Less, который разработан как независимый от платформы / среды. автономный язык).
  2. Фундаментальные «типы / языковые сущности» CSS и JS в лучшем случае просто ортогональны, а в худшем - снова прямо противоречат друг другу. Как вы уже заметили, у JavaScript нет возможности напрямую поддерживать такие значения, как 5px , red , url(//foo/icon.png) и т. Д. И т. Д. Итак, чтобы передать значения и операторы CSS в «буквальный javascript», вам нужно будет предоставить промежуточный синтаксис и средство преобразования для объединения этих ортогональных элементов на одном языке. На самом деле нет ничего страшного в разработке такого языка, но он не будет иметь ничего общего с Less (который снова разработан как надмножество CSS и не имеет ничего общего с JS в целом).

Другими словами, все наши обсуждения выше не являются результатом так называемого синдрома «изобретено не здесь», а просто попытка максимально гладко подогнать возможный синтаксис определения функции к уже существующей базе синтаксиса Less.

Пожалуйста пожалуйста пожалуйста:

.halfway-between(<strong i="6">@large</strong>, @small) {
    max(<strong i="7">@large</strong>, @small) - (abs(<strong i="8">@large</strong> - @small) / 2);
}

: смайлик:

@andrewhosgood Что здесь происходит?

.halfway-between(<strong i="7">@large</strong>, @small) {
    max(<strong i="8">@large</strong>, @small) - (abs(<strong i="9">@large</strong> - @small) / 2);
}
.halfway-between(<strong i="10">@large</strong>, @small) {
    property: value;
    foo: bar;
}
.rule {
    width: halfway-between(3, 2);
}

В конечном итоге миксин - это параметризованный набор правил, который может иметь несколько совпадений и возвращает несколько значений, а имя функции может иметь только одно совпадение (для каждой области) и может возвращать только одно значение.

Я думаю, что у @battlesnake было самое простое и

<strong i="16">@function</strong> square(@x): <strong i="17">@x</strong> * @x;

Небольшая корректировка, чтобы не путать объем @x :

<strong i="22">@function</strong> square(@x) { <strong i="23">@x</strong> * @x; }

Или (возможно), чтобы не путать с функциями на основе JS:

<strong i="27">@expression</strong> square(@x) { <strong i="28">@x</strong> * @x; }

Я думаю, что одноразовые выражения было бы проще всего изучить, и они не мешали бы пониманию миксинов. И также послужил бы большинству приведенных примеров. По сути, вы просто сокращаете выражения (псевдонимы) для быстрого повторного использования. Мысли? Я действительно задаюсь вопросом, есть ли способ «определить» имя выражения без правила at. Хм.

@ matthew-dean Дело принято. Просто пытаюсь использовать существующие шаблоны. Итак, если бы я изменил свой запрос, это было бы так:

<strong i="6">@function</strong> halfway-between(<strong i="7">@large</strong>, @small) {
    max(<strong i="8">@large</strong>, @small) - (abs(<strong i="9">@large</strong> - @small) / 2);
}

Я не беспокоюсь о синтаксисе, но это позволило бы мне делать то, что я не могу делать сейчас.

С синтаксисом труднее всего разобраться. И вы хотите сделать это правильно, потому что это новая языковая функция.

Я немного опасаюсь @function сейчас, больше, чем когда это обсуждение было активно в прошлом, просто из-за @plugin -определенных функций и существующих функций в Less.js. А без оператора return это не очень функционально.

<strong i="9">@expr</strong> square(@x): { <strong i="10">@x</strong> * <strong i="11">@x</strong> };
<strong i="12">@expr</strong> halfway-between(<strong i="13">@large</strong>, @small): {
    max(<strong i="14">@large</strong>, @small) - (abs(<strong i="15">@large</strong> - @small) / 2)
};

Поразмыслив над этим, я думаю, что назначение двоеточия : и терминатора точки с запятой ; более логично. В этом square(@x) присваивается значение оцененного выражения. Казалось бы, это больше соответствует отдельным наборам правил. Фигурные скобки {} указывают на то, что область действия @x - это не область, окружающая оператор, а то, что назначается через псевдоним выражения.

Мне нравится эта более простая концепция многократно используемых выражений, а не «функций» (что уже означает «определенные языком синтаксического анализа», то есть JavaScript). Итак, @expression или @expr имеют здесь смысл. Я думаю, что многократно используемые выражения имеют более широкое применение и их легче понять.

Мне нравится эта более простая концепция многоразовых выражений, а не "функций".

В основном; это параметризованные расширения макросов препроцессора, как в старом простом C, верно? Но, надеюсь, без сумасшедших злоупотреблений, связанных с ними, поскольку Less будет иметь @plugin functions в качестве гораздо более достойной альтернативы более тяжелым и действительно сложным функциям.

@rjgotten

гораздо более достойная альтернатива для более тяжелых работ и действительно сложных функций.

https://github.com/less/less.js/issues/538#issuecomment -107247753. Хотя неважно.


И я по-прежнему возражаю против изобретения специального синтаксиса, жестко запрограммированного для конкретных «однострочных» примеров. По-прежнему пахнет синдромом «я люблю изобретать новые крутые синтаксисы».
В конце концов, он просто требует дополнительных проблем с точки зрения реализации парсера ... Например, вспомните # 2785 и подумайте, насколько неоднозначно

{
   foo();
   foo() - bar();
   bar();
}

становится на самом деле. Там вам придется ввести множество новых правил синтаксического анализа, чтобы определить, какой оператор на самом деле является функцией, возвращающей значение, а какие являются просто вызовами корневых функций (даже не считая дружественных сообщений об ошибках, если что-то пойдет не так).
Короче говоря, я думаю, что все, что я написал в https://github.com/less/less.js/issues/538#issuecomment -107255583, все еще в силе.

И да, еще раз подчеркивая Sassish @at-rule directive еще никогда не был в Less, так почему же это будет сейчас? (Похоже, что кто-то в последнее время просто слишком много использует PostCSS;).

@ семь фаз-макс

{
   foo();
   foo() - bar();
   bar();
}

Я имел в виду, что здесь несколько операторов будут недопустимыми (будут оцениваться как одно выражение), так что это не применимо, НО ....

... еще раз подчеркивая директиву Sassish @ at-rule - никогда еще не был в Less, так почему же это будет сейчас? (Похоже, что кто-то в последнее время просто слишком много использует PostCSS;).

Я не использовал PostCSS, но да, написание @function и @expression заставило меня почувствовать себя немного грязным. Как я уже упоминал, когда этот вопрос был повторно прокомментирован, большая часть обсуждения синтаксиса отошла еще дальше от этой возможности. У Less просто нет подходящей синтаксической парадигмы для этого, потому что все декларативно. Это означает, что даже в операторе return в миксине эти два оператора будут разумно равны, поскольку значения являются константами для области (после разрешения).

.function-sqralpha(@c) {
    <strong i="14">@a</strong>: alpha(@c);
    return <strong i="15">@a</strong> * @a;
}
.function-sqralpha(@c) {
  return <strong i="18">@a</strong> * @a;
  <strong i="19">@a</strong>: alpha(@c);
}

В любом случае, учитывая то, что обсуждалось до сих пор, это кажется несколько квадратным отверстием для штифта / круглого отверстия. Я не думаю, что миксины могут разумно претендовать на роль функций (без некоторых компромиссов и неожиданного поведения), и определение функций (или выражений, или расширений макросов) с помощью Less (то есть в вашей таблице стилей) также оказалось проблематичным.


Отдельно отметим-

Одна вещь, которая может еще больше подтолкнуть нас к закрытию этой ветки: когда я просматривал комментарии, в том числе тот, на который вы ссылались, у вас был не лучший способ решить указанную выше проблему.

functions.addMultiple({
    sqralpha : function(c) {
        var a = c.alpha; // no docs and no guaranty this internal stays the same, but there's no easy way to reuse built-in Less `alpha()` here
        return new tree.Dimension(a * a); // Dimension? some kind of quantum mechanics?
    }
});

В Less 3.0 я упростил возвраты, так что любые не-узлы (кроме значений falsey), возвращаемые функцией, приводятся к анонимному узлу, так что они легко выводятся в ваш окончательный CSS. Очевидно, что если вы хотите включить этот результат в другое выражение, вам нужно явно указать тип узла. Buuuuut .... 3.0 также включает функцию "позднего синтаксического анализа" (все значения анонимны до тех пор, пока не будут указаны ссылки - это позволяет ссылаться на свойства без создания дополнительной работы синтаксического анализа или дополнительных узлов), так что это может быть изменено так, чтобы быть похожим на:

functions.addMultiple({
    sqralpha : function(c) {
        var a = c.alpha; // docs have started! doing my best!
        return a * a;     // Cast to Dimension because Less is cool... maybe?
    }
});

И рассмотрение 3.0 должно быть посвящено функциям и @plugin , и оставшемуся списку вещей, которые необходимо выпустить ... Я бы сказал, по крайней мере, сейчас не подходящее время для этой функции. Я приложил все усилия, чтобы упростить последние примеры, но даже с учетом этого ваши возражения остаются в силе, и я могу закрыть их.

@ семь фаз-макс

538 (комментарий). Хотя неважно.

Нет нет; вы поднимаете хороший вопрос.

Существуют значительные накладные расходы для промежуточного уровня, когда вам нужно сделать больше, чем простое однострочное выражение, но их недостаточно, чтобы гарантировать запуск JS-плагина и написание кода, который обрабатывает все сопоставления типов узлов.

Хотя @ matthew-dean поднимает хороший вопрос о том, что типы возвращаемых узлов могут быть выведены, это все еще кажется большим количеством накладных расходов для некоторой простой математической или строковой интерполяции. (В частности, последнее; строковая интерполяция _ требует_ временной переменной, поэтому вы никогда не сможете написать для нее однострочное выражение.)

Если проблема заключается в использовании удобного возврата в синтаксисе, то почему бы вообще не пропустить явный оператор возврата, _ указав, с каким именем будет привязана исходящая переменная _:

.answer(<strong i="12">@a</strong>, @b):<strong i="13">@c</strong> {
  <strong i="14">@c</strong>   : ~"The answer is @{sum}";
  <strong i="15">@sum</strong> : <strong i="16">@a</strong> + @b;
}

Это кажется естественным с независимостью от порядка и декларативным характером языка Less. Он также напрямую расширяет подпись объявлений миксинов недвусмысленным образом, который может искать синтаксический анализатор и который позволяет избежать необходимости в ключевом слове @expression или @function или настраиваемом at-правиле.

Это также означает, что он может работать вместе с перегрузкой миксинов и многоадресными вызовами. Если миксин вызывается как функция, он _requires_, что существует объявление, которое имеет как совпадающую сигнатуру параметра _, так и заданный параметр, разделенный двоеточиями. И если существует несколько совпадающих перегрузок, возвращаемое значение становится списком соответствующих вызовов в порядке объявления миксинов. (Точно так же, как несколько совпадающих перегрузок в настоящее время выводят правила в порядке объявления.)

Хм. На самом деле это не так уж и плохо.

Вопрос: что происходит тогда со свойствами, значениями и другими переменными, объявленными в миксине (если они вызываются как функция). Можно ли предположить, что они изолированы от области действия вызывающего (поскольку свойства не могут быть опущены в месте вызова, если вызов находится в выражении значения)?

Это неплохо. Мы расширили функции, чтобы они вызывались повсюду. Таким образом, миксины могут быть вызваны повсюду с одинаковыми проверками, чтобы увидеть, является ли результирующий выходной узел допустимым в этом месте. Итак, функции = JS и миксины = МЕНЬШЕ.

Мне также понравилось, как вы обратились и разрешили несколько совпадающих миксинов (в результате - список). Умная. И декларативно.

Я был готов отказаться от этой идеи, но это действительно неплохо.

Мы также могли бы обновить документацию, согласно которой миксины по умолчанию «выводят» набор правил, если не указана выходная переменная (или переменные, или $ properties ??).

Для этого было обновление?

@distransient Проектирование решений для этого более подробно обсуждалось в: https://github.com/less/less-meta/issues/16.

(Less-meta - это репозиторий для планирования целей более высокого уровня для Less.js, а не для отдельных проблем или отчетов об ошибках.)

Эта проблема была автоматически помечена как устаревшая, поскольку в последнее время не было активности. Он будет закрыт, если больше не будет активности. Спасибо за ваш вклад.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги