Less.js: Como lidar com matemática

Criado em 17 fev. 2014  ·  102Comentários  ·  Fonte: less/less.js

  1. Decidimos fazer matemática estrita daqui para frente, mas há um desconforto geral sobre forçar () em cada cálculo
  2. Não acho que queremos mudar as coisas de forma massiva ou voltar para a prancheta

Veja # 1872

Possibilidade de adicionar outro caso para calc que, como a fonte, com o modo estrito desativado, essencialmente ativa o modo estrito para uma regra? Muitas exceções no futuro?

@ sete fases-máx .:
Bem, há muitas outras possibilidades, por exemplo, ./ ou exigir parênteses para divisão (por exemplo, 1/2 -> 1/2 mas (1/2) -> 0.5 ) etc ...
Além disso, os "casos especiais" (por exemplo, propriedades onde x/y podem aparecer como abreviações) não são tão raros (começando em padding / margin e terminando com background / border-radius e eventualmente pode haver mais ) então simplesmente não podemos codificar todos eles como se fosse font (e por causa disso eu acho que a fonte atual "alternativa" é apenas um kludge temporário e bastante sujo que, idealmente, também deve ser removido).

feature request high priority

Comentários muito úteis

Para simplificar / reformular a proposta - as alterações matemáticas seriam as seguintes

  1. Adição e subtração seriam calculadas apenas em unidades semelhantes. por exemplo, 1px + 2px = 3px , 1px + 1vh = 1px + 1vh
  2. A divisão e a multiplicação seriam calculadas apenas com divisores / multiplicadores sem unidades. por exemplo, 10px/2 = 5px , 10px/5px = 10px/5px
  3. Relações de valor sem unidades seriam tratadas de forma semelhante a # 2. por exemplo, 1/3 = 1/3
  4. Para simplificar, as expressões com subexpressões parcialmente inválidas podem ser tratadas como expressões matemáticas inválidas e geradas no estado em que se encontram. por exemplo, 1px + 2vh / 2 = 1px + 2vh / 2

Esta proposta resolve o seguinte (deste tópico):

  • font: 10px/5px e sintaxe semelhante (proporção) (sem cálculo)
  • calc(100vh - 30px) (sem cálculo)
  • lost-column: 1/3 e sintaxe de proporção personalizada semelhante (sem cálculo)

Ao mesmo tempo, essas mudanças preservariam 99% do uso típico de matemática do Less. Da mesma forma, as funções unit() e convert() permitem que os usuários convertam valores em unidades compatíveis para matemática.

Todos 102 comentários

Não acho que queremos mudar as coisas de forma massiva ou voltar para a prancheta

Sim, sugeri começar isto apenas porque _se_ quisermos alguma matemática estrita "padrão" no 3.0, teremos que inventar algo menos pesado do que o atual (e a possibilidade de consertar todos os problemas sem introduzir nenhum --alt-strict-math opção parece ser bastante irreal por causa de problemas ocultos por trás da solução de codificação rígida semelhante a font ...).

Eu não tinha percebido que está crescendo

https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius

:(

Acho que, no momento, sou a favor de expandir inicialmente o strictMaths para ser

  • Fora
  • Divisão
  • Sobre

e então para 2.0.0 configurando o padrão para Divisão

Assim..

Consultas de mídia - se desativado, alterne para divisão para subnós
Fonte - se desligado, mude para divisão para subnó
calc (- se desligado ou divisão, ligue para subnós

https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius

Sim, acho que eles devem permitir "valores abreviados" (ou seja, x/y ) em _qualquer_ "propriedade shorthand" ...

Outra opção .. processar chamadas de cálculo, mas apenas onde as unidades tornam isso possível, por exemplo
calc (1% + 2%) => 3%
calc (100% - 10 px) => inalterado

Isso vai consertar calc mas não vai consertar # 1627 e coisas relacionadas.
Quer dizer, sim, calc(100% - 10 px) => unchanged poderia ser uma solução para calc mas isso não cancela a necessidade de uma solução less-heavy-than-parens-everywhere .

Se a matemática estrita está sendo revisada, eu gostaria de sugerir que as funções de Less, como percentage() não exijam parênteses extras dentro delas. Com matemática estrita ativada, você tem que embrulhar duas vezes o argumento. Isso reduziria muito a possibilidade de confusão e bugs difíceis de encontrar, uma vez que percentage(16 / 17) e percentage((16 / 17)) seriam válidos.

@calvinjuarez V2 fornece um subsistema de plug-in onde um plug-in pode adicionar um número arbitrário de funções ao ambiente e, neste sentido, o núcleo não será capaz de decidir se tal função embutida espera um único valor ou uma expressão, ou seja, é permitido aceitar 16/17 , e então avaliar 16/17 _antes_ de ser passado para uma função seria incorreto (bem, falando grosso modo - é um pouco mais complicado do que internamente).

Nesse contexto, a mudança de ./ parece ser minha favorita, embora eu entenda que seria uma mudança muito dramática (se comparada a (/) , sem contar, também requer um espaço em branco antes de . , por exemplo, 16 ./17 e não 16./17 , hmm).

Outra coisa em que o less atualmente quebra um css válido é uma abreviatura de plano de fundo:

background: url(image.png) 50%/300px no-repeat;

Acho que, no momento, sou a favor de expandir inicialmente o strictMaths para ser

Fora
Divisão
Sobre
e então para 2.0.0 configurando o padrão para Divisão

Desculpe, não respondi a isso antes do 2.0 ser lançado. Acho que é um bom instinto. Operadores de divisão nua simplesmente entram em conflito com muito CSS, e entrarão em conflito cada vez mais conforme as pessoas usam mais recursos do CSS3. E eu entendo a reação das pessoas de não exigir parênteses para toda a matemática, já que não é necessário em muitos casos.

@ sete fases-máx.

é permitido aceitar 16/17, e então avaliar 16/17 antes de ser passado para uma função seria incorreto

Estritamente falando, sim, está absolutamente correto. Isso não deve ser avaliado ANTES de atingir a função, especialmente para uma função personalizada. No entanto, acho que seria inteligente permitir que funções optassem por processar argumentos como este, se fizer sentido. Portanto, a porcentagem receberia 16/17 como um argumento de texto e, em seguida, a função de porcentagem poderia fazer uma chamada para alguma função auxiliar para ver se o texto é matemático. No caso da porcentagem, o argumento não é ambíguo. Uma declaração CSS3 não é válida aqui. Portanto, outras funções definidas pelo usuário podem operar da mesma maneira: opt para avaliar argumentos para equações matemáticas válidas. Portanto, não é necessariamente verdade que a matemática estrita "force" dois parênteses neste caso. Acho que sugerir que isso causa algum retrocesso à ideia de matemática estrita, que deve, como uma necessidade, ser prolixa em todos os casos.

Nossas opções --math poderiam ser mais como:

  • Sempre
  • Divisão (padrão)
  • Rigoroso

Portanto, poderíamos descontinuar --strict-math = true e torná-lo um apelido para --math = strict

No entanto, acho que seria inteligente permitir que funções optassem por processar argumentos como este, se fizer sentido.

Eles já são permitidos (apenas teste como percentage(16 / 17) e percentage((16 / 17)) funcionam com --strict-math=on ).
Embora nenhuma das funções use:

e então a função de porcentagem pode fazer uma chamada para alguma função auxiliar para ver se o texto é matemático.

simplesmente porque desta forma cada função teria que ter aquelas ~ 20 linhas extras daquele extra-helpers-conversion-arg-checking-smart-arg-handling-stuff, enquanto o próprio código de função é apenas uma linha (!) na maioria dos casos.

Cada função deve ter 20 linhas extras? Como você descobre?

Se a porcentagem já funciona com matemática estrita de parênteses simples, então não entendo o problema de @calvinjuarez . Você pareceu sugerir em sua resposta que parênteses isolados não eram possíveis.

Cada função deve ter 20 linhas extras? Como você descobre?

Isso é apenas um exagero típico de: talvez 5, talvez 10, talvez 20 ... Quem se importaria com os números exatos se a proporção código real / código auxiliar -> 0 . (Adotando uma abordagem pragmática, eu pararia em percentage(16 / 17) apenas lançando um erro em vez de produzir NaN% (como agora) e não tentando realizar nenhuma conversão ... Embora mesmo assim ainda seja 4 linhas extras de código - bem, menos ou mais aceitável, eu acho :)

Minha resposta inicial estava implicando que ele assume esta 16/17 -> (16/17) conversão a ser executada implicitamente pelo próprio compilador (e não pela função).


Falando em opções. Em um mundo perfeito, eu sonharia que não haveria opções para isso (ou seja, deveria ser o único e o resto a ser marcado como obsoleto e eventualmente removido) ... Todas essas opções extras tornam a base de código não -manutenível .. mesmo para uma pequena correção / alteração de uma linha, o número de casos extremos que você tem que prever e os testes que você precisa realizar cresce exponencialmente ... (quase sem motivo).

Eu estava pensando que seria algo como:

percentage: function(...) {
  Helper.convertMath(arguments);  // a function that doesn't need it doesn't call it
  // ... the rest
} 

Falando em opções. Em um mundo perfeito, eu sonharia que não haveria opções para isso

Eu concordo. Mas vamos precisar das opções a curto prazo. Especialmente se estivermos nos desviando da matemática estrita e do comportamento legado. Ambos podem ser marcados como obsoletos se aperfeiçoarmos uma opção de "matemática mais inteligente".

Helper.convertMath(arguments);

arguments é muito otimista.
Na melhor das hipóteses (contando não apenas percentage - o que é meio inútil de qualquer maneira , mas qualquer outra função esperando um arg numérico) um requisito mínimo seria:

some: function(a, b, c) { 
    a = convert2number(a, "Error message when fails"); 
    // b is not a number for example
    c = convert2number(c, "Error message when fails"); 
} 

Mas esse não foi o meu ponto realmente, o que eu quis dizer é provavelmente algo como: embora isso sempre seja / fosse possível, ninguém se preocupa em escrever tal código ... (com algumas exceções limitadas como ) ...

Sim, eu entendo você.

percentage(16 / 17) apenas lançando um erro

seria uma melhoria, certamente. (Não consigo pensar em nenhum momento em que NaN% seria uma saída útil.)

No que diz respeito a quais funções tentariam ser inteligentes sobre seus argumentos, não há razão para tentar antecipar tudo. Uma função auxiliar, como sugere @ matthew-dean, pode ser implementada de maneira bastante simples, à medida que as solicitações de recursos são feitas e discutidas para que funções específicas sejam mais inteligentes.

Na verdade, desde o início, eu diria que apenas as funções matemáticas devem ser inteligentes sobre seus argumentos.

Editar: Na verdade, apenas sempre que uma função matemática é passada apenas um argumento.

Qual é o status disso? Estamos recebendo reclamações de que o LESS tenta analisar propriedades CSS inválidas como matemática. por exemplo, lost-column: 1/3; quebras.

Também parece que http://www.w3.org/TR/css-grid-1/#grid -template-rowcol não funcionará com LESS.

Alguém pode consertar isso se alguém quiser explicitamente usar o MENOS para fazer a divisão em uma propriedade e precisar envolvê-la entre parênteses ou algo assim?

@corysimmons Você não perguntou isso no # 2769 e recebeu uma resposta? o_O

Uma coisa que não discutimos quando isso aconteceu pela primeira vez. Parece que o único conflito matemático real é a divisão. E a divisão é essencialmente um problema porque essencialmente estamos "reaproveitando" um caractere de "separação" CSS.

Em vez de tentar "quebrar" a divisão de várias maneiras, ou envolver toda a matemática (como nossa primeira solução para este problema), eu me pergunto por que nunca falamos sobre o óbvio: _não reaproveitar um operador existente em primeiro lugar_, especialmente quando ele tão claramente a) torna o código menos ambíguo, b) causa conflito.

Depois de termos tido tempo para digerir isso, colocando a matemática entre parênteses, mesmo que seja apenas uma divisão, _ainda_ causa ambigüidade para os casos em que a matemática já está entre parênteses. (O que também poderia significar que os parênteses eram uma escolha errada de "invólucro matemático".)

Então, por que não descontinuar / como operador de divisão? Eu sei que é um símbolo de divisão comum, mas há outras compensações de sintaxe que Less fez para estender o CSS. E está claro para mim agora que basicamente estamos tentando contornar um problema criado por Less em primeiro lugar usando uma única barra. Estamos criando ambigüidade e, em seguida, tentando reverter a ambigüidade.

Para ser justo, os outros símbolos matemáticos são todos reaproveitados em outras partes do CSS, só que seu uso em matemática não causa qualquer ambigüidade.

Eu ia propor algumas idéias, mas, vejam só, já existem caracteres alternativos padrão para a divisão. Além de ÷ , que não está no teclado, descobri o seguinte:

O sinal de divisão também é matematicamente equivalente ao símbolo de proporção, normalmente denotado por dois pontos (:) e lido "é para". Assim, para qualquer número real x e qualquer número real diferente de zero y, esta equação é válida:

x ÷ y = x: y

Em outras palavras:

lost-column: 1/3;   //  value
lost-column: 1:3;   // division 

Eu sei que seria necessário um pouco de ajuste no analisador para usar dois pontos em matemática, mas _é_ matematicamente correto, aparentemente. Não consigo pensar em outros símbolos que seriam melhores substitutos. Talvez | como uma segunda opção? No entanto, seria mais arbitrário.

Pensamentos?

_Alternativamente_, ainda poderíamos suportar o símbolo de divisão entre parênteses e / ou colchetes, como em:

lost-column: 1/3;   //  value
lost-column: 1:3;   // division 
lost-column: (1/3);
lost-column: [1/3];

Sim, é por isso que inicialmente comecei com ./ (inspirado no operador vetor-div Matlab, são dois símbolos, mas visualmente é provavelmente o menos pesado por causa do ponto leve, embora no contexto de Menos estragamento, o ponto não é uma ideia brilhante).
: - Isto irá empurrar margaridas mais uma vez, este símbolo é usado em muitos contextos CSS. Na verdade, já existe uma sintaxe conflitante:

.foo(<strong i="9">@a</strong>: 1, <strong i="10">@b</strong>: 2) {
  result: <strong i="11">@a</strong> @b;  
}

bar {
    <strong i="12">@b</strong>: 4;
    .foo(<strong i="13">@b</strong>:3); // would mean both @second-parameter:3 and 4/3
}

@ sete-fases-máx. Ah, sim, droga. SE SÓ OS TECLADOS FORAM MAIORES. Sim, uma sequência de 2 caracteres para divisão parece inevitável. Já fazia muito tempo que eu não lia todo o tópico, então me esqueci disso. ./ Não é realmente ruim. Se você e @lukeapage estiverem a bordo, isso não será um mau acordo. Talvez passemos para o estágio de proposta e vejamos se há alguma objeção?

Lendo de volta, até este ponto:

sem contar, também requer um espaço em branco antes de . , por exemplo, 16 ./17 e não 16./17

Não tenho certeza se concordo. Sim, 16. é um número válido, tecnicamente, mas seria bizarro alguém escrever dessa forma. Eu acho que não importa como você escreveria, com espaço em branco ou não, ele deve dividir 16 por 17.

Não haverá uma opção perfeita, mas acho que é melhor do que a) Usar / para divisão por padrão, b) sempre exigindo parênteses. (Apesar de minhas posições no passado, também cheguei a conclusão de que sim, isso é meio chato, especialmente dentro de outros parênteses. E especialmente porque é necessário apenas por causa da divisão, que eu saiba. Sim?)

Eu acho que não importa como você escreveria, com espaço em branco ou não, ele deve dividir 16 por 17.

Sim, de fato.
Pensando mais nisso, espero que ./ coloque alguns truques adicionais no analisador (a análise de números precisará de uma análise mais detalhada para parar antes de ./ enquanto atualmente sempre começa a terminar . )

E principalmente porque só é necessário por causa da divisão, que eu saiba. Sim?)

Sim, exatamente. Sem contar o código dentro de calc - mas para este eu acho que a solução sugerida por @lukepage deve

(Tecnicamente, no futuro pode haver alguma ambigüidade adicional para +, -, * se eles permanecerem em sua sintaxe de funções de manipulação de cores CSS - mas isso não deve ser muito dramático, pois os valores lá têm a forma * 20% (portanto eles podem ser detectados claramente como alguma expr não avaliada por Menos. Depois de todos esses testes, serão necessárias algumas alterações de análise de qualquer maneira, já que valores atuais como (* 20%) causam erro de análise).

Talvez ... estivéssemos fazendo tudo errado. (Definitivamente me incluindo nesse grupo, já que fui um ávido defensor inicial do recurso de "matemática estrita".)

Estamos tentando fazer a matemática funcionar universalmente, mas ... realmente não é necessário. Ou seja, estamos tentando fazer matemática em casos em que deveria ser óbvio que nenhuma matemática deveria ser realizada.

O exemplo calc(100% - 10px) é o mais óbvio. Não há nenhum cálculo Less que pode / deve ser executado a menos que lançamos unidades, o que eu concordo que Less deve parar de fazer, por padrão. 1

Vejamos a propriedade abreviada da fonte usada como exemplo.

font: italic small-caps normal 13px/150% Arial, Helvetica, sans-serif;
font: italic bold 12px/30px Georgia, serif;

A solução atual para isso é transformar strict-math: on para a propriedade da fonte. Mas ... por que Less deveria fazer cálculos? Claro, 13px/150% é uma afirmação válida em matemática, mas é razoável tratá-la como válida em Less? 12px/30px você _poderia_ tratar como uma declaração matemática válida, mas deveria? 2

Ou seja: em Menos, as operações matemáticas em unidades devem ser realizadas por _integers_ e _floats_, não por unidades. Estamos tratando isso como afirmações matemáticas válidas, como se as pessoas estivessem realmente escrevendo sua matemática dessa maneira. Mas não vejo como isso seja possivelmente verdade.

Ou seja, é razoável exigir que alguém escreva 13px/150% como 13px/1.5 . E mesmo ignorando o fato de que 12px/30px não faria sentido como uma operação matemática, não precisamos saber que não é e não precisamos colocar font lista branca . Se um autor de Less estivesse fazendo uma operação matemática, ele razoavelmente a estaria escrevendo 12px/30 . Isso não apenas seria razoável, como também é uma probabilidade extremamente alta _como eles estão escrevendo em primeiro lugar_.

É comum para mim escrever um mixin ou mesmo usar algo assim em um único bloco:

width: <strong i="5">@size</strong> / 2;
height: <strong i="6">@size</strong> / 2;

Por que eu escreveria dessa maneira? _Alguém_ está escrevendo dessa maneira?

width: <strong i="10">@size</strong> / 2px;
height: <strong i="11">@size</strong> / 2px;

A operação _sort of_ faz sentido se @size é uma unidade px , mas, independentemente, faz menos sentido no domínio de MENOS / CSS tentar fazer matemática no último caso quando o divisor é um valor com uma unidade. O segundo não parece matemática. Parece um valor CSS.

Se parássemos de fazer operações matemáticas para multiplicação ou divisão (apenas divisão necessária para ambigüidade, mas multiplicação também para consistência lógica) quando o multiplicador ou divisor é um valor com uma unidade, acho que esse problema desapareceria em grande parte. Em contraste, as unidades _são_ lógicas para adição e subtração, mas provavelmente não precisam ser exigidas (que é como é agora).

<strong i="18">@pad</strong>: 2px;
width: 10px + @pad; 

Mas ao adicionar / subtrair um valor c / unidade para outro c / uma unidade diferente, Less deve deixá-lo sozinho.

<strong i="22">@val1</strong>: 100%;
<strong i="23">@val2</strong>: 10px;
width: calc(<strong i="24">@val1</strong> - @val2);

// output
width: calc(100% - 10px);

Exigir unidades correspondentes para adição / subtração (ou número inteiro / flutuante) e exigir números inteiros / flutuantes em operações matemáticas contra unidades (sem unidades multiplicadas / divididas por unidades) resolveria 99% das ambigüidades e ainda permitiria operações matemáticas válidas sem quaisquer novos símbolos .

Por exemplo, com base nessas regras, a abreviatura de fundo seria adequada:

background: no-repeat 10px 10px/80% url("../img/image.png");

% é uma unidade CSS. px é uma unidade CSS diferente. Portanto, nenhuma matemática. A exceção especial seria zero.

background: no-repeat 0 0/80% url("../img/image.png");

Se alguém parece estar dividindo zero por outro número, ou dividindo um número por zero, acho que podemos com segurança apenas produzir como está.

Limite de raio, mesma coisa:

border-radius: 30% / 20%;

Menos daria um passe. Se alguém pretendesse fazer matemática, a maneira apropriada de escrevê-la seria:

border-radius: 30% / 0.2;

O bom é que, ao fazer essas distinções, deveria ficar óbvio que uma operação matemática _não_ pode ser um valor CSS, uma vez que, como o exemplo border-radius , um valor CSS válido exigiria unidades em ambos os lados. Não haveria sobreposição / ambigüidade.

Exceto um caso em que consigo pensar, e pode haver outros:

font: 10px/1.5;

Você pode (e geralmente deve) representar a altura da linha como apenas um número. (Mas também provavelmente não deve usar abreviatura de fonte.) Mas se o reduzirmos a um caso, isso é muito bom. Ativar matemática estrita para font (exceto para funções internas dentro do valor da fonte) é uma solução correta. (Não tenho certeza se não há um melhor, mas funciona.) E ainda é a solução menos prejudicial, uma vez que esses valores abreviados de fonte geralmente aparecem em bibliotecas de estilo de IU importadas, redefinições de CSS ou folhas de estilo de fonte personalizadas.

Então, ainda existe um uso para a matemática estrita, mas acho que com essas mudanças, menos, e talvez não seja necessária como uma opção no futuro.

Agradeço as respostas / comentários da galeria.

1 _Eu percebi que deveria deixar claro que os comentários de @lukeapage e o link de @ seven-
2 _Como descobri enquanto olhava os exemplos, ativar a matemática estrita para a fonte pode ser uma solução inevitável, mas acho que o resto da lógica se aplica._

Apenas para alguns contextos históricos, é importante observar que lançar unidades quando Less.js foi lançado pela primeira vez não foi um grande problema. calc() não foi implementado, e background e border-radius não tinham barras como valores válidos. Acho que font foi o único lugar que tropeçou nas coisas (o que, ironicamente, pode ainda ser o caso).

Minha única preocupação é o lado da implementação, por exemplo: para calc(4px + 2rem + 20%) (unidades reais não importam), a primeira adição resulta em um resultado não mais numérico, portanto, o segundo manipulador de adição não consegue distinguir sua entrada de qualquer instrução not-a-number + 20% onde deveria gerar um erro. Provavelmente não é um grande problema (solucionável colocando sinalizadores de tipo / tipo extras), mas ainda precisa de alguma investigação.

E a outra preocupação é ehm, não tem certeza, "redabilty"? Ou seja, enquanto para números explícitos o resultado parece cristalino, para variáveis ​​começa a parecer bastante ambíguo, por exemplo: border-radius: 10px <strong i="8">@a</strong> / <strong i="9">@b</strong> 30px; - você nunca sabe o que isso significa até que você veja @a e @b definições.

E sim, font ainda continua sendo um problema (provavelmente outras propriedades abreviadas parecem usar unidades em ambos os lados, mas, novamente, nunca sabemos o que elas farão em seguida (também contando coisas como # 2769) ... A mais alguns itens como font e ele começará a parecer quebrado novamente).

PS Mais um problema (talvez uma pequena regressão). Existem valores como:

border-radius: 10px / auto;
border-radius: 1px inherit / 2px;
background: ... center / 80% ...;
// etc.

Ou seja, para que tudo funcione, teremos que desabilitar qualquer erro de operando-div incompatível atual para que qualquer foo/bar , 1x/bar e foo/1x possam passar sem erro.

Minha única preocupação é o lado da implementação, por exemplo: para calc (4px + 2rem + 20%) (unidades reais não importam)

Isso é o que estou dizendo. As unidades reais devem importar. Menos deve deixar isso de lado, independentemente. 4px + 2rem tem significado no navegador, mas não tem significado em Menos. Não há razão para tentar adicioná-lo quando não faz sentido e causa esses problemas de add-on.

por exemplo: border-radius: 10px <strong i="10">@a</strong> / <strong i="11">@b</strong> 30px ; - você nunca sabe o que isso significa até que veja as definições de @a e @b .

Este é um caso em que não podemos salvar o autor do estilo dele mesmo (o mesmo com o primeiro exemplo, se alguém realmente estava tentando adicionar rems aos pixels por algum motivo). Tenho certeza de que existem todos os tipos de exemplos em que alguém poderia escrever seu código LESS para ser confuso de seguir. Isso existe em qualquer lugar.

Com essas regras matemáticas que estou propondo, considere:
calc(4px + 2rem - 2px)

Less poderia / iria calcular isso como calc(2px + 2rem) , o que na verdade é perfeitamente normal e é, na verdade, uma saída de valor correto. No momento, Less o calcula como calc(4px) , o que não é uma resposta correta ou útil. (Sim, atualmente está correto se eliminarmos as unidades, mas as unidades não são insignificantes e, exceto em alguns casos, não são interoperáveis.) Menos calcula 2px + 100% como 102px , como se houvesse algum valor em esse resultado, quando ninguém possivelmente iria querer isso como resultado.

para que tudo funcione, teremos que desabilitar quaisquer erros de operandos-div incompatíveis atuais para que qualquer foo / bar, 1x / bar e foo / 1x possa passar sem um erro.

Acho que essa é a maneira mais saudável de tratar isso. Como funções, se não houver um resultado Less, ele deve passar. Como / é um separador válido para mais de um valor de propriedade, Less não pode saber que _não_ é válido, a menos que adicionemos valores na lista de permissões para propriedades específicas. (Não.) Nesse ponto, o resultado não é trágico. Se um valor de passagem for inválido no navegador, é visualmente aparente. Parece melhor tentar passar o valor para o navegador, caso seja válido, do que lançar um erro porque Less não tem certeza.

Menos poderia / iria calcular isso como calc (2px + 2rem)

Temo que nunca será, pois isso exigirá um novo manipulador de expressão de otimização que seria um exagero (basicamente 4px + 2rem - 2px está armazenado na árvore como (4px + 2rem) - 2px para obter 2px + 2rem tem que ser um mecanismo de reordenamento para tentar todo embaralhamento válido (trivial neste caso particular, mas se tornando bastante complexo para mais operandos / operadores). Mas não importa, deixar 4px + 2rem - 2px como está é bom (depois tudo se você fizer 4px - 2px + 2rem , será otimizado).

Mas o que eu realmente quis dizer com essa observação é algo semelhante a:

de modo que qualquer foo / bar, 1x / bar e foo / 1x pode passar sem erro.

Ou seja, (4px + 2rem) - 2px para o expr.evaluator seria semelhante a foo + 2px , portanto, para funcionar, ele não deve gerar erros para esse tipo de coisa também.
Na verdade, eu testei foo/bar, 1x/bar, foo/1x e eles já passam sem erros (estranho, achei que eles jogam), mas outros operadores resultam em todos os tipos de coisas estranhas (nada realmente crítico, porém, apenas uma questão de consertar cada caso um por um).

Receio que nunca será, pois isso exigirá um manipulador de expressão de otimização totalmente novo que seria um exagero (basicamente 4px + 2rem - 2px está armazenado na árvore como (4px + 2rem) - 2px para obter 2px + 2rem para ser um mecanismo de reordenamento para tentar todo embaralhamento válido (trivial neste caso particular, mas tornando-se bastante complexo para mais operandos / operadores).

Por que embaralhar? Você nivela os operadores no mesmo nível de precedência (de forma que a árvore seja Sum(4px, 2rem, -2px) ), coleta termos com unidades compatíveis (talvez normalizando unidades de antemão) e simplifica cada parte. É álgebra simbólica, onde as unidades são tratadas como variáveis ​​independentes.

Eu gostaria de escrevê-lo sozinho, mas existem muitas bibliotecas por aí que são provavelmente mais bem testadas e com maior probabilidade de estarem completas. Aposto que alguns compiladores de otimização de código aberto escritos em Javascript têm esses subsistemas de simplificação.

O ponto é que, embora este não seja um problema fácil de resolver, o problema mais geral já está muito bem resolvido e tal subsistema poderia ser útil para Less.js de outras maneiras.

Você nivela os operadores no mesmo nível de precedência (então a árvore é Soma (4px, 2rem, -2px)),

E o que exatamente faz o código pensar que alguma árvore de expressão é realmente nivelável? (Portanto, meu "sufocamento" não é sobre algum algoritmo de dedução específico, mas um atalho para "tente todos eles", incluindo seu "nivelar").

mas existem muitas bibliotecas por aí que são provavelmente mais bem testadas e com maior probabilidade de serem completas.

Não tenho certeza se você está falando sério. Então você acha que todo o código para converter a árvore Less em uma árvore lib externa e vice-versa (sem contar que nenhuma dessas libs JS pode lidar com unidades CSS) realmente vale aquele 4px + 2rem - 2p caso específico a ser otimizado? Hum...

Então, sem problemas (eu não disse que é impossível, apenas que nunca valerá a pena) - experimente e RP é bem-vindo.
(Também por precaução, é provavelmente importante notar que a otimização da subexpressão nem mesmo é o objetivo deste tíquete, nem mesmo entre os três primeiros).

E o que exatamente faz o código pensar que alguma árvore de expressão é realmente nivelável? (Portanto, meu "sufocamento" não é sobre algum algoritmo de dedução específico, mas um atalho para "tente todos eles", incluindo seu "nivelar").

O analisador determina se o contexto é, por exemplo, "comprimento" e se a subárvore pode ser interpretada como "comprimento".

Não tenho certeza se você está falando sério. Então você acha que todo aquele código para converter a árvore Less em uma árvore lib externa e vice-versa

Ele precisa ser analisado em uma árvore de sintaxe. A partir daí, seria relativamente simples gerar uma string representando uma expressão algébrica. Voltar pode ser mais difícil: pode ser necessário analisar novamente a partir de uma string ou, sim, pode ser necessário usar a árvore da biblioteca externa. A dificuldade depende de qual biblioteca é escolhida.

(sem contar que nenhuma dessas bibliotecas JS pode lidar com unidades CSS)

Você apenas converteria unidades em variáveis ​​algébricas. Substituições (por exemplo, mm -> px ) podem até ser feitas enquanto a expressão está na forma simbólica.

vale a pena aquele caso específico 4px + 2rem - 2p para ser otimizado?

Estou fazendo uma sugestão alternativa para otimização de expressão que é menos difícil (como um problema de algoritmo que o próprio código de Less deve resolver) e mais geralmente útil do que o que você disse ser necessário.

A simplificação algébrica pode resolver coisas com subexpressões entre parênteses e permitir que Less adicione mais recursos matemáticos.

tente e PR é bem-vindo.

Eu vou tentar. Só comecei a pesquisar o Less hoje e estou com problemas para terminar projetos, então admito que provavelmente não vou divulgar um PR.

Além disso, por precaução, é provavelmente importante notar que a otimização da subexpressão nem mesmo é o objetivo deste tíquete, nem mesmo em seus três primeiros

Eu sei. Eu estava aqui por um dos motivos. Por que essa mordida?

Por que essa mordida?

Bem, talvez ... Em caso afirmativo - minhas desculpas (Parece que estou muito chocado com os esforços e tempo que alguém está pronto para dedicar para resolver o problema praticamente inexistente de calc(4px + 2rem - 2px) . Provavelmente temos uma noção muito diferente de leveza).

e permitir que Less adicione mais recursos matemáticos.

Você poderia citar alguns?

para resolver o problema praticamente inexistente de calc(4px + 2rem - 2px)

Huh? Less não consegue lidar com isso. [restante excluído porque eu entendi mal o que estava sendo tratado]

Para simplificar / reformular a proposta - as alterações matemáticas seriam as seguintes

  1. Adição e subtração seriam calculadas apenas em unidades semelhantes. por exemplo, 1px + 2px = 3px , 1px + 1vh = 1px + 1vh
  2. A divisão e a multiplicação seriam calculadas apenas com divisores / multiplicadores sem unidades. por exemplo, 10px/2 = 5px , 10px/5px = 10px/5px
  3. Relações de valor sem unidades seriam tratadas de forma semelhante a # 2. por exemplo, 1/3 = 1/3
  4. Para simplificar, as expressões com subexpressões parcialmente inválidas podem ser tratadas como expressões matemáticas inválidas e geradas no estado em que se encontram. por exemplo, 1px + 2vh / 2 = 1px + 2vh / 2

Esta proposta resolve o seguinte (deste tópico):

  • font: 10px/5px e sintaxe semelhante (proporção) (sem cálculo)
  • calc(100vh - 30px) (sem cálculo)
  • lost-column: 1/3 e sintaxe de proporção personalizada semelhante (sem cálculo)

Ao mesmo tempo, essas mudanças preservariam 99% do uso típico de matemática do Less. Da mesma forma, as funções unit() e convert() permitem que os usuários convertam valores em unidades compatíveis para matemática.

Less não consegue lidar com isso.

Você simplesmente não leu o que eu e @leewz conversamos acima. Não teve nada a ver com calc(100vh - 30px) . E meu "resolver praticamente um problema inexistente" vai unicamente para "otimizar expressões aritméticas em calc ".

@ sete-fases-max Ohhh certo isso. Desculpe. Não, não precisamos otimizar. Apenas descubra quando fazer matemática.

Este problema foi marcado automaticamente como obsoleto porque não teve atividades recentes. Ele será fechado se nenhuma outra atividade ocorrer. Obrigado por suas contribuições.

Removendo o rótulo do slate, uma vez que o problema ainda é importante e piorando à medida que o CSS evolui.

@ matthew-dean
Vou bancar o advogado do diabo por um momento aqui ...

12px/30px você _poderia_ tratar como uma declaração matemática válida, mas deveria?

Sim; você deve. Ele calcula um valor escalar que representa uma razão entre os dois tamanhos e que pode ser bastante útil ao converter para a unidade em.

Digamos que eu tenha um tamanho de fonte de base conhecido de 16 px e um tamanho de cabeçalho conhecido de 24 px, ambos inseridos em variáveis, e depois quero atribuir um tipo específico de título com o tamanho de fonte correto, mas em uma unidade em.

@fontsize-body    : 16px;
@fontsize-heading : 24px;

// ( ... and then somewhere else ... )

.heading {
  font-size : unit(@fontsize-body/@fontsize-heading, em);

  // Or if dividing compatible unit values is produces a unit-less scalar
  // value ( as it really _should_ -- mind you... ),  you could prefer:
  font-size : @fontsize-body/@fontsize-heading * 1em;
}

E se você precisar oferecer suporte à divisão de unidades compatíveis como uma expressão matemática, você continuará a precisar oferecer suporte a uma maneira de remover a ambigüidade do CSS literal das expressões matemáticas do Less para cobrir cada metade dos casos.

Agora concedido, isso pode envolver o uso de parênteses para forçar uma expressão matemática e tomar um CSS literal por padrão. Mas isso parece errado e sujeito a erros. Requer muitos casos especiais pré-cozinhados, como em border-radius e font atalhos, e requer que Less se mantenha continuamente atualizado sobre eles. (Como foi ilustrado por algumas das novas propriedades da grade desenvolvendo o mesmo problema com o sinal de divisão.)

Assim...

Por que não inverter seu raciocínio? Se algo se parecer com uma expressão matemática e tiver unidades compatíveis, será tratado como uma expressão matemática por padrão. E se você não quer que isso aconteça ... bem; em seguida, use a escotilha de escape ~"..." . Afinal, é exatamente para isso que existe ...

Minha visão atual da proposta:

  • Pare de tratar / como divisão em qualquer
    Assim, apenas 1anything./3whatever e (opcionalmente) (1anything/3whatever) são avaliados por Less.
  • + , - e * permanecem inalterados
  • calc é resolvida pela não avaliação de nenhum aritmo. expressões dentro de calc(...) (embora, mais uma vez, parênteses redundantes também possam ter seu efeito).

@ sete fases-máx.

O problema com isso é que / está incrivelmente arraigado como o operador de divisão. Usar qualquer outro símbolo para isso seria difícil de vender para os usuários. Você está pegando o caso de uso geral e jogando-o fora para o caso de uso excepcional ( / em abreviações CSS) que quase ninguém usa.

@rjgotten

O problema com isso é / está incrivelmente arraigado como o operador de divisão.

Não em CSS.

para o caso de uso excepcional (/ em abreviações CSS) que quase ninguém usa.

Por agora / já é muito usado, e em comparação é o Less div op é totalmente muito mais excepcional do que CSS / hoje em dia (ao contrário de apenas alguns anos atrás, onde CSS / podem ser encontrados principalmente em font apenas).

@ seven-phase-max Obrigado por manter-se atualizado. Eu adicionei o bot Stale para nos ajudar a gerenciar problemas e dei uma quantidade de tempo bem generosa para marcar como obsoleto. Também isentei dois rótulos, "bug" e "disponível". Quaisquer sugestões sobre isso são bem-vindas, como outros rótulos para a lista de permissões. O arquivo está aqui: https://github.com/less/less.js/blob/3.x/.github/stale.yml

Voltando ao tópico do problema ...

@rjgotten
Seu caso de uso cria um problema arbitrário. O argumento é que é útil. Mas estruturar seu vars dessa forma cria um problema que pode ser evitado com a sintaxe que é, como @ seven-phase-max apontou, ambígua.

Mesmo considerando o valor de face, com CSS como o guia para os princípios do Less, você não pode, no cálculo, dividir 12px por 30px. Fazer isso no Less não apenas cria um problema de ambigüidade, mas rompe com o modelo sem um bom motivo (exceto histórico). Provavelmente, uma das coisas que está faltando em Less é apenas uma maneira de extrair o valor numérico de um valor unitário para que Less não tenha que fazer essa mágica matemática para divisão.

Portanto, a resposta simples é que seu exemplo seria algo como:

font-size : @fontsize-body/number(@fontsize-heading) * 1em

Mas estou bem com a proposta do @ seven-phase-max também. Ainda poderíamos avaliar _vars_ em calc() , mas não em matemática. E não avaliar a divisão fora dos parênteses. Acho que é um bom compromisso. E, possivelmente, se você quisesse preservar a matemática da divisão mágica de dividir uma unidade por uma unidade, mas mantendo a unidade (o que ainda é estranho, mas tudo bem), isso poderia acontecer entre parênteses.

Sei que existem algumas preferências diferentes sobre matemática no Less, mas acho que seria ótimo se pudéssemos chegar a um consenso sobre algo que causasse menos efeitos colaterais e fosse o mais fácil de raciocinar sem causar uma grande manutenção ou carga de desenvolvimento.

Acho que estamos todos na mesma página que a abordagem atual (padrão) da matemática no Less está quebrada. E recebemos o feedback de que parênteses - tudo como padrão era mais fácil de raciocinar, mas era pesado. Portanto, espero um bom meio-termo que possamos colocar como padrão em breve (provavelmente no 4.0?)

Provavelmente, uma das coisas que está faltando em Less é apenas uma maneira de extrair o valor numérico de um valor unitário

A função unit realmente faz isso se você não especificar um segundo parâmetro. Mas isso é mais um efeito colateral do fato de que os escalares são atualmente implementados com um tipo de nó Dimension que não tem uma unidade definida.

Garantido; é o caminho mais longo, mas se você _realmente_ deseja evitar dividir dimensões que têm unidades compatíveis, então separar a unidade funcionaria.

Eu também acrescentaria que sou fortemente contra qualquer suposição de "unidades compatíveis" (como deixar a/b continuar sendo uma divisão e b/c não ser) neste contexto particular.
Simplesmente porque:

  • tratamento excepcional é a raiz de todos os males (por exemplo, # 3047 - veja abaixo, http://stackoverflow.com/questions/19705791- Lembro que não consegui encontrar a razão para o problema do SO até que realmente pisei em cada uma das zilhões de linhas do código Less envolvido em um depurador).
  • e o mais importante, não é à prova de futuro, ou seja, se uma grande mudança for inevitável, é melhor garantirmos que seja feita uma vez (e idealmente para sempre) ... e não como se eles adicionassem algum novo recurso CSS envolvendo a/b e está quebrado novamente.

Então, para mim, o material de "Unidades Compatíveis" é mais algo totalmente não relacionado e ortogonal (pode haver algumas discussões sobre unidades resultantes com ou sem -su , mas isso é outra história).


(fora do assunto:)
E aliás, falando dos exemplos acima:
@rjgotten se você tiver:

@fontsize-body/@fontsize-heading * 1em; 

em algum lugar do seu código e qualquer uma das duas variáveis ​​está px você está realmente usando um bug :)
O código adequado é:

1em * @fontsize-body/@fontsize-heading;

Isso sempre resulta em uma unidade bem definida por http://lesscss.org/features/#features -overview-feature-operations (contando # 3047 para ser corrigido, o bug é mais uma vez um exemplo de um bug produzido exatamente por excesso código de adivinhação em torno de "unidades compatíveis" na base de código). Não há necessidade real de --su , number , unit bla-bla ... Comportamento -su atual como "apenas lançar um erro se você vir unidades incompatíveis" , ou seja, uma validação simples, é mais do que bom (para mim). Não vejo necessidade de superengenharia de 1px/2px->.5 e 1px*2px->2px^2 mambo-jambo. Mas, mais uma vez, esta é outra história não relacionada).

@ sete fases-máx.

realmente usando um bug

Uhm .. sim; você está certo, é claro. Felizmente, não tenho esse código em produção em lugar nenhum. Foi apenas um exemplo rápido combinado para ilustrar o ponto.

Eu também acrescentaria que sou fortemente contra qualquer suposição de "unidades compatíveis" (como deixar a / b permanecer como uma divisão eb / c não ser) neste contexto específico.

Acho que concordei com isso mais como um ramo de oliveira para quem quer divisores nus. Mas acho que seu comentário [ aqui ] é a proposta mais viável. Era a intenção original da "matemática estrita" eliminar a ambigüidade. Eu acho que a preocupação passou a ser operações dentro do mixin e chamadas de função levando a todos os tipos de parênteses dentro dos parênteses. Mas, em geral, estou com você que os esforços para tornar a matemática mais fácil no Less também, ironicamente, tornou-a muito difícil, devido ao aumento da ambigüidade.

Além disso, mais tarde percebi que font: 10px/3 é uma abreviação válida. Portanto, não há realmente nenhuma solução algorítmica que possa ajudar nisso.

Para voltar à sua pergunta, @rjgotten ...

Por que não inverter seu raciocínio? Se algo se parecer com uma expressão matemática e tiver unidades compatíveis, será tratado como uma expressão matemática por padrão. E se você não quer que isso aconteça ... bem; em seguida, use a saída de emergência ~ "...". Afinal, é exatamente para isso que existe ...

A ideia / relacionamento de Less para CSS é semelhante a TypeScript para JavaScript. Ou seja, renomeie seu .css válido para .less e você pode começar a adicionar menos recursos. Semelhante a como você pode renomear .js para .ts e começar a adicionar recursos do TypeScript. Se você não adicionar nada, deverá obter a saída do mesmo Less / JavaScript válido, porque as linguagens são superconjuntos da linguagem base.

No entanto, no caso dessas proporções ou outros divisores / em CSS, Less já falha logo de cara, por padrão. Seu CSS regular torna-se arbitrariamente uma expressão matemática Less com um resultado diferente, mesmo que você não tenha alterado nada. Isso viola o contrato do idioma. Ser capaz de mudar seu .less em uma expressão Less totalmente diferente a fim de recuperar o CSS original com o qual você começou perde o ponto. Esse trabalho nunca deve ser exigido. O Less não deve exigir que você altere seu CSS válido para expressões Less compatíveis a fim de obter de volta o CSS válido que você tinha em primeiro lugar. Esse é apenas um modelo quebrado.

O mesmo raciocínio se aplica a calc() . Sim, você pode escapar de suas expressões, mas não deveria. .css renomeado para .less deve produzir o mesmo CSS eficaz. Este deve ser o objetivo básico do projeto, para não interferir / sobrescrever / superinterpretar a folha de estilo original. Qualquer outra coisa é tentar empurrar o problema para o desenvolvedor por nenhum outro pecado do que usar o analisador / linguagem em primeiro lugar.

Sim, você pode escapar de suas expressões, mas não deveria. .css renomeado para .less deve produzir o mesmo CSS eficaz. Este deve ser o objetivo básico do projeto, para não interferir / sobrescrever / superinterpretar a folha de estilo original. Qualquer outra coisa é tentar empurrar o problema para o desenvolvedor por nenhum outro pecado do que usar o analisador / linguagem em primeiro lugar.

Que.

MENOS sabe onde / é permitido e onde não está no css. Onde não está, mas aparece de qualquer maneira, deve assumir que a matemática foi feita. Além disso, onde a matemática é cercada por colchetes, onde colchetes não são permitidos em css, deve ser interpretado por MENOS.

Em outras palavras, o LESS deve tentar interpretar o mínimo de matemática possível para chegar a um CSS válido. Assim que a saída for válida, pare de executar mais cálculos matemáticos.

@thany

Muitas suposições sobre o que o compilador sabe (e algumas delas estão simplesmente erradas).
De qualquer maneira, o modo "colchetes" é quase o que --sm=on faz, então use-o e esqueça este tópico (provavelmente você não está usando nenhuma matemática em seus projetos além de calc (introduziu alguns anos depois de Less ser projetado), então você não pode ver como os parênteses extras são irritantes. Mas outros vêem.)


Para o resto, consulte https://github.com/less/less.js/issues/1880#issuecomment -345194431.

@ seven-phase-max Não se esqueça de que / também tem significado em background e border-radius abreviações e possivelmente outras que não estou pensando agora. A LESS ficará feliz em tratá-los como uma divisão. Com ou sem o modo matemático estrito, o LESS deve "saber quando parar" de fazer suas próprias pequenas contas.

@thany
LESS deveria "saber quando parar" de fazer suas próprias pequenas contas.

Não, não deveria. Não há como saber onde as futuras abreviações CSS com a barra de divisão aparecerão. Ter o compilador Less 'sabendo' sobre isso é uma abordagem fundamentalmente falha e a mesma coisa para a qual esta discussão está tentando encontrar uma solução.

Além disso, existem duas escolhas sensatas e previsíveis para / como um operador de divisão:

  • Sempre trate-o como tal e exija escape explícito para outros usos.
    Isso interromperá o comportamento em que a sintaxe Less é um superconjunto estrito da sintaxe CSS.
  • Nunca o trate como um operador de divisão, __a menos que esteja dentro de um contexto matemático conhecido.
    Onde o contexto matemático conhecido poderia / seria decidido como no comportamento atual de --strict-math=on .

(Além disso, observe que o nome Less não está mais escrito em maiúsculas.)

Não se esqueça de que / também tem significado nas abreviações de background e border-radius,

É basicamente com isso que este tópico começa.
E veja o resumo das alterações propostas em https://github.com/less/less.js/issues/1880#issuecomment -345194431 (sem quaisquer suposições sobre o que o compilador deve ou não deve saber).

Não, não deveria. Não há como saber onde as futuras abreviações CSS com a barra de divisão aparecerão. Ter o compilador Less 'sabendo' sobre isso é uma abordagem fundamentalmente falha e a mesma coisa para a qual esta discussão está tentando encontrar uma solução.

Eu concordo totalmente com isso. @thany Embora você tenha concordado comigo no que citou do que escrevi, você está chegando a uma conclusão diferente da que eu faria. Less não deve e não pode saber quando "parar de fazer matemática". O que eu diria é que a mudança decisiva deve ser que Less é mais conservador sobre começar a matemática (para usar o americano / canadense) em primeiro lugar.

@rjgotten

Nunca o trate como um operador de divisão, a menos que esteja dentro de um contexto matemático conhecido.
Onde o contexto matemático conhecido poderia / seria decidido como no comportamento atual --strict-math = on.

Só para esclarecer, esta parte (com a qual concordo):

Nunca o trate como um operador de divisão, a menos que esteja dentro de um contexto matemático conhecido.

Na verdade tem 4 soluções possíveis, que eu sei que você conhece, mas apenas resumindo para o tópico:

  1. Faça todas as contas apenas entre parênteses . Aparentemente, isso foi rejeitado pelos comuns, o que é bom, embora ainda esteja disponível como uma alternância opcional ( strictMath ).
  2. Faça toda a matemática em todos os lugares, mas divida apenas entre parênteses.
  3. Faça toda a matemática em todos os lugares, mas divida apenas entre parênteses. A menos que o operador de divisão seja impresso como ./
  4. Faça toda a matemática em todos os lugares, mas conserte a matemática para que 12px/4px não resulte em divisão. (Multiplicação e divisão apenas com valores sem unidades.) Em outras palavras, divisão em todos os lugares, mas com regras muito mais conservadoras. Nos casos em que não resolve, volte a fugir. Portanto, não é uma solução completa, mas ainda uma (discutível) melhoria em relação à situação atual.

Do ponto de vista da usabilidade, gosto de tornar a matemática "mais inteligente", como em #4 . Do ponto de vista de engenharia e manutenção, e para proteção contra futuras alterações de CSS, considero #3 a solução mais robusta.

No entanto, acho que, na realidade, precisaríamos fazer #3 E #4 para consertar calc() . No momento, menos ignorar todas as unidades ao fazer matemática é uma verdadeira bagunça. 100vh - 12px nunca deve ser tocado por Less (parênteses ou não). Mas a IMO também não deveria 12px/4px (parênteses ou não), mas posso estar em minoria nesse caso.

Portanto, não vejo isso tanto como um problema de "matemática em conflito com a sintaxe CSS", mas sim como Less sendo excessivamente agressivo ao resolver equações matemáticas prematuramente.

Multiplicação e divisão apenas com valores sem unidades.

não vai funcionar, pois existem coisas como:

font: small-caps bold 24px/3 ...;
lost-column: 1/3;
// etc.

e eles não são divs.

No entanto, acho que, na realidade, precisaríamos fazer #3 E #4 para consertar calc()

calc() é um saco. Ironicamente, é _provavelmente_ melhor resolvido implementando-a como uma função Less real, que idealmente pegaria sua árvore de expressão analisada e tentaria simplificar a expressão. Isto é: ele deve pré-computar e combinar componentes compatíveis como 4px + 12px (ou 4px + @a quando @a é conhecido por ter um valor de pixel), mas deixa componentes incompatíveis, por exemplo, aqueles com unidades incompatíveis, sozinho.

Por exemplo

<strong i="17">@a</strong> : 4px;
<strong i="18">@b</strong> : 2;
width : calc(100%/<strong i="19">@b</strong> - 10px + @a);

deve eventualmente renderizar

width : calc(50% - 6px);

(repetindo-me em https://github.com/less/less.js/issues/1880#issuecomment-345345735)
E não vejo nenhum benefício em fazer uma engenharia excessiva do compilador para otimizar as expressões dentro de calc . Se você está escrevendo calc então está tudo bem com o navegador para fazer o trabalho, seja qual for a expressão longa que você tiver lá. Como já mencionado acima, eu sou a favor de "não toque em nada dentro de calc " (= não tente ser mais inteligente do que o necessário) e deixe-o para o navegador ( ou para um minificador de css desde , se bem me lembro, alguns deles já fazem um trabalho muito bom na otimização de subexpressões calc).


O "comportamento de unidade inteligente mamabo-jambo" me lembra dos monstros min/max (pilha inchada de código não sustentável e nunca usado ) - o quanto eu lamento não ter gritado contra as "unidades mambo" naquela época , oh (então vou continuar reclamando aqui até que a própria ideia de "semântica de operador diferente dependendo das unidades de operando" seja totalmente aniquilada: P).


PS Assim que calc se tornar uma função recebendo uma expressão não avaliada por aritmo (terá que fazê-lo de qualquer maneira), será possível escrever um plugin e substituí-lo com qualquer otimização desejada.

@rjgotten
Ter o compilador Less 'sabendo' sobre isso é uma abordagem fundamentalmente falha

Acho que é uma abordagem fundamentalmente correta . LESS é um compilador para CSS, então faz todo o sentido do mundo que LESS saiba para o que está compilando.

@ matthew-dean
Less não deve e não pode saber quando "parar de fazer matemática". O que eu diria é que a mudança decisiva deve ser que Less é mais conservador sobre começar a matemática (para usar o americano / canadense) em primeiro lugar.

Interessante você pensar nisso do outro lado, por assim dizer. Aqui está o que estou propondo:

background: url(...) no-repeat 50% 50% / 40px + 10px 40px;

O que LESS deve fazer aqui é óbvio para mim:

background: url(...) no-repeat 50% 50% / (40px + 10px) 40px;

Resultando em:

background: url(...) no-repeat 50% 50% / 50px 40px;

Não deve calcular a parte 50% / 50px nisso, porque (1) não deve ser capaz por causa de unidades incompatíveis e (2) porque isso já está longe o suficiente para um background . Então é aqui que ele vai "parar de fazer matemática".

Isso é o que eu quis dizer com MENOS "saber quando parar".

Se fosse uma propriedade diferente como esta:

padding-left: 50% / 10px + 5px;

Deve interromper com um erro (unidades incompatíveis). Uma saída possível seria 50% / 15px que é inválido para esta propriedade. Outro resultado poderia ser 5% que acontecerá atualmente, o que é errado em todas as direções.
E:

padding-left: 50px / 10px + 5px;

Deve resultar em:

padding-left: 10px;

Como esperado. Portanto, neste caso, / é inválido para padding-left e é levado para MENOS e faz suas contas matemáticas.

@ matthew-dean
Na verdade tem 4 soluções possíveis, que eu sei que você conhece, mas apenas resumindo para o tópico:

Mais um:
5) Use o operador \ para divisões em LESS e desative o uso de / . O MATLAB tem algo parecido com isso, e certos sabores do BASIC o usavam para forçar a divisão inteira. Portanto, usar a barra invertida não é algo totalmente inédito.

/editar
Também podemos fazer lobby para incluir uma chave ÷ nos teclados e usá-la como o operador de divisão. Foi isso que aprendi na escola primária :)

O que você sugere já foi discutido muitas vezes antes (não hesite em olhar os tópicos referenciados aqui). Então, aqui estão apenas comentários minúsculos preguiçosos:

Use o operador \ para divisões em LESS e desative o uso de / .

https://github.com/less/less.js/issues/1872#issuecomment -35245890

o suficiente para background ... é inválido para padding-left

Conheça o "Pessoal, meu navegador / polyfill / qualquer que seja o suporte adicionado / atualizado / expandido para uma propriedade fnord , vocês podem lançar uma nova versão do Less para mim?" emitir.
Conheça o problema de font .
etc etc.
Bem, @rjgotten já comentou acima sobre porque esse tipo de "conhecimento" é o caminho para lugar nenhum.

@ sete fases-máx.
A barra invertida foi apenas uma sugestão. Você também pode usar ? para divisão. Realmente não importa. O que estou sugerindo, eu acho, é não usar um caractere ( / ) que tenha significados muito diferentes e ambíguos.

Conheça o "Pessoal, meu navegador / polyfill / qualquer que seja o suporte adicionado / atualizado / expandido para uma propriedade fnord , vocês podem lançar uma nova versão do Less para mim?" emitir.

CSS é um padrão bem definido. Você não deve apoiar nada fora do padrão. Esse é o seu problema, eu sinto. Você não deve apoiar a propriedade fnord , porque ela não faz parte de nenhum padrão. Quando esta nova propriedade não especificada acontece, LESS pode voltar ao seu comportamento padrão, que poderia ser o atual, ou requerendo parênteses, ou qualquer outra coisa, desde que não seja ambíguo.

Conheça o problema da fonte.

O problema da fonte prova que o problema / existe desde o início absoluto do LESS. Não apenas quando background teve a capacidade de incluir um valor para o tamanho do fundo ou quando border-radius surgiu. Tbh, ao declarar o problema da fonte, você acabou de fazer o melhor argumento contra si mesmo :)

Tbh, ao declarar o problema da fonte, você acabou de fazer o melhor argumento contra si mesmo :)

Eu acho que você entendeu mal alguma coisa. Fui eu quem inicialmente propôs remover totalmente / como um operador div. Então, para o resto das coisas, suponho que seja o mesmo problema de você não prestar atenção ao que responde.

CSS é um padrão bem definido.

Se você for se ater às partes da especificação que atingiram a maturidade completa no nível TR, talvez.
De outra forma? Não, não é. Existem especificações de satélite de novos 'módulos' CSS e revisões de módulos existentes com novas adições a eles aparecendo mensalmente, se não semanalmente.

@ sete fases-máx.

não vai adiantar, pois há coisas como: fonte: versalete negrito 24px / 3 ...

Não, eu entendo. Meu ponto era exatamente isso: apenas div / multiplicação sem unidade diminui o problema, mas não o resolve.

E eu acho que em geral sua sugestão de ./ para todas as divisões ainda parece bastante lógica.

@thany Em vez de responder a todos os exemplos específicos, direi que, em geral, os esforços para tornar a matemática menos inteligente apenas irão chutar a bola para uma linha de jarda diferente. Ainda são os mesmos problemas, só que em um lugar diferente. Como @ seven-phase-max disse, nada do que você sugeriu não foi discutido.

E eu não vejo nenhum benefício em exagerar na engenharia do compilador para otimizar as expressões dentro do calc. Se você está escrevendo calc, então está tudo bem com o navegador para fazer o trabalho, seja qual for a expressão longa que você tiver lá. Então, como já mencionei acima, eu sou a favor de "não toque em nada dentro do calc" (= não tente ser mais inteligente do que o necessário) e deixo para o navegador (ou para um minificador de css, se bem me lembro , alguns deles já fazem um bom trabalho na otimização de subexpressões calc).

Eu concordo inteiramente com isso. Mataríamos 99% das novas questões relacionadas à matemática se apenas colocássemos calc() lista de permissões. Embora eu tenha sugerido algumas maneiras de Less fazer matemática de maneira mais inteligente para TAMBÉM evitar calc() problemas (o que talvez devesse), peço desculpas se isso foi interpretado como um argumento contra essa ideia. Eu também apoio isso.

A única ressalva (conforme discutido aqui / em outro lugar) é que um desenvolvedor inevitavelmente desejará usar variáveis ​​em calc() , então precisamos ter cuidado para ter certeza de que continuaremos a trocar vars, mas simplesmente não o faça matemática. Não tenho certeza de como isso é desafiador. Se conseguíssemos fazer isso, eu apoiaria uma mudança na manipulação de calc() hoje.

@thany

O problema da fonte prova que o problema / existe desde o início absoluto do LESS.

Isso pode ser verdade e é um ponto justo, mas havia muitas soluções alternativas adequadas e não era necessariamente uma prática padrão na época usar a abreviação da propriedade font . Na verdade, é o fato de que vários fundos e calc() chegaram depois que Less começou que tornou isso mais um problema, e agora a sintaxe CSS Grid significa que agora há uma tonelada de conflito onde inicialmente nenhum existia em termos práticos do dia-a-dia.

Aliás, é assim que Sass resolve o problema, ilustrado por este exemplo:

p {
  font: 10px/8px;             // Plain CSS, no division
  $width: 1000px;
  width: $width/2;            // Uses a variable, does division
  width: round(1.5)/2;        // Uses a function, does division
  height: (500px/2);          // Uses parentheses, does division
  margin-left: 5px + 8px/2px; // Uses +, does division
  font: (italic bold 10px/8px); // In a list, parentheses don't count
}

Não é um um-para-um, já que você pode fazer matemática (atualmente) dentro dos argumentos das funções Less, as funções E Less podem retornar valores de pixel (então Less poderia fazer font: print10px()/8px , teoricamente? Não?), Então eu estou apenas colando ilustrativamente, não como qualquer tipo de sugestão. É interessante como eles abordaram o problema.

Pessoalmente, acho que fazer os desenvolvedores tentarem se lembrar em quais casos a matemática ocorrerá com base na existência de expressões mágicas é uma espécie de loucura (como ser antecipado por um + ?), Mas para cada um deles. .

Pessoalmente, acho que fazer os desenvolvedores tentarem se lembrar em quais casos a matemática ocorrerá com base na existência de expressões mágicas é uma espécie de loucura

+1


Sem contar que a "solução" não resolve lessc --sm já resolve. E resultados diferentes para 1/2 e $var/2 é simplesmente fenomenalmente brilhante ... ~ estupidez ~ "Boa depuração, perdedores!"

@ matthew-dean
Aliás, é assim que Sass resolve o problema, ilustrado por este exemplo:

É uma solução brilhante sem recorrer a um operador diferente.
Se a expressão for possivelmente CSS válida, deixe-a.

Pessoalmente, acho que fazer os desenvolvedores tentarem lembrar em quais casos a matemática ocorrerá com base na existência de expressões mágicas é uma espécie de loucura

Discordo. É um conjunto simples de regras, não diferente de quaisquer outros conjuntos de regras (malucas ou não) que você precisa lembrar.

Existem alguns casos extremos em que a matemática ocorre sem querer, mas então você apenas aplicará parênteses e pronto.

Sem contar que a "solução" não resolve nenhum dos problemas discutidos aqui além do que o lessc --sm já resolve. Por que escreveria 0 + 1/2 em vez de (1/2) quando o que quero é apenas uma divisão? E resultados diferentes para 1/2 e $ var / 2 é simplesmente uma estupidez ... estupidez "Boa depuração, perdedores!" mensagem.

Ha, sim, isso.

@thany

É uma solução brilhante sem recorrer a um operador diferente.
Se a expressão for possivelmente um CSS válido, deixe-o.

Não é para entrar no mato, mas não vai funcionar para o Less, por razões sintáticas e também consistência de linguagem. Pode ser brilhante para Sass, o que eu diria que é discutível, mas não estou pessoalmente envolvido com esse projeto do ponto de vista do design, então quem pode dizer. Tudo o que sei é que as opções em cima da mesa são o melhor lugar para começar, e tenho certeza de que se você gastou tanto tempo examinando alguns dos encadeamentos de mensagens relacionados a este problema e passou tempo com o idioma, você viria à mesma conclusão.

Uma observação da qual não podemos fugir: se você importar um CSS vanilla válido, sua saída deve ser funcionalmente idêntica. Portanto, a única conclusão que posso tirar é que LESS não deve tocar em expressões que já sejam CSS possivelmente válidas. Como isso é feito, não depende de mim. Mas permanece o fato de que a importação de CSS simples não é confiável, principalmente como resultado de LESS executar divisões com muita ansiedade.

Importar o vanilla CSS no Sass funciona virtualmente sem falhas, porque, como disse, o Sass deixa o operador / sozinho se ele não indicar ao compilador para ir e fazer as coisas, de acordo com algumas regras de sintaxe simples. Essas regras de sintaxe descrevem maneiras de forçar uma divisão que não pode ocorrer em um CSS vanilla válido, e é por isso que é brilhante.

Você ainda discute com sua própria imaginação e não com o que ela lhe diz. Responda à pergunta simples: "Como 0 + 1/2 pode ser melhor do que (1/2) ?". Se 100% de compatibilidade -CSS é a única coisa que você se importa, defina o adorável -sm e esqueça este tópico.

Uma observação da qual não podemos fugir: se você importar um CSS vanilla válido, sua saída deve ser funcionalmente idêntica. Portanto, a única conclusão que posso tirar é que LESS não deve tocar em expressões que já sejam CSS possivelmente válidas. Como isso é feito, não depende de mim. Mas permanece o fato de que a importação de CSS simples não é confiável, principalmente como resultado de LESS executar divisões com muita ansiedade.

Eu essencialmente concordo com esta parte, e acho que você encontrará muita concordância neste tópico sobre esse ponto. A maioria das discordâncias gira em torno de soluções, com cada solução tendo vários efeitos colaterais.

Eu concordaria em fazer essas alterações importantes como uma prioridade:

  1. matemática fora dos parênteses exigindo ./ vez de / nua. 12px./10px ainda parece um pouco estranho.

@ seven-phase-max - quero revisitar a barra invertida. Relacionado a isso, sei que você mencionou https://github.com/less/less.js/issues/1872#issuecomment -35245890, mas não vejo nenhum conflito total, uma vez que esses identificadores não são e acho que não podem ser parte das expressões matemáticas. Ou eu estou errado? Suponho que seja possível inventar um caso teórico como um nome de função com um caractere escapado como parte do nome, mas isso parece mais um exercício intelectual do que um caso do mundo real. Seletores de escape, sim, eles são comumente usados ​​por vários motivos, mas em valores de propriedade, parece improvável ou, em um caso extremo, não há problema em interromper / contornar a alternativa histórica (apenas escapar deste texto).

Podemos explorar um pouco mais que o uso de uma única barra invertida para divisão causaria conflitos no mundo real? Meu instinto é que \ é menos problemático do que a situação atual em torno de / , e é mais amigável do que ./ . Se fizéssemos a pesquisa e descobríssemos que era viável, poderíamos fazer a alteração significativa para usá-lo em todos os lugares, em vez de alternar o contexto permitindo / entre parênteses. E então poderíamos oferecer suporte a / com um switch legado.

  1. (segunda prioridade) calc() sendo especial para que possa fazer a substituição de variáveis, mas não avaliará quaisquer expressões matemáticas

Podemos explorar um pouco mais que o uso de uma única barra invertida para divisão causaria conflitos no mundo real?

Bem, o problema de que \anycharacter é CSS válido e tem seu próprio significado. Claro, você dificilmente encontra tal código em projetos reais (exceto talvez os hacks como \9 ), mas ... queremos alimentar aquele leão? Consertar um "uh-oh, meu CSS 100% válido não compila" introduzindo outro "uh-oh" do mesmo parece um pouco estranho :)

Quanto a calc , acho que tivemos um consenso desde o início - então, basicamente, esperamos por um voluntário para implementá-lo (estimo que a correção rápida seja feita em apenas 5-6 linhas de novo código - então na verdade, trata-se apenas de um homem corajoso para fazer isso - pequenos detalhes de implementação podem variar, mas eu acho que eles podem ser decididos no processo).

Bem, o problema é que \ anycharacter é CSS válido e tem seu próprio significado. Claro, você dificilmente encontra tal código em projetos reais (exceto talvez os hacks do tipo ie \ 9), mas ... queremos alimentar aquele leão? Consertar um "uh-oh, meu CSS 100% válido não compila" introduzindo outro "uh-oh" do mesmo parece um pouco estranho :)

Eu ouvi você, é uma possível troca. E sim, eu sei que \anycharacter é CSS válido. Acho que estou me perguntando se é um conjunto melhor de compensações. É que quando escrevi 12px./10px parecia estranho, sintaticamente. Eu sinto que o Less sintaticamente tentou refazer o CSS tanto quanto possível sem criar conflitos.

Por exemplo, ./ fornece clareza de sintaxe e evita completamente o conflito, mas também o fez aplicar parênteses em todos os lugares para matemática, e é por isso que apoiei, mas houve uma reação negativa e estou preocupado com isso aqui. Portanto, há algum caso legítimo em que confundiríamos 10px\10 como a intenção do desenvolvedor de escapar de \10 ? Eu sei que é uma teoria difícil, e seu ponto provavelmente seria que nós realmente não sabemos ... É uma questão complicada, e adicionar uma nova sintaxe é sempre complicado, especialmente com Less, já que não conhecemos todos os CSS em o CSS selvagem nem futuro.

Quanto ao cálculo, acho que tivemos um consenso desde o início - então é basicamente apenas esperar por um voluntário para implementá-lo (eu estimo que a correção rápida seja feita em apenas 5-6 linhas de novo código - então é realmente apenas sobre um homem corajoso para fazer isso - detalhes de implementação menores podem variar, mas acho que eles estão bem para serem decididos no processo).

Boa! Devemos rastreá-lo separadamente para aumentar a visibilidade?

@ sete fases-máx .:

Claro, você dificilmente encontra tal código em projetos reais (exceto talvez os hacks como \9 )

Certo . Oh, aqueles "ocidentais" presunçosos ... :)

@ sete fases-máx.
Responda à pergunta simples: "Como 0 + 1/2 pode ser melhor do que (1/2)?"

Não vejo aonde você quer chegar com isso. (1/2) deve ser executado por LESS porque não pode ser um CSS válido, então deve significar LESS. 0 + 1/2 deve se tornar 1/2 onde LESS executa a parte 0 + 1 porque essa é a parte que não pode ser CSS válido. A parte 1/2 pode ser válida, então é melhor não tocá-la.

@thany
OK, agora perceba que (1/2) funciona conforme o esperado tanto no Less quanto no Sass ..
E 0 + 1/2 (assim como 1 * 1/2 etc.) é a parte da solução que você chama de brilhante acima e o resultado de "a solução brilhante" é 0.5 .
Ainda não tem ideia do que está acontecendo aqui?
Releia tudo (começando pelo seu primeiro post) acima mais uma vez e tente responder para si mesmo "Do que exatamente estou reclamando?".

@ sete fases-máx.
E 0 + 1/2 (bem como 1 * 1/2 etc.) é a parte da solução que você chama de brilhante acima e o resultado de "a solução brilhante" é 0,5.

Não, a solução seria 1/2 not 0.5 , já que 1/2 pode ser CSS válido. Você não parece querer MENOS para saber quando uma barra é válida, então suponha que sempre seja. Portanto, 1/2 é o único resultado lógico. Da mesma forma, 2 * 1/2 resultaria em 2/2 , porque * tornaria CSS inválido.

Ainda não tem ideia do que está acontecendo aqui?

Estou perfeitamente certo do que está acontecendo aqui. LESS está executando divisões matemáticas de maneira avidamente e cegamente ignora as unidades.

Releia tudo (começando pelo seu primeiro post) acima mais uma vez e tente responder para si mesmo "Do que exatamente estou reclamando?".

Não há necessidade de ataques pessoais.

LESS está executando divisões matemáticas de maneira avidamente e cegamente ignora as unidades.

Então é disso que você está reclamando, certo?

Não há necessidade de ataques pessoais.

Então, o que devo fazer em vez disso? Repetir as duas postagens originais uma e outra vez (e novamente)? Até que fique claro para você:
@community :

use a opção -sm

@thany :

então ele deve estar ativado por padrão.

@ sete fases-máx .:

Não pode ser porque isso quebraria imediatamente um milhão de projetos por aí. Portanto, se você tratar o comportamento padrão como um problema, apenas defina a opção documentada e pronto.


Então você está repetindo "deveria", "deveria", "deveria" esperando o quê? Acho que para nós é mais fácil responder apenas "Não, não deveria" em vez de perder nosso tempo tentando explicar em detalhes por que o que você sugere não vai funcionar ou não faz sentido em geral (as explicações que você não quer compreender ou simplesmente não pode).


Então, sobre o que é esse tópico? É sobre "perceber que, embora uma eventual mudança brusca de tornar um comportamento padrão" -sm padrão seja inevitável, temos que fornecer facilidades para uma aritmética mais confortável que não a terrível: margin: (1/2) (3/4) (5/6) (7/8); para aqueles que usar muito o aritmo ".
Suas postagens aqui sugerem algo que não é nada melhor do que (ou faz exatamente o mesmo) já existente -sm comportamento ou argumenta com algo que está fora de questão desde o início (como ). Em outras palavras, apenas um ruído aleatório .

@ seven- phase -max

Acho que a maioria das pessoas está na mesma página em relação a ambos, idealmente, não sendo interpretadas por Less como uma expressão matemática:

font: 12px/10px;
width: calc(100% - 20px);

Portanto, quase todos concordam nesses pontos e a maioria dos argumentos gira em torno de possíveis soluções. O problema calc() parece ter consenso suficiente para seguir em frente. Basicamente: não toque em calc e trate vars em calc() como interpolação de string. É mais ou menos assim que o Sass faz, embora exija a sintaxe de interpolação em calc() , que eu não acho que precisamos.

As soluções para a parte font ficam muito mais complicadas e as principais soluções têm sido:

  1. Exigir parênteses para tudo por padrão (primeira tentativa - quase implementado, mas a comunidade rejeitada)
  2. Vire o switch strictMath (que foi adicionado ao invés de torná-lo o padrão, e a sugestão de @ seven-phase-max) e então faça explicitamente toda a sua matemática. É, tecnicamente, uma solução possível para a maioria das pessoas no momento, mas ... a questão surge com tanta frequência e sabemos, psicologicamente, que alguém novo em qualquer sistema provavelmente mantém quaisquer padrões, por isso é problemático. E nem todo desenvolvedor pode alterar suas configurações de construção, especialmente em equipes.
  3. Essencialmente, altere o operador de divisão em Menos. O principal candidato no tópico foi ./ , que funciona, mas é um pouco estranho de se olhar. \ é um desconhecido neste momento, sem pesquisa. Pode funcionar, pode causar conflitos desconhecidos com a fuga. É uma sintaxe mais limpa, com maior risco (potencialmente, mas desconhecido). Se alguém perder algum tempo demonstrando que isso NÃO causará conflito, ou seja, fornecer exemplos de escape e matemática misturados de uma forma que o analisador possa distinguir claramente os dois, então ainda é uma possibilidade. Portanto, só dá trabalho. @thany , se você ou outra pessoa é fã disso, então este é o trabalho necessário. A última coisa que queremos é mover as quebras para outro lugar.

Acho que, para simplificar este tópico, devemos, a partir daqui, focar APENAS em #3 . Postei o exemplo do Sass principalmente como curiosidade, mas não acredito que essas soluções sejam boas ou resolvam completamente o problema, e são conceitualmente incompatíveis com Less. Discutir sobre a validade de exigir 0 + 1/2 não nos levará a lugar nenhum.

Portanto, com uma boa solução na mesa por calc() , o que nos leva a 50% do caminho até lá para a maioria dos problemas postados, eu recomendaria focar apenas nesta questão no curto prazo:

Se o operador de divisão Less deve ser alterado, o que deve ser alterado?

  • ./ - isso é tão estranho quanto eu sinto, ou as pessoas acham que está bom?
  • \ - sem pesquisa e provas, e pseudo-código para um analisador a seguir, isso não avançará. Eu pessoalmente prefiro, se puder ser provado que é seguro.
  • Outras substituições?

Honestamente, se mudarmos calc() e mudarmos / , acho que diminuiríamos 99% do ruído em torno da matemática em Menos.

Olá a todos, consertei calc() - https://github.com/less/less.js/pull/3162

Fiquei meio surpreso quando descobri uma solução que funcionava sem muitos códigos complementares. Basicamente, já tínhamos o código para a chave strictMath e verifica as expressões para não avaliar a matemática se ela estivesse fora dos parênteses, então adicionei uma chave adicional na chamada para desligar a matemática enquanto avaliava a calc() args e, em seguida, reinicie. Já tínhamos todas as peças para deixar a matemática em paz, mas ainda substituir vars. Huh.

Confira https://github.com/less/less.js/pull/3162/files#diff -a94aaffd78b1d3c5eda7a42d5be1ca0d e https://github.com/less/less.js/pull/3162/files#diff -4e696271823c96903a91fff84983bab6

Os testes são suficientes?

@ matthew-dean: café:

Os testes são suficientes?

por comentários no PR, adicione um teste como:

foo: 1 + 2 calc(3 + 4) 5 + 6; // expected result: 3 calc(3 + 4) 11;

E uma pequena observação: esta correção obviamente introduz o mesmo problema que em # 1627, ou seja,

<strong i="13">@a</strong>: floor(1.1);
<strong i="14">@b</strong>: floor(1 + .1);

div {
    foo: calc(<strong i="15">@a</strong> + 20%); // ok
    bar: calc(<strong i="16">@b</strong> + 20%); // error: invalid floor arguments
    baz: @b;             // ok
}

Mas por calc está tudo bem, eu acho (afinal, simplesmente não há outras maneiras simples de consertar sem uma grande reformulação do conceito de avaliação preguiçosa). Portanto, acho que é apenas uma questão de colocar um aviso na documentação para manter a avaliação preguiçosa em mente ao usar vars em calc .

E uma pequena observação: esta correção obviamente introduz o mesmo problema que em # 1627

Boa pegada!

Mudar a propriedade mathOn contexto por chamada resolve isso, semelhante ao seu comentário no PR. Eu adicionei um teste para float(1 + .1) que passa!

Alternar a propriedade mathOn de contexto por chamada resolve isso, semelhante ao seu comentário no PR. Eu adicionei um teste para float (1 + .1) que passa!

:) Não, o erro "floor" deve estar lá quando -sm: off . Veja meu comentário mais recente no PR.
A restauração cuida apenas de coisas semelhantes a 1 + 2 calc(3 + 4) 5 + 6 .

:) Não, o erro "floor" deve estar presente quando -sm: off.

Por quê? Quaisquer funções dentro de calc() devem ser funções Less. Mesmo se não forem, não há funções nativas de CSS dentro de calc () que eu saiba que podem usar expressões matemáticas brutas. O resultado esperado seria avaliar as funções vars e Less, mas deixar as funções brutas dentro de calc() sozinhas.

Observação lateral: eu fiz um experimento de ramificação de alternar / para \ como um operador de divisão em Less. Já existem muitos testes de escape (e eu adicionei mais, para resolver: # 3160), e todos eles ainda funcionam bem, e a matemática funciona bem com os operadores trocados. Eu não vi nenhum conflito inerente. Branch está aqui na minha bifurcação: https://github.com/matthew-dean/less.js/commit/509d34fff7e234846afa150b099cd259755a39d0

Re: funções aninhadas

Por esta:

div {
    bar: calc(floor(1 + .1) + 20%);
}

Como desenvolvedor, o resultado esperado deve ser:

div {
    bar: calc(1 + 20%);
}

Isso é exatamente o que acontece agora (com essas mudanças). Não deve gerar um erro.

@ matthew-dean
Não, do jeito que você escreveu, este:

foo: unit(1/2, px);

com -sm:on compilará para:

foo: .5px;

^ - errado.
O mesmo para funções aninhadas. Além disso, o fato de que a maioria das funções geralmente não pode aceitar expressões aritméticas como argumento não é uma razão para violar -sm: on ;
Assim, em -sm: on ambas as linhas:

foo: floor(1 + .1);
bar: calc(floor(1 + .1) + 20%);`

deve lançar um erro (e é isso que é quebrado no commit).

Do que você está falando?

unit(1/2, px) com -sm:on :

ERROR: error evaluating function `unit`: the first argument to unit must be a number. Have you forgotten parenthesis?

calc(floor(1 + .1) + 20%) com -sm:on

ERROR: error evaluating function `floor`: argument must be a number

Confira a filial. Experimente.

Uma coisa que pode ser mais útil ao revisar o código é que, se você não tiver certeza se algo produzirá uma saída incorreta, verifique-o. Ou peça que eu experimente uma entrada específica para verificar se funciona conforme o esperado. Ou faça perguntas se não tiver certeza de como / por que funciona. Chamar de errado sem saber se não ajuda.

Minhas desculpas. Acho que perdi o controle indireto dessa parte .

Confira a filial. Experimente

Eu não posso, desculpe.

Minhas desculpas. Acho que perdi o controle indireto dessa parte.

Sem problemas. Com isso resolvido, parece que está funcionando como você esperava?

Com isso resolvido, parece que está funcionando como você esperava?

Sim, até agora não consigo imaginar outras coisas suspeitas lá.

@ matthew-dean
Essencialmente, altere o operador de divisão em Menos. O principal candidato no tópico foi ./, que funciona, mas é um pouco estranho de se olhar. \ é um desconhecido neste ponto sem pesquisa [...] @thany , se você ou outra pessoa é fã disso, então este é o trabalho necessário. A última coisa que queremos é mover as quebras para outro lugar.

Nem um pouco, na verdade. Sugeri o operador \ como último recurso depois de não conseguir prosseguir, tentando fazer com que MENOS fizesse apenas seus próprios cálculos. Se um novo operador de divisão for o necessário ... Bem, calc() também pode fazer adição, subtração e multiplicação. Novos operadores para esses? Acho que não é prático. Um novo operador de divisão pode ser uma solução para coisas como fonte, plano de fundo e raio da borda, mas não é solução para matemática CSS.

Ainda acho que a solução real é MENOS saber sobre o contexto. Ele deveria (sim, lá vou eu de novo com meu "deveria", que outra palavra devo usar? ...) saber que calc() é uma função CSS e deve apenas avaliar matemática que o CSS não pode fazer . Mas floor() não existe em CSS, então aquele deveria ser avaliado (inteiramente) para não vomitar CSS inválido. Acho que isso foi mencionado antes, porém, com uma redação diferente.

Ainda acho que a solução real é MENOS saber sobre o contexto. Ele deveria (sim, lá vou eu de novo com meu "deveria", que outra palavra devo usar? ...) saber que calc () é uma função CSS e deve apenas avaliar matemática que o CSS não pode fazer. Mas floor () não existe no CSS, então aquele deveria ser avaliado (inteiramente) para não lançar CSS inválido. Acho que isso foi mencionado antes, porém, com uma redação diferente.

Muito justo: \ , mas no que diz respeito ao contexto, com base em suas outras postagens, posso garantir que é um problema muito mais complexo do que você está pensando. Você realmente tem que reduzir para:

12px/10px  // Is this division, or not?
10px/1.5 // is this division, or not? 

Se você deseja definitivamente deixar / como um operador de divisão, para imitar calc() , e não ser ambíguo, então você absolutamente precisa ter certeza de que / está em parênteses (exceto a exceção calc() ). Isso forneceria um contexto previsível.

Essa sugestão no início deste tópico também ainda é uma possibilidade e teve um forte apoio. Essencialmente, a configuração padrão é que toda a matemática é suportada fora dos parênteses EXCETO a divisão (e novamente, exceto calc() , agora é o caso de 3.0+). Talvez seja esse o caminho a percorrer. Isso permitiria:

font: 10px/1.5;   // not division
font: (10px/10);  // division, result is 1px
font: 10px+15px/1.5;   // addition but not division, result is 25px/1.5
font: (10px+15px/1.5);  // result is 20px

O fato é que o resultado para 10px+15px/1.5 ainda pode ser difícil para os desenvolvedores grocarem, com uma expressão que parece ser "avaliada pela metade", a menos que esteja entre parênteses. Se tivéssemos ido em frente e ativado a matemática estrita por padrão, provavelmente estaria tudo bem. É ainda menos ambíguo. [encolher os ombros] De qualquer maneira, envolver a matemática em algum tipo de contexto É a maneira de eliminar a ambigüidade, e a única maneira de divisão além de alterar o operador de divisão.

A comunidade deve essencialmente decidir a direção. Existem opções viáveis ​​neste tópico. Cada um tem suas desvantagens. Cada um tem pontos de dor. Nenhum terá consenso total. Mas IMO qualquer um deles é melhor do que o cenário atual. Só tenho que engolir aquela pílula.

Última chamada para uma decisão

Então, em um esforço para trabalhar o impossível, gostaria de propor que façamos isso (referindo-se aos comentários de 3 anos atrás).

--strict-math 3 configurações

  1. fora
  2. divisão
  3. estrito (alias on para back-compat)

Para encerrar o debate, permita que o switch --strict-math=division faça o seguinte:

  1. Não execute a divisão com apenas / caractere fora dos parênteses. Por exemplo, border-radius: 55px / 25px; -> não matemática (sim, isso é CSS válido)
  2. Permita a divisão com dois métodos diferentes:
    uma. . prefixo - border-radius: 55px ./ 25px;
    b. parênteses - border-radius: (55px / 25px);
  3. Ambas as formas são válidas entre parênteses - por exemplo, border-radius: (55px ./ 25px); seria válido

Portanto, como desenvolvedor, se você sentir que uma versão não é sua preferência, você pode usar a outra. Alguns podem preferir não usar parênteses; alguns podem preferir não usar um operador de divisão modificado. Algo para todos. E não há mais surpresas desagradáveis ​​para os novos em Less usando o que agora é uma sintaxe amplamente difundida em CSS, com / sendo usado em font , background , border-radius , @media queries, propriedades CSS Grid e provavelmente mais no futuro.

Próximos passos

Eu recomendo que isso vá para um PR como uma opção e, como discutido, é alterado como o padrão para uma versão principal futura

@ matthew-dean

Ou seja, o período funciona como o inverso de uma sequência de escape?
Não é uma má ideia, realmente ...

E considerando todas as coisas, _provavelmente_ uma das soluções mais limpas possíveis.

@rjgotten Comece aqui: https://github.com/matthew-dean/less.js/tree/strict-math-division

Ainda estou recebendo um erro estranho em um dos testes, em que parece transformar um dos nós de dimensão em um nó de operação (e, em seguida, gera um erro porque não pode executar uma operação em um nó de operação. Parece ser um problema de análise porque outro teste que não está sendo executado em strictMath: division funciona bem. Quer dar uma olhada e ver se você pode ajudar?

O que eu gostaria de fazer é fechar este problema e criar novos problemas que lidem com as questões matemáticas restantes. Especificamente:

  1. Divisão de tratamento e o recurso strictMath: 'division' .
  2. Manipulação de matemática de unidades mistas. Veja: https://github.com/less/less.js/issues/3047
Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

chricken picture chricken  ·  6Comentários

joe223 picture joe223  ·  4Comentários

briandipalma picture briandipalma  ·  6Comentários

BrianMulhall picture BrianMulhall  ·  4Comentários

pknepper picture pknepper  ·  3Comentários