Scala - parametry domniemane - motywacja

Odpowiedz Nowy wątek
2018-08-10 07:52
0

Po dłuższej przerwie wracam do nauki Scali. Może pytanie, które zadam jest po prostu jest głupie i równoważne z tym "po co zostały wprowadzone pętle", ale zastanawia mnie po co (jaka motywacja za tym stoi) wprowadzone zostały "parametry domniemane" (implicit parameters)?

Z przykładów praktycznych to przewija się automatyczna konwersja typów, wstrzykiwanie metod czy zależności. Natomiast nie wiem czy przykłady wynikają z tego, że najpierw pojawiły się parametry domniemane i przykłady są konsekwencją, czy może odwrotnie, najpierw pojawiły się problemy (będziemy potrzebować automatycznej konwersji typów) i wymyślono ten mechanizm, który ma również inne zastosowania.

edytowany 2x, ostatnio: yarel, 2018-08-10 07:54

Pozostało 580 znaków

2018-08-10 12:37
1

Hej,
ja myślę, że to trudne pytanie... Generalnie twórca Scali (Martin Odersky)... wprowadził pewne techniki umożliwiające domyślne działania funkcji lub jej konwersję w zależności od kontekstu... Między innymi umożliwia mu to korzystanie ze wszystkich dobrodziejstw Javy, ale można tworzyć też własne Scalowe odpowiedniki... Myślę, że także dzięki tej elastyczności można pracować na objektach Sparka jak na zwykłych objektach Scalowych, wykorzystując też przy tym Scalowe funkcje, np. filter, itp... Ale w Pythonie "konwersje" chyba robi się łatwiej:

def f(x):
    try:
       if type(x[0])=='int':
            return sum(x)
       else:
            return list(x)
    except:
        print("think a little about it")

Poczytaj sobie może to: http://www.lihaoyi.com/post/ImplicitDesignPatternsinScala.html Może ciut trywializuję problem... Pozdrawiam... :)

edytowany 7x, ostatnio: hurgadion, 2018-08-10 12:47

Pozostało 580 znaków

2018-08-10 13:33
2

Parametry implicit nie mają nic wspólnego z konwersjami typów. Są uogólnieniem wzorca type-classes z Haskella.
Są zaawansowaną formą programowania generycznego. Umożliwiają rozwiązanie choćby tzw. expression problem (https://en.wikipedia.org/wiki/Expression_problem).
W praktyce przekłada się to na możliwość pisania kodu, który łatwo rozszerzać o obsługę nowych typów bez konieczności modyfikacji istniejącego kodu.

Przykład: biblioteka standardowa wie jak posortować Stringi i wie jak posortować Inty. Jednak Ty chcesz wprowadzić własny typ Z, który też chcesz aby był sortowalny. Dzięki implicitom możesz to zrobić w taki sposób, że Twój typ będzie akceptowany we wbudowanych metodach sortBy, min, max, minBy wymagających porównywania elementów itp. Co więcej, dzieki implicitom np. krotka (Int, Int, Z) też będzie wtedy sortowalna. W słabszych językach (Java, Kotlin, C#) takie coś też da się do pewnego stopnia uzyskać korzystając z dziedziczenia i interfejsów, ale jest mocno ułomne.

A konwersje typów to raczej jakiś niezamierzony efekt uboczny implicitów. Nie należy tego tak używać.

edytowany 2x, ostatnio: Krolik, 2018-08-10 13:35

Pozostało 580 znaków

2018-08-10 13:50
0

Dzięki za linki, które sporo wyjaśniają i co dla mnie istotne, dają nowe spojrzenie.

Zastanawia mnie jeszcze jedno, czy w takim razie mixiny nie są w pewien sposób redundantne jeśli dysponujemy funkcjonalnością parametrów domniemanych?

Pozostało 580 znaków

2018-08-10 15:50
1

Może pytanie, które zadam jest po prostu jest głupie i równoważne z tym "po co zostały wprowadzone pętle", ale zastanawia mnie po co (jaka motywacja za tym stoi) wprowadzone zostały "parametry domniemane" (implicit parameters)?

Parametry implicit pojawiły się w którejś wersji Scali przy okazji przerabiania hierarchii kolekcji. Wprowadzono wtedy domniemany parametr CanBuildFrom, który służył do wielu rzeczy związanych z kolekcjami. Potem zauważono, że parametry implicit mają wiele innych zastosowań i można nimi emulować wiele konstrukcji znanych z innych języków (jak np wspomniane tutaj typeclasses z Haskella).

Zastanawia mnie jeszcze jedno, czy w takim razie mixiny nie są w pewien sposób redundantne jeśli dysponujemy funkcjonalnością parametrów domniemanych?

Trait ma dostęp do parametrów o widoczności protected (i może takie zawierać), obsługuje wielodziedziczenie poprzez linearyzację traitów (to rozwiązuje diamond problem) i może mieć składowe abstrakcyjne (niezaimplementowane). Zależnie od stylu programowania bardziej przydatne mogą być albo mixiny albo implicit parametry.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.

Pozostało 580 znaków

2018-08-10 16:42
0

Patrząc teraz od strony obiektowej, to wydaje mi się że jest to podobne do wyrzucenia na zewnątrz klasy pewnej logiki:

Pseudo-java-kod:

interface ExternalLogic<T> {
    boolean evaluateFoo(T x);
}
...
MyClass(Param param, ExternalLogic<T> externalLogic)    {
    this.externalLogic = externalLogic;
    this.param = param;
}

// Uzywa externalLogic do podjecia decyzji 
Object doSth()  {
    ...
}
...

Gdyby w Scali nie było "implicit", to nadal można by korzystać z tego wzorca, tylko (albo "aż") ręcznie uzupełniać "implicitParam" (tak, wiem, wtedy byłby "explicit" ;-) ), ewentualnie stworzyć sobie mechanizm, który nas od tego uwolni.

Jeśli dobrze zrozumiałem, to w Scali jest "bogatsza" realizacja takiego wzorca, gdyż:

  • błędy zostaną wykryte na etapie kompilacji
  • parametr domniemany zostanie "wstrzyknięty" (czyli tak jakbyśmy mieli funkcjonalność wstrzykiwania zależności)
  • kod będzie zwięzły
  • mechanizm znajduje się w standardzie języka

Pozostało 580 znaków

2018-08-10 17:05
0

Wstrzykiwanie będziesz miał jak wstawisz słówko implicit obok parametru konstruktora. Zwykle robi się wtedy dwie listy parametrów w konstruktorze, np:

class Klaska(parametrJawny: A)(implicit parametrDomniemany: B) {
 // (...)
}

Parametry implicit skracają kod. Czasami mocno, bo argumentem implicit może być wynik metody, która sama ma parametry implicit.

Dotty, czyli rozwojowa wersja Scali 3 idzie z implicitami jeszcze dalej: http://dotty.epfl.ch/docs/ref[...]/implicit-function-types.html


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0