(n >= 3) && (n <= 99)
O¿Cuál es más rápido y por qué?
n `elem` [3..99]
Cuál es más rápido y por qué?
(n >= 3) && (n <= 99)
O¿Cuál es más rápido y por qué?
n `elem` [3..99]
Cuál es más rápido y por qué?
El primero es más rápido
(n >= 3) && (n <= 99)
que está haciendo 3 operaciones
n >= 3
n <= 99
and
Donde como la elem está mirando hacia arriba del elemento de la matriz, por lo que está haciendo hasta (99 - 3) * 2 operaciones.
index = 0
isFound = false
array[] = { 3, 4, 5, 6, ... 98, 99 }
while isFound == false
isFound = (n == array[index++])
(n> = 3) & & (n = < 99) es más rápido, ya que implica sólo dos comparaciones triviales. Si el compilador/intérprete no hace ningún tipo de optimización real de magia negra, tiene que construir la lista ([3.99]) porque la evaluación diferida no se puede usar (normalmente "tirando" el siguiente valor hasta que hayas terminado, tendría una complejidad de O (n/2) en este caso).
+1 Bienvenido a stackoverflow :) –
+1 Así que no hay magia negra, aunque estaba esperando :) también bienvenido a SO! –
Estas dos expresiones no significan lo mismo. Una sutil diferencia es que uno se basa en Ord
y el otro en Enum
:
> :t \n -> (n >= 3) && (n <= 99)
\n -> (n >= 3) && (n <= 99) :: (Num a, Ord a) => a -> Bool
> :t \n -> n `elem` [3..99]
\n -> n `elem` [3..99] :: (Num a, Enum a) => a -> Bool
Así, por ejemplo, si n es 3,14159, a continuación, se pasa la primera prueba, pero el segundo no:
> (pi >= 3) && (pi <= 99)
True
> pi `elem` [3..99]
False
Además, aunque las cuatro Prelude Num
instancias (Int
, Integer
, Float
, y Double
) son todas las instancias de ambos Ord
y Enum
, es posible imaginar un tipo numérico que es una instancia de Ord
pero no Enum
. En tal caso, entonces la segunda prueba ni siquiera sería legal.
Por lo tanto, en general, el compilador no puede optomize el segundo para ser tan rápido como el primero a menos que sepa para un tipo dado, que es Ord
y que todos los valores ordenados en el rango también están en la lista enumeración creado por enumFromTo
. Para Float
y Double
esto no es cierto, y para Int
y Integer
no hay forma de que el compilador lo obtenga, el compilador y los programadores de la biblioteca tendrían que codificarlo a mano y garantizar que se mantenga en todos los casos.
Depende de la máquina y el compilador (o intérprete).
¿Es así como realmente se implementa 'elem'? ¿Realmente no hay magia negra? ¿¿en absoluto?? :) –
¿Qué "magia negra" esperarías? Incluso si bajo el capó el compilador reconoce que [3.99] es un rango y preparó un rango de verificación, seguiría siendo el mismo que (n> = 3) && (n <= 99) –
Supongo que podría hacer que GHC optimice este caso en particular usando una regla de reescritura a la '" elem/enumFromTo "forall x lo hi". elem x (enumFromTo lo hi) = (x> = lo && x <= hi) '. Aunque nunca he hecho nada con las reglas de reescritura (demasiado parecido a la magia negra ;-), ¡así que tómalo con una gran pizca de sal! – yatima2975