├── 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 | 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 | 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 | 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" 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" 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" 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 | } --------------------------------------------------------------------------------