1. SCALA:
— GROW OR SHRINK ?
FACTORS OF HATE/LOVE RELATIONSHIPS
SCALA WAY VS WAYS OF TECHNICAL EVOLUTION
// Ruslan Shevchenko
<ruslan@shevchenko.kiev.ua>
@rssh1
2. Disclaimer: %noassoc
I’m not associated with any organization, which have
influence on the language design.
Try to avoid:
complain on things, which you can’t change
speaking about decisions of others.
Instead:
Analyze technical/social/economics phenomenas
3. 80 vs Now =>
C / Objective-C / C++ / Objective - C++
Pascal / Modula 2
Algol 60 / Algol 68 / …
Java {1, 1.1, 1.2 … 1.5, 6, 7, 8, 9 ….. }
Scala { 2.7, .. 2.13 -> 3, … }
Smalltalk 80
C++ { __, 0x, 17, 19, 21 … }
4. Evolution (where is beast ?)
language usage ~ type of bacteria
software project ~ organism
people, money ~ resources
horizontal gene transfer.
gene: feature/idiom/(incapsulated into libraries …)
//biology evolution— decisions are accident
//technical evolution— decisions generated by committee
this difference is not very big.
5. What needed to be evolutionary stable ?
Survie
Adopt
Be attractive
6. What needed to be evolutionary stable ?
Survie
Adopt
Be attractive
Population > 1 %
∃ • EPFL Labs (Gov. financing)
• Lightbend ( Commercial financing)
• Community Center (Org ?)
• Support industry: Hydra, SoftwareMill,
etc..
• Monetization of PL ? (common problem)
• Oracle try to monetize JVM
7. What needed to be evolutionary stable ?
Survie
Adopt
Be attractive
Static metaprogrammig.
• Unique, popular in PL academia world.
• Will be better in Dotty: Staging/Partial
Evaluation
• Can emulate most of the other language
features without (with little) compiler
change:
• RUST Derive: Scalaz-deriving
• coroutines - storm-enrote
• go : scala-gopher, etc.
// technical part will follow
8. What needed to be evolutionary stable ?
Survie
Adopt
Be attractive
Static metaprogrammig.
• Unique, popular in PL academia world.
• Will be better in Dotty: Staging/Partial
Evaluation
• Can emulate most of the other language
features without (with little) compiler
change:
• RUST Derive: Scalaz-deriving
• coroutines - storm-enrote
• go : scala-gopher, etc.
// technical part will follow
• Metaprogramming still hard and incomplete.
• Distance between academic concept/real industrial API
• async/await
• storm/enroute
• monadless …..
• Now all stalled: wait new API in dotty/(squid in scala2)
• JVM (but exists scala-native & scala-js).
9. What needed to be evolutionary stable ?
Survie
Adopt
Be attractive
Hello! I'm A .signature Virus.
Join In The Fun And Copy Me Into Yours!
//memes
Learning curve
10. What needed to be evolutionary stable ?
Survie
Adopt
Be attractive
//memes
Learning curve
({ type EF[X]=Either[S,X] })#EF
val x = 1
culture
Isolate subsets
Software development
is not scalable !
Education too……..
Kaa’s law ….
11. Non-Issues:
- FP/OOP (this is solved problem)
Unsolved problems:
- Distributed computing.
- Mass-parallelism (GPU, TPU)
Issues:
- concurrency support
- small boilerplate instead no-boilerplate
- big core //gene rubbish
12. Concurrency support.
Monad [Future, Task] (extra wrap)
Streams [Akka-Streams, Monix, fs2] (extra wrap)
2009. CPS [shift/reset]. Tiark Rompf, Ingo Maier Martin Odersky. Implementing First-Class Polymorphic Delimited
Continuations by a Type-Directed Selective CPS-Transform.: https://infoscience.epfl.ch/record/149136/files/icfp113-rompf.pdf
— deprecated, not prod. quality
2013. Async/Await. Philipp Haller and Jason Zaugg. SIP22-Async. https://docs.scala-lang.org/sips/async.html.
— dormant, not prod. quality (try/catch support is missing)
2017. Coroutines. Aleksandar Prokopec, Fengyun Liu. Theory and Practice of Coroutines with Snapshots. http://
aleksandar-prokopec.com/publications/theory-and-practice-of-coroutines-with-snapshots/
—- Yet not ready, not prod. quality.
using inside hight-order functions…. - theoretically possible (implemented in gopher)
13. Concurrency/Learning Curve
for{ x <- retrieveA()
y <- retrieveB() }
yield x+y
async{ retrieveA()! + retrieveB()! }
vs
• Monads
• Combinators
• Nesting
// in Go, C#, Kotlin, C++ (Karl!), Python, JavaScript
something is implemented.
14. small boilerplate instead no-boilerplate
pathEndOrSingleSlash {
getAll
} ~ pathPrefix(Segment) { name =>
pathEndOrSingleSlash {
put {
saveValue(name)
} ~ get {
findValue(name)
} ~ delete {
deleteValue(name)
}
}
}
def getAll():List[String] = ..
@JsonBin
@Path(“entities”)
class Service
{
List<String> getAll()
@Post
void saveValue(@Path name)
String findValue(@Path name)
@Delete
// Java version is cleaner
//too easy implement all directly
15. big core
any AST transformation => check all possible
variants.
Unroll syntax sugar themselves
Possible solutions:
IR layer, which will keep simplifier code (like in
Scala.JS)
Standard transform library.
// will be better in dotty
16. Conclusion
FP/OOP - non issue.
The unique value - static metaprogramming.
Will allow lower barrier to language extending, but need to
be done at first.
Where other mainstream languages outperform Scala:
Concurrency support
Tooling (smaller core)
17. Technical part: squid
next generation of macro
http://epfldata.github.io/squid/home.htm
Lionel Parreaux, Amir Shaikhha, and Christoph E. Koch. 2017. Squid: Type-Safe,
Hygienic, and Reusable Quasiquotes. In Proceedings of the 2017 8th ACM
SIGPLAN Symposium on Scala (SCALA 2017).
scala> def power(n: Int, x: ClosedCode[Double]):
ClosedCode[Double] = {
| if (n > 0) code"${power(n-1, x)} * $x"
| else code"1.0"
| }
scala> val pgrm = power(3, code”0.5")
scala> pgrm.compile
18. Technical part: dotty metaprogramming
https://dotty.epfl.ch/docs/reference/principled-meta-
programming.html
probably, next direction for squid
inline def power(inline n: Int, x: Double) =
~powerCode(n, '(x))
private def powerCode(n: Int, x: Expr[Double]): Expr[Double] =
if (n == 0) '(1.0)
else if (n == 1) x
else if (n % 2 == 0)
'{ { val y = ~x * ~x; ~powerCode(n / 2, '(y)) } }
else
‘{ ~x * ~powerCode(n - 1, x) }
19. Technical part: scalar-deriving
https://gitlab.com/fommil/scalaz-deriving
no dependency from scalar ;)
scalac plugin, to expand annotation into boilerplate
@deriving(Encoder, Decoder)
case class Bar(s: String)
case class Bar(s: String)
object Bar {
implicit val _deriving_encoder: Encoder[Bar] = deriving
implicit val _deriving_decoder: Decoder[Bar] = deriving
}