├── src ├── main │ ├── scala │ │ ├── immutable │ │ │ ├── README.md │ │ │ ├── AccountMutable.scala │ │ │ └── AccountImmutable.scala │ │ ├── kamil │ │ │ └── Kamil.scala │ │ ├── combinators │ │ │ ├── README.md │ │ │ └── ContactInfo.scala │ │ ├── encapsulation │ │ │ ├── oop │ │ │ │ └── Unit.scala │ │ │ ├── unit │ │ │ │ ├── DistanceMiles.scala │ │ │ │ ├── TimeUnit.scala │ │ │ │ ├── SpeedUnit.scala │ │ │ │ ├── Formulas.scala │ │ │ │ └── DistanceUnit.scala │ │ │ ├── README.md │ │ │ └── EncapsulationApp.scala │ │ ├── nomock │ │ │ ├── user │ │ │ │ ├── Failure.scala │ │ │ │ ├── Check.scala │ │ │ │ └── API.scala │ │ │ └── app │ │ │ │ └── UserCreation.scala │ │ ├── cbt │ │ │ ├── BuildS.scala │ │ │ └── Build.scala │ │ ├── fizzbuzz │ │ │ └── FizzBuzz.scala │ │ ├── com │ │ │ └── example │ │ │ │ ├── Icon.scala │ │ │ │ ├── Fibonacci.scala │ │ │ │ ├── Stack.scala │ │ │ │ ├── SymbolicExpressions.scala │ │ │ │ ├── CakeDI.scala │ │ │ │ ├── Composition.scala │ │ │ │ ├── Symbolic.scala │ │ │ │ ├── OoDI.scala │ │ │ │ └── FuncDI.scala │ │ ├── url_shortener │ │ │ └── UrlShortener.scala │ │ ├── ddd │ │ │ ├── ErrorAPI.scala │ │ │ ├── ErrorMessages.scala │ │ │ ├── PaymentAPI.scala │ │ │ ├── ShoppingCartConfig.scala │ │ │ ├── Directives.scala │ │ │ ├── ShoppingCartAPI.scala │ │ │ ├── Validation.scala │ │ │ ├── SampleData.scala │ │ │ ├── Commons.scala │ │ │ ├── ShoppingCartApp.scala │ │ │ └── ShoppingCart.scala │ │ ├── plainFP │ │ │ ├── Roman.scala │ │ │ ├── Table.scala │ │ │ ├── Domain.scala │ │ │ ├── WiredLogger.scala │ │ │ ├── MonadLogger.scala │ │ │ ├── Logger.scala │ │ │ ├── Config.scala │ │ │ ├── SimpleImp.scala │ │ │ ├── SimpleCommon.scala │ │ │ ├── SimpleFP.scala │ │ │ └── RequestResponse.scala │ │ ├── control │ │ │ ├── ForOO.scala │ │ │ └── For.scala │ │ ├── zio │ │ │ ├── MyApp.scala │ │ │ └── Fibonacci.scala │ │ ├── tdd │ │ │ └── RequestResponse.scala │ │ ├── shape │ │ │ ├── CalculatorPF.scala │ │ │ ├── Shape.scala │ │ │ └── ShapeSimple.scala │ │ ├── bird │ │ │ └── Bird.scala │ │ ├── colossus │ │ │ └── Akka.scala │ │ ├── tank │ │ │ └── Tank.scala │ │ ├── queens │ │ │ └── Queens.scala │ │ ├── family │ │ │ └── Family.scala │ │ ├── licit │ │ │ └── Licit.scala │ │ ├── supervisor │ │ │ └── Main.scala │ │ ├── lnko │ │ │ └── Lnko.scala │ │ ├── rest │ │ │ └── RestApi.scala │ │ ├── tight │ │ │ └── TightCoupling.scala │ │ ├── ebi │ │ │ └── Store.scala │ │ ├── independence │ │ │ ├── ResultOps.scala │ │ │ ├── Logger.scala │ │ │ └── Result.scala │ │ ├── log │ │ │ └── Analyzer.scala │ │ ├── knapsack │ │ │ └── Knapsack.scala │ │ └── loopperf │ │ │ └── NBodyArray.scala │ ├── resources │ │ ├── index.html │ │ ├── comments.json │ │ ├── comment.hbs │ │ └── fak │ │ │ ├── index.html │ │ │ ├── css │ │ │ └── main.css │ │ │ └── js │ │ │ └── main.js │ └── java │ │ ├── fpjdbc │ │ ├── ThrowingConsumer.java │ │ ├── ThrowingFunction.java │ │ ├── FpJdbc.java │ │ └── Record.java │ │ ├── IntOperation.java │ │ ├── handlebars │ │ └── Handlebars.java │ │ ├── exception │ │ ├── Either.java │ │ ├── Tuple2.java │ │ ├── Calc.java │ │ ├── CalcEither.java │ │ ├── Right.java │ │ ├── Left.java │ │ └── Failure.java │ │ ├── log │ │ ├── Server.java │ │ ├── App.java │ │ └── Logger.java │ │ ├── SecurityListing.java │ │ ├── Color.java │ │ ├── independence │ │ ├── TightCoupling.java │ │ ├── TightAndIndependentCoupling.java │ │ └── LooseCoupling.java │ │ ├── total │ │ ├── NotZeroInt.java │ │ ├── Pair.java │ │ └── Total.java │ │ ├── DecimalFormat.java │ │ ├── fp │ │ └── Either.java │ │ ├── cart │ │ ├── ShoppingCart.java │ │ └── ShoppingCartImpl.java │ │ ├── BufReadMulti.java │ │ ├── PP.java │ │ ├── builder │ │ └── Contact.java │ │ ├── OccurenceOfLetters.java │ │ └── threads │ │ └── README.md └── test │ └── scala │ ├── family │ └── FamilySpec.scala │ ├── plainFP │ ├── LoggerBench.scala │ └── RequestResponseSpec.scala │ ├── queens │ └── QueensSpec.scala │ ├── tdd │ └── WebServerSpec.scala │ ├── shape │ ├── ShapeSpec.scala │ ├── ShapePFSpec.scala │ ├── ShapeSimpleSpec.scala │ └── ShapeOOSpec.scala │ ├── nomock │ ├── user │ │ └── Infra.scala │ └── app │ │ └── UserCreationSpec.scala │ ├── loopperf │ └── NBodyArrayPerf.scala │ └── independence │ └── IndependenceDaySpec.scala ├── activator-launch-1.3.2.jar ├── project ├── plugins.sbt └── build.properties ├── README.md └── .gitignore /src/main/scala/immutable/README.md: -------------------------------------------------------------------------------- 1 | # Immutable vs mutable 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/main/resources/index.html: -------------------------------------------------------------------------------- 1 | 2 |

Hello

3 | 4 | -------------------------------------------------------------------------------- /activator-launch-1.3.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enpassant/miniatures/HEAD/activator-launch-1.3.2.jar -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("org.scoverage" %% "sbt-scoverage" % "1.5.1") 2 | addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.4.5") 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # miniatures 2 | 3 | Miniature scala sources 4 | 5 | ## Symbolic.scala 6 | 7 | Sample symbolic programming with traits, case classes and objects. 8 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | #Activator-generated Properties 2 | #Tue Jun 30 17:13:53 CEST 2015 3 | template.uuid=7faf8e1e-4e8d-4387-8159-642b50383096 4 | sbt.version=1.4.2 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /RUNNING_PID 2 | /logs/ 3 | /project/*-shim.sbt 4 | /project/project/ 5 | /project/target/ 6 | /target/ 7 | /out/ 8 | .metals/ 9 | .bloop/ 10 | .bsp/ 11 | .scalafmt.conf 12 | -------------------------------------------------------------------------------- /src/main/java/fpjdbc/ThrowingConsumer.java: -------------------------------------------------------------------------------- 1 | package fpjdbc; 2 | 3 | @FunctionalInterface 4 | public interface ThrowingConsumer { 5 | void accept(T t) throws E; 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/fpjdbc/ThrowingFunction.java: -------------------------------------------------------------------------------- 1 | package fpjdbc; 2 | 3 | @FunctionalInterface 4 | public interface ThrowingFunction { 5 | R apply(T t) throws E; 6 | } 7 | -------------------------------------------------------------------------------- /src/main/scala/kamil/Kamil.scala: -------------------------------------------------------------------------------- 1 | object Kamil extends App { 2 | val stream = Stream.continually(scala.io.StdIn.readLine).foldLeft(1)( 3 | (x,c)=>if("FLDT".contains(c)) x*2 else x) 4 | println(stream) 5 | } 6 | -------------------------------------------------------------------------------- /src/main/scala/combinators/README.md: -------------------------------------------------------------------------------- 1 | [Use lambdas and combinators to improve your API](http://blog.leifbattermann.de/2017/09/05/use-lambdas-and-combinators-to-improve-your-api/) 2 | 3 | (or use partial functions instead of combinators) 4 | -------------------------------------------------------------------------------- /src/main/scala/encapsulation/oop/Unit.scala: -------------------------------------------------------------------------------- 1 | package encapsulation.oop 2 | 3 | class Unit private[oop]( 4 | private[oop] val value: Double, 5 | private[oop] val unit: String 6 | ) { 7 | override def toString(): String = s"$value $unit" 8 | } 9 | -------------------------------------------------------------------------------- /src/main/scala/encapsulation/unit/DistanceMiles.scala: -------------------------------------------------------------------------------- 1 | package encapsulation.unit 2 | 3 | import DistanceUnit._ 4 | 5 | object DistanceMiles { 6 | def createMile(mile: Double): Distance = new Distance(mile * 1609.344) 7 | 8 | def asMile(distance: Distance): Double = distance.meter * 0.00062137119224 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/nomock/user/Failure.scala: -------------------------------------------------------------------------------- 1 | package nomock.user 2 | 3 | import scala.util.{Either, Left, Right} 4 | 5 | object Failure { 6 | trait Error { 7 | def message: String 8 | } 9 | 10 | case class BusinessError(message: String) extends Error 11 | case class InfrastructureError(message: String) extends Error 12 | } 13 | -------------------------------------------------------------------------------- /src/main/scala/cbt/BuildS.scala: -------------------------------------------------------------------------------- 1 | import shapeless._ ; import syntax.singleton._ ; import record._ 2 | 3 | object BuildS { 4 | val build = 5 | ("x" ->> 5) :: 6 | ("y" ->> 6) :: 7 | ("z" ->> (() => 5)) :: 8 | ("zz" ->> (() => 5)) :: 9 | HNil 10 | 11 | val build2 = build + ("z" ->> (() => build("x") + build("y"))) 12 | } 13 | -------------------------------------------------------------------------------- /src/main/scala/encapsulation/unit/TimeUnit.scala: -------------------------------------------------------------------------------- 1 | package encapsulation.unit 2 | 3 | class Time private[unit](private[unit] val second: Double) 4 | 5 | object TimeUnit { 6 | def createTime(second: Double): Time = new Time(second) 7 | 8 | def asHour(time: Time): Double = time.second / 60 9 | def asSecond(time: Time): Double = time.second 10 | } 11 | -------------------------------------------------------------------------------- /src/main/scala/fizzbuzz/FizzBuzz.scala: -------------------------------------------------------------------------------- 1 | package fizzbuzz 2 | 3 | object Fizzbuzz extends App { 4 | val factors = Map(3 -> "Fizz", 5 -> "Buzz", 2 -> "Baxx") 5 | val result = (1 to 30) map { i => 6 | factors 7 | .filter(x => i % x._1 == 0) 8 | .map(_._2) 9 | .reduceOption(_ + _) 10 | .getOrElse(i) 11 | } 12 | println(result) 13 | } 14 | -------------------------------------------------------------------------------- /src/main/scala/encapsulation/unit/SpeedUnit.scala: -------------------------------------------------------------------------------- 1 | package encapsulation.unit 2 | 3 | class Speed private[unit](private[unit] val mps: Double) 4 | 5 | object SpeedUnit { 6 | def createSpeed(mps: Double): Speed = new Speed(mps) 7 | 8 | def createKph(kph: Double): Speed = new Speed(kph / 3.6) 9 | 10 | def asMps(speed: Speed): Double = speed.mps 11 | def asKph(speed: Speed): Double = speed.mps * 3.6 12 | } 13 | -------------------------------------------------------------------------------- /src/main/scala/encapsulation/unit/Formulas.scala: -------------------------------------------------------------------------------- 1 | package encapsulation.unit 2 | 3 | object Formulas { 4 | def calcSpeed(distance: Distance, time: Time): Speed = 5 | new Speed(distance.meter / time.second) 6 | def calcTime(distance: Distance, speed: Speed): Time = 7 | new Time(distance.meter / speed.mps) 8 | def calcDistance(speed: Speed, time: Time): Distance = 9 | new Distance(speed.mps * time.second) 10 | } 11 | -------------------------------------------------------------------------------- /src/main/scala/com/example/Icon.scala: -------------------------------------------------------------------------------- 1 | package com.example 2 | 3 | import scala.language.implicitConversions 4 | 5 | case class IntValue(x: Int) { 6 | def less(b: Int): Option[Int] = 7 | if (x < b) Some(b) else None 8 | } 9 | 10 | object Icon extends App { 11 | implicit def int2Integer(x: Int) = IntValue(x) 12 | val x = 8 13 | println( 14 | for { 15 | expr <- 2 less x 16 | } yield (expr * 2) 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /src/main/scala/encapsulation/unit/DistanceUnit.scala: -------------------------------------------------------------------------------- 1 | package encapsulation.unit 2 | 3 | class Distance private[unit](private[unit] val meter: Double) 4 | 5 | object DistanceUnit { 6 | def createDistance(meter: Double): Distance = new Distance(meter) 7 | 8 | def createKm(km: Double): Distance = new Distance(km * 1000) 9 | 10 | def asMeter(distance: Distance): Double = distance.meter 11 | def asKm(distance: Distance): Double = distance.meter / 1000 12 | } 13 | -------------------------------------------------------------------------------- /src/main/scala/encapsulation/README.md: -------------------------------------------------------------------------------- 1 | # Egységbezárás 2 | 3 | Az egységbe zárás azt fejezi ki, hogy az összetartozó adatok és függvények, eljárások együtt vannak, egy egységbe tartoznak. További fontos fogalom az adatelrejtés, ami azt jelenti, hogy kívülről csak az férhető hozzá közvetlenül, amit az objektum osztálya megenged. Ez fontos ahhoz, hogy megelőzze a nem kívánt kapcsolatok kialakulását, megkönnyítse a kód értelmezését, és elkerülje az adatok ellenőrizetlen terjedését (lásd objektumtobzódás). 4 | -------------------------------------------------------------------------------- /src/main/resources/comments.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": 5, 3 | "comments": [ 4 | { 5 | "commentId": 7, 6 | "userName": "John", 7 | "content": "

Test comment 1

", 8 | "comments": [ 9 | { 10 | "commentId": "8", 11 | "userName": "Susan", 12 | "content": "

Reply

" 13 | }] 14 | }, 15 | { 16 | "commentId": "9", 17 | "userName": "George", 18 | "content": "

Test comment 2

" 19 | } 20 | ]}"; 21 | 22 | -------------------------------------------------------------------------------- /src/main/scala/nomock/user/Check.scala: -------------------------------------------------------------------------------- 1 | package nomock.user 2 | 3 | import scala.util.{Either, Left, Right} 4 | 5 | object Check { 6 | import API._ 7 | import Failure._ 8 | 9 | val invalidLoginInfo = BusinessError("username or password is empty") 10 | 11 | def checkUserLogin(userName: String, password: String): Either[Error, Login] = { 12 | if (userName == "" || password == "") { 13 | Left(invalidLoginInfo) 14 | } else { 15 | Right(new Login(userName, password)) 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/scala/url_shortener/UrlShortener.scala: -------------------------------------------------------------------------------- 1 | package url_shortener 2 | 3 | import java.util.Base64 4 | import scala.math.BigInt 5 | import scala.util.Random 6 | 7 | object UrlShortener extends App { 8 | (1000000001 to 1000000010) map { 9 | i => i ^ 0x3a75dc68 10 | } map { 11 | i => new Random(147).shuffle(i.toBinaryString.toList) 12 | } map { 13 | s => Integer.parseInt(s.mkString, 2) 14 | } map { 15 | i => Base64.getEncoder.encodeToString(BigInt(i).toByteArray) 16 | } foreach println 17 | } 18 | 19 | -------------------------------------------------------------------------------- /src/main/scala/ddd/ErrorAPI.scala: -------------------------------------------------------------------------------- 1 | package ddd 2 | 3 | import Types._ 4 | import PaymentAPI._ 5 | import ShoppingCartAPI._ 6 | 7 | object ErrorAPI { 8 | case class ItemAlreadyAdded(item: Item) extends Error 9 | case class NoItemInCart(item: Item) extends Error 10 | case class CardProcessFailure(card: Card) extends Error 11 | 12 | case class UnknownCommand(state: State, command: Command) extends Error 13 | case class UnknownEvent(state: State, event: Event) extends Error 14 | case class UnknownCapability(state: State, command: Command) extends Error 15 | } 16 | -------------------------------------------------------------------------------- /src/main/scala/plainFP/Roman.scala: -------------------------------------------------------------------------------- 1 | package plainFP 2 | 3 | object Roman extends App { 4 | val romanNumber = "MCMLXIX" 5 | val digit = List('I', 'V', 'X', 'L', 'C', 'D', 'M') 6 | val digitValue = List(1, 5, 10, 50, 100, 500, 1000) 7 | val indexes = romanNumber.map(ch => digit.indexOf(ch)) 8 | 9 | val pairs = indexes.zip(indexes.drop(1) :+ 0) 10 | val values = pairs.map(pair => 11 | if (pair._1 >= pair._2) 12 | digitValue(pair._1) 13 | else 14 | -digitValue(pair._1)) 15 | val arab = values.sum 16 | println("Arab: " + arab) 17 | } 18 | -------------------------------------------------------------------------------- /src/test/scala/family/FamilySpec.scala: -------------------------------------------------------------------------------- 1 | package family 2 | 3 | import org.scalatest._ 4 | 5 | class FamilySpec extends FunSpec with Matchers { 6 | import Family._ 7 | 8 | describe("Family. Husband") { 9 | it("should greet anyone formally") { 10 | val moduls = List.empty[Modul] 11 | val greet = composeGreet(moduls) 12 | greet(Husband, Albert) shouldBe "How do you do!" 13 | } 14 | it("should greet his friends") { 15 | val moduls = List(HusbandModul) 16 | val greet = composeGreet(moduls) 17 | greet(Husband, Albert) shouldBe "Hey budd!" 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/scala/plainFP/LoggerBench.scala: -------------------------------------------------------------------------------- 1 | package plainFP 2 | 3 | import org.scalameter.api._ 4 | import plainFP._ 5 | 6 | object LoggerBench extends Bench.ForkedTime { 7 | val ranges = for { 8 | size <- Gen.range("size")(20000, 100000, 20000) 9 | } yield 0 until size 10 | 11 | performance of "MonadLogger" in { 12 | measure method "main" in { 13 | using(ranges) in { 14 | _.map(i => MonadLogger.main(Array("-t"))) 15 | } 16 | } 17 | } 18 | 19 | performance of "Logger" in { 20 | measure method "main" in { 21 | using(ranges) in { 22 | _.map(i => Logger.main(Array("-t"))) 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/IntOperation.java: -------------------------------------------------------------------------------- 1 | public class IntOperation { 2 | private static int add(int a, int b) { 3 | return a + b; 4 | } 5 | 6 | private static int mul(int a, int b) { 7 | return a * b; 8 | } 9 | 10 | @FunctionalInterface 11 | interface Operation { 12 | int apply(int a, int b); 13 | } 14 | 15 | public static int run(Operation operation, int a, int b) { 16 | return operation.apply(a, b); 17 | } 18 | 19 | public static void main(String[] args) { 20 | //int result = run(DecimalFormat::add, 10, 14); 21 | int result = run((a, b) -> a * b, 10, 14); 22 | System.out.println("Result: " + result); 23 | } 24 | } 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/main/scala/control/ForOO.scala: -------------------------------------------------------------------------------- 1 | package control 2 | 3 | trait For[S] { 4 | def init: S 5 | def predicate(s: S): Boolean 6 | def step(s: S): S 7 | def core(s: S) 8 | 9 | def run() = { 10 | def loop(state: S): Unit = { 11 | if (predicate(state)) { 12 | core(state) 13 | val nextState = step(state) 14 | loop(nextState) 15 | } 16 | } 17 | loop(init) 18 | } 19 | } 20 | 21 | object ForOOApp extends App { 22 | val data = List(1, 3, 5, 7, 8, 4, 9) 23 | (new For[Int] { 24 | def init = 0 25 | def predicate(state: Int) = state < data.length 26 | def step(state: Int) = state + 1 27 | def core(state: Int) = { 28 | println(data(state)) 29 | } 30 | }).run() 31 | } 32 | -------------------------------------------------------------------------------- /src/main/scala/com/example/Fibonacci.scala: -------------------------------------------------------------------------------- 1 | package com.example 2 | 3 | object Fibonacci extends App { 4 | def fibonacci(n: Int) = { 5 | def fib(current: Int, next: Int, index: Int): Int = { 6 | if (index <= 1) next 7 | else fib(next, current + next, index - 1) 8 | } 9 | fib(0, 1, n) 10 | } 11 | 12 | def tribonacci(n: Int) = { 13 | def trib(v1: Int, v2: Int, v3: Int, index: Int): Int = { 14 | if (index <= 1) v3 15 | else trib(v2, v3, v1 + v2 + v3, index - 1) 16 | } 17 | trib(0, 1, 1, n) 18 | } 19 | 20 | println( 21 | (1 to 10) map { n => 22 | s"fibonacci($n)=${fibonacci(n)}" 23 | } 24 | ) 25 | 26 | println( 27 | (1 to 10) map { n => 28 | s"tribonacci($n)=${tribonacci(n)}" 29 | } 30 | ) 31 | } 32 | -------------------------------------------------------------------------------- /src/main/scala/control/For.scala: -------------------------------------------------------------------------------- 1 | package control 2 | 3 | object ForFP { 4 | def forFn[S]( 5 | init: S, 6 | predicate: S => Boolean, 7 | step: S => S, 8 | core: S => Unit 9 | ) = { 10 | def loop(state: S): Unit = { 11 | if (predicate(state)) { 12 | core(state) 13 | val nextState = step(state) 14 | loop(nextState) 15 | } 16 | } 17 | loop(init) 18 | } 19 | } 20 | 21 | object ForApp extends App { 22 | val data = List(1, 3, 5, 7, 8, 4, 9) 23 | ForFP.forFn[Int](0, _ < data.length, _ + 1, i => { 24 | println(data(i)) 25 | }) 26 | 27 | def forRange(s: Int, n: Int) = 28 | ForFP.forFn[Int](s, _ < n, _ + 1, _) 29 | 30 | forRange(0, data.length) { i => 31 | println(data(i)) 32 | } 33 | 34 | data.foreach(println) 35 | } 36 | -------------------------------------------------------------------------------- /src/main/scala/zio/MyApp.scala: -------------------------------------------------------------------------------- 1 | package zio 2 | 3 | import zio.{App, ExitCode, IO, random} 4 | import zio.blocking.effectBlocking 5 | import zio.console._ 6 | 7 | import java.io.IOException 8 | 9 | object MyApp extends App { 10 | 11 | def run(args: List[String]) = 12 | myAppLogic.fold(_ => ExitCode(1), _ => ExitCode(0)) 13 | 14 | val finalizer = IO.effectTotal(println("Sleep interrupted")) 15 | 16 | def myAppLogic = 17 | for { 18 | r <- random.nextInt 19 | fiber <- effectBlocking({ Thread.sleep(5000); r}) 20 | .ensuring(finalizer) 21 | .fork 22 | _ <- putStrLn("Hello! What is your name?") 23 | n <- getStrLn 24 | _ <- putStrLn("Hello " + n + ", good to meet you!") 25 | v <- fiber.interrupt 26 | _ <- putStrLn("Value: " + v) 27 | } yield () 28 | } 29 | -------------------------------------------------------------------------------- /src/main/scala/ddd/ErrorMessages.scala: -------------------------------------------------------------------------------- 1 | package ddd 2 | 3 | import Types._ 4 | import PaymentAPI._ 5 | import ErrorAPI._ 6 | 7 | object ErrorMessages { 8 | def toMessage(error: Failure) = error match { 9 | case ItemAlreadyAdded(item) => 10 | s"${item} is already added!" 11 | case NoItemInCart(item) => 12 | s"There is no ${item} in the cart!" 13 | case CardProcessFailure(card) => 14 | s"There was a problem processing your $card card!" 15 | 16 | case UnknownCommand(state, command) => 17 | s"Unknown $command command for $state state!" 18 | case UnknownEvent(state, event) => 19 | s"Unknown $event event for $state state!" 20 | case UnknownCapability(state, command) => 21 | s"Unknown capability /$command command for $state state/!" 22 | 23 | case _ => error.toString 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/scala/plainFP/Table.scala: -------------------------------------------------------------------------------- 1 | package plainFP 2 | 3 | object TableAPI { 4 | case class Table(rows: Vector[Row]) 5 | case class Row(cells: Vector[Cell]) 6 | case class Cell(value: String) 7 | 8 | val table = (init: Table => Table) => { 9 | val t = Table(Vector()) 10 | init(t) 11 | } 12 | 13 | val row = (init: Row => Row) => (t: Table) => { 14 | val r = Row(Vector()) 15 | Table(t.rows :+ init(r)) 16 | } 17 | 18 | val cell = (str: String) => (r: Row) => { 19 | Row(r.cells :+ Cell(str)) 20 | } 21 | } 22 | 23 | object TableApp extends App { 24 | import TableAPI._ 25 | 26 | val t = table { 27 | row { 28 | cell("top left") andThen 29 | cell("top right") 30 | } andThen 31 | row { 32 | cell("bottom left") andThen 33 | cell("bottom right") 34 | } 35 | } 36 | 37 | println(t) 38 | } 39 | -------------------------------------------------------------------------------- /src/main/scala/tdd/RequestResponse.scala: -------------------------------------------------------------------------------- 1 | package tdd 2 | 3 | import scala.util.Random 4 | 5 | object Method extends Enumeration { 6 | type Method = Value 7 | val GET, HEAD, POST, PUT, DELETE, PATCH = Value 8 | } 9 | import Method._ 10 | 11 | case class Response( 12 | code: Int, 13 | contentType: String, 14 | content: String 15 | ) 16 | 17 | case class Order(id: String, rows: List[OrderRow]) 18 | 19 | case class OrderRow(id: String, price: Double) 20 | 21 | object Database { 22 | def getOrder(id: String): Option[Order] = { 23 | //Thread.sleep(2000) 24 | if (id == "15") { 25 | Some(Order(id, List(OrderRow("1", 10000.0), OrderRow("2", 17456.0)))) 26 | } else if (Random.nextBoolean) { 27 | Some(Order(id, List( 28 | OrderRow("1", Random.nextDouble), 29 | OrderRow("2", Random.nextDouble)))) 30 | } else None 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/scala/shape/CalculatorPF.scala: -------------------------------------------------------------------------------- 1 | package shape 2 | 3 | object CalculatorPF extends App { 4 | def literal(v: Double): Double = v 5 | def add(a: Double, b: Double): Double = a + b 6 | 7 | def literalPP(v: Double) = { println(s"$v"); v } 8 | def addPP(a: Double, b: Double) = { println(s"$a + $b"); a + b } 9 | 10 | case class Calculator[T]( 11 | literal: T => T, 12 | add: (T, T) => T 13 | ) 14 | 15 | val doubleCalculator = Calculator(literal, add) 16 | val ppCalculator = Calculator(literalPP, addPP) 17 | 18 | def calc[T](expression: Calculator[T] => T)(calculator: Calculator[T]) = { 19 | expression(calculator) 20 | } 21 | 22 | val expression = calc[Double] { c => 23 | val la = c.literal(10.2) 24 | val lb = c.literal(1.5) 25 | c.add(la, lb) 26 | } _ 27 | 28 | println(expression(doubleCalculator)) 29 | expression(ppCalculator) 30 | } 31 | -------------------------------------------------------------------------------- /src/main/scala/bird/Bird.scala: -------------------------------------------------------------------------------- 1 | object Duck { 2 | def Quack() = {} 3 | def Walk() = {} 4 | def Fly() = {} 5 | } 6 | 7 | object OtherDuck { 8 | def Quack() = {} 9 | def Walk() = {} 10 | } 11 | 12 | object ThirdDuck { 13 | def Quack() = {} 14 | def Walk() = {} 15 | def Sit() = {} 16 | def Stand() = {} 17 | } 18 | 19 | object Bird { 20 | type Fn = () => Unit 21 | 22 | def M(quack: Fn, walk: Fn, fly: Option[Fn], sit: Option[Fn], stand: Option[Fn]) { 23 | quack() 24 | walk() 25 | fly.foreach(_()) 26 | walk() 27 | quack() 28 | sit.foreach(_()) 29 | quack() 30 | quack() 31 | stand.foreach(_()) 32 | quack() 33 | } 34 | 35 | M(Duck.Quack, Duck.Walk, Some(Duck.Fly), None, None) 36 | M(OtherDuck.Quack, OtherDuck.Walk, None, None, None) 37 | M(ThirdDuck.Quack, ThirdDuck.Walk, None, Some(ThirdDuck.Sit), Some(ThirdDuck.Stand)) 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/test/scala/queens/QueensSpec.scala: -------------------------------------------------------------------------------- 1 | package queens 2 | 3 | import org.scalatest._ 4 | import org.scalatest.Matchers._ 5 | 6 | class QueensSpec extends FunSpec with Matchers { 7 | import Queens._ 8 | 9 | describe("4 Queens") { 10 | it("all solution") { 11 | allSolution(4, 4) should contain theSameElementsAs 12 | Seq(Seq(2, 0, 3, 1), Seq(1, 3, 0, 2)) 13 | } 14 | 15 | it("nothing to do") { 16 | lazy val solutions = allSolutionLog(4, 4) 17 | } 18 | 19 | it("all solution log") { 20 | lazy val solutions = allSolutionLog(4, 4) 21 | println("Searching first solution") 22 | solutions.take(1).toList 23 | println("Searching two solutions") 24 | solutions.take(2) should contain theSameElementsAs 25 | Seq(Seq(2, 0, 3, 1), Seq(1, 3, 0, 2)) 26 | println("Searching three solutions") 27 | solutions.take(3).toList 28 | } 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /src/main/scala/ddd/PaymentAPI.scala: -------------------------------------------------------------------------------- 1 | package ddd 2 | 3 | import Types._ 4 | 5 | object PaymentAPI { 6 | sealed trait CardType 7 | case object MasterCard extends CardType 8 | case object Visa extends CardType 9 | 10 | type CardNumber = String 11 | 12 | sealed trait Currency { 13 | def rate: BigDecimal 14 | def sign: String 15 | } 16 | case class USD(rate: BigDecimal, sign: String = "$") extends Currency 17 | case class GBP(rate: BigDecimal, sign: String = "£") extends Currency 18 | case class EUR(rate: BigDecimal, sign: String = "€") extends Currency 19 | case class HUF(rate: BigDecimal, sign: String = "Ft") extends Currency 20 | case class Money(amount: BigDecimal, currency: Currency) 21 | 22 | sealed trait Payment 23 | case object Cash extends Payment 24 | case class Cheque(money: Money) extends Payment 25 | case class Card(cardType: CardType, cardNumber: CardNumber) extends Payment 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/handlebars/Handlebars.java: -------------------------------------------------------------------------------- 1 | package handlebars; 2 | 3 | import com.github.enpassant.ickenham.*; 4 | import com.github.enpassant.ickenham.adapter.JavaAdapter; 5 | 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import org.json.simple.parser.JSONParser; 12 | 13 | class Handlebars { 14 | public static void main(String[] args) { 15 | Ickenham ickenham = new Ickenham(new JavaAdapter()); 16 | 17 | scala.Function1 template = ickenham.compile("comment"); 18 | 19 | try { 20 | String jsonString = ickenham.loadFile("comments.json"); 21 | JSONParser parser = new JSONParser(); 22 | Object json = parser.parse(jsonString); 23 | 24 | System.out.println("Html: " + template.apply(json)); 25 | } catch (Exception e) { 26 | System.out.println("Error: " + e.getMessage()); 27 | } 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /src/main/java/exception/Either.java: -------------------------------------------------------------------------------- 1 | package exception; 2 | 3 | import java.util.Optional; 4 | import java.util.function.Consumer; 5 | import java.util.function.Function; 6 | 7 | public interface Either { 8 | Either map(Function f); 9 | Either mapLeft(Function f); 10 | Either flatMap(Function> f); 11 | Either flatMapLeft(Function> f); 12 | Either flatten(); 13 | Either forEach(Consumer f); 14 | Either forEachLeft(Consumer f); 15 | R orElse(R value); 16 | Optional left(); 17 | Optional right(); 18 | R get(); 19 | 20 | public static Either ofOptional(L left, Optional optional) { 21 | if (optional.isPresent()) { 22 | return Right.of(optional.get()); 23 | } else { 24 | return Left.of(left); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/scala/nomock/app/UserCreation.scala: -------------------------------------------------------------------------------- 1 | package nomock.app 2 | 3 | import scala.util.{Either, Left, Right} 4 | 5 | object UserCreation { 6 | import nomock.user.API._ 7 | import nomock.user.Check._ 8 | import nomock.user.Failure._ 9 | 10 | def registerUser(s: UserService)(newUser: NewUser): Either[Error, SavedUser] = { 11 | return for { 12 | // Business validation 13 | login <- checkUserLogin(newUser.username, newUser.password) 14 | // Validate there is no such username 15 | checkedUserName <- s.users.checkUsername(login.username) 16 | checkedLogin = CheckedLogin.of(checkedUserName, login) 17 | // Call an external (government?) service to verify the ID number 18 | verifiedID <- s.iDService.verifyID(newUser.iDNumber) 19 | verifiedUser = VerifiedUser(checkedLogin, verifiedID) 20 | // Save the user in the persistent store 21 | savedUser <- s.users.saveUser(verifiedUser) 22 | } yield savedUser 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/log/Server.java: -------------------------------------------------------------------------------- 1 | package log; 2 | 3 | import java.util.Optional; 4 | 5 | class Server { 6 | private static final Logger logger = Logger.getLogger(Server.class); 7 | 8 | public static String process(final String request) { 9 | //if (logger.isDebugEnabled()) { 10 | //logger.debug("request: " + request); 11 | //} 12 | 13 | final int number = Integer.parseInt(request); 14 | final int square = number * number; 15 | final String output = "Response: " + square; 16 | //if (logger.isDebugEnabled()) { 17 | //logger.debug("response: " + output); 18 | //} 19 | 20 | return output; 21 | } 22 | 23 | public static Optional parse(final String request) { 24 | try { 25 | final int number = Integer.parseInt(request); 26 | return Optional.of(number); 27 | } catch(Exception e) { 28 | return Optional.empty(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/resources/comment.hbs: -------------------------------------------------------------------------------- 1 | 2 |

Hello

3 | {{#each comments}} 4 |
5 |
6 |
7 |
8 | {{userName}} 9 |
10 |
11 | permalink 12 | {{#if ../commentId}} 13 | szülő 14 | {{/if}} 15 | Válasz 16 |
17 |
18 |
19 | {{{content}}} 20 |
21 |
22 | {{#if comments}} 23 | {{> comment}} 24 | {{/if}} 25 |
26 | {{/each}} 27 | 28 | -------------------------------------------------------------------------------- /src/main/scala/zio/Fibonacci.scala: -------------------------------------------------------------------------------- 1 | package zio 2 | 3 | import zio.{App, ExitCode, IO} 4 | import zio.console._ 5 | 6 | import java.io.IOException 7 | 8 | object Fibonacci extends App { 9 | 10 | sealed trait AppError 11 | 12 | case object NoneException extends AppError 13 | case class AppException(exception: Exception) extends AppError 14 | 15 | def run(args: List[String]) = 16 | myAppLogic.fold(_ => ExitCode(1), _ => ExitCode(0)) 17 | 18 | def myAppLogic = 19 | for { 20 | _ <- putStrLn("Hello! Which fibonacci value should calculate?") 21 | n <- getStrLn 22 | index <- IO.effect(n.toInt) 23 | value <- fib(index) 24 | _ <- putStrLn(s"$index. fibonacci value is $value") 25 | } yield () 26 | 27 | def fib(n: Int): IO[Void, Int] = 28 | if (n <= 1) IO.succeed(1) 29 | else for { 30 | fiber1 <- fib(n - 2).fork 31 | fiber2 <- fib(n - 1).fork 32 | v2 <- fiber2.join 33 | v1 <- fiber1.join 34 | } yield v1 + v2 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/SecurityListing.java: -------------------------------------------------------------------------------- 1 | import java.security.Provider; 2 | import java.security.Security; 3 | 4 | public class SecurityListing { 5 | public static class Test {}; 6 | public static class Test2 extends Test {}; 7 | 8 | public static void main(String[] args) { 9 | for (Provider provider : Security.getProviders()) { 10 | System.out.println("Provider: " + provider.getName()); 11 | for (Provider.Service service : provider.getServices()) { 12 | System.out.println(" Algorithm: " + service.getAlgorithm()); 13 | } 14 | } 15 | 16 | Test test = getValue("test", Test.class); 17 | } 18 | 19 | public static Object getObject() { 20 | return new Test2(); 21 | } 22 | 23 | public static T getValue(String name, Class valueType) { 24 | try { 25 | return valueType.newInstance(); 26 | } catch(Exception e) { 27 | throw new RuntimeException(""); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/scala/plainFP/Domain.scala: -------------------------------------------------------------------------------- 1 | import java.time.Instant 2 | import java.net.URI 3 | 4 | case class Id[Entity](value: String) extends AnyVal 5 | 6 | case class User( 7 | id: Id[User], 8 | updatedOn: Instant, 9 | image: URI, 10 | nickname: String, 11 | verified: Boolean, 12 | deleted: Boolean 13 | ) 14 | case class Post( 15 | id: Id[Post], 16 | updatedOn: Instant, 17 | author: Id[User], 18 | text: String, 19 | image: URI, 20 | deleted: Boolean 21 | ) 22 | case class Like( 23 | userId: Id[User], 24 | postId: Id[Post], 25 | updatedOn: Instant, 26 | unliked: Boolean 27 | ) 28 | case class Comment( 29 | id: Id[Comment], 30 | postId: Id[Post], 31 | updatedOn: Instant, 32 | author: Id[User], 33 | text: String, 34 | deleted: Boolean 35 | ) 36 | 37 | object Domain extends App { 38 | val userId = Id[User]("1") 39 | val postId = Id[Post]("1") 40 | val user = User(userId, Instant.now, new URI(""), "", false, false) 41 | val post = Post(postId, Instant.now, user.id, "", new URI(""), false) 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/Color.java: -------------------------------------------------------------------------------- 1 | import java.util.Optional; 2 | 3 | class Color { 4 | private final long hex; 5 | static Color makeFromRGB(String rgb) { 6 | return new Color(Integer.parseInt(rgb, 16)); 7 | } 8 | static Optional makeFromPalette(int red, int green, int blue) { 9 | if (red < 0 || red > 255 || 10 | green < 0 || green > 255 || 11 | blue < 0 || blue > 255) 12 | { 13 | return Optional.empty(); 14 | } 15 | 16 | return Optional.of(new Color((red << 16) + (green << 8) + blue)); 17 | } 18 | static Color makeFromHex(int h) { 19 | return new Color(h); 20 | } 21 | private Color(int h) { 22 | this.hex = h; 23 | } 24 | 25 | public String toString() { 26 | return "Color: " + hex; 27 | } 28 | 29 | public static void main(String[] args) { 30 | Color blue = Color.makeFromPalette(0, 0, 255).get(); 31 | 32 | System.out.println("Color: " + 33 | Color.makeFromPalette(128, 73, 2)); 34 | System.out.println("Color: " + 35 | Color.makeFromPalette(1128, 73, 2).orElse(blue)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/scala/com/example/Stack.scala: -------------------------------------------------------------------------------- 1 | package com.example 2 | 3 | trait Stack { 4 | type Elem 5 | 6 | def push(e: Elem): Unit 7 | def pop: Elem 8 | } 9 | 10 | trait AbstaractStackModel { 11 | type Elem 12 | var buffer = List.empty[Elem] 13 | 14 | def push(e: Elem): Unit = buffer = e :: buffer 15 | def pop: Elem = { 16 | val elem = buffer.head 17 | buffer = buffer.tail 18 | elem 19 | } 20 | } 21 | 22 | trait PrintStackModel { 23 | type Elem 24 | var buffer = List.empty[Elem] 25 | 26 | def push(e: Elem): Unit = { 27 | buffer = e :: buffer 28 | println(s"push($e)") 29 | } 30 | 31 | def pop: Elem = { 32 | val elem = buffer.head 33 | buffer = buffer.tail 34 | println(s"pop [$elem]") 35 | elem 36 | } 37 | } 38 | 39 | trait ConcreteStackModel[A] { 40 | type Elem = A 41 | } 42 | 43 | object StackMain extends App { 44 | val stack = new Stack with PrintStackModel with ConcreteStackModel[String] 45 | 46 | stack.push("7") 47 | stack.push("3") 48 | stack.push("6") 49 | stack.pop 50 | stack.pop 51 | stack.pop 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/exception/Tuple2.java: -------------------------------------------------------------------------------- 1 | package exception; 2 | 3 | import java.util.Arrays; 4 | import java.util.LinkedHashMap; 5 | import java.util.Map; 6 | import java.util.stream.Collectors; 7 | 8 | public final class Tuple2 { 9 | private final A first; 10 | private final B second; 11 | 12 | public Tuple2(A first, B second) { 13 | this.first = first; 14 | this.second = second; 15 | } 16 | 17 | public static Tuple2 of(A first, B second) { 18 | return new Tuple2<>(first, second); 19 | } 20 | 21 | @SafeVarargs 22 | public static Map toMap(Tuple2... tuples) { 23 | return Arrays.stream(tuples) 24 | .collect(Collectors.toMap( 25 | Tuple2::getFirst, 26 | Tuple2::getSecond, 27 | (u, v) -> v, 28 | LinkedHashMap::new 29 | )); 30 | } 31 | 32 | public A getFirst() { 33 | return first; 34 | } 35 | 36 | public B getSecond() { 37 | return second; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/resources/fak/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |

11 | + 12 | Add column 13 | Add Row 14 | CSV 15 |

16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
#Type
1.0
30 |
31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/scala/plainFP/WiredLogger.scala: -------------------------------------------------------------------------------- 1 | import scala.collection.mutable.ListBuffer 2 | 3 | object WiredLogger { 4 | class Logger(id : String) { 5 | private val log = new ListBuffer[String] 6 | def println(s: String): Unit = log += s 7 | def dump(): Unit = 8 | log.foreach(entry => Console.println(s"$id: $entry")) 9 | } 10 | 11 | def factBase(log: Logger)(x: Int): Int = { 12 | log.println(s"fact: $x") 13 | wget(s"http://catpics.net/pic$x") 14 | if (x == 1) 1 else x * factBase(log)(x-1) 15 | } 16 | 17 | val log1 = new Logger("log1") 18 | val log2 = new Logger("log2") 19 | val fact = factBase(log1) _ 20 | val wget = { url: String => 21 | log2.println("log in here is different!") 22 | WiredWebTools.wgetBase(log2)(url) 23 | } 24 | 25 | def main(args: Array[String]) = { 26 | val in = 3 27 | val out = fact(in) 28 | log2.dump() 29 | println(s"fact($in): $out") 30 | log1.dump() 31 | } 32 | } 33 | 34 | object WiredWebTools { 35 | import WiredLogger.Logger 36 | def wgetBase(log: Logger)(url: String): Unit = { 37 | log.println(s"Downloading $url") 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/scala/colossus/Akka.scala: -------------------------------------------------------------------------------- 1 | package colossus 2 | 3 | import akka.actor.ActorSystem 4 | import akka.http.scaladsl.Http 5 | import akka.http.scaladsl.model._ 6 | import akka.http.scaladsl.server.Directives._ 7 | import akka.stream.ActorMaterializer 8 | import scala.io.StdIn 9 | 10 | object WebServer { 11 | def main(args: Array[String]) { 12 | 13 | implicit val system = ActorSystem("my-system") 14 | implicit val materializer = ActorMaterializer() 15 | // needed for the future flatMap/onComplete in the end 16 | implicit val executionContext = system.dispatcher 17 | 18 | val route = 19 | path("hello") { 20 | get { 21 | complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "Hello World!")) 22 | } 23 | } 24 | 25 | val bindingFuture = Http().bindAndHandle(route, "localhost", 9000) 26 | 27 | println(s"Server online at http://localhost:8080/\nPress RETURN to stop...") 28 | StdIn.readLine() // let it run until user presses return 29 | bindingFuture 30 | .flatMap(_.unbind()) // trigger unbinding from the port 31 | .onComplete(_ => system.terminate()) // and shutdown when done 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/scala/tank/Tank.scala: -------------------------------------------------------------------------------- 1 | import scala.math._ 2 | 3 | case class Tank(x: Int, y: Int, d: Int = 0) { 4 | def előre(l: Int) = Tank( 5 | (x + cos(Pi * d / 180) * l).toInt, 6 | (y + sin(Pi * d / 180) * l).toInt, 7 | d) 8 | 9 | def hátra(l: Int) = előre(-l) 10 | 11 | def fordul(dr: Int) = Tank(x, y, (d + dr) % 360) 12 | } 13 | 14 | object Tank { 15 | def balra = 90 16 | def jobbra = -90 17 | 18 | val előre = (l: Int) => (tank: Tank) => tank.előre(l) 19 | val hátra = (l: Int) => (tank: Tank) => tank.előre(-l) 20 | val fordul = (dr: Int) => (tank: Tank) => tank.fordul(dr) 21 | } 22 | 23 | object TankApp extends App { 24 | import Tank._ 25 | 26 | def kiír(msg: Any) = println(msg) 27 | 28 | val tank = Tank(50, 50) 29 | val tank2 = tank fordul balra előre 10 fordul jobbra hátra 10 30 | kiír(tank2) 31 | 32 | val mozgás = fordul(balra) andThen előre(10) andThen fordul(jobbra) andThen hátra(10) 33 | val tank3 = mozgás(tank) 34 | kiír(tank3) 35 | 36 | val mozgásLista = Seq(fordul(balra), előre(10), fordul(jobbra), hátra(10)) 37 | val mozgás2 = mozgásLista reduce { _ andThen _ } 38 | val tank4 = mozgás2(tank) 39 | kiír(tank4) 40 | } 41 | -------------------------------------------------------------------------------- /src/main/resources/fak/css/main.css: -------------------------------------------------------------------------------- 1 | th[id] { 2 | cursor: pointer; 3 | } 4 | td[id] { 5 | cursor: pointer; 6 | } 7 | td.counter { 8 | cursor: pointer; 9 | text-align: right; 10 | } 11 | 12 | table, td, th { 13 | border: 1px solid #ddd; 14 | text-align: left; 15 | } 16 | 17 | table { 18 | border-collapse: collapse; 19 | } 20 | 21 | th, td { 22 | padding: 15px; 23 | } 24 | 25 | a.button { 26 | display: inline-block; 27 | padding: 0.5em 1.3em; 28 | margin: 0 0.3em 0.3em 0; 29 | border-radius: 0.2em; 30 | box-sizing: border-box; 31 | text-decoration: none; 32 | font-family: sans-serif; 33 | font-weight: 400; 34 | color: #FFFFFF; 35 | background-color: #3369ff; 36 | box-shadow:inset 0 -0.6em 1em -0.35em rgba(0,0,0,0.17),inset 0 0.6em 2em -0.3em rgba(255,255,255,0.15),inset 0 0 0em 0.05em rgba(255,255,255,0.12); 37 | text-align: center; 38 | position: relative; 39 | } 40 | a.button:active{ 41 | box-shadow:inset 0 0.6em 2em -0.3em rgba(0,0,0,0.15),inset 0 0 0em 0.05em rgba(255,255,255,0.12); 42 | } 43 | @media all and (max-width:30em){ 44 | a.button{ 45 | display:block; 46 |   margin:0.4em auto; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/scala/queens/Queens.scala: -------------------------------------------------------------------------------- 1 | package queens 2 | 3 | object Queens { 4 | var count = 0 5 | 6 | def permutationSolution(n: Int) = (0 until n).permutations.toStream filter { 7 | qs => 8 | count = count + 1 9 | qs.zipWithIndex.flatMap { 10 | case (c, d) => Seq(n + c + d, c - d) 11 | }.distinct.size == 2*n } 12 | 13 | def allSolution(n: Int, i: Int): Stream[Seq[Int]] = 14 | if (i <= 0) Stream(Seq()) else allSolution(n, i-1) flatMap extendSolution(n) 15 | 16 | def extendSolution(n: Int)(qs: Seq[Int]) = 17 | Stream.range(0, n) filter okToAdd(qs) map (q => q +: qs) 18 | 19 | def okToAdd(qs: Seq[Int])(q: Int) = 20 | qs zip (1 to qs.length) forall notThreaten(q).tupled 21 | 22 | val notThreaten = (qi: Int) => (qj: Int, j: Int) => 23 | (qi != qj) && math.abs(qi - qj) != j 24 | 25 | def extendSolutionLog(n: Int)(qs: Seq[Int]) = 26 | Stream.range(0, n) filter okToAdd(qs) map { q => 27 | val ret = q +: qs; 28 | println(ret) 29 | ret 30 | } 31 | 32 | def allSolutionLog(n: Int, i: Int): Stream[Seq[Int]] = 33 | if (i <= 0) 34 | Stream(Seq()) 35 | else allSolutionLog(n, i-1) flatMap extendSolutionLog(n) 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/independence/TightCoupling.java: -------------------------------------------------------------------------------- 1 | package independence; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | 7 | class TightCoupling { 8 | public static String read() { 9 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 10 | try { 11 | return br.readLine(); 12 | } catch (IOException e) { 13 | return "ERROR: " + e.getMessage(); 14 | } 15 | } 16 | 17 | public static void write(String str) { 18 | System.out.println(str); 19 | } 20 | 21 | public static String capitalize(String str) { 22 | if (str.isEmpty()) return "UNKNOWN"; 23 | else return str.substring(0, 1).toUpperCase() + str.substring(1); 24 | } 25 | 26 | public static String formatGreeting(String name) { 27 | return "Hello " + name + "!"; 28 | } 29 | 30 | public static void main(String[] args) { 31 | write("Enter your name: "); 32 | String name = read(); 33 | String capitalizedName = capitalize(name); 34 | String greeting = formatGreeting(capitalizedName); 35 | write(greeting); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/main/scala/ddd/ShoppingCartConfig.scala: -------------------------------------------------------------------------------- 1 | package ddd 2 | 3 | import ErrorAPI._ 4 | import Types._ 5 | import ShoppingCartAPI._ 6 | import ShoppingCart._ 7 | 8 | object ShoppingCartConfig { 9 | val wrongCommand: CommandHandler[State, Command, Event] = { 10 | case (state: State, command: Command) => 11 | Left(UnknownCommand(state, command)) 12 | } 13 | 14 | val commandHandler = 15 | addToEmpty orElse 16 | addToActive orElse 17 | removeFromActive orElse 18 | payActive orElse 19 | wrongCommand 20 | 21 | val wrongEvent: EventHandler[State, Event, State] = { 22 | case (state: State, event: Event) => 23 | Left(UnknownEvent(state, event)) 24 | } 25 | 26 | val eventHandler = 27 | handleFirstItemAdded orElse 28 | handleNextItemAdded orElse 29 | handleAnItemRemoved orElse 30 | handleLastItemRemoved orElse 31 | handlePaid orElse 32 | wrongEvent 33 | 34 | val getCapabilities = 35 | getEmptyCartCaps orElse 36 | getActiveCartCaps orElse 37 | getPaidCartCaps 38 | 39 | val wrongCapability: State => Capability = { 40 | state => { 41 | case command => 42 | Left(UnknownCapability(state, command)) 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/total/NotZeroInt.java: -------------------------------------------------------------------------------- 1 | package total; 2 | 3 | import java.util.Objects; 4 | import java.util.Optional; 5 | import java.util.function.Consumer; 6 | import java.util.function.Function; 7 | 8 | public final class NotZeroInt { 9 | public final int number; 10 | 11 | private NotZeroInt(int number) { 12 | this.number = number; 13 | } 14 | 15 | public static Optional of(int number) { 16 | if (number == 0) { 17 | return Optional.empty(); 18 | } else { 19 | return Optional.of(new NotZeroInt(number)); 20 | } 21 | } 22 | 23 | @Override 24 | public String toString() { 25 | return "NotZeroInt(" + number + ")"; 26 | } 27 | 28 | @Override 29 | public boolean equals(Object value) { 30 | if (value == this) return true; 31 | if (value instanceof NotZeroInt) { 32 | @SuppressWarnings("unchecked") 33 | NotZeroInt notZeroInt = (NotZeroInt) value; 34 | return Objects.equals(number, notZeroInt.number); 35 | } 36 | return false; 37 | } 38 | 39 | @Override 40 | public int hashCode() { 41 | return Objects.hash(number); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/scala/plainFP/MonadLogger.scala: -------------------------------------------------------------------------------- 1 | package plainFP 2 | 3 | import independence._ 4 | import independence.Level._ 5 | 6 | object MonadLogger { 7 | def fact(x: Int): Result[Int] = for { 8 | logFact <- LogResult("", INFO, "log1", s"fact: $x") 9 | logDiff <- LogResult("", DEBUG, "log2", "log in here is different!") 10 | response <- MonadWebTools.wget(s"http://catpics.net/pic$x") 11 | factorial <- if (x == 1) GoodResult(1) else fact(x-1).map(_ * x) 12 | } yield factorial 13 | 14 | def main(args: Array[String]): Unit = { 15 | val in = 3 16 | val result = fact(in) 17 | if (!args.contains("-t")) { 18 | result.processInfos(processLog("log2")) 19 | result.map(out => println(s"fact($in): $out")) 20 | result.processInfos(processLog("log1")) 21 | } 22 | } 23 | 24 | def processLog(place: String)(logs: List[Log]) = { 25 | logs foreach { 26 | case log @ Log(level, place_) if place == place_ => 27 | println(f"/LOG/ [$level%5s] |$place%4s| ${log.message()}") 28 | case _ => 29 | } 30 | Result(()) 31 | } 32 | } 33 | 34 | object MonadWebTools { 35 | def wget(url: String): Result[String] = { 36 | LogResult("", INFO, "log2", s"Downloading $url") 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/DecimalFormat.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | import java.util.Locale; 3 | import java.text.NumberFormat; 4 | 5 | public class DecimalFormat { 6 | 7 | public static void main(String[] args) { 8 | Locale[] locales = NumberFormat.getAvailableLocales(); 9 | System.out.println("Kérem a Celsius-fok értéket: "); 10 | Scanner be = new Scanner(System.in); 11 | double C = be.nextDouble(); 12 | for (int i = 0; i < locales.length; ++i) { 13 | if (locales[i].getCountry().length() == 0) { 14 | continue; // Skip language-only locales 15 | } 16 | System.out.print(locales[i].getDisplayName()); 17 | //NumberFormat form = NumberFormat.getInstance(locales[i]); 18 | NumberFormat form = NumberFormat.getInstance(Locale.forLanguageTag("hu-HU")); 19 | System.out.println("Country: " + Locale.forLanguageTag("hu-HU").getDisplayName()); 20 | java.text.DecimalFormat formatter = new java.text.DecimalFormat("#.0#"); 21 | double szam2 = (double)9/5*C+32; 22 | System.out.println("Fahrenheitben: " +form.format(szam2)+" fok"); 23 | System.out.println("Fahrenheitben: " +formatter.format(szam2)+" fok"); 24 | } 25 | 26 | } 27 | } 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/main/scala/plainFP/Logger.scala: -------------------------------------------------------------------------------- 1 | package plainFP 2 | 3 | import scala.collection.mutable.ListBuffer 4 | 5 | object Logger extends App { 6 | val silent = args.contains("-t") 7 | 8 | class Logger(id : String) { 9 | private val log = new ListBuffer[String] 10 | def println(s: String): Unit = log += s 11 | def dump(): Unit = if (!silent) { 12 | log.foreach(entry => Console.println(s"$id: $entry")) 13 | } 14 | } 15 | 16 | type Logged[T] = Logger => T 17 | 18 | def logContext[T](logger: Logger)(op: Logged[T]) = { 19 | op(logger) 20 | logger.dump() 21 | } 22 | 23 | val logger1 = new Logger("log1") 24 | val logger2 = new Logger("log2") 25 | 26 | def fact(x: Int): Logged[Int] = { log => 27 | log.println(s"fact: $x") 28 | logContext(logger2) { log2 => 29 | log2.println("log in here is different!") 30 | WebTools.wget(s"http://catpics.net/pic$x")(log2) 31 | } 32 | if (x == 1) 1 else x * fact(x-1)(log) 33 | } 34 | 35 | logContext(logger1) { log1 => 36 | val in = 3 37 | val out = fact(in)(log1) 38 | if (!silent) println(s"fact($in): $out") 39 | } 40 | } 41 | 42 | object WebTools { 43 | import Logger.Logged 44 | def wget(url: String): Logged[Unit] = { log => 45 | log.println(s"Downloading $url") 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/exception/Calc.java: -------------------------------------------------------------------------------- 1 | package exception; 2 | 3 | public class Calc { 4 | public static int calc(int value) throws ArithmeticException { 5 | final int a = calcA(value); 6 | final int b = calcB(value); 7 | return calcAB(a, b); 8 | } 9 | 10 | public static int calcA(int value) { 11 | return value * 5; 12 | } 13 | 14 | public static int calcB(int value) throws ArithmeticException { 15 | return 10000 / (20 - calcA(10 - value)); 16 | } 17 | 18 | public static int calcAB(int a, int b) { 19 | return a + b; 20 | } 21 | 22 | public static void main(String[] args) { 23 | try { 24 | final int result1 = calc(6); 25 | System.out.println("Result1: " + result1); 26 | } catch (Exception e) { 27 | System.out.println("Result1: " + e); 28 | } 29 | 30 | int result2; 31 | try { 32 | result2 = calc(8); 33 | } catch (Exception e) { 34 | result2 = 0; 35 | } 36 | System.out.println("Result2: " + result2); 37 | 38 | int result3; 39 | try { 40 | result3 = calc(6); 41 | } catch (Exception e) { 42 | result3 = 0; 43 | } 44 | System.out.println("Result3: " + result3); 45 | } 46 | } 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/main/java/independence/TightAndIndependentCoupling.java: -------------------------------------------------------------------------------- 1 | package independence; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | 7 | class TightAndIndeendentCoupling { 8 | public static String read() { 9 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 10 | try { 11 | return br.readLine(); 12 | } catch (IOException e) { 13 | return "ERROR: " + e.getMessage(); 14 | } 15 | } 16 | 17 | public static void write(String str) { 18 | System.out.println(str); 19 | } 20 | 21 | public static String capitalize(String str) { 22 | if (str.isEmpty()) return "UNKNOWN"; 23 | else return str.substring(0, 1).toUpperCase() + str.substring(1); 24 | } 25 | 26 | public static String formatGreeting(String name) { 27 | return "Hello " + name + "!"; 28 | } 29 | 30 | public static void main(String[] args) { 31 | write("Enter your name: "); 32 | String name = read(); 33 | String greeting = createGreeting(name); 34 | write(greeting); 35 | } 36 | 37 | public static String createGreeting(String name) { 38 | String capitalizedName = capitalize(name); 39 | return formatGreeting(capitalizedName); 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /src/main/scala/nomock/user/API.scala: -------------------------------------------------------------------------------- 1 | package nomock.user 2 | 3 | import scala.util.{Either, Left, Right} 4 | 5 | object API { 6 | import Failure._ 7 | 8 | type VerifiedID = String 9 | 10 | trait IDService { 11 | def verifyID(id: String): Either[Error, VerifiedID] 12 | } 13 | 14 | case class NewUser private[user] ( 15 | val username: String, 16 | val password: String, 17 | val iDNumber: String 18 | ) 19 | 20 | type CheckedUserName = String 21 | 22 | case class Login private[user] (val username: String, val password: String) 23 | 24 | case class CheckedLogin private[user] ( 25 | val checkedUserName: CheckedUserName, 26 | val password: String 27 | ) 28 | object CheckedLogin { 29 | def of(checkedUserName: CheckedUserName, login: Login) = 30 | new CheckedLogin(checkedUserName, login.password) 31 | } 32 | 33 | case class VerifiedUser ( 34 | checkedLogin: CheckedLogin, 35 | verifiedId: VerifiedID 36 | ) 37 | 38 | case class SavedUser private[user] ( 39 | val verifiedUser: VerifiedUser 40 | ) 41 | 42 | trait UserRepository { 43 | def checkUsername(username: String): Either[Error, CheckedUserName] 44 | def saveUser(verifiedUser: VerifiedUser): Either[Error, SavedUser] 45 | } 46 | 47 | trait UserService { 48 | def iDService: IDService 49 | def users: UserRepository 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/fp/Either.java: -------------------------------------------------------------------------------- 1 | package fp; 2 | 3 | import java.util.Optional; 4 | import java.util.function.Consumer; 5 | import java.util.function.Function; 6 | 7 | public final class Either 8 | { 9 | public static Either left(L value) { 10 | return new Either<>(Optional.of(value), Optional.empty()); 11 | } 12 | public static Either right(R value) { 13 | return new Either<>(Optional.empty(), Optional.of(value)); 14 | } 15 | private final Optional left; 16 | private final Optional right; 17 | private Either(Optional l, Optional r) { 18 | left=l; 19 | right=r; 20 | } 21 | public T map( 22 | Function lFunc, 23 | Function rFunc) 24 | { 25 | return left.map(lFunc).orElseGet(()->right.map(rFunc).get()); 26 | } 27 | public Either mapLeft(Function lFunc) 28 | { 29 | return new Either<>(left.map(lFunc),right); 30 | } 31 | public Either mapRight(Function rFunc) 32 | { 33 | return new Either<>(left, right.map(rFunc)); 34 | } 35 | public void apply(Consumer lFunc, Consumer rFunc) 36 | { 37 | left.ifPresent(lFunc); 38 | right.ifPresent(rFunc); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/scala/family/Family.scala: -------------------------------------------------------------------------------- 1 | package family 2 | 3 | object Family { 4 | trait FamilyMember 5 | trait Friend 6 | type Greet = PartialFunction[(FamilyMember, Friend), String] 7 | object Husband extends FamilyMember 8 | object Albert extends Friend 9 | object Joe extends Friend 10 | object Jane extends Friend 11 | object Wife extends FamilyMember 12 | val composePF = (g1: Greet, g2: Greet) => g2 orElse g1 13 | val greetDef: Greet = { case (fm, f) => s"How do you do!" } 14 | val friends = List(Albert) 15 | val accept = (friend: Friend) => friends.contains(friend) 16 | val wifeFriends = List(Albert, Jane) 17 | val wifeAccept = (friend: Friend) => wifeFriends.contains(friend) 18 | val greetHusbandHisFriend: Greet = { case (Husband, friend) if (accept(friend)) => "Hey budd!" } 19 | val greetWifeHisFriend: Greet = { case (Wife, friend) if (wifeAccept(friend)) => s"Hello my darling!" } 20 | trait GreetFn { 21 | def greet: Greet 22 | } 23 | trait Modul 24 | val composeGreet = (moduls: List[Modul]) => 25 | moduls.collect { case g: GreetFn => g.greet }.foldLeft(greetDef)(composePF) 26 | object HusbandModul extends Modul with GreetFn { 27 | def greet = greetHusbandHisFriend 28 | } 29 | object HusbandModulWithoutGreet extends Modul { 30 | def greet = greetHusbandHisFriend 31 | } 32 | object WifeModul extends Modul with GreetFn { 33 | def greet = greetWifeHisFriend 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/scala/tdd/WebServerSpec.scala: -------------------------------------------------------------------------------- 1 | package tdd 2 | 3 | import org.scalatest._ 4 | 5 | import scala.util.Random 6 | 7 | class WebServerSpec extends FunSpec with Matchers { 8 | val orderId = "15" 9 | val testOrder = 10 | Order(orderId, List(OrderRow("1", 10000.0), OrderRow("2", 17456.0))) 11 | 12 | def getOrder(id: String): Option[Order] = { 13 | if (id == orderId) Some(testOrder) else None 14 | } 15 | 16 | describe("WebServer.processOrderPrice") { 17 | it("should respond sum price of order for valid order") { 18 | val response = OrderPriceHandler.processOrderPrice(getOrder)("15") 19 | response shouldBe Some(Response(200, "text/plain", "27456.0")) 20 | } 21 | } 22 | 23 | describe("WebServer.processOrderPrice") { 24 | it("should respond None for invalid order") { 25 | val response = OrderPriceHandler.processOrderPrice(getOrder)("10") 26 | response shouldBe None 27 | } 28 | } 29 | 30 | describe("WebServer.calcPrice") { 31 | it("should calc sum price of order") { 32 | val price = OrderPriceHandler.calcPrice(testOrder) 33 | price shouldBe 27456.0 34 | } 35 | } 36 | 37 | describe("WebServer.convertToParameters") { 38 | it("should convert to map of parameters") { 39 | val parameters = WebServer.RootHandler.convertToParameters( 40 | "cmd=CalcSumPrice&discount=10") 41 | parameters shouldBe Map("cmd" -> "CalcSumPrice", "discount" -> "10") 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/cart/ShoppingCart.java: -------------------------------------------------------------------------------- 1 | package cart; 2 | 3 | import java.util.List; 4 | import java.util.stream.Stream; 5 | 6 | interface Item {} 7 | interface Error {} 8 | interface Payment {} 9 | 10 | public interface ShoppingCart {} 11 | 12 | interface EmptyOrActiveCart extends ShoppingCart {} 13 | 14 | class EmptyCart implements EmptyOrActiveCart { 15 | } 16 | 17 | class ActiveCart implements EmptyOrActiveCart { 18 | private final List unpaidItems; 19 | 20 | public ActiveCart(List unpaidItems) { 21 | this.unpaidItems = unpaidItems; 22 | } 23 | 24 | public Stream getUnpaidItems() { 25 | return unpaidItems.stream(); 26 | } 27 | } 28 | 29 | class PaidCart { 30 | private final List paidItems; 31 | private final Payment payment; 32 | 33 | public PaidCart(List paidItems, Payment payment) { 34 | this.paidItems = paidItems; 35 | this.payment = payment; 36 | } 37 | 38 | public Stream getPaidItems() { 39 | return paidItems.stream(); 40 | } 41 | 42 | public Payment getPayment() { 43 | return payment; 44 | } 45 | } 46 | 47 | interface AddToEmpty { 48 | ActiveCart apply(EmptyCart emptyCart, Item item); 49 | } 50 | 51 | interface AddToActive { 52 | ActiveCart apply(ActiveCart activeCart, Item item); 53 | } 54 | 55 | interface RemoveFromActive { 56 | EmptyOrActiveCart apply(ActiveCart activeCart, Item item); 57 | } 58 | 59 | interface PayActive { 60 | PaidCart apply(ActiveCart activeCart,Payment payment); 61 | } 62 | -------------------------------------------------------------------------------- /src/main/scala/licit/Licit.scala: -------------------------------------------------------------------------------- 1 | package licit 2 | 3 | case class Palyazat(parcellaKezdet: Int, parcellaVeg: Int, ar: Int) 4 | case class Elozmeny(elozmenyPalyazatok: List[Palyazat], osszAr: Int) 5 | 6 | object Licit { 7 | def szamitMegoldas(palyazatok: List[Palyazat]): List[Palyazat] = { 8 | val rendezettPalyazatok = palyazatok.sortBy(_.parcellaVeg) 9 | val elozmenyek = szamitElozmenyek(rendezettPalyazatok) 10 | osszeallitMegoldas(elozmenyek) 11 | } 12 | 13 | def szamitElozmenyek(palyazatok: List[Palyazat]): List[Elozmeny] = { 14 | palyazatok.foldLeft(List.empty[Elozmeny])(keszitElozmeny) 15 | } 16 | 17 | def keszitElozmeny(osszesElozmeny: List[Elozmeny], palyazat: Palyazat): List[Elozmeny] = { 18 | val elozmeny = keresesElozmeny(osszesElozmeny, palyazat) 19 | val elozmenyPalyazatok = elozmeny map ( e => e.elozmenyPalyazatok) getOrElse Nil 20 | val osszAr = (elozmeny map (_.osszAr) getOrElse 0) + palyazat.ar 21 | Elozmeny(palyazat :: elozmenyPalyazatok, osszAr) :: osszesElozmeny 22 | } 23 | 24 | def keresesElozmeny(osszesElozmeny: List[Elozmeny], palyazat: Palyazat): Option[Elozmeny] = { 25 | osszesElozmeny.sortBy(-_.osszAr).find { pe => 26 | palyazat.parcellaKezdet > pe.elozmenyPalyazatok.head.parcellaVeg } 27 | } 28 | 29 | def osszeallitMegoldas(osszesElozmeny: List[Elozmeny]): List[Palyazat] = { 30 | val csokkenoAruElozmenyek = osszesElozmeny.sortBy(-_.osszAr) 31 | csokkenoAruElozmenyek.head.elozmenyPalyazatok.reverse 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/scala/ddd/Directives.scala: -------------------------------------------------------------------------------- 1 | package ddd 2 | 3 | import Types._ 4 | import ShoppingCartConfig._ 5 | 6 | import akka.http.scaladsl.model.HttpMethods._ 7 | import akka.http.scaladsl.server.Directives._ 8 | import akka.http.scaladsl.model._ 9 | import akka.http.scaladsl.model.headers.{Accept, Link, LinkParams, LinkValue} 10 | import java.util.UUID 11 | 12 | case class AppState( 13 | state: State, 14 | capabilities: Map[String, Capability], 15 | uris: Map[String, String] 16 | ) 17 | 18 | object Directives { 19 | def setState(newState: State) = { 20 | val capabilities = getCapabilities(newState) 21 | val uris = (capabilities.keys map { key => 22 | (UUID.randomUUID.toString -> key) 23 | }).toMap 24 | AppState(newState, capabilities, uris) 25 | } 26 | 27 | def headComplete = (get | options | head) { complete("") } 28 | 29 | def stringLink(uri: String, rel: String, methods: HttpMethod*) = { 30 | LinkValue(Uri(uri), 31 | LinkParams.rel(rel), 32 | LinkParams.`type`(MediaTypes.`text/plain`.withParams( 33 | Map("method" -> methods.map(_.name).mkString(" "))))) 34 | } 35 | 36 | def respondCapabilities(uris: Map[String, String]) = { 37 | val links = (uris.keys map { 38 | uri => stringLink(uri, uris(uri), POST) 39 | }).toList 40 | 41 | respondWithLinks(links:_*) 42 | } 43 | 44 | def respondWithLinks(links: LinkValue*) = 45 | respondWithHeader(Link(links)) 46 | } 47 | -------------------------------------------------------------------------------- /src/main/scala/cbt/Build.scala: -------------------------------------------------------------------------------- 1 | import scala.concurrent.Future 2 | import scala.concurrent.ExecutionContext.Implicits.global 3 | 4 | trait MyDAG { 5 | def x = 5 6 | def y = 6 7 | def z = x + y 8 | def zz = z 9 | } 10 | 11 | trait MyPatchedDAG extends MyDAG { 12 | override def y = 7 13 | } 14 | 15 | case class Build( 16 | x: Int, 17 | y: Int, 18 | z: () => Int 19 | ) 20 | 21 | case class Build2( 22 | build: Build, 23 | zz: () => Int 24 | ) 25 | 26 | object MyBuild { 27 | def build( 28 | x: Int = 5, 29 | y: Int = 6, 30 | z: (Int, Int) => Int = (x, y) => x + y 31 | ) : Build = { 32 | Build(x, y, () => z(x, y)) 33 | } 34 | 35 | def build2( 36 | b: Build, 37 | zz: (() => Int) => Int = z => z() 38 | ): Build2 = { 39 | Build2(b, () => zz(() => b.z())) 40 | } 41 | } 42 | 43 | case class BuildF( 44 | x: Future[Int], 45 | y: Future[Int], 46 | z: () => Future[Int] 47 | ) 48 | 49 | case class BuildF2( 50 | build: BuildF, 51 | zz: () => Future[Int] 52 | ) 53 | 54 | object MyBuildF { 55 | def build( 56 | x: Future[Int] = Future{ 5 }, 57 | y: Future[Int] = Future { 6 }, 58 | z: (Future[Int], Future[Int]) => Future[Int] = (xF, yF) => { 59 | for { 60 | x <- xF 61 | y <- yF 62 | } yield (x + y) 63 | } 64 | ) : BuildF = { 65 | BuildF(x, y, () => z(x, y)) 66 | } 67 | 68 | def build2( 69 | b: BuildF, 70 | zz: (() => Future[Int]) => Future[Int] = z => z() 71 | ): BuildF2 = { 72 | BuildF2(b, () => zz(() => b.z())) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/scala/encapsulation/EncapsulationApp.scala: -------------------------------------------------------------------------------- 1 | package encapsulation 2 | 3 | object EncapsulationApp extends App { 4 | import unit.DistanceUnit._ 5 | import unit.DistanceMiles._ 6 | import unit.TimeUnit._ 7 | import unit.SpeedUnit._ 8 | import unit.Formulas._ 9 | 10 | //new unit.Distance(15) 11 | //createKm(1).meter 12 | 13 | println( 14 | s"10000 meter = ${asMile(createDistance(10000))} miles" 15 | ) 16 | println( 17 | s"1 mile = ${asKm(createMile(1))} km" 18 | ) 19 | println( 20 | s"50 km/h * 1800 sec = ${asKm(calcDistance(createKph(50), createTime(1800)))} km" 21 | ) 22 | 23 | case class ID(value: String) 24 | 25 | def loadFile(id: ID): Array[Byte] = id.value.getBytes() 26 | def loadDatabase(id: ID): Array[Byte] = ("Database" + id.value).getBytes() 27 | 28 | def dataToHex(data: Array[Byte]): String = data.map("%02X" format _).mkString 29 | 30 | def process(id: ID, load: ID => Array[Byte]): String = { 31 | val data = load(id) 32 | dataToHex(data) 33 | } 34 | 35 | println( 36 | process(ID("test"), loadFile) 37 | ) 38 | 39 | case class IDObject(id: ID, load: ID => Array[Byte]) 40 | 41 | def processObject(idObject: IDObject): String = { 42 | val data = idObject.load(idObject.id) 43 | dataToHex(data) 44 | } 45 | 46 | println( 47 | processObject(IDObject(ID("test"), loadDatabase)) 48 | ) 49 | 50 | def createDatabaseID(id: String): IDObject = IDObject(ID(id), loadDatabase) 51 | 52 | println( 53 | processObject(createDatabaseID("test")) 54 | ) 55 | } 56 | -------------------------------------------------------------------------------- /src/main/scala/plainFP/Config.scala: -------------------------------------------------------------------------------- 1 | package plainFP 2 | 3 | object ConfigAPI { 4 | case class Config(name: String, age: Int) 5 | case class Name(first: String, last: String) 6 | case class Age(age: Int) 7 | case class Person(name: Name, age: Age) 8 | 9 | def readName(name: String): Option[Name] = { 10 | val parts = name.split(" ") 11 | if (parts.length >= 2) Some(Name(parts(0), parts.tail.mkString(" "))) 12 | else None 13 | } 14 | 15 | def readAge(age: Int): Option[Age] = { 16 | if (1 <= age && age <= 150) Some(Age(age)) 17 | else None 18 | } 19 | 20 | def readPerson(config: Config): Option[Person] = { 21 | for { 22 | name <- readName(config.name) 23 | age <- readAge(config.age) 24 | } yield Person(name, age) 25 | } 26 | 27 | // or better: 28 | def optMap2[A, B, C](f: (A, B) => C)(optA: Option[A], optB: Option[B]) = 29 | for {a <- optA; b <- optB} yield f(a, b) 30 | } 31 | 32 | object ConfigApp extends App { 33 | import ConfigAPI._ 34 | 35 | val config1 = Config("John Doe", 20) 36 | println(readPerson(config1)) 37 | println(optMap2(Person)(readName(config1.name), readAge(config1.age))) 38 | println(optMap2(Tuple2[Name, Age])(readName(config1.name), readAge(config1.age))) 39 | val config2 = Config("Incognito", 99) 40 | println(readPerson(config2)) 41 | println(optMap2(Person)(readName(config2.name), readAge(config2.age))) 42 | val config3 = Config("John Doe", 170) 43 | println(readPerson(config3)) 44 | println(optMap2(Person)(readName(config3.name), readAge(config3.age))) 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/BufReadMulti.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.FileReader; 3 | import java.io.Reader; 4 | import java.util.stream.Stream; 5 | 6 | public class BufReadMulti { 7 | 8 | public static Reader createReader(char value) { 9 | return new Reader() { 10 | private int max = 30000; 11 | public int read(char[] buf, int offset, int length) { 12 | try { 13 | Thread.sleep(1000); 14 | } catch(Exception e) { 15 | } 16 | 17 | for (int i=0; i 0) { 20 | buf[offset + i] = '\n'; 21 | } else { 22 | return -1; 23 | } 24 | } 25 | buf[offset + length - 1] = value; 26 | return length; 27 | } 28 | 29 | public void close() { 30 | } 31 | }; 32 | } 33 | 34 | public static void main(String[] args) { 35 | try { 36 | BufferedReader brf = new BufferedReader(new FileReader("/home/kalman/index.html")); 37 | BufferedReader br1 = new BufferedReader(createReader('1')); 38 | BufferedReader br2 = new BufferedReader(createReader('2')); 39 | 40 | Stream lines = Stream.concat(br1.lines(), brf.lines()); 41 | lines.forEach(l -> System.out.println(l)); 42 | } catch(Exception e) { 43 | } 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /src/test/scala/shape/ShapeSpec.scala: -------------------------------------------------------------------------------- 1 | package shape 2 | 3 | import org.scalatest._ 4 | 5 | class ShapeSpec extends FunSpec with Matchers { 6 | import Shape._ 7 | 8 | describe("Draw") { 9 | it("circle") { 10 | draw(Circle(10), Point(3, 7)) shouldBe 11 | "Drawing circle at (3, 7) Radius: 10" 12 | } 13 | 14 | it("rectangle") { 15 | draw(Rectangle(10,20), Point(3, 7)) shouldBe 16 | "Drawing rectangle at (3, 7) Width 10, Height 20" 17 | } 18 | 19 | it("ellipse") { 20 | draw(Ellipse(10,20), Point(3, 7)) shouldBe 21 | "Drawing ellipse at (3, 7) Width 10, Height 20" 22 | } 23 | 24 | it("rounded rectangle") { 25 | draw(Rectangle(10,20,15), Point(3, 7)) shouldBe 26 | "Drawing rounded rectangle at (3, 7) Width 10, Height 20, Smoothing 15" 27 | } 28 | 29 | it("rounded rectangle with smoothing 100% (aka ellipse)") { 30 | draw(Rectangle(10,20,100), Point(3, 7)) shouldBe 31 | "Drawing ellipse at (3, 7) Width 10, Height 20" 32 | } 33 | } 34 | 35 | describe("Side count") { 36 | it("circle should be 1") { 37 | sideCount(Circle(10)) shouldBe 1 38 | } 39 | 40 | it("rectangle should be 4") { 41 | sideCount(Rectangle(10,20)) shouldBe 4 42 | } 43 | 44 | it("ellipse should be 1") { 45 | sideCount(Ellipse(10,20)) shouldBe 1 46 | } 47 | 48 | it("rounded rectangle should be 1") { 49 | sideCount(Rectangle(10,20,15)) shouldBe 1 50 | } 51 | 52 | it("rounded rectangle with smoothing 100% (aka ellipse) should be 1") { 53 | sideCount(Rectangle(10,20,100)) shouldBe 1 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/scala/com/example/SymbolicExpressions.scala: -------------------------------------------------------------------------------- 1 | package com.example 2 | 3 | object SymbolicExpressions { 4 | type Variable = () => Unit 5 | type Context = Variable => Float 6 | type Expression = Context => Float 7 | type Operator = (Expression, Expression) => Expression 8 | 9 | def variable = () => () 10 | 11 | val value = (variable: Variable) => (context: Context) => context(variable) 12 | 13 | val constant = (value: Float) => (context: Context) => value 14 | 15 | val set = (variable: Variable, value: Float, expression: Expression) => 16 | (context: Context) => 17 | { 18 | val newContext: Context = { 19 | case `variable` => value 20 | case v => context(v) 21 | } 22 | expression(newContext) 23 | } 24 | 25 | val operator = (floatOperator: (Float, Float) => Float) => 26 | (a: Expression, b: Expression) => 27 | (context: Context) => 28 | { 29 | floatOperator(a(context), b(context)) 30 | } 31 | 32 | val plus: Operator = operator(_ + _) 33 | val minus: Operator = operator(_ - _) 34 | val multiply: Operator = operator(_ * _) 35 | val divide: Operator = operator(_ / _) 36 | 37 | val sqrt = (x: Expression) => (context: Context) => math.sqrt(x(context)).toFloat 38 | } 39 | 40 | object ExpressionSample extends App { 41 | import SymbolicExpressions._ 42 | 43 | val a = variable 44 | val b = variable 45 | val c = variable 46 | val d = variable 47 | 48 | val expression = set(d, 1f, plus(minus(multiply(divide(value(a), value(b)), value(c)), value(d)), sqrt(constant(25f)))) 49 | 50 | val context = Map(a -> 1f, b -> 2f, c -> 3f, d -> 4f) 51 | println(expression(context)) 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/PP.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class PP { 4 | public static void main(String[] args) { 5 | Scanner scanner = new Scanner(System.in); 6 | int Z = scanner.nextInt(); 7 | for (int i = 0; i < Z; ++i) { 8 | int n = scanner.nextInt(); 9 | int j = 2; 10 | for (int k = 0; k < n; j++) { 11 | if (isPrime(j) && isPalindrome(j)) { 12 | k++; 13 | } 14 | } 15 | j--; 16 | int product = calcProduct(j); 17 | int l = 2; 18 | for (int k = 0; k < product; l++) { 19 | if (isPrime(l)) { 20 | k++; 21 | } 22 | } 23 | l--; 24 | System.out.println(j + " " + l); 25 | } 26 | } 27 | 28 | public static int calcProduct(int n) { 29 | int p = 1; 30 | String s = Integer.toString(n); 31 | for (int i = 0; i < s.length(); i++) { 32 | if (s.charAt(i) != 0) { 33 | Character ch = s.charAt(i); 34 | String chStr = Character.toString(ch); 35 | p = p * Integer.parseInt(chStr); 36 | } 37 | } 38 | return p; 39 | } 40 | 41 | public static boolean isPalindrome(int n) { 42 | String s = "" + n; 43 | return s.equals(new StringBuilder(s).reverse().toString()); 44 | } 45 | 46 | public static boolean isPrime(int n) { 47 | for (int i = 2; i <= Math.sqrt(n); i++) { 48 | if (n % i == 0) return false; 49 | } 50 | return true; 51 | } 52 | } 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/main/java/log/App.java: -------------------------------------------------------------------------------- 1 | package log; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.InputStreamReader; 5 | import java.io.IOException; 6 | import java.util.function.Function; 7 | 8 | class App { 9 | public static void main(final String[] args) { 10 | Logger.config(args); 11 | 12 | BufferedReader br = null; 13 | 14 | final Function process = Logger.makeLogged( 15 | App.class, "process", Server::process); 16 | 17 | final Function process2 = Logger.makeLogged( 18 | App.class, "process", 19 | Server::parse 20 | ).andThen( 21 | (o -> o.map(n -> n * n)) 22 | ).andThen(Logger.makeLogged(App.class, "process", 23 | (o -> o.map(n -> "Response: " + n))) 24 | ).andThen( 25 | (o -> o.orElse("Parse error")) 26 | ); 27 | 28 | try { 29 | br = new BufferedReader(new InputStreamReader(System.in)); 30 | while (true) { 31 | final String request = br.readLine(); 32 | 33 | if (request == null) { 34 | System.out.println("Exit!"); 35 | break; 36 | } 37 | final String response = process.apply(request); 38 | System.out.println(response); 39 | } 40 | } catch (IOException e) { 41 | e.printStackTrace(); 42 | } finally { 43 | if (br != null) { 44 | try { 45 | br.close(); 46 | } catch (IOException e) { 47 | e.printStackTrace(); 48 | } 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/scala/shape/Shape.scala: -------------------------------------------------------------------------------- 1 | package shape 2 | 3 | object Shape { 4 | case class Point(x: Int, y: Int) 5 | 6 | sealed trait Shape 7 | case class Circle(radius: Int) extends Shape 8 | case class Rectangle(width: Int, height: Int, smoothing: Int = 0) extends Shape 9 | case class Ellipse(width: Int, height: Int) extends Shape 10 | 11 | val draw = (shape: Shape, point: Point) => shape match { 12 | case Circle(radius) => 13 | drawCircle(point, radius) 14 | case Rectangle(width, height, 0) => 15 | drawRectangle(point, width, height) 16 | case Rectangle(width, height, 100) => 17 | drawEllipse(point, width, height) 18 | case Rectangle(width, height, smoothing) => 19 | drawRoundedRectangle(point, width, height, smoothing) 20 | case Ellipse(width, height) => 21 | drawEllipse(point, width, height) 22 | } 23 | 24 | val drawCircle = (point: Point, radius: Int) => 25 | s"Drawing circle at (${point.x}, ${point.y}) Radius: $radius" 26 | 27 | val drawRectangle = (point: Point, width: Int, height: Int) => 28 | s"Drawing rectangle at (${point.x}, ${point.y}) Width $width, Height $height" 29 | 30 | val drawEllipse = (point: Point, width: Int, height: Int) => 31 | s"Drawing ellipse at (${point.x}, ${point.y}) Width $width, Height $height" 32 | 33 | val drawRoundedRectangle = (point: Point, width: Int, height: Int, smoothing: Int) => 34 | s"Drawing rounded rectangle at (${point.x}, ${point.y}) " + 35 | s"Width $width, Height $height, Smoothing $smoothing" 36 | 37 | val sideCount = (shape: Shape) => shape match { 38 | case Circle(_) | Ellipse(_, _) => 1 39 | case Rectangle(_, _, smoothing) if smoothing > 0 => 1 40 | case Rectangle(_, _, _) => 4 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/scala/shape/ShapePFSpec.scala: -------------------------------------------------------------------------------- 1 | package shape 2 | 3 | import org.scalatest._ 4 | 5 | class ShapePFSpec extends FunSpec with Matchers { 6 | import ShapePF._ 7 | 8 | describe("Draw") { 9 | it("circle") { 10 | draw(Circle(Point(3, 7), 10)) shouldBe 11 | "Drawing circle at (3, 7) Radius: 10" 12 | } 13 | 14 | it("rectangle") { 15 | draw(Rectangle(Point(3, 7), 10,20)) shouldBe 16 | "Drawing rectangle at (3, 7) Width 10, Height 20" 17 | } 18 | 19 | it("ellipse") { 20 | draw(Ellipse(Point(3, 7), 10,20)) shouldBe 21 | "Drawing ellipse at (3, 7) Width 10, Height 20" 22 | } 23 | 24 | it("rounded rectangle") { 25 | drawWithRoundRectangle(Rectangle(Point(3, 7), 10,20,15)) shouldBe 26 | "Drawing rounded rectangle at (3, 7) Width 10, Height 20, Smoothing 15" 27 | } 28 | 29 | it("rounded rectangle with smoothing 100% (aka ellipse)") { 30 | drawWithRoundRectangle(Rectangle(Point(3, 7), 10,20,100)) shouldBe 31 | "Drawing ellipse at (3, 7) Width 10, Height 20" 32 | } 33 | } 34 | 35 | describe("Side count") { 36 | it("circle should be 1") { 37 | sideCount(Circle(Point(3, 7), 10)) shouldBe 1 38 | } 39 | 40 | it("rectangle should be 4") { 41 | sideCount(Rectangle(Point(3, 7), 10,20)) shouldBe 4 42 | } 43 | 44 | it("ellipse should be 1") { 45 | sideCount(Ellipse(Point(3, 7), 10,20)) shouldBe 1 46 | } 47 | 48 | it("rounded rectangle should be 1") { 49 | sideCount(Rectangle(Point(3, 7), 10,20,15)) shouldBe 1 50 | } 51 | 52 | it("rounded rectangle with smoothing 100% (aka ellipse) should be 1") { 53 | sideCount(Rectangle(Point(3, 7), 10,20,100)) shouldBe 1 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/total/Pair.java: -------------------------------------------------------------------------------- 1 | package total; 2 | 3 | import java.util.Objects; 4 | import java.util.Optional; 5 | import java.util.function.Consumer; 6 | import java.util.function.Function; 7 | 8 | public final class Pair { 9 | public final L left; 10 | public final R right; 11 | 12 | private Pair(L l, R r) { 13 | left = l; 14 | right = r; 15 | } 16 | 17 | public static Pair of(L l, R r) { 18 | return new Pair(l, r); 19 | } 20 | 21 | public Pair leftMap(Function f) { 22 | return new Pair(f.apply(left), right); 23 | } 24 | 25 | public Pair rightMap(Function f) { 26 | return new Pair(left, f.apply(right)); 27 | } 28 | 29 | public Optional> leftOptMap(Function> f) { 30 | return f.apply(left).map(l -> new Pair(l, right)); 31 | } 32 | 33 | public Optional> rightOptMap(Function> f) { 34 | return f.apply(right).map(r -> new Pair(left, r)); 35 | } 36 | 37 | @Override 38 | public String toString() { 39 | return "Pair(" + left + ", " + right + ")"; 40 | } 41 | 42 | @Override 43 | public boolean equals(Object value) { 44 | if (value == this) return true; 45 | if (value instanceof Pair) { 46 | @SuppressWarnings("unchecked") 47 | Pair pair = (Pair) value; 48 | return Objects.equals(left, pair.left) 49 | && Objects.equals(right, pair.right); 50 | } 51 | return false; 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | return Objects.hash(left, right); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/scala/shape/ShapeSimpleSpec.scala: -------------------------------------------------------------------------------- 1 | package shape 2 | 3 | import org.scalatest._ 4 | 5 | class ShapeSimpleSpec extends FunSpec with Matchers { 6 | import ShapeSimple._ 7 | 8 | describe("Draw") { 9 | it("circle") { 10 | draw(Point(3,7), createCircle(10)) shouldBe 11 | "Drawing circle at (3, 7) Radius: 10" 12 | } 13 | 14 | it("rectangle") { 15 | draw(Point(3,7), createRectangle(10, 20)) shouldBe 16 | "Drawing rectangle at (3, 7) Width 10, Height 20" 17 | } 18 | 19 | it("ellipse") { 20 | draw(Point(3,7), createEllipse(10, 20)) shouldBe 21 | "Drawing ellipse at (3, 7) Width 10, Height 20" 22 | } 23 | 24 | it("rounded rectangle") { 25 | draw(Point(3,7), createRoundedRectangle(10, 20, 15)) shouldBe 26 | "Drawing rounded rectangle at (3, 7) Width 10, Height 20, Smoothing 15" 27 | } 28 | 29 | it("rounded rectangle with smoothing 100% (aka ellipse)") { 30 | draw(Point(3,7), createRoundedRectangle(10, 20, 100)) shouldBe 31 | "Drawing ellipse at (3, 7) Width 10, Height 20" 32 | } 33 | } 34 | 35 | describe("Side count") { 36 | it("circle should be 1") { 37 | sideCount(createCircle(10)) shouldBe 1 38 | } 39 | 40 | it("rectangle should be 4") { 41 | sideCount(createRectangle(10, 20)) shouldBe 4 42 | } 43 | 44 | it("ellipse should be 1") { 45 | sideCount(createEllipse(10, 20)) shouldBe 1 46 | } 47 | 48 | it("rounded rectangle should be 1") { 49 | sideCount(createRoundedRectangle(10, 20, 15)) shouldBe 1 50 | } 51 | 52 | it("rounded rectangle with smoothing 100% (aka ellipse) should be 1") { 53 | sideCount(createRoundedRectangle(10, 20, 100)) shouldBe 1 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/test/scala/shape/ShapeOOSpec.scala: -------------------------------------------------------------------------------- 1 | package shape 2 | 3 | import org.scalatest._ 4 | 5 | class ShapeOOSpec extends FunSpec with Matchers { 6 | import ShapeOO._ 7 | 8 | describe("Draw") { 9 | it("circle") { 10 | Circle(Point(3, 7), 10).draw(Display(), 7) shouldBe 11 | "Drawing circle at (3, 7) Radius: 10" 12 | } 13 | 14 | it("rectangle") { 15 | Rectangle(Point(3, 7), 10,20).draw(Display(), 7) shouldBe 16 | "Drawing rectangle at (3, 7) Width 10, Height 20" 17 | } 18 | 19 | it("ellipse") { 20 | Ellipse(Point(3, 7), 10,20).draw(Display(), 7) shouldBe 21 | "Drawing ellipse at (3, 7) Width 10, Height 20" 22 | } 23 | 24 | it("rounded rectangle") { 25 | Rectangle(Point(3, 7), 10,20,15).draw(Display(), 7) shouldBe 26 | "Drawing rounded rectangle at (3, 7) Width 10, Height 20, Smoothing 15" 27 | } 28 | 29 | it("rounded rectangle with smoothing 100% (aka ellipse)") { 30 | Rectangle(Point(3, 7), 10,20,100).draw(Display(), 7) shouldBe 31 | "Drawing ellipse at (3, 7) Width 10, Height 20" 32 | } 33 | } 34 | 35 | describe("Side count") { 36 | it("circle should be 1") { 37 | Circle(Point(3, 7), 10).sideCount shouldBe 1 38 | } 39 | 40 | it("rectangle should be 4") { 41 | Rectangle(Point(3, 7), 10,20).sideCount shouldBe 4 42 | } 43 | 44 | it("ellipse should be 1") { 45 | Ellipse(Point(3, 7), 10,20).sideCount shouldBe 1 46 | } 47 | 48 | it("rounded rectangle should be 1") { 49 | Rectangle(Point(3, 7), 10,20,15).sideCount shouldBe 1 50 | } 51 | 52 | it("rounded rectangle with smoothing 100% (aka ellipse) should be 1") { 53 | Rectangle(Point(3, 7), 10,20,100).sideCount shouldBe 1 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/scala/ddd/ShoppingCartAPI.scala: -------------------------------------------------------------------------------- 1 | package ddd 2 | 3 | import Types._ 4 | 5 | object ShoppingCartAPI { 6 | import PaymentAPI._ 7 | 8 | case class Item(id: ID, name: String80, qty: Quantity, price: Money) 9 | 10 | sealed trait ShoppingCart extends State 11 | 12 | case object EmptyCart extends ShoppingCart 13 | case class ActiveCart(unpaidItems: List[Item]) extends ShoppingCart 14 | 15 | case class PaidCart( 16 | paidItems: List[Item], 17 | payment: Payment 18 | ) extends ShoppingCart 19 | 20 | case class AddItem(item: Item) extends Command 21 | case class RemoveItem(item: Item) extends Command 22 | case class Pay(payment: Payment) extends Command 23 | 24 | case class FirstItemAdded(item: Item) extends Event 25 | case class NextItemAdded(item: Item) extends Event 26 | sealed trait ItemRemoved extends Event 27 | case class AnItemRemoved(item: Item) extends ItemRemoved 28 | case class LastItemRemoved(item: Item) extends ItemRemoved 29 | case class Paid(payment: Payment) extends Event 30 | 31 | type AddToEmpty = CommandHandler[EmptyCart.type, AddItem, FirstItemAdded] 32 | type AddToActive = CommandHandler[ActiveCart, AddItem, NextItemAdded] 33 | type RemoveFromActive = CommandHandler[ActiveCart, RemoveItem, ItemRemoved] 34 | type PayActive = CommandHandler[ActiveCart, Pay, Paid] 35 | 36 | type HandleFirstItemAdded = 37 | EventHandler[EmptyCart.type, FirstItemAdded, ActiveCart] 38 | type HandleNextItemAdded = 39 | EventHandler[ActiveCart, NextItemAdded, ActiveCart] 40 | type HandleAnItemRemoved = 41 | EventHandler[ActiveCart, AnItemRemoved, ActiveCart] 42 | type HandleLastItemRemoved = 43 | EventHandler[ActiveCart, LastItemRemoved, EmptyCart.type] 44 | type HandlePaid = 45 | EventHandler[ActiveCart, Paid, PaidCart] 46 | } 47 | -------------------------------------------------------------------------------- /src/main/scala/ddd/Validation.scala: -------------------------------------------------------------------------------- 1 | package ddd 2 | 3 | trait Failure 4 | trait Warning extends Failure 5 | trait Error extends Failure 6 | trait Fatal extends Failure 7 | 8 | sealed abstract class Validation[Value] extends Product with Serializable { 9 | def map[T](f: Value => T): Validation[T] = this match { 10 | case Passed(value, warnings) => Passed(f(value), warnings) 11 | case _ => this.asInstanceOf[Validation[T]] 12 | } 13 | 14 | def flatMap[T](f: Value => Validation[T]): Validation[T] = this match { 15 | case Passed(value, warnings) => 16 | f(value) match { 17 | case Passed(v, ws) => Passed(v, warnings ++ ws) 18 | case Failed(errors) => Failed[T](warnings ++ errors) 19 | } 20 | case _ => this.asInstanceOf[Validation[T]] 21 | } 22 | 23 | def getOrElse(other: Value) = this match { 24 | case Passed(value, warnings) => value 25 | case _ => other 26 | } 27 | 28 | def noError: Validation[Value] = this match { 29 | case Passed(value, warnings) 30 | if warnings.exists(f => f.isInstanceOf[Error]) => 31 | Failed(warnings) 32 | 33 | case _ => 34 | this 35 | } 36 | } 37 | 38 | case class Passed[Value](value: Value, warnings: List[Failure] = Nil) 39 | extends Validation[Value] 40 | case class Failed[Value](errors: List[Failure]) extends Validation[Value] 41 | 42 | object Validation { 43 | def apply[Value](value: Value): Validation[Value] = Passed(value) 44 | def apply[Value](value: Value, failure: Failure): Validation[Value] = 45 | failure match { 46 | case error: Fatal => Failed(List(error)) 47 | case warning: Failure => Passed(value, List(warning)) 48 | } 49 | } 50 | 51 | case class TooLong(name: String) extends Warning 52 | case class TooBig(quantity: BigDecimal) extends Warning 53 | -------------------------------------------------------------------------------- /src/main/scala/supervisor/Main.scala: -------------------------------------------------------------------------------- 1 | package supervisor 2 | 3 | import akka.actor._ 4 | import akka.actor.OneForOneStrategy 5 | import akka.actor.SupervisorStrategy._ 6 | import scala.concurrent.duration._ 7 | 8 | object Main extends App { 9 | implicit val actorSystem = ActorSystem() 10 | val supervisor = actorSystem.actorOf(Props[Supervisor], "supervisor") 11 | supervisor ! StartCache 12 | } 13 | 14 | case object StartCache 15 | case object Terminate 16 | 17 | class Supervisor extends Actor with ActorLogging { 18 | override def receive = { 19 | case StartCache => 20 | val cache = context.actorOf(Props[Cache], "cache") 21 | context.watch(cache) 22 | (1 to 1000000) foreach { index => cache ! index } 23 | cache ! PoisonPill 24 | 25 | case Terminated => 26 | context.stop(self) 27 | } 28 | 29 | override val supervisorStrategy = 30 | OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 10.seconds) { 31 | case e: RuntimeException => 32 | log.info("Exception occured: {}", e) 33 | Restart 34 | } 35 | 36 | override def postStop() { 37 | log.info("stopping actor") 38 | context.system.terminate 39 | } 40 | } 41 | 42 | class Cache extends Actor with ActorLogging { 43 | override def receive = store(Map()) 44 | 45 | def store(storage: Map[Int, String]): Receive = { 46 | case number: Int => 47 | if (number % 1000 == 0) 48 | log.info("{}, mem: {}", number, Runtime.getRuntime.freeMemory) 49 | if (Runtime.getRuntime.freeMemory < 60000000) 50 | throw new RuntimeException("Low memory!") 51 | context become store(storage + (number -> ("".padTo(1000, '*')))) 52 | } 53 | 54 | override def postStop() { 55 | log.info("stopping actor") 56 | System.gc() 57 | Thread.sleep(100) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/scala/ddd/SampleData.scala: -------------------------------------------------------------------------------- 1 | package ddd 2 | 3 | import Types._ 4 | import PaymentAPI._ 5 | import ShoppingCartAPI._ 6 | 7 | class SampleData { 8 | val usd = USD(270) 9 | val gbp = GBP(370) 10 | val eur = EUR(310) 11 | val huf = HUF(1) 12 | 13 | //val itemMilk = Item("1", String80("milk"), Volume(10), Money(2, usd)) 14 | val itemTV = Item("2", "TV", Volume(7), Money(1000, eur)) 15 | 16 | def checkLength(name: String): Validation[String] = { 17 | if (name.length <= 2) Validation(name) 18 | else Validation(name, TooLong(name)) 19 | } 20 | 21 | def checkMax(value: BigDecimal, max: BigDecimal): Validation[BigDecimal] = { 22 | if (value <= max) Validation(value) 23 | else Validation(value, TooBig(value)) 24 | } 25 | 26 | val itemMilkChecked: Validation[Item] = (for { 27 | name <- checkLength("milk") 28 | volume <- checkMax(10000, 1000) 29 | } yield Item("1", name, Volume(volume), Money(2, usd))).noError 30 | 31 | println(s"itemMilkChecked: $itemMilkChecked") 32 | 33 | val itemMilk = itemMilkChecked getOrElse 34 | Item("1", "milk", Volume(10), Money(2, usd)) 35 | 36 | val mastercard = Card(MasterCard, "1234-5678-1234-5678") 37 | 38 | val convertToCommand = (data: String) => data match { 39 | case "AddItemMilk" => AddItem(itemMilk) 40 | case "AddItemTV" => AddItem(itemTV) 41 | case "PayCard" => Pay(mastercard) 42 | case "PayCash" => Pay(Cash) 43 | case "" => NoCommand 44 | case _ => WrongCommand(data) 45 | } 46 | } 47 | 48 | case class WrongCommand(text: String) extends Command 49 | 50 | object SampleData { 51 | val sd: Validation[SampleData] = Passed(new SampleData) 52 | val convertToCommand = (data: String) => sd match { 53 | case Passed(sd, _) => sd.convertToCommand(data) 54 | case _ => WrongCommand(data) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/scala/lnko/Lnko.scala: -------------------------------------------------------------------------------- 1 | package lnko 2 | 3 | import scala.math.{max, sqrt} 4 | 5 | object Lnko extends App { 6 | def legkisebbOszto(szam: Int): Int = 7 | (2 to sqrt(szam).toInt) 8 | .find(i => szam % i == 0) 9 | .getOrElse(szam) 10 | 11 | def primtenyezo(szam: Int): List[Int] = { 12 | def loop(szam: Int, list: List[Int]): List[Int] = { 13 | if (szam <= 1) list 14 | else { 15 | val res = legkisebbOszto(szam) 16 | loop(szam / res, res :: list) 17 | } 18 | } 19 | if (szam == 1) List(1) 20 | else loop(szam, Nil) 21 | } 22 | 23 | def lnko_lkkt(szam1: Int, szam2: Int): (Int, Int) = { 24 | def loop(p1: List[Int], p2: List[Int], lnko: List[Int], lkkt: List[Int]): (Int, Int) = { 25 | (p1.headOption, p2.headOption) match { 26 | case (None, None) => (lnko.product, lkkt.product) 27 | case (Some(a), None) => loop(p1.tail, p2, lnko, a :: lkkt) 28 | case (None, Some(b)) => loop(p1, p2.tail, lnko, b :: lkkt) 29 | case (Some(a), Some(b)) if (a > b) => loop(p1.tail, p2, lnko, a :: lkkt) 30 | case (Some(a), Some(b)) if (a < b) => loop(p1, p2.tail, lnko, b :: lkkt) 31 | case (Some(a), Some(b)) => loop(p1.tail, p2.tail, a :: lnko, b :: lkkt) 32 | } 33 | } 34 | loop(primtenyezo(szam1), primtenyezo(szam2), Nil, Nil) 35 | } 36 | 37 | println("Egyszerű példa: legkisebb közös többszörös és legnagyobb közös osztó.\n") 38 | 39 | (1 to 10) foreach { i => 40 | println(s"$i prímtényezői: ${primtenyezo(i)}") 41 | } 42 | 43 | val a = 240 44 | val b = 180 45 | println(s"\n$a prímtényezői: ${primtenyezo(a)}") 46 | println(s"$b primtényezői: ${primtenyezo(b)}\n") 47 | 48 | val kokt = lnko_lkkt(a, b) 49 | println(s"LNKO($a, $b) = ${kokt._1}") 50 | println(s"LKKT($a, $b) = ${kokt._2}") 51 | } 52 | -------------------------------------------------------------------------------- /src/main/scala/com/example/CakeDI.scala: -------------------------------------------------------------------------------- 1 | package com.example 2 | 3 | trait PluginModule { 4 | def init: Unit = {} 5 | } 6 | 7 | package persister { 8 | trait Storage { 9 | def read: String 10 | } 11 | 12 | trait StorageModule extends PluginModule { 13 | def storage: Storage 14 | } 15 | } 16 | 17 | package authentication { 18 | import persister._ 19 | 20 | class Authentication(storage: persister.Storage) { 21 | def login = storage.read 22 | } 23 | 24 | trait AuthenticationModule extends PluginModule { 25 | override def init = { 26 | super.init 27 | println("AuthenticationModule") 28 | } 29 | 30 | lazy val authentication = new Authentication(storage) 31 | def storage: Storage 32 | } 33 | } 34 | 35 | package persister { 36 | class Database() extends Storage { 37 | def read = "Read from database" 38 | } 39 | 40 | trait DatabaseModule extends StorageModule { 41 | override def init = { 42 | super.init 43 | println("DatabaseModule") 44 | } 45 | 46 | lazy val storage = new Database 47 | } 48 | } 49 | 50 | package persister { 51 | class MemStorage() extends Storage { 52 | def read = "Read from memory" 53 | } 54 | 55 | trait MemStorageModule extends StorageModule { 56 | override def init = { 57 | super.init 58 | println("MemStorageModule") 59 | } 60 | 61 | lazy val storage = new MemStorage 62 | } 63 | } 64 | 65 | object CakeDI extends App { 66 | import authentication._ 67 | import persister._ 68 | 69 | val databaseModules = new AuthenticationModule with DatabaseModule 70 | 71 | val memoryModules = new AuthenticationModule with MemStorageModule 72 | 73 | memoryModules.init 74 | databaseModules.init 75 | 76 | println(memoryModules.authentication.login) 77 | println(databaseModules.authentication.login) 78 | } 79 | -------------------------------------------------------------------------------- /src/main/scala/com/example/Composition.scala: -------------------------------------------------------------------------------- 1 | package com.example 2 | 3 | object Decoration extends App { 4 | trait Logger { 5 | def debug(msg: String) 6 | def error(msg: String) 7 | } 8 | 9 | def log[A, B](logger: Logger)(fn: A => B): A => B = { 10 | input => 11 | try { 12 | logger.debug(s"Start. <= $input") 13 | val start = System.nanoTime 14 | val output = fn(input) 15 | val time = (System.nanoTime - start) / 1000000 16 | logger.debug(s"End $time ms. => $output") 17 | output 18 | } catch { 19 | case e: Exception => 20 | logger.error(e.toString) 21 | throw e 22 | } 23 | } 24 | 25 | trait DB { 26 | def begin 27 | def commit 28 | def rollback 29 | def select(sql: String) 30 | } 31 | 32 | class TestDB extends DB { 33 | def begin = println("[begin]") 34 | def commit = println("[commit]") 35 | def rollback = println("[rollback]") 36 | def select(sql: String) = println(s"[select] $sql") 37 | } 38 | 39 | def transaction[T](fn: DB => T): DB => T = { 40 | db => 41 | try { 42 | db.begin 43 | val result = fn(db) 44 | db.commit 45 | result 46 | } catch { 47 | case e: Exception => 48 | db.rollback 49 | throw e 50 | } 51 | } 52 | 53 | class TestLogger extends Logger { 54 | def debug(msg: String) = println(s"[Debug] $msg") 55 | def error(msg: String) = println(s"[Error] $msg") 56 | } 57 | 58 | def testLogger = new TestLogger 59 | def testDB = new TestDB 60 | 61 | val selectPerson = log(testLogger) { 62 | transaction { 63 | db => 64 | db.select("select * from person") 65 | Thread.sleep(103) 66 | //throw new RuntimeException("Error") 67 | "Alex Smith" 68 | } 69 | } 70 | 71 | selectPerson(testDB) 72 | } 73 | -------------------------------------------------------------------------------- /src/test/scala/nomock/user/Infra.scala: -------------------------------------------------------------------------------- 1 | package nomock.user 2 | 3 | import API._ 4 | import Failure._ 5 | import scala.util.{Either, Left, Right} 6 | 7 | object Infra { 8 | val verifiedId = "Verified" 9 | val savingFailure = " SavingFailure" 10 | val wrongId = InfrastructureError("Wrong id") 11 | val usernameIsNotValid = InfrastructureError("username is not valid") 12 | val optimisticLockFailure = InfrastructureError("Optimistic lock failure") 13 | 14 | class TestUserService extends UserService { 15 | var userTable = Map[CheckedUserName, SavedUser]() 16 | 17 | object TestIDService extends IDService { 18 | def verifyID(id: String): Either[Error, VerifiedID] = 19 | if (id.startsWith("Verified")) Right(new VerifiedID(id)) 20 | else Left(wrongId) 21 | } 22 | 23 | object TestUserRepository extends UserRepository { 24 | def checkUsername(username: String): Either[Error, CheckedUserName] = 25 | if (userTable.keySet.contains(username)) { 26 | Left(usernameIsNotValid) 27 | } else { 28 | Right(new CheckedUserName(username)) 29 | } 30 | 31 | def saveUser(verifiedUser: VerifiedUser): Either[Error, SavedUser] = 32 | if (verifiedUser.verifiedId.endsWith(savingFailure)) { 33 | Left(optimisticLockFailure) 34 | } else { 35 | val savedUser = new SavedUser(verifiedUser) 36 | userTable = userTable + (verifiedUser.checkedLogin.checkedUserName -> savedUser) 37 | Right(savedUser) 38 | } 39 | } 40 | 41 | val iDService = TestIDService 42 | val users = TestUserRepository 43 | } 44 | 45 | def createTestSavedUser(username: String, password: String, id: String) = 46 | new SavedUser( 47 | new VerifiedUser( 48 | new CheckedLogin( 49 | new CheckedUserName(username), 50 | password 51 | ), 52 | new VerifiedID(id) 53 | ) 54 | ) 55 | } 56 | -------------------------------------------------------------------------------- /src/main/scala/ddd/Commons.scala: -------------------------------------------------------------------------------- 1 | package ddd 2 | 3 | trait State 4 | trait Command 5 | trait Event 6 | 7 | case object NoCommand extends Command 8 | 9 | object Types { 10 | sealed trait Quantity { 11 | def volume: BigDecimal 12 | def unit: String 13 | } 14 | case class Pieces(volume: BigDecimal) extends Quantity { def unit = "pcs" } 15 | case class Volume(volume: BigDecimal) extends Quantity { def unit = "l" } 16 | case class Mass(volume: BigDecimal) extends Quantity { def unit = "kg" } 17 | 18 | type ID = String 19 | type String80 = String 20 | 21 | case class StateResult(state: State, events: List[Event]) 22 | type ->[A, B] = PartialFunction[A, B] 23 | type CommandResult[Event] = Either[Failure, List[Event]] 24 | type CommandHandler[S <: State, C <: Command, E <: Event] = 25 | (State, Command) -> CommandResult[Event] 26 | type EventHandler[S <: State, E <: Event, St <: State] = 27 | (State, Event) -> Either[Failure, State] 28 | type Capability = 29 | Command -> Either[Failure, StateResult] 30 | type GetCapabilities = 31 | State -> Map[String, Capability] 32 | 33 | def createCapability( 34 | state: State, 35 | commandHandler: CommandHandler[State, Command, Event], 36 | eventHandler: EventHandler[State, Event, State]): Capability = 37 | { 38 | case command if commandHandler.isDefinedAt(state, command) => 39 | val fn = commandHandler andThen 40 | (r => r.right.flatMap { 41 | ls => eventHandler(state, ls.head).right.map { 42 | st => StateResult(st, ls) 43 | } 44 | }) 45 | fn(state, command) 46 | } 47 | 48 | def createCapability( 49 | state: State, 50 | command: Command, 51 | commandHandler: CommandHandler[State, Command, Event], 52 | eventHandler: EventHandler[State, Event, State]): Capability = 53 | { 54 | case cmd => createCapability(state, commandHandler, eventHandler)(command) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/independence/LooseCoupling.java: -------------------------------------------------------------------------------- 1 | package independence; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | 7 | class LooseCoupling { 8 | static interface Reader { 9 | String read(); 10 | } 11 | 12 | static class StdInReader implements Reader { 13 | public String read() { 14 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 15 | try { 16 | return br.readLine(); 17 | } catch (IOException e) { 18 | return "ERROR: " + e.getMessage(); 19 | } 20 | } 21 | } 22 | 23 | static interface Writer { 24 | void write(String str); 25 | } 26 | 27 | static class StdOutWriter implements Writer { 28 | public void write(String str) { 29 | System.out.println(str); 30 | } 31 | } 32 | 33 | static class Greeting { 34 | private Reader reader; 35 | private Writer writer; 36 | 37 | public Greeting(Reader reader, Writer writer) { 38 | this.reader = reader; 39 | this.writer = writer; 40 | } 41 | 42 | public void greet() { 43 | writer.write("Enter your name: "); 44 | String name = reader.read(); 45 | String capitalizedName = capitalize(name); 46 | String greeting = formatGreeting(capitalizedName); 47 | writer.write(greeting); 48 | } 49 | 50 | private static String capitalize(String str) { 51 | if (str.isEmpty()) return "UNKNOWN"; 52 | else return str.substring(0, 1).toUpperCase() + str.substring(1); 53 | } 54 | 55 | public static String formatGreeting(String name) { 56 | return "Hello " + name + "!"; 57 | } 58 | } 59 | 60 | public static void main(String[] args) { 61 | Greeting greeting = new Greeting(new StdInReader(), new StdOutWriter()); 62 | greeting.greet(); 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /src/main/java/cart/ShoppingCartImpl.java: -------------------------------------------------------------------------------- 1 | package cart; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.stream.Collectors; 6 | 7 | class Milk implements Item {} 8 | class Butter implements Item {} 9 | class Bread implements Item {} 10 | 11 | class MasterCard implements Payment { 12 | } 13 | 14 | public class ShoppingCartImpl { 15 | private ShoppingCartImpl() {}; 16 | 17 | public static AddToEmpty addToEmpty = (emptyCart, item) -> { 18 | return new ActiveCart(Arrays.asList(item)); 19 | }; 20 | 21 | public static AddToActive addToActive = (activeCart, item) -> { 22 | List items = activeCart.getUnpaidItems().collect(Collectors.toList()); 23 | items.add(item); 24 | return new ActiveCart(items); 25 | }; 26 | 27 | public static RemoveFromActive removeFromActive = (activeCart, item) -> { 28 | List items = 29 | activeCart.getUnpaidItems() 30 | .filter(i -> !i.equals(item)) 31 | .collect(Collectors.toList()); 32 | if (items.isEmpty()) return new EmptyCart(); 33 | else return new ActiveCart(items); 34 | }; 35 | 36 | public static PayActive payActive = (activeCart, payment) -> { 37 | List items = activeCart.getUnpaidItems().collect(Collectors.toList()); 38 | return new PaidCart(items, payment); 39 | }; 40 | 41 | public static void main(String[] args) { 42 | Milk milk = new Milk(); 43 | Bread bread = new Bread(); 44 | MasterCard masterCard = new MasterCard(); 45 | 46 | EmptyCart emptyCart = new EmptyCart(); 47 | ActiveCart activeCartMilk = 48 | addToEmpty.apply(emptyCart, milk); 49 | 50 | ActiveCart activeCartMilkAndBread = 51 | addToActive.apply(activeCartMilk, bread); 52 | 53 | EmptyOrActiveCart emptyOrActiveCart = 54 | removeFromActive.apply(activeCartMilkAndBread, milk); 55 | 56 | if (emptyOrActiveCart instanceof ActiveCart) { 57 | PaidCart paidCart = 58 | payActive.apply((ActiveCart) emptyOrActiveCart, masterCard); 59 | paidCart.getPaidItems().forEach(System.out::println); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/exception/CalcEither.java: -------------------------------------------------------------------------------- 1 | package exception; 2 | 3 | import java.util.stream.IntStream; 4 | import java.util.stream.Collectors; 5 | import java.util.Optional; 6 | 7 | public class CalcEither { 8 | public static Either calc(int value) { 9 | final int a = calcA(value); 10 | return calcB(value) 11 | .map(b -> calcAB(a, b)); 12 | } 13 | 14 | public static int calcA(int value) { 15 | return value * 5; 16 | } 17 | 18 | public static Either calcB(int value) { 19 | final int divisor = (20 - calcA(10 - value)); 20 | return divisor == 0 ? 21 | Left.of(Failure.of("/ by zero")) : 22 | Right.of(10000 / divisor); 23 | } 24 | 25 | public static int calcAB(int a, int b) { 26 | return a + b; 27 | } 28 | 29 | public static void main(String[] args) { 30 | final Either result1 = calc(6); 31 | System.out.println("Result1: " + result1); 32 | 33 | final int result2 = calc(8).orElse(0); 34 | System.out.println("Result2: " + result2); 35 | 36 | final int result3 = calc(6).orElse(0); 37 | System.out.println("Result3: " + result3); 38 | 39 | System.out.println("Result4: " + 40 | IntStream 41 | .range(1, 20) 42 | .mapToObj(CalcEither::calc) 43 | .map(v ->v.orElse(0)) 44 | .collect(Collectors.toList()) 45 | ); 46 | 47 | System.out.println("Result5: " + 48 | IntStream 49 | .range(1, 20) 50 | .mapToObj(CalcEither::calc) 51 | .map(Either::right) 52 | .filter(Optional::isPresent) 53 | .map(Optional::get) 54 | .collect(Collectors.toList()) 55 | ); 56 | 57 | System.out.println("Result6: " + 58 | IntStream 59 | .range(1, 20) 60 | .mapToObj(CalcEither::calc) 61 | .map(Either::left) 62 | .filter(Optional::isPresent) 63 | .map(Optional::get) 64 | .collect(Collectors.toList()) 65 | ); 66 | } 67 | } 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/main/scala/plainFP/SimpleImp.scala: -------------------------------------------------------------------------------- 1 | package plainFP 2 | 3 | object SimpleImp { 4 | def runApp(implicit config: Config) = { 5 | val webServer = new WebServer(config.host, config.port) 6 | while (webServer.listen(process)) {} 7 | webServer.close 8 | } 9 | 10 | def process(request: Request)(implicit config: Config): Response = { 11 | val id = parseJson(request.message) 12 | 13 | val modifiedPerson = updateEntity(id) 14 | 15 | modifiedPerson map { person => 16 | sendMail(person) 17 | Response(person.toString) 18 | } getOrElse Response("Error!") 19 | } 20 | 21 | def updateEntity(id: String)(implicit config: Config) = { 22 | val dbServer = new DBServer(config.dbUrl, config.dbUser, config.dbPassword) 23 | 24 | val personOpt = dbServer.getEntity[Person](id) 25 | val modified = personOpt map { person => 26 | val modifiedPerson = modifyPerson(person) 27 | dbServer.updateEntity(modifiedPerson) 28 | 29 | modifiedPerson 30 | } 31 | 32 | dbServer.close 33 | 34 | modified 35 | } 36 | 37 | def modifyPerson(person: Person)(implicit config: Config) = { 38 | val modifiedPerson = person.copy(age = person.age + 1) 39 | if (config.personNameToUppercase) { 40 | modifiedPerson.copy(name = modifiedPerson.name.toUpperCase) 41 | } else { 42 | modifiedPerson 43 | } 44 | } 45 | 46 | def createMail(person: Person)(implicit config: Config) = { 47 | Mail(config.smtpFrom, person.email, "Person updated", person.toString) 48 | } 49 | 50 | def sendMail(person: Person)(implicit config: Config) = { 51 | val smtpServer = new SmtpServer( 52 | config.smtpServer, 53 | config.smtpUser, 54 | config.smtpPassword 55 | ) 56 | 57 | val mail = createMail(person) 58 | smtpServer.sendMail(mail) 59 | 60 | smtpServer.close 61 | } 62 | 63 | def parseJson(json: String) = json 64 | } 65 | 66 | object SimpleImpApp extends App { 67 | implicit val config = Config( 68 | "localhost", 69 | 9000, 70 | "jdbc:..", 71 | "dbUser", 72 | "dbPassword", 73 | "smtp.local.com", 74 | "smtpUser", 75 | "smtpPassword", 76 | "simple@app.com", 77 | true 78 | ) 79 | 80 | SimpleImp.runApp 81 | } 82 | -------------------------------------------------------------------------------- /src/main/scala/combinators/ContactInfo.scala: -------------------------------------------------------------------------------- 1 | package combinators 2 | 3 | case class ContactInfo(name: String, email: String) 4 | 5 | object ContactInfoService { 6 | def toContactInfoList( 7 | csv: Seq[String], 8 | nameRequired: Boolean, 9 | emailRequired: Boolean): Seq[ContactInfo] = { 10 | csv 11 | .map(_.split(';')) 12 | .map(tokens => 13 | (tokens.headOption.getOrElse(""), 14 | tokens.drop(1).headOption.getOrElse(""))) 15 | .flatMap { 16 | case (name, email) => 17 | if ((name == "" && nameRequired) || (email == "" && emailRequired)) { 18 | None 19 | } else { 20 | Some(ContactInfo(name, email)) 21 | } 22 | } 23 | } 24 | 25 | type Converter = PartialFunction[(String, String), Option[ContactInfo]] 26 | 27 | def toContactInfoList2( 28 | csv: Seq[String], 29 | converter: Converter): Seq[ContactInfo] = { 30 | csv 31 | .map(_.split(';')) 32 | .map(tokens => 33 | (tokens.headOption.getOrElse(""), 34 | tokens.drop(1).headOption.getOrElse(""))) 35 | .flatMap { 36 | case (name, email) => converter(name, email) 37 | } 38 | } 39 | 40 | def makeContactInfo: Converter = { 41 | case (name, email) => Some(ContactInfo(name, email)) 42 | } 43 | 44 | def noEmptyName: Converter = { 45 | case ("", _) => None 46 | } 47 | 48 | def noEmptyEmail: Converter = { 49 | case (_, "") => None 50 | } 51 | } 52 | 53 | object ContactInfoApp extends App { 54 | import ContactInfoService._ 55 | 56 | val csv = List( 57 | ";", 58 | "Teszt Elek;", 59 | ";teszt@elek.hu", 60 | "Teszt Elek;teszt@elek.hu" 61 | ) 62 | 63 | println(toContactInfoList(csv, true, true)) 64 | println(toContactInfoList(csv, false, true)) 65 | println(toContactInfoList(csv, true, false)) 66 | println(toContactInfoList(csv, false, false)) 67 | 68 | println( 69 | toContactInfoList2( 70 | csv, 71 | noEmptyName orElse noEmptyEmail orElse makeContactInfo) 72 | ) 73 | println(toContactInfoList2(csv, noEmptyEmail orElse makeContactInfo)) 74 | println(toContactInfoList2(csv, noEmptyName orElse makeContactInfo)) 75 | println(toContactInfoList2(csv, makeContactInfo)) 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/total/Total.java: -------------------------------------------------------------------------------- 1 | package total; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.Optional; 6 | 7 | public class Total { 8 | static final List> pairs = Arrays.asList( 9 | Pair.of(6, 2), 10 | Pair.of(2, 6), 11 | Pair.of(2, 0), 12 | Pair.of(2, 8) 13 | ); 14 | 15 | private static long percent(int a, int b) { 16 | return a * 100L / b; 17 | } 18 | 19 | private static long percent(Pair pair) { 20 | return percent(pair.left, pair.right); 21 | } 22 | 23 | private static Optional percentOptional(int a, int b) { 24 | if (b == 0) { 25 | return Optional.empty(); 26 | } else { 27 | return Optional.of(a * 100L / b); 28 | } 29 | } 30 | 31 | private static Optional percentOptional(Pair pair) { 32 | return percentOptional(pair.left, pair.right); 33 | } 34 | 35 | private static long percentStrict(int a, NotZeroInt b) { 36 | return a * 100L / b.number; 37 | } 38 | 39 | private static long percentStrict(Pair pair) { 40 | return percentStrict(pair.left, pair.right); 41 | } 42 | 43 | public static void main(String[] args) { 44 | pairs.stream() 45 | .map(pair -> { 46 | try { 47 | return Optional.of(Total.percent(pair)); 48 | } catch (ArithmeticException e) { 49 | return Optional.empty(); 50 | } 51 | }) 52 | .forEach(System.out::println); 53 | 54 | pairs.stream() 55 | .map(Total::percentOptional) 56 | .forEach(System.out::println); 57 | 58 | pairs.stream() 59 | .map(pair -> pair.rightOptMap(NotZeroInt::of)) 60 | .map(pairOpt -> pairOpt.map(Total::percentStrict)) 61 | .forEach(System.out::println); 62 | 63 | pairs.stream() 64 | .map(pair -> pair.rightOptMap(NotZeroInt::of)) 65 | .filter(Optional::isPresent) 66 | .map(Optional::get) 67 | .map(Total::percentStrict) 68 | .forEach(System.out::println); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/builder/Contact.java: -------------------------------------------------------------------------------- 1 | package builder; 2 | 3 | import java.util.Optional; 4 | import java.util.function.Consumer; 5 | 6 | public class Contact { 7 | public final Optional email; 8 | public final Optional phone; 9 | 10 | private Contact(Optional email, Optional phone) { 11 | this.email = email; 12 | this.phone = phone; 13 | } 14 | 15 | public static Optional create(Consumer build) { 16 | ContactBuilder builder = new ContactBuilder(); 17 | 18 | build.accept(builder); 19 | 20 | if (builder.email.isPresent() || builder.phone.isPresent()) { 21 | return Optional.of(new Contact(builder.email, builder.phone)); 22 | } 23 | 24 | return Optional.empty(); 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return (!email.isPresent() ? "" : "Email: " + email.get() + " ") 30 | + (!phone.isPresent() ? "" : "Phone: " + phone.get() + " "); 31 | } 32 | 33 | private static Consumer companyPhone() { 34 | return builder -> builder.phone("55/555-555"); 35 | } 36 | 37 | private static ContactBuilder companyEmail(ContactBuilder builder) { 38 | return builder.email("test@company.com"); 39 | } 40 | 41 | public static void main(String[] args) { 42 | Optional contact1 = Contact.create(Contact::companyEmail); 43 | System.out.println("Contact1: " + contact1); 44 | 45 | Optional contact2 = Contact.create(builder -> {}); 46 | System.out.println("Contact2: " + contact2); 47 | 48 | Optional contact3 = Contact.create( 49 | companyPhone().andThen(Contact::companyEmail) 50 | ); 51 | System.out.println("Contact3: " + contact3); 52 | } 53 | 54 | public static class ContactBuilder { 55 | private Optional email = Optional.empty(); 56 | private Optional phone = Optional.empty(); 57 | 58 | private ContactBuilder() {}; 59 | 60 | public ContactBuilder email(String email) { 61 | this.email = Optional.of(email); 62 | return this; 63 | } 64 | public ContactBuilder phone(String phone) { 65 | this.phone = Optional.of(phone); 66 | return this; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/scala/rest/RestApi.scala: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | trait MediaTypeStructure 4 | 5 | case class StringMTStructure(content: String) extends MediaTypeStructure 6 | case class CollectionMTStructure(contentMT: MediaType) extends MediaTypeStructure 7 | 8 | case class MediaType(value: String, structure: MediaTypeStructure) 9 | 10 | sealed trait HttpMethod 11 | 12 | case object GET extends HttpMethod 13 | case object HEAD extends HttpMethod 14 | case object PUT extends HttpMethod 15 | case object DELETE extends HttpMethod 16 | 17 | case class RelLink( 18 | rel: String, 19 | method: HttpMethod, 20 | in: Option[MediaType], 21 | out: MediaType 22 | ) 23 | 24 | case class Link( 25 | uri: String, 26 | relLink: RelLink 27 | ) 28 | 29 | case class Transition( 30 | context: List[MediaType], 31 | relLink: RelLink 32 | ) 33 | 34 | trait Message { 35 | } 36 | 37 | case class ParsedUri(id: String, params: Map[String, String]) 38 | 39 | case class Action[R]( 40 | transition: Transition, 41 | parseUri: String => ParsedUri, 42 | fn: Message => R 43 | ) 44 | 45 | case class RestApi(entryPoint: String, transitions: Transition*) 46 | 47 | object RestApi extends App { 48 | val account = MediaType( 49 | "Account", 50 | StringMTStructure("Account(name: Name, number: AccountNumber, balance: Double)") 51 | ) 52 | val accountList = MediaType( 53 | "List[Account]", 54 | CollectionMTStructure(account) 55 | ) 56 | val name = MediaType( 57 | "Name", 58 | StringMTStructure("Name(value: String[80])") 59 | ) 60 | val deposit = MediaType( 61 | "Deposit", 62 | StringMTStructure("Deposit(sourceAccount: AccountNumber, amount: Double)") 63 | ) 64 | val withdraw = MediaType( 65 | "Withdraw", 66 | StringMTStructure("Withdraw(targetAccount: AccountNumber, amount: Double)") 67 | ) 68 | 69 | val accountApi = RestApi( 70 | "/api", 71 | Transition(Nil, RelLink("accounts", GET, None, accountList)), 72 | Transition(List(accountList), RelLink("new", PUT, Option(account), account)), 73 | Transition(List(accountList), RelLink("item", GET, None, account)), 74 | Transition(List(account), RelLink("delete", DELETE, None, account)), 75 | Transition(List(account), RelLink("edit", PUT, Option(name), account)), 76 | Transition(List(account), RelLink("edit", PUT, Option(deposit), account)), 77 | Transition(List(account), RelLink("edit", PUT, Option(withdraw), account)) 78 | ) 79 | 80 | println(accountApi) 81 | } 82 | -------------------------------------------------------------------------------- /src/test/scala/plainFP/RequestResponseSpec.scala: -------------------------------------------------------------------------------- 1 | package plainFP 2 | 3 | import org.scalatest._ 4 | import org.scalatest.Matchers._ 5 | 6 | class RequestResponseSpec extends FunSpec with Matchers { 7 | import RequestResponse._ 8 | import Method._ 9 | 10 | val badResponse = Response("400", "", "text/plain", "") 11 | val goodResponse = Response("200", "", "text/plain", "Hello John!") 12 | 13 | describe("hello") { 14 | it("should give good response") { 15 | val request = Request(GET, "/hello", "", "", "", "", "john") 16 | val response = hello(request) 17 | response shouldEqual goodResponse 18 | } 19 | it("should give bad response if method is wrong") { 20 | val request = Request(POST, "/hello", "???", "", "", "", "john") 21 | val response = hello(request) 22 | response shouldEqual badResponse 23 | } 24 | it("should give bad response if path is wrong") { 25 | val request = Request(GET, "/bye", "???", "", "", "", "john") 26 | val response = hello(request) 27 | response shouldEqual badResponse 28 | } 29 | } 30 | 31 | describe("isMethod") { 32 | it("should give true if method is equal") { 33 | val request = Request(GET, "", "", "", "", "", "") 34 | val response = isGetMethod(request) 35 | response shouldEqual true 36 | } 37 | it("should give false if method is wrong") { 38 | val request = Request(POST, "", "", "", "", "", "") 39 | val response = isGetMethod(request) 40 | response shouldEqual false 41 | } 42 | } 43 | 44 | describe("isPath") { 45 | it("should give true if path is equal") { 46 | val request = Request(GET, "/hello", "", "", "", "", "") 47 | val response = isHelloPath(request) 48 | response shouldEqual true 49 | } 50 | it("should give false if path is wrong") { 51 | val request = Request(GET, "/bye", "", "", "", "", "") 52 | val response = isHelloPath(request) 53 | response shouldEqual false 54 | } 55 | } 56 | 57 | describe("createHelloContent") { 58 | it("should give 'Hello John!'") { 59 | val request = Request(GET, "", "", "", "", "", "john") 60 | val response = createHelloContent(request) 61 | response shouldEqual "Hello John!" 62 | } 63 | it("should give 'Hello !' if name is empty") { 64 | val request = Request(GET, "", "", "", "", "", "") 65 | val response = createHelloContent(request) 66 | response shouldEqual "Hello !" 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/scala/immutable/AccountMutable.scala: -------------------------------------------------------------------------------- 1 | package immutable 2 | import scala.concurrent.Future 3 | import scala.concurrent.ExecutionContext 4 | 5 | object AccountMutable extends App { 6 | class Account(var balance: Double) { 7 | def deposit(amount: Double): Unit = { 8 | balance += amount 9 | } 10 | 11 | def withdraw(amount: Double): Boolean = { 12 | if (balance >= amount) { 13 | balance -= amount 14 | true 15 | } else { 16 | false 17 | } 18 | } 19 | 20 | override def toString() = { 21 | s"Account($balance)" 22 | } 23 | } 24 | 25 | def sendMoney(source: Account, target: Account, amount: Double): Boolean = { 26 | source.synchronized { 27 | Thread.sleep(1) 28 | val success = source.withdraw(amount) 29 | if (success) { 30 | target.synchronized { 31 | Thread.sleep(1) 32 | target.deposit(amount) 33 | } 34 | } 35 | success 36 | } 37 | } 38 | 39 | def sendMoneyRefactored(source: Account, target: Account, amount: Double): Boolean = { 40 | val newTarget = target.deposit(amount) 41 | val success = source.withdraw(amount) 42 | success 43 | } 44 | 45 | def testSendMoney(sendMoney: (Account, Account, Double) => Boolean) = { 46 | val accountFred = new Account(100) 47 | val accountJoe = new Account(100) 48 | accountFred.deposit(10) 49 | accountFred.withdraw((180)) 50 | println(s"accountFred: $accountFred, accountJoe: $accountJoe") 51 | sendMoney(accountFred, accountJoe, 70) 52 | println(s"accountFred: $accountFred, accountJoe: $accountJoe") 53 | sendMoney(accountFred, accountJoe, 70) 54 | println(s"accountFred: $accountFred, accountJoe: $accountJoe") 55 | } 56 | 57 | testSendMoney(sendMoney) 58 | testSendMoney(sendMoneyRefactored) 59 | 60 | implicit val ec = ExecutionContext.global 61 | def testSendMoneyPar() = { 62 | val accountFred = new Account(100) 63 | val accountJoe = new Account(100) 64 | println(s"accountFred: $accountFred, accountJoe: $accountJoe") 65 | val future1 = Future { sendMoney(accountFred, accountJoe, 70) } 66 | val future2 = Future { sendMoney(accountJoe, accountFred, 50) } 67 | val future = for { 68 | success <- future1 69 | _ <- future2 70 | } yield (success) 71 | future.foreach( 72 | success => println(s"success: $success, accountFred: $accountFred, accountJoe: $accountJoe") 73 | ) 74 | } 75 | 76 | testSendMoneyPar() 77 | Thread.sleep(1000) 78 | } 79 | -------------------------------------------------------------------------------- /src/main/scala/tight/TightCoupling.scala: -------------------------------------------------------------------------------- 1 | package tight 2 | 3 | import java.util.concurrent.ConcurrentHashMap 4 | 5 | import scala.concurrent.ExecutionContext.Implicits.global 6 | import scala.concurrent.duration._ 7 | import scala.concurrent.{Await, Future} 8 | 9 | object Cooking extends App { 10 | class KVStore[K, V] { 11 | private val s = new ConcurrentHashMap[K, V]() 12 | 13 | def create(k: K, v: V): Future[Boolean] = Future.successful(s.putIfAbsent(k, v) == null) 14 | def read(k: K): Future[Option[V]] = Future.successful(Option(s.get(k))) 15 | def update(k: K, v: V): Future[Unit] = Future.successful(s.put(k, v)) 16 | def delete(k: K): Future[Boolean] = Future.successful(s.remove(k) != null) 17 | } 18 | 19 | // 20 | 21 | type FoodName = String 22 | type Quantity = Int 23 | type FoodKV = KVStore[String, Int] 24 | type TestFoodKV = KVStore[String, Int] 25 | 26 | def addFood(n: FoodName, q: Quantity): Future[Unit] = for { 27 | current <- fc.read(n) 28 | updated = current.map(c => c + q).getOrElse(q) 29 | _ <- fc.update(n, updated) 30 | } yield () 31 | 32 | def takeFood(n: FoodName, q: Quantity): Future[Quantity] = for { 33 | current <- fc.read(n) 34 | inStock = current.getOrElse(0) 35 | taken = Math.min(inStock, q) 36 | left = inStock - taken 37 | _ <- if (left > 0) fc.update(n, left) else fc.delete(n) 38 | } yield taken 39 | 40 | // 41 | 42 | def cookSauce(q: Quantity): Future[Quantity]= 43 | for { 44 | tomatoQ <- takeFood("tomato", q) 45 | vegQ <- takeFood("non-tomato veggies", q) 46 | _ <- takeFood("garlic", q*2) 47 | sauceQ = tomatoQ/2 + vegQ*3/4 48 | _ <- addFood("sauce", sauceQ) 49 | } yield sauceQ 50 | 51 | def cookPasta(q: Quantity): Future[Quantity]= 52 | for { 53 | pastaQ <- takeFood("pasta", q) 54 | _ <- takeFood("salt", 10) 55 | _ <- addFood("cooked pasta", pastaQ) 56 | } yield pastaQ 57 | 58 | // 59 | 60 | val test = true 61 | val fc = if (test) new TestFoodKV else new FoodKV 62 | 63 | // 64 | 65 | val shopping = for { 66 | _ <- addFood("tomato", 10) 67 | _ <- addFood("non-tomato veggies", 15) 68 | _ <- addFood("garlic", 42) 69 | _ <- addFood("salt", 1) 70 | _ <- addFood("pasta", 5) 71 | } yield () 72 | 73 | val cooking = for { 74 | _ <- shopping 75 | sq <- cookSauce(5) 76 | pq <- cookPasta(10) 77 | } yield s"Cooked $sq sauce and $pq pasta" 78 | 79 | val eating = Await.result(cooking, 1.minute) 80 | println(eating) 81 | } 82 | 83 | 84 | -------------------------------------------------------------------------------- /src/main/java/OccurenceOfLetters.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | import java.util.LinkedHashMap; 3 | import java.util.List; 4 | import java.util.Map; 5 | import java.util.Scanner; 6 | import java.util.function.*; 7 | import java.util.stream.*; 8 | 9 | public class OccurenceOfLetters { 10 | 11 | private static String phrase; 12 | 13 | private static Scanner scn = null; 14 | 15 | private static Map hashMap; 16 | 17 | private static Map result; 18 | 19 | public static void main(String[] args) { 20 | 21 | System.out.print("Enter your string:"); 22 | 23 | scn = new Scanner(System.in); 24 | 25 | phrase = scn.nextLine(); 26 | 27 | System.out.print("Occurences:["); 28 | 29 | Counter(); 30 | 31 | System.out.println(result); 32 | 33 | final Map occurences = phrase.toUpperCase().chars() 34 | .mapToObj(i -> (char) i) 35 | .filter(c -> c != ' ') 36 | .collect(Collectors.groupingBy(c -> c, Collectors.counting())); 37 | 38 | final List> sortedOccurences = 39 | occurences.entrySet().stream() 40 | .sorted(Map.Entry. comparingByValue().reversed()) 41 | .collect(Collectors.toList()); 42 | 43 | System.out.println(sortedOccurences); 44 | } 45 | 46 | 47 | private static char Counter() { 48 | 49 | char actLetter; 50 | int count; 51 | 52 | hashMap = new HashMap<>(); 53 | 54 | result = new LinkedHashMap<>(); 55 | 56 | 57 | for(actLetter=(char)65; actLetter<=90; actLetter++) 58 | { 59 | count=0; 60 | 61 | for(int j=0; j0) 72 | { 73 | 74 | hashMap.put(actLetter, count); 75 | 76 | System.out.printf("%c:%d,",actLetter,count); 77 | 78 | } 79 | 80 | } 81 | hashMap.entrySet() 82 | .stream() 83 | .sorted(Map.Entry.comparingByValue().reversed()) 84 | .forEach(x -> result.put(x.getKey(), x.getValue())); 85 | 86 | System.out.print("]"); 87 | System.out.println(); 88 | 89 | return actLetter; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/scala/immutable/AccountImmutable.scala: -------------------------------------------------------------------------------- 1 | package immutable 2 | import scala.concurrent.ExecutionContext 3 | import akka.compat.Future 4 | import scala.concurrent.Future 5 | 6 | object AccountImmutable extends App { 7 | case class Account(balance: Double) { 8 | def deposit(amount: Double): Account= { 9 | copy(balance = balance + amount) 10 | } 11 | 12 | def withdraw(amount: Double): Option[Account] = { 13 | if (balance >= amount) { 14 | Some(copy(balance = balance - amount)) 15 | } else { 16 | None 17 | } 18 | } 19 | } 20 | 21 | def sendMoney(source: Account, target: Account, amount: Double) : (Account, Account) = { 22 | source.withdraw(amount).map(newSource => 23 | (newSource, target.deposit(amount)) 24 | ).getOrElse(source, target) 25 | } 26 | 27 | def sendMoneyRefactored(source: Account, target: Account, amount: Double) : (Account, Account) = { 28 | val newTarget = target.deposit(amount) 29 | source.withdraw(amount).map(newSource => 30 | (newSource, newTarget) 31 | ).getOrElse(source, target) 32 | } 33 | 34 | def testSendMoney(sendMoney: (Account, Account, Double) => (Account, Account)) = { 35 | val accountFred = new Account(100) 36 | val accountJoe = new Account(100) 37 | val accountFred2 = accountFred.deposit(10) 38 | val accountFred3Opt = accountFred2.withdraw((180)) 39 | val accountFred3 = accountFred3Opt.getOrElse(accountFred2) 40 | println(s"accountFred: $accountFred3, accountJoe: $accountJoe") 41 | val(accountFred4, accountJoe2) = sendMoney(accountFred3, accountJoe, 70) 42 | println(s"accountFred: $accountFred4, accountJoe: $accountJoe2") 43 | val(accountFred5, accountJoe3) = sendMoney(accountFred4, accountJoe2, 70) 44 | println(s"accountFred: $accountFred5, accountJoe: $accountJoe3") 45 | } 46 | 47 | testSendMoney(sendMoney) 48 | testSendMoney(sendMoneyRefactored) 49 | 50 | implicit val ec = ExecutionContext.global 51 | def testSendMoneyPar() = { 52 | val accountFred = new Account(100) 53 | val accountJoe = new Account(100) 54 | println(s"accountFred: $accountFred, accountJoe: $accountJoe") 55 | val future = for { 56 | (accountFred2, accountJoe2) <- Future { sendMoney(accountFred, accountJoe, 70) } 57 | (accountJoe3, accountFred3) <- Future { sendMoney(accountJoe2, accountFred2, 50) } 58 | } yield (accountFred3, accountJoe3) 59 | future.foreach { 60 | case (accountFred3, accountJoe3) => 61 | println(s"accountFred3: $accountFred3, accountJoe3: $accountJoe3") 62 | } 63 | } 64 | 65 | testSendMoneyPar() 66 | Thread.sleep(1000) 67 | } 68 | -------------------------------------------------------------------------------- /src/main/scala/ebi/Store.scala: -------------------------------------------------------------------------------- 1 | package ebi 2 | 3 | case class Item(name: String, price: Double) 4 | case class OrderedItem(itemId: String, quantity: Double) 5 | case class Order(id: String, customer: String, items: List[OrderedItem]) 6 | 7 | object StoreAPI { 8 | case class OrderRequest(order: Order) 9 | case class OrderResponse(status: Either[String, Double]) 10 | 11 | type PlaceOrder = OrderRequest => OrderResponse 12 | } 13 | 14 | object DatabaseAPI { 15 | type GetItem = String => Either[String, Item] 16 | type SaveOrder = Order => Either[String, Order] 17 | } 18 | 19 | object MemDatabase { 20 | import DatabaseAPI._ 21 | 22 | val items = Map( 23 | "001" -> Item("Sword", 399.9), 24 | "002" -> Item("Chair", 24.9), 25 | "003" -> Item("Table", 99.9), 26 | "004" -> Item("Bed", 59.9) 27 | ) 28 | 29 | val getItem: GetItem = id => items get id match { 30 | case None => Left(s"Missing item $id!") 31 | case Some(item) => Right(item) 32 | } 33 | val saveOrder: SaveOrder = order => Right(order) 34 | val saveOrderFailing: SaveOrder = order => Left("No space on disk!") 35 | } 36 | 37 | object Store { 38 | import DatabaseAPI._ 39 | import StoreAPI._ 40 | 41 | private def sequence[A, B](s: Seq[Either[A, B]]): Either[A, Seq[B]] = 42 | s.foldRight(Right(Nil): Either[A, List[B]]) { 43 | (e, acc) => for (xs <- acc.right; x <- e.right) yield x :: xs 44 | } 45 | 46 | val placeOrderBusinessLogic: (GetItem, SaveOrder) => PlaceOrder = (getItem, saveOrder) => 47 | request => { 48 | val sumList = request.order.items.map { 49 | orderedItem => getItem(orderedItem.itemId).right map { _.price * orderedItem.quantity } 50 | } 51 | val savedOrder = sequence(sumList).right flatMap { 52 | sl => saveOrder(request.order).right map (_ => sl.sum) 53 | } 54 | OrderResponse(savedOrder) 55 | } 56 | } 57 | 58 | object StoreApp extends App { 59 | import MemDatabase._ 60 | import Store._ 61 | import StoreAPI._ 62 | 63 | val placeOrder: PlaceOrder = placeOrderBusinessLogic(getItem, saveOrder) 64 | val placeOrderFailing: PlaceOrder = placeOrderBusinessLogic(getItem, saveOrderFailing) 65 | 66 | val orderRequest1 =OrderRequest(Order("ORD_01", "IBM", 67 | List( 68 | OrderedItem("002", 12.0), 69 | OrderedItem("004", 2.0) 70 | ))) 71 | 72 | val orderRequest2 =OrderRequest(Order("ORD_02", "Google", 73 | List( 74 | OrderedItem("002", 12.0), 75 | OrderedItem("005", 2.0) 76 | ))) 77 | 78 | println(placeOrder(orderRequest1).toString) 79 | println(placeOrderFailing(orderRequest1).toString) 80 | 81 | println(placeOrder(orderRequest2).toString) 82 | println(placeOrderFailing(orderRequest2).toString) 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/exception/Right.java: -------------------------------------------------------------------------------- 1 | package exception; 2 | 3 | import java.util.Optional; 4 | import java.util.function.Consumer; 5 | import java.util.function.Function; 6 | 7 | public final class Right implements Either { 8 | private final R value; 9 | 10 | private Right(R r) { 11 | value = r; 12 | } 13 | 14 | public static Right of(R r) { 15 | return new Right<>(r); 16 | } 17 | 18 | @Override 19 | public Either map(Function f) { 20 | return new Right<>(f.apply(value)); 21 | } 22 | 23 | @SuppressWarnings("unchecked") 24 | @Override 25 | public Either mapLeft(Function f) { 26 | return (Either) this; 27 | } 28 | 29 | @Override 30 | public Either flatMap(Function> f) { 31 | return f.apply(value); 32 | } 33 | 34 | @SuppressWarnings("unchecked") 35 | @Override 36 | public Either flatMapLeft(Function> f) { 37 | return (Either) this; 38 | } 39 | 40 | @SuppressWarnings("unchecked") 41 | @Override 42 | public Either flatten() { 43 | return (Either) value; 44 | } 45 | 46 | @Override 47 | public Either forEachLeft(Consumer f) { 48 | return this; 49 | } 50 | 51 | @Override 52 | public Either forEach(Consumer f) { 53 | f.accept(value); 54 | return this; 55 | } 56 | 57 | @Override 58 | public R orElse(R value) { 59 | return this.value; 60 | } 61 | 62 | @Override 63 | public Optional left() { 64 | return Optional.empty(); 65 | } 66 | 67 | @Override 68 | public Optional right() { 69 | return Optional.of(value); 70 | } 71 | 72 | @Override 73 | public R get() { 74 | return value; 75 | } 76 | 77 | @Override 78 | public String toString() { 79 | return "Right(" + value + ")"; 80 | } 81 | 82 | @Override 83 | public boolean equals(Object value) { 84 | if (value == this) { 85 | return true; 86 | } 87 | if (value instanceof Right) { 88 | @SuppressWarnings("unchecked") 89 | Right valueRight = (Right) value; 90 | return this.value.equals(valueRight.right().get()); 91 | } 92 | return false; 93 | } 94 | 95 | @Override 96 | public int hashCode() { 97 | return value.hashCode(); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/log/Logger.java: -------------------------------------------------------------------------------- 1 | package log; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.InputStreamReader; 5 | import java.util.function.Function; 6 | 7 | class Logger { 8 | private static String loggedClassName; 9 | private final Class currentClass; 10 | 11 | public static void config(final String[] args) { 12 | if (args.length >= 1) { 13 | loggedClassName = args[0]; 14 | } 15 | } 16 | 17 | public static Logger getLogger(final Class loggedClass) { 18 | return new Logger(loggedClass); 19 | } 20 | 21 | private Logger(final Class currentClass) { 22 | this.currentClass = currentClass; 23 | } 24 | 25 | public boolean isDebugEnabled() { 26 | boolean isEnabled = currentClass.getName().equals(loggedClassName); 27 | debugInternal("isDebugEnabled", "" + isEnabled); 28 | return currentClass.getName().equals(loggedClassName); 29 | } 30 | 31 | public void debug(final String method, final String message) { 32 | if (isDebugEnabled()) { 33 | debugInternal(method, message); 34 | } 35 | } 36 | 37 | private void debugInternal(final String method, final String message) { 38 | System.err.println("[" + currentClass.getName() 39 | + "." + method + "] " + message); 40 | } 41 | 42 | public static Function makeLogged( 43 | final Class loggedClass, 44 | final String method, 45 | final Function fn) 46 | { 47 | final Logger logger = Logger.getLogger(loggedClass); 48 | if (logger.isDebugEnabled()) { 49 | return new Function() { 50 | public O apply(final I input) { 51 | StringBuilder sb = new StringBuilder(); 52 | 53 | final long start = System.nanoTime(); 54 | sb.append("Input: ").append(input); 55 | try { 56 | final O output = fn.apply(input); 57 | sb.append(". Output: ").append(output); 58 | return output; 59 | } catch(Exception e) { 60 | sb.append(". Exception: ").append(e.getMessage()); 61 | throw e; 62 | } finally { 63 | final long end = System.nanoTime(); 64 | sb.append(". Running time: ") 65 | .append((end - start)) 66 | .append(" ns"); 67 | logger.debugInternal(method, sb.toString()); 68 | } 69 | } 70 | }; 71 | } else { 72 | return fn; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/exception/Left.java: -------------------------------------------------------------------------------- 1 | package exception; 2 | 3 | import java.util.NoSuchElementException; 4 | import java.util.Optional; 5 | import java.util.function.Consumer; 6 | import java.util.function.Function; 7 | 8 | public final class Left implements Either { 9 | private final L value; 10 | 11 | private Left(L l) { 12 | value = l; 13 | } 14 | 15 | public static Left of(L l) { 16 | return new Left<>(l); 17 | } 18 | 19 | @SuppressWarnings("unchecked") 20 | @Override 21 | public Either map(Function f) { 22 | return (Either) this; 23 | } 24 | 25 | @Override 26 | public Either mapLeft(Function f) { 27 | return new Left<>(f.apply(value)); 28 | } 29 | 30 | @SuppressWarnings("unchecked") 31 | @Override 32 | public Either flatMap(Function> f) { 33 | return (Either) this; 34 | } 35 | 36 | @Override 37 | public Either flatMapLeft(Function> f) { 38 | return f.apply(value); 39 | } 40 | 41 | @SuppressWarnings("unchecked") 42 | @Override 43 | public Either flatten() { 44 | return (Either) this; 45 | } 46 | 47 | @Override 48 | public Either forEach(Consumer f) { 49 | return this; 50 | } 51 | 52 | @Override 53 | public Either forEachLeft(Consumer f) { 54 | f.accept(value); 55 | return this; 56 | } 57 | 58 | @Override 59 | public R orElse(R value) { 60 | return value; 61 | } 62 | 63 | @Override 64 | public Optional left() { 65 | return Optional.of(value); 66 | } 67 | 68 | @Override 69 | public Optional right() { 70 | return Optional.empty(); 71 | } 72 | 73 | @Override 74 | public R get() { 75 | throw new NoSuchElementException(); 76 | } 77 | 78 | @Override 79 | public String toString() { 80 | return "Left(" + value + ")"; 81 | } 82 | 83 | @Override 84 | public boolean equals(Object value) { 85 | if (value == this) { 86 | return true; 87 | } 88 | if (value instanceof Left) { 89 | @SuppressWarnings("unchecked") 90 | Left valueLeft = (Left) value; 91 | return this.value.equals(valueLeft.left().get()); 92 | } 93 | return false; 94 | } 95 | 96 | @Override 97 | public int hashCode() { 98 | return value.hashCode(); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/scala/ddd/ShoppingCartApp.scala: -------------------------------------------------------------------------------- 1 | package ddd 2 | 3 | import ErrorAPI._ 4 | import Types._ 5 | import ShoppingCartAPI._ 6 | import ShoppingCart._ 7 | import ShoppingCartConfig._ 8 | import PaymentAPI._ 9 | import Directives._ 10 | 11 | import akka.actor.ActorSystem 12 | import akka.http.scaladsl.Http 13 | import akka.http.scaladsl.model._ 14 | import akka.http.scaladsl.model.HttpMethods._ 15 | import akka.http.scaladsl.server.Directives._ 16 | import akka.http.scaladsl.model._ 17 | import akka.http.scaladsl.model.headers.{Accept, Link, LinkParams, LinkValue} 18 | import akka.http.scaladsl.model.StatusCodes._ 19 | import akka.stream.ActorMaterializer 20 | import java.util.UUID 21 | import scala.io.StdIn 22 | 23 | object ShoppingCartApp extends App { 24 | implicit val system = ActorSystem("ShoppingCart") 25 | implicit val materializer = ActorMaterializer() 26 | implicit val executionContext = system.dispatcher 27 | 28 | var appState = setState(EmptyCart) 29 | var events: List[Event] = List() 30 | 31 | val route = 32 | path("") { 33 | respondCapabilities(appState.uris) { 34 | headComplete 35 | } 36 | } ~ 37 | path("replay") { 38 | val replayedState = events.foldLeft[State](EmptyCart) { 39 | (state, event) => eventHandler(state, event).right.get 40 | } 41 | complete(s"ReplayedState: $replayedState") 42 | } ~ 43 | path(Segment) { uri => 44 | post { 45 | entity(as[String]) { data => 46 | if (appState.uris contains uri) { 47 | val command = SampleData.convertToCommand(data) 48 | val rel = appState.uris(uri) 49 | val capability = appState.capabilities(rel) orElse 50 | wrongCapability(appState.state) 51 | val stateResultEither = capability(command) 52 | stateResultEither match { 53 | case Right(stateResult) => 54 | appState = setState(stateResult.state) 55 | events = events ++ stateResult.events 56 | respondCapabilities(appState.uris) { 57 | complete(s"Events: $events\nResult: $stateResult") 58 | } 59 | case Left(error) => 60 | respondCapabilities(appState.uris) { 61 | complete((BadRequest, ErrorMessages.toMessage(error))) 62 | } 63 | } 64 | } else reject 65 | } 66 | } 67 | } 68 | 69 | val bindingFuture = Http().bindAndHandle(route, "localhost", 9000) 70 | 71 | println(s"Server online at http://localhost:9000/\nPress RETURN to stop...") 72 | StdIn.readLine() 73 | bindingFuture 74 | .flatMap(_.unbind()) 75 | .onComplete(_ => system.terminate()) 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/fpjdbc/FpJdbc.java: -------------------------------------------------------------------------------- 1 | package fpjdbc; 2 | 3 | import java.util.Arrays; 4 | 5 | import exception.Either; 6 | import exception.Failure; 7 | 8 | final class FpJdbc { 9 | public static void main(String[] args) { 10 | System.out.println("FP JDBC"); 11 | 12 | final Either repositoryOrFailure = Repository.load( 13 | "org.h2.Driver", 14 | "jdbc:h2:mem:test", 15 | "SELECT 1" 16 | ).forEach(repository -> { 17 | fill(repository); 18 | 19 | final Either personOrFailure1 = 20 | repository.querySingle( 21 | "SELECT id, name, age FROM person WHERE id = 2 and age < 30", 22 | rs -> new Person( 23 | rs.getInt("id"), 24 | rs.getString("name"), 25 | rs.getInt("age") 26 | ) 27 | ); 28 | 29 | System.out.println("personOrFailure1: " + personOrFailure1); 30 | 31 | final Either personOrFailure2 = 32 | repository.querySingleAs( 33 | Person.class, 34 | "SELECT id, name, age FROM person p WHERE id = ? and age < ?", 35 | 2, 30 36 | ); 37 | 38 | System.out.println("personOrFailure2: " + personOrFailure2); 39 | 40 | final Record record = Record.build(builder -> builder 41 | .field("id", 3) 42 | .field("name", "Jake Doe") 43 | .field("age", 13) 44 | ); 45 | System.out.println("Record: " + record); 46 | 47 | final Either personOrFailure3 = 48 | record.as(Person.class); 49 | System.out.println("personOrFailure3: " + personOrFailure3); 50 | 51 | repository.close(); 52 | }); 53 | 54 | System.out.println(repositoryOrFailure); 55 | } 56 | 57 | private static void fill(Repository repository) { 58 | Arrays.asList( 59 | "CREATE TABLE person(id INT, name VARCHAR(30), age INT)", 60 | "INSERT INTO person VALUES(1, 'John Doe', 32)", 61 | "INSERT INTO person VALUES(2, 'Jane Doe', 28)" 62 | ).stream().forEach(repository::update); 63 | } 64 | 65 | public static class Person { 66 | private final int id; 67 | private final String name; 68 | private final int age; 69 | 70 | Person(final int id, final String name, final int age) { 71 | this.id = id; 72 | this.name = name; 73 | this.age = age; 74 | } 75 | 76 | public String toString() { 77 | return "Person(" + id + ", " + name + ", " + age + ")"; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/scala/independence/ResultOps.scala: -------------------------------------------------------------------------------- 1 | package independence 2 | 3 | object Level extends Enumeration { 4 | type Level = Value 5 | val TRACE, DEBUG, INFO, WARN, ERROR, FATAL = Value 6 | } 7 | import Level._ 8 | 9 | class Log(val level: Level, val place: String, val message: () => String) 10 | extends Information 11 | { 12 | override def toString = s"Log($level, $place)" 13 | 14 | def canEqual(a: Any) = a.isInstanceOf[Log] 15 | 16 | override def equals(that: Any): Boolean = 17 | that match { 18 | case that: Log => 19 | that.canEqual(this) && this.hashCode == that.hashCode 20 | case _ => false 21 | } 22 | 23 | override def hashCode:Int = { 24 | level.hashCode + place.hashCode 25 | } 26 | } 27 | 28 | object Log { 29 | def apply(level: Level, place: String, message: => String) = { 30 | lazy val msg = message 31 | new Log(level, place, () => msg) 32 | } 33 | 34 | def unapply(log: Log): Option[(Level, String)] = { 35 | Some((log.level, log.place)) 36 | } 37 | } 38 | 39 | object LogResult { 40 | def apply[T](value: T, level: Level, place: String, message: => String) = { 41 | GoodResult(value, List(new Log(level, place, () => message))) 42 | } 43 | } 44 | 45 | trait DBStatement extends Information 46 | 47 | case class DBPersist[T](entity: T) extends DBStatement 48 | case class DBMerge[T](entity: T) extends DBStatement 49 | 50 | case class Email(to: String, subject: String, message: String) 51 | extends Information 52 | 53 | case class Sms(to: String, subject: String, message: String) 54 | extends Information 55 | 56 | case class Validation(level: Symbol, field: String, message: String) 57 | extends Information 58 | 59 | case class Validator[T](predicate: T => Boolean, cause: String) 60 | 61 | case class FatalValidation(level: Level = ERROR) extends Fault 62 | 63 | object ResultOps { 64 | import Result._ 65 | 66 | def log[T](level: Level, place: String, result: Result[T]) = { 67 | lazy val message = result match { 68 | case GoodResult(v, i) => v.toString 69 | case BadResult(c, i) => c.toString 70 | } 71 | result.addInformation(Log(level, place, message)) 72 | } 73 | 74 | def hasFatal[T](result: Result[T]): Result[T] = { 75 | val fatal = result.infos find { 76 | case v @ Validation(level, field, msg) if level == 'Fatal => true 77 | case _ => false 78 | } 79 | fatal match { 80 | case Some(_) => BadResult(FatalValidation()) 81 | case _ => result 82 | } 83 | } 84 | 85 | def validateField[T]( 86 | value: T, 87 | field: String, 88 | validators: (Symbol, Validator[T])*): Result[Option[T]] = 89 | { 90 | validators.find { 91 | case (level, validator) => !validator.predicate(value) 92 | } map { 93 | case (l, v) => validate(value, v.predicate, Validation(l, field, v.cause)) 94 | } getOrElse GoodResult(Some(value)) 95 | } 96 | } 97 | 98 | -------------------------------------------------------------------------------- /src/main/java/threads/README.md: -------------------------------------------------------------------------------- 1 | # Szálak 2 | 3 | A következőkben a szálakról (Thread), szálak kezeléséről és a szálkészletekről (ThreadPool) lesz szó. 4 | Elsősorban a JVM alatti szálakról lesz szó, de sok a hasonlóság más rendszerekben alkalmazottakkal. 5 | 6 | ## Mikor használjunk szálakat? 7 | 8 | 1. Ha fontos a teljesítmény és szeretnénk kihasználni a mai sok magos processzorokban rejlő lehetőségeket. 9 | 2. Ha konkurrensen akarunk kezelni erőforrásokat. 10 | 3. Ha egyik sem illik ránk, de olyan keretrendszer (pl. alkalmazásszerver) alá fejlesztünk, ami több szálat használ, akkor akarva akaratlanul is több szálat fogunk használni. 11 | 12 | ## Mikor futtassunk több szálat? 13 | 14 | ### Blokkoló utasítások (I/O) 15 | 16 | Ha egy feladatot (task) futtatunk, akkor időnként előfordul, hogy blokkoló utasítást hajtunk végre. Ilyen például a legtöbb adatkezelés vagy más I/O utasítás. Ilyenkor az adott szál végrehajtása blokkolódik, gyakorlatilag semmit sem fog csinálni a programunk a válasz megérkezéséig. Ilyenkor célszerű egy másik szálon más feladatot végeztetni. 17 | 18 | ### Több mag esetén 19 | 20 | Ha több mag van a processzorunkban, akkor érdemes legalább annyi szálon futtatni a feladatokat, amennyi mag van a processzorunkban. 21 | 22 | ## Mennyi szálat futtassunk? 23 | 24 | Régen az volt az arany szabály, hogy ahány mag van a processzorunkban annyit plusz egy vagy kettőt. Ezt az elméletet már túlhaladtuk. 25 | 26 | 1. Ha CPU intenzív feladatot futtatunk, azokból pont annyit érdemes, amennyi mag van a processzorunkban. Ha kevesebbet futtatunk, akkor nincs kihasználva processzor, ha többet, akkor meg a konteksztus váltások miatt lassabb lesz a futtatás. 27 | 2. Ha blokkoló feladatot futtatunk, azokhoz plusz egy szálat érdemes létrehozni. Amíg blokkol, addig a többi szálat szépen futtathatja. Több száz blokkoló utasítás egymás melletti futtatása esetén akár több százat is érdemes. 28 | 3. Ha nem blokkoló I/O (NIO) válaszát kérdezgetjük le, erre és csak erre a kis időre elég pontosan egy magas prioritású szál. Ezen az egy szálon az összes ilyen aszinkron I/O kérdezgethető (polling). 29 | 30 | ## Hogyan érdemes futtatni a szálakat? 31 | 32 | Érdemes kimenni a szálstrandra és igénybe venni a szálmedencéket! ;-) 33 | 34 | Erre a legjobb a szálkészleteket (ThreadPools) igénybe venni. 35 | Alapvetően két fajta szálkészletet különböztetünk meg: 36 | 1. Maximálisan meghatározott elemszámú. (pl. 1 vagy ahány magunk van). 37 | 2. Korlátlan elemszámú. 38 | 39 | Ha egy szálkészleten keresztül futtatunk egy feladatot, akkor 40 | 1. ha nincs hozzá felhasználható szál, akkor készít egyet és berakja a szálkészletbe, 41 | 2. ha van, akkor kivesz egyet 42 | 43 | és azt használja. 44 | 45 | Az adott feladat végrehajtása után visszateszi a szálat a készletbe, így a már felkonfiguráltat gyorsan igénybe tudja venni. Meg lehet határozni egy időtartamot is, ameddig ha nincs használva, akkor szüntesse meg az adott szálat. 46 | 47 | ## Milyen szálkészletet érdemes használni? 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/main/scala/log/Analyzer.scala: -------------------------------------------------------------------------------- 1 | package log.anal 2 | 3 | import java.io._ 4 | import monix.eval.Task 5 | import monix.execution._ 6 | import monix.execution.atomic._ 7 | import monix.execution.Scheduler.Implicits.global 8 | import monix.reactive._ 9 | import monix.reactive.OverflowStrategy._ 10 | import monix.reactive.observers._ 11 | import monix.reactive.subjects._ 12 | import scala.concurrent.duration._ 13 | import scala.concurrent._ 14 | 15 | object Analyzer extends App { 16 | def aggregatePipe[I,O](s: O)(fn: (O, I) => Either[O,O]) = new Pipe[I,O] { 17 | override def unicast: (Observer[I], Observable[O]) = { 18 | val (in, out) = 19 | Observable.multicast[O](MulticastStrategy.Publish, Unbounded)(global) 20 | 21 | var state: O = s 22 | 23 | val observer = new Observer[I] { 24 | override def onError(ex: Throwable) = {} 25 | override def onComplete() = { } 26 | override def onNext(elem: I) = { 27 | fn(state, elem) match { 28 | case Left(o) => 29 | state = o 30 | Ack.Continue 31 | case Right(o) => 32 | val ack = in.onNext(state) 33 | state = o 34 | ack 35 | } 36 | } 37 | } 38 | 39 | (observer, out) 40 | } 41 | } 42 | 43 | //def parseLine(line: String): String = { 44 | //val parts = line.split("\\s+") 45 | //val items = parts(0).split("\\|") 46 | //if (items.length > 5) items(5) + " " + line else line 47 | //} 48 | 49 | //val file = new File("/home/kalman/Nyilvános/server.log_2018-01-11T08-07-54") 50 | //val reader = new BufferedReader(new FileReader(file)) 51 | 52 | //val lines = Observable.fromLinesReader(reader) 53 | //.filter(_.trim.length != 0) 54 | //.map(parseLine) 55 | //.pipeThrough(new AggregatePipe("", (acc: String, line: String) => 56 | //if (line.startsWith("_ThreadID")) Right(line) else Left(acc + line) 57 | //)) 58 | //lines.foreach(println) 59 | 60 | val consumer: String => Long => Future[Ack] = title => value => Future { 61 | val max = Math.max(100 - 3 * value.toInt, 20) 62 | val wait = scala.util.Random.nextInt(max) * 10 63 | println(s"$title($wait): $value") 64 | Thread.sleep(wait) 65 | Ack.Continue 66 | } 67 | 68 | val kafka = Observable.interval(200.milliseconds) 69 | //.pipeThrough( 70 | //aggregatePipe(0L) { (acc: Long, value: Long) => 71 | //if (value % 5 == 0) Right(value) else Left(value + acc) 72 | //}) 73 | .pipeThrough( 74 | aggregatePipe(List.empty[Long]) { (acc: List[Long], value: Long) => 75 | if (value % 5 == 0) Right(List(value)) else Left(value :: acc) 76 | }) 77 | 78 | //kafka.asyncBoundary(DropNew(20000)).subscribe(consumer("First")) 79 | //kafka.asyncBoundary(DropNew(20000)).subscribe(consumer("Second")) 80 | //kafka.asyncBoundary(DropNew(20000)).subscribe(consumer("Third")) 81 | kafka.foreach(println) 82 | 83 | Thread.sleep(10000) 84 | } 85 | -------------------------------------------------------------------------------- /src/main/scala/independence/Logger.scala: -------------------------------------------------------------------------------- 1 | package independence 2 | 3 | import Level._ 4 | 5 | object Logger { 6 | def asLog[I, O](logger: Logger, level: Level) 7 | (fn: => O): Result[O] = 8 | { 9 | if (logger.isLevelEnabled(level)) { 10 | val sb = new StringBuilder 11 | val start = System.nanoTime 12 | val throwable = new Throwable() 13 | val stackTrace = throwable.getStackTrace()(2) 14 | val place = stackTrace.getFileName + ":" + stackTrace.getLineNumber 15 | try { 16 | val output = fn 17 | sb.append(". Output: ").append(output) 18 | val end = System.nanoTime 19 | sb.append(". Running time: ").append(end - start).append(" ns") 20 | GoodResult(output, List(Log(level, place, sb.toString))) 21 | } catch { 22 | case e: RuntimeException => 23 | sb.append(". Exception: ").append(e.getMessage) 24 | val end = System.nanoTime 25 | sb.append(". Running time: ").append(end - start).append(" ns") 26 | BadResult(ExceptionError(e), List(Log(FATAL, place, sb.toString))) 27 | case e: Exception => 28 | sb.append(". Exception: ").append(e.getMessage) 29 | val end = System.nanoTime 30 | sb.append(". Running time: ").append(end - start).append(" ns") 31 | BadResult(ExceptionError(e), List(Log(ERROR, place, sb.toString))) 32 | } 33 | } else { 34 | GoodResult(fn) 35 | } 36 | } 37 | 38 | def makeLog[I, O](logger: Logger, level: Level) 39 | (fn: I => O): I => Result[O] = 40 | { 41 | if (logger.isLevelEnabled(level)) { 42 | input: I => 43 | val sb = new StringBuilder 44 | val start = System.nanoTime 45 | val throwable = new Throwable() 46 | val stackTrace = throwable.getStackTrace()(2) 47 | val place = stackTrace.getFileName + ":" + stackTrace.getLineNumber 48 | try { 49 | sb.append("Input: ").append(input) 50 | val output = fn(input) 51 | sb.append(". Output: ").append(output) 52 | val end = System.nanoTime 53 | sb.append(". Running time: ").append(end - start).append(" ns") 54 | GoodResult(output, List(Log(level, place, sb.toString))) 55 | } catch { 56 | case e: RuntimeException => 57 | sb.append(". Exception: ").append(e.getMessage) 58 | val end = System.nanoTime 59 | sb.append(". Running time: ").append(end - start).append(" ns") 60 | BadResult(ExceptionError(e), List(Log(FATAL, place, sb.toString))) 61 | case e: Exception => 62 | sb.append(". Exception: ").append(e.getMessage) 63 | val end = System.nanoTime 64 | sb.append(". Running time: ").append(end - start).append(" ns") 65 | BadResult(ExceptionError(e), List(Log(ERROR, place, sb.toString))) 66 | } 67 | } else { 68 | input: I => GoodResult(fn(input)) 69 | } 70 | } 71 | } 72 | 73 | trait Logger { 74 | def isLevelEnabled(level: Level): Boolean 75 | } 76 | 77 | -------------------------------------------------------------------------------- /src/main/scala/ddd/ShoppingCart.scala: -------------------------------------------------------------------------------- 1 | package ddd 2 | 3 | import Types._ 4 | import ShoppingCartAPI._ 5 | import ErrorAPI._ 6 | import PaymentAPI._ 7 | 8 | import scala.util.Random 9 | 10 | object ShoppingCart { 11 | val addToEmpty: AddToEmpty = { 12 | case (EmptyCart, AddItem(item)) => 13 | Right(List(FirstItemAdded(item))) 14 | } 15 | 16 | val addToActive: AddToActive = { 17 | case (ActiveCart(unpaidItems), AddItem(item)) => 18 | if (unpaidItems.contains(item)) { 19 | Left(ItemAlreadyAdded(item)) 20 | } else { 21 | Right(List(NextItemAdded(item))) 22 | } 23 | } 24 | 25 | val removeFromActive: RemoveFromActive = { 26 | case (ActiveCart(unpaidItems), RemoveItem(item)) => 27 | if (!unpaidItems.contains(item)) { 28 | Left(NoItemInCart(item)) 29 | } else if (unpaidItems.size > 1) { 30 | Right(List(AnItemRemoved(item))) 31 | } else { 32 | Right(List(LastItemRemoved(item))) 33 | } 34 | } 35 | 36 | val payActive: PayActive = { 37 | case (ActiveCart(unpaidItems), Pay(payment)) => 38 | payment match { 39 | case card: Card if (Random.nextInt(100) < 30) => 40 | Left(CardProcessFailure(card)) 41 | case _ => 42 | Right(List(Paid(payment))) 43 | } 44 | } 45 | 46 | val handleFirstItemAdded: HandleFirstItemAdded = { 47 | case (EmptyCart, FirstItemAdded(item)) => 48 | Right(ActiveCart(List(item))) 49 | } 50 | 51 | val handleNextItemAdded: HandleNextItemAdded = { 52 | case (ActiveCart(unpaidItems), NextItemAdded(item)) => 53 | Right(ActiveCart(unpaidItems :+ item)) 54 | } 55 | 56 | val handleAnItemRemoved: HandleAnItemRemoved = { 57 | case (ActiveCart(unpaidItems), AnItemRemoved(item)) => 58 | Right(ActiveCart(unpaidItems filter (i => i != item))) 59 | } 60 | 61 | val handleLastItemRemoved: HandleLastItemRemoved = { 62 | case (ActiveCart(unpaidItems), LastItemRemoved(item)) => 63 | Right(EmptyCart) 64 | } 65 | 66 | val handlePaid: HandlePaid = { 67 | case (ActiveCart(unpaidItems), Paid(payment)) => 68 | Right(PaidCart(unpaidItems, payment)) 69 | } 70 | 71 | val getEmptyCartCaps: GetCapabilities = { 72 | case state @ EmptyCart => 73 | Map("AddItem" -> 74 | createCapability(state, addToEmpty, handleFirstItemAdded)) 75 | } 76 | 77 | val getActiveCartCaps: GetCapabilities = { 78 | case state @ ActiveCart(unpaidItems) => 79 | Map( 80 | "AddItem" -> 81 | createCapability(state, addToActive, handleNextItemAdded), 82 | "Pay" -> createCapability(state, payActive, handlePaid) 83 | ) ++ 84 | unpaidItems.map { item => 85 | "RemoveItem_" + item.id -> createCapability( 86 | state, 87 | RemoveItem(item), 88 | removeFromActive, 89 | handleAnItemRemoved orElse handleLastItemRemoved 90 | ) 91 | }.toMap 92 | } 93 | 94 | val getPaidCartCaps: GetCapabilities = { 95 | case PaidCart(state, payment) => 96 | Map() 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/scala/com/example/Symbolic.scala: -------------------------------------------------------------------------------- 1 | package com.example 2 | 3 | sealed trait Suit { def num: Int } 4 | 5 | case object Spade extends Suit { def num = 4 } 6 | case object Heart extends Suit { def num = 3 } 7 | case object Diamond extends Suit { def num = 2 } 8 | case object Club extends Suit { def num = 1 } 9 | 10 | object Suit { 11 | def toString(suit: Suit) = suit match { 12 | case Spade => "♠" 13 | case Club => "♣" 14 | case Heart => "♥" 15 | case Diamond => "♦" 16 | } 17 | } 18 | 19 | sealed trait CardValue { 20 | def num: Int 21 | 22 | def suit(suit: Suit) = Card(this, suit) 23 | } 24 | 25 | case class CardNum(num: Int) extends CardValue 26 | 27 | case object CardAce extends CardValue { def num = 1 } 28 | case object CardKing extends CardValue { def num = 13 } 29 | case object CardQueen extends CardValue { def num = 12 } 30 | case object CardJack extends CardValue { def num = 11 } 31 | 32 | object CardValue { 33 | def toString(cardValue: CardValue) = cardValue match { 34 | case CardAce => "A" 35 | case CardKing => "K" 36 | case CardQueen => "Q" 37 | case CardJack => "J" 38 | case _ => cardValue.num.toString 39 | } 40 | } 41 | 42 | case class Card(cardValue: CardValue, suit: Suit) extends Ordered[Card] { 43 | override def toString = 44 | (CardValue toString cardValue) + (Suit toString suit) 45 | 46 | import scala.math.Ordered.orderingToOrdered 47 | def compare(card: Card): Int = 48 | (suit.num, cardValue.num) compare (card.suit.num, card.cardValue.num) 49 | 50 | def plus(card: Card) = Cards(List(this, card)) 51 | } 52 | 53 | case class Cards(cards: List[Card]) { 54 | def plus(card: Card) = copy(cards = cards ++ List(card)) 55 | def and(card: Card) = cards ++ List(card) 56 | } 57 | 58 | object Deck { 59 | type Deck = List[Card] 60 | 61 | val random = new scala.util.Random 62 | 63 | def apply(card: Card*) = List(card :_*) 64 | def shuffle(deck: Deck) = deck.sortWith { (_, _) => random.nextBoolean } 65 | 66 | def make(card: Card) = Cards(List(card)) 67 | } 68 | 69 | object Symbolic { 70 | def main(args: Array[String]): Unit = { 71 | import Deck._ 72 | 73 | val deck1 = Deck( 74 | Card(CardKing, Spade), 75 | Card(CardNum(10), Heart), 76 | Card(CardNum(3), Club), 77 | Card(CardQueen, Club), 78 | Card(CardNum(7), Club), 79 | Card(CardNum(5), Club), 80 | Card(CardJack, Diamond) 81 | ) 82 | 83 | val deck = 84 | (CardKing suit Spade) plus 85 | (CardNum(10) suit Heart) plus 86 | (CardNum(3) suit Club) plus 87 | (CardQueen suit Club) plus 88 | (CardNum(7) suit Club) plus 89 | (CardNum(5) suit Club) and 90 | (CardJack suit Diamond) 91 | 92 | println(s"Shuffled deck: ${ Deck shuffle deck }") 93 | println(s"Sorted deck: ${ deck.sorted }") 94 | println(s"Face cards: ${ deck filter (_.cardValue.num >= 11) }") 95 | println(s"King cards: ${ deck filter (_.cardValue == CardKing) }") 96 | println(s"Simple cards: ${ deck.filter((2 to 10) contains _.cardValue.num) }") 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/scala/shape/ShapeSimple.scala: -------------------------------------------------------------------------------- 1 | package shape 2 | 3 | object ShapeSimple { 4 | case class Point(x: Int, y: Int) 5 | 6 | case class Shape(form: Symbol, radius: Int = 0, 7 | width: Int = 0, height: Int = 0, 8 | smoothing: Int = 0) 9 | 10 | val createCircle = (radius: Int) => 11 | Shape('Circle, radius=radius) 12 | val createRectangle = (width: Int, height: Int) => 13 | Shape('Rectangle, width=width, height=height) 14 | val createEllipse = (width: Int, height: Int) => 15 | Shape('Ellipse, width=width, height=height) 16 | val createRoundedRectangle = (width: Int, height: Int, smoothing: Int) => 17 | Shape('Rectangle, width=width, height=height, smoothing=smoothing) 18 | 19 | val draw = (point: Point, shape: Shape) => shape match { 20 | case Shape('Circle, radius, _, _, _) => 21 | drawCircle(point, radius) 22 | case Shape('Rectangle, _, width, height, 0) => 23 | drawRectangle(point, width, height) 24 | case Shape('Rectangle, _, _, _, 100) | Shape('Ellipse, _, _, _, _) => 25 | drawEllipse(point, shape.width, shape.height) 26 | case Shape('Rectangle, _, width, height, smoothing) => 27 | drawRoundedRectangle(point, width, height, smoothing) 28 | } 29 | 30 | val drawCircle = (point: Point, radius: Int) => 31 | s"Drawing circle at (${point.x}, ${point.y}) Radius: $radius" 32 | 33 | val drawRectangle = (point: Point, width: Int, height: Int) => 34 | s"Drawing rectangle at (${point.x}, ${point.y}) Width $width, Height $height" 35 | 36 | val drawEllipse = (point: Point, width: Int, height: Int) => 37 | s"Drawing ellipse at (${point.x}, ${point.y}) Width $width, Height $height" 38 | 39 | val drawRoundedRectangle = (point: Point, width: Int, height: Int, smoothing: Int) => 40 | s"Drawing rounded rectangle at (${point.x}, ${point.y}) " + 41 | s"Width $width, Height $height, Smoothing $smoothing" 42 | 43 | val sideCount = (shape: Shape) => shape match { 44 | case Shape('Circle, _, _, _, _) | Shape('Ellipse, _, _, _, _) => 1 45 | case Shape('Rectangle, _, _, _, smoothing) if smoothing > 0 => 1 46 | case Shape('Rectangle, _, _, _, _) => 4 47 | } 48 | 49 | val removeSmoothing = (shape: Shape) => shape.copy(smoothing=0) 50 | 51 | val reform: (Shape, Symbol) => Option[Shape] = (shape, to) => (shape.form, to) match { 52 | case (a, b) if a == b => 53 | Some(shape) 54 | case ('Circle, 'Ellipse) => 55 | Some(Shape('Ellipse, width=shape.radius*2, height=shape.radius*2)) 56 | case ('Ellipse, 'Rectangle) => 57 | Some(shape.copy(form='Rectangle, smoothing=100)) 58 | case ('Circle, 'Rectangle) => 59 | reform(shape, 'Ellipse) flatMap { ellipse => reform(ellipse, 'Rectangle) } 60 | case ('Ellipse, 'Circle) if shape.width == shape.height => 61 | Some(Shape('Circle, radius= shape.width / 2)) 62 | case ('Rectangle, 'Ellipse) if shape.smoothing == 100 => 63 | Some(shape.copy(form='Ellipse, smoothing=0)) 64 | case ('Rectangle, 'Circle) => 65 | reform(shape, 'Ellipse) flatMap { ellipse => reform(ellipse, 'Circle) } 66 | case _ => 67 | None 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/test/scala/nomock/app/UserCreationSpec.scala: -------------------------------------------------------------------------------- 1 | package nomock.app 2 | 3 | import org.scalatest._ 4 | 5 | class UserCreationSpec extends FunSpec with Matchers { 6 | import nomock.user.API._ 7 | import nomock.user.Infra._ 8 | import nomock.user.Check._ 9 | 10 | val expectedUserName = "Teszt Elek" 11 | val expectedPassword = "t1tk0s" 12 | val expectedIdGood = verifiedId + "1" 13 | val expectedIdBad = "1" 14 | val expectedSavedUser = createTestSavedUser( 15 | expectedUserName, 16 | expectedPassword, 17 | expectedIdGood 18 | ) 19 | 20 | describe("UserCreation.registerUser") { 21 | describe("when everything is ok") { 22 | it("should be savedUser response") { 23 | val userService = new TestUserService() 24 | val newUser = NewUser(expectedUserName, expectedPassword, expectedIdGood) 25 | val savedUserEither = UserCreation.registerUser(userService)(newUser) 26 | savedUserEither shouldBe Right(expectedSavedUser) 27 | } 28 | } 29 | describe("when login information is wrong") { 30 | it("username is empty") { 31 | val userService = new TestUserService() 32 | val newUser = NewUser("", expectedPassword, expectedIdGood) 33 | val savedUserEither = UserCreation.registerUser(userService)(newUser) 34 | savedUserEither shouldBe Left(invalidLoginInfo) 35 | } 36 | it("password is empty") { 37 | val userService = new TestUserService() 38 | val newUser = NewUser(expectedUserName, "", expectedIdGood) 39 | val savedUserEither = UserCreation.registerUser(userService)(newUser) 40 | savedUserEither shouldBe Left(invalidLoginInfo) 41 | } 42 | } 43 | describe("when fail the saving") { 44 | it("should be optimistic lock failure") { 45 | val userService = new TestUserService() 46 | val newUser = NewUser( 47 | expectedUserName, 48 | expectedPassword, 49 | expectedIdGood + savingFailure 50 | ) 51 | val savedUserEither = UserCreation.registerUser(userService)(newUser) 52 | savedUserEither shouldBe Left(optimisticLockFailure) 53 | } 54 | } 55 | describe("when username is exists") { 56 | it("should be username is not valid failure") { 57 | val userService = new TestUserService() 58 | val newUser = NewUser( 59 | expectedUserName, 60 | expectedPassword, 61 | expectedIdGood 62 | ) 63 | val savedUserEither = UserCreation.registerUser(userService)(newUser) 64 | savedUserEither shouldBe Right(expectedSavedUser) 65 | val secondSavedUserEither = UserCreation.registerUser(userService)(newUser) 66 | secondSavedUserEither shouldBe Left(usernameIsNotValid) 67 | } 68 | } 69 | describe("when id is bad") { 70 | it("should be wrong id message") { 71 | val userService = new TestUserService() 72 | val newUser = NewUser(expectedUserName, expectedPassword, expectedIdBad) 73 | val savedUserEither = UserCreation.registerUser(userService)(newUser) 74 | savedUserEither shouldBe Left(wrongId) 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/scala/plainFP/SimpleCommon.scala: -------------------------------------------------------------------------------- 1 | package plainFP 2 | 3 | import scala.language.higherKinds 4 | import scala.util.Random 5 | 6 | case class Config( 7 | host: String, 8 | port: Int, 9 | 10 | dbUrl: String, 11 | dbUser: String, 12 | dbPassword: String, 13 | 14 | smtpServer: String, 15 | smtpUser: String, 16 | smtpPassword: String, 17 | smtpFrom: String, 18 | 19 | personNameToUppercase: Boolean 20 | ) 21 | 22 | case class Person(id: String, name: String, email: String, age: Int) 23 | extends Entity 24 | 25 | case class Request(message: String) 26 | case class Response(message: String) 27 | 28 | class WebServer(host: String, port: Int) { 29 | var count = 0 30 | 31 | def close = { println("WebServer has closed") } 32 | 33 | def listen(callback: Request => Response): Boolean = { 34 | val request = Request(count.toString) 35 | println(s" => $request") 36 | val response = callback(Request(count.toString)) 37 | count = count + 1 38 | println(s"<= $response") 39 | count < 3 40 | } 41 | } 42 | 43 | trait Entity 44 | case object GetEntityFailed extends Failure 45 | case object UpdateEntityFailed extends Failure 46 | 47 | class DBServer(url: String, user: String, password: String) { 48 | def close = { println("DBServer has closed") } 49 | 50 | def getEntity[T <: Entity](id: String): Either[Failure, T] = { 51 | val entity = Person( 52 | id, 53 | "John Doe", 54 | "john@doe.com", 55 | 27 + Integer.parseInt(id) 56 | ).asInstanceOf[T] 57 | println(s"getEntity: id $id entity $entity") 58 | if (Random.nextInt(100) < 10) Left(GetEntityFailed) 59 | else Right(entity) 60 | } 61 | 62 | def updateEntity[T <: Entity](entity: T): Either[Failure, T] = { 63 | println(s"updateEntity: $entity") 64 | if (Random.nextInt(100) < 20) Left(UpdateEntityFailed) 65 | else Right(entity) 66 | } 67 | } 68 | 69 | case class Mail(from: String, to: String, subject: String, content: String) 70 | 71 | case object SendMailFailed extends Failure 72 | 73 | class SmtpServer(smtpServer: String, smtpUser: String, smtpPassword: String) { 74 | def close = { println("SmtpServer has closed") } 75 | 76 | def sendMail(mail: Mail): Either[Failure, Boolean] = { 77 | println(s"sendMail: $mail") 78 | if (Random.nextInt(100) < 20) Left(SendMailFailed) 79 | else Right(true) 80 | } 81 | } 82 | 83 | trait Failure 84 | 85 | object Common { 86 | def map[A, B](f: A => B): Either[Failure, A] => Either[Failure, B] = { 87 | x => x.map(f) 88 | } 89 | 90 | def flatMap[A, B](f: A => Either[Failure, B]): 91 | Either[Failure, A] => Either[Failure, B] = 92 | { 93 | x => x.flatMap(f) 94 | } 95 | 96 | //implicit class Function1Option2[-T1, R](f: T1 => Either[Failure, R]) 97 | //extends Function1[T1, Either[Failure, R]] 98 | //{ 99 | //def apply(x: T1): Either[Failure, R] = f(x) 100 | 101 | //def ~>[A](g: (R) => A): (T1) => Either[Failure, A] = x => apply(x).map(g) 102 | //def ~~>[A](g: (R) => Either[Failure, A]): (T1) => Either[Failure, A] = 103 | //x => apply(x).flatMap(g) 104 | //} 105 | } 106 | -------------------------------------------------------------------------------- /src/main/scala/com/example/OoDI.scala: -------------------------------------------------------------------------------- 1 | package com.example.oo 2 | 3 | case class Item(name: String, price: Double) 4 | case class OrderedItem(itemId: String, quantity: Double) 5 | case class Order(id: String, customer: String, items: List[OrderedItem]) 6 | 7 | object StoreAPI { 8 | case class OrderRequest(order: Order) 9 | case class OrderResponse(status: Either[String, Double]) 10 | 11 | type PlaceOrder = OrderRequest => OrderResponse 12 | 13 | trait IStore { 14 | def placeOrder: PlaceOrder 15 | } 16 | } 17 | 18 | object DatabaseAPI { 19 | type GetItem = String => Either[String, Item] 20 | type SaveOrder = Order => Either[String, Order] 21 | 22 | trait IDatabase { 23 | def getItem: GetItem 24 | def saveOrder: SaveOrder 25 | } 26 | } 27 | 28 | abstract class MemDatabase() extends DatabaseAPI.IDatabase { 29 | import DatabaseAPI._ 30 | 31 | val items = Map( 32 | "001" -> Item("Sword", 399.9), 33 | "002" -> Item("Chair", 24.9), 34 | "003" -> Item("Table", 99.9), 35 | "004" -> Item("Bed", 59.9) 36 | ) 37 | 38 | val getItem: GetItem = id => items get id match { 39 | case None => Left(s"Missing item $id!") 40 | case Some(item) => Right(item) 41 | } 42 | } 43 | 44 | case class MemDatabaseGood() extends MemDatabase { 45 | import DatabaseAPI._ 46 | 47 | val saveOrder: SaveOrder = order => Right(order) 48 | } 49 | 50 | case class MemDatabaseFailing() extends MemDatabase { 51 | import DatabaseAPI._ 52 | 53 | val saveOrder: SaveOrder = order => Left("No space on disk!") 54 | } 55 | 56 | case class Store(db: DatabaseAPI.IDatabase) extends StoreAPI.IStore { 57 | import DatabaseAPI._ 58 | import StoreAPI._ 59 | 60 | private def sequence[A, B](s: Seq[Either[A, B]]): Either[A, Seq[B]] = 61 | s.foldRight(Right(Nil): Either[A, List[B]]) { 62 | (e, acc) => for (xs <- acc.right; x <- e.right) yield x :: xs 63 | } 64 | 65 | val placeOrder = 66 | (request: OrderRequest) => 67 | { 68 | val sumList = request.order.items.map { 69 | orderedItem => db.getItem(orderedItem.itemId).right map { 70 | _.price * orderedItem.quantity } 71 | } 72 | val savedOrder = sequence(sumList).right flatMap { 73 | sl => db.saveOrder(request.order).right map (_ => sl.sum) 74 | } 75 | OrderResponse(savedOrder) 76 | } 77 | } 78 | 79 | object OoDI extends App { 80 | import StoreAPI._ 81 | import DatabaseAPI._ 82 | 83 | val orderRequest1 = OrderRequest(Order("ORD_01", "IBM", 84 | List( 85 | OrderedItem("002", 12.0), 86 | OrderedItem("004", 2.0) 87 | ))) 88 | 89 | val orderRequest2 = OrderRequest(Order("ORD_02", "Google", 90 | List( 91 | OrderedItem("002", 12.0), 92 | OrderedItem("005", 2.0) 93 | ))) 94 | 95 | val storeMemDB = Store(MemDatabaseGood()) 96 | 97 | println(storeMemDB.placeOrder(orderRequest1).toString) 98 | println(storeMemDB.placeOrder(orderRequest2).toString) 99 | 100 | val storeMemDBFailing = Store(MemDatabaseFailing()) 101 | 102 | println(storeMemDBFailing.placeOrder(orderRequest1).toString) 103 | println(storeMemDBFailing.placeOrder(orderRequest2).toString) 104 | } 105 | -------------------------------------------------------------------------------- /src/main/scala/plainFP/SimpleFP.scala: -------------------------------------------------------------------------------- 1 | package plainFP 2 | 3 | import scala.language.reflectiveCalls 4 | import scala.util.Random 5 | 6 | import Common._ 7 | 8 | object SimpleFP { 9 | def runApp(config: Config) = { 10 | val webServer = new WebServer(config.host, config.port) 11 | val dbServer = new DBServer(config.dbUrl, config.dbUser, config.dbPassword) 12 | val smtpServer = new SmtpServer( 13 | config.smtpServer, 14 | config.smtpUser, 15 | config.smtpPassword 16 | ) 17 | 18 | val getPerson = (id: String) => using(dbServer)(_.getEntity[Person](id)) 19 | val updatePerson = (person: Person) => 20 | using(dbServer)(_.updateEntity[Person](person)) 21 | 22 | val createAndSendMail = (person: Person) => { 23 | val mail = createMail(config.smtpFrom)(person) 24 | using(smtpServer)(_.sendMail(mail)) 25 | person 26 | } 27 | 28 | //val processOpt: Request => Either[Failure, Response] = 29 | //getMessage andThen parseJson andThen 30 | //getPerson ~~> modifyPerson(config.personNameToUppercase) ~~> 31 | //updatePerson ~> createAndSendMail ~> makeResponse 32 | 33 | val processOpt: Request => Either[Failure, Response] = 34 | getMessage andThen 35 | parseJson andThen 36 | getPerson andThen 37 | flatMap(modifyPerson(config.personNameToUppercase)) andThen 38 | flatMap(updatePerson) andThen 39 | map(createAndSendMail) andThen 40 | map(makeResponse) 41 | 42 | val process: Request => Response = request => 43 | processOpt(request) match { 44 | case Right(response) => response 45 | case Left(failure) => Response(failure.toString) 46 | } 47 | 48 | using(webServer){ ws => while (ws.listen(process)) {} } 49 | } 50 | 51 | val getMessage = (request: Request) => request.message 52 | val makeResponse = (person: Person) => Response(person.toString) 53 | 54 | case object ModifyPersonFailed extends Failure 55 | 56 | def modifyPerson(toUpperCase: Boolean)(person: Person) = { 57 | val modifiedPerson = person.copy(age = person.age + 1) 58 | if (toUpperCase) { 59 | if (Random.nextInt(100) < 30) Left(ModifyPersonFailed) 60 | else Right(modifiedPerson.copy(name = modifiedPerson.name.toUpperCase)) 61 | } else { 62 | Right(modifiedPerson) 63 | } 64 | } 65 | 66 | def createMail(from: String)(person: Person) = { 67 | Mail(from, person.email, "Person updated", person.toString) 68 | } 69 | 70 | def parseJson(json: String) = json 71 | 72 | def using[A <: { def close: Unit }, B](resource: A)(f: A => B): B = { 73 | val result = f(resource) 74 | resource.close 75 | result 76 | } 77 | } 78 | 79 | final case class ID private(val key: String) 80 | 81 | object ID { 82 | private val keyPattern = raw"(\d{4}-\d{4}-\d{4})".r 83 | def apply(key: String) = key match { 84 | case keyPattern(k) => Some(new ID(k)) 85 | case _ => None 86 | } 87 | } 88 | 89 | object SimpleFPApp extends App { 90 | println(ID("0123-4567-8901")) 91 | println(ID("122")) 92 | 93 | val config = Config( 94 | "localhost", 95 | 9000, 96 | "jdbc:..", 97 | "dbUser", 98 | "dbPassword", 99 | "smtp.local.com", 100 | "smtpUser", 101 | "smtpPassword", 102 | "simple@app.com", 103 | true 104 | ) 105 | 106 | SimpleFP.runApp(config) 107 | } 108 | -------------------------------------------------------------------------------- /src/main/scala/plainFP/RequestResponse.scala: -------------------------------------------------------------------------------- 1 | package plainFP 2 | 3 | object RequestResponse { 4 | object Method extends Enumeration { 5 | type Method = Value 6 | val GET, HEAD, POST, PUT, DELETE, PATCH = Value 7 | } 8 | import Method._ 9 | 10 | case class Request( 11 | method: Method, 12 | path: String, 13 | cookie: String, 14 | parameter: String, 15 | acceptType: String, 16 | contentType: String, 17 | content: String 18 | ) 19 | 20 | case class Response( 21 | code: String, 22 | cookie: String, 23 | contentType: String, 24 | content: String 25 | ) 26 | 27 | def hello(request: Request): Response = { 28 | if (isGetMethod(request) && isHelloPath(request)) { 29 | Response("200", "", "text/plain", createHelloContent(request)) 30 | } else { 31 | Response("400", "", "text/plain", "") 32 | } 33 | } 34 | 35 | def isGetMethod(request: Request) = 36 | //request.method == GET 37 | request.method == GET || !request.contentType.isEmpty 38 | def isHelloPath(request: Request) = 39 | //request.path == "/hello" 40 | request.path == "/hello" || !request.acceptType.isEmpty 41 | def createHelloContent(request: Request) = 42 | //s"Hello ${request.content.capitalize}!" 43 | s"Hello ${request.content.capitalize + request.cookie}!" 44 | 45 | def hello2(request: Request): Response = { 46 | hello2BL(request.method, request.path, request.content) 47 | } 48 | 49 | def hello2BL(method: Method, path: String, content: String): Response = { 50 | if (method == GET && path == "/hello") { 51 | Response("200", "", "text/plain", createHelloContent2(content)) 52 | } else { 53 | Response("400", "", "text/plain", "") 54 | } 55 | } 56 | 57 | def createHelloContent2(content: String) = s"Hello ${content.capitalize}!" 58 | 59 | object SimpleReq { 60 | def unapply(request: Request) = { 61 | Some((request.method, request.path, request.content)) 62 | } 63 | } 64 | 65 | def hello3(request: Request): Response = request match { 66 | case SimpleReq(GET, "/hello", content) => hello3BL(content) 67 | //case Request(GET, "/hello", _, _, _, _, content) => hello3BL(content) 68 | case _ => Response("400", "", "text/plain", "") 69 | } 70 | 71 | def hello3BL(content: String): Response = { 72 | Response("200", "", "text/plain", createHelloContent2(content)) 73 | } 74 | } 75 | 76 | object RequestResponseApp extends App { 77 | import RequestResponse._ 78 | import Method._ 79 | 80 | val badResponse = Response("400", "", "text/plain", "") 81 | val goodResponse = Response("200", "", "text/plain", "Hello John!") 82 | 83 | val requests = Map( 84 | Request(GET, "/hello", "???", "", "", "", "john") -> goodResponse, 85 | Request(POST, "/hello", "???", "", "", "text/plain", "john") -> badResponse, 86 | Request(GET, "/bye", "???", "", "text/plain", "", "john") -> badResponse 87 | ) 88 | 89 | def show( 90 | title: String, 91 | request: Request, 92 | response: Response, 93 | fn: Request => Response) = 94 | { 95 | var result = fn(request) 96 | var state = if (result == response) "ok" else "failed" 97 | println(s"$title: $result -> $state") 98 | } 99 | 100 | requests.foreach { case (request, response) => 101 | show("hello " , request, response, hello) 102 | show("hello2" , request, response, hello2) 103 | show("hello3" , request, response, hello3) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/exception/Failure.java: -------------------------------------------------------------------------------- 1 | package exception; 2 | 3 | import java.text.MessageFormat; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import java.util.Optional; 7 | import java.util.Set; 8 | 9 | public class Failure { 10 | public static final String EXCEPTION = "EXCEPTION"; 11 | protected final String code; 12 | protected final Map params; 13 | 14 | private Failure(String code, Map params) { 15 | this.code = code; 16 | this.params = params; 17 | } 18 | 19 | public static Failure of(String code) { 20 | return new Failure(code, new HashMap<>()); 21 | } 22 | 23 | public static Failure of(String code, String key, Object value) { 24 | Map params = new HashMap<>(); 25 | params.put(key, value); 26 | return new Failure(code, params); 27 | } 28 | 29 | @SafeVarargs 30 | public static Failure of(String code, Tuple2... tuples) { 31 | return new Failure(code, Tuple2.toMap(tuples)); 32 | } 33 | 34 | public static Either tryCatch( 35 | SupplierCatch process 36 | ) { 37 | try { 38 | return Right.of(process.get()); 39 | } catch(Exception e) { 40 | return Left.of( 41 | Failure.of(e.getClass().getSimpleName(), EXCEPTION, e) 42 | ); 43 | } 44 | } 45 | 46 | public static Either tryCatch( 47 | String code, 48 | SupplierCatch process 49 | ) { 50 | try { 51 | return Right.of(process.get()); 52 | } catch(Exception e) { 53 | return Left.of( 54 | Failure.of(code, EXCEPTION, e) 55 | ); 56 | } 57 | } 58 | 59 | public static Optional tryCatchOptional( 60 | SupplierCatch process 61 | ) { 62 | try { 63 | return Optional.of(process.get()); 64 | } catch(Exception e) { 65 | return ignoreException(e, Optional.empty()); 66 | } 67 | } 68 | 69 | public String getCode() { 70 | return code; 71 | } 72 | 73 | public Set getParamNames() { 74 | return params.keySet(); 75 | } 76 | 77 | @SuppressWarnings("unchecked") 78 | public T getParamValue(String paramName) { 79 | return (T) params.get(paramName); 80 | } 81 | 82 | public String format(String pattern) { 83 | return MessageFormat.format( 84 | pattern, 85 | params.values().toArray(new Object[0]) 86 | ); 87 | } 88 | 89 | @Override 90 | public String toString() { 91 | final Optional paramStrOpt = params.entrySet() 92 | .stream() 93 | .map(entry -> entry.getKey() + " -> " + entry.getValue()) 94 | .reduce((s1, s2) -> s1 + ", " + s2); 95 | final String paramStr = paramStrOpt.map(p -> ", " + p).orElse(""); 96 | 97 | return "Failure(" + code + paramStr + ")"; 98 | } 99 | 100 | public static R ignoreException(E e, R r) { 101 | e.getCause(); 102 | return r; 103 | } 104 | 105 | @FunctionalInterface 106 | public static interface SupplierCatch { 107 | R get() throws E; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/fpjdbc/Record.java: -------------------------------------------------------------------------------- 1 | package fpjdbc; 2 | 3 | import java.lang.reflect.*; 4 | import java.sql.ResultSet; 5 | import java.sql.ResultSetMetaData; 6 | import java.sql.SQLException; 7 | import java.util.Map; 8 | import java.util.LinkedHashMap; 9 | import java.util.Optional; 10 | import java.util.function.Function; 11 | import java.util.function.Consumer; 12 | 13 | import exception.Either; 14 | import exception.Failure; 15 | import exception.Left; 16 | import exception.Right; 17 | 18 | public class Record { 19 | private final Map values; 20 | 21 | private Record(Map values) { 22 | this.values = values; 23 | } 24 | 25 | public Optional field(String name) { 26 | return Optional.ofNullable(values.get(name)); 27 | } 28 | 29 | public Either as(Class type) { 30 | try { 31 | Constructor constructors[] = type.getDeclaredConstructors(); 32 | Constructor ctRet = constructors[0]; 33 | //for (int i = 0; i < constructors.length; i++) { 34 | //Constructor ct = constructors[i]; 35 | //System.out.println("name = " + ct.getName()); 36 | //System.out.println("decl class = " + 37 | //ct.getDeclaringClass()); 38 | //Class pvec[] = ct.getParameterTypes(); 39 | //for (int j = 0; j < pvec.length; j++) 40 | //System.out.println("param #" 41 | //+ j + " " + pvec[j]); 42 | //} 43 | Object arglist[] = values.values().toArray(); 44 | return Right.of((T) ctRet.newInstance(arglist)); 45 | } catch(Exception e) { 46 | return Left.of( 47 | Failure.of(e.getClass().getSimpleName(), Failure.EXCEPTION, e) 48 | ); 49 | } 50 | } 51 | 52 | public static Either ofAs(ResultSet rs, Class type) { 53 | return of(rs).flatMap(record -> record.as(type)); 54 | } 55 | 56 | public static ThrowingFunction, SQLException> 57 | expandAs(Class type) 58 | { 59 | return rs -> ofAs(rs, type); 60 | } 61 | 62 | public static Record build(Consumer factory) { 63 | final Builder builder = new Builder(); 64 | factory.accept(builder); 65 | return builder.build(); 66 | } 67 | 68 | public static Either of(ResultSet rs) { 69 | return Failure.tryCatch(() -> { 70 | final Map values = new LinkedHashMap<>(); 71 | final ResultSetMetaData rsmd = rs.getMetaData(); 72 | final int numberOfColumns = rsmd.getColumnCount(); 73 | 74 | for (int i=1; i<=numberOfColumns; i++) { 75 | values.put(rsmd.getColumnLabel(i).toLowerCase(), rs.getObject(i)); 76 | } 77 | 78 | return new Record(values); 79 | }); 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | final String fieldStr = values.entrySet() 85 | .stream() 86 | .map(entry -> entry.getKey() + " -> " + entry.getValue()) 87 | .reduce((s1, s2) -> s1 + ", " + s2) 88 | .orElse(""); 89 | 90 | return "Record(" + fieldStr + ")"; 91 | } 92 | 93 | public static final class Builder { 94 | private final Map values = new LinkedHashMap<>(); 95 | 96 | public Builder field(String name, Object value) { 97 | values.put(name, value); 98 | return this; 99 | } 100 | 101 | private Record build() { 102 | return new Record(values); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/scala/knapsack/Knapsack.scala: -------------------------------------------------------------------------------- 1 | package knapsack 2 | 3 | import cats.effect.IO 4 | import org.scalameter.api._ 5 | import scala.collection._ 6 | 7 | object KnapsackImp { 8 | def knapsack(maxWeight: Int, values: Seq[Int], weights: Seq[Int]): Int = 9 | { 10 | val n = values.length 11 | var solutions: Array[Int] = Array.fill(maxWeight + 1)( 0 ) 12 | (1 to n) foreach { i => 13 | val newSolutions = Array.fill(maxWeight + 1)( 0 ) 14 | (1 to maxWeight) foreach { j => 15 | newSolutions(j) = if( j - weights(i-1) >= 0 ) { 16 | Math.max( 17 | solutions(j) , 18 | solutions(j - weights(i-1)) + values(i-1) 19 | ) 20 | } else { 21 | solutions(j) 22 | } 23 | } 24 | solutions = newSolutions 25 | } 26 | solutions(maxWeight) 27 | } 28 | } 29 | 30 | object KnapsackFP { 31 | def knapsack(maxWeight: Int, values: Seq[Int], weights: Seq[Int]): Int = 32 | { 33 | def M(i: Int, j: Int): IO[Int] = { 34 | if (i < 0) { 35 | IO(0) 36 | } else { 37 | val value1 = M(i-1, j) 38 | if (j >= weights(i)) { 39 | val value2 = M(i-1, j-weights(i)).map(_ + values(i)) 40 | for { 41 | v1 <- value1 42 | v2 <- value2 43 | } yield Math.max(v1, v2) 44 | } else { 45 | value1 46 | } 47 | } 48 | } 49 | 50 | M(values.length-1, maxWeight).unsafeRunSync 51 | } 52 | } 53 | 54 | object KnapsackMemo { 55 | def memoize[I, O](f: I => O): I => O = new mutable.HashMap[I, O]() { 56 | override def apply(key: I) = getOrElseUpdate(key, f(key)) 57 | } 58 | 59 | def knapsack(maxWeight: Int, values: Seq[Int], weights: Seq[Int]): Int = 60 | { 61 | lazy val M: ((Int, Int)) => Int = memoize { 62 | case (i, _) if (i < 0) => 63 | 0 64 | case (i, j) => 65 | val value1 = M(i-1, j) 66 | if (j >= weights(i)) { 67 | val value2 = M(i-1, j-weights(i)) + values(i) 68 | Math.max(value1, value2) 69 | } else { 70 | value1 71 | } 72 | } 73 | 74 | M(values.length-1, maxWeight) 75 | } 76 | } 77 | 78 | //* 79 | object Knapsack extends Bench.LocalTime { 80 | val random = new scala.util.Random(1000) 81 | val length = random.nextInt(10) + 10 82 | val values = (1 to length) map { j => random.nextInt(10) + 1 } 83 | val weights = (1 to length) map { j => random.nextInt(10) + 1 } 84 | 85 | //val length = 9 86 | //val values = Vector(3, 3, 5, 3, 7) 87 | //val weights = Vector(1, 2, 4, 2, 3) 88 | 89 | val retImp = KnapsackImp.knapsack(length, values, weights) 90 | val retFP = KnapsackFP.knapsack(length, values, weights) 91 | val retMemo = KnapsackMemo.knapsack(length, values, weights) 92 | 93 | println(s"result Imp: $retImp, FP: $retFP, Memo: $retMemo") 94 | //println(s"result Imp: $retImp, Memo: $retMemo") 95 | 96 | if (true) { 97 | 98 | val sizes = Gen.range("size")(1, 10, 1) 99 | 100 | val ranges = for { 101 | size <- sizes 102 | } yield 0 until size 103 | 104 | performance of "Knapsack" in { 105 | measure method "Imperative" in { 106 | using(ranges) in { 107 | r => r.foreach( i => KnapsackImp.knapsack(length, values, weights)) 108 | } 109 | } 110 | 111 | measure method "FP" in { 112 | using(ranges) in { 113 | r => r.foreach(i => KnapsackFP.knapsack(length, values, weights)) 114 | } 115 | } 116 | 117 | measure method "Memo" in { 118 | using(ranges) in { 119 | r => r.foreach(i => KnapsackMemo.knapsack(length, values, weights)) 120 | } 121 | } 122 | } 123 | } 124 | } 125 | //*/ 126 | -------------------------------------------------------------------------------- /src/test/scala/loopperf/NBodyArrayPerf.scala: -------------------------------------------------------------------------------- 1 | package loopperf 2 | 3 | /* 4 | import org.scalameter.api._ 5 | 6 | object NBodyArrayPerf extends Bench.LocalTime { 7 | val sizes = Gen.range("size")(100, 1000, 100) 8 | 9 | val ranges = for { 10 | size <- sizes 11 | } yield 0 until size 12 | 13 | NBodyArray.initArrays 14 | 15 | performance of "NBodyArray" in { 16 | measure method "for" in { 17 | using(ranges) in { 18 | r => r.foreach(i => NBodyArray.forSim(100)) 19 | } 20 | } 21 | 22 | measure method "while" in { 23 | using(ranges) in { 24 | r => r.foreach(i => NBodyArray.whileSim(100)) 25 | } 26 | } 27 | 28 | } 29 | } 30 | */ 31 | 32 | /** 33 | * Results 34 | * 35 | * Scala 2.11.7 36 | * 37 | * [info] ::Benchmark NBodyArray.for:: 38 | * [info] cores: 8 39 | * [info] hostname: kalman-Aspire-VN7-791G 40 | * [info] name: Java HotSpot(TM) 64-Bit Server VM 41 | * [info] osArch: amd64 42 | * [info] osName: Linux 43 | * [info] vendor: Oracle Corporation 44 | * [info] version: 25.91-b14 45 | * [info] Parameters(size -> 100): 0.131104 46 | * [info] Parameters(size -> 200): 0.263584 47 | * [info] Parameters(size -> 300): 0.39575 48 | * [info] Parameters(size -> 400): 0.526925 49 | * [info] Parameters(size -> 500): 0.666313 50 | * [info] Parameters(size -> 600): 0.791579 51 | * [info] Parameters(size -> 700): 0.895099 52 | * [info] Parameters(size -> 800): 1.022956 53 | * [info] Parameters(size -> 900): 1.153401 54 | * [info] Parameters(size -> 1000): 1.277743 55 | * 56 | * [info] ::Benchmark NBodyArray.while:: 57 | * [info] cores: 8 58 | * [info] hostname: kalman-Aspire-VN7-791G 59 | * [info] name: Java HotSpot(TM) 64-Bit Server VM 60 | * [info] osArch: amd64 61 | * [info] osName: Linux 62 | * [info] vendor: Oracle Corporation 63 | * [info] version: 25.91-b14 64 | * [info] Parameters(size -> 100): 8.36E-4 65 | * [info] Parameters(size -> 200): 0.001564 66 | * [info] Parameters(size -> 300): 0.002172 67 | * [info] Parameters(size -> 400): 0.002765 68 | * [info] Parameters(size -> 500): 0.002888 69 | * [info] Parameters(size -> 600): 0.003314 70 | * [info] Parameters(size -> 700): 0.003925 71 | * [info] Parameters(size -> 800): 0.004432 72 | * [info] Parameters(size -> 900): 0.004961 73 | * [info] Parameters(size -> 1000): 0.005477 74 | * 75 | * Scala 2.11.8 76 | * [info] ::Benchmark NBodyArray.for:: 77 | * [info] cores: 8 78 | * [info] hostname: kalman-Aspire-VN7-791G 79 | * [info] name: Java HotSpot(TM) 64-Bit Server VM 80 | * [info] osArch: amd64 81 | * [info] osName: Linux 82 | * [info] vendor: Oracle Corporation 83 | * [info] version: 25.91-b14 84 | * [info] Parameters(size -> 100): 0.261338 85 | * [info] Parameters(size -> 200): 0.52403 86 | * [info] Parameters(size -> 300): 0.784779 87 | * [info] Parameters(size -> 400): 1.040066 88 | * [info] Parameters(size -> 500): 1.321773 89 | * [info] Parameters(size -> 600): 1.524742 90 | * [info] Parameters(size -> 700): 1.766986 91 | * [info] Parameters(size -> 800): 2.014274 92 | * [info] Parameters(size -> 900): 2.284899 93 | * [info] Parameters(size -> 1000): 2.553726 94 | * 95 | * [info] ::Benchmark NBodyArray.while:: 96 | * [info] cores: 8 97 | * [info] hostname: kalman-Aspire-VN7-791G 98 | * [info] name: Java HotSpot(TM) 64-Bit Server VM 99 | * [info] osArch: amd64 100 | * [info] osName: Linux 101 | * [info] vendor: Oracle Corporation 102 | * [info] version: 25.91-b14 103 | * [info] Parameters(size -> 100): 8.59E-4 104 | * [info] Parameters(size -> 200): 0.001486 105 | * [info] Parameters(size -> 300): 0.002719 106 | * [info] Parameters(size -> 400): 0.003524 107 | * [info] Parameters(size -> 500): 0.003324 108 | * [info] Parameters(size -> 600): 0.003898 109 | * [info] Parameters(size -> 700): 0.004324 110 | * [info] Parameters(size -> 800): 0.004915 111 | * [info] Parameters(size -> 900): 0.005348 112 | * [info] Parameters(size -> 1000): 0.005938 113 | */ 114 | -------------------------------------------------------------------------------- /src/main/scala/independence/Result.scala: -------------------------------------------------------------------------------- 1 | package independence 2 | 3 | import scala.Enumeration 4 | import scala.reflect._ 5 | import scala.util.{ Try, Success, Failure, Either, Left, Right } 6 | import Level._ 7 | 8 | trait Fault { 9 | def level: Level 10 | } 11 | 12 | trait FieldFault extends Fault { 13 | def field: String 14 | } 15 | 16 | case class ExceptionError(cause: Throwable, level: Level = ERROR) extends Fault 17 | case class OptionMissing(level: Level = ERROR) extends Fault 18 | 19 | case class PredicateDoesNotHoldFor[T](value: T, level: Level = FATAL) 20 | extends Fault 21 | 22 | trait Information 23 | 24 | sealed trait Result[+T] { 25 | 26 | def infos: List[Information] 27 | 28 | def ++[T](that: Result[T]): Result[T] 29 | 30 | def flatMap[B](fn: T => Result[B]): Result[B] 31 | 32 | def map[B](fn: T => B): Result[B] = flatMap(t => Result(fn(t))) 33 | 34 | def check(p: T => Boolean, makeCause: T => Fault): Result[T] = this match { 35 | case r @ GoodResult(v, i) if (p(v)) => r 36 | case r @ GoodResult(v, i) => BadResult(makeCause(v), i) 37 | case r @ BadResult(c, i) => r 38 | } 39 | 40 | def filter(p: T => Boolean): Result[T] = 41 | check(p, value => PredicateDoesNotHoldFor(value)) 42 | 43 | def withFilter(p: T => Boolean): Result[T] = filter(p) 44 | 45 | def addInformation(info: Information): Result[T] = this match { 46 | case r @ GoodResult(v, i) => r.copy(infos = info :: infos) 47 | case r @ BadResult(c, i) => r.copy(infos = info :: infos) 48 | } 49 | 50 | def isGood = this match { 51 | case GoodResult(_, _) => true 52 | case _ => false 53 | } 54 | 55 | def processInfos[I:ClassTag,R](processor: List[I] => Result[R]): Result[R] = 56 | this match { 57 | case GoodResult(_, _) => 58 | processAllInfos(processor) 59 | case b @ BadResult(_, _) => b 60 | } 61 | 62 | def processAllInfos[I:ClassTag,R](processor: List[I] => Result[R]): 63 | Result[R] = 64 | { 65 | val infos = this.infos.reverse collect { 66 | case info: I => info 67 | } 68 | this ++ processor(infos) 69 | } 70 | } 71 | 72 | case class GoodResult[T](value: T, infos: List[Information] = List()) 73 | extends Result[T] 74 | { 75 | def flatMap[B](fn: T => Result[B]): Result[B] = { 76 | fn(value) match { 77 | case r @ GoodResult(v, i) => r.copy(infos = i ::: infos) 78 | case r @ BadResult(c, i) => r.copy(infos = i ::: infos) 79 | } 80 | } 81 | 82 | def ++[T](that: Result[T]): Result[T] = that match { 83 | case r @ GoodResult(v, i) => r.copy(infos = i ::: infos) 84 | case r @ BadResult(c, i) => r.copy(infos = i ::: infos) 85 | } 86 | } 87 | 88 | case class BadResult(cause: Fault, infos: List[Information] = List()) 89 | extends Result[Nothing] 90 | { 91 | def flatMap[B](fn: Nothing => Result[B]): Result[B] = this 92 | 93 | def ++[T](that: Result[T]): Result[T] = this 94 | } 95 | 96 | object Result { 97 | def apply[T](value: T) = GoodResult(value) 98 | 99 | def fromOption[T](opt: Option[T], cause: Option[Fault]) = opt match { 100 | case Some(value) => GoodResult(value) 101 | case None => BadResult(cause getOrElse OptionMissing()) 102 | } 103 | 104 | def fromTry[T](value: => T, cause: => Option[Fault] = None) = Try(value) match { 105 | case Success(value) => GoodResult(value) 106 | case Failure(throwable) => 107 | BadResult(cause getOrElse ExceptionError(throwable)) 108 | } 109 | 110 | def fromEither[T](either: Either[Fault, T], cause: Option[Fault] = None) = 111 | either match { 112 | case Right(value) => GoodResult(value) 113 | case Left(left) => 114 | BadResult(cause getOrElse left) 115 | } 116 | 117 | def validate[T](value: T, p: T => Boolean, info: Information): 118 | Result[Option[T]] = 119 | { 120 | if (p(value)) { 121 | GoodResult(Some(value)) 122 | } else { 123 | GoodResult(None, List(info)) 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/test/scala/independence/IndependenceDaySpec.scala: -------------------------------------------------------------------------------- 1 | package independence 2 | 3 | import org.scalatest._ 4 | import org.scalatest.Matchers._ 5 | 6 | class IndependenceDaySpec extends FunSpec with Matchers { 7 | import IndependenceDay._ 8 | import Level._ 9 | import ResultOps._ 10 | 11 | describe("getUserId") { 12 | it("should give BadResult if no id") { 13 | val result = getUserId(None) 14 | result shouldEqual BadResult(IdCookieIsMissing()) 15 | } 16 | 17 | it("should give BadResult if id is not a number") { 18 | val result = getUserId(Option("alma")) 19 | result shouldEqual BadResult(IdCookieIsNotNumber()) 20 | } 21 | 22 | it("should give BadResult if id is negative") { 23 | val result = getUserId(Option("-5")) 24 | result shouldEqual BadResult(PredicateDoesNotHoldFor(-5)) 25 | } 26 | 27 | it("should give BadResult if id is even") { 28 | val result = getUserId(Option("8")) 29 | result should matchPattern { 30 | case BadResult(UserIdMustBeOdd(_), _) => 31 | } 32 | } 33 | 34 | it("should give GoodResult if id cookie is positive and odd") { 35 | val result = getUserId(Option("7")) 36 | result should matchPattern { 37 | case GoodResult(21, _) => 38 | } 39 | } 40 | } 41 | 42 | describe("insertUser") { 43 | it("should give BadResult if id is negative") { 44 | val result = insertUser(Option("-7"), "als", "54", "asa") 45 | result should matchPattern { 46 | case BadResult(PredicateDoesNotHoldFor(-7, _), _) => 47 | } 48 | result.infos should contain allOf ( 49 | Log(DEBUG, "validateUser", ""), 50 | Validation('Error, "userName", "wrong name format"), 51 | Validation('Error, "userPhone", "wrong phone format"), 52 | Validation('Warning, "userEmail", "wrong email format")) 53 | } 54 | 55 | it("should give BadResult if all parameter is empty") { 56 | val result = insertUser(Option("7"), "", "", "") 57 | result should matchPattern { 58 | case BadResult(FatalValidation(_), _) => 59 | } 60 | } 61 | 62 | it("should give BadResult if name is wrong, others empty") { 63 | val result = insertUser(Option("7"), "Elek", "", "") 64 | result should matchPattern { 65 | case BadResult(MissingUserName(_), _) => 66 | } 67 | } 68 | 69 | it("should give BadResult if name is good, others empty") { 70 | val result = insertUser(Option("7"), "Teszt Elek", "", "") 71 | 72 | result.isGood shouldBe true 73 | 74 | result.infos should contain allOf ( 75 | Validation('Error, "userPhone", "required"), 76 | Validation('Error, "userEmail", "required"), 77 | DBPersist(DBUser(21, "Teszt Elek"))) 78 | } 79 | 80 | it("should give BadResult if name and phone good, mail wrong") { 81 | val result = insertUser(Option("7"), "Teszt Elek", "(20)234-5678", "mail") 82 | 83 | result.isGood shouldBe true 84 | 85 | result.infos should contain allOf ( 86 | Validation('Warning, "userEmail", "wrong email format"), 87 | DBPersist(DBUser(21, "Teszt Elek")), 88 | DBPersist(DBContact(21, "phone", "(20)234-5678")), 89 | Sms("(20)234-5678", "User inserted", "Teszt Elek user has inserted")) 90 | } 91 | 92 | it("should give GoodResult if everything is right") { 93 | val result = insertUser( 94 | Option("7"), 95 | "Teszt Elek", 96 | "(20)234-5678", 97 | "teszt@elek.hu") 98 | 99 | result.isGood shouldBe true 100 | 101 | result.infos should contain allOf ( 102 | Log(INFO, "id * 3", ""), 103 | Log(INFO, "persistUser", ""), 104 | DBPersist(DBUser(21, "Teszt Elek")), 105 | DBPersist(DBContact(21, "phone", "(20)234-5678")), 106 | DBPersist(DBContact(21, "email", "teszt@elek.hu")), 107 | Email("teszt@elek.hu", "User inserted", "Teszt Elek user has inserted"), 108 | Sms("(20)234-5678", "User inserted", "Teszt Elek user has inserted")) 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/scala/loopperf/NBodyArray.scala: -------------------------------------------------------------------------------- 1 | package loopperf 2 | 3 | object NBodyArray extends App { 4 | def timeCode[T](warmups: Int, timeRuns: Int)(body: => T): Seq[Double] = { 5 | for(_ <- 1 to warmups) body 6 | for(_ <- 1 to timeRuns) yield { 7 | val start = System.nanoTime() 8 | body 9 | (System.nanoTime()-start)*1e-9 10 | } 11 | } 12 | def printTimeInfo(times: Seq[Double]): Unit = { 13 | val mean = times.sum/times.length 14 | val rms = math.sqrt(times.map(x => (x-mean)*(x-mean)).sum/times.length) 15 | println(s"mean = $mean, rms = $rms") 16 | } 17 | 18 | val numBodies = 1000 19 | val positions = Array.fill(numBodies*3)(0.0) 20 | val velocities = Array.fill(numBodies*3)(0.0) 21 | val accel = Array.fill(numBodies*3)(0.0) 22 | val masses = Array.fill(numBodies)(1e-10) 23 | masses(0) = 1.0 24 | class Particle(val index: Int) extends AnyVal { 25 | def x = positions(index*3) 26 | def y = positions(index*3+1) 27 | def z = positions(index*3+2) 28 | def vx = velocities(index*3) 29 | def vy = velocities(index*3+1) 30 | def vz = velocities(index*3+2) 31 | def ax = accel(index*3) 32 | def ay = accel(index*3+1) 33 | def az = accel(index*3+2) 34 | def mass = masses(index) 35 | def x_=(d: Double): Unit = positions(index*3) = d 36 | def y_=(d: Double): Unit = positions(index*3+1) = d 37 | def z_=(d: Double): Unit = positions(index*3+2) = d 38 | def vx_=(d: Double): Unit = velocities(index*3) = d 39 | def vy_=(d: Double): Unit = velocities(index*3+1) = d 40 | def vz_=(d: Double): Unit = velocities(index*3+2) = d 41 | def ax_=(d: Double): Unit = accel(index*3) = d 42 | def ay_=(d: Double): Unit = accel(index*3+1) = d 43 | def az_=(d: Double): Unit = accel(index*3+2) = d 44 | } 45 | 46 | val dt = 0.01 47 | initArrays() 48 | println("for:") 49 | printTimeInfo(timeCode(5,20){ forSim(100) }) 50 | initArrays() 51 | println("while:") 52 | printTimeInfo(timeCode(5,20){ whileSim(100) }) 53 | 54 | def initArrays(): Unit = { 55 | for(i <- 1 until numBodies) { 56 | val p = new Particle(i) 57 | p.x = i 58 | p.vy = math.sqrt(1.0/i) 59 | } 60 | } 61 | 62 | def forSim(steps: Int): Unit = { 63 | for(_ <- 1 to steps) { 64 | for(i <- 0 until numBodies*3) { 65 | accel(i) = 0.0 66 | } 67 | for { 68 | i <- 0 until numBodies 69 | j <- i+1 until numBodies 70 | } { 71 | val pi = new Particle(i) 72 | val pj = new Particle(j) 73 | val dx = pi.x-pj.x 74 | val dy = pi.y-pj.y 75 | val dz = pi.z-pj.z 76 | val dist = math.sqrt(dx*dx+dy*dy+dz*dz) 77 | val magi = pj.mass/(dist*dist*dist) 78 | pi.ax -= magi*dx 79 | pi.ay -= magi*dy 80 | pi.az -= magi*dz 81 | val magj = pi.mass/(dist*dist*dist) 82 | pj.ax += magj*dx 83 | pj.ay += magj*dy 84 | pj.az += magj*dz 85 | } 86 | for(i <- 0 until numBodies) { 87 | val p = new Particle(i) 88 | p.vx += p.ax*dt 89 | p.vy += p.ay*dt 90 | p.vz += p.az*dt 91 | p.x += p.vx*dt 92 | p.y += p.vy*dt 93 | p.z += p.vz*dt 94 | } 95 | } 96 | } 97 | 98 | def whileSim(steps: Int): Unit = { 99 | var s = 0 100 | while(s < steps) { 101 | var i = 0 102 | while(i < numBodies*3) { 103 | accel(i) = 0.0 104 | i += 1 105 | } 106 | i = 0 107 | while (i < numBodies) { 108 | val pi = new Particle(i) 109 | var j = i+1 110 | while(j < numBodies) { 111 | val pj = new Particle(j) 112 | val dx = pi.x-pj.x 113 | val dy = pi.y-pj.y 114 | val dz = pi.z-pj.z 115 | val dist = math.sqrt(dx*dx+dy*dy+dz*dz) 116 | val magi = pj.mass/(dist*dist*dist) 117 | pi.ax -= magi*dx 118 | pi.ay -= magi*dy 119 | pi.az -= magi*dz 120 | val magj = pi.mass/(dist*dist*dist) 121 | pj.ax += magj*dx 122 | pj.ay += magj*dy 123 | pj.az += magj*dz 124 | j += 1 125 | } 126 | i += 1 127 | } 128 | i = 0 129 | while(i < numBodies) { 130 | val p = new Particle(i) 131 | p.vx += p.ax*dt 132 | p.vy += p.ay*dt 133 | p.vz += p.az*dt 134 | p.x += p.vx*dt 135 | p.y += p.vy*dt 136 | p.z += p.vz*dt 137 | i += 1 138 | } 139 | s += 1 140 | } 141 | } 142 | } 143 | 144 | -------------------------------------------------------------------------------- /src/main/resources/fak/js/main.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | const base = {}; 3 | 4 | function init() { 5 | console.log("Init"); 6 | base.table = document.getElementById('table'), 7 | base.commandEl = document.getElementById('command'); 8 | base.commandEl.addEventListener('click', clickCommand); 9 | const addColumn = document.getElementById('addColumn'); 10 | addColumn.addEventListener('click', clickAddColumn); 11 | const addRow = document.getElementById('addRow'); 12 | addRow.addEventListener('click', clickAddRow); 13 | const generateCsv = document.getElementById('generateCsv'); 14 | generateCsv.addEventListener('click', clickGenerateCsv); 15 | addEventListener('click', 'td.counter', clickCell); 16 | } 17 | 18 | function clickCommand(event) { 19 | doCommand( 20 | () => base.commandEl.textContent = '-', 21 | () => base.commandEl.textContent = '0', 22 | () => base.commandEl.textContent = '+' 23 | ); 24 | } 25 | 26 | function clickCell(event) { 27 | const value = parseInt(event.target.textContent); 28 | doCommand( 29 | () => event.target.textContent = value + 1, 30 | () => event.target.textContent = value - 1, 31 | () => event.target.textContent = 0 32 | ); 33 | } 34 | 35 | function clickGenerateCsv(event) { 36 | let csv = []; 37 | for (let i = 0; i < table.rows.length; i++) { 38 | let row = table.rows[i]; 39 | let csvRow = []; 40 | for (let j = 0; j < row.cells.length; j++) { 41 | let cell = row.cells[j]; 42 | csvRow.push(cell.textContent); 43 | } 44 | csv.push(csvRow.join(', ')); 45 | } 46 | let blob = new Blob([csv.join('\n')], {type: "text/plain;charset=utf-8"}); 47 | saveAs(blob, "values.csv"); 48 | } 49 | 50 | function clickAddColumn(event) { 51 | appendColumn(base.table); 52 | } 53 | 54 | function clickAddRow(event) { 55 | appendRow(base.table); 56 | } 57 | 58 | function doCommand(fnPlus, fnMinus, fnZero) { 59 | const command = base.commandEl.textContent; 60 | if (command === '+') { 61 | fnPlus.apply(); 62 | } else if (command === '-') { 63 | fnMinus.apply(); 64 | } else if (command === '0') { 65 | fnZero.apply(); 66 | } 67 | } 68 | 69 | function appendRow(table) { 70 | let row = table.insertRow(table.rows.length), 71 | i; 72 | for (i = 0; i < table.rows[0].cells.length; i++) { 73 | let cell = row.insertCell(i); 74 | if (i === 0) { 75 | cell.textContent = (table.rows.length - 1) + '.'; 76 | } else { 77 | cell.textContent = '0'; 78 | cell.className = 'counter'; 79 | } 80 | } 81 | } 82 | 83 | function appendColumn(table) { 84 | var headerCell = document.createElement("TH"); 85 | headerCell.innerHTML = 'Type'; 86 | headerCell.contentEditable = 'true'; 87 | table.rows[0].appendChild(headerCell); 88 | 89 | for (let i = 1; i < table.rows.length; i++) { 90 | let cell = table.rows[i].insertCell(table.rows[i].cells.length); 91 | cell.textContent = '0'; 92 | cell.className = 'counter'; 93 | } 94 | } 95 | 96 | function ready(fn) { 97 | if (document.readyState != 'loading'){ 98 | init(); 99 | } else { 100 | document.addEventListener('DOMContentLoaded', init); 101 | } 102 | } 103 | 104 | function addEventListener(eventName, elementSelector, handler) { 105 | document.addEventListener(eventName, function(e) { 106 | for (var target = e.target; target && target != this; target = target.parentNode) { 107 | if (target.matches(elementSelector)) { 108 | handler.call(target, e); 109 | break; 110 | } 111 | } 112 | }, false); 113 | } 114 | 115 | ready(); 116 | })(); 117 | -------------------------------------------------------------------------------- /src/main/scala/com/example/FuncDI.scala: -------------------------------------------------------------------------------- 1 | package com.example 2 | 3 | import cats.effect.IO 4 | import cats.data.EitherT 5 | import cats.implicits._ 6 | 7 | sealed trait Error 8 | 9 | case class MissingItem(id: ItemID) extends Error 10 | case object NoSpaceOnDisk extends Error 11 | 12 | object result { 13 | type ResultIO[A] = EitherT[IO, Error, A] 14 | 15 | def makeLogged[I, O](fn: I => ResultIO[O])(input: I): ResultIO[O] = { 16 | println(s"LOG. input: $input") 17 | fn(input).flatMap { output: O => 18 | println(s"LOG. output: $output") 19 | EitherT.rightT(output) 20 | } 21 | } 22 | } 23 | import result._ 24 | 25 | case class ItemID(id: String) extends AnyVal 26 | case class OrderID(id: String) extends AnyVal 27 | 28 | case class Item(name: String, price: Double) 29 | case class OrderedItem(itemId: ItemID, quantity: Double) 30 | case class Order(id: OrderID, customer: String, items: List[OrderedItem]) 31 | 32 | object StoreAPI { 33 | case class OrderRequest(order: Order) 34 | case class OrderResponse(status: Either[Error, Double]) 35 | 36 | type PlaceOrder = OrderRequest => ResultIO[OrderResponse] 37 | } 38 | 39 | object DatabaseAPI { 40 | type GetItem = ItemID => ResultIO[Item] 41 | type SaveOrder = Order => ResultIO[Order] 42 | } 43 | 44 | object MemDatabase { 45 | import DatabaseAPI._ 46 | 47 | val items = Map( 48 | ItemID("001") -> Item("Sword", 399.9), 49 | ItemID("002") -> Item("Chair", 24.9), 50 | ItemID("003") -> Item("Table", 99.9), 51 | ItemID("004") -> Item("Bed", 59.9) 52 | ) 53 | 54 | val getItem: GetItem = id => { 55 | items get id match { 56 | case None => EitherT.leftT(MissingItem(id)) 57 | case Some(item) => EitherT.rightT(item) 58 | } 59 | } 60 | val saveOrder: SaveOrder = order => EitherT.rightT(order) 61 | val saveOrderFailing: SaveOrder = order => EitherT.leftT(NoSpaceOnDisk) 62 | } 63 | 64 | object Store { 65 | import DatabaseAPI._ 66 | import StoreAPI._ 67 | 68 | val getItems: GetItem => OrderRequest => ResultIO[List[(Item, OrderedItem)]] = { 69 | getItem => request => 70 | (request.order.items.map { 71 | orderedItem => getItem(orderedItem.itemId).map((_, orderedItem)) 72 | }).sequence 73 | } 74 | 75 | val calcPrice: (Item, OrderedItem) => Double = (item, orderedItem) => 76 | item.price * orderedItem.quantity 77 | 78 | val placeOrderBusinessLogic: (GetItem, SaveOrder) => PlaceOrder = 79 | { 80 | (getItem, saveOrder) => request => 81 | for { 82 | itemList <- getItems(getItem)(request) 83 | priceList = itemList.map(calcPrice.tupled) 84 | _ <- saveOrder(request.order) 85 | } yield OrderResponse(Right(priceList.sum)) 86 | } 87 | } 88 | 89 | case class Config(logged: Boolean) 90 | 91 | object FuncDI extends App { 92 | import Store._ 93 | import StoreAPI._ 94 | import DatabaseAPI._ 95 | import MemDatabase._ 96 | 97 | val config: Config = Config(false) 98 | 99 | lazy val getItemFn = 100 | if (config.logged) makeLogged(getItem) _ 101 | else getItem 102 | 103 | val orderRequest1 = OrderRequest(Order(OrderID("ORD_01"), "IBM", 104 | List( 105 | OrderedItem(ItemID("002"), 12.0), 106 | OrderedItem(ItemID("004"), 2.0) 107 | ))) 108 | 109 | val orderRequest2 = OrderRequest(Order(OrderID("ORD_02"), "Google", 110 | List( 111 | OrderedItem(ItemID("002"), 12.0), 112 | OrderedItem(ItemID("005"), 2.0) 113 | ))) 114 | 115 | val placeOrderMemDB = placeOrderBusinessLogic(getItemFn, saveOrder) 116 | 117 | println(placeOrderMemDB(orderRequest1).value.unsafeRunSync.toString) 118 | println(placeOrderMemDB(orderRequest2).value.unsafeRunSync.toString) 119 | 120 | val placeOrderMemDBFailing = placeOrderBusinessLogic( 121 | getItem, 122 | saveOrderFailing) 123 | 124 | println(placeOrderMemDBFailing(orderRequest1).value.unsafeRunSync.toString) 125 | println(placeOrderMemDBFailing(orderRequest2).value.unsafeRunSync.toString) 126 | 127 | val placeOrderLogged = placeOrderBusinessLogic( 128 | makeLogged(getItem), 129 | makeLogged(saveOrder)) 130 | 131 | println(placeOrderLogged(orderRequest1).value.unsafeRunSync.toString) 132 | println(placeOrderLogged(orderRequest2).value.unsafeRunSync.toString) 133 | } 134 | --------------------------------------------------------------------------------