una poligono para pairs mas librerias graficos graficas graficar funcion ejemplos codigo scala

scala - poligono - pairs en r



¿Cuál es la diferencia entre "def" y "val" para definir una función (7)

Cuál es la diferencia entre:

def even: Int => Boolean = _ % 2 == 0

y

val even: Int => Boolean = _ % 2 == 0

Ambos pueden ser llamados como even(10) .


Además de las respuestas útiles anteriores, mis conclusiones son:

def test1: Int => Int = { x => x } --test1: test1[] => Int => Int def test2(): Int => Int = { x => x+1 } --test2: test2[]() => Int => Int def test3(): Int = 4 --test3: test3[]() => Int

Lo anterior muestra que "def" es un método (con parámetros de cero argumentos) que devuelve otra función "Int => Int" cuando se invoca.

La conversión de métodos a funciones está bien explicada aquí: https://tpolecat.github.io/2014/06/09/methods-functions.html


Además, Val es una evaluación por valor. Lo que significa que la expresión del lado derecho se evalúa durante la definición. Donde Def es por evaluación de nombre. No se evaluará hasta que se use.


Considera esto:

scala> def even: (Int => Boolean) = { println("def"); (x => x % 2 == 0) } even: Int => Boolean scala> val even2: (Int => Boolean) = { println("val"); (x => x % 2 == 0) } val //gets printed while declaration. line-4 even2: Int => Boolean = <function1> scala> even(1) def res9: Boolean = false scala> even2(1) res10: Boolean = false

¿Ves la diferencia? En breve:

def : para cada llamada a even , llama al cuerpo del método even nuevamente. Pero con even2 es decir, val , la función se inicializa solo una vez mientras se declara (y por lo tanto imprime val en la línea 4 y nunca más) y se usa la misma salida cada vez que se accede. Por ejemplo intenta hacer esto:

scala> import scala.util.Random import scala.util.Random scala> val x = { Random.nextInt } x: Int = -1307706866 scala> x res0: Int = -1307706866 scala> x res1: Int = -1307706866

Cuando se inicializa x , el valor devuelto por Random.nextInt se establece como el valor final de x . La próxima vez que se vuelva a utilizar x , siempre devolverá el mismo valor.

También puede inicializar perezosamente x . Es decir, la primera vez que se usa, se inicializa y no mientras se declara. Por ejemplo:

scala> lazy val y = { Random.nextInt } y: Int = <lazy> scala> y res4: Int = 323930673 scala> y res5: Int = 323930673


La ejecución de una definición como def x = e no evaluará la expresión e. En lugar de e se evalúa cada vez que se invoca x.

Alternativamente, Scala ofrece una definición de valor val x = e , que evalúa el lado derecho como parte de la evaluación de la definición. Si luego se usa x, se reemplaza inmediatamente por el valor precalculado de e, por lo que no es necesario evaluar la expresión nuevamente.


Method def even evalúa en llamada y crea una nueva función cada vez (nueva instancia de Function1 ).

def even: Int => Boolean = _ % 2 == 0 even eq even //Boolean = false val even: Int => Boolean = _ % 2 == 0 even eq even //Boolean = true

Con def puede obtener una nueva función en cada llamada:

val test: () => Int = { val r = util.Random.nextInt () => r } test() // Int = -1049057402 test() // Int = -1049057402 - same result def test: () => Int = { val r = util.Random.nextInt () => r } test() // Int = -240885810 test() // Int = -1002157461 - new result

val evalúa cuando se define, def - cuando se llama:

scala> val even: Int => Boolean = ??? scala.NotImplementedError: an implementation is missing scala> def even: Int => Boolean = ??? even: Int => Boolean scala> even scala.NotImplementedError: an implementation is missing

Tenga en cuenta que hay una tercera opción: lazy val .

Se evalúa cuando se llama la primera vez:

scala> lazy val even: Int => Boolean = ??? even: Int => Boolean = <lazy> scala> even scala.NotImplementedError: an implementation is missing

Pero devuelve el mismo resultado (en este caso, la misma instancia de FunctionN ) cada vez:

lazy val even: Int => Boolean = _ % 2 == 0 even eq even //Boolean = true lazy val test: () => Int = { val r = util.Random.nextInt () => r } test() // Int = -1068569869 test() // Int = -1068569869 - same result

Actuación

val evalúa cuando se define.

def evalúa en cada llamada, por lo que el rendimiento podría ser peor que el val de val para múltiples llamadas. Obtendrá el mismo rendimiento con una sola llamada. Y sin llamadas, no tendrá gastos generales desde la def , por lo que puede definirlo incluso si no lo usará en algunas sucursales.

Con un valor lazy val obtendrás una evaluación perezosa: puedes definirlo incluso si no lo usarás en algunas sucursales, y se evalúa una vez o nunca, pero obtendrás un poco de sobrecarga por el doble control en cada acceso a tu lazy val .

Como @SargeBorsch señaló, podría definir el método, y esta es la opción más rápida:

def even(i: Int): Boolean = i % 2 == 0

Pero si necesita una función (no un método) para la composición de la función o para funciones de orden superior (como filter(even) ), el compilador generará una función desde su método cada vez que la use como una función, por lo que el rendimiento podría ser un poco peor que con val .


Mira esto:

var x = 2 // using var as I need to change it to 3 later val sq = x*x // evaluates right now x = 3 // no effect! sq is already evaluated println(sq)

Sorprendentemente, esto imprimirá 4 y no 9! val (incluso var) se evalúa inmediatamente y se asigna.
Ahora cambia de val a def .. se imprimirá 9! Def es una llamada de función ... evaluará cada vez que se llame.


val es decir "sq" es por definición de Scala es fijo. Se evalúa en el momento de la declaración, no se puede cambiar más adelante. En otros ejemplos, donde even2 también es val, pero se declara con la firma de función, es decir, "(Int => Boolean)", por lo que no es el tipo Int. Es una función y su valor se establece mediante la siguiente expresión

{ println("val"); (x => x % 2 == 0) }

Según la propiedad val Scala, no puede asignar otra función a even2, la misma regla que sq.

¿Sobre por qué llamar a la función val eval2 no imprimir "val" una y otra vez?

Código original:

val even2: (Int => Boolean) = { println("val"); (x => x % 2 == 0) }

Sabemos que, en Scala, la última declaración del tipo de expresión anterior (dentro de {..}) es en realidad volver al lado izquierdo. Así que terminas configurando even2 en la función "x => x% 2 == 0", que coincide con el tipo que declaraste para el tipo de valor de even2, es decir (Int => Boolean), por lo que el compilador está contento. Ahora even2 solo apunta a la función "(x => x% 2 == 0)" (no a ninguna otra declaración antes, es decir, println ("val") etc. Invocar event2 con diferentes parámetros realmente invocará "(x => x% 2 == 0) "código, ya que solo se guarda con event2.

scala> even2(2) res7: Boolean = true scala> even2(3) res8: Boolean = false

Solo para aclarar esto más, la siguiente es una versión diferente del código.

scala> val even2: (Int => Boolean) = { | println("val"); | (x => { | println("inside final fn") | x % 2 == 0 | }) | }

Lo que sucederá ? Aquí vemos "dentro de fn final" impreso una y otra vez, cuando llama a even2 ().

scala> even2(3) inside final fn res9: Boolean = false scala> even2(2) inside final fn res10: Boolean = true scala>