software - ¿Es correcto mi entendimiento del siguiente código scala?
scala vs java (4)
Después de ver el video de la conferencia sobre "Currying", creo que la solución de Paolo expresada de una manera más detallada es:
def singletonSet(elem: Int): Set = {
def innerFunction (givenElement: Int) =
if (elem == givenElement) true
else false
innerFunction
}
¡Plesae me corrige si estoy equivocado!
Solo trato de entender el siguiente código:
Aquí se declara un nuevo alias tipo Set, que es una función que toma un parámetro Int y devuelve un booleano
type Set = Int => Boolean
Aquí se declara un nuevo método ''contains'', que toma dos parámetros de tipo Set e Int que devuelve un booleano. El valor booleano se establece en la función declarada anteriormente (''type Set = Int => Boolean'') Pero qué lógica se realiza para determinar si el ''elem'' Int es un miembro de Set ''s''
def contains(set: Set, elem: Int): Boolean = set(elem)
Aquí se define un método que devuelve un conjunto que devuelve una función?
def singletonSet(elem: Int): Set = set => set == elem
Código completo con comentarios:
/**
* We represent a set by its characteristic function, i.e.
* its `contains` predicate.
*/
type Set = Int => Boolean
/**
* Indicates whether a set contains a given element.
*/
def contains(set: Set, elem: Int): Boolean = set(elem)
/**
* Returns the set of the one given element.
*/
def singletonSet(elem: Int): Set = set => set == elem
Estoy tomando el curso ahora, también estaba confundido, pero creo que entiendo el punto ahora.
def singletonSet(elem: Int): Set = (x : Int) => x == elem
aquí singletonSet es una función que devuelve una función con el tipo Set , que se define como type Set = Int => Boolean
así que cuando llame def contains(s:Set, elem:Int): Boolean = s(elem)
, por ejemplo: contains(singletonSet(1), 2)
, singletonSet (1) devuelve una función con elem (en la definición de singletonSet) establecido en 1, y el 2 (también definido como elem, pero se define en el parámetro de contiene) se pasa como la x en la definición de singletonSet, tenemos que deshacernos de la idea de conjunto de java, no necesitamos el singletonSet para persistir el valor que establecemos.
Para una mejor comprensión, podemos cambiar el nombre del parámetro de la siguiente manera:
def singletonSet(elemToStore: Int): Set = (x : Int) => x == elemToStore
def contains(s: Set, elemToCheck: Int): Boolean = s(elemToCheck)
Leamos un poco al revés, en orden lógico.
Supongamos que tiene un conjunto finito de enteros: 0, 1, 2, 3, 5, 8
por ejemplo
Una forma de describir este conjunto de enteros es a través de una función (su característica o función indicadora ) que, para cada entero, devuelve verdadero si el entero está en el conjunto, falso si no lo es. La firma para esta función, tal como la describimos, debe ser siempre Int => Bool
("proporcióneme un número entero, le diré si está en el conjunto"), mientras que su implementación variará dependiendo del conjunto específico.
Para el conjunto en mi ejemplo anterior, puede escribir esta función simplemente como:
val mySet: Int => Boolean = x => Array(0,1,2,3,5,8) contains x
o reconocer que las entradas en el conjunto son las primeras de la secuencia de Fibonacci y definen f de una manera un poco más sofisticada (que no haré aquí ...). Tenga en cuenta que el "contiene" que he usado se define para todas las colecciones de scala. En cualquier caso, ahora tienes una función que te dice qué hay en el conjunto y qué no. Probémoslo en el REPL.
scala> val mySet: Int => Boolean = x => Array(0,1,2,3,5,8) contains x
mySet: Int => Boolean = <function1>
scala> mySet(3)
res0: Boolean = true
scala> mySet(9)
res1: Boolean = false
Ahora, mySet tiene tipo Int => Boolean
, que podemos hacer más legible si lo definimos como un alias de tipo.
scala> type Set = Int => Boolean
defined type alias Set
Además de la legibilidad, definir Set
como un alias de Int => Boolean
hace que sea explícito que de alguna manera un conjunto es su función característica. Podemos redefinir mySet de una manera más concisa (pero por lo demás equivalente) con el alias Set
type:
scala> val mySet: Set = x => Array(0,1,2,3,5,8) contains x
mySet: Int => Boolean = <function1>
Ahora para la última parte de esta larga respuesta. Definamos una función característica para describir este conjunto de Singleton: 3
. Fácil:
val Singleton3 : Set = set => set == 3
para un conjunto de Singleton que contiene solo 4, sería:
val Singleton4 : Set = set => set == 4
Por lo tanto, generalicemos la creación de estas funciones y escriba un método que devuelva una función Singleton que, para cualquier número entero, describa el conjunto que contiene solo ese entero:
def singletonSet(elem: Int): Set = set => set == elem
APÉNDICE:
Me salteé esta parte, porque no era realmente necesaria: def contains(set: Set, elem: Int): Boolean = set(elem)
Creo que es algo sin sentido y (sin más contexto) se ve como un ejemplo artificial para demostrar cómo se puede pasar una función como un argumento, al igual que cualquier otro tipo en Scala. Toma la función Int => Bool
y la Int
y simplemente aplica la función al Int
para que pueda hacer
scala> contains(mySet, 3)
res2: Boolean = true
que es como llamar a mySet(3)
directamente.
Para responder a su pregunta: ¿Pero qué lógica se realiza para determinar si el ''elem'' Int es miembro de Set ''s''?
Esto se realiza cuando realiza la llamada a la función real. Considere la siguiente llamada de función.
contiene (singletonSet (1), 1)
Ahora singletonSet se define como def singletonSet (elem: Int): Set = x => x == elem (elijo usar el identificador x para mayor claridad). El tipo de retorno de singletonSet es la función de tipo Set que toma un argumento Int y devuelve Boolean. Así que el primer argumento de la función de llamada anterior, singletonSet (1) equivale a la función x => x == 1 ya que elem aquí es 1. Entonces obtenemos
contiene ((x => x == 1), 1)
Ahora, considerando la definición de contiene función def contiene (f: Set, elem: Int): Boolean = f (elem) . El primer argumento en la llamada anterior es la función x => x == 1 que sustituye el parámetro formal f y el segundo argumento 1 sustituye al parámetro formal elem. El valor de retorno de contiene es la función f (elem) que equivale a f (1). Como f (x) se define como (x == 1), f (1) equivale a (1 == 1) que devuelve verdadero.
Siguiendo la misma lógica, una llamada a función como contiene (singletonSet (1), 2) finalmente equivaldría a (1 == 2) que devolverá false.