├── project
├── build.properties
└── plugins.sbt
├── src
└── main
│ ├── scala
│ ├── loan
│ │ ├── loaned.txt
│ │ ├── BoundedLoan.scala
│ │ ├── DuckLoan.scala
│ │ └── SimpleLoan.scala
│ ├── hello
│ │ ├── NoFun.scala
│ │ ├── package.scala
│ │ ├── HelloFun.scala
│ │ └── TupleTrouble.scala
│ ├── evaluation
│ │ ├── package.scala
│ │ ├── ByName.scala
│ │ ├── ByValue.scala
│ │ └── LazyFibo.scala
│ ├── tailcall
│ │ ├── InfiniteStack.scala
│ │ └── Fibonacci.scala
│ ├── pimp
│ │ ├── ImplicitPimp.scala
│ │ ├── StringPimp.scala
│ │ └── ViewBoundPimp.scala
│ ├── syntax
│ │ └── scala
│ │ │ ├── Pessoa.scala
│ │ │ ├── Bicho.scala
│ │ │ ├── TypeAliases.scala
│ │ │ └── DOMLegacy.scala
│ ├── fun
│ │ ├── PartialFun.scala
│ │ ├── ComposeFun.scala
│ │ └── ExtractFun.scala
│ ├── style
│ │ └── ListMatch.scala
│ ├── reactiveish
│ │ ├── TickTock.scala
│ │ ├── SomeDay.scala
│ │ └── Earthquakes.scala
│ ├── gonads
│ │ ├── Optional.scala
│ │ ├── Attempt.scala
│ │ └── Gonads.scala
│ ├── streaming
│ │ └── Pages.scala
│ ├── cake
│ │ └── Sitcoms.scala
│ ├── interpol
│ │ └── Technicolour.scala
│ └── roadshow
│ │ └── ScalaEm10.scala
│ └── java
│ ├── tailcall
│ └── BigStack.java
│ └── syntax
│ └── java
│ ├── Bicho.java
│ ├── TypeAliases.java
│ ├── Pessoa.java
│ └── DOMLegacy.java
├── .idea
├── codeStyles
│ ├── codeStyleConfig.xml
│ └── Project.xml
├── vcs.xml
├── .gitignore
├── misc.xml
├── scala_compiler.xml
├── modules.xml
├── sbt.xml
└── modules
│ ├── scala-patterns_1595.iml
│ └── scala-patterns_1595-build.iml
├── .gitignore
├── .bsp
└── sbt.json
├── README.md
├── demos
├── scalaem10.sc
└── qconrj14.sc
└── .worksheet
└── src
└── ScalaEm10m.scala
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.5.3
2 |
--------------------------------------------------------------------------------
/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.4")
2 |
--------------------------------------------------------------------------------
/src/main/scala/loan/loaned.txt:
--------------------------------------------------------------------------------
1 | ************************
2 | ** Hello Loan Pattern **
3 | ************************
--------------------------------------------------------------------------------
/src/main/scala/hello/NoFun.scala:
--------------------------------------------------------------------------------
1 | package hello
2 |
3 | object NoFun
4 | extends App{
5 | o ▽ o
6 | ____
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/src/main/scala/evaluation/package.scala:
--------------------------------------------------------------------------------
1 | package object evaluation {
2 | def answer: Int = {
3 | println("calculating...")
4 | 42
5 | }
6 | }
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/main/scala/hello/package.scala:
--------------------------------------------------------------------------------
1 | package object hello {
2 | val o = 'o
3 | implicit class Emoticons(s:Symbol) {
4 | def ▽(s:Symbol) = println("Não faça isso em casa!")
5 | }
6 | def ____ = None
7 | }
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/scala_compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/main/scala/hello/HelloFun.scala:
--------------------------------------------------------------------------------
1 | package hello
2 |
3 | object HelloFun extends App {
4 | List("Hello", "QCon", "SP", "2016", "?", "!!!")
5 | .map { _.toUpperCase }
6 | .filter { _ != "?" }
7 | .foreach { println }
8 | }
--------------------------------------------------------------------------------
/src/main/scala/hello/TupleTrouble.scala:
--------------------------------------------------------------------------------
1 | package hello
2 |
3 | object TupleTrouble extends App {
4 |
5 | def div(a:Int,b:Int):(Int,Int) = (a/b, a%b)
6 |
7 | val (result,remain) = div (9,4)
8 | println(s"result: $result remain: $remain")
9 |
10 | }
--------------------------------------------------------------------------------
/src/main/scala/evaluation/ByName.scala:
--------------------------------------------------------------------------------
1 | package evaluation
2 |
3 | object ByName extends App {
4 | def pronounce(number: => Int) = {
5 | println(s"The number is $number !")
6 | println(s"The number is $number !")
7 | }
8 |
9 | pronounce(answer)
10 | }
--------------------------------------------------------------------------------
/src/main/java/tailcall/BigStack.java:
--------------------------------------------------------------------------------
1 | package tailcall;
2 |
3 | public class BigStack {
4 | static final Integer loop(int x) {
5 | System.out.println(x);
6 | return loop(-1*x);
7 | }
8 |
9 | public static void main(String[] args) {
10 | loop(1);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/scala/tailcall/InfiniteStack.scala:
--------------------------------------------------------------------------------
1 | package tailcall
2 |
3 | import scala.annotation.tailrec
4 |
5 | object InfiniteStack {
6 | @tailrec
7 | def lupi(x:Int):Int = {
8 | println(x)
9 | lupi(-1*x)
10 | }
11 |
12 | def main(args: Array[String]) { lupi(1) }
13 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 | *.log
3 |
4 | # sbt specific
5 | dist/*
6 | target/
7 | lib_managed/
8 | src_managed/
9 | project/boot/
10 | project/plugins/project/
11 |
12 | # Scala-IDE specific
13 | .scala_dependencies
14 |
15 |
16 | .DS_Store
17 | .project
18 | .settings
19 | .classpath
20 |
--------------------------------------------------------------------------------
/src/main/scala/evaluation/ByValue.scala:
--------------------------------------------------------------------------------
1 | package evaluation
2 |
3 | object ByValue extends App {
4 | def pronounce(number: Int) = {
5 | println(s"The number is $number !")
6 | println(s"The number is $number !")
7 | }
8 |
9 | pronounce(answer) //Where is anwser defined?
10 | }
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/main/scala/pimp/ImplicitPimp.scala:
--------------------------------------------------------------------------------
1 | package pimp
2 |
3 | object ImplicitPimp extends App {
4 |
5 | implicit class PimpedString(original: String) {
6 | def strong = s"$original"
7 | def em = s"$original"
8 | }
9 |
10 | println("Hello World".strong.em)
11 | }
--------------------------------------------------------------------------------
/src/main/scala/pimp/StringPimp.scala:
--------------------------------------------------------------------------------
1 | package pimp
2 |
3 | class StringPimp(original:String) {
4 | def strong = s"$original"
5 | def em = s"$original"
6 | }
7 |
8 | object Example extends App {
9 | implicit def pimpMyString(str:String) = new StringPimp(str)
10 | println("Hello World".strong.em)
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/src/main/scala/syntax/scala/Pessoa.scala:
--------------------------------------------------------------------------------
1 | package syntax.scala
2 |
3 | class Pessoa(val nome:String) {
4 | def saudacao = if (nome.length < 10)
5 | s"Oi $nome!"
6 | else throw new Exception("Nome muito longo")
7 | }
8 |
9 | object Pessoa extends App{
10 | val p = new Pessoa("Fulano")
11 | println(p.saudacao)
12 | println(p.nome)
13 | }
--------------------------------------------------------------------------------
/src/main/scala/fun/PartialFun.scala:
--------------------------------------------------------------------------------
1 | package fun
2 |
3 | object PartialFun extends App{
4 |
5 | type Named = PartialFunction[Int,String]
6 |
7 | val douglas:Named = {case 42 => "The Answer"}
8 | val sheldon:Named = {case 73 => "The Best"}
9 | val cool = douglas orElse sheldon
10 |
11 | 1 to 1000 collect cool foreach println
12 |
13 | }
--------------------------------------------------------------------------------
/.bsp/sbt.json:
--------------------------------------------------------------------------------
1 | {"name":"sbt","version":"1.5.3","bspVersion":"2.0.0-M5","languages":["scala"],"argv":["/home/jufaerma/.sdkman/candidates/java/11.0.11.9.1-amzn/bin/java","-Xms100m","-Xmx100m","-classpath","/home/jufaerma/.sdkman/candidates/sbt/1.5.3/bin/sbt-launch.jar","xsbt.boot.Boot","-bsp","--sbt-launch-jar=/home/jufaerma/.sdkman/candidates/sbt/1.5.3/bin/sbt-launch.jar"]}
--------------------------------------------------------------------------------
/src/main/scala/fun/ComposeFun.scala:
--------------------------------------------------------------------------------
1 | package fun
2 |
3 | object ComposeFun extends App{
4 | def twist(s:String) = s.reverse
5 | def shout(s:String) = s.toUpperCase + "!"
6 |
7 | def twistAndShout = twist _ andThen shout _
8 | def shoutedTwist = twist _ compose shout _
9 |
10 | println(twistAndShout("Shaking"))
11 | println(shoutedTwist("Oh Baby"))
12 | }
--------------------------------------------------------------------------------
/src/main/java/syntax/java/Bicho.java:
--------------------------------------------------------------------------------
1 | package syntax.java;
2 |
3 | class Nomeado {
4 | String nome;
5 | public Nomeado comNome(String nome){
6 | this.nome = nome;
7 | return this;
8 | }
9 | }
10 |
11 | class Bicho extends Nomeado {
12 | public void oi() {
13 | System.out.println(nome);
14 | }
15 |
16 | public static void main(String[] args) {
17 | new Bicho().comNome("Rex");//.oi();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/scala/tailcall/Fibonacci.scala:
--------------------------------------------------------------------------------
1 | package tailcall
2 |
3 | import scala.annotation.tailrec
4 |
5 | object Fiboonacci extends App {
6 | def fibo(num: Int): BigInt = fibo(num, 1, 0)
7 |
8 | @tailrec def fibo(num: Int, nxt: BigInt, res: BigInt): BigInt =
9 | num match {
10 | case 0 => res
11 | case _ => fibo(num - 1, nxt + res, nxt)
12 | }
13 |
14 | println(fibo(999999))
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/scala/syntax/scala/Bicho.scala:
--------------------------------------------------------------------------------
1 | package syntax.scala
2 | import scala.language.postfixOps
3 |
4 | object Bicho extends App{
5 |
6 | trait Nomeado {
7 | var name: String = _
8 |
9 | def comNome(name: String): this.type = {
10 | this.name = name
11 | this
12 | }
13 | }
14 |
15 | class Pessoa extends Nomeado {
16 | def oi = println(s"Oi $name")
17 | }
18 |
19 | new Pessoa() comNome("Julio") oi
20 | }
--------------------------------------------------------------------------------
/src/main/scala/style/ListMatch.scala:
--------------------------------------------------------------------------------
1 | package style
2 |
3 | //from http://twitter.github.io/effectivescala/
4 | object ListMatch extends App{
5 | val list = List(Option(1),Option(null),Option(3))
6 |
7 | list map { item =>
8 | item match {
9 | case Some(x) => println(x)
10 | case None => println("Oops")
11 | }
12 | }
13 |
14 | list map {
15 | case Some(x) => println(x)
16 | case None => println("Nice!")
17 | }
18 |
19 | }
--------------------------------------------------------------------------------
/src/main/scala/loan/BoundedLoan.scala:
--------------------------------------------------------------------------------
1 | package loan
2 |
3 | import java.io._
4 | import scala.io.Source._
5 |
6 | object BoundedLoan extends App {
7 |
8 | def withCloseable[R <: Closeable, T](closeable: R)(f: R => T): T =
9 | try f(closeable)
10 | finally if (closeable != null) closeable.close
11 |
12 | val in = getClass.getResourceAsStream("loaned.txt")
13 |
14 | withCloseable(in) { c =>
15 | println(fromInputStream(c).mkString)
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/src/main/scala/loan/DuckLoan.scala:
--------------------------------------------------------------------------------
1 | package loan
2 |
3 | import java.io._
4 | import scala.io.Source._
5 |
6 | object DuckLoan extends App {
7 |
8 | def withCloseable[R <: { def close() }, T](closeable: R)(f: R => T): T =
9 | try f(closeable)
10 | finally if (closeable != null) closeable.close
11 |
12 | val in = getClass.getResourceAsStream("loaned.txt")
13 |
14 | withCloseable(in) { in =>
15 | println(fromInputStream(in).mkString)
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/main/scala/syntax/scala/TypeAliases.scala:
--------------------------------------------------------------------------------
1 | package syntax.scala
2 |
3 | class TypeAliases {
4 |
5 | type Versao = Int
6 | type Significado = String
7 | type Significados = Map[Versao,Significado]
8 | type Palavra = String
9 | type Dicionario = Map[Palavra,Significados]
10 |
11 | val dics:Dicionario = Map()
12 | def lookup(palavra:Palavra,versao:Versao) =
13 | dics.get(palavra)
14 | .flatMap{_.get(versao)}
15 | .getOrElse(throw new IllegalArgumentException)
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/scala/loan/SimpleLoan.scala:
--------------------------------------------------------------------------------
1 | package loan
2 |
3 | import java.io._
4 | import scala.io.Source._
5 |
6 | object SimpleLoan extends App {
7 |
8 | def withResource[T](resource: String)(f: InputStream => T):T = {
9 | var in: InputStream = null
10 | try {
11 | in = getClass.getResourceAsStream(resource)
12 | f(in)
13 | } finally {
14 | if (in != null) in.close
15 | }
16 | }
17 |
18 | withResource("loaned.txt") { in =>
19 | println(fromInputStream(in).mkString)
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/src/main/java/syntax/java/TypeAliases.java:
--------------------------------------------------------------------------------
1 | package syntax.java;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | public class TypeAliases {
7 |
8 | Map> dics = new HashMap<>();
9 |
10 | public String lookup(String palavra, Integer versao) {
11 | if(dics.containsKey(palavra)){
12 | Map dict = dics.get(palavra);
13 | if (dict.containsKey(versao)){
14 | return dict.get(versao);
15 | }
16 | }
17 | throw new IllegalArgumentException();
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/syntax/java/Pessoa.java:
--------------------------------------------------------------------------------
1 | package syntax.java;
2 |
3 | public class Pessoa {
4 | String nome;
5 |
6 | public Pessoa(String nome) {
7 | this.nome = nome;
8 | }
9 |
10 | public String saudacao() throws Exception {
11 | if(nome.length() < 10)
12 | return "Oi "+nome+"!";
13 | else
14 | throw new Exception("Nome muito longo");
15 | }
16 |
17 | public static void main(String[] args) throws Exception{
18 | Pessoa p = new Pessoa("Fulano");
19 | System.out.println(p.saudacao());
20 | System.out.println(p.nome);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/scala/pimp/ViewBoundPimp.scala:
--------------------------------------------------------------------------------
1 | package pimp
2 |
3 | trait Numberish
4 | case object one extends Numberish
5 | case object two extends Numberish
6 | case object three extends Numberish
7 |
8 | object ViewBoundPimp extends App {
9 | implicit def toInt(x: Numberish) = x match {
10 | case `one` => 1
11 | case `two` => 2
12 | case `three` => 3
13 | }
14 |
15 | def cube[T <% Int](a: T) = a * a * a
16 |
17 | val answer = cube(three)
18 | + cube(2)
19 | + 2 * three
20 | + one
21 | println(answer)
22 | }
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/.idea/sbt.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/scala/fun/ExtractFun.scala:
--------------------------------------------------------------------------------
1 | package fun
2 |
3 | import java.math.BigInteger
4 |
5 | object ExtractFun extends App {
6 |
7 | def isPrime(x: Int) = BigInteger
8 | .valueOf(x)
9 | .isProbablePrime(Integer.MAX_VALUE)
10 |
11 | object Prime {
12 | def unapply(x: Int): Option[Int] =
13 | if (isPrime(x)) Some(x)
14 | else None
15 | }
16 |
17 | object Double {
18 | def unapply(x: Int): Option[Int] =
19 | if (x % 2 == 0) Some(x)
20 | else None
21 | }
22 |
23 | (1 to 20) collect {
24 | case Prime(x) => s"$x is a prime"
25 | case Double(x) => s"$x is a double"
26 | } foreach println
27 |
28 | }
--------------------------------------------------------------------------------
/src/main/scala/reactiveish/TickTock.scala:
--------------------------------------------------------------------------------
1 | package reactiveish
2 |
3 | import rx.lang.scala._
4 | import rx.lang.scala.schedulers._
5 | import scala.concurrent.duration._
6 | import scala.concurrent.Await
7 | import java.util.Date
8 | import scala.language.postfixOps
9 |
10 | object TickTock extends App {
11 | val freq = 500
12 | val ticks: Observable[Long] = Observable.interval(freq millis)
13 |
14 | val sub = ticks
15 | .map { _ * freq }
16 | .filter { _ % 1000 == 0 }
17 | //.buffer(3,2)
18 | .subscribe { tick => println(f"${new Date}%tT ${tick}%s") }
19 |
20 | Thread.sleep(20 * freq)
21 | sub.unsubscribe
22 | Thread.sleep(2 * freq)
23 | println("Time for lunch!")
24 | }
--------------------------------------------------------------------------------
/src/main/scala/evaluation/LazyFibo.scala:
--------------------------------------------------------------------------------
1 | package evaluation
2 |
3 | import java.math.BigInteger
4 | import scala.annotation.tailrec
5 | import scala.language.postfixOps
6 |
7 | object FiboFight extends App {
8 |
9 | def fibo(num: Int): BigInt = fiborec(num, 1, 0)
10 |
11 | @tailrec
12 | def fiborec(num: Int,
13 | nxt: BigInt,
14 | res: BigInt): BigInt = num match {
15 | case 0 => res
16 | case _ => fiborec(num - 1, nxt + res, nxt)
17 | }
18 |
19 | println(fibo(1000000))
20 |
21 | lazy val fibs:Stream[BigInt] =
22 | BigInt(BigInteger.ZERO) #::
23 | BigInt(BigInteger.ONE) #::
24 | (fibs zip fibs.tail).map{ t => t._1 + t._2 }
25 | println(fibs drop(100) take(1) head)
26 |
27 | }
--------------------------------------------------------------------------------
/src/main/scala/gonads/Optional.scala:
--------------------------------------------------------------------------------
1 | package gonads
2 |
3 | import scala.util.Random
4 | import scala.util.Success
5 | import scala.util.Success
6 |
7 | object Optional extends App {
8 | def random = Random.nextInt(4)
9 |
10 | def unreliable:Integer = {
11 | val result = random // Is "random" a field or a method?
12 | if (result == 0) null else result
13 | }
14 |
15 | def optional = Option(unreliable)
16 |
17 | optional match {
18 | case Some(x) => println(s"Got a $x! Yay!")
19 | case None => println("Not today :(")
20 | }
21 |
22 | println
23 |
24 | val names:Function[Int,String] = Map(1 -> "One", 2 -> "Two", 3 -> "Three")
25 |
26 | List.fill(10)(optional)
27 | .flatMap { _ map { names(_) } } // Is "names" a Map, a method or a field?
28 | .zipWithIndex
29 | .foreach { case (name, index) => println(s"$index. $name") }
30 |
31 | }
--------------------------------------------------------------------------------
/src/main/scala/streaming/Pages.scala:
--------------------------------------------------------------------------------
1 | package streaming
2 | import math._
3 |
4 | case class Page(number: Int)
5 |
6 | case class Pages(pages: Seq[Page], truncated: Boolean)
7 |
8 | class PagesService(pageSize: Int, pagesServed: Int) {
9 | def getPages =
10 | Pages((1 to pageSize).map(Page), pageSize < pagesServed)
11 |
12 | def nextPages(previous: Pages) = {
13 | val first = previous.pages.last.number + 1
14 | val last = min(first + pageSize, pagesServed)
15 | Pages((first to last).map(Page), last < pagesServed)
16 | }
17 | }
18 |
19 | object PagesClient extends App {
20 | val service = new PagesService(10, 100)
21 |
22 | val chapters: Stream[Pages] = service.getPages #::
23 | chapters
24 | .map(service.nextPages)
25 | .takeWhile(_.pages.nonEmpty)
26 |
27 | val book: Stream[Page] = chapters.flatten(_.pages)
28 |
29 | book take 50 foreach { println(_) }
30 | }
31 |
--------------------------------------------------------------------------------
/.idea/modules/scala-patterns_1595.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/main/java/syntax/java/DOMLegacy.java:
--------------------------------------------------------------------------------
1 | package syntax.java;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.InputStream;
5 |
6 | import javax.xml.parsers.DocumentBuilderFactory;
7 |
8 | import org.w3c.dom.Document;
9 | import org.w3c.dom.NodeList;
10 |
11 | public class DOMLegacy {
12 | public static void main(String[] args) throws Exception {
13 | String xhtml = ""
14 | +" Oi
"
15 | +" Mundo
"
16 | +"";
17 | InputStream is = new ByteArrayInputStream(xhtml.getBytes());
18 | Document doc = DocumentBuilderFactory
19 | .newInstance()
20 | .newDocumentBuilder()
21 | .parse(is);
22 | NodeList nodes = doc.getElementsByTagName("h1");
23 | //Se ao menos NodeList estendesse Iterable...
24 | for (int i = 0; i < nodes.getLength() ; i++) {
25 | String content = nodes.item(i).getTextContent();
26 | System.out.println(content);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/scala/cake/Sitcoms.scala:
--------------------------------------------------------------------------------
1 | package cake
2 |
3 | trait InterjectionComponent {
4 | def interjector: Interjector
5 |
6 | trait Interjector {
7 | def interjection: String
8 | }
9 | }
10 |
11 | trait BigBangTheory extends InterjectionComponent {
12 | def interjector = Sheldon
13 |
14 | object Sheldon extends Interjector {
15 | def interjection = "BAZINGA"
16 | }
17 | }
18 |
19 | trait Simpsons extends InterjectionComponent {
20 | def interjector = Homer
21 |
22 | object Homer extends Interjector {
23 | def interjection = "DUH"
24 | }
25 | }
26 |
27 | trait Sitcom {
28 | def play
29 | }
30 |
31 | trait SimpleSitcom extends Sitcom {
32 | this: InterjectionComponent => /* this self type is required to be mixed-in */
33 |
34 | def play = println( s"${interjector.interjection}! Ahauhuauhahu!")
35 | }
36 |
37 | object Sitcoms extends App {
38 | val sony = new SimpleSitcom with BigBangTheory
39 | val fox = new SimpleSitcom with Simpsons
40 | sony.play
41 | fox.play
42 | }
--------------------------------------------------------------------------------
/src/main/scala/reactiveish/SomeDay.scala:
--------------------------------------------------------------------------------
1 | package reactiveish
2 |
3 | import scala.util._
4 | import scala.concurrent._
5 | import ExecutionContext.Implicits.global
6 | import scala.language.postfixOps
7 | import scala.concurrent.duration._
8 |
9 | object SomeDay extends App {
10 | def read(url: String) = {
11 | Thread.sleep(1000)
12 | url
13 | }
14 |
15 | val qconsp = Future {
16 | println("Going to a nice conference will take a while!")
17 | read("http://qconsp.com")
18 | }
19 | println("The future has begun!")
20 | Thread.sleep(2000)
21 |
22 | println("Let us check results")
23 | qconsp.onComplete {
24 | case Success(site) => println(s"Once: ${site.substring(0, 50)}")
25 | case Failure(exception) => exception.printStackTrace()
26 | }
27 |
28 | //And cache results
29 | qconsp.onComplete {
30 | case Success(site) => println(s"Again: ${site.substring(0, 50)}")
31 | case Failure(exception) => exception.printStackTrace()
32 | }
33 |
34 | Await.ready(qconsp, 10 seconds)
35 | }
--------------------------------------------------------------------------------
/src/main/scala/syntax/scala/DOMLegacy.scala:
--------------------------------------------------------------------------------
1 | package syntax.scala
2 |
3 | import java.io.ByteArrayInputStream
4 | import javax.xml.parsers.DocumentBuilderFactory
5 | import org.w3c.dom.NodeList
6 | import org.w3c.dom.Node
7 |
8 | import java.util
9 |
10 | object DOMLegacy extends App {
11 | val xhtml = """
12 | Oi
13 | Mundo
14 | """
15 | val is = new ByteArrayInputStream(xhtml.getBytes)
16 | val doc = DocumentBuilderFactory
17 | .newInstance
18 | .newDocumentBuilder
19 | .parse(is)
20 | val nodes:NodeList = doc.getElementsByTagName("h1")
21 | //Nada que uma conversao implicita nao resolva
22 | implicit class TraversableNodeList(nl: NodeList)
23 | extends Traversable[Node] {
24 |
25 | def iterator: Iterator[org.w3c.dom.Node] = ???
26 |
27 | override def foreach[U](f: Node => U): Unit =
28 | for (i <- 0 until nl.getLength) f(nl.item(i))
29 | }
30 |
31 | /*
32 | for (node <- nodes;
33 | content <- node.getTextContent)
34 | println(content)
35 |
36 | */
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/scala/gonads/Attempt.scala:
--------------------------------------------------------------------------------
1 | package gonads
2 |
3 | import scala.util.Try
4 | import scala.util.Success
5 | import scala.util.Failure
6 |
7 | object Attempt extends App {
8 | //Try: Explicitly materialize exception and defer handling
9 | def divide(num:Int,denom:Int) = Try { num/denom }
10 |
11 | def name(small:Int) = Try {
12 | small match {
13 | case 1 => "One"
14 | case 2 => "Two"
15 | case 3 => "Three"
16 | case _ => throw new IllegalArgumentException
17 | }
18 | }
19 |
20 | //Composition with flatMap
21 | def divideAndName1(num:Int,denom:Int):Try[String] = divide(num,denom) flatMap name
22 |
23 | //Composition with for comprehension
24 | def divideAndName2(num:Int,denom:Int):Try[String] = for {
25 | result <- divide(num,denom)
26 | name <- name(result)
27 | } yield name
28 |
29 | val three = divideAndName1(9,3)
30 | val nan = divideAndName2(42,0)
31 |
32 | //Pattern matching on Try
33 | three match {
34 | case Success(s) => println(s)
35 | case Failure(t) => println(s"Oops: ${t.getMessage}")
36 | }
37 |
38 | println(nan)
39 |
40 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Some examples of design patterns for Scala programming
2 |
3 | References:
4 |
5 | Patterns in Scala 101
6 | - https://code.sahebmotiani.com/patterns-in-scala-101-5d0fa70aaf3f#.p6x1krijb
7 |
8 | Loan Pattern
9 | - https://wiki.scala-lang.org/display/SYGN/Loan
10 |
11 | Cake Pattern
12 | - http://lampwww.epfl.ch/~odersky/papers/ScalableComponent.pdf
13 | - http://www.cakesolutions.net/teamblogs/2011/12/19/cake-pattern-in-depth/
14 | - http://biased-and-fair-software-development.blogspot.com.br/2011/01/slicing-cake.html
15 |
16 | Pimp my lib Pattern
17 | - http://www.artima.com/weblogs/viewpost.jsp?thread=179766
18 |
19 | Type Bounds
20 | - http://twitter.github.com/scala_school/advanced-types.html
21 |
22 | Misc Scala
23 | - http://zeroturnaround.com/labs/scala-sink-or-swim-part-1/
24 | - http://zeroturnaround.com/labs/scala-sink-or-swim-part-2/
25 | - http://zeroturnaround.com/labs/scala-sink-or-swim-part-3/
26 | - http://www.infoq.com/articles/scala-java-myths-facts
27 | - http://www.artima.com/scalazine/articles/package_objects.html
28 |
29 | Misc Functional Programing
30 | - Functional Programming Pearls http://www.haskell.org/haskellwiki/Research_papers/Functional_pearls
31 |
--------------------------------------------------------------------------------
/.idea/modules/scala-patterns_1595-build.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/main/scala/gonads/Gonads.scala:
--------------------------------------------------------------------------------
1 | package gonads
2 |
3 | import scala.util.Try
4 | import scala.concurrent._
5 | import scala.concurrent.ExecutionContext.Implicits.global
6 | import java.text.SimpleDateFormat
7 | import java.util.Date
8 | import scala.util.Random._
9 |
10 | object Gonads extends App {
11 |
12 | def triplo(i: Integer) = i * 3
13 |
14 | def triploOuNada(i: Integer):Integer =
15 | if (i % 2 == 0) triplo(i)
16 | else null
17 |
18 | def triploOuFalha(i: Integer):Integer =
19 | if (i % 3 == 0) triplo(i)
20 | else throw new Exception("Ops")
21 |
22 | def triploOuDemora(i: Integer): Integer = {
23 | if (i % 4 != 0) Thread.sleep(2000)
24 | triplo(i)
25 | }
26 |
27 | Option{ triploOuNada(2) }.map(triplo).foreach(println)
28 | Option{ triploOuNada(3) }.map(triplo).foreach(println)
29 |
30 | //Lidando com falhas
31 |
32 |
33 | Try{ triploOuFalha(3) }.map(triplo).foreach(println)
34 | Try{ triploOuFalha(4) }.map(triplo).foreach(println)
35 |
36 | //Lidando com latencia
37 |
38 |
39 | val sdf = new SimpleDateFormat("HH:mm:ss")
40 | def now = sdf.format(new Date)
41 |
42 | Future{ triploOuDemora(4) }.map(triplo).foreach(i => println(s"${i} @ ${now}"))
43 | Future{ triploOuDemora(5) }.map(triplo).foreach(i => println(s"${i} @ ${now}"))
44 |
45 | Thread.sleep(3000)
46 |
47 | val rands = Seq.fill(12){nextInt(100)}
48 |
49 | for {
50 | r <- rands
51 | o <- Option { triploOuNada(r) }
52 | t <- Try { triploOuFalha(o) }
53 | f <- Future { triploOuDemora(t) }
54 | } println(s"${f} @ ${now} !" )
55 |
56 |
57 | Thread.sleep(5000)
58 |
59 | }
--------------------------------------------------------------------------------
/src/main/scala/interpol/Technicolour.scala:
--------------------------------------------------------------------------------
1 | package interpol
2 |
3 | import scala.collection.mutable.ListBuffer
4 | import scala.util.Try
5 | import scala.util.Random
6 |
7 | object Colour extends Enumeration {
8 | val Blue, Red, Green, Yellow, Magenta, Cyan, Flicts = Value
9 | }
10 |
11 | object Technicolour extends App {
12 | val green = Colour.Green
13 |
14 | println(colour"$green + Blue")
15 |
16 | println(colour"Blue with ${green} and Yellow vs. ${green} or Magenta")
17 |
18 | implicit class Colored(val sc: StringContext) extends AnyVal {
19 | //Interpolation magic below
20 | //Derived from http://www.monadzoo.com/blog/2013/01/06/scala-string-interpolation-it-happened/
21 |
22 | def colour(args: Any*): Colour.Value = {
23 | //Mutable WITH Immutable
24 | val strings = sc.parts.iterator
25 | val expressions = args.iterator
26 | var buf = new ListBuffer[Colour.Value]
27 | while (strings.hasNext) {
28 | buf ++= strings.next
29 | if (expressions.hasNext)
30 | buf ++= expressions.next.toString
31 | }
32 | val result = buf reduceLeft mix
33 | //println(s"[DEBUG] $buf = $result") // <= S Interpolator
34 | result
35 | }
36 |
37 | //Combine pairs of colours
38 | def mix(a: Colour.Value, b: Colour.Value): Colour.Value = (a, b) match {
39 | case (Colour.Green, Colour.Red) => Colour.Yellow
40 | case (Colour.Red, Colour.Green) => Colour.Yellow
41 | case (Colour.Red, Colour.Blue) => Colour.Magenta
42 | case (Colour.Blue, Colour.Red) => Colour.Magenta
43 | case (Colour.Blue, Colour.Green) => Colour.Cyan
44 | case (Colour.Green, Colour.Blue) => Colour.Cyan
45 | case (_, _) => Colour.Flicts
46 | }
47 |
48 | //Implicit conversion from String to Colours
49 | implicit def flying(colors: String): Seq[Colour.Value] =
50 | colors.split("\\s+")
51 | .map(t => Try { Colour.withName(t) })
52 | .filter { _.isSuccess }
53 | .map { _.get }
54 | }
55 |
56 | }
--------------------------------------------------------------------------------
/src/main/scala/reactiveish/Earthquakes.scala:
--------------------------------------------------------------------------------
1 | package reactiveish
2 |
3 | import rx.lang.scala._
4 | import scala.util.Random
5 | import scala.concurrent.Future
6 | import scala.concurrent.ExecutionContext.Implicits.global
7 | object Earthquakes extends App {
8 | type GeoCoordinate = Tuple2[Double, Double]
9 |
10 | case class Earthquake(magnitude: Double, location: GeoCoordinate)
11 |
12 | def usgs: Observable[Earthquake] = Observable { observer =>
13 | {
14 | while (true) {
15 | val freq = 1500
16 | val rand: Double = Random.nextInt(freq)
17 | val quake = Earthquake((rand / freq), (rand % 3, (rand % 3) + 1))
18 | observer.onNext(quake)
19 | Thread.sleep(500 + rand.round)
20 | }
21 | }
22 | }
23 |
24 | object Magnitude extends Enumeration {
25 | def apply(magnitude: Double): Magnitude = magnitude match {
26 | case x if (x < 0.15) => Micro
27 | case x if (x < 0.30) => Minor
28 | case x if (x < 0.45) => Light
29 | case x if (x < 0.60) => Moderate
30 | case x if (x < 0.75) => Strong
31 | case x if (x < 0.90) => Major
32 | case _ => Great
33 | }
34 |
35 | type Magnitude = Value
36 | val Micro, Minor, Light, Moderate, Strong, Major, Great = Value
37 | }
38 |
39 | object Country extends Enumeration {
40 | type Country = Value
41 | val Aral, Dudkinka, Vladivostok = Value
42 | }
43 |
44 | val quakes = usgs
45 |
46 | val decent = quakes
47 | .map { q => (q.location, Magnitude(q.magnitude)) }
48 | .filter { case (loc, mag) => mag >= Magnitude.Moderate }
49 |
50 | //decent.subscribe { println(_) }
51 |
52 | def reverseGeocode(c: GeoCoordinate): Future[Country.Value] = Future {
53 | Thread.sleep(Random.nextInt(1000))
54 | c match {
55 | case (1.0, 2.0) => Country.Aral
56 | case (2.0, 3.0) => Country.Dudkinka
57 | case _ => Country.Vladivostok
58 | }
59 | }
60 |
61 | val withCountry: Observable[Observable[(Magnitude.Value, Country.Value)]] = {
62 | quakes.map { quake => {
63 | val country: Future[Country.Value] = reverseGeocode(quake.location)
64 | Observable.from(country.map(country => (Magnitude(quake.magnitude), country)))
65 | }
66 | }
67 | }
68 |
69 | withCountry.concat.subscribe { println(_) }
70 |
71 | }
--------------------------------------------------------------------------------
/demos/scalaem10.sc:
--------------------------------------------------------------------------------
1 | /**
2 | * Scala em 10m
3 | *
4 | * Julio M. Faerman
5 | * @jmfaerman
6 | *
7 | * - Por que aprender Scala?
8 | * - Três melhorias ao Java
9 | * 1- Linguagem Enxuta
10 | * 2- Reuso e Melhoria de APIs
11 | * 3- Programação Funcional
12 | *
13 | * Codigo em http://bit.ly/scalaem10m
14 | **/
15 |
16 | import java.text._
17 | import java.util._
18 | import javax.xml.parsers._
19 | import org.w3c.dom._
20 | import java.io._
21 |
22 | object ScalaEm10m {
23 | println("Scala em 10m") //> Scala em 10m
24 |
25 | //1. Linguagem Enxuta
26 |
27 | class Pessoa(nome: String) {
28 | /*
29 | var nome
30 | def this(nome:String) = {
31 | this.nome = nome
32 | }
33 | */
34 |
35 | /*public*/ def saudacao /*():String throws Exception*/ =
36 | //{
37 | //var result:String
38 | if (nome.length() < 10)
39 | //Interpolacao de String
40 | /*result =*/ s"oi $nome!"
41 | else throw new Exception("Nome Muito Longo")
42 | //return result
43 | //}
44 | }
45 |
46 | //Inferencia de tipos
47 | val fulano = new Pessoa("Fulano") //> fulano : ScalaEm10m.Pessoa = ScalaEm10m$$anonfun$main$1$Pessoa$1@7f63425a
48 | println(fulano.saudacao) //> oi Fulano!
49 |
50 | //2. Reuso e Melhoria
51 |
52 | // Melhorando a classe String
53 | implicit class StringMelhor(str: String) {
54 | def enfatize = s"$str"
55 | }
56 |
57 | println("Uau!!!".enfatize) //> Uau!!!
58 |
59 | // NodeList vs List?
60 | def xhtml = """
61 |
62 | um
63 | dois
64 | tres
65 |
66 | """ //> xhtml: => String
67 |
68 | val doc = DocumentBuilderFactory
69 | .newInstance
70 | .newDocumentBuilder
71 | .parse(new ByteArrayInputStream(xhtml.getBytes))
72 | //> doc : org.w3c.dom.Document = [#document: null]
73 |
74 | val nodeList:NodeList = doc.getElementsByTagName("div")
75 | //> nodeList : org.w3c.dom.NodeList = com.sun.org.apache.xerces.internal.dom.D
76 | //| eepNodeListImpl@2d6e8792
77 |
78 | implicit class TraversableNodeList(nl: NodeList) extends Traversable[Node] {
79 | override def foreach[U](f: Node => U): Unit =
80 | for (i <- 0 until nl.getLength) f(nl.item(i))
81 | }
82 |
83 | for (node <- nodeList) println(node.getTextContent())
84 | //> um
85 | //| dois
86 | //| tres
87 |
88 | //3. Programacao Funcional
89 |
90 | //Collections e Closures
91 | nodeList
92 | .map { _.getTextContent }
93 | .filter { _.length > 3 }
94 | .foreach { println } //> dois
95 | //| tres
96 | val sdf = new SimpleDateFormat("HH:mm:ss")//> sdf : java.text.SimpleDateFormat = java.text.SimpleDateFormat@8140d380
97 | def now = sdf.format(new Date) //> now: => String
98 | def imprime(s:Any) = println(s"${s} @ ${now}") //> imprime: (s: Any)Unit
99 |
100 | def treta(i: Integer) =
101 | if (i == 2)
102 | null
103 | else if (i == 3)
104 | throw new Exception()
105 | else if (i == 4) {
106 | Thread.sleep(2000)
107 | i
108 | } else i //> treta: (i: Integer)Integer
109 |
110 | // Lidando com null
111 | val o1 = Option{ treta(1) } //> o1 : Option[Integer] = Some(1)
112 | val o2 = Option{ treta(2) } //> o2 : Option[Integer] = None
113 |
114 | o1.map(_ * 2).foreach(imprime) //> 2 @ 20:11:50
115 | o2.map(_ * 2).foreach(imprime)
116 |
117 | // Lidando com falha
118 | import scala.util.Try
119 |
120 | Try{ treta(1) }.map(_ * 2).foreach(imprime) //> 2 @ 20:11:50
121 | Try{ treta(3) }.map(_ * 2).foreach(imprime)
122 |
123 | // Lidando com latencia
124 | import scala.concurrent._
125 | import scala.concurrent.ExecutionContext.Implicits.global
126 |
127 | Future{ treta(1) }.map(_ * 2).foreach(imprime)
128 | Future{ treta(4) }.map(_ * 2).foreach(imprime)
129 | //> 2 @ 20:11:50
130 |
131 | Thread.sleep(5000) //> 8 @ 20:11:52
132 |
133 | // Alguma semelhanca?
134 | Option { treta(2) }.map(_ * 2).foreach(imprime)
135 | Try { treta(3) }.map(_ * 2).foreach(imprime)
136 | Future { treta(4) }.map(_ * 2).foreach(imprime)
137 |
138 | Thread.sleep(3000) //> 8 @ 20:11:57
139 |
140 |
141 | def rand = new Random().nextInt(3)+1 //> rand: => Int
142 |
143 | val itof = Future(Option(Try(treta(rand))))
144 | //> itof : scala.concurrent.Future[Option[scala.util.Try[Integer]]] = scala.co
145 | //| ncurrent.impl.Promise$DefaultPromise@29ca901e
146 |
147 | for (ito <- itof;
148 | it <- ito;
149 | i <- it)
150 | imprime(i)
151 |
152 | Thread.sleep(5000) //> 1 @ 20:11:58-
153 | }
154 | // Obrigado! Perguntas?
155 | // Codigo em http://bit.ly/scalaem10m
156 | //
157 | // Julio M. Faerman - @jmfaerman
158 | // ___________________
159 | // < Conheça a Eduvem >
160 | // < http://eduvem.com >
161 | // -------------------
162 | // \ ^__^
163 | // \ (oo)\_______
164 | // (__)\ )\/\
165 | // ||----w |
166 | // || ||
167 | //
--------------------------------------------------------------------------------
/.worksheet/src/ScalaEm10m.scala:
--------------------------------------------------------------------------------
1 | import org.w3c.dom.NodeList
2 | import java.io.InputStream
3 |
4 | /**
5 | * Julio M. Faerman
6 | * @jmfaerman
7 | *
8 | * - Por que aprender Scala?
9 | * - Três funcionalidades chave
10 | * 1 Linguagem Enxuta
11 | * 2 Reuso e Melhoria
12 | * 3 Programação Funcional
13 | * - E dai?
14 | *
15 | * Codigo em http://bit.ly/scalaem10m
16 | **/
17 | object ScalaEm10m {;import org.scalaide.worksheet.runtime.library.WorksheetSupport._; def main(args: Array[String])=$execute{;$skip(347);
18 | println("Scala em 10m no Speakers Weekend")
19 |
20 | //1. Linguagem Enxuta
21 |
22 | class Pessoa(nome: String) { //<- Isso e um contstrutor e um campo
23 | /*public*/ def saudacao /*():String throws Exception*/ =
24 | //{
25 | //var result:String
26 | if (nome.length() < 10)
27 | //Interpolacao de String
28 | /*result =*/ s"oi $nome!"
29 | else throw new Exception("Nome Muito Longo")
30 | //return result
31 | //}
32 | };$skip(434);
33 |
34 | //Inferencia de tipos
35 | val fulano = new Pessoa("Fulano");System.out.println("""fulano : ScalaEm10m.Pessoa = """ + $show(fulano ));$skip(26);
36 | println(fulano.saudacao)
37 |
38 | //2. Reuso e Melhoria
39 | implicit class StringMelhor(str: String) {
40 | def tagueie(tag: String) = s"<$tag>$str$tag>"
41 | def enfatize = tagueie("em")
42 | };$skip(189);
43 |
44 | println("Uau!!!".enfatize)
45 |
46 | //"Compativel" com bibliotecas Java
47 | import javax.xml.parsers._
48 | import org.w3c.dom._
49 | import java.io._;$skip(257);
50 |
51 | def data = new ByteArrayInputStream(
52 | """
53 |
54 | um
55 | dois
56 | tres
57 |
58 | """.getBytes);System.out.println("""data: => java.io.ByteArrayInputStream""");$skip(93);
59 |
60 | val doc = DocumentBuilderFactory
61 | .newInstance
62 | .newDocumentBuilder
63 | .parse(data);System.out.println("""doc : org.w3c.dom.Document = """ + $show(doc ));$skip(108);
64 |
65 |
66 | //As "palavras chave" te entendem também
67 | val nodeList:NodeList = doc.getElementsByTagName("div")
68 |
69 | implicit class TraversableNodeList(nl: NodeList) extends Traversable[Node] {
70 | override def foreach[U](f: Node => U): Unit =
71 | for (i <- 0 until nl.getLength) f(nl.item(i))
72 | };System.out.println("""nodeList : org.w3c.dom.NodeList = """ + $show(nodeList ));$skip(245);
73 |
74 | for (node <- nodeList) println(node.getTextContent());$skip(153);
75 |
76 | //3. Programacao Funcional
77 |
78 | //Collections e Closures
79 | nodeList
80 | .map { _.getTextContent }
81 | .filter { _.length > 3 }
82 | .foreach { println }
83 |
84 | //Funcoes como argumentos e retornos
85 | implicit class InputExtreme(in: InputStream) {
86 | def aplica[T](f: InputStream => T): T =
87 | try f(in)
88 | finally in.close
89 | }
90 |
91 | import scala.io.Source;$skip(336);
92 | def destagueia(in: InputStream) = Source
93 | .fromInputStream(in)
94 | .mkString
95 | .replaceAll("<", "[")
96 | .replaceAll(">", "]");System.out.println("""destagueia: (in: java.io.InputStream)String""");$skip(27); val res$0 =
97 |
98 | data.aplica(destagueia);System.out.println("""res0: String = """ + $show(res$0));$skip(55);
99 |
100 | //Lidando com null
101 | def triplo(i: Integer) = i * 3;System.out.println("""triplo: (i: Integer)Int""");$skip(74);
102 | def triploOuNada(i: Int): Integer = if (i % 2 == 0) triplo(i) else null;System.out.println("""triploOuNada: (i: Int)Integer""");$skip(58);
103 |
104 | Option{ triploOuNada(2) }.map(triplo).foreach(println);$skip(57);
105 | Option{ triploOuNada(3) }.map(triplo).foreach(println)
106 |
107 | //3.4 Lidando com falha
108 | import scala.util.Try;$skip(153);
109 |
110 | def triploOuFalha(i: Integer): Integer = if (i % 3 == 0) triplo(i) else throw new Exception("Ops");System.out.println("""triploOuFalha: (i: Integer)Integer""");$skip(55);
111 | Try{ triploOuFalha(3) }.map(triplo).foreach(println);$skip(55);
112 | Try{ triploOuFalha(4) }.map(triplo).foreach(println)
113 |
114 | //3.5 Lidando com latencia
115 | import scala.concurrent._
116 | import scala.concurrent.ExecutionContext.Implicits.global;$skip(237);
117 |
118 | def triploOuDemora(i: Integer): Integer = if (i % 4 == 0)
119 | triplo(i)
120 | else {
121 | Thread.sleep(2000)
122 | i
123 | }
124 |
125 | import java.text.SimpleDateFormat
126 | import java.util.Date;System.out.println("""triploOuDemora: (i: Integer)Integer""");$skip(111);
127 |
128 | val sdf = new SimpleDateFormat("HH:mm:ss");System.out.println("""sdf : java.text.SimpleDateFormat = """ + $show(sdf ));$skip(33);
129 | def now = sdf.format(new Date);System.out.println("""now: => String""");$skip(84);
130 |
131 | Future{ triploOuDemora(4) }.map(triplo).foreach(i => println(s"${i} @ ${now}"));$skip(81);
132 | Future{ triploOuDemora(5) }.map(triplo).foreach(i => println(s"${i} @ ${now}"));$skip(21);
133 | Thread.sleep(3000);$skip(85);
134 |
135 | // Alguma semelhanca?
136 | Option { triploOuNada(1) }.map(triplo).foreach(println);$skip(59);
137 | Try { triploOuFalha(1) }.map(triplo).foreach(println);$skip(59);
138 | Future { triploOuDemora(1) }.map(triplo).foreach(println)
139 |
140 | import scala.util.Random._;$skip(71);
141 | val rands = Seq.fill(12){nextInt(100)};System.out.println("""rands : Seq[Int] = """ + $show(rands ));$skip(152);
142 | for {
143 | q <- rands
144 | c <- Option { triploOuNada(q) }
145 | o <- Try { triploOuFalha(c) }
146 | n <- Future { triploOuDemora(o) }
147 | } println(s"${n} @ ${now}" );$skip(21);
148 |
149 | Thread.sleep(5000)}
150 | }
151 | // Obrigado! Perguntas?
152 | // Codigo em http://bit.ly/scalaem10m
153 | //
154 | // Julio M. Faerman - @jmfaerman
155 | // ___________________
156 | // < Conheça a Eduvem >
157 | // < http://eduvem.com >
158 | // -------------------
159 | // \ ^__^
160 | // \ (oo)\_______
161 | // (__)\ )\/\
162 | // ||----w |
163 | // || ||
164 | //
165 |
--------------------------------------------------------------------------------
/src/main/scala/roadshow/ScalaEm10.scala:
--------------------------------------------------------------------------------
1 | package roadshow
2 |
3 | import org.w3c.dom.NodeList
4 | import java.io.InputStream
5 |
6 | object ScalaEm10 extends App {
7 | println("Scala em 10m")
8 |
9 | //1. Seja menos prolixo
10 | class Pessoa(nome: String) { //<- Isso e um contstrutor
11 | /*public*/ def saudacao /*():String throws Exception*/ =
12 | //{
13 | //var result:String
14 | if (nome.length() < 10)
15 | /*result =*/ s"oi $nome!"
16 | else throw new Exception("Nome Muito Longo")
17 | //return result
18 | //}
19 |
20 | def digaOi = println(saudacao)
21 | }
22 |
23 | //1.1 Inferencia de tipos
24 | val fulano = new Pessoa("Fulano")
25 | fulano.digaOi
26 |
27 | //1.2 Princípio do acesso uniforme
28 | println(fulano.saudacao)
29 |
30 | //1.3 Mutabilidade explicita
31 | var ciclano = new Pessoa("Ciclano")
32 | ciclano = fulano
33 | //fulano = ciclano
34 |
35 | ///// 2. Melhore APIs existentes e o codigo legado
36 | implicit class StringMelhor(str: String) {
37 | //1.4 String Interpolation
38 | def tagueie(tag: String) = s"<$tag>$str$tag>"
39 | def enfatize = tagueie("em")
40 | }
41 |
42 | println("Uau!!!".enfatize)
43 |
44 | //2.1 "Compativel" com bibliotecas Java
45 | import javax.xml.parsers._
46 | import org.w3c.dom._
47 | import java.io._
48 |
49 | def data = new ByteArrayInputStream(
50 | //1.5 Strings de varias linhas
51 | """
52 |
53 | um
54 | dois
55 | tres
56 |
57 | """.getBytes) //> data: => java.io.ByteArrayInputStream
58 | val doc = DocumentBuilderFactory
59 | .newInstance
60 | .newDocumentBuilder
61 | .parse(data) //> doc : org.w3c.dom.Document = [#document: null]
62 |
63 |
64 |
65 | //2.2 As "palavras chave" te entendem também
66 | val nodeList:NodeList = doc.getElementsByTagName("div")
67 | //> nodeList : org.w3c.dom.NodeList = com.sun.org.apache.xerces.internal.dom.D
68 | //| eepNodeListImpl@6442b0a6
69 | /*
70 | implicit class TraversableNodeList(nl: NodeList) extends Traversable[Node] {
71 | override def foreach[U](f: Node => U): Unit =
72 | for (i <- 0 until nl.getLength) f(nl.item(i))
73 | }
74 |
75 | for (node <- nodeList) println(node.getTextContent())
76 | //> um
77 | //| dois
78 | //| tres
79 | //| res0: = ()
80 | */
81 |
82 | //// 3. É funcional, mas e dai?
83 |
84 | //3.1 Collections e Closures
85 | /*
86 | nodeList
87 | .map { _.getTextContent }
88 | .filter { _.length > 3 }
89 | .foreach { println } //> dois
90 | //| tres
91 | //| res1: = ()
92 | */
93 | //3.2 Funções como argumentos e retornos
94 | implicit class InputExtreme(in: InputStream) {
95 | def aplica[T](f: InputStream => T): T =
96 | try f(in)
97 | finally in.close
98 | }
99 |
100 | import scala.io.Source
101 | def destagueia(in: InputStream) = Source
102 | .fromInputStream(in)
103 | .mkString
104 | .replaceAll("<", "[")
105 | .replaceAll(">", "]") //> destagueia: (in: java.io.InputStream)String
106 |
107 | data.aplica(destagueia) //> res2: = "
108 | //| [html]
109 | //| [div]um[/div]
110 | //| [div]dois[/div]
111 | //| [div]tres[/div]
112 | //| [/html]
113 | //| "
114 |
115 | //3.3 Lidando com null
116 | def triplo(i: Integer) = i * 3 //> triplo: (i: Integer)Int
117 | def triploOuNada(i: Int): Integer = if (i % 2 == 0) triplo(i) else null
118 | //> triploOuNada: (i: Int)Integer
119 |
120 | Option{ triploOuNada(2) }.map(triplo).foreach(println)
121 | //> 18
122 | Option{ triploOuNada(3) }.map(triplo).foreach(println)
123 |
124 | //3.4 Lidando com falha
125 | import scala.util.Try
126 |
127 | def triploOuFalha(i: Integer): Integer = if (i % 3 == 0) triplo(i) else throw new Exception("Ops")
128 | //> triploOuFalha: (i: Integer)Integer
129 | Try{ triploOuFalha(3) }.map(triplo).foreach(println)
130 | //> 27
131 | Try{ triploOuFalha(4) }.map(triplo).foreach(println)
132 |
133 | //3.5 Lidando com latencia
134 | import scala.concurrent._
135 | import scala.concurrent.ExecutionContext.Implicits.global
136 |
137 | def triploOuDemora(i: Integer): Integer = if (i % 4 == 0)
138 | triplo(i)
139 | else {
140 | Thread.sleep(2000)
141 | i
142 | } //> triploOuDemora: (i: Integer)Integer
143 |
144 | import java.text.SimpleDateFormat
145 | import java.util.Date
146 |
147 | val sdf = new SimpleDateFormat("HH:mm:ss") //> sdf : java.text.SimpleDateFormat = java.text.SimpleDateFormat@8140d380
148 | def now = sdf.format(new Date) //> now: => String
149 |
150 | Future{ triploOuDemora(4) }.map(triplo).foreach(i => println(s"${i} @ ${now}"))
151 | Future{ triploOuDemora(5) }.map(triplo).foreach(i => println(s"${i} @ ${now}"))
152 | //> 36 @ 18:37:03
153 | Thread.sleep(3000) //> 15 @ 18:37:05
154 |
155 | //3.666. Lidando com M* :)
156 | // Xxxxx{ triploOuXxxx(0) }.map(triplo).foreach(println)
157 |
158 | import scala.util.Random._
159 | val rands = Seq.fill(12){nextInt(100)} //> rands : Seq[Int] = List(16, 23, 79, 36, 62, 59, 38, 78, 45, 46, 8, 90)
160 | for {
161 | q <- rands
162 | c <- Option { triploOuNada(q) }
163 | o <- Try { triploOuFalha(c) }
164 | n <- Future { triploOuDemora(o) }
165 | } println(s"${n} @ ${now}" ) //> 432 @ 18:37:06
166 | //| 972 @ 18:37:06
167 |
168 | Thread.sleep(5000) //> 216 @ 18:37:06
169 | //| 342 @ 18:37:08
170 | //| 702 @ 18:37:08
171 | //| 810 @ 18:37:08
172 | //| 414 @ 18:37:08
173 | //| 558 @ 18:37:08|
174 | // Codigo em http://bit.ly/scala20m
175 | }
--------------------------------------------------------------------------------
/demos/qconrj14.sc:
--------------------------------------------------------------------------------
1 | object qconrj14 {
2 | println("Scala em 20m no QCON Rio") //> Scala em 20m no QCON Rio
3 |
4 | //1. Seja menos prolixo
5 | class Pessoa(nome: String) { //<- Isso e um contstrutor
6 | /*public*/ def saudacao /*():String throws Exception*/ =
7 | //{
8 | //var result:String
9 | if (nome.length() < 10)
10 | /*result =*/ s"oi $nome!"
11 | else throw new Exception("Nome Muito Longo")
12 | //return result
13 | //}
14 |
15 | def digaOi = println(saudacao)
16 | }
17 |
18 | //1.1 Inferencia de tipos
19 | val fulano = new Pessoa("Fulano") //> fulano : qconrj14.Pessoa = qconrj14$$anonfun$main$1$Pessoa$1@b684286
20 | fulano.digaOi //> oi Fulano!
21 |
22 | //1.2 Princípio do acesso uniforme
23 | println(fulano.saudacao) //> oi Fulano!
24 |
25 | //1.3 Mutabilidade explicita
26 | var ciclano = new Pessoa("Ciclano") //> ciclano : qconrj14.Pessoa = qconrj14$$anonfun$main$1$Pessoa$1@4411d970
27 | ciclano = fulano
28 | //fulano = ciclano
29 |
30 | //2. Melhore APIs existentes e o codigo legado
31 | implicit class StringMelhor(str: String) {
32 | //1.4 String Interpolation
33 | def tagueie(tag: String) = s"<$tag>$str$tag>"
34 | def enfatize = tagueie("em")
35 | }
36 |
37 | println("Uau!!!".enfatize) //> Uau!!!
38 |
39 | //2.1 "Compativel" com bibliotecas Java
40 | import javax.xml.parsers._
41 | import org.w3c.dom._
42 | import java.io._
43 |
44 | def data = new ByteArrayInputStream(
45 | //1.5 Strings de varias linhas
46 | """
47 |
48 | um
49 | dois
50 | tres
51 |
52 | """.getBytes) //> data: => java.io.ByteArrayInputStream
53 | val doc = DocumentBuilderFactory
54 | .newInstance
55 | .newDocumentBuilder
56 | .parse(data) //> doc : org.w3c.dom.Document = [#document: null]
57 |
58 |
59 | //2.2 As "palavras chave" te entendem também
60 | val nodeList:NodeList = doc.getElementsByTagName("div")
61 | //> nodeList : org.w3c.dom.NodeList = com.sun.org.apache.xerces.internal.dom.D
62 | //| eepNodeListImpl@6442b0a6
63 |
64 | implicit class TraversableNodeList(nl: NodeList) extends Traversable[Node] {
65 | override def foreach[U](f: Node => U): Unit =
66 | for (i <- 0 until nl.getLength) f(nl.item(i))
67 | }
68 |
69 | for (node <- nodeList) println(node.getTextContent())
70 | //> um
71 | //| dois
72 | //| tres
73 | //| res0: = ()
74 |
75 | //3. É funcional, mas e dai?
76 |
77 | //3.1 Collections e Closures
78 | nodeList
79 | .map { _.getTextContent }
80 | .filter { _.length > 3 }
81 | .foreach { println } //> dois
82 | //| tres
83 | //| res1: = ()
84 |
85 | //3.2 Funções como argumentos e retornos
86 | implicit class InputExtreme(in: InputStream) {
87 | def aplica[T](f: InputStream => T): T =
88 | try f(in)
89 | finally in.close
90 | }
91 |
92 | import scala.io.Source
93 | def destagueia(in: InputStream) = Source
94 | .fromInputStream(in)
95 | .mkString
96 | .replaceAll("<", "[")
97 | .replaceAll(">", "]") //> destagueia: (in: java.io.InputStream)String
98 |
99 | data.aplica(destagueia) //> res2: = "
100 | //| [html]
101 | //| [div]um[/div]
102 | //| [div]dois[/div]
103 | //| [div]tres[/div]
104 | //| [/html]
105 | //| "
106 |
107 | //3.3 Lidando com null
108 | def triplo(i: Integer) = i * 3 //> triplo: (i: Integer)Int
109 | def triploOuNada(i: Int): Integer = if (i % 2 == 0) triplo(i) else null
110 | //> triploOuNada: (i: Int)Integer
111 |
112 | Option{ triploOuNada(2) }.map(triplo).foreach(println)
113 | //> 18
114 | Option{ triploOuNada(3) }.map(triplo).foreach(println)
115 |
116 | //3.4 Lidando com falha
117 | import scala.util.Try
118 |
119 | def triploOuFalha(i: Integer): Integer = if (i % 3 == 0) triplo(i) else throw new Exception("Ops")
120 | //> triploOuFalha: (i: Integer)Integer
121 | Try{ triploOuFalha(3) }.map(triplo).foreach(println)
122 | //> 27
123 | Try{ triploOuFalha(4) }.map(triplo).foreach(println)
124 |
125 | //3.5 Lidando com latencia
126 | import scala.concurrent._
127 | import scala.concurrent.ExecutionContext.Implicits.global
128 |
129 | def triploOuDemora(i: Integer): Integer = if (i % 4 == 0)
130 | triplo(i)
131 | else {
132 | Thread.sleep(2000)
133 | i
134 | } //> triploOuDemora: (i: Integer)Integer
135 |
136 | import java.text.SimpleDateFormat
137 | import java.util.Date
138 |
139 | val sdf = new SimpleDateFormat("HH:mm:ss") //> sdf : java.text.SimpleDateFormat = java.text.SimpleDateFormat@8140d380
140 | def now = sdf.format(new Date) //> now: => String
141 |
142 | Future{ triploOuDemora(4) }.map(triplo).foreach(i => println(s"${i} @ ${now}"))
143 | Future{ triploOuDemora(5) }.map(triplo).foreach(i => println(s"${i} @ ${now}"))
144 | //> 36 @ 18:37:03
145 | Thread.sleep(3000) //> 15 @ 18:37:05
146 |
147 | //3.666. Lidando com M* :)
148 | // Xxxxx{ triploOuXxxx(0) }.map(triplo).foreach(println)
149 |
150 | import scala.util.Random._
151 | val rands = Seq.fill(12){nextInt(100)} //> rands : Seq[Int] = List(16, 23, 79, 36, 62, 59, 38, 78, 45, 46, 8, 90)
152 | for {
153 | q <- rands
154 | c <- Option { triploOuNada(q) }
155 | o <- Try { triploOuFalha(c) }
156 | n <- Future { triploOuDemora(o) }
157 | } println(s"${n} @ ${now}" ) //> 432 @ 18:37:06
158 | //| 972 @ 18:37:06
159 |
160 | Thread.sleep(5000) //> 216 @ 18:37:06
161 | //| 342 @ 18:37:08
162 | //| 702 @ 18:37:08
163 | //| 810 @ 18:37:08
164 | //| 414 @ 18:37:08
165 | //| 558 @ 18:37:08|
166 | // Codigo em http://bit.ly/scala20m
167 | }
--------------------------------------------------------------------------------