tl; dr
Odpowiedzi udzielone do tej pory (o @wbarksdale, @PlexQ i @Daniel C. Sobral w komentarzu) są wystarczająco dobre, aby kierować problem opisany tutaj.
Ale brakuje im prawdziwego wyjaśnienia, dlaczego początkowy kod, używając foreach
, nie działa.
To nie działa, ponieważ foreach
zwraca Unit
.
zabaw koncepcje
Podam krótki nuty/przypomnieć o tym, jak działają szablony.
System szablonów Scala dostarczany domyślnie w Play Framework 2 jest rzeczywiście oparty na koncepcjach FP i dlatego używa wielu niezmiennych struktur i tak dalej.
Co więcej, taki szablon Scala (powiedzmy myTemplate.scala.html
) zostanie wkompilowany w zwykłą Scalę object
, która nazywa się metoda apply
. Ta ostatnia funkcja umożliwia nam wywołanie obiektu jako funkcji z niektórymi parametrami (zadeklarowanymi w pierwszym wierszu szablonu).
Ten object
opiera się również na konstrukcji podobnej do BaseScalaTemplate
, która jest zbudowana za pomocą formatera wyjściowego (HTML). Ten formatator będzie mógł pobierać elementy (takie jak String
, Unit
, Seq[Int]
,, ...) i renderować je do kodu HTML.
formatowanie nastąpi podczas stosując metodę _display_
z BaseScalaTemplate
, która zwraca wystąpienie sformatowane wyjściu. Ta metoda wyświetlania zostanie wywołana w kodzie skompilowanym pliku .scala.html
w treści obiektu obiektu apply
.
więc organizm może skończyć tak:
def apply/*1.2*/(testMap:scala.collection.immutable.Map[String, Int]):play.api.templates.Html =
_display_ {
Seq[Any](
_display_(
Seq[Any](
/*3.2*/testMap/*3.9*/.map/*3.13*/ { e =>
_display_(Seq[Any](_display_(Seq[Any](/*5.3*/e))))
}
)
)
)
}
See? Wywołania _display_
niczego nie mutują, ale są skomponowane w taki sposób, że samo zastosowanie zwróci instancję sformatowanego kodu (Html
)!
To daje nam wskazówkę ...
tak bla bla ... teraz, dlaczego?
Po tych błyskawicach, które zostały podane o urządzeniach Play, możemy teraz zmierzyć się z prawdziwym pytaniem: dlaczego, do cholery, jest idealny kod Scala podany w pytaniu, nie działa ... czytaj, nic nie wyświetla na wszystko.
Jest to dość proste, przy użyciu foreach
na Map
, jesteś rzeczywiście zapętlenie nad elementami i dostosowania je do HTML. Jednak te obliczenia nie będą możliwe do zastosowania przez system szablonów, ponieważ są one zawarte w pętli foreach
. To jest foreach
musi być użyte, gdy efekty uboczne są wymagane dla każdego elementu w sekwencji ... I wróć Unit
kiedy to się stanie.
Ponieważ system szablonów spróbuje _display_
wynikiem foreach
na danym Map
będzie to po prostu renderowania/format Unit
a tym samym pustym String
!
Podsumowując, wystarczy użyć map
która będzie zwracać nową sekwencję utrzymującą dostosowany przedmioty, instancja Html
.
Hmmm a co z numerem for
?
Tak, masz rację ... Na podstawie tego, co zostało powiedziane, dlaczego są odpowiedzi, że proponowane użył pracy for
pętli, ponieważ bez uzyskując wartość, o for
jest równoważna foreach
! (Wprowadzenie yield
zakończy się map
-Jak zachowań)
Odpowiedź jest w kodzie ... Kompilator Szablon będzie poprzedzić yield
słowa kluczowego do ciała for
„s - to sprawdzić here.:-D
Et voilà, że działa zbyt, ponieważ wygenerowane spożywczych w organizmie for
„s zostanie dołączony do zwracanego sekwencji po jej zakończeniu.
Nie mam dużego doświadczenia z Play, ale czy to dlatego, że typem zwrotu foreach jest 'Unit'? Czy próbowałeś użyć 'map' zamiast? – Gareth
@Gareth Myślę, że gdzie masz rację, zmieniłem pętlę, aby użyć składni 'for()' zamiast wywoływania metody 'foreach()' i zadziałało – wbarksdale