SlideShare ist ein Scribd-Unternehmen logo
1 von 45
Downloaden Sie, um offline zu lesen
Functional	OO	ImperativeFunctional	OO	Imperative
ScalaScala
関数型オブジェクト指向命関数型オブジェクト指向命
令型	Scala令型	Scala
Sébastien	Doeraene	--	セバスチャン·ドゥラン
June	28,	2019	--	Scala	Matsuri	--	2019年6⽉28⽇
@sjrdoeraene
Scala	Center,	
École	polytechnique	fédérale	de	Lausanne
 
	           	
scala.epfl.ch
1
BasicsBasics
Japanese	line	1
Japanese	line	2
2
def times2(xs: List[Int]): List[Int] = {
var result: List[Int] = Nil
var i = 0
while (i < xs.length) {
result = result :+ (xs(i) * 2)
i += 1
}
result
}
3
def times2(xs: List[Int]): List[Int] = {
var result: List[Int] = Nil
for (i <- 0 until xs.length) {
result = result :+ (xs(i) * 2)
}
result
}
4
def times2(xs: List[Int]): List[Int] = {
val builder = List.newBuilder[Int]
for (i <- 0 until xs.length) {
builder += xs(i) * 2
}
builder.result()
}
5
def times2(xs: List[Int]): List[Int] = {
val builder = List.newBuilder[Int]
for (x <- xs) {
builder += x * 2
}
builder.result()
}
6
def times2(xs: List[Int]): List[Int] = {
for (x <- xs)
yield x * 2
}
def times2(xs: List[Int]): List[Int] = {
xs.map(x => x * 2)
}
7
Sometimes,	builders	are	better
Japanese	line	1
Japanese	line	2
8
def fromPathClasspath(classpath: Seq[Path]): (Seq[IRContainer], Seq[Path]) = {
val containers = Seq.newBuilder[IRContainer]
val paths = Seq.newBuilder[Path]
for (entry <- classpath if Files.exists(entry)) {
val attrs = Files.readAttributes(entry, classOf[BasicFileAttributes])
if (attrs.isDirectory()) {
walkIR(entry) { (path, attrs) =>
containers += IRContainer.fromIRFile(...)
paths += path
}
} else if (entry.getFileName().toString().endsWith(".jar")) {
containers += new JarIRContainer(entry, attrs.lastModifiedTime())
paths += entry
} else {
throw new IllegalArgumentException("Illegal classpath entry " + entry)
}
}
(containers.result(), paths.result())
}
9
def fromPathClasspath(classpath: Seq[Path]): (Seq[IRContainer], Seq[Path]) = {
val containers = Seq.newBuilder[IRContainer]
val paths = Seq.newBuilder[Path]
for (entry <- classpath if Files.exists(entry)) {
val attrs = Files.readAttributes(entry, classOf[BasicFileAttributes])
if (attrs.isDirectory()) {
walkIR(entry) { (path, attrs) =>
containers += IRContainer.fromIRFile(...)
paths += path
}
} else if (entry.getFileName().toString().endsWith(".jar")) {
containers += new JarIRContainer(entry, attrs.lastModifiedTime())
paths += entry
} else {
throw new IllegalArgumentException("Illegal classpath entry " + entry)
}
}
(containers.result(), paths.result())
}
9
Sometimes,	 s	are	better
Japanese	line	1
Japanese	line	2
10
var test = {
genIsScalaJSObject(obj) &&
genIsClassNameInAncestors(...)
}
def typeOfTest(typeString: String): js.Tree = ...
if (isAncestorOfString)
test = test || typeOfTest("string")
if (isAncestorOfHijackedNumberClass) {
test = test || typeOfTest("number")
if (useBigIntForLongs)
test = test || genCallHelper("isLong", obj)
}
if (isAncestorOfBoxedBooleanClass)
test = test || typeOfTest("boolean")
if (isAncestorOfBoxedCharacterClass)
test = test || (obj instanceof envField("Char"))
test
11
var test = {
genIsScalaJSObject(obj) &&
genIsClassNameInAncestors(...)
}
def typeOfTest(typeString: String): js.Tree = ...
if (isAncestorOfString)
test = test || typeOfTest("string")
if (isAncestorOfHijackedNumberClass) {
test = test || typeOfTest("number")
if (useBigIntForLongs)
test = test || genCallHelper("isLong", obj)
}
if (isAncestorOfBoxedBooleanClass)
test = test || typeOfTest("boolean")
if (isAncestorOfBoxedCharacterClass)
test = test || (obj instanceof envField("Char"))
test
11
val test0 = {
genIsScalaJSObject(obj) &&
genIsClassNameInAncestors(...)
}
def typeOfTest(typeString: String): js.Tree = ...
val test1 =
if (isAncestorOfString) test0 || typeOfTest("string")
else test0
val test3 = if (isAncestorOfHijackedNumberClass) {
val test2 = test1 || typeOfTest("number")
if (useBigIntForLongs) test2 || genCallHelper("isLong", obj)
else test2
}
val test4 =
if (isAncestorOfBoxedBooleanClass) test3 || typeOfTest("boolean")
else test3
val test5 =
if (isAncestorOfBoxedCharacterClass) test4 || (obj instanceof envField("Char"))
else test4
test5
12
val test0 = {
genIsScalaJSObject(obj) &&
genIsClassNameInAncestors(...)
}
def typeOfTest(typeString: String): js.Tree = ...
val test1 =
if (isAncestorOfString) test0 || typeOfTest("string")
else test0
val test3 = if (isAncestorOfHijackedNumberClass) {
val test2 = test1 || typeOfTest("number")
if (useBigIntForLongs) test2 || genCallHelper("isLong", obj)
else test2
}
val test4 =
if (isAncestorOfBoxedBooleanClass) test3 || typeOfTest("boolean")
else test3
val test5 =
if (isAncestorOfBoxedCharacterClass) test4 || (obj instanceof envField("Char"))
else test4
test5
12
val test0 = {
genIsScalaJSObject(obj) &&
genIsClassNameInAncestors(...)
}
def typeOfTest(typeString: String): js.Tree = ...
val test1 =
if (isAncestorOfString) test0 || typeOfTest("string")
else test0
val test3 = if (isAncestorOfHijackedNumberClass) {
val test2 = test1 || typeOfTest("number")
if (useBigIntForLongs) test2 || genCallHelper("isLong", obj)
else test2
}
val test4 =
if (isAncestorOfBoxedBooleanClass) test3 || typeOfTest("boolean")
else test3
val test5 =
if (isAncestorOfBoxedCharacterClass) test4 || (obj instanceof envField("Char"))
else test4
test5
12
val test0 = {
genIsScalaJSObject(obj) &&
genIsClassNameInAncestors(...)
}
def typeOfTest(typeString: String): js.Tree = ...
val test1 =
if (isAncestorOfString) test0 || typeOfTest("string")
else test0
val test3 = if (isAncestorOfHijackedNumberClass) {
val test2 = test1 || typeOfTest("number")
if (useBigIntForLongs) test2 || genCallHelper("isLong", obj)
else test2
}
val test4 =
if (isAncestorOfBoxedBooleanClass) test3 || typeOfTest("boolean")
else test3
val test5 =
if (isAncestorOfBoxedCharacterClass) test4 || (obj instanceof envField("Char"))
else test4
test5
12
In	the	(super)	smallIn	the	(super)	small
Immutable/functional	API
Locally	imperative	implementation	(if	more	readable)
Japanese	line	1
Japanese	line	2
13
Algorithms	with	mutable	internal	dataAlgorithms	with	mutable	internal	data
structuresstructures
The	 	of	Scala.js
The	change	detection	algorithm	of	the	optimizer
Japanese	line	1
Japanese	line	2
14
At	the	instance	levelAt	the	instance	level
Japanese	line	1
Japanese	line	2
15
final class Emitter(config: CommonPhaseConfig) {
def emitAll(unit: LinkingUnit, builder: JSLineBuilder,
logger: Logger): Unit = {
...
}
}
16
final class Emitter(config: CommonPhaseConfig) {
private class State(val lastMentionedDangerousGlobalRefs: Set[String]) {
val jsGen: JSGen = new JSGen(..., lastMentionedDangerousGlobalRefs)
val classEmitter: ClassEmitter = new ClassEmitter(jsGen)
val coreJSLib: WithGlobals[js.Tree] = CoreJSLib.build(jsGen)
}
private var state: State = new State(Set.empty)
private def jsGen: JSGen = state.jsGen
private def classEmitter: ClassEmitter = state.classEmitter
private def coreJSLib: WithGlobals[js.Tree] = state.coreJSLib
private val classCaches = mutable.Map.empty[List[String], ClassCache]
def emitAll(unit: LinkingUnit, builder: JSLineBuilder,
logger: Logger): Unit = {
...
classCaches.getOrElseUpdate(..., ...)
...
val mentionedDangerousGlobalRefs = ...
state = new State(mentionedDangerousGlobalRefs)
...
}
}
17
final class Emitter(config: CommonPhaseConfig) {
private class State(val lastMentionedDangerousGlobalRefs: Set[String]) {
val jsGen: JSGen = new JSGen(..., lastMentionedDangerousGlobalRefs)
val classEmitter: ClassEmitter = new ClassEmitter(jsGen)
val coreJSLib: WithGlobals[js.Tree] = CoreJSLib.build(jsGen)
}
private var state: State = new State(Set.empty)
private def jsGen: JSGen = state.jsGen
private def classEmitter: ClassEmitter = state.classEmitter
private def coreJSLib: WithGlobals[js.Tree] = state.coreJSLib
private val classCaches = mutable.Map.empty[List[String], ClassCache]
def emitAll(unit: LinkingUnit, builder: JSLineBuilder,
logger: Logger): Unit = {
...
classCaches.getOrElseUpdate(..., ...)
...
val mentionedDangerousGlobalRefs = ...
state = new State(mentionedDangerousGlobalRefs)
...
}
}
17
final class Emitter(config: CommonPhaseConfig) {
private class State(val lastMentionedDangerousGlobalRefs: Set[String]) {
val jsGen: JSGen = new JSGen(..., lastMentionedDangerousGlobalRefs)
val classEmitter: ClassEmitter = new ClassEmitter(jsGen)
val coreJSLib: WithGlobals[js.Tree] = CoreJSLib.build(jsGen)
}
private var state: State = new State(Set.empty)
private def jsGen: JSGen = state.jsGen
private def classEmitter: ClassEmitter = state.classEmitter
private def coreJSLib: WithGlobals[js.Tree] = state.coreJSLib
private val classCaches = mutable.Map.empty[List[String], ClassCache]
def emitAll(unit: LinkingUnit, builder: JSLineBuilder,
logger: Logger): Unit = {
...
classCaches.getOrElseUpdate(..., ...)
...
val mentionedDangerousGlobalRefs = ...
state = new State(mentionedDangerousGlobalRefs)
...
}
}
17
final class Emitter(config: CommonPhaseConfig) {
private class State(val lastMentionedDangerousGlobalRefs: Set[String]) {
val jsGen: JSGen = new JSGen(..., lastMentionedDangerousGlobalRefs)
val classEmitter: ClassEmitter = new ClassEmitter(jsGen)
val coreJSLib: WithGlobals[js.Tree] = CoreJSLib.build(jsGen)
}
private var state: State = new State(Set.empty)
private def jsGen: JSGen = state.jsGen
private def classEmitter: ClassEmitter = state.classEmitter
private def coreJSLib: WithGlobals[js.Tree] = state.coreJSLib
private val classCaches = mutable.Map.empty[List[String], ClassCache]
def emitAll(unit: LinkingUnit, builder: JSLineBuilder,
logger: Logger): Unit = {
...
classCaches.getOrElseUpdate(..., ...)
...
val mentionedDangerousGlobalRefs = ...
state = new State(mentionedDangerousGlobalRefs)
...
}
}
17
At	the	instance	levelAt	the	instance	level
Immutable/functional	object	API
Mutable	state	carried	between	invocations
But	not	observable	from	the	outside
The	state	is	encapsulated	using	object-orientation
Japanese	line	1
Japanese	line	2
18
At	the	instance	levelAt	the	instance	level
Not	possible	using	pure	functional	programming
Difficult	to	reason	about	if	the	state	is	observable	(using
an	imperative	API)
Unique	power	of	combining	functional	programming,
object-orientation	and	imperative	features
Japanese	line	1
Japanese	line	2
19
Used	at	several	levels:
The	emitter
The	optimizer
The	caches	for	 	files
The	all-encompassing	 	method
etc.
Japanese	line	1
Japanese	line	2
20
Open	class	hierarchiesOpen	class	hierarchies
Japanese	line	1
Japanese	line	2
21
So	far:	 	traits	and	 	classes
Japanese	line	1
Japanese	line	2
22
/** A backend of a standard Scala.js linker. */
abstract class LinkerBackend {
/** Core specification that this linker backend implements. */
val coreSpec: CoreSpec
/** Symbols this backend needs to be present in the linking unit. */
val symbolRequirements: SymbolRequirement
/** Emit the given LinkingUnit to the target output. */
def emit(unit: LinkingUnit, output: LinkerOutput, logger: Logger)(
implicit ec: ExecutionContext): Future[Unit]
}
23
/** The basic backend for the Scala.js linker. */
final class BasicLinkerBackend(config: LinkerBackendImpl.Config)
extends LinkerBackend {
val coreSpec = config.commonConfig.coreSpec
private[this] val emitter = new Emitter(config.commonConfig)
val symbolRequirements: SymbolRequirement = emitter.symbolRequirements
def emit(unit: LinkingUnit, output: LinkerOutput, logger: Logger)(
implicit ec: ExecutionContext): Future[Unit] = {
...
val builder = new JSFileBuilder
emitter.emitAll(unit, builder, logger)
OutputFileImpl.fromOutputFile(output.jsFile)
.writeFull(builer.complete())
...
}
}
24
/** The Closure backend of the Scala.js linker. */
final class ClosureLinkerBackend(config: LinkerBackendImpl.Config)
extends LinkerBackend {
val coreSpec = config.commonConfig.coreSpec
private[this] val emitter = new Emitter(config.commonConfig)
val symbolRequirements: SymbolRequirement = emitter.symbolRequirements
def emit(unit: LinkingUnit, output: LinkerOutput, logger: Logger)(
implicit ec: ExecutionContext): Future[Unit] = {
...
val builer = new ClosureModuleBuilder
emitter.emitAll(unit, builer, logger)
val closureModules = makeClosureModules(builder.result())
val result = closureCompiler.compileModules(..., closureModules, ...)
writeResult(result, ...)
...
}
}
25
Possible	to	write	your	own	Scala.js	backend	in	user-space
	actually	does	that,
to	collect	imported	modules	for	Webpack
Japanese	line	1
Japanese	line	2
26
/** A JavaScript execution environment.
*
* This can run and interact with JavaScript code.
*
* Any implementation is expected to be fully thread-safe.
*/
trait JSEnv {
/** Human-readable name for this [[JSEnv]] */
val name: String
/** Starts a new (asynchronous) JS run. */
def start(input: Input, config: RunConfig): JSRun
/** Like [[start]], but initializes a communication channel. */
def startWithCom(input: Input, config: RunConfig,
onMessage: String => Unit): JSComRun
}
27
In	the	main	repo,	one	implementation:	
Completely	unrelated	but	compatible	implementations
are	in	other	repos:
Custom	environments	in	users'	builds
Japanese	line	1
Japanese	line	2
28
Custom	for	comprehensionsCustom	for	comprehensions
the	M	word
Japanese	line	1
Japanese	line	2
29
def genMethod(className: String, method: MethodDef)(
implicit globalKnowledge: GlobalKnowledge): WithGlobals[js.Tree] = {
val methodBody = method.body.getOrElse(
throw new AssertionError("Cannot generate an abstract method"))
implicit val pos = method.pos
val namespace = method.flags.namespace
val methodFunWithGlobals: WithGlobals[js.Function] =
desugarToFunction(className, method.args, methodBody, method.resultType)
methodFunWithGlobals.flatMap { methodFun =>
if (namespace != MemberNamespace.Public) {
...
} else {
if (useClasses) {
for (propName <- genPropertyName(method.name)) yield {
js.MethodDef(static = false, propName, methodFun.args,
methodFun.body)
}
} else {
genAddToPrototype(className, method.name, methodFun)
}
}
}
}
30
def genMethod(className: String, method: MethodDef)(
implicit globalKnowledge: GlobalKnowledge): WithGlobals[js.Tree] = {
val methodBody = method.body.getOrElse(
throw new AssertionError("Cannot generate an abstract method"))
implicit val pos = method.pos
val namespace = method.flags.namespace
val methodFunWithGlobals: WithGlobals[js.Function] =
desugarToFunction(className, method.args, methodBody, method.resultType)
methodFunWithGlobals.flatMap { methodFun =>
if (namespace != MemberNamespace.Public) {
...
} else {
if (useClasses) {
for (propName <- genPropertyName(method.name)) yield {
js.MethodDef(static = false, propName, methodFun.args,
methodFun.body)
}
} else {
genAddToPrototype(className, method.name, methodFun)
}
}
}
}
30
def genMethod(className: String, method: MethodDef)(
implicit globalKnowledge: GlobalKnowledge): WithGlobals[js.Tree] = {
val methodBody = method.body.getOrElse(
throw new AssertionError("Cannot generate an abstract method"))
implicit val pos = method.pos
val namespace = method.flags.namespace
val methodFunWithGlobals: WithGlobals[js.Function] =
desugarToFunction(className, method.args, methodBody, method.resultType)
methodFunWithGlobals.flatMap { methodFun =>
if (namespace != MemberNamespace.Public) {
...
} else {
if (useClasses) {
for (propName <- genPropertyName(method.name)) yield {
js.MethodDef(static = false, propName, methodFun.args,
methodFun.body)
}
} else {
genAddToPrototype(className, method.name, methodFun)
}
}
}
}
30
def genMethod(className: String, method: MethodDef)(
implicit globalKnowledge: GlobalKnowledge): WithGlobals[js.Tree] = {
val methodBody = method.body.getOrElse(
throw new AssertionError("Cannot generate an abstract method"))
implicit val pos = method.pos
val namespace = method.flags.namespace
val methodFunWithGlobals: WithGlobals[js.Function] =
desugarToFunction(className, method.args, methodBody, method.resultType)
methodFunWithGlobals.flatMap { methodFun =>
if (namespace != MemberNamespace.Public) {
...
} else {
if (useClasses) {
for (propName <- genPropertyName(method.name)) yield {
js.MethodDef(static = false, propName, methodFun.args,
methodFun.body)
}
} else {
genAddToPrototype(className, method.name, methodFun)
}
}
}
}
30
/** A monad that associates a set of global variable names to a value. */
private[emitter] final case class WithGlobals[+A](
value: A, globalVarNames: Set[String]) {
def map[B](f: A => B): WithGlobals[B] =
WithGlobals(f(value), globalVarNames)
def flatMap[B](f: A => WithGlobals[B]): WithGlobals[B] = {
val t = f(value)
WithGlobals(t.value, globalVarNames ++ t.globalVarNames)
}
}
private[emitter] object WithGlobals {
/** Constructs a `WithGlobals` with an empty set `globalVarNames`. */
def apply[A](value: A): WithGlobals[A] =
new WithGlobals(value, Set.empty)
def list[A](xs: List[WithGlobals[A]]): WithGlobals[List[A]] =
...
def option[A](xs: Option[WithGlobals[A]]): WithGlobals[Option[A]] =
...
} 31
Further	exploration	of	the	codeFurther	exploration	of	the	code
Time	permitting
Japanese	line	1
Japanese	line	2
32
         	
         scala-js.org scala.epfl.ch
33

Weitere ähnliche Inhalte

Was ist angesagt?

11. session 11 functions and objects
11. session 11   functions and objects11. session 11   functions and objects
11. session 11 functions and objects
Phúc Đỗ
 
Scala-对Java的修正和超越
Scala-对Java的修正和超越Scala-对Java的修正和超越
Scala-对Java的修正和超越
Caoyuan Deng
 
Functional Objects & Function and Closures
Functional Objects  & Function and ClosuresFunctional Objects  & Function and Closures
Functional Objects & Function and Closures
Sandip Kumar
 
Model-Driven Software Development - Static Analysis & Error Checking
Model-Driven Software Development - Static Analysis & Error CheckingModel-Driven Software Development - Static Analysis & Error Checking
Model-Driven Software Development - Static Analysis & Error Checking
Eelco Visser
 

Was ist angesagt? (20)

Scala cheatsheet
Scala cheatsheetScala cheatsheet
Scala cheatsheet
 
Workshop Scala
Workshop ScalaWorkshop Scala
Workshop Scala
 
Scala
ScalaScala
Scala
 
Scala taxonomy
Scala taxonomyScala taxonomy
Scala taxonomy
 
11. session 11 functions and objects
11. session 11   functions and objects11. session 11   functions and objects
11. session 11 functions and objects
 
The Ring programming language version 1.9 book - Part 41 of 210
The Ring programming language version 1.9 book - Part 41 of 210The Ring programming language version 1.9 book - Part 41 of 210
The Ring programming language version 1.9 book - Part 41 of 210
 
Scala-对Java的修正和超越
Scala-对Java的修正和超越Scala-对Java的修正和超越
Scala-对Java的修正和超越
 
All about scala
All about scalaAll about scala
All about scala
 
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
JDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation streamJDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation stream
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
 
Starting with Scala : Frontier Developer's Meetup December 2010
Starting with Scala : Frontier Developer's Meetup December 2010Starting with Scala : Frontier Developer's Meetup December 2010
Starting with Scala : Frontier Developer's Meetup December 2010
 
Scala jargon cheatsheet
Scala jargon cheatsheetScala jargon cheatsheet
Scala jargon cheatsheet
 
The Ring programming language version 1.2 book - Part 22 of 84
The Ring programming language version 1.2 book - Part 22 of 84The Ring programming language version 1.2 book - Part 22 of 84
The Ring programming language version 1.2 book - Part 22 of 84
 
Scala for Java Developers (Silicon Valley Code Camp 13)
Scala for Java Developers (Silicon Valley Code Camp 13)Scala for Java Developers (Silicon Valley Code Camp 13)
Scala for Java Developers (Silicon Valley Code Camp 13)
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 World
 
Functional Objects & Function and Closures
Functional Objects  & Function and ClosuresFunctional Objects  & Function and Closures
Functional Objects & Function and Closures
 
Model-Driven Software Development - Static Analysis & Error Checking
Model-Driven Software Development - Static Analysis & Error CheckingModel-Driven Software Development - Static Analysis & Error Checking
Model-Driven Software Development - Static Analysis & Error Checking
 
JavaScript objects and functions
JavaScript objects and functionsJavaScript objects and functions
JavaScript objects and functions
 
Scala for curious
Scala for curiousScala for curious
Scala for curious
 
Scala vs java 8
Scala vs java 8Scala vs java 8
Scala vs java 8
 
Scala: Object-Oriented Meets Functional, by Iulian Dragos
Scala: Object-Oriented Meets Functional, by Iulian DragosScala: Object-Oriented Meets Functional, by Iulian Dragos
Scala: Object-Oriented Meets Functional, by Iulian Dragos
 

Ähnlich wie Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébastien Doeraene

(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?
Tomasz Wrobel
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 

Ähnlich wie Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébastien Doeraene (20)

(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?
 
Scala coated JVM
Scala coated JVMScala coated JVM
Scala coated JVM
 
Meet scala
Meet scalaMeet scala
Meet scala
 
An introduction to scala
An introduction to scalaAn introduction to scala
An introduction to scala
 
Introduction to scala
Introduction to scalaIntroduction to scala
Introduction to scala
 
Introducing scala
Introducing scalaIntroducing scala
Introducing scala
 
Scala Bootcamp 1
Scala Bootcamp 1Scala Bootcamp 1
Scala Bootcamp 1
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
Scala ntnu
Scala ntnuScala ntnu
Scala ntnu
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
A Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIOA Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIO
 
Coding in Style
Coding in StyleCoding in Style
Coding in Style
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
ハイブリッド言語Scalaを使う
ハイブリッド言語Scalaを使うハイブリッド言語Scalaを使う
ハイブリッド言語Scalaを使う
 
Beyond xUnit example-based testing: property-based testing with ScalaCheck
Beyond xUnit example-based testing: property-based testing with ScalaCheckBeyond xUnit example-based testing: property-based testing with ScalaCheck
Beyond xUnit example-based testing: property-based testing with ScalaCheck
 
Scala
ScalaScala
Scala
 

Mehr von scalaconfjp

Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメント
Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメントScalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメント
Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメント
scalaconfjp
 

Mehr von scalaconfjp (20)

脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~
脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~
脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~
 
Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会
Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会
Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会
 
GraalVM Overview Compact version
GraalVM Overview Compact versionGraalVM Overview Compact version
GraalVM Overview Compact version
 
Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...
Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...
Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...
 
Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...
Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...
Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...
 
Scala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan Goyeau
Scala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan GoyeauScala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan Goyeau
Scala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan Goyeau
 
Scala ♥ Graal by Flavio Brasil
Scala ♥ Graal by Flavio BrasilScala ♥ Graal by Flavio Brasil
Scala ♥ Graal by Flavio Brasil
 
Introduction to GraphQL in Scala
Introduction to GraphQL in ScalaIntroduction to GraphQL in Scala
Introduction to GraphQL in Scala
 
Safety Beyond Types
Safety Beyond TypesSafety Beyond Types
Safety Beyond Types
 
Reactive Kafka with Akka Streams
Reactive Kafka with Akka StreamsReactive Kafka with Akka Streams
Reactive Kafka with Akka Streams
 
Reactive microservices with play and akka
Reactive microservices with play and akkaReactive microservices with play and akka
Reactive microservices with play and akka
 
Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメント
Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメントScalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメント
Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメント
 
DWANGO by ドワンゴ
DWANGO by ドワンゴDWANGO by ドワンゴ
DWANGO by ドワンゴ
 
OCTOPARTS by M3, Inc.
OCTOPARTS by M3, Inc.OCTOPARTS by M3, Inc.
OCTOPARTS by M3, Inc.
 
Try using Aeromock by Marverick, Inc.
Try using Aeromock by Marverick, Inc.Try using Aeromock by Marverick, Inc.
Try using Aeromock by Marverick, Inc.
 
統計をとって高速化する
Scala開発 by CyberZ,Inc.
統計をとって高速化する
Scala開発 by CyberZ,Inc.統計をとって高速化する
Scala開発 by CyberZ,Inc.
統計をとって高速化する
Scala開発 by CyberZ,Inc.
 
Short Introduction of Implicit Conversion by TIS, Inc.
Short Introduction of Implicit Conversion by TIS, Inc.Short Introduction of Implicit Conversion by TIS, Inc.
Short Introduction of Implicit Conversion by TIS, Inc.
 
ビズリーチ x ScalaMatsuri by BIZREACH, Inc.
ビズリーチ x ScalaMatsuri  by BIZREACH, Inc.ビズリーチ x ScalaMatsuri  by BIZREACH, Inc.
ビズリーチ x ScalaMatsuri by BIZREACH, Inc.
 
sbt, past and future / sbt, 傾向と対策
sbt, past and future / sbt, 傾向と対策sbt, past and future / sbt, 傾向と対策
sbt, past and future / sbt, 傾向と対策
 
The Evolution of Scala / Scala進化論
The Evolution of Scala / Scala進化論The Evolution of Scala / Scala進化論
The Evolution of Scala / Scala進化論
 

Kürzlich hochgeladen

AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 

Kürzlich hochgeladen (20)

Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 

Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébastien Doeraene

  • 4. def times2(xs: List[Int]): List[Int] = { var result: List[Int] = Nil var i = 0 while (i < xs.length) { result = result :+ (xs(i) * 2) i += 1 } result } 3
  • 5. def times2(xs: List[Int]): List[Int] = { var result: List[Int] = Nil for (i <- 0 until xs.length) { result = result :+ (xs(i) * 2) } result } 4
  • 6. def times2(xs: List[Int]): List[Int] = { val builder = List.newBuilder[Int] for (i <- 0 until xs.length) { builder += xs(i) * 2 } builder.result() } 5
  • 7. def times2(xs: List[Int]): List[Int] = { val builder = List.newBuilder[Int] for (x <- xs) { builder += x * 2 } builder.result() } 6
  • 8. def times2(xs: List[Int]): List[Int] = { for (x <- xs) yield x * 2 } def times2(xs: List[Int]): List[Int] = { xs.map(x => x * 2) } 7
  • 10. def fromPathClasspath(classpath: Seq[Path]): (Seq[IRContainer], Seq[Path]) = { val containers = Seq.newBuilder[IRContainer] val paths = Seq.newBuilder[Path] for (entry <- classpath if Files.exists(entry)) { val attrs = Files.readAttributes(entry, classOf[BasicFileAttributes]) if (attrs.isDirectory()) { walkIR(entry) { (path, attrs) => containers += IRContainer.fromIRFile(...) paths += path } } else if (entry.getFileName().toString().endsWith(".jar")) { containers += new JarIRContainer(entry, attrs.lastModifiedTime()) paths += entry } else { throw new IllegalArgumentException("Illegal classpath entry " + entry) } } (containers.result(), paths.result()) } 9
  • 11. def fromPathClasspath(classpath: Seq[Path]): (Seq[IRContainer], Seq[Path]) = { val containers = Seq.newBuilder[IRContainer] val paths = Seq.newBuilder[Path] for (entry <- classpath if Files.exists(entry)) { val attrs = Files.readAttributes(entry, classOf[BasicFileAttributes]) if (attrs.isDirectory()) { walkIR(entry) { (path, attrs) => containers += IRContainer.fromIRFile(...) paths += path } } else if (entry.getFileName().toString().endsWith(".jar")) { containers += new JarIRContainer(entry, attrs.lastModifiedTime()) paths += entry } else { throw new IllegalArgumentException("Illegal classpath entry " + entry) } } (containers.result(), paths.result()) } 9
  • 13. var test = { genIsScalaJSObject(obj) && genIsClassNameInAncestors(...) } def typeOfTest(typeString: String): js.Tree = ... if (isAncestorOfString) test = test || typeOfTest("string") if (isAncestorOfHijackedNumberClass) { test = test || typeOfTest("number") if (useBigIntForLongs) test = test || genCallHelper("isLong", obj) } if (isAncestorOfBoxedBooleanClass) test = test || typeOfTest("boolean") if (isAncestorOfBoxedCharacterClass) test = test || (obj instanceof envField("Char")) test 11
  • 14. var test = { genIsScalaJSObject(obj) && genIsClassNameInAncestors(...) } def typeOfTest(typeString: String): js.Tree = ... if (isAncestorOfString) test = test || typeOfTest("string") if (isAncestorOfHijackedNumberClass) { test = test || typeOfTest("number") if (useBigIntForLongs) test = test || genCallHelper("isLong", obj) } if (isAncestorOfBoxedBooleanClass) test = test || typeOfTest("boolean") if (isAncestorOfBoxedCharacterClass) test = test || (obj instanceof envField("Char")) test 11
  • 15. val test0 = { genIsScalaJSObject(obj) && genIsClassNameInAncestors(...) } def typeOfTest(typeString: String): js.Tree = ... val test1 = if (isAncestorOfString) test0 || typeOfTest("string") else test0 val test3 = if (isAncestorOfHijackedNumberClass) { val test2 = test1 || typeOfTest("number") if (useBigIntForLongs) test2 || genCallHelper("isLong", obj) else test2 } val test4 = if (isAncestorOfBoxedBooleanClass) test3 || typeOfTest("boolean") else test3 val test5 = if (isAncestorOfBoxedCharacterClass) test4 || (obj instanceof envField("Char")) else test4 test5 12
  • 16. val test0 = { genIsScalaJSObject(obj) && genIsClassNameInAncestors(...) } def typeOfTest(typeString: String): js.Tree = ... val test1 = if (isAncestorOfString) test0 || typeOfTest("string") else test0 val test3 = if (isAncestorOfHijackedNumberClass) { val test2 = test1 || typeOfTest("number") if (useBigIntForLongs) test2 || genCallHelper("isLong", obj) else test2 } val test4 = if (isAncestorOfBoxedBooleanClass) test3 || typeOfTest("boolean") else test3 val test5 = if (isAncestorOfBoxedCharacterClass) test4 || (obj instanceof envField("Char")) else test4 test5 12
  • 17. val test0 = { genIsScalaJSObject(obj) && genIsClassNameInAncestors(...) } def typeOfTest(typeString: String): js.Tree = ... val test1 = if (isAncestorOfString) test0 || typeOfTest("string") else test0 val test3 = if (isAncestorOfHijackedNumberClass) { val test2 = test1 || typeOfTest("number") if (useBigIntForLongs) test2 || genCallHelper("isLong", obj) else test2 } val test4 = if (isAncestorOfBoxedBooleanClass) test3 || typeOfTest("boolean") else test3 val test5 = if (isAncestorOfBoxedCharacterClass) test4 || (obj instanceof envField("Char")) else test4 test5 12
  • 18. val test0 = { genIsScalaJSObject(obj) && genIsClassNameInAncestors(...) } def typeOfTest(typeString: String): js.Tree = ... val test1 = if (isAncestorOfString) test0 || typeOfTest("string") else test0 val test3 = if (isAncestorOfHijackedNumberClass) { val test2 = test1 || typeOfTest("number") if (useBigIntForLongs) test2 || genCallHelper("isLong", obj) else test2 } val test4 = if (isAncestorOfBoxedBooleanClass) test3 || typeOfTest("boolean") else test3 val test5 = if (isAncestorOfBoxedCharacterClass) test4 || (obj instanceof envField("Char")) else test4 test5 12
  • 22. final class Emitter(config: CommonPhaseConfig) { def emitAll(unit: LinkingUnit, builder: JSLineBuilder, logger: Logger): Unit = { ... } } 16
  • 23. final class Emitter(config: CommonPhaseConfig) { private class State(val lastMentionedDangerousGlobalRefs: Set[String]) { val jsGen: JSGen = new JSGen(..., lastMentionedDangerousGlobalRefs) val classEmitter: ClassEmitter = new ClassEmitter(jsGen) val coreJSLib: WithGlobals[js.Tree] = CoreJSLib.build(jsGen) } private var state: State = new State(Set.empty) private def jsGen: JSGen = state.jsGen private def classEmitter: ClassEmitter = state.classEmitter private def coreJSLib: WithGlobals[js.Tree] = state.coreJSLib private val classCaches = mutable.Map.empty[List[String], ClassCache] def emitAll(unit: LinkingUnit, builder: JSLineBuilder, logger: Logger): Unit = { ... classCaches.getOrElseUpdate(..., ...) ... val mentionedDangerousGlobalRefs = ... state = new State(mentionedDangerousGlobalRefs) ... } } 17
  • 24. final class Emitter(config: CommonPhaseConfig) { private class State(val lastMentionedDangerousGlobalRefs: Set[String]) { val jsGen: JSGen = new JSGen(..., lastMentionedDangerousGlobalRefs) val classEmitter: ClassEmitter = new ClassEmitter(jsGen) val coreJSLib: WithGlobals[js.Tree] = CoreJSLib.build(jsGen) } private var state: State = new State(Set.empty) private def jsGen: JSGen = state.jsGen private def classEmitter: ClassEmitter = state.classEmitter private def coreJSLib: WithGlobals[js.Tree] = state.coreJSLib private val classCaches = mutable.Map.empty[List[String], ClassCache] def emitAll(unit: LinkingUnit, builder: JSLineBuilder, logger: Logger): Unit = { ... classCaches.getOrElseUpdate(..., ...) ... val mentionedDangerousGlobalRefs = ... state = new State(mentionedDangerousGlobalRefs) ... } } 17
  • 25. final class Emitter(config: CommonPhaseConfig) { private class State(val lastMentionedDangerousGlobalRefs: Set[String]) { val jsGen: JSGen = new JSGen(..., lastMentionedDangerousGlobalRefs) val classEmitter: ClassEmitter = new ClassEmitter(jsGen) val coreJSLib: WithGlobals[js.Tree] = CoreJSLib.build(jsGen) } private var state: State = new State(Set.empty) private def jsGen: JSGen = state.jsGen private def classEmitter: ClassEmitter = state.classEmitter private def coreJSLib: WithGlobals[js.Tree] = state.coreJSLib private val classCaches = mutable.Map.empty[List[String], ClassCache] def emitAll(unit: LinkingUnit, builder: JSLineBuilder, logger: Logger): Unit = { ... classCaches.getOrElseUpdate(..., ...) ... val mentionedDangerousGlobalRefs = ... state = new State(mentionedDangerousGlobalRefs) ... } } 17
  • 26. final class Emitter(config: CommonPhaseConfig) { private class State(val lastMentionedDangerousGlobalRefs: Set[String]) { val jsGen: JSGen = new JSGen(..., lastMentionedDangerousGlobalRefs) val classEmitter: ClassEmitter = new ClassEmitter(jsGen) val coreJSLib: WithGlobals[js.Tree] = CoreJSLib.build(jsGen) } private var state: State = new State(Set.empty) private def jsGen: JSGen = state.jsGen private def classEmitter: ClassEmitter = state.classEmitter private def coreJSLib: WithGlobals[js.Tree] = state.coreJSLib private val classCaches = mutable.Map.empty[List[String], ClassCache] def emitAll(unit: LinkingUnit, builder: JSLineBuilder, logger: Logger): Unit = { ... classCaches.getOrElseUpdate(..., ...) ... val mentionedDangerousGlobalRefs = ... state = new State(mentionedDangerousGlobalRefs) ... } } 17
  • 32. /** A backend of a standard Scala.js linker. */ abstract class LinkerBackend { /** Core specification that this linker backend implements. */ val coreSpec: CoreSpec /** Symbols this backend needs to be present in the linking unit. */ val symbolRequirements: SymbolRequirement /** Emit the given LinkingUnit to the target output. */ def emit(unit: LinkingUnit, output: LinkerOutput, logger: Logger)( implicit ec: ExecutionContext): Future[Unit] } 23
  • 33. /** The basic backend for the Scala.js linker. */ final class BasicLinkerBackend(config: LinkerBackendImpl.Config) extends LinkerBackend { val coreSpec = config.commonConfig.coreSpec private[this] val emitter = new Emitter(config.commonConfig) val symbolRequirements: SymbolRequirement = emitter.symbolRequirements def emit(unit: LinkingUnit, output: LinkerOutput, logger: Logger)( implicit ec: ExecutionContext): Future[Unit] = { ... val builder = new JSFileBuilder emitter.emitAll(unit, builder, logger) OutputFileImpl.fromOutputFile(output.jsFile) .writeFull(builer.complete()) ... } } 24
  • 34. /** The Closure backend of the Scala.js linker. */ final class ClosureLinkerBackend(config: LinkerBackendImpl.Config) extends LinkerBackend { val coreSpec = config.commonConfig.coreSpec private[this] val emitter = new Emitter(config.commonConfig) val symbolRequirements: SymbolRequirement = emitter.symbolRequirements def emit(unit: LinkingUnit, output: LinkerOutput, logger: Logger)( implicit ec: ExecutionContext): Future[Unit] = { ... val builer = new ClosureModuleBuilder emitter.emitAll(unit, builer, logger) val closureModules = makeClosureModules(builder.result()) val result = closureCompiler.compileModules(..., closureModules, ...) writeResult(result, ...) ... } } 25
  • 36. /** A JavaScript execution environment. * * This can run and interact with JavaScript code. * * Any implementation is expected to be fully thread-safe. */ trait JSEnv { /** Human-readable name for this [[JSEnv]] */ val name: String /** Starts a new (asynchronous) JS run. */ def start(input: Input, config: RunConfig): JSRun /** Like [[start]], but initializes a communication channel. */ def startWithCom(input: Input, config: RunConfig, onMessage: String => Unit): JSComRun } 27
  • 39. def genMethod(className: String, method: MethodDef)( implicit globalKnowledge: GlobalKnowledge): WithGlobals[js.Tree] = { val methodBody = method.body.getOrElse( throw new AssertionError("Cannot generate an abstract method")) implicit val pos = method.pos val namespace = method.flags.namespace val methodFunWithGlobals: WithGlobals[js.Function] = desugarToFunction(className, method.args, methodBody, method.resultType) methodFunWithGlobals.flatMap { methodFun => if (namespace != MemberNamespace.Public) { ... } else { if (useClasses) { for (propName <- genPropertyName(method.name)) yield { js.MethodDef(static = false, propName, methodFun.args, methodFun.body) } } else { genAddToPrototype(className, method.name, methodFun) } } } } 30
  • 40. def genMethod(className: String, method: MethodDef)( implicit globalKnowledge: GlobalKnowledge): WithGlobals[js.Tree] = { val methodBody = method.body.getOrElse( throw new AssertionError("Cannot generate an abstract method")) implicit val pos = method.pos val namespace = method.flags.namespace val methodFunWithGlobals: WithGlobals[js.Function] = desugarToFunction(className, method.args, methodBody, method.resultType) methodFunWithGlobals.flatMap { methodFun => if (namespace != MemberNamespace.Public) { ... } else { if (useClasses) { for (propName <- genPropertyName(method.name)) yield { js.MethodDef(static = false, propName, methodFun.args, methodFun.body) } } else { genAddToPrototype(className, method.name, methodFun) } } } } 30
  • 41. def genMethod(className: String, method: MethodDef)( implicit globalKnowledge: GlobalKnowledge): WithGlobals[js.Tree] = { val methodBody = method.body.getOrElse( throw new AssertionError("Cannot generate an abstract method")) implicit val pos = method.pos val namespace = method.flags.namespace val methodFunWithGlobals: WithGlobals[js.Function] = desugarToFunction(className, method.args, methodBody, method.resultType) methodFunWithGlobals.flatMap { methodFun => if (namespace != MemberNamespace.Public) { ... } else { if (useClasses) { for (propName <- genPropertyName(method.name)) yield { js.MethodDef(static = false, propName, methodFun.args, methodFun.body) } } else { genAddToPrototype(className, method.name, methodFun) } } } } 30
  • 42. def genMethod(className: String, method: MethodDef)( implicit globalKnowledge: GlobalKnowledge): WithGlobals[js.Tree] = { val methodBody = method.body.getOrElse( throw new AssertionError("Cannot generate an abstract method")) implicit val pos = method.pos val namespace = method.flags.namespace val methodFunWithGlobals: WithGlobals[js.Function] = desugarToFunction(className, method.args, methodBody, method.resultType) methodFunWithGlobals.flatMap { methodFun => if (namespace != MemberNamespace.Public) { ... } else { if (useClasses) { for (propName <- genPropertyName(method.name)) yield { js.MethodDef(static = false, propName, methodFun.args, methodFun.body) } } else { genAddToPrototype(className, method.name, methodFun) } } } } 30
  • 43. /** A monad that associates a set of global variable names to a value. */ private[emitter] final case class WithGlobals[+A]( value: A, globalVarNames: Set[String]) { def map[B](f: A => B): WithGlobals[B] = WithGlobals(f(value), globalVarNames) def flatMap[B](f: A => WithGlobals[B]): WithGlobals[B] = { val t = f(value) WithGlobals(t.value, globalVarNames ++ t.globalVarNames) } } private[emitter] object WithGlobals { /** Constructs a `WithGlobals` with an empty set `globalVarNames`. */ def apply[A](value: A): WithGlobals[A] = new WithGlobals(value, Set.empty) def list[A](xs: List[WithGlobals[A]]): WithGlobals[List[A]] = ... def option[A](xs: Option[WithGlobals[A]]): WithGlobals[Option[A]] = ... } 31