W Function representation in Scala trafiłem na:
val add:(Int, Int) => Int = (x,y) => x + ypodczas gdy większość przykładów, które do tej pory napotkałem definiowały funkcję jak poniżej:
def add(x: Int, y: Int): Int = x + yNiby nic odkrywczego, ale przywołały mi różnicę między funkcjami a symbolami (aka vars), które wskazują na funkcje w Clojure. W programowaniu funkcyjnym funkcje są pierwszej kategorii, więc można je przypisywać, akceptować na wejściu do funkcji i zwracać jako wyjście. Dokładnie tak, jak ma to miejsce w Javie z obiektami, co pozwala nazwać Javę obiektowym językiem.
Również w Thread: Code in book as transcript in REPL pojawiła się ciekawa cecha Scala REPL:
scala> scala> println("Hello, World!") // Detected repl transcript paste: ctrl-D to finish. Hello, World! // Replaying 1 commands from transcript. scala> println("Hello, World!") Hello, World!Wystarczy wkleić dowolną kombinację powyższych linii i REPL wykryje, że wkleiliśmy kawałek kodu, który był prezentowany jako wynik działania REPL. Użyteczna cecha scalowego REPLa. Trochę pokręcone przy próbie wytłumaczenia, więc zachęcam do samodzielnego popróbowania się z tym.
Jeszcze trafiłem na słówko lazy, które jak łatwo było się domyśleć ma służyć opóźnieniu wykonania obliczenia.
scala> lazy val a = 4 + 4 a: Int = <lazy> scala> a res13: Int = 8Nie spędziłem specjalnie wiele czasu na poszukiwania i poprzestanę na poniższym, aby uzmysłowić leniwe obliczenie.
scala> lazy val b = { println("Ala ma kota"); } b: Unit = <lazy> scala> b Ala ma kotaGdyby usunąć lazy wykonanie przypisania będzie wykonane natychmiast i wyświetli się napis "Ala ma kota", tak jak wykonanie b z lazy powyżej.
Na zakończenie, czytając player/winner typo, zwróciłem uwagę na
if (p1.score > p2.score) declareWinner(p1) else declareWinner(p2)które powtarza wywołanie funkcji declareWinner. Sądzę, że możnaby zamienić to na reduce. W Clojure już mam, pracuję nad wersją w Scali. Może ktoś pomoże?
Poniżej kod w Clojure. Uzmysławia stosowanie mapy jako jednej z podstawowych struktur danych (coś ala javowy obiekt) oraz map i reduce - filary programowania funkcyjnego w Clojure.
$ lein2 repl nREPL server started on port 55072 Welcome to REPL-y! Clojure 1.3.0 Exit: Control+D or (exit) or (quit) Commands: (help) Docs: (doc function-name-here) (find-doc "part-of-name-here") Source: (source function-name-here) (sourcery function-name-here) Javadoc: (javadoc java-object-or-class-here) Examples from clojuredocs.org: (clojuredocs name-here) (clojuredocs "ns-here" "name-here") nil user=> (def players {:p1 10 :p2 20 :p3 15 :p4 8 :p5 2}) #'user/players user=> (defn pme [me] [(me 0) (me 1)]) #'user/pme user=> (map pme players) ([:p1 10] [:p3 15] [:p2 20] [:p4 8] [:p5 2]) user=> (defn >me [me1 me2] (if (> (val me2) (val me1)) me2 me1)) #'user/>me user=> (reduce >me players) [:p2 20] user=> (defn declareWinner [[name score]] (format "Player %s won (score: %s)" name score)) #'user/declareWinner user=> (declareWinner (reduce >me players)) "Player :p2 won (score: 20)"Proszę pytać, jak coś niejasne. Chętnie udzielę odpowiedzi.
Śledzę sobie Twoje zmagania ze Scalą.
OdpowiedzUsuńJeśli chodzi o drugą definicję add, to zwracam uwagę, że to nie jest funkcja tylko metoda. To nie to samo. Funkcje są wartościami, a metody nie są.
Ponadto może Cię zainteresują inne jeszcze definicje:
val add = (x:Int,y:Int) => x + y
val add:(Int, Int) => Int = _ + _
val add = (_:Int) + (_:Int)
object add { def apply(x:Int, y:Int) = x+y }
val add = new Function2[Int,Int,Int] { def apply(x:Int, y:Int) = x+y }
Grzegorz
Jeszcze reduce:
OdpowiedzUsuńval players = Map( 'p1 -> 10, 'p2 -> 20, 'p3 -> 15, 'p4 -> 8, 'p5 -> 2 )
players.reduce{(a,b) => if(a._2 > b._2) a else b}
Grzegorz