Eu sempre fui ensinado que ter efeitos colaterais em uma if
condição é ruim. O que eu quero dizer é;
if (conditionThenHandle()) {
// do effectively nothing
}
... em oposição a;
if (condition()) {
handle();
}
... e eu entendo isso, e meus colegas estão felizes porque eu não faço, e todos nós voltamos para casa às 17:00 na sexta-feira e todo mundo tem um fim de semana feliz.
Agora, o ECMAScript5 introduziu métodos como every()
e some()
para Array
, e eu os acho muito úteis. Eles são mais limpos que for (;;;)
os outros, oferecem outro escopo e tornam o elemento acessível por uma variável.
No entanto, ao validar a entrada, eu geralmente me encontro usando every
/ some
na condição de validar a entrada e depois uso every
/ some
novamente no corpo para converter a entrada em um modelo utilizável;
if (input.every(function (that) {
return typeof that === "number";
})) {
input.every(function (that) {
// Model.findById(that); etc
}
} else {
return;
}
... quando o que eu quero fazer é;
if (!input.every(function (that) {
var res = typeof that === "number";
if (res) {
// Model.findById(that); etc.
}
return res;
})) {
return;
}
... o que me causa efeitos colaterais em uma if
condição ruim.
Em comparação, esse é o código com o qual seria antigo for (;;;)
;
for (var i=0;i<input.length;i++) {
var curr = input[i];
if (typeof curr === "number") {
return;
}
// Model.findById(curr); etc.
}
Minhas perguntas são:
- Definitivamente, é uma prática ruim?
- Estou (mis | ab) usando
some
eevery
( devo usar umfor(;;;)
para isso?) - Existe uma abordagem melhor?
fonte
some
, quero fazer algo com o elemento, se eu usarevery
, quero fazer algo com todos esses elementos ...some
eevery
não me permita acessar essas informações, para que não possa usá-los, ou eu tenho que adicionar efeitos colaterais.some
na minhaif
condição para determinar se um determinado elemento da matriz exibe uma determinada propriedade, 9/10 eu preciso operar com esse elemento no meuif
corpo; agora, comosome
não me diz qual dos elementos exibia a propriedade (apenas "um fez"), posso usarsome
novamente no corpo (O (2n)) ou executar a operação dentro da condição if ( o que é ruim, porque é um efeito colateral na cabeça).every
também, é claro.Respostas:
Se eu entendo o seu ponto corretamente, você parece ser mis-usando ou abusando
every
esome
mas é um pouco inevitável se você quiser mudar os elementos de suas matrizes diretamente. Corrija-me se estiver errado, mas o que você está tentando fazer é descobrir se algum ou todos os elementos da sua sequência exibem uma determinada condição e depois modifica-os. Além disso, seu código parece estar aplicando algo a todos os itens até você encontrar um que não passa no predicado e acho que não é isso que você quer fazer. Enfim.Vamos dar o seu primeiro exemplo (ligeiramente modificado)
O que você está fazendo aqui é um pouco contrário ao espírito dos conceitos de alguns / todos / mapas / reduções / filtros / etc.
Every
não deve ser usado para afetar todos os itens que estejam em conformidade com algo, mas deve ser usado apenas para informar se todos os itens de uma coleção são compatíveis. Se você deseja aplicar uma função a todos os itens para os quais um predicado é avaliado como verdadeiro, a maneira "boa" de fazer isso éComo alternativa, você pode usar em
foreach
vez do mapa para modificar os itens no local.A mesma lógica se aplica
some
, basicamente:every
para testar se todos os elementos de uma matriz passam em algum teste.some
para testar se pelo menos um elemento de uma matriz passa em algum teste.map
para retornar uma nova matriz contendo 1 elemento (que é o resultado de uma função de sua escolha) para cada elemento em uma matriz de entrada.filter
para retornar uma matriz de comprimento 0 <length
<initial array length
elementos, todos contidos na matriz original e todos passar no teste predicado fornecido.foreach
se quiser mapa, mas no localreduce
se quiser combinar os resultados de uma matriz em um único resultado de objeto (que pode ser uma matriz, mas não precisa).Quanto mais você os usa (e quanto mais escreve código LISP), mais percebe como eles estão relacionados e como é ainda possível emular / implementar um com os outros. O que é poderoso nessas consultas e o que é realmente interessante são as semânticas e como elas realmente o pressionam para eliminar efeitos colaterais prejudiciais no seu código.
EDIT (à luz dos comentários): digamos que você queira validar que cada elemento é um objeto e convertê-los em um Modelo de Aplicativo, se todos forem válidos. Uma maneira de fazer isso em uma única passagem seria:
Dessa forma, quando um objeto não passa na validação, você continua repetindo toda a matriz, o que seria mais lento do que a validação
every
. No entanto, na maioria das vezes sua matriz será válida (ou eu espero que sim), portanto, na maioria dos casos, você executará uma única passagem sobre sua matriz e terminará com uma matriz utilizável de objetos do Modelo de Aplicativo. A semântica será respeitada, os efeitos colaterais serão evitados e todos serão felizes!Observe que você também pode escrever sua própria consulta, semelhante ao foreach, que aplicaria uma função a todos os membros de uma matriz e retornará verdadeiro / falso se todos passarem em um teste de predicado. Algo como:
Embora isso modifique a matriz no lugar.
Espero que isso ajude, foi muito divertido escrever. Felicidades!
fonte
if (input.every())
, para verificar que cada elemento é um objeto (typeof el === "object && el !== null
) etc, então se que valida, eu quero converter cada elemento em o respectivo modelo de aplicativo (que, agora que você mencionoumap()
que eu poderia usarinput.map(function (el) { return new Model(el); });
, mas não necessariamente no lugar .map()
tendo de repetir a matriz duas vezes; uma vez para validar e outra para converter. No entanto, usando um padrão defor(;;;)
circuito, que poderia fazer isso usando uma iteração, mas não consegue encontrar uma maneira de aplicarevery
,some
,map
oufilter
neste cenário, e executar apenas uma passagem, sem ter-secundários indesejáveis efeitos ou de outro modo que introduz ruim- prática.Os efeitos colaterais não estão na condição if, eles estão no corpo do if. Você determinou apenas se deve ou não executar esse corpo na condição real. Não há nada de errado com sua abordagem aqui.
fonte
if
condição, apenas com oreturn
ser dentro doif
corpo do corpo; Obviamente, estou falando sobre o exemplo de código precedido por "o que queremos fazer é; ..."if
condição.