Underscore: Error de métodos de cadena de matriz en valores que no son de matriz

Creado en 20 mar. 2016  ·  6Comentarios  ·  Fuente: jashkenas/underscore

Error de métodos de cadena de matriz en valores que no son de matriz, a diferencia de otros métodos de categoría de matriz.

_().pop(); // error
_('').pop(); // error
_().first() // undefined

Comentario más útil

Esto trae a colación otro problema, ¿deberíamos emitir me gusta de matriz a matriz?

_('hello').first() // 'h'
_('hello').pop() // ?

Todos 6 comentarios

Esto trae a colación otro problema, ¿deberíamos emitir me gusta de matriz a matriz?

_('hello').first() // 'h'
_('hello').pop() // ?

Esto parece seguir siendo un problema: lo encontramos después de cambiar nuestra versión de 1.8.3 a 1.9.0

Editar: Parece que esto se solucionó en 1.9.1, si es así, ¿este problema debe permanecer abierto?

Este comportamiento todavía está presente en 1.10.2.

Un contraste un poco más convincente en mi opción, ya que ambos implican modificar un valor en el lugar:

Object.assign(undefined, {a: 1})  // error
_().extend({a: 1})  // undefined

Array.prototype.push.call(undefined, 1)  // error
_().push(1)  // error

Estoy un poco de acuerdo en que esto es inconsistente.

Vale la pena considerar en qué tipo de situación del mundo real es más probable que se encuentre y qué esperar del objeto envuelto en tales casos.

En medio de una cadena, el objeto envuelto es predecible. Por ejemplo, en la siguiente cadena, el objeto envuelto que se pasa a push será Array o undefined . Por esta razón, diría que los métodos de envoltorio Array deberían implementar una verificación nula. Esto es facil.

_.chain(something).map(f).push(x)  // hoping to push x to an array

Si es más probable que el objeto envuelto predicho sea algo más que una matriz, entonces podría decirse que es un error del programador. No me importa lanzar una excepción en ese caso.

_.chain(something).map(f).join('').push(x)  // hoping to push x to a string??

Al comienzo de una cadena, la historia puede parecer un poco diferente a primera vista, pero argumentaré que es lo mismo y que deberíamos dejarlo en un control nulo. Al menos debe darse el caso de que el programador tenga alguna razón para esperar que something sea ​​una matriz mutable, ya que de lo contrario, no habría razón para llamar a push :

function giveMeAMutableArraylike(something) {
    _.chain(something).push(x)
}

La expectativa de que something sea ​​similar a una matriz mutable podría no cumplirse por una variedad de razones:

  1. giveMeAMutableArraylike terminó siendo igualado con null o undefined por cualquier motivo. Esto es comparable al primer ejemplo de cadena en el medio y se puede abordar con la misma verificación nula.
  2. La persona que llama está tratando de hacer que giveMeAMutableArraylike haga algo que obviamente no puede hacer, es decir, romper el contrato. Esto es comparable al segundo ejemplo de cadena en el medio. Nuevamente, creo que está bien arrojar un error en este caso.
  3. something es un valor simple en lugar de una matriz con un solo elemento, es decir, v en lugar de [v] . Esta es una situación común en muchas API de JavaScript. Si el contrato de giveMeAMutableArraylike permite esto, obviamente es incorrecto arrojar un error independientemente de lo que resulte ser v .

En el último caso, Underscore no puede saber si giveMeAMutableArraylike permite o no elementos desnudos únicos, por lo que depende del programador de giveMeAMutableArraylike implementar su contrato particular. No hay nada que una biblioteca como Underscore pueda hacer que haga lo correcto para todos los contratos posibles:

| Comportamiento actual | Envolver en una matriz de un solo elemento
---|---|---
Contrato permite solo elemento desnudo | _El programador necesita intervenir_ | El guión bajo hace lo correcto automáticamente
El contrato no permite un solo elemento desnudo | El guión bajo hace lo correcto automáticamente | _El programador necesita intervenir_

Además, ¿cómo decide si un valor debe envolverse? Algunos contratos pueden querer envolver cualquier cosa que no sea un Array , mientras que otros pueden querer pasar arguments y objetos simples tal cual. Nuevamente, esto es algo que una biblioteca como Underscore no puede adivinar en nombre del usuario.

También son concebibles situaciones más exóticas, por ejemplo, un contrato que permita objetos inmutables similares a una matriz, como cadenas, y que los convierta primero en Array . Es imposible cubrir todas las variaciones posibles. Según el principio de cambio mínimo, simplemente no existe un argumento convincente para respaldar algunos contratos a expensas de los contratos que ya fueron respaldados. También hay un caso sólido para mantener la implementación lo más mínima posible.

Así que creo que la solución correcta es insertar solo un cheque nulo y dejarlo así. Este es el único cambio en el comportamiento de Underscore que parece defendible en todas las situaciones imaginables y también es coherente con el comportamiento de _.extend . Una verificación nula aún podría considerarse una corrección de errores, mientras que hacer algo más que eso lo convertiría rápidamente en un cambio de ruptura arbitrario.

@jashkenas , ¿podrías iluminar esto? Si está de acuerdo, prepararé una solicitud de extracción que implemente la verificación nula.

@jgongrijp : ¿Puede elaborar en una oración o dos el comportamiento que desea implementar con la verificación nula?

¿Es que los métodos de matriz arrojarán explícitamente una excepción cuando se les llame en un valor nulo? ¿O que no funcionarán cuando se les solicite un valor nulo?

@jashkenas Sí. El comportamiento que implementaría no es operativo, siguiendo el estilo de las funciones de matriz de subrayado:

https://github.com/jashkenas/underscore/blob/4cf715f593805ba8d7c5685cd06c82b3cd9b55ae/modules/index.js#L495

Excepto que el cheque length no sería necesario, así que solo insertaría

if (obj == null) return chainresult(this, obj);

entre estas dos lineas:

https://github.com/jashkenas/underscore/blob/4cf715f593805ba8d7c5685cd06c82b3cd9b55ae/modules/index.js#L1654 -L1655

Además de las pruebas, por supuesto, y si esas pruebas revelan una necesidad, tal vez también una verificación nula que convierta el método en no operativo antes de esta línea:

https://github.com/jashkenas/underscore/blob/4cf715f593805ba8d7c5685cd06c82b3cd9b55ae/modules/index.js#L1665

¡Suena bien para mí!

¿Fue útil esta página
0 / 5 - 0 calificaciones