Reaktive Programmierung Vorlesung 8 vom 15.05.19 Meta-Programmierung
Christoph Lüth, Martin Ring Universität Bremen Sommersemester 2019
17:06:11 2019-07-10 1 [18]
Fahrplan
IEinführung
IMonaden und Monadentransformer INebenläufigkeit: Futures and Promises IAktoren I: Grundlagen
IAktoren II: Implementation IMeta-Programmierung IBidirektionale Programmierung IReaktive Ströme I
IReaktive Ströme II
IFunktional-Reaktive Programmierung ISoftware Transactional Memory IEventual Consistency IRobustheit und Entwurfsmuster ITheorie der Nebenläufigkeit, Abschluss
RP SS 2019 2 [18]
Was ist Meta-Programmierung?
“Programme höherer Ordnung” / Makros
Source Compiler Program
RP SS 2019 3 [18]
Was sehen wir heute?
IAnwendungsbeispiel: JSON Serialisierung IMeta-Programmierung in Scala:
IScala Meta
IMeta-Programmierung in Haskell:
ITemplate Haskell
IGenerische Programmierung in Scala und Haskell
RP SS 2019 4 [18]
Beispiel: JSON Serialisierung
Scala
case class Person(
names : L i s t [ String ] , age : Int
)
Haskell
data Person = Person { names :: [ String ] , age :: Int }
Ziel: Scala←−−−→JSON Haskell
RP SS 2019 5 [18]
JSON: Erster Versuch
JSON1.scala
IUnpraktisch: Für jeden Typ muss manuell eine Instanz erzeugt werden IIdee: Makros for the win
RP SS 2019 6 [18]
Klassische Metaprogrammierung (Beispiel C)
#define square (n) ((n)∗(n) )
#define UpTo( i , n) for(( i ) = 0; ( i )<(n) ; ( i )++) UpTo( i ,10) {
p r i n t f (" i squared i s : %d\n", square ( i ) ) ; }
IEigene Sprache: C Präprozessor
IKeine Typsicherheit: einfache String Ersetzungen
RP SS 2019 7 [18]
Metaprogrammierung in Scala: Scalameta
IIdee: Der Compiler ist im Programm verfügbar
>"x + 2∗ 7". parse [Term ] . get . structure
Term. ApplyInfix (Term.Name("x") , Term.Name("+") , Nil , Seq(Term. ApplyInfix ( L i t . Int (2) , Term.Name("∗") , Nil , Seq( L i t . Int (7) ) ) ) )
IAbstrakter syntaxbaum (AST) als algebraischer Datentyp→typsicher ISehr komplexer Datentyp . . .
RP SS 2019 8 [18]
Quasiquotations
IIdee: Programmcode statt AST IZur Konstruktion . . .
>val p = q"case c l a s s Person(name: String ) "
p : meta . Defn . Class =case class Person(name: String ) I. . . und zur Extraktion
>val q"case c l a s s $name($param) "= p name: meta . Type .Name = Person
param : scala . meta .Term.Param = name: String
RP SS 2019 9 [18]
Makro Annotationen
IIdee: FunktionAST→ASTzur Compilezeit ausführen IWerkzeug: Annotationen
class h e l l o extends StaticAnnotation {
inline def apply ( defn : Any) : Any = meta { defnmatch{ caseq" object $name { . . $members }"⇒
q""" object $name { . . $members
def h e l l o : Unit = p r i n t l n ("Hello" ) }"""
case_⇒ abort ("@h e l l o must annotate an object ") } }
}
@h e l l o object Test
RP SS 2019 10 [18]
JSON: Zweiter Versuch
JSON2.scala
IGenerische Ableitungen fürcase classes IFunktioniert das für alle algebraischen Datentypen?
RP SS 2019 11 [18]
Generische Programmierung
IBeispiel: YAML statt JSON erzeugen
IIdee: Abstraktion über die Struktur von Definitionen
IErster Versuch:ToMap. scala IDas klappt so nicht . . . IKeine geeignete Repräsentation!
RP SS 2019 12 [18]
Heterogene Listen
IGenerische Abstraktion von Tupeln
>val l = 42 : : "foo" : : 4.3 : : HNil l : Int : : String : : Double : : HNil = . . .
IViele Operationen normaler Listen vorhanden:
IWas ist der parameter fürflatMap?
⇒Polymorphe Funktionen
RP SS 2019 13 [18]
Records
IUns fehlen namen IDafür: Records
>import shapeless ._; record ._; import syntax . singleton ._
>val person = ("name"→>"Donald") : : ("age"→> 70) : : HNil
person : String withKeyTag[ String ("name") , String ] : : Int withKeyTag[ String ("age") , Int ] : : HNil = Donald : : 70 : : HNil
> person ("name") res1 : String = Donald
RP SS 2019 14 [18]
Die Typklasse Generic
ITypklasseGeneric [T]
t r a i t Generic [T] { type Repr
def from( r : Repr) : T def to ( t : T) : Repr }
Ikann magisch abgeleitet werden:
>case class Person(name: String , age : Int )
>val gen = Generic [ Person ]
gen : shapeless . Generic [ Person ]{typeRepr = String : : Int : : shapeless . HNil} = . . .
I→Makro Magie
IFunktioniert allgemein für algebraische Datentypen
RP SS 2019 15 [18]
JSON Serialisierung: Teil 3
JSON3. scala
RP SS 2019 16 [18]
Automatische Linsen
case class Address( s t r e e t : String , c i t y : String , zip : Int ) case class Person(name: String , age : Int , address : Address) val streetLens = lens [ Person ] >> ’ address >> ’s t r e e t
RP SS 2019 17 [18]
Zusammenfassung
IMeta-Programmierung: “Programme Höherer Ordnung”
IScalameta: Scala in Scala manipulieren IQuasiquotations: Reify and Splice
IMacros mit Scalameta:AST→ASTzur Compilezeit IÄquivalent in Haskell: TemplateHaskell
IGenerische Programmierung in Shapeless IÄquivalent in Haskell: GHC.Generic
RP SS 2019 18 [18]