telefono telefonica telcel online nombre llamadas llamada identificador gratis fijo ejemplos con como bloqueado activar scala

scala - telcel - identificador de llamadas telefonica



Llamada por nombre vs llamada por valor en Scala, se necesita aclaración (15)

Como lo entiendo, en Scala, una función puede llamarse

  • por valor o
  • por nombre

Por ejemplo, dadas las siguientes declaraciones, ¿sabemos cómo se llamará la función?

Declaración:

def f (x:Int, y:Int) = x;

Llamada

f (1,2) f (23+55,5) f (12+3, 44*11)

¿Cuáles son las reglas por favor?


Aquí hay un ejemplo de Martin Odersky:

def test (x:Int, y: Int)= x*x

Queremos examinar la estrategia de evaluación y determinar cuál es más rápida (menos pasos) en estas condiciones:

test (2,3)

llamada por valor: prueba (2,3) -> 2 * 2 -> 4
llamada por nombre: prueba (2,3) -> 2 * 2 -> 4
Aquí el resultado se alcanza con el mismo número de pasos.

test (3+4,8)

Llamada por valor: prueba (7,8) -> 7 * 7 -> 49
llamada por nombre: (3 + 4) (3 + 4) -> 7 (3 + 4) -> 7 * 7 -> 49
Aquí la llamada por valor es más rápida.

test (7,2*4)

Llamada por valor: prueba (7,8) -> 7 * 7 -> 49
llamada por nombre: 7 * 7 -> 49
Aquí la llamada por nombre es más rápida

test (3+4, 2*4)

llamada por valor: prueba (7,2 * 4) -> prueba (7, 8) -> 7 * 7 -> 49
llamada por nombre: (3 + 4) (3 + 4) -> 7 (3 + 4) -> 7 * 7 -> 49
El resultado se alcanza en los mismos pasos.


Como supongo, la función de call-by-value como se discutió anteriormente pasa solo los valores a la función. Según Martin Odersky , es una estrategia de evaluación seguida por un Scala que juega un papel importante en la evaluación de la función. Pero, que sea simple para call-by-name . Es como pasar la función como argumento al método, también conocido como Higher-Order-Functions . Cuando el método accede al valor del parámetro pasado, llama a la implementación de las funciones pasadas. como a continuación:

De acuerdo con el ejemplo de @dhg, primero cree el método como:

def something() = { println("calling something") 1 // return value }

Esta función contiene una instrucción println y devuelve un valor entero. Cree la función, que tiene argumentos como una call-by-name :

def callByName(x: => Int) = { println("x1=" + x) println("x2=" + x) }

Este parámetro de función es definir una función anónima que ha devuelto un valor entero. En este x contiene una definición de función que tiene 0 argumentos pasados ​​pero devuelve el valor int y nuestra función something contiene la misma firma. Cuando llamamos a la función, pasamos la función como un argumento a callByName . Pero en el caso de la call-by-value solo pasa el valor entero a la función. Llamamos a la función de la siguiente manera:

scala> callByName(something()) calling something x1=1 calling something x2=1

En este nuestro método something se llama dos veces, porque cuando accedemos al valor de x en el método callByName , se llama al método de definición de something .


El ejemplo que ha dado solo utiliza la llamada por valor, por lo que le daré un nuevo ejemplo más simple que muestra la diferencia.

Primero, asumamos que tenemos una función con un efecto secundario. Esta función imprime algo y luego devuelve un Int .

def something() = { println("calling something") 1 // return value }

Ahora vamos a definir dos funciones que aceptan argumentos Int que son exactamente iguales, excepto que una toma el argumento en un estilo de llamada por valor ( x: Int ) y la otra en un estilo de llamada por nombre ( x: => Int ).

def callByValue(x: Int) = { println("x1=" + x) println("x2=" + x) } def callByName(x: => Int) = { println("x1=" + x) println("x2=" + x) }

Ahora, ¿qué sucede cuando los llamamos con nuestra función de efecto secundario?

scala> callByValue(something()) calling something x1=1 x2=1 scala> callByName(something()) calling something x1=1 calling something x2=1

Así que puedes ver que en la versión de llamada por valor, el efecto secundario de la llamada de función pasada ( something() ) solo ocurrió una vez. Sin embargo, en la versión de llamada por nombre, el efecto secundario ocurrió dos veces.

Esto se debe a que las funciones de llamada por valor calculan el valor de la expresión pasada antes de llamar a la función, por lo que se accede al mismo valor cada vez. Sin embargo, las funciones de llamada por nombre vuelven a calcular el valor de la expresión pasada cada vez que se accede.


En el caso de su ejemplo, todos los parámetros se evaluarán antes de que se llame a la función, ya que solo los definirá por valor . Si desea definir sus parámetros por nombre , debe pasar un bloque de código:

def f(x: => Int, y:Int) = x

De esta manera, el parámetro x no se evaluará hasta que se llame en la función.

Este pequeño post aquí explica esto muy bien también.


En una llamada por valor , el valor de la expresión se calcula previamente en el momento de la llamada a la función y ese valor particular se pasa como parámetro a la función correspondiente. El mismo valor se utilizará en toda la función.

Mientras que en una llamada por nombre , la expresión en sí misma se pasa como un parámetro a la función y solo se calcula dentro de la función, siempre que se llame a ese parámetro en particular.

La diferencia entre Llamada por nombre y Llamada por valor en Scala podría entenderse mejor con el siguiente ejemplo:

Fragmento de código

object CallbyExample extends App { // function definition of call by value def CallbyValue(x: Long): Unit = { println("The current system time via CBV: " + x); println("The current system time via CBV " + x); } // function definition of call by name def CallbyName(x: => Long): Unit = { println("The current system time via CBN: " + x); println("The current system time via CBN: " + x); } // function call CallbyValue(System.nanoTime()); println("/n") CallbyName(System.nanoTime()); }

Salida

The current system time via CBV: 1153969332591521 The current system time via CBV 1153969332591521 The current system time via CBN: 1153969336749571 The current system time via CBN: 1153969336856589

En el fragmento de código anterior, para la llamada de función CallbyValue (System.nanoTime ()) , el tiempo nano del sistema se calcula previamente y ese valor calculado previamente ha pasado un parámetro a la llamada de función.

Pero en la llamada a la función CallbyName (System.nanoTime ()) , la expresión "System.nanoTime ())" en sí misma se pasa como un parámetro a la llamada a la función y el valor de esa expresión se calcula cuando ese parámetro se usa dentro de la función .

Observe la definición de la función de CallbyName, donde hay un símbolo => que separa el parámetro x y su tipo de datos. Ese símbolo particular allí indica que la función es de tipo llamada por nombre.

En otras palabras, los argumentos de la función llamada por valor se evalúan una vez antes de ingresar a la función, pero los argumentos de la función llamada por nombre se evalúan dentro de la función solo cuando son necesarios.

¡Espero que esto ayude!


La llamada por valor es un caso de uso general como se explica en muchas respuestas aquí ..

La llamada por nombre pasa un bloque de código a la persona que llama y cada vez que la persona que llama accede al parámetro, se ejecuta el bloque de código y se calcula el valor.

Intentaré demostrar la forma más simple de llamar por nombre con los casos de uso a continuación

Ejemplo 1:

El ejemplo simple / caso de uso de llamada por nombre está debajo de la función, que toma la función como parámetro y da el tiempo transcurrido.

/** * Executes some code block and prints to stdout the time taken to execute the block for interactive testing and debugging. */ def time[T](f: => T): T = { val start = System.nanoTime() val ret = f val end = System.nanoTime() println(s"Time taken: ${(end - start) / 1000 / 1000} ms") ret }

Ejemplo 2:

apache spark (con scala) usa el registro utilizando la forma llamada por nombre. Consulte el rasgo del Logging en el que evalúa perezosamente si log.isInfoEnabled o no se realiza con el método siguiente.

protected def logInfo(msg: => String) { if (log.isInfoEnabled) log.info(msg) }


Los parámetros generalmente se pasan por valor, lo que significa que se evaluarán antes de ser sustituidos en el cuerpo de la función.

Puede forzar que un parámetro sea llamado por nombre usando la flecha doble al definir la función.

// first parameter will be call by value, second call by name, using `=>` def returnOne(x: Int, y: => Int): Int = 1 // to demonstrate the benefits of call by name, create an infinite recursion def loop(x: Int): Int = loop(x) // will return one, since `loop(2)` is passed by name so no evaluated returnOne(2, loop(2)) // will not terminate, since loop(2) will evaluate. returnOne(loop(2), 2) // -> returnOne(loop(2), 2) -> returnOne(loop(2), 2) -> ...


Mira esto:

object NameVsVal extends App { def mul(x: Int, y: => Int) : Int = { println("mul") x * y } def add(x: Int, y: Int): Int = { println("add") x + y } println(mul(3, add(2, 1))) }

y: => Int es llamada por nombre. Lo que se pasa como llamada por nombre es agregar (2, 1). Esto será evaluado perezosamente. Por lo tanto, la salida en la consola será "mul" seguida de "agregar", aunque parece que primero se llama a agregar. Llamar por nombre actúa como un tipo de puntero de función.
Ahora cambia de y: => Int a y: Int. La consola mostrará "agregar" seguido de "mul"! Forma habitual de evaluación.


No creo que todas las respuestas aquí hagan la justificación correcta:

En la llamada por valor, los argumentos se calculan una sola vez:

def f(x : Int, y :Int) = x // following the substitution model f(12 + 3, 4 * 11) f(15, 4194304) 15

Se puede ver arriba que todos los argumentos se evalúan según sea necesario, normalmente, la call-by-value puede ser rápida, pero no siempre es así en este caso.

Si la estrategia de evaluación fuera call-by-name , la descomposición habría sido:

f(12 + 3, 4 * 11) 12 + 3 15

Como puede ver arriba, nunca tuvimos que evaluar 4 * 11 y, por lo tanto, ahorramos un poco de cómputo, lo que a veces puede ser beneficioso.


Para explicar el punto de @ Ben en los comentarios anteriores, creo que es mejor pensar en "llamada por nombre" como solo azúcar sintáctica. El analizador simplemente envuelve las expresiones en funciones anónimas, para que puedan llamarse en un momento posterior, cuando se utilizan.

En efecto, en lugar de definir

def callByName(x: => Int) = { println("x1=" + x) println("x2=" + x) }

y corriendo:

scala> callByName(something()) calling something x1=1 calling something x2=1

También podrías escribir:

def callAlsoByName(x: () => Int) = { println("x1=" + x()) println("x2=" + x()) }

Y ejecútalo como sigue para el mismo efecto:

callAlsoByName(() => {something()}) calling something x1=1 calling something x2=1


Pasar por un ejemplo debería ayudarlo a comprender mejor la diferencia.

Definamos una función simple que devuelve la hora actual:

def getTime = System.currentTimeMillis

Ahora definiremos una función, por nombre , que imprime dos veces retrasada por un segundo:

def getTimeByName(f: => Long) = { println(f); Thread.sleep(1000); println(f)}

Y uno por valor :

def getTimeByValue(f: Long) = { println(f); Thread.sleep(1000); println(f)}

Ahora llamemos a cada uno:

getTimeByName(getTime) // prints: // 1514451008323 // 1514451009325 getTimeByValue(getTime) // prints: // 1514451024846 // 1514451024846

El resultado debe explicar la diferencia. El fragmento está disponible here .


Típicamente, los parámetros a las funciones son parámetros por valor; es decir, el valor del parámetro se determina antes de pasarlo a la función. Pero, ¿qué sucede si necesitamos escribir una función que acepte como parámetro una expresión que no queremos que se evalúe hasta que sea llamada dentro de nuestra función? Para esta circunstancia, Scala ofrece parámetros de llamada por nombre.

Un mecanismo de llamada por nombre pasa un bloque de código al destinatario y cada vez que accede al parámetro, se ejecuta el bloque de código y se calcula el valor.

object Test { def main(args: Array[String]) { delayed(time()); } def time() = { println("Getting time in nano seconds") System.nanoTime } def delayed( t: => Long ) = { println("In delayed method") println("Param: " + t) t } }

1. C:/>scalac Test.scala 2. scala Test 3. In delayed method 4. Getting time in nano seconds 5. Param: 81303808765843 6. Getting time in nano seconds


Ya hay muchas respuestas fantásticas para esta pregunta en Internet. Escribiré una compilación de varias explicaciones y ejemplos que he reunido sobre el tema, en caso de que alguien pueda encontrarlo útil.

INTRODUCCIÓN

llamada por valor (CBV)

Típicamente, los parámetros a las funciones son parámetros de llamada por valor; es decir, los parámetros se evalúan de izquierda a derecha para determinar su valor antes de evaluar la función en sí.

def first(a: Int, b: Int): Int = a first(3 + 4, 5 + 6) // will be reduced to first(7, 5 + 6), then first(7, 11), and then 7

llamada por nombre (CBN)

Pero, ¿qué sucede si necesitamos escribir una función que acepte como parámetro una expresión que no evaluemos hasta que sea llamada dentro de nuestra función? Para esta circunstancia, Scala ofrece parámetros de llamada por nombre. Lo que significa que el parámetro se pasa a la función tal como es, y su valoración tiene lugar después de la sustitución

def first1(a: Int, b: => Int): Int = a first1(3 + 4, 5 + 6) // will be reduced to (3 + 4) and then to 7

Un mecanismo de llamada por nombre pasa un bloque de código a la llamada y cada vez que la llamada accede al parámetro, se ejecuta el bloque de código y se calcula el valor. En el siguiente ejemplo, retrasado imprime un mensaje que demuestra que el método se ha ingresado. A continuación, retrasa imprime un mensaje con su valor. Finalmente, retrasa las devoluciones ''t'':

object Demo { def main(args: Array[String]) { delayed(time()); } def time() = { println("Getting time in nano seconds") System.nanoTime } def delayed( t: => Long ) = { println("In delayed method") println("Param: " + t) } }

En método retrasado
Obteniendo tiempo en nano segundos
Param: 2027245119786400

PROS Y CONTRAS POR CADA CASO

CBN: + Termina con más frecuencia * marque debajo de la terminación anterior * + Tiene la ventaja de que no se evalúa un argumento de función si el parámetro correspondiente no se usa en la evaluación del cuerpo de la función. Es más lento, crea más clases (lo que significa que el programa toma Más tiempo para cargar) y consume más memoria.

CBV: + A menudo es exponencialmente más eficiente que CBN, porque evita esta repetición de recálculos de los argumentos que conlleva la expresión por nombre. Evalúa cada argumento de función solo una vez + Juega mucho mejor con efectos imperativos y efectos secundarios, porque tiendes a saber mucho mejor cuándo se evaluarán las expresiones. -Puede llevar a un bucle durante la evaluación de sus parámetros * verifique la terminación anterior a la anterior *

¿Qué pasa si la terminación no está garantizada?

-Si la evaluación CBV de una expresión e termina, entonces la evaluación CBN de e termina también -La otra dirección no es verdadera

Ejemplo de no terminación

def first(x:Int, y:Int)=x

Considera la expresión primero (1, bucle)

CBN: primero (1, bucle) → 1 CBV: primero (1, bucle) → reducir los argumentos de esta expresión. Como uno es un bucle, reduce los argumentos infinitamente. No termina

DIFERENCIAS EN CADA CONDUCTA DE CASO

Vamos a definir una prueba de método que será

Def test(x:Int, y:Int) = x * x //for call-by-value Def test(x: => Int, y: => Int) = x * x //for call-by-name

Prueba de Case1 (2,3)

test(2,3) → 2*2 → 4

Ya que comenzamos con argumentos ya evaluados, serán la misma cantidad de pasos para la llamada por valor y la llamada por nombre

Prueba de Case2 (3 + 4,8)

call-by-value: test(3+4,8) → test(7,8) → 7 * 7 → 49 call-by-name: (3+4)*(3+4) → 7 * (3+4) → 7 * 7 → 49

En este caso, la llamada por valor realiza menos pasos.

Prueba de Case3 (7, 2 * 4)

call-by-value: test(7, 2*4) → test(7,8) → 7 * 7 → 49 call-by-name: (7)*(7) → 49

Evitamos el cálculo innecesario del segundo argumento.

Prueba de Case4 (3 + 4, 2 * 4)

call-by-value: test(7, 2*4) → test(7,8) → 7 * 7 → 49 call-by-name: (3+4)*(3+4) → 7*(3+4) → 7*7 → 49

Enfoque diferente

Primero, asumamos que tenemos una función con un efecto secundario. Esta función imprime algo y luego devuelve un Int.

def something() = { println("calling something") 1 // return value }

Ahora vamos a definir dos funciones que aceptan argumentos Int que son exactamente iguales, excepto que una toma el argumento en un estilo de llamada por valor (x: Int) y la otra en un estilo de llamada por nombre (x: => Int).

def callByValue(x: Int) = { println("x1=" + x) println("x2=" + x) } def callByName(x: => Int) = { println("x1=" + x) println("x2=" + x) }

Ahora, ¿qué sucede cuando los llamamos con nuestra función de efecto secundario?

scala> callByValue(something()) calling something x1=1 x2=1 scala> callByName(something()) calling something x1=1 calling something x2=1

Así que puedes ver que en la versión de llamada por valor, el efecto secundario de la llamada de función pasada (algo ()) solo ocurrió una vez. Sin embargo, en la versión de llamada por nombre, el efecto secundario ocurrió dos veces.

Esto se debe a que las funciones de llamada por valor calculan el valor de la expresión pasada antes de llamar a la función, por lo que se accede al mismo valor cada vez. Sin embargo, las funciones de llamada por nombre vuelven a calcular el valor de la expresión pasada cada vez que se accede.

EJEMPLOS DONDE ESTÁ MEJOR USAR CALL BY BY NAME

Desde: https://.com/a/19036068/1773841

Ejemplo de rendimiento simple: registro.

Imaginemos una interfaz como esta:

trait Logger { def info(msg: => String) def warn(msg: => String) def error(msg: => String) }

Y luego se usa así:

logger.info("Time spent on X: " + computeTimeSpent)

Si el método de información no hace nada (porque, por ejemplo, el nivel de registro se configuró para un nivel más alto que eso), computeTimeSpent nunca recibe llamadas, lo que ahorra tiempo. Esto sucede mucho con los registradores, donde a menudo se ve una manipulación de cadenas que puede ser costosa en relación con las tareas que se registran.

Ejemplo de corrección: operadores lógicos.

Probablemente has visto un código como este:

if (ref != null && ref.isSomething)

Imagina que declararías un método como este:

trait Boolean { def &&(other: Boolean): Boolean }

luego, siempre que la referencia sea nula, obtendrá un error porque se llamará a Algo en una referencia nula antes de pasar a &&. Por esta razón, la declaración real es:

trait Boolean { def &&(other: => Boolean): Boolean = if (this) this else other }


CallByName se invoca cuando se usa y callByValue se invoca cada vez que se encuentra la declaración.

Por ejemplo:-

Tengo un bucle infinito, es decir, si ejecuta esta función, nunca obtendremos una solicitud de scala .

scala> def loop(x:Int) :Int = loop(x-1) loop: (x: Int)Int

una función callByName toma el método de loop anterior como un argumento y nunca se usa dentro de su cuerpo.

scala> def callByName(x:Int,y: => Int)=x callByName: (x: Int, y: => Int)Int

En la ejecución del método callByName no encontramos ningún problema (nos devuelven el aviso de callByName ) ya que no estamos usando la función de bucle dentro de la función callByName .

scala> callByName(1,loop(10)) res1: Int = 1 scala>

una función callByValue toma el método de loop anterior como un parámetro, como resultado de que la función o expresión se evalúa antes de ejecutar la función externa allí mediante la función de loop ejecutada de forma recursiva y nunca recibimos una callByValue .

scala> def callByValue(x:Int,y:Int) = x callByValue: (x: Int, y: Int)Int scala> callByValue(1,loop(1))


Trataré de explicar con un simple caso de uso en lugar de simplemente proporcionar un ejemplo.

Imagina que quieres crear una "aplicación naga" que te agarra cada vez desde la última vez que te molestaron.

Examina las siguientes implementaciones:

object main { def main(args: Array[String]) { def onTime(time: Long) { while(time != time) println("Time to Nag!") println("no nags for you!") } def onRealtime(time: => Long) { while(time != time) println("Realtime Nagging executed!") } onTime(System.nanoTime()) onRealtime(System.nanoTime()) } }

En la implementación anterior, el Nagger funcionará solo cuando se pase por nombre, el motivo es que, al pasar por valor, se reutilizará y, por lo tanto, el valor no se reevaluará, mientras que al pasar por nombre, el valor se reevaluará cada hora en que se accede a las variables