2012-10-24 17 views
32

Próbuję tylko zrozumieć poniższy kod:Czy moje zrozumienie kodu poniżej scala jest poprawne?


Oto nowy typ alias Zestaw jest zadeklarowana która jest funkcją, która przyjmuje parametr Int i zwraca logiczną

type Set = Int => Boolean 

Tutaj deklarowana jest nowa metoda "zawiera", która przyjmuje dwa parametry typu Set i Int , która zwraca wartość logiczną. Wartość logiczna jest ustawiony do funkcji zadeklarowanych we wcześniejszym („typu Set = Int => Boolean”) Ale co logika jest wykonywana w celu określenia, czy int „elem” jest członkiem Ustaw „s”

def contains(set: Set, elem: Int): Boolean = set(elem) 

Tutaj jest zdefiniowana metoda, która zwraca zestaw, który zwraca funkcję?

def singletonSet(elem: Int): Set = set => set == elem 

Kompletny kod z komentarzami:

/** 
    * 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 
+8

Prosisz o odpowiedź na Coursera Scala przypisanie przedmiotu 2. –

+38

wierzę, po prostu poprosił o wyjaśnienie. W rzeczywistości biorę ten kurs już teraz i funkcjonalne programowanie jest dla mnie całkowicie nowe. Też mam problem z tym przypuszczeniem ... Nie chcę rozwiązania - tylko wytłumaczenie. A Paola poniżej dawała dokładnie to, czego potrzebowałem. – Moby04

+3

Ja też intuicyjnie napisałem to (ostatecznie), ale skorzystałem z odpowiedzi Paola. Nie każdy, kto tu przychodzi, próbuje oszukać. Dziękuję Moby za obronę dobrego punktu, w którym zadawano to pytanie. +1 – noogrub

Odpowiedz

79

Przeczytajmy rodzaj tyłu, w logicznym porządku.

Say masz skończony zbiór liczb całkowitych: 0, 1, 2, 3, 5, 8 na przykład

Jednym ze sposobów, aby opisać to zbiór liczb całkowitych jest przez funkcję (jej characteristic or indicator function), że dla każdej liczby całkowitej, zwraca prawdę, jeśli liczba całkowita jest w set, false, jeśli tak nie jest. Podpis dla tej funkcji, jak to opisaliśmy, musi zawsze być Int => Bool ("podaj liczbę całkowitą, powiem ci, jeśli jest w zestawie"), a jej implementacja będzie się różnić w zależności od konkretnego zestawu.

Do zestawu w moim przykładzie powyżej można napisać tej funkcji, po prostu jako:

val mySet: Int => Boolean = x => Array(0,1,2,3,5,8) contains x 

lub uznają, że ints w zestawie są pierwszymi sekwencji Fibonacciego i określić F w nieco bardziej wyrafinowany sposób (czego nie zrobię tutaj ...). Należy zauważyć, że "zawiera" użyłem jest zdefiniowany dla wszystkich kolekcji scala. W każdym razie teraz masz funkcję, która mówi ci, co jest w zestawie, a co nie. Spróbujmy w 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 

Teraz MYSET ma typ Int => Boolean, co możemy uczynić bardziej czytelny jeśli definiujemy ją jako rodzaj pseudonimu.

scala> type Set = Int => Boolean 
defined type alias Set 

Poza czytelności, definiowanie Set jak aliasem Int => Boolean czyni to wyraźnie zaznaczyć, że w pewnym sensie Set jest jej funkcja charakterystyczna. możemy przedefiniować MYSET w bardziej zwięzły (ale inaczej równoważnik) sposób z Set typu alias:

scala> val mySet: Set = x => Array(0,1,2,3,5,8) contains x 
mySet: Int => Boolean = <function1> 

teraz za ostatnim elementem tej długiej odpowiedzi.Zdefiniujmy charakterystyczną funkcję opisującą ten zestaw Singleton: 3. proste:

val Singleton3 : Set = set => set == 3 

dla zestawu Singleton zawierającego tylko 4, byłoby:

val Singleton4 : Set = set => set == 4 

Tak, niech uogólniać tworzenie tych funkcji i napisać metodę, która zwraca funkcję Singleton, że dla liczbą całkowitą opisuje zestawu zawierającego że całkowita:

def singletonSet(elem: Int): Set = set => set == elem 

DODATEK:

pominąłem tę część, ponieważ nie było naprawdę potrzebne: def contains(set: Set, elem: Int): Boolean = set(elem)

Myślę, że to rodzaj bezcelowe i (bez więcej kontekstu) wygląda podobnie jak contrived przykład wykazać, w jaki sposób może przekazać funkcję jako argument, tak jak każdy inny typ w scala. Zajmuje funkcję Int => Bool i Int i dotyczy tylko funkcja do Int więc można zrobić

scala> contains(mySet, 3) 
res2: Boolean = true 

który jakby wzywając mySet(3) bezpośrednio.

+2

Zgadzam się z twoim dodatkiem: To jest zasadniczo Kościół Kodowanie zbiorów w Rachunku Lambda (co jest zaskakujące jest również Kodowanie Obiektowe - patrz [* O Zrozumieniu Abstrakcji Danych, Ponownie] * (http: // CS. UTexas.Edu/~wcook/Drafts/2009/essay.pdf) autorstwa [William R. Cook] (http://WCook.BlogSpot.Com/), aby zrozumieć dlaczego). Zwykła sztuczka polega właśnie na tym, że zestaw jest jednocześnie obiektem i charakterystyczną funkcją, a ta metoda "zawiera" niepotrzebnie zaciemnia ten piękny projekt. –

+0

@ JörgWMittag Piękny artykuł, dzięki! –

+0

@PaoloFalabella Jaka jest wulgarna metoda dla "val Singleton4: Set = set => set == 4" Nie mogę zrozumieć, skąd pochodzi parametr "set" z –

4

Po obejrzeniu wideo wykład na temat „currying”, uważam, że rozwiązanie Paolo wyrażane w sposób bardziej opisowym jest:

def singletonSet(elem: Int): Set = { 
    def innerFunction (givenElement: Int) = 
     if (elem == givenElement) true 
     else false 
     innerFunction 
    } 

Plesae mnie poprawić jeśli się mylę!

+1

Jest to dużo krócej przy użyciu anonimowej funkcji: 'def singletonSet (elem: Int): Set = (x: Int) => elem == x' –

+0

Metoda singletonSet zwraca zestaw, gdzie ponieważ zamknięcie zwraca wartość boolowską. Jestem zmieszany. –

1

Aby odpowiedzieć na to pytanie - Ale co logika jest wykonywana w celu określenia, czy int „elem” jest członkiem Ustaw „s”

ta wykonywana jest po dokonaniu faktycznej wywołanie funkcji. Rozważ następujące wywołanie funkcji.

zawiera (singletonSet (1) 1)

Teraz singletonSet jest zdefiniowany jako def singletonSet (elem: int): Ustaw = x => x == elem (I zdecydować się na stosowanie identyfikator x dla jasności). Zwracany typ singletonSet jest funkcją typu Set, który pobiera argument Int i zwraca wartość logiczną. Tak więc pierwszy argument powyższych wywołanie funkcji za singletonSet (1) równa się funkcji x => x == 1 jako elem tu jest 1. Więc mamy

zawiera ((x => x == 1) , 1)

rozważa definicji zawiera funkcję zawiera def (f: Set elem INT) logiczny = f (elem). Pierwszym argumentem w powyższym wywołaniu jest funkcja x => x == 1, która zastępuje parametr formalny f, a drugi argument 1 zastępuje formalny parametr elem. Wartość zwracana zawiera funkcję f (elem), która jest równa f (1). Ponieważ f (x) jest zdefiniowane jako (x == 1), f (1) jest równe (1 == 1), które zwraca wartość true.

Idąc tą samą logiką, wywołanie funkcji jak zawiera (singletonSet (1), 2) ostatecznie utożsamia się z (1 == 2), co zwróci wartość false.

+0

Ramya, jak by to działało w następującym scenariuszu? def zawiera (s: Set, elem: Int): Boolean = s (elem); val set: Set = Set (1,2,3,4); zawiera (zestaw, 5); W tym przypadku utworzyłem zestaw więcej niż 1 wartości. A to działa doskonale. Czy iteracja dla wszystkich wartości jedna po drugiej? – Rahul

0

Przejmuję teraz kurs, byłem także zdezorientowany, ale myślę, że teraz rozumiem.

def singletonSet(elem: Int): Set = (x : Int) => x == elem

tutaj singletonSet jest funkcja, która zwraca funkcję z typem Ustaw, który jest zdefiniowany jako type Set = Int => Boolean

więc kiedy zadzwonić def contains(s:Set, elem:Int): Boolean = s(elem), na przykład: contains(singletonSet(1), 2), singletonSet (1) jest zwracając funkcję z elem (w definicji singletonSet) ustawioną na 1, a 2 (również zdefiniowane jako elem, ale jest zdefiniowane w parametrze zawiera) jest przekazywane jako x w definicji singletonSet, musimy pozbyć się java set idea, nie potrzebujemy singletonSet do utrzymywania ustawionej przez nas wartości.

Dla lepszego zrozumienia, możemy zmienić nazwę parametru w następujący sposób:

def singletonSet(elemToStore: Int): Set = (x : Int) => x == elemToStore

def contains(s: Set, elemToCheck: Int): Boolean = s(elemToCheck)

Powiązane problemy