├── .bsp
└── sbt.json
├── .gitignore
├── .idea
├── .gitignore
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── encodings.xml
├── hydra.xml
├── misc.xml
├── modules.xml
├── modules
│ ├── scala-2-advanced-build.iml
│ └── scala-2-advanced.iml
├── sbt.xml
├── scala_compiler.xml
├── scala_settings.xml
└── vcs.xml
├── README.md
├── build.sbt
├── project
├── build.properties
├── project
│ └── target
│ │ └── config-classes
│ │ └── $41de159e78a080d879ac.cache
└── target
│ ├── config-classes
│ ├── $2f0d6020feb87165a227.cache
│ ├── $ace5525ffd90805a6f8e.cache
│ └── $e46239a10b23e237b883.cache
│ ├── scala-2.12
│ └── sbt-1.0
│ │ ├── sync
│ │ └── copy-resource
│ │ └── update
│ │ └── update_cache_2.12
│ │ ├── inputs
│ │ └── output
│ └── streams
│ ├── _global
│ ├── _global
│ │ ├── _global
│ │ │ └── streams
│ │ │ │ └── out
│ │ └── csrLogger
│ │ │ └── _global
│ │ │ └── streams
│ │ │ └── out
│ ├── csrConfiguration
│ │ └── _global
│ │ │ └── streams
│ │ │ └── out
│ ├── csrProject
│ │ └── _global
│ │ │ └── streams
│ │ │ └── out
│ ├── dependencyPositions
│ │ └── _global
│ │ │ └── streams
│ │ │ └── update_cache_2.12
│ │ │ ├── input_dsp
│ │ │ └── output_dsp
│ ├── ivyConfiguration
│ │ └── _global
│ │ │ └── streams
│ │ │ └── out
│ ├── ivySbt
│ │ └── _global
│ │ │ └── streams
│ │ │ └── out
│ ├── moduleSettings
│ │ └── _global
│ │ │ └── streams
│ │ │ └── out
│ ├── projectDescriptors
│ │ └── _global
│ │ │ └── streams
│ │ │ └── out
│ ├── scalaCompilerBridgeScope
│ │ └── _global
│ │ │ └── streams
│ │ │ └── out
│ └── update
│ │ └── _global
│ │ └── streams
│ │ └── out
│ ├── compile
│ ├── _global
│ │ └── _global
│ │ │ ├── compileOutputs
│ │ │ └── previous
│ │ │ └── discoveredMainClasses
│ │ │ └── data
│ ├── bspReporter
│ │ └── _global
│ │ │ └── streams
│ │ │ └── out
│ ├── compile
│ │ └── _global
│ │ │ └── streams
│ │ │ └── out
│ ├── compileIncremental
│ │ └── _global
│ │ │ └── streams
│ │ │ ├── export
│ │ │ └── out
│ ├── copyResources
│ │ └── _global
│ │ │ └── streams
│ │ │ └── out
│ ├── dependencyClasspath
│ │ └── _global
│ │ │ └── streams
│ │ │ └── export
│ ├── exportedProducts
│ │ └── _global
│ │ │ └── streams
│ │ │ └── export
│ ├── externalDependencyClasspath
│ │ └── _global
│ │ │ └── streams
│ │ │ └── export
│ ├── incOptions
│ │ └── _global
│ │ │ └── streams
│ │ │ └── out
│ ├── internalDependencyClasspath
│ │ └── _global
│ │ │ └── streams
│ │ │ ├── export
│ │ │ └── out
│ ├── managedClasspath
│ │ └── _global
│ │ │ └── streams
│ │ │ └── export
│ ├── scalacOptions
│ │ └── _global
│ │ │ └── streams
│ │ │ └── out
│ ├── unmanagedClasspath
│ │ └── _global
│ │ │ └── streams
│ │ │ ├── export
│ │ │ └── out
│ └── unmanagedJars
│ │ └── _global
│ │ └── streams
│ │ └── export
│ └── runtime
│ ├── dependencyClasspath
│ └── _global
│ │ └── streams
│ │ └── export
│ ├── exportedProducts
│ └── _global
│ │ └── streams
│ │ └── export
│ ├── externalDependencyClasspath
│ └── _global
│ │ └── streams
│ │ └── export
│ ├── fullClasspath
│ └── _global
│ │ └── streams
│ │ └── export
│ ├── internalDependencyClasspath
│ └── _global
│ │ └── streams
│ │ ├── export
│ │ └── out
│ ├── managedClasspath
│ └── _global
│ │ └── streams
│ │ └── export
│ ├── unmanagedClasspath
│ └── _global
│ │ └── streams
│ │ ├── export
│ │ └── out
│ └── unmanagedJars
│ └── _global
│ └── streams
│ └── export
├── src
├── .DS_Store
├── exercises
│ ├── EqualityPlayground.scala
│ ├── MySet.scala
│ └── StreamsPlayground.scala
├── lectures
│ ├── part1as
│ │ ├── AdvancedPatternMatching.scala
│ │ ├── DarkSugars.scala
│ │ └── Recap.scala
│ ├── part2afp
│ │ ├── CurriesPAF.scala
│ │ ├── LazyEvaluation.scala
│ │ ├── Monads.scala
│ │ └── PartialFunctions.scala
│ ├── part3concurrency
│ │ ├── FuturesPromises.scala
│ │ ├── Intro.scala
│ │ ├── ParallelUtils.scala
│ │ └── ThreadCommunication.scala
│ ├── part4implicits
│ │ ├── ImplicitsIntro.scala
│ │ ├── JSONSerialization.scala
│ │ ├── MagnetPattern.scala
│ │ ├── MyTypeClassTemplate.scala
│ │ ├── OrganizingImplicits.scala
│ │ ├── PimpMyLibrary.scala
│ │ ├── ScalaJavaConversions.scala
│ │ └── TypeClasses.scala
│ └── part5ts
│ │ ├── FBoundedPolymorphism.scala
│ │ ├── HigherKindedTypes.scala
│ │ ├── PathDependentTypes.scala
│ │ ├── Reflection.scala
│ │ ├── RockingInheritance.scala
│ │ ├── SelfTypes.scala
│ │ ├── StructuralTypes.scala
│ │ ├── TypeMembers.scala
│ │ └── Variance.scala
└── playground
│ ├── JavaPlayground.java
│ └── ScalaPlayground.scala
└── target
├── .history3
├── scala-2.13
└── update
│ └── update_cache_2.13
│ ├── inputs
│ └── output
└── streams
├── _global
├── _global
│ ├── csrLogger
│ │ └── _global
│ │ │ └── streams
│ │ │ └── out
│ └── dumpStructure
│ │ └── _global
│ │ └── streams
│ │ └── out
├── csrConfiguration
│ └── _global
│ │ └── streams
│ │ └── out
├── csrProject
│ └── _global
│ │ └── streams
│ │ └── out
├── dependencyPositions
│ └── _global
│ │ └── streams
│ │ └── update_cache_2.13
│ │ ├── input_dsp
│ │ └── output_dsp
├── ivyConfiguration
│ └── _global
│ │ └── streams
│ │ └── out
├── ivySbt
│ └── _global
│ │ └── streams
│ │ └── out
├── moduleSettings
│ └── _global
│ │ └── streams
│ │ └── out
├── projectDescriptors
│ └── _global
│ │ └── streams
│ │ └── out
├── ssExtractDependencies
│ └── _global
│ │ └── streams
│ │ └── out
├── update
│ └── _global
│ │ └── streams
│ │ └── out
└── updateClassifiers
│ └── _global
│ └── streams
│ ├── out
│ └── update_cache_2.13
│ ├── inputs
│ └── output
├── compile
├── externalDependencyClasspath
│ └── _global
│ │ └── streams
│ │ └── export
├── managedClasspath
│ └── _global
│ │ └── streams
│ │ └── export
├── scalacOptions
│ └── _global
│ │ └── streams
│ │ └── out
├── unmanagedClasspath
│ └── _global
│ │ └── streams
│ │ ├── export
│ │ └── out
└── unmanagedJars
│ └── _global
│ └── streams
│ └── export
├── runtime
├── externalDependencyClasspath
│ └── _global
│ │ └── streams
│ │ └── export
├── managedClasspath
│ └── _global
│ │ └── streams
│ │ └── export
├── unmanagedClasspath
│ └── _global
│ │ └── streams
│ │ ├── export
│ │ └── out
└── unmanagedJars
│ └── _global
│ └── streams
│ └── export
└── test
├── externalDependencyClasspath
└── _global
│ └── streams
│ └── export
├── managedClasspath
└── _global
│ └── streams
│ └── export
├── unmanagedClasspath
└── _global
│ └── streams
│ ├── export
│ └── out
└── unmanagedJars
└── _global
└── streams
└── export
/.bsp/sbt.json:
--------------------------------------------------------------------------------
1 | {"name":"sbt","version":"1.8.0","bspVersion":"2.1.0-M1","languages":["scala"],"argv":["/Applications/IntelliJ IDEA CE.app/Contents/jbr/Contents/Home/bin/java","-Xms100m","-Xmx100m","-classpath","/Users/daniel/Library/Application Support/JetBrains/IdeaIC2023.1/plugins/Scala/launcher/sbt-launch.jar","-Dsbt.script=/usr/local/bin/sbt","xsbt.boot.Boot","-bsp"]}
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/scala,intellij
3 |
4 | ### Intellij ###
5 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
6 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
7 |
8 | # User-specific stuff
9 | .idea/**/workspace.xml
10 | .idea/**/tasks.xml
11 | .idea/**/usage.statistics.xml
12 | .idea/**/dictionaries
13 | .idea/**/shelf
14 |
15 | # Generated files
16 | .idea/**/contentModel.xml
17 |
18 | # Sensitive or high-churn files
19 | .idea/**/dataSources/
20 | .idea/**/dataSources.ids
21 | .idea/**/dataSources.local.xml
22 | .idea/**/sqlDataSources.xml
23 | .idea/**/dynamic.xml
24 | .idea/**/uiDesigner.xml
25 | .idea/**/dbnavigator.xml
26 |
27 | # Gradle
28 | .idea/**/gradle.xml
29 | .idea/**/libraries
30 |
31 | # Gradle and Maven with auto-import
32 | # When using Gradle or Maven with auto-import, you should exclude module files,
33 | # since they will be recreated, and may cause churn. Uncomment if using
34 | # auto-import.
35 | # .idea/modules.xml
36 | # .idea/*.iml
37 | # .idea/modules
38 |
39 | # CMake
40 | cmake-build-*/
41 |
42 | # Mongo Explorer plugin
43 | .idea/**/mongoSettings.xml
44 |
45 | # File-based project format
46 | *.iws
47 |
48 | # IntelliJ
49 | out/
50 |
51 | # mpeltonen/sbt-idea plugin
52 | .idea_modules/
53 |
54 | # JIRA plugin
55 | atlassian-ide-plugin.xml
56 |
57 | # Cursive Clojure plugin
58 | .idea/replstate.xml
59 |
60 | # Crashlytics plugin (for Android Studio and IntelliJ)
61 | com_crashlytics_export_strings.xml
62 | crashlytics.properties
63 | crashlytics-build.properties
64 | fabric.properties
65 |
66 | # Editor-based Rest Client
67 | .idea/httpRequests
68 |
69 | ### Intellij Patch ###
70 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
71 |
72 | # *.iml
73 | # modules.xml
74 | # .idea/misc.xml
75 | # *.ipr
76 |
77 | # Sonarlint plugin
78 | .idea/sonarlint
79 |
80 | ### Scala ###
81 | *.class
82 | *.log
83 |
84 |
85 | # End of https://www.gitignore.io/api/scala,intellij
86 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/hydra.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/modules/scala-2-advanced-build.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/.idea/modules/scala-2-advanced.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/sbt.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/scala_compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/scala_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## The official repository for the Scala Advanced course
2 |
3 | **For the new course repo (Scala 3), use this link: https://github.com/rockthejvm/advanced-scala**. The new course is at https://rockthejvm.com/p/advanced-scala.
4 |
5 | Powered by [Rock the JVM!](rockthejvm.com)
6 |
7 | This repository contains the code we wrote during [Rock the JVM's Scala 2 Advanced course](https://rockthejvm.com/course/scala-2-advanced) on Udemy. Unless explicitly mentioned, the code in this repository is exactly what was caught on camera.
8 |
9 | How to install:
10 | - either clone the repo or download as zip
11 | - open with IntelliJ as it's a simple IDEA project
12 |
13 | If you have changes to suggest to this repo, either
14 | - submit a GitHub issue
15 | - tell me in the course Q/A forum
16 | - submit a pull request!
17 |
--------------------------------------------------------------------------------
/build.sbt:
--------------------------------------------------------------------------------
1 |
2 | lazy val root = project
3 | .in(file("."))
4 | .settings(
5 | name := "scala-2-advanced",
6 | version := "0.1.0",
7 | scalaVersion := "2.13.5",
8 | libraryDependencies ++= Seq(
9 | "com.novocode" % "junit-interface" % "0.11" % "test",
10 | "org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.4",
11 | )
12 | )
13 |
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.8.0
2 |
--------------------------------------------------------------------------------
/project/project/target/config-classes/$41de159e78a080d879ac.cache:
--------------------------------------------------------------------------------
1 | sbt.internal.DslEntry
--------------------------------------------------------------------------------
/project/target/config-classes/$2f0d6020feb87165a227.cache:
--------------------------------------------------------------------------------
1 | root
2 |
--------------------------------------------------------------------------------
/project/target/config-classes/$ace5525ffd90805a6f8e.cache:
--------------------------------------------------------------------------------
1 | sbt.internal.DslEntry
--------------------------------------------------------------------------------
/project/target/config-classes/$e46239a10b23e237b883.cache:
--------------------------------------------------------------------------------
1 | sbt.internal.DslEntry
--------------------------------------------------------------------------------
/project/target/scala-2.12/sbt-1.0/sync/copy-resource:
--------------------------------------------------------------------------------
1 | [[{},{}],{}]
--------------------------------------------------------------------------------
/project/target/scala-2.12/sbt-1.0/update/update_cache_2.12/inputs:
--------------------------------------------------------------------------------
1 | -1885806411
--------------------------------------------------------------------------------
/project/target/streams/_global/_global/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/project/target/streams/_global/_global/_global/streams/out
--------------------------------------------------------------------------------
/project/target/streams/_global/_global/csrLogger/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/project/target/streams/_global/_global/csrLogger/_global/streams/out
--------------------------------------------------------------------------------
/project/target/streams/_global/csrConfiguration/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/project/target/streams/_global/csrConfiguration/_global/streams/out
--------------------------------------------------------------------------------
/project/target/streams/_global/csrProject/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/project/target/streams/_global/csrProject/_global/streams/out
--------------------------------------------------------------------------------
/project/target/streams/_global/dependencyPositions/_global/streams/update_cache_2.12/input_dsp:
--------------------------------------------------------------------------------
1 | 116610538
--------------------------------------------------------------------------------
/project/target/streams/_global/dependencyPositions/_global/streams/update_cache_2.12/output_dsp:
--------------------------------------------------------------------------------
1 | {"{\"organization\":\"org.scala-lang\",\"name\":\"scala-library\",\"revision\":\"2.12.17\",\"configurations\":\"provided\",\"isChanging\":false,\"isTransitive\":true,\"isForce\":false,\"explicitArtifacts\":[],\"inclusions\":[],\"exclusions\":[],\"extraAttributes\":{},\"crossVersion\":{\"type\":\"Disabled\"}}":{"value":{"$fields":["path","range"],"path":"/private/var/folders/0_/l801qy2501d6655txswpw8lc0000gn/T/idea.sbt","range":{"$fields":["start","end"],"start":5,"end":11}},"type":"RangePosition"},"{\"organization\":\"org.jetbrains.scala\",\"name\":\"sbt-structure-extractor\",\"revision\":\"2022.3.1\",\"isChanging\":false,\"isTransitive\":true,\"isForce\":false,\"explicitArtifacts\":[],\"inclusions\":[],\"exclusions\":[],\"extraAttributes\":{\"e:sbtVersion\":\"1.0\",\"e:scalaVersion\":\"2.12\"},\"crossVersion\":{\"type\":\"Disabled\"}}":{"value":{"$fields":["path","range"],"path":"/private/var/folders/0_/l801qy2501d6655txswpw8lc0000gn/T/idea.sbt","range":{"$fields":["start","end"],"start":5,"end":11}},"type":"RangePosition"},"{\"organization\":\"org.jetbrains.scala\",\"name\":\"sbt-idea-shell\",\"revision\":\"2021.1.0\",\"isChanging\":false,\"isTransitive\":true,\"isForce\":false,\"explicitArtifacts\":[],\"inclusions\":[],\"exclusions\":[],\"extraAttributes\":{\"e:sbtVersion\":\"1.0\",\"e:scalaVersion\":\"2.12\"},\"crossVersion\":{\"type\":\"Disabled\"}}":{"value":{"$fields":["path","range"],"path":"/private/var/folders/0_/l801qy2501d6655txswpw8lc0000gn/T/idea.sbt","range":{"$fields":["start","end"],"start":5,"end":11}},"type":"RangePosition"},"{\"organization\":\"org.jetbrains.scala\",\"name\":\"sbt-idea-compiler-indices\",\"revision\":\"1.0.13\",\"isChanging\":false,\"isTransitive\":true,\"isForce\":false,\"explicitArtifacts\":[],\"inclusions\":[],\"exclusions\":[],\"extraAttributes\":{\"e:sbtVersion\":\"1.0\",\"e:scalaVersion\":\"2.12\"},\"crossVersion\":{\"type\":\"Disabled\"}}":{"value":{"$fields":["path","range"],"path":"/private/var/folders/0_/l801qy2501d6655txswpw8lc0000gn/T/idea.sbt","range":{"$fields":["start","end"],"start":5,"end":11}},"type":"RangePosition"}}
--------------------------------------------------------------------------------
/project/target/streams/_global/ivyConfiguration/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/project/target/streams/_global/ivyConfiguration/_global/streams/out
--------------------------------------------------------------------------------
/project/target/streams/_global/ivySbt/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/project/target/streams/_global/ivySbt/_global/streams/out
--------------------------------------------------------------------------------
/project/target/streams/_global/moduleSettings/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/project/target/streams/_global/moduleSettings/_global/streams/out
--------------------------------------------------------------------------------
/project/target/streams/_global/projectDescriptors/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/project/target/streams/_global/projectDescriptors/_global/streams/out
--------------------------------------------------------------------------------
/project/target/streams/_global/scalaCompilerBridgeScope/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/project/target/streams/_global/scalaCompilerBridgeScope/_global/streams/out
--------------------------------------------------------------------------------
/project/target/streams/_global/update/_global/streams/out:
--------------------------------------------------------------------------------
1 | [0m[[0m[0mdebug[0m] [0m[0mnot up to date. inChanged = true, force = false[0m
2 | [0m[[0m[0mdebug[0m] [0m[0mUpdating ProjectRef(uri("file:/Users/daniel/dev/rockthejvm/courses/scala-2-advanced/project/"), "scala-2-advanced-build")...[0m
3 | [0m[[0m[33mwarn[0m] [0m[0mUnrecognized repository Scala Plugin Bundled Repository, ignoring it[0m
4 | [0m[[0m[33mwarn[0m] [0m[0mUnrecognized repository Scala Plugin Bundled Repository, ignoring it[0m
5 | [0m[[0m[0mdebug[0m] [0m[0mDone updating ProjectRef(uri("file:/Users/daniel/dev/rockthejvm/courses/scala-2-advanced/project/"), "scala-2-advanced-build")[0m
6 |
--------------------------------------------------------------------------------
/project/target/streams/compile/_global/_global/compileOutputs/previous:
--------------------------------------------------------------------------------
1 | ["sbt.Task[scala.collection.Seq[java.nio.file.Path]]",["/Users/daniel/dev/rockthejvm/courses/scala-2-advanced/project/target/scala-2.12/sbt-1.0/zinc/inc_compile_2.12.zip"]]
--------------------------------------------------------------------------------
/project/target/streams/compile/_global/_global/discoveredMainClasses/data:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/project/target/streams/compile/bspReporter/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/project/target/streams/compile/bspReporter/_global/streams/out
--------------------------------------------------------------------------------
/project/target/streams/compile/compile/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/project/target/streams/compile/compile/_global/streams/out
--------------------------------------------------------------------------------
/project/target/streams/compile/compileIncremental/_global/streams/export:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/project/target/streams/compile/compileIncremental/_global/streams/export
--------------------------------------------------------------------------------
/project/target/streams/compile/compileIncremental/_global/streams/out:
--------------------------------------------------------------------------------
1 | [0m[[0m[0mdebug[0m] [0m[0m[zinc] IncrementalCompile -----------[0m
2 | [0m[[0m[0mdebug[0m] [0m[0mIncrementalCompile.incrementalCompile[0m
3 | [0m[[0m[0mdebug[0m] [0m[0mprevious = Stamps for: 0 products, 0 sources, 0 libraries[0m
4 | [0m[[0m[0mdebug[0m] [0m[0mcurrent source = Set()[0m
5 | [0m[[0m[0mdebug[0m] [0m[0m> initialChanges = InitialChanges(Changes(added = Set(), removed = Set(), changed = Set(), unmodified = ...),Set(),Set(),API Changes: Set())[0m
6 | [0m[[0m[0mdebug[0m] [0m[0mFull compilation, no sources in previous analysis.[0m
7 |
--------------------------------------------------------------------------------
/project/target/streams/compile/copyResources/_global/streams/out:
--------------------------------------------------------------------------------
1 | [0m[[0m[0mdebug[0m] [0m[0mCopy resource mappings: [0m
2 | [0m[[0m[0mdebug[0m] [0m[0m [0m
3 |
--------------------------------------------------------------------------------
/project/target/streams/compile/dependencyClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 | /Users/daniel/.sbt/1.0/plugins/target/scala-2.12/sbt-1.0/classes:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-library.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-structure-extractor_2.12_1.0/2022.3.1/sbt-structure-extractor-2022.3.1.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-idea-shell_2.12_1.0/2021.1.0/sbt-idea-shell-2021.1.0.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-idea-compiler-indices_2.12_1.0/1.0.13/sbt-idea-compiler-indices-1.0.13.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/scala-compiler-indices-protocol_2.12/1.0.13/scala-compiler-indices-protocol_2.12-1.0.13.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/io/spray/spray-json_2.12/1.3.5/spray-json_2.12-1.3.5.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-compiler.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-reflect.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-xml_2.12-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/lm-coursier-shaded_2.12-2.0.13.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-classfile_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/librarymanagement-ivy_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/testing_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-cache_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-jawn-parser_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/task-system_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/librarymanagement-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-position_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-compile_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-reader-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-api-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/main_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sbt-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sbinary_2.12-0.5.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/error_prone_annotations-2.4.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/gigahorse-core_2.12-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/config-1.4.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/test-interface-1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-relation_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-interface-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/slf4j-api-2.0.3.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-tracking_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-core_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/file-tree-views-2.1.9.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/compiler-bridge_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/gigahorse-apache-http_2.12-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/checker-qual-3.4.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/caffeine-2.8.5.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/completion_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-compiler-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jna-5.12.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-core-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-apiinfo_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-slf4j-impl-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-2.14.7-sbt-a1b0ffbb8f64bb820f4f84a0c07a0c0964507493.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-jna-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ssl-config-core_2.12-0.6.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-compile-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/test-agent-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-lm-integration_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-reflect-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/launcher-interface-1.4.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-logging_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-jansi-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/run_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-parser-combinators_2.12-1.1.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ipcsocket-1.5.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/protocol_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/reactive-streams-1.0.3.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/compiler-interface-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jansi-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/disruptor-3.4.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-builtins-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-library-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-murmurhash_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/template-resolver-0.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-classpath_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/io_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-persist_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-scalajson_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jsch-0.1.54.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-xml_2.12-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-style-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/logic_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jna-platform-5.12.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-collection-compat_2.12-2.8.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-persist-core-assembly-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/collections_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scripted-plugin_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ivy-2.3.0-sbt-a8f9eb5bf09d0539ea3658a2c2d4e09755b5133e.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/tasks_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zero-allocation-hashing-0.10.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/command_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/main-settings_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/actions_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-scalajson_2.12-1.0.0-M4.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/core-macros_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-apache-httpasyncclient-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-control_2.12-1.8.0.jar
2 |
--------------------------------------------------------------------------------
/project/target/streams/compile/exportedProducts/_global/streams/export:
--------------------------------------------------------------------------------
1 | /Users/daniel/dev/rockthejvm/courses/scala-2-advanced/project/target/scala-2.12/sbt-1.0/classes
2 |
--------------------------------------------------------------------------------
/project/target/streams/compile/externalDependencyClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 | /Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-library.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-structure-extractor_2.12_1.0/2022.3.1/sbt-structure-extractor-2022.3.1.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-idea-shell_2.12_1.0/2021.1.0/sbt-idea-shell-2021.1.0.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-idea-compiler-indices_2.12_1.0/1.0.13/sbt-idea-compiler-indices-1.0.13.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/scala-compiler-indices-protocol_2.12/1.0.13/scala-compiler-indices-protocol_2.12-1.0.13.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/io/spray/spray-json_2.12/1.3.5/spray-json_2.12-1.3.5.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-compiler.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-reflect.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-xml_2.12-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/lm-coursier-shaded_2.12-2.0.13.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-classfile_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/librarymanagement-ivy_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/testing_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-cache_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-jawn-parser_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/task-system_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/librarymanagement-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-position_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-compile_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-reader-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-api-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/main_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sbt-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sbinary_2.12-0.5.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/error_prone_annotations-2.4.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/gigahorse-core_2.12-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/config-1.4.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/test-interface-1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-relation_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-interface-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/slf4j-api-2.0.3.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-tracking_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-core_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/file-tree-views-2.1.9.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/compiler-bridge_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/gigahorse-apache-http_2.12-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/checker-qual-3.4.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/caffeine-2.8.5.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/completion_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-compiler-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jna-5.12.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-core-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-apiinfo_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-slf4j-impl-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-2.14.7-sbt-a1b0ffbb8f64bb820f4f84a0c07a0c0964507493.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-jna-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ssl-config-core_2.12-0.6.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-compile-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/test-agent-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-lm-integration_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-reflect-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/launcher-interface-1.4.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-logging_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-jansi-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/run_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-parser-combinators_2.12-1.1.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ipcsocket-1.5.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/protocol_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/reactive-streams-1.0.3.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/compiler-interface-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jansi-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/disruptor-3.4.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-builtins-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-library-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-murmurhash_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/template-resolver-0.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-classpath_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/io_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-persist_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-scalajson_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jsch-0.1.54.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-xml_2.12-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-style-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/logic_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jna-platform-5.12.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-collection-compat_2.12-2.8.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-persist-core-assembly-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/collections_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scripted-plugin_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ivy-2.3.0-sbt-a8f9eb5bf09d0539ea3658a2c2d4e09755b5133e.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/tasks_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zero-allocation-hashing-0.10.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/command_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/main-settings_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/actions_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-scalajson_2.12-1.0.0-M4.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/core-macros_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-apache-httpasyncclient-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-control_2.12-1.8.0.jar
2 |
--------------------------------------------------------------------------------
/project/target/streams/compile/incOptions/_global/streams/out:
--------------------------------------------------------------------------------
1 | [0m[[0m[0mdebug[0m] [0m[0mCreated transactional ClassFileManager with tempDir = /Users/daniel/dev/rockthejvm/courses/scala-2-advanced/project/target/scala-2.12/sbt-1.0/classes.bak[0m
2 | [0m[[0m[0mdebug[0m] [0m[0mRemoving the temporary directory used for backing up class files: /Users/daniel/dev/rockthejvm/courses/scala-2-advanced/project/target/scala-2.12/sbt-1.0/classes.bak[0m
3 |
--------------------------------------------------------------------------------
/project/target/streams/compile/internalDependencyClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/project/target/streams/compile/internalDependencyClasspath/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/project/target/streams/compile/internalDependencyClasspath/_global/streams/out
--------------------------------------------------------------------------------
/project/target/streams/compile/managedClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 | /Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-library.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-structure-extractor_2.12_1.0/2022.3.1/sbt-structure-extractor-2022.3.1.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-idea-shell_2.12_1.0/2021.1.0/sbt-idea-shell-2021.1.0.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-idea-compiler-indices_2.12_1.0/1.0.13/sbt-idea-compiler-indices-1.0.13.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/scala-compiler-indices-protocol_2.12/1.0.13/scala-compiler-indices-protocol_2.12-1.0.13.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/io/spray/spray-json_2.12/1.3.5/spray-json_2.12-1.3.5.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-compiler.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-reflect.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-xml_2.12-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/lm-coursier-shaded_2.12-2.0.13.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-classfile_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/librarymanagement-ivy_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/testing_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-cache_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-jawn-parser_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/task-system_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/librarymanagement-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-position_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-compile_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-reader-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-api-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/main_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sbt-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sbinary_2.12-0.5.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/error_prone_annotations-2.4.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/gigahorse-core_2.12-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/config-1.4.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/test-interface-1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-relation_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-interface-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/slf4j-api-2.0.3.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-tracking_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-core_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/file-tree-views-2.1.9.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/compiler-bridge_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/gigahorse-apache-http_2.12-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/checker-qual-3.4.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/caffeine-2.8.5.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/completion_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-compiler-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jna-5.12.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-core-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-apiinfo_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-slf4j-impl-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-2.14.7-sbt-a1b0ffbb8f64bb820f4f84a0c07a0c0964507493.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-jna-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ssl-config-core_2.12-0.6.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-compile-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/test-agent-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-lm-integration_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-reflect-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/launcher-interface-1.4.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-logging_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-jansi-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/run_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-parser-combinators_2.12-1.1.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ipcsocket-1.5.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/protocol_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/reactive-streams-1.0.3.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/compiler-interface-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jansi-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/disruptor-3.4.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-builtins-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-library-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-murmurhash_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/template-resolver-0.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-classpath_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/io_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-persist_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-scalajson_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jsch-0.1.54.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-xml_2.12-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-style-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/logic_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jna-platform-5.12.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-collection-compat_2.12-2.8.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-persist-core-assembly-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/collections_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scripted-plugin_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ivy-2.3.0-sbt-a8f9eb5bf09d0539ea3658a2c2d4e09755b5133e.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/tasks_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zero-allocation-hashing-0.10.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/command_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/main-settings_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/actions_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-scalajson_2.12-1.0.0-M4.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/core-macros_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-apache-httpasyncclient-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-control_2.12-1.8.0.jar
2 |
--------------------------------------------------------------------------------
/project/target/streams/compile/scalacOptions/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/project/target/streams/compile/scalacOptions/_global/streams/out
--------------------------------------------------------------------------------
/project/target/streams/compile/unmanagedClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/project/target/streams/compile/unmanagedClasspath/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/project/target/streams/compile/unmanagedClasspath/_global/streams/out
--------------------------------------------------------------------------------
/project/target/streams/compile/unmanagedJars/_global/streams/export:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/project/target/streams/runtime/dependencyClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 | /Users/daniel/dev/rockthejvm/courses/scala-2-advanced/project/target/scala-2.12/sbt-1.0/classes:/Users/daniel/.sbt/1.0/plugins/target/scala-2.12/sbt-1.0/classes:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-structure-extractor_2.12_1.0/2022.3.1/sbt-structure-extractor-2022.3.1.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-idea-shell_2.12_1.0/2021.1.0/sbt-idea-shell-2021.1.0.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-idea-compiler-indices_2.12_1.0/1.0.13/sbt-idea-compiler-indices-1.0.13.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/scala-compiler-indices-protocol_2.12/1.0.13/scala-compiler-indices-protocol_2.12-1.0.13.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-library.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/io/spray/spray-json_2.12/1.3.5/spray-json_2.12-1.3.5.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-compiler.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-reflect.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-xml_2.12-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/lm-coursier-shaded_2.12-2.0.13.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-classfile_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/librarymanagement-ivy_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/testing_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-cache_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-jawn-parser_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/task-system_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/librarymanagement-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-position_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-compile_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-reader-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-api-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/main_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sbt-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sbinary_2.12-0.5.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/error_prone_annotations-2.4.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/gigahorse-core_2.12-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/config-1.4.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/test-interface-1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-relation_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-interface-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/slf4j-api-2.0.3.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-tracking_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-core_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/file-tree-views-2.1.9.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/compiler-bridge_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/gigahorse-apache-http_2.12-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/checker-qual-3.4.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/caffeine-2.8.5.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/completion_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-compiler-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jna-5.12.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-core-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-apiinfo_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-slf4j-impl-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-2.14.7-sbt-a1b0ffbb8f64bb820f4f84a0c07a0c0964507493.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-jna-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ssl-config-core_2.12-0.6.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-compile-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/test-agent-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-lm-integration_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-reflect-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/launcher-interface-1.4.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-logging_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-jansi-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/run_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-parser-combinators_2.12-1.1.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ipcsocket-1.5.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/protocol_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/reactive-streams-1.0.3.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/compiler-interface-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jansi-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/disruptor-3.4.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-builtins-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-library-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-murmurhash_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/template-resolver-0.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-classpath_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/io_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-persist_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-scalajson_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jsch-0.1.54.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-xml_2.12-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-style-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/logic_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jna-platform-5.12.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-collection-compat_2.12-2.8.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-persist-core-assembly-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/collections_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scripted-plugin_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ivy-2.3.0-sbt-a8f9eb5bf09d0539ea3658a2c2d4e09755b5133e.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/tasks_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zero-allocation-hashing-0.10.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/command_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/main-settings_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/actions_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-scalajson_2.12-1.0.0-M4.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/core-macros_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-apache-httpasyncclient-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-control_2.12-1.8.0.jar
2 |
--------------------------------------------------------------------------------
/project/target/streams/runtime/exportedProducts/_global/streams/export:
--------------------------------------------------------------------------------
1 | /Users/daniel/dev/rockthejvm/courses/scala-2-advanced/project/target/scala-2.12/sbt-1.0/classes
2 |
--------------------------------------------------------------------------------
/project/target/streams/runtime/externalDependencyClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 | /Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-structure-extractor_2.12_1.0/2022.3.1/sbt-structure-extractor-2022.3.1.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-idea-shell_2.12_1.0/2021.1.0/sbt-idea-shell-2021.1.0.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-idea-compiler-indices_2.12_1.0/1.0.13/sbt-idea-compiler-indices-1.0.13.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/scala-compiler-indices-protocol_2.12/1.0.13/scala-compiler-indices-protocol_2.12-1.0.13.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-library.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/io/spray/spray-json_2.12/1.3.5/spray-json_2.12-1.3.5.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-compiler.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-reflect.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-xml_2.12-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/lm-coursier-shaded_2.12-2.0.13.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-classfile_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/librarymanagement-ivy_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/testing_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-cache_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-jawn-parser_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/task-system_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/librarymanagement-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-position_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-compile_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-reader-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-api-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/main_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sbt-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sbinary_2.12-0.5.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/error_prone_annotations-2.4.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/gigahorse-core_2.12-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/config-1.4.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/test-interface-1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-relation_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-interface-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/slf4j-api-2.0.3.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-tracking_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-core_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/file-tree-views-2.1.9.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/compiler-bridge_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/gigahorse-apache-http_2.12-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/checker-qual-3.4.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/caffeine-2.8.5.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/completion_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-compiler-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jna-5.12.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-core-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-apiinfo_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-slf4j-impl-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-2.14.7-sbt-a1b0ffbb8f64bb820f4f84a0c07a0c0964507493.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-jna-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ssl-config-core_2.12-0.6.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-compile-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/test-agent-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-lm-integration_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-reflect-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/launcher-interface-1.4.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-logging_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-jansi-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/run_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-parser-combinators_2.12-1.1.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ipcsocket-1.5.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/protocol_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/reactive-streams-1.0.3.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/compiler-interface-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jansi-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/disruptor-3.4.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-builtins-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-library-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-murmurhash_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/template-resolver-0.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-classpath_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/io_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-persist_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-scalajson_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jsch-0.1.54.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-xml_2.12-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-style-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/logic_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jna-platform-5.12.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-collection-compat_2.12-2.8.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-persist-core-assembly-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/collections_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scripted-plugin_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ivy-2.3.0-sbt-a8f9eb5bf09d0539ea3658a2c2d4e09755b5133e.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/tasks_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zero-allocation-hashing-0.10.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/command_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/main-settings_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/actions_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-scalajson_2.12-1.0.0-M4.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/core-macros_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-apache-httpasyncclient-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-control_2.12-1.8.0.jar
2 |
--------------------------------------------------------------------------------
/project/target/streams/runtime/fullClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 | /Users/daniel/dev/rockthejvm/courses/scala-2-advanced/project/target/scala-2.12/sbt-1.0/classes:/Users/daniel/.sbt/1.0/plugins/target/scala-2.12/sbt-1.0/classes:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-structure-extractor_2.12_1.0/2022.3.1/sbt-structure-extractor-2022.3.1.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-idea-shell_2.12_1.0/2021.1.0/sbt-idea-shell-2021.1.0.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-idea-compiler-indices_2.12_1.0/1.0.13/sbt-idea-compiler-indices-1.0.13.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/scala-compiler-indices-protocol_2.12/1.0.13/scala-compiler-indices-protocol_2.12-1.0.13.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-library.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/io/spray/spray-json_2.12/1.3.5/spray-json_2.12-1.3.5.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-compiler.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-reflect.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-xml_2.12-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/lm-coursier-shaded_2.12-2.0.13.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-classfile_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/librarymanagement-ivy_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/testing_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-cache_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-jawn-parser_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/task-system_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/librarymanagement-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-position_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-compile_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-reader-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-api-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/main_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sbt-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sbinary_2.12-0.5.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/error_prone_annotations-2.4.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/gigahorse-core_2.12-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/config-1.4.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/test-interface-1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-relation_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-interface-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/slf4j-api-2.0.3.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-tracking_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-core_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/file-tree-views-2.1.9.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/compiler-bridge_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/gigahorse-apache-http_2.12-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/checker-qual-3.4.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/caffeine-2.8.5.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/completion_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-compiler-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jna-5.12.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-core-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-apiinfo_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-slf4j-impl-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-2.14.7-sbt-a1b0ffbb8f64bb820f4f84a0c07a0c0964507493.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-jna-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ssl-config-core_2.12-0.6.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-compile-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/test-agent-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-lm-integration_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-reflect-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/launcher-interface-1.4.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-logging_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-jansi-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/run_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-parser-combinators_2.12-1.1.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ipcsocket-1.5.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/protocol_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/reactive-streams-1.0.3.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/compiler-interface-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jansi-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/disruptor-3.4.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-builtins-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-library-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-murmurhash_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/template-resolver-0.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-classpath_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/io_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-persist_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-scalajson_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jsch-0.1.54.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-xml_2.12-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-style-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/logic_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jna-platform-5.12.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-collection-compat_2.12-2.8.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-persist-core-assembly-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/collections_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scripted-plugin_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ivy-2.3.0-sbt-a8f9eb5bf09d0539ea3658a2c2d4e09755b5133e.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/tasks_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zero-allocation-hashing-0.10.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/command_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/main-settings_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/actions_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-scalajson_2.12-1.0.0-M4.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/core-macros_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-apache-httpasyncclient-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-control_2.12-1.8.0.jar
2 |
--------------------------------------------------------------------------------
/project/target/streams/runtime/internalDependencyClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 | /Users/daniel/dev/rockthejvm/courses/scala-2-advanced/project/target/scala-2.12/sbt-1.0/classes
2 |
--------------------------------------------------------------------------------
/project/target/streams/runtime/internalDependencyClasspath/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/project/target/streams/runtime/internalDependencyClasspath/_global/streams/out
--------------------------------------------------------------------------------
/project/target/streams/runtime/managedClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 | /Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-structure-extractor_2.12_1.0/2022.3.1/sbt-structure-extractor-2022.3.1.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-idea-shell_2.12_1.0/2021.1.0/sbt-idea-shell-2021.1.0.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/sbt-idea-compiler-indices_2.12_1.0/1.0.13/sbt-idea-compiler-indices-1.0.13.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/jetbrains/scala/scala-compiler-indices-protocol_2.12/1.0.13/scala-compiler-indices-protocol_2.12-1.0.13.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-library.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/io/spray/spray-json_2.12/1.3.5/spray-json_2.12-1.3.5.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-compiler.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-reflect.jar:/Users/daniel/.sbt/boot/scala-2.12.17/lib/scala-xml_2.12-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/lm-coursier-shaded_2.12-2.0.13.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-classfile_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/librarymanagement-ivy_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/testing_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-cache_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-jawn-parser_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/task-system_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/librarymanagement-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-position_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-compile_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-reader-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-api-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/main_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sbt-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sbinary_2.12-0.5.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/error_prone_annotations-2.4.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/gigahorse-core_2.12-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/config-1.4.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/test-interface-1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-relation_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-interface-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/slf4j-api-2.0.3.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-tracking_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-core_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/file-tree-views-2.1.9.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/compiler-bridge_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/gigahorse-apache-http_2.12-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/checker-qual-3.4.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/caffeine-2.8.5.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/completion_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-compiler-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jna-5.12.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-core-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-apiinfo_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/log4j-slf4j-impl-2.17.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-2.14.7-sbt-a1b0ffbb8f64bb820f4f84a0c07a0c0964507493.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-jna-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ssl-config-core_2.12-0.6.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-compile-core_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/test-agent-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-lm-integration_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-reflect-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/launcher-interface-1.4.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-logging_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-terminal-jansi-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/run_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-parser-combinators_2.12-1.1.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ipcsocket-1.5.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/protocol_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/reactive-streams-1.0.3.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/compiler-interface-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jansi-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/disruptor-3.4.2.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-builtins-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-library-2.12.17.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-murmurhash_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/template-resolver-0.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-classpath_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/io_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-persist_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/sjson-new-scalajson_2.12-0.9.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jsch-0.1.54.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-xml_2.12-2.1.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jline-style-3.19.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/logic_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/jna-platform-5.12.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scala-collection-compat_2.12-2.8.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zinc-persist-core-assembly-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/collections_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/scripted-plugin_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/ivy-2.3.0-sbt-a8f9eb5bf09d0539ea3658a2c2d4e09755b5133e.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/tasks_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/zero-allocation-hashing-0.10.1.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/command_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/main-settings_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/actions_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-scalajson_2.12-1.0.0-M4.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/core-macros_2.12-1.8.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/shaded-apache-httpasyncclient-0.7.0.jar:/Users/daniel/.sbt/boot/scala-2.12.17/org.scala-sbt/sbt/1.8.0/util-control_2.12-1.8.0.jar
2 |
--------------------------------------------------------------------------------
/project/target/streams/runtime/unmanagedClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/project/target/streams/runtime/unmanagedClasspath/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/project/target/streams/runtime/unmanagedClasspath/_global/streams/out
--------------------------------------------------------------------------------
/project/target/streams/runtime/unmanagedJars/_global/streams/export:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/src/.DS_Store
--------------------------------------------------------------------------------
/src/exercises/EqualityPlayground.scala:
--------------------------------------------------------------------------------
1 | package exercises
2 |
3 | import lectures.part4implicits.TypeClasses.User
4 |
5 | /**
6 | * Created by Daniel.
7 | */
8 | object EqualityPlayground extends App {
9 |
10 | /**
11 | * Equality
12 | */
13 | trait Equal[T] {
14 | def apply(a: T, b: T): Boolean
15 | }
16 |
17 | implicit object NameEquality extends Equal[User] {
18 | override def apply(a: User, b: User): Boolean = a.name == b.name
19 | }
20 |
21 | object FullEquality extends Equal[User] {
22 | override def apply(a: User, b: User): Boolean = a.name == b.name && a.email == b.email
23 | }
24 |
25 | /*
26 | Exercise: implement the TC pattern for the Equality tc.
27 | */
28 | object Equal {
29 | def apply[T](a: T, b: T)(implicit equalizer: Equal[T]): Boolean =
30 | equalizer.apply(a, b)
31 | }
32 |
33 | val john = User("John", 32, "john@rockthejvm.com")
34 | val anotherJohn = User("John", 45, "anotherJohn@rtjvm.com")
35 | println(Equal(john, anotherJohn))
36 | // AD-HOC polymorphism
37 |
38 | /*
39 | Exercise - improve the Equal TC with an implicit conversion class
40 | ===(anotherValue: T)
41 | !==(anotherValue: T)
42 | */
43 | implicit class TypeSafeEqual[T](value: T) {
44 | def ===(other: T)(implicit equalizer: Equal[T]): Boolean = equalizer.apply(value, other)
45 | def !==(other: T)(implicit equalizer: Equal[T]): Boolean = ! equalizer.apply(value, other)
46 | }
47 |
48 | println(john === anotherJohn)
49 | /*
50 | john.===(anotherJohn)
51 | new TypeSafeEqual[User](john).===(anotherJohn)
52 | new TypeSafeEqual[User](john).===(anotherJohn)(NameEquality)
53 | */
54 | /*
55 | TYPE SAFE
56 | */
57 | println(john == 43)
58 | // println(john === 43) // TYPE SAFE
59 | }
60 |
--------------------------------------------------------------------------------
/src/exercises/MySet.scala:
--------------------------------------------------------------------------------
1 | package exercises
2 |
3 | import scala.annotation.tailrec
4 |
5 | /**
6 | * Created by Daniel.
7 | */
8 | trait MySet[A] extends (A => Boolean) {
9 |
10 | /*
11 | EXERCISE - implement a functional set
12 | */
13 | def apply(elem: A): Boolean =
14 | contains(elem)
15 |
16 | def contains(elem: A): Boolean
17 | def +(elem: A): MySet[A]
18 | def ++(anotherSet: MySet[A]): MySet[A] // union
19 |
20 | def map[B](f: A => B): MySet[B]
21 | def flatMap[B](f: A => MySet[B]): MySet[B]
22 | def filter(predicate: A => Boolean): MySet[A]
23 | def foreach(f: A => Unit): Unit
24 |
25 | /*
26 | EXERCISE #2
27 | - removing an element
28 | - intersection with another set
29 | - difference with another set
30 | */
31 | def -(elem: A): MySet[A]
32 | def --(anotherSet: MySet[A]): MySet[A] // difference
33 | def &(anotherSet: MySet[A]): MySet[A] // intersection
34 |
35 | // EXERCISE #3 - implement a unary_! = NEGATION of a set
36 | // set[1,2,3] =>
37 | def unary_! : MySet[A]
38 | }
39 |
40 | class EmptySet[A] extends MySet[A] {
41 | def contains(elem: A): Boolean = false
42 | def +(elem: A): MySet[A] = new NonEmptySet[A](elem, this)
43 | def ++(anotherSet: MySet[A]): MySet[A] = anotherSet
44 |
45 | def map[B](f: A => B): MySet[B] = new EmptySet[B]
46 | def flatMap[B](f: A => MySet[B]): MySet[B] = new EmptySet[B]
47 | def filter(predicate: A => Boolean): MySet[A] = this
48 | def foreach(f: A => Unit): Unit = ()
49 |
50 | // part 2
51 | def -(elem: A): MySet[A] = this
52 | def --(anotherSet: MySet[A]): MySet[A] = this
53 | def &(anotherSet: MySet[A]): MySet[A] = this
54 |
55 | def unary_! : MySet[A] = new PropertyBasedSet[A](_ => true)
56 | }
57 |
58 | // all elements of type A which satisfy a property
59 | // { x in A | property(x) }
60 | class PropertyBasedSet[A](property: A => Boolean) extends MySet[A] {
61 | def contains(elem: A): Boolean = property(elem)
62 | // { x in A | property(x) } + element = { x in A | property(x) || x == element }
63 | def +(elem: A): MySet[A] =
64 | new PropertyBasedSet[A](x => property(x) || x == elem)
65 |
66 | // { x in A | property(x) } ++ set => { x in A | property(x) || set contains x }
67 | def ++(anotherSet: MySet[A]): MySet[A] =
68 | new PropertyBasedSet[A](x => property(x) || anotherSet(x))
69 |
70 | // all integers => (_ % 3) => [0 1 2]
71 | def map[B](f: A => B): MySet[B] = politelyFail
72 | def flatMap[B](f: A => MySet[B]): MySet[B] = politelyFail
73 | def foreach(f: A => Unit): Unit = politelyFail
74 |
75 | def filter(predicate: A => Boolean): MySet[A] = new PropertyBasedSet[A](x => property(x) && predicate(x))
76 | def -(elem: A): MySet[A] = filter(x => x != elem)
77 | def --(anotherSet: MySet[A]): MySet[A] = filter(!anotherSet)
78 | def &(anotherSet: MySet[A]): MySet[A] = filter(anotherSet)
79 | def unary_! : MySet[A] = new PropertyBasedSet[A](x => !property(x))
80 |
81 | def politelyFail = throw new IllegalArgumentException("Really deep rabbit hole!")
82 | }
83 |
84 | class NonEmptySet[A](head: A, tail: MySet[A]) extends MySet[A] {
85 | def contains(elem: A): Boolean =
86 | elem == head || tail.contains(elem)
87 |
88 | def +(elem: A): MySet[A] =
89 | if (this contains elem) this
90 | else new NonEmptySet[A](elem, this)
91 |
92 | /*
93 | [1 2 3] ++ [4 5] =
94 | [2 3] ++ [4 5] + 1 =
95 | [3] ++ [4 5] + 1 + 2 =
96 | [] ++ [4 5] + 1 + 2 + 3
97 | [4 5] + 1 + 2 + 3 = [4 5 1 2 3]
98 | */
99 | def ++(anotherSet: MySet[A]): MySet[A] =
100 | tail ++ anotherSet + head
101 |
102 | def map[B](f: A => B): MySet[B] = (tail map f) + f(head)
103 | def flatMap[B](f: A => MySet[B]): MySet[B] = (tail flatMap f) ++ f(head)
104 | def filter(predicate: A => Boolean): MySet[A] = {
105 | val filteredTail = tail filter predicate
106 | if (predicate(head)) filteredTail + head
107 | else filteredTail
108 | }
109 |
110 | def foreach(f: A => Unit): Unit = {
111 | f(head)
112 | tail foreach f
113 | }
114 |
115 | // part 2
116 | def -(elem: A): MySet[A] =
117 | if (head == elem) tail
118 | else tail - elem + head
119 |
120 | def --(anotherSet: MySet[A]): MySet[A] = filter(!anotherSet)
121 | def &(anotherSet: MySet[A]): MySet[A] = filter(anotherSet) // intersection = filtering!
122 |
123 | // new operator
124 | def unary_! : MySet[A] = new PropertyBasedSet[A](x => !this.contains(x))
125 | }
126 |
127 | object MySet {
128 | /*
129 | val s = MySet(1,2,3) = buildSet(seq(1,2,3), [])
130 | = buildSet(seq(2,3), [] + 1)
131 | = buildSet(seq(3), [1] + 2)
132 | = buildSet(seq(), [1, 2] + 3)
133 | = [1,2,3]
134 | */
135 | def apply[A](values: A*): MySet[A] = {
136 | @tailrec
137 | def buildSet(valSeq: Seq[A], acc: MySet[A]): MySet[A] =
138 | if (valSeq.isEmpty) acc
139 | else buildSet(valSeq.tail, acc + valSeq.head)
140 |
141 | buildSet(values, new EmptySet[A])
142 | }
143 | }
144 |
145 | object MySetPlayground extends App {
146 | val s = MySet(1,2,3,4)
147 | s + 5 ++ MySet(-1, -2) + 3 flatMap (x => MySet(x, 10 * x)) filter (_ % 2 == 0) foreach println
148 |
149 |
150 | val negative = !s // s.unary_! = all the naturals not equal to 1,2,3,4
151 | println(negative(2))
152 | println(negative(5))
153 |
154 | val negativeEven = negative.filter(_ % 2 == 0)
155 | println(negativeEven(5))
156 |
157 | val negativeEven5 = negativeEven + 5 // all the even numbers > 4 + 5
158 | println(negativeEven5(5))
159 | }
160 |
--------------------------------------------------------------------------------
/src/exercises/StreamsPlayground.scala:
--------------------------------------------------------------------------------
1 | package exercises
2 |
3 | import scala.annotation.tailrec
4 |
5 |
6 | /**
7 | * Created by Daniel.
8 | */
9 |
10 | abstract class MyStream[+A] {
11 | def isEmpty: Boolean
12 | def head: A
13 | def tail: MyStream[A]
14 |
15 | def #::[B >: A](element: B): MyStream[B] // prepend operator
16 | def ++[B >: A](anotherStream: => MyStream[B]): MyStream[B] // concatenate two streams
17 |
18 | def foreach(f: A => Unit): Unit
19 | def map[B](f: A => B): MyStream[B]
20 | def flatMap[B](f: A => MyStream[B]): MyStream[B]
21 | def filter(predicate: A => Boolean): MyStream[A]
22 |
23 | def take(n: Int): MyStream[A] // takes the first n elements out of this stream
24 | def takeAsList(n: Int): List[A] = take(n).toList()
25 |
26 | /*
27 | [1 2 3].toList([]) =
28 | [2 3].toList([1]) =
29 | [3].toList([2 1]) =
30 | [].toList([3 2 1])
31 | = [1 2 3]
32 | */
33 | @tailrec
34 | final def toList[B >: A](acc: List[B] = Nil): List[B] =
35 | if (isEmpty) acc.reverse
36 | else tail.toList(head :: acc)
37 | }
38 |
39 | object EmptyStream extends MyStream[Nothing] {
40 | def isEmpty: Boolean = true
41 | def head: Nothing = throw new NoSuchElementException
42 | def tail: MyStream[Nothing] = throw new NoSuchElementException
43 |
44 | def #::[B >: Nothing](element: B): MyStream[B] = new Cons(element, this)
45 | def ++[B >: Nothing](anotherStream: => MyStream[B]): MyStream[B] = anotherStream
46 |
47 | def foreach(f: Nothing => Unit): Unit = ()
48 | def map[B](f: Nothing => B): MyStream[B] = this
49 | def flatMap[B](f: Nothing => MyStream[B]): MyStream[B] = this
50 | def filter(predicate: Nothing => Boolean): MyStream[Nothing] = this
51 |
52 | def take(n: Int): MyStream[Nothing] = this
53 | }
54 |
55 | class Cons[+A](hd: A, tl: => MyStream[A]) extends MyStream[A] {
56 | def isEmpty: Boolean = false
57 |
58 | override val head: A = hd
59 | override lazy val tail: MyStream[A] = tl // call by need
60 | /*
61 | val s = new Cons(1, EmptyStream)
62 | val prepended = 1 #:: s = new Cons(1, s)
63 | */
64 | def #::[B >: A](element: B): MyStream[B] = new Cons(element, this)
65 | def ++[B >: A](anotherStream: => MyStream[B]): MyStream[B] = new Cons(head, tail ++ anotherStream)
66 |
67 | def foreach(f: A => Unit): Unit = {
68 | f(head)
69 | tail.foreach(f)
70 | }
71 |
72 | /*
73 | s = new Cons(1, ?)
74 | mapped = s.map(_ + 1) = new Cons(2, s.tail.map(_ + 1))
75 | ... mapped.tail
76 | */
77 | def map[B](f: A => B): MyStream[B] = new Cons(f(head), tail.map(f)) // preserves lazy evaluation
78 | def flatMap[B](f: A => MyStream[B]): MyStream[B] = f(head) ++ tail.flatMap(f)
79 | def filter(predicate: A => Boolean): MyStream[A] =
80 | if (predicate(head)) new Cons(head, tail.filter(predicate))
81 | else tail.filter(predicate) // preserves lazy eval!
82 |
83 | def take(n: Int): MyStream[A] =
84 | if (n <= 0) EmptyStream
85 | else if (n == 1) new Cons(head, EmptyStream)
86 | else new Cons(head, tail.take(n-1))
87 | }
88 |
89 | object MyStream {
90 | def from[A](start: A)(generator: A => A): MyStream[A] =
91 | new Cons(start, MyStream.from(generator(start))(generator))
92 | }
93 |
94 |
95 | object StreamsPlayground extends App{
96 | val naturals = MyStream.from(1)(_ + 1)
97 | println(naturals.head)
98 | println(naturals.tail.head)
99 | println(naturals.tail.tail.head)
100 |
101 | val startFrom0 = 0 #:: naturals // naturals.#::(0)
102 | println(startFrom0.head)
103 |
104 | startFrom0.take(10000).foreach(println)
105 |
106 | // map, flatMap
107 | println(startFrom0.map(_ * 2).take(100).toList())
108 | println(startFrom0.flatMap(x => new Cons(x, new Cons(x + 1, EmptyStream))).take(10).toList())
109 | println(startFrom0.filter(_ < 10).take(10).take(20).toList())
110 |
111 | // Exercises on streams
112 | // 1 - stream of Fibonacci numbers
113 | // 2 - stream of prime numbers with Eratosthenes' sieve
114 | /*
115 | [ 2 3 4 ... ]
116 | filter out all numbers divisible by 2
117 | [ 2 3 5 7 9 11 ...]
118 | filter out all numbers divisible by 3
119 | [ 2 3 5 7 11 13 17 ... ]
120 | filter out all numbers divisible by 5
121 | ...
122 | */
123 |
124 | /*
125 | [ first, [ ...
126 | [ first, fibo(second, first + second)
127 | */
128 | def fibonacci(first: BigInt, second: BigInt): MyStream[BigInt] =
129 | new Cons(first, fibonacci(second, first + second))
130 |
131 | println(fibonacci(1, 1).take(100).toList())
132 |
133 | /*
134 | [ 2 3 4 5 6 7 8 9 10 11 12 ...
135 | [ 2 3 5 7 9 11 13 ...
136 | [ 2 eratosthenes applied to (numbers filtered by n % 2 != 0)
137 | [ 2 3 eratosthenes applied to [ 5 7 9 11 ... ] filtered by n % 3 != 0
138 | [ 2 3 5
139 | */
140 | // eratosthenes sieve
141 | def eratosthenes(numbers: MyStream[Int]): MyStream[Int] =
142 | if (numbers.isEmpty) numbers
143 | else new Cons(numbers.head, eratosthenes(numbers.tail.filter(_ % numbers.head != 0)))
144 |
145 | val primes = eratosthenes(MyStream.from(2)(_ + 1))
146 |
147 | def isPrime(n: Int) = {
148 | def isPrimeRec(primesStream: MyStream[Int]): Boolean =
149 | if (primesStream.head > n / 2) true
150 | else if (n % primesStream.head == 0) false
151 | else isPrimeRec(primesStream.tail)
152 |
153 | isPrimeRec(primes)
154 | }
155 |
156 | primes.take(10000).foreach(println)
157 |
158 | }
--------------------------------------------------------------------------------
/src/lectures/part1as/AdvancedPatternMatching.scala:
--------------------------------------------------------------------------------
1 | package lectures.part1as
2 |
3 | /**
4 | * Created by Daniel.
5 | */
6 | object AdvancedPatternMatching extends App {
7 |
8 | val numbers = List(1)
9 | val description = numbers match {
10 | case head :: Nil => println(s"the only element is $head.")
11 | case _ =>
12 | }
13 |
14 | /*
15 | - constants
16 | - wildcards
17 | - case classes
18 | - tuples
19 | - some special magic like above
20 | */
21 |
22 | class Person(val name: String, val age: Int)
23 |
24 | object Person {
25 | def unapply(person: Person): Option[(String, Int)] =
26 | if (person.age < 21) None
27 | else Some((person.name, person.age))
28 |
29 | def unapply(age: Int): Option[String] =
30 | Some(if (age < 21) "minor" else "major")
31 | }
32 |
33 | val bob = new Person("Bob", 25)
34 | val greeting = bob match {
35 | case Person(n, a) => s"Hi, my name is $n and I am $a yo."
36 | }
37 |
38 | println(greeting)
39 |
40 | val legalStatus = bob.age match {
41 | case Person(status) => s"My legal status is $status"
42 | }
43 |
44 | println(legalStatus)
45 |
46 | /*
47 | Exercise.
48 | */
49 |
50 | object even {
51 | def unapply(arg: Int): Boolean = arg % 2 == 0
52 | }
53 |
54 | object singleDigit {
55 | def unapply(arg: Int): Boolean = arg > -10 && arg < 10
56 | }
57 |
58 | val n: Int = 8
59 | val mathProperty = n match {
60 | case singleDigit() => "single digit"
61 | case even() => "an even number"
62 | case _ => "no property"
63 | }
64 |
65 | println(mathProperty)
66 |
67 | // infix patterns
68 | case class Or[A, B](a: A, b: B)
69 | val either = Or(2, "two")
70 | val humanDescription = either match {
71 | case number Or string => s"$number is written as $string"
72 | }
73 | println(humanDescription)
74 |
75 | // decomposing sequences
76 | val vararg = numbers match {
77 | case List(1, _*) => "starting with 1"
78 | }
79 |
80 | abstract class MyList[+A] {
81 | def head: A = ???
82 | def tail: MyList[A] = ???
83 | }
84 | case object Empty extends MyList[Nothing]
85 | case class Cons[+A](override val head: A, override val tail: MyList[A]) extends MyList[A]
86 |
87 | object MyList {
88 | def unapplySeq[A](list: MyList[A]): Option[Seq[A]] =
89 | if (list == Empty) Some(Seq.empty)
90 | else unapplySeq(list.tail).map(list.head +: _)
91 | }
92 |
93 | val myList: MyList[Int] = Cons(1, Cons(2, Cons(3, Empty)))
94 | val decomposed = myList match {
95 | case MyList(1, 2, _*) => "starting with 1, 2"
96 | case _ => "something else"
97 | }
98 |
99 | println(decomposed)
100 |
101 | // custom return types for unapply
102 | // isEmpty: Boolean, get: something.
103 |
104 | abstract class Wrapper[T] {
105 | def isEmpty: Boolean
106 | def get: T
107 | }
108 |
109 | object PersonWrapper {
110 | def unapply(person: Person): Wrapper[String] = new Wrapper[String] {
111 | def isEmpty = false
112 | def get= person.name
113 | }
114 | }
115 |
116 | println(bob match {
117 | case PersonWrapper(n) => s"This person's name is $n"
118 | case _ => "An alien"
119 | })
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/src/lectures/part1as/DarkSugars.scala:
--------------------------------------------------------------------------------
1 | package lectures.part1as
2 |
3 | import scala.util.Try
4 |
5 | /**
6 | * Created by Daniel.
7 | */
8 | object DarkSugars extends App {
9 |
10 | // syntax sugar #1: methods with single param
11 | def singleArgMethod(arg: Int): String = s"$arg little ducks..."
12 |
13 | val description = singleArgMethod {
14 | // write some complex code
15 | 42
16 | }
17 |
18 | val aTryInstance = Try { // java's try {...}
19 | throw new RuntimeException
20 | }
21 |
22 | List(1,2,3).map { x =>
23 | x + 1
24 | }
25 |
26 | // syntax sugar #2: single abstract method
27 | trait Action {
28 | def act(x: Int): Int
29 | }
30 |
31 | val anInstance: Action = new Action {
32 | override def act(x: Int): Int = x + 1
33 | }
34 |
35 | val aFunkyInstance: Action = (x: Int) => x + 1 // magic
36 |
37 | // example: Runnables
38 | val aThread = new Thread(new Runnable {
39 | override def run(): Unit = println("hello, Scala")
40 | })
41 |
42 | val aSweeterThread = new Thread(() => println("sweet, Scala!"))
43 |
44 | abstract class AnAbstractType {
45 | def implemented: Int = 23
46 | def f(a: Int): Unit
47 | }
48 |
49 | val anAbstractInstance: AnAbstractType = (a: Int) => println("sweet")
50 |
51 | // syntax sugar #3: the :: and #:: methods are special
52 |
53 | val prependedList = 2 :: List(3, 4)
54 | // 2.::(List(3,4))
55 | // List(3,4).::(2)
56 | // ?!
57 |
58 | // scala spec: last char decides associativity of method
59 | 1 :: 2 :: 3 :: List(4, 5)
60 | List(4,5).::(3).::(2).::(1) // equivalent
61 |
62 | class MyStream[T] {
63 | def -->:(value: T): MyStream[T] = this // actual implementation here
64 | }
65 |
66 | val myStream = 1 -->: 2 -->: 3 -->: new MyStream[Int]
67 |
68 | // syntax sugar #4: multi-word method naming
69 |
70 | class TeenGirl(name: String) {
71 | def `and then said`(gossip: String) = println(s"$name said $gossip")
72 | }
73 |
74 | val lilly = new TeenGirl("Lilly")
75 | lilly `and then said` "Scala is so sweet!"
76 |
77 | // syntax sugar #5: infix types
78 | class Composite[A, B]
79 | val composite: Int Composite String = ???
80 |
81 | class -->[A, B]
82 | val towards: Int --> String = ???
83 |
84 | // syntax sugar #6: update() is very special, much like apply()
85 | val anArray = Array(1,2,3)
86 | anArray(2) = 7 // rewritten to anArray.update(2, 7)
87 | // used in mutable collections
88 | // remember apply() AND update()!
89 |
90 | // syntax sugar #7: setters for mutable containers
91 | class Mutable {
92 | private var internalMember: Int = 0 // private for OO encapsulation
93 | def member = internalMember // "getter"
94 | def member_=(value: Int): Unit =
95 | internalMember = value // "setter"
96 | }
97 |
98 | val aMutableContainer = new Mutable
99 | aMutableContainer.member = 42 // rewrittern as aMutableContainer.member_=(42)
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/src/lectures/part1as/Recap.scala:
--------------------------------------------------------------------------------
1 | package lectures.part1as
2 |
3 | import scala.annotation.tailrec
4 |
5 |
6 | /**
7 | * Created by Daniel.
8 | */
9 | object Recap extends App {
10 |
11 | val aCondition: Boolean = false
12 | val aConditionedVal = if (aCondition) 42 else 65
13 | // instructions vs expressions
14 |
15 | // compiler infers types for us
16 | val aCodeBlock = {
17 | if (aCondition) 54
18 | 56
19 | }
20 |
21 | // Unit = void
22 | val theUnit = println("hello, Scala")
23 |
24 | // functions
25 | def aFunction(x: Int): Int = x + 1
26 |
27 | // recursion: stack and tail
28 | @tailrec def factorial(n: Int, accumulator: Int): Int =
29 | if (n <= 0) accumulator
30 | else factorial(n - 1, n * accumulator)
31 |
32 | // object-oriented programming
33 |
34 | class Animal
35 | class Dog extends Animal
36 | val aDog: Animal = new Dog // subtyping polymorphism
37 |
38 | trait Carnivore {
39 | def eat(a: Animal): Unit
40 | }
41 |
42 | class Crocodile extends Animal with Carnivore {
43 | override def eat(a: Animal): Unit = println("crunch!")
44 | }
45 |
46 | // method notations
47 | val aCroc = new Crocodile
48 | aCroc.eat(aDog)
49 | aCroc eat aDog // natural language
50 |
51 | // anonymous classes
52 | val aCarnivore = new Carnivore {
53 | override def eat(a: Animal): Unit = println("roar!")
54 | }
55 |
56 | // generics
57 | abstract class MyList[+A] // variance and variance problems in THIS course
58 | // singletons and companions
59 | object MyList
60 |
61 | // case classes
62 | case class Person(name: String, age: Int)
63 |
64 | // exceptions and try/catch/finally
65 |
66 | val throwsException = throw new RuntimeException // Nothing
67 | val aPotentialFailure = try {
68 | throw new RuntimeException
69 | } catch {
70 | case e: Exception => "I caught an exception"
71 | } finally {
72 | println("some logs")
73 | }
74 |
75 | // packaging and imports
76 |
77 | // functional programming
78 | val incrementer = new Function1[Int, Int] {
79 | override def apply(v1: Int): Int = v1 + 1
80 | }
81 |
82 | incrementer(1)
83 |
84 | val anonymousIncrementer = (x: Int) => x + 1
85 | List(1,2,3).map(anonymousIncrementer) // HOF
86 | // map, flatMap, filter
87 |
88 | // for-comprehension
89 | val pairs = for {
90 | num <- List(1,2,3) // if condition
91 | char <- List('a', 'b', 'c')
92 | } yield num + "-" + char
93 |
94 | // Scala collections: Seqs, Arrays, Lists, Vectors, Maps, Tuples
95 | val aMap = Map(
96 | "Daniel" -> 789,
97 | "Jess" -> 555
98 | )
99 |
100 | // "collections": Options, Try
101 | val anOption = Some(2)
102 |
103 | // pattern matching
104 | val x = 2
105 | val order = x match {
106 | case 1 => "first"
107 | case 2 => "second"
108 | case 3 => "third"
109 | case _ => x + "th"
110 | }
111 |
112 | val bob = Person("Bob", 22)
113 | val greeting = bob match {
114 | case Person(n, _) => s"Hi, my name is $n"
115 | }
116 |
117 | // all the patterns
118 | }
119 |
--------------------------------------------------------------------------------
/src/lectures/part2afp/CurriesPAF.scala:
--------------------------------------------------------------------------------
1 | package lectures.part2afp
2 |
3 | /**
4 | * Created by Daniel.
5 | */
6 | object CurriesPAF extends App {
7 |
8 | // curried functions
9 | val superAdder: Int => Int => Int =
10 | x => y => x + y
11 |
12 | val add3 = superAdder(3) // Int => Int = y => 3 + y
13 | println(add3(5))
14 | println(superAdder(3)(5)) // curried function
15 |
16 | // METHOD!
17 | def curriedAdder(x: Int)(y: Int): Int = x + y // curried method
18 |
19 | val add4: Int => Int = curriedAdder(4)
20 | // lifting = ETA-EXPANSION
21 |
22 | // functions != methods (JVM limitation)
23 | def inc(x: Int) = x + 1
24 | List(1,2,3).map(x => inc(x)) // ETA-expansion
25 |
26 | // Partial function applications
27 | val add5 = curriedAdder(5) _ // Int => Int
28 |
29 | // EXERCISE
30 | val simpleAddFunction = (x: Int, y: Int) => x + y
31 | def simpleAddMethod(x: Int, y: Int) = x + y
32 | def curriedAddMethod(x: Int)(y: Int) = x + y
33 |
34 | // add7: Int => Int = y => 7 + y
35 | // as many different implementations of add7 using the above
36 | // be creative!
37 | val add7 = (x: Int) => simpleAddFunction(7, x) // simplest
38 | val add7_2 = simpleAddFunction.curried(7)
39 | val add7_6 = simpleAddFunction(7, _: Int) // works as well
40 |
41 | val add7_3 = curriedAddMethod(7) _ // PAF
42 | val add7_4 = curriedAddMethod(7)(_) // PAF = alternative syntax
43 |
44 | val add7_5 = simpleAddMethod(7, _: Int) // alternative syntax for turning methods into function values
45 | // y => simpleAddMethod(7, y)
46 |
47 | // underscores are powerful
48 | def concatenator(a: String, b: String, c: String) = a + b + c
49 | val insertName = concatenator("Hello, I'm ", _: String, ", how are you?") // x: String => concatenator(hello, x, howarewyou)
50 | println(insertName("Daniel"))
51 |
52 | val fillInTheBlanks = concatenator("Hello, ", _: String, _: String) // (x, y) => concatenator("Hello, ", x, y)
53 | println(fillInTheBlanks("Daniel", " Scala is awesome!"))
54 |
55 | // EXERCISES
56 | /*
57 | 1. Process a list of numbers and return their string representations with different formats
58 | Use the %4.2f, %8.6f and %14.12f with a curried formatter function.
59 | */
60 | def curriedFormatter(s: String)(number: Double): String = s.format(number)
61 | val numbers = List(Math.PI, Math.E, 1, 9.8, 1.3e-12)
62 |
63 | val simpleFormat = curriedFormatter("%4.2f") _ // lift
64 | val seriousFormat = curriedFormatter("%8.6f") _
65 | val preciseFormat = curriedFormatter("%14.12f") _
66 |
67 | println(numbers.map(curriedFormatter("%14.12f"))) // compiler does sweet eta-expansion for us
68 |
69 | /*
70 | 2. difference between
71 | - functions vs methods
72 | - parameters: by-name vs 0-lambda
73 | */
74 | def byName(n: => Int) = n + 1
75 | def byFunction(f: () => Int) = f() + 1
76 |
77 | def method: Int = 42
78 | def parenMethod(): Int = 42
79 |
80 | /*
81 | calling byName and byFunction
82 | - int
83 | - method
84 | - parenMethod
85 | - lambda
86 | - PAF
87 | */
88 | byName(23) // ok
89 | byName(method) // ok
90 | byName(parenMethod())
91 | byName(parenMethod) // ok but beware ==> byName(parenMethod())
92 | // byName(() => 42) // not ok
93 | byName((() => 42)()) // ok
94 | // byName(parenMethod _) // not ok
95 |
96 | // byFunction(45) // not ok
97 | // byFunction(method) // not ok!!!!!! does not do ETA-expansion!
98 | byFunction(parenMethod) // compiler does ETA-expansion
99 | byFunction(() => 46) // works
100 | byFunction(parenMethod _) // also works, but warning- unnecessary
101 | }
102 |
103 |
--------------------------------------------------------------------------------
/src/lectures/part2afp/LazyEvaluation.scala:
--------------------------------------------------------------------------------
1 | package lectures.part2afp
2 |
3 | /**
4 | * Created by Daniel.
5 | */
6 | object LazyEvaluation extends App {
7 |
8 | // lazy DELAYS the evaluation of values
9 | lazy val x: Int = {
10 | println("hello")
11 | 42
12 | }
13 | println(x)
14 | println(x)
15 |
16 | // examples of implications:
17 | // side effects
18 | def sideEffectCondition: Boolean = {
19 | println("Boo")
20 | true
21 | }
22 | def simpleCondition: Boolean = false
23 |
24 | lazy val lazyCondition = sideEffectCondition
25 | println(if (simpleCondition && lazyCondition) "yes" else "no")
26 |
27 | // in conjunction with call by name
28 | def byNameMethod(n: => Int): Int = {
29 | // CALL BY NEED
30 | lazy val t = n // only evaluated once
31 | t + t + t + 1
32 | }
33 | def retrieveMagicValue = {
34 | // side effect or a long computation
35 | println("waiting")
36 | Thread.sleep(1000)
37 | 42
38 | }
39 |
40 | println(byNameMethod(retrieveMagicValue))
41 | // use lazy vals
42 |
43 | // filtering with lazy vals
44 | def lessThan30(i: Int): Boolean = {
45 | println(s"$i is less than 30?")
46 | i < 30
47 | }
48 |
49 | def greaterThan20(i: Int): Boolean = {
50 | println(s"$i is greater than 20?")
51 | i > 20
52 | }
53 |
54 | val numbers = List(1, 25, 40, 5, 23)
55 | val lt30 = numbers.filter(lessThan30) // List(1, 25, 5, 23)
56 | val gt20 = lt30.filter(greaterThan20)
57 | println(gt20)
58 |
59 | val lt30lazy = numbers.withFilter(lessThan30) // lazy vals under the hood
60 | val gt20lazy = lt30lazy.withFilter(greaterThan20)
61 | println
62 | gt20lazy.foreach(println)
63 |
64 | // for-comprehensions use withFilter with guards
65 | for {
66 | a <- List(1,2,3) if a % 2 == 0 // use lazy vals!
67 | } yield a + 1
68 | List(1,2,3).withFilter(_ % 2 == 0).map(_ + 1) // List[Int]
69 |
70 | /*
71 | Exercise: implement a lazily evaluated, singly linked STREAM of elements.
72 |
73 | naturals = MyStream.from(1)(x => x + 1) = stream of natural numbers (potentially infinite!)
74 | naturals.take(100).foreach(println) // lazily evaluated stream of the first 100 naturals (finite stream)
75 | naturals.foreach(println) // will crash - infinite!
76 | naturals.map(_ * 2) // stream of all even numbers (potentially infinite)
77 | */
78 | abstract class MyStream[+A] {
79 | def isEmpty: Boolean
80 | def head: A
81 | def tail: MyStream[A]
82 |
83 | def #::[B >: A](element: B): MyStream[B] // prepend operator
84 | def ++[B >: A](anotherStream: MyStream[B]): MyStream[B] // concatenate two streams
85 |
86 | def foreach(f: A => Unit): Unit
87 | def map[B](f: A => B): MyStream[B]
88 | def flatMap[B](f: A => MyStream[B]): MyStream[B]
89 | def filter(predicate: A => Boolean): MyStream[A]
90 |
91 | def take(n: Int): MyStream[A] // takes the first n elements out of this stream
92 | def takeAsList(n: Int): List[A]
93 | }
94 |
95 | object MyStream {
96 | def from[A](start: A)(generator: A => A): MyStream[A] = ???
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/lectures/part2afp/Monads.scala:
--------------------------------------------------------------------------------
1 | package lectures.part2afp
2 |
3 | /**
4 | * Created by Daniel.
5 | */
6 | object Monads extends App {
7 |
8 | // our own Try monad
9 |
10 | trait Attempt[+A] {
11 | def flatMap[B](f: A => Attempt[B]): Attempt[B]
12 | }
13 | object Attempt {
14 | def apply[A](a: => A): Attempt[A] =
15 | try {
16 | Success(a)
17 | } catch {
18 | case e: Throwable => Fail(e)
19 | }
20 | }
21 |
22 | case class Success[+A](value: A) extends Attempt[A] {
23 | def flatMap[B](f: A => Attempt[B]): Attempt[B] =
24 | try {
25 | f(value)
26 | } catch {
27 | case e: Throwable => Fail(e)
28 | }
29 | }
30 |
31 | case class Fail(e: Throwable) extends Attempt[Nothing] {
32 | def flatMap[B](f: Nothing => Attempt[B]): Attempt[B] = this
33 | }
34 |
35 | /*
36 | left-identity
37 |
38 | unit.flatMap(f) = f(x)
39 | Attempt(x).flatMap(f) = f(x) // Success case!
40 | Success(x).flatMap(f) = f(x) // proved.
41 |
42 | right-identity
43 |
44 | attempt.flatMap(unit) = attempt
45 | Success(x).flatMap(x => Attempt(x)) = Attempt(x) = Success(x)
46 | Fail(e).flatMap(...) = Fail(e)
47 |
48 | associativity
49 |
50 | attempt.flatMap(f).flatMap(g) == attempt.flatMap(x => f(x).flatMap(g))
51 | Fail(e).flatMap(f).flatMap(g) = Fail(e)
52 | Fail(e).flatMap(x => f(x).flatMap(g)) = Fail(e)
53 |
54 | Success(v).flatMap(f).flatMap(g) =
55 | f(v).flatMap(g) OR Fail(e)
56 |
57 | Success(v).flatMap(x => f(x).flatMap(g)) =
58 | f(v).flatMap(g) OR Fail(e)
59 |
60 | */
61 |
62 | val attempt = Attempt {
63 | throw new RuntimeException("My own monad, yes!")
64 | }
65 |
66 | println(attempt)
67 |
68 | /*
69 | EXERCISE:
70 | 1) implement a Lazy[T] monad = computation which will only be executed when it's needed.
71 | unit/apply
72 | flatMap
73 |
74 | 2) Monads = unit + flatMap
75 | Monads = unit + map + flatten
76 |
77 | Monad[T] {
78 |
79 | def flatMap[B](f: T => Monad[B]): Monad[B] = ... (implemented)
80 |
81 | def map[B](f: T => B): Monad[B] = ???
82 | def flatten(m: Monad[Monad[T]]): Monad[T] = ???
83 |
84 | (have List in mind)
85 | */
86 |
87 | // 1 - Lazy monad
88 | class Lazy[+A](value: => A) {
89 | // call by need
90 | private lazy val internalValue = value
91 | def use: A = internalValue
92 | def flatMap[B](f: (=> A) => Lazy[B]): Lazy[B] = f(internalValue)
93 | }
94 | object Lazy {
95 | def apply[A](value: => A): Lazy[A] = new Lazy(value) // unit
96 | }
97 |
98 | val lazyInstance = Lazy {
99 | println("Today I don't feel like doing anything")
100 | 42
101 | }
102 |
103 | val flatMappedInstance = lazyInstance.flatMap(x => Lazy {
104 | 10 * x
105 | })
106 | val flatMappedInstance2 = lazyInstance.flatMap(x => Lazy {
107 | 10 * x
108 | })
109 | flatMappedInstance.use
110 | flatMappedInstance2.use
111 |
112 | /*
113 | left-identity
114 | unit.flatMap(f) = f(v)
115 | Lazy(v).flatMap(f) = f(v)
116 |
117 | right-identity
118 | l.flatMap(unit) = l
119 | Lazy(v).flatMap(x => Lazy(x)) = Lazy(v)
120 |
121 | associativity: l.flatMap(f).flatMap(g) = l.flatMap(x => f(x).flatMap(g))
122 |
123 | Lazy(v).flatMap(f).flatMap(g) = f(v).flatMap(g)
124 | Lazy(v).flatMap(x => f(x).flatMap(g)) = f(v).flatMap(g)
125 | */
126 |
127 | def flatten[T](lz: Lazy[Lazy[T]]): Lazy[T] = lz.flatMap(x => x)
128 | // 2: map and flatten in terms of flatMap
129 | /*
130 | Monad[T] { // List
131 | def flatMap[B](f: T => Monad[B]): Monad[B] = ... (implemented)
132 |
133 | def map[B](f: T => B): Monad[B] = flatMap(x => unit(f(x))) // Monad[B]
134 | def flatten(m: Monad[Monad[T]]): Monad[T] = m.flatMap((x: Monad[T]) => x)
135 |
136 | List(1,2,3).map(_ * 2) = List(1,2,3).flatMap(x => List(x * 2))
137 | List(List(1, 2), List(3, 4)).flatten = List(List(1, 2), List(3, 4)).flatMap(x => x) = List(1,2,3,4)
138 | }
139 |
140 | */
141 | }
142 |
--------------------------------------------------------------------------------
/src/lectures/part2afp/PartialFunctions.scala:
--------------------------------------------------------------------------------
1 | package lectures.part2afp
2 |
3 | /**
4 | * Created by Daniel.
5 | */
6 | object PartialFunctions extends App {
7 |
8 | val aFunction = (x: Int) => x + 1 // Function1[Int, Int] === Int => Int
9 |
10 | val aFussyFunction = (x: Int) =>
11 | if (x == 1) 42
12 | else if (x == 2) 56
13 | else if (x == 5) 999
14 | else throw new FunctionNotApplicableException
15 |
16 | class FunctionNotApplicableException extends RuntimeException
17 |
18 | val aNicerFussyFunction = (x: Int) => x match {
19 | case 1 => 42
20 | case 2 => 56
21 | case 5 => 999
22 | }
23 | // {1,2,5} => Int
24 |
25 | val aPartialFunction: PartialFunction[Int, Int] = {
26 | case 1 => 42
27 | case 2 => 56
28 | case 5 => 999
29 | } // partial function value
30 |
31 | println(aPartialFunction(2))
32 | // println(aPartialFunction(57273))
33 |
34 | // PF utilities
35 | println(aPartialFunction.isDefinedAt(67))
36 |
37 | // lift
38 | val lifted = aPartialFunction.lift // Int => Option[Int]
39 | println(lifted(2))
40 | println(lifted(98))
41 |
42 | val pfChain = aPartialFunction.orElse[Int, Int] {
43 | case 45 => 67
44 | }
45 |
46 | println(pfChain(2))
47 | println(pfChain(45))
48 |
49 | // PF extend normal functions
50 |
51 | val aTotalFunction: Int => Int = {
52 | case 1 => 99
53 | }
54 |
55 | // HOFs accept partial functions as well
56 | val aMappedList = List(1,2,3).map {
57 | case 1 => 42
58 | case 2 => 78
59 | case 3 => 1000
60 | }
61 | println(aMappedList)
62 |
63 | /*
64 | Note: PF can only have ONE parameter type
65 | */
66 |
67 | /**
68 | * Exercises
69 | *
70 | * 1 - construct a PF instance yourself (anonymous class)
71 | * 2 - dumb chatbot as a PF
72 | */
73 |
74 | val aManualFussyFunction = new PartialFunction[Int, Int] {
75 | override def apply(x: Int): Int = x match {
76 | case 1 => 42
77 | case 2 => 65
78 | case 5 => 999
79 | }
80 |
81 | override def isDefinedAt(x: Int): Boolean =
82 | x == 1 || x == 2 || x == 5
83 | }
84 |
85 | val chatbot: PartialFunction[String, String] = {
86 | case "hello" => "Hi, my name is HAL9000"
87 | case "goodbye" => "Once you start talking to me, there is no return, human!"
88 | case "call mom" => "Unable to find your phone without your credit card"
89 | }
90 |
91 | scala.io.Source.stdin.getLines().map(chatbot).foreach(println)
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/src/lectures/part3concurrency/FuturesPromises.scala:
--------------------------------------------------------------------------------
1 | package lectures.part3concurrency
2 |
3 | import scala.concurrent.{Await, Future, Promise}
4 | import scala.util.{Failure, Random, Success, Try}
5 | import scala.concurrent.duration._
6 |
7 | // important for futures
8 | import scala.concurrent.ExecutionContext.Implicits.global
9 | /**
10 | * Created by Daniel.
11 | */
12 | object FuturesPromises extends App {
13 |
14 | def calculateMeaningOfLife: Int = {
15 | Thread.sleep(2000)
16 | 42
17 | }
18 |
19 | val aFuture = Future {
20 | calculateMeaningOfLife // calculates the meaning of life on ANOTHER thread
21 | } // (global) which is passed by the compiler
22 |
23 |
24 | println(aFuture.value) // Option[Try[Int]]
25 |
26 | println("Waiting on the future")
27 | aFuture.onComplete {
28 | case Success(meaningOfLife) => println(s"the meaning of life is $meaningOfLife")
29 | case Failure(e) => println(s"I have failed with $e")
30 | } // SOME thread
31 |
32 | Thread.sleep(3000)
33 |
34 | // mini social network
35 |
36 | case class Profile(id: String, name: String) {
37 | def poke(anotherProfile: Profile) =
38 | println(s"${this.name} poking ${anotherProfile.name}")
39 | }
40 |
41 | object SocialNetwork {
42 | // "database"
43 | val names = Map(
44 | "fb.id.1-zuck" -> "Mark",
45 | "fb.id.2-bill" -> "Bill",
46 | "fb.id.0-dummy" -> "Dummy"
47 | )
48 | val friends = Map(
49 | "fb.id.1-zuck" -> "fb.id.2-bill"
50 | )
51 |
52 | val random = new Random()
53 |
54 | // API
55 | def fetchProfile(id: String): Future[Profile] = Future {
56 | // fetching from the DB
57 | Thread.sleep(random.nextInt(300))
58 | Profile(id, names(id))
59 | }
60 |
61 | def fetchBestFriend(profile: Profile): Future[Profile] = Future {
62 | Thread.sleep(random.nextInt(400))
63 | val bfId = friends(profile.id)
64 | Profile(bfId, names(bfId))
65 | }
66 | }
67 |
68 | // client: mark to poke bill
69 | val mark = SocialNetwork.fetchProfile("fb.id.1-zuck")
70 | // mark.onComplete {
71 | // case Success(markProfile) => {
72 | // val bill = SocialNetwork.fetchBestFriend(markProfile)
73 | // bill.onComplete {
74 | // case Success(billProfile) => markProfile.poke(billProfile)
75 | // case Failure(e) => e.printStackTrace()
76 | // }
77 | // }
78 | // case Failure(ex) => ex.printStackTrace()
79 | // }
80 |
81 |
82 | // functional composition of futures
83 | // map, flatMap, filter
84 | val nameOnTheWall = mark.map(profile => profile.name)
85 | val marksBestFriend = mark.flatMap(profile => SocialNetwork.fetchBestFriend(profile))
86 | val zucksBestFriendRestricted = marksBestFriend.filter(profile => profile.name.startsWith("Z"))
87 |
88 | // for-comprehensions
89 | for {
90 | mark <- SocialNetwork.fetchProfile("fb.id.1-zuck")
91 | bill <- SocialNetwork.fetchBestFriend(mark)
92 | } mark.poke(bill)
93 |
94 | Thread.sleep(1000)
95 |
96 | // fallbacks
97 | val aProfileNoMatterWhat = SocialNetwork.fetchProfile("unknown id").recover {
98 | case e: Throwable => Profile("fb.id.0-dummy", "Forever alone")
99 | }
100 |
101 | val aFetchedProfileNoMatterWhat = SocialNetwork.fetchProfile("unknown id").recoverWith {
102 | case e: Throwable => SocialNetwork.fetchProfile("fb.id.0-dummy")
103 | }
104 |
105 | val fallbackResult = SocialNetwork.fetchProfile("unknown id").fallbackTo(SocialNetwork.fetchProfile("fb.id.0-dummy"))
106 |
107 | // online banking app
108 | case class User(name: String)
109 | case class Transaction(sender: String, receiver: String, amount: Double, status: String)
110 |
111 | object BankingApp {
112 | val name = "Rock the JVM banking"
113 |
114 | def fetchUser(name: String): Future[User] = Future {
115 | // simulate fetching from the DB
116 | Thread.sleep(500)
117 | User(name)
118 | }
119 |
120 | def createTransaction(user: User, merchantName: String, amount: Double): Future[Transaction] = Future {
121 | // simulate some processes
122 | Thread.sleep(1000)
123 | Transaction(user.name, merchantName, amount, "SUCCESS")
124 | }
125 |
126 | def purchase(username: String, item: String, merchantName: String, cost: Double): String = {
127 | // fetch the user from the DB
128 | // create a transaction
129 | // WAIT for the transaction to finish
130 | val transactionStatusFuture = for {
131 | user <- fetchUser(username)
132 | transaction <- createTransaction(user, merchantName, cost)
133 | } yield transaction.status
134 |
135 | Await.result(transactionStatusFuture, 2.seconds) // implicit conversions -> pimp my library
136 | }
137 | }
138 |
139 | println(BankingApp.purchase("Daniel", "iPhone 12", "rock the jvm store", 3000))
140 |
141 | // promises
142 |
143 | val promise = Promise[Int]() // "controller" over a future
144 | val future = promise.future
145 |
146 | // thread 1 - "consumer"
147 | future.onComplete {
148 | case Success(r) => println("[consumer] I've received " + r)
149 | }
150 |
151 | // thread 2 - "producer"
152 | val producer = new Thread(() => {
153 | println("[producer] crunching numbers...")
154 | Thread.sleep(500)
155 | // "fulfilling" the promise
156 | promise.success(42)
157 | println("[producer] done")
158 | })
159 |
160 | producer.start()
161 | Thread.sleep(1000)
162 |
163 | /*
164 | 1) fulfill a future IMMEDIATELY with a value
165 | 2) inSequence(fa, fb)
166 | 3) first(fa, fb) => new future with the first value of the two futures
167 | 4) last(fa, fb) => new future with the last value
168 | 5) retryUntil[T](action: () => Future[T], condition: T => Boolean): Future[T]
169 | */
170 |
171 | // 1 - fulfill immediately
172 | def fulfillImmediately[T](value: T): Future[T] = Future(value)
173 | // 2 - insequence
174 | def inSequence[A, B](first: Future[A], second: Future[B]): Future[B] =
175 | first.flatMap(_ => second)
176 |
177 | // 3 - first out of two futures
178 | def first[A](fa: Future[A], fb: Future[A]): Future[A] = {
179 | val promise = Promise[A]
180 | fa.onComplete(promise.tryComplete)
181 | fb.onComplete(promise.tryComplete)
182 |
183 | promise.future
184 | }
185 |
186 | // 4 - last out of the two futures
187 | def last[A](fa: Future[A], fb: Future[A]): Future[A] = {
188 | // 1 promise which both futures will try to complete
189 | // 2 promise which the LAST future will complete
190 | val bothPromise = Promise[A]
191 | val lastPromise = Promise[A]
192 | val checkAndComplete = (result: Try[A]) =>
193 | if(!bothPromise.tryComplete(result))
194 | lastPromise.complete(result)
195 |
196 | fa.onComplete(checkAndComplete)
197 | fb.onComplete(checkAndComplete)
198 |
199 | lastPromise.future
200 | }
201 |
202 | val fast = Future {
203 | Thread.sleep(100)
204 | 42
205 | }
206 |
207 | val slow = Future {
208 | Thread.sleep(200)
209 | 45
210 | }
211 | first(fast, slow).foreach(f => println("FIRST: " + f))
212 | last(fast, slow).foreach(l => println("LAST: " + l))
213 |
214 | Thread.sleep(1000)
215 |
216 | // retry until
217 | def retryUntil[A](action: () => Future[A], condition: A => Boolean): Future[A] =
218 | action()
219 | .filter(condition)
220 | .recoverWith {
221 | case _ => retryUntil(action, condition)
222 | }
223 |
224 | val random = new Random()
225 | val action = () => Future {
226 | Thread.sleep(100)
227 | val nextValue = random.nextInt(100)
228 | println("generated " + nextValue)
229 | nextValue
230 | }
231 |
232 | retryUntil(action, (x: Int) => x < 10).foreach(result => println("settled at " + result))
233 | Thread.sleep(10000)
234 | }
235 |
--------------------------------------------------------------------------------
/src/lectures/part3concurrency/Intro.scala:
--------------------------------------------------------------------------------
1 | package lectures.part3concurrency
2 |
3 | import java.util.concurrent.Executors
4 |
5 | /**
6 | * Created by Daniel.
7 | */
8 | object Intro extends App {
9 |
10 | /*
11 | interface Runnable {
12 | public void run()
13 | }
14 | */
15 | // JVM threads
16 | val runnable = new Runnable {
17 | override def run(): Unit = println("Running in parallel")
18 | }
19 | val aThread = new Thread(runnable)
20 |
21 | aThread.start() // gives the signal to the JVM to start a JVM thread
22 | // create a JVM thread => OS thread
23 | runnable.run() // doesn't do anything in parallel!
24 | aThread.join() // blocks until aThread finishes running
25 |
26 | val threadHello = new Thread(() => (1 to 5).foreach(_ => println("hello")))
27 | val threadGoodbye = new Thread(() => (1 to 5).foreach(_ => println("goodbye")))
28 | // threadHello.start()
29 | // threadGoodbye.start()
30 | // different runs produce different results!
31 |
32 | // executors
33 | val pool = Executors.newFixedThreadPool(10)
34 | // pool.execute(() => println("something in the thread pool"))
35 |
36 | // pool.execute(() => {
37 | // Thread.sleep(1000)
38 | // println("done after 1 second")
39 | // })
40 | //
41 | // pool.execute(() => {
42 | // Thread.sleep(1000)
43 | // println("almost done")
44 | // Thread.sleep(1000)
45 | // println("done after 2 seconds")
46 | // })
47 |
48 | pool.shutdown()
49 | // pool.execute(() => println("should not appear")) // throws an exception in the calling thread
50 |
51 | // pool.shutdownNow()
52 | println(pool.isShutdown) // true
53 |
54 | def runInParallel = {
55 | var x = 0
56 |
57 | val thread1 = new Thread(() => {
58 | x = 1
59 | })
60 |
61 | val thread2 = new Thread(() => {
62 | x = 2
63 | })
64 |
65 | thread1.start()
66 | thread2.start()
67 | println(x)
68 | }
69 |
70 | // for (_ <- 1 to 10000) runInParallel
71 | // race condition
72 |
73 | class BankAccount(@volatile var amount: Int) {
74 | override def toString: String = "" + amount
75 | }
76 |
77 | def buy(account: BankAccount, thing: String, price: Int) = {
78 | account.amount -= price // account.amount = account.amount - price
79 | // println("I've bought " + thing)
80 | // println("my account is now " + account)
81 | }
82 |
83 | // for (_ <- 1 to 10000) {
84 | // val account = new BankAccount(50000)
85 | // val thread1 = new Thread(() => buy(account, "shoes", 3000))
86 | // val thread2 = new Thread(() => buy(account, "iPhone12", 4000))
87 | //
88 | // thread1.start()
89 | // thread2.start()
90 | // Thread.sleep(10)
91 | // if (account.amount != 43000) println("AHA: " + account.amount)
92 | //// println()
93 | // }
94 |
95 | /*
96 | thread1 (shoes): 50000
97 | - account = 50000 - 3000 = 47000
98 | thread2 (iphone): 50000
99 | - account = 50000 - 4000 = 46000 overwrites the memory of account.amount
100 | */
101 |
102 | // option #1: use synchronized()
103 | def buySafe(account: BankAccount, thing: String, price: Int) =
104 | account.synchronized {
105 | // no two threads can evaluate this at the same time
106 | account.amount -= price
107 | println("I've bought " + thing)
108 | println("my account is now " + account)
109 | }
110 |
111 | // option #2: use @volatile
112 |
113 | /**
114 | * Exercises
115 | *
116 | * 1) Construct 50 "inception" threads
117 | * Thread1 -> thread2 -> thread3 -> ...
118 | * println("hello from thread #3")
119 | * in REVERSE ORDER
120 | *
121 | */
122 | def inceptionThreads(maxThreads: Int, i: Int = 1): Thread = new Thread(() => {
123 | if (i < maxThreads) {
124 | val newThread = inceptionThreads(maxThreads, i + 1)
125 | newThread.start()
126 | newThread.join()
127 | }
128 | println(s"Hello from thread $i")
129 | })
130 |
131 | inceptionThreads(50).start()
132 |
133 | /*
134 | 2
135 | */
136 | var x = 0
137 | val threads = (1 to 100).map(_ => new Thread(() => x += 1))
138 | threads.foreach(_.start())
139 | /*
140 | 1) what is the biggest value possible for x? 100
141 | 2) what is the SMALLEST value possible for x? 1
142 |
143 | thread1: x = 0
144 | thread2: x = 0
145 | ...
146 | thread100: x = 0
147 |
148 | for all threads: x = 1 and write it back to x
149 | */
150 | threads.foreach(_.join())
151 | println(x)
152 |
153 | /*
154 | 3 sleep fallacy
155 | */
156 | var message = ""
157 | val awesomeThread = new Thread(() => {
158 | Thread.sleep(1000)
159 | message = "Scala is awesome"
160 | })
161 |
162 | message = "Scala sucks"
163 | awesomeThread.start()
164 | Thread.sleep(1001)
165 | awesomeThread.join() // wait for the awesome thread to join
166 | println(message)
167 | /*
168 | what's the value of message? almost always "Scala is awesome"
169 | is it guaranteed? NO!
170 | why? why not?
171 |
172 | (main thread)
173 | message = "Scala sucks"
174 | awesomeThread.start()
175 | sleep() - relieves execution
176 | (awesome thread)
177 | sleep() - relieves execution
178 | (OS gives the CPU to some important thread - takes CPU for more than 2 seconds)
179 | (OS gives the CPU back to the MAIN thread)
180 | println("Scala sucks")
181 | (OS gives the CPU to awesomethread)
182 | message = "Scala is awesome"
183 |
184 | */
185 |
186 | // how do we fix this?
187 | // syncrhonizing does NOT work
188 |
189 |
190 | }
191 |
192 |
--------------------------------------------------------------------------------
/src/lectures/part3concurrency/ParallelUtils.scala:
--------------------------------------------------------------------------------
1 | package lectures.part3concurrency
2 |
3 | import java.util.concurrent.atomic.AtomicReference
4 |
5 | import scala.collection.parallel.{ForkJoinTaskSupport, Task, TaskSupport}
6 | import scala.collection.parallel.immutable.ParVector
7 | import scala.concurrent.forkjoin.ForkJoinPool
8 |
9 | /**
10 | * Created by Daniel.
11 | */
12 | object ParallelUtils extends App {
13 |
14 | // 1 - parallel collections
15 |
16 | val parList = List(1,2,3).par
17 |
18 | val aParVector = ParVector[Int](1,2,3)
19 |
20 | /*
21 | Seq
22 | Vector
23 | Array
24 | Map - Hash, Trie
25 | Set - Hash, Trie
26 | */
27 |
28 | def measure[T](operation: => T): Long = {
29 | val time = System.currentTimeMillis()
30 | operation
31 | System.currentTimeMillis() - time
32 | }
33 |
34 | val list = (1 to 10000).toList
35 | val serialTime = measure {
36 | list.map(_ + 1)
37 | }
38 | println("serial time: " + serialTime)
39 |
40 | val parallelTime = measure {
41 | list.par.map(_ + 1)
42 | }
43 |
44 | println("parallel time: " + parallelTime)
45 |
46 | /*
47 | Map-reduce model
48 | - split the elements into chunks - Splitter
49 | - operation
50 | - recombine - Combiner
51 | */
52 |
53 | // map, flatMap, filter, foreach, reduce, fold
54 |
55 | // fold, reduce with non-associative operators
56 | println(List(1,2,3).reduce(_ - _))
57 | println(List(1,2,3).par.reduce(_ - _))
58 |
59 | // synchronization
60 | var sum = 0
61 | List(1,2,3).par.foreach(sum += _)
62 | println(sum) // race conditions!
63 |
64 | // configuring
65 | aParVector.tasksupport = new ForkJoinTaskSupport(new ForkJoinPool(2))
66 | /*
67 | alternatives
68 | - ThreadPoolTaskSupport - deprecated
69 | - ExecutionContextTaskSupport(EC)
70 | */
71 |
72 | // aParVector.tasksupport = new TaskSupport {
73 | // override def execute[R, Tp](fjtask: Task[R, Tp]): () => R = ???
74 | //
75 | // override def executeAndWaitResult[R, Tp](task: Task[R, Tp]): R = ???
76 | //
77 | // override def parallelismLevel: Int = ???
78 | //
79 | // override val environment: AnyRef = ???
80 | // }
81 |
82 | // 2 - atomic ops and references
83 |
84 | val atomic = new AtomicReference[Int](2)
85 |
86 | val currentValue = atomic.get() // thread-safe read
87 | atomic.set(4) // thread-safe write
88 |
89 | atomic.getAndSet(5) // thread safe combo
90 |
91 | atomic.compareAndSet(38, 56)
92 | // if the value is 38, then set to 56
93 | // reference equality
94 |
95 | atomic.updateAndGet(_ + 1) // thread-safe function run
96 | atomic.getAndUpdate(_ + 1)
97 |
98 | atomic.accumulateAndGet(12, _ + _) // thread-safe accumulation
99 | atomic.getAndAccumulate(12, _ + _)
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/src/lectures/part3concurrency/ThreadCommunication.scala:
--------------------------------------------------------------------------------
1 | package lectures.part3concurrency
2 |
3 | import scala.collection.mutable
4 | import scala.util.Random
5 |
6 | /**
7 | * Created by Daniel.
8 | */
9 | object ThreadCommunication extends App {
10 |
11 | /*
12 | the producer-consumer problem
13 |
14 | producer -> [ ? ] -> consumer
15 | */
16 | class SimpleContainer {
17 | private var value: Int = 0
18 |
19 | def isEmpty: Boolean = value == 0
20 | def set(newValue: Int) = value = newValue
21 | def get = {
22 | val result = value
23 | value = 0
24 | result
25 | }
26 | }
27 |
28 | def naiveProdCons(): Unit = {
29 | val container = new SimpleContainer
30 |
31 | val consumer = new Thread(() => {
32 | println("[consumer] waiting...")
33 | while(container.isEmpty) {
34 | println("[consumer] actively waiting...")
35 | }
36 |
37 | println("[consumer] I have consumed " + container.get)
38 | })
39 |
40 | val producer = new Thread(() => {
41 | println("[producer] computing...")
42 | Thread.sleep(500)
43 | val value = 42
44 | println("[producer] I have produced, after long work, the value " + value)
45 | container.set(value)
46 | })
47 |
48 | consumer.start()
49 | producer.start()
50 | }
51 |
52 | // naiveProdCons()
53 |
54 | // wait and notify
55 | def smartProdCons(): Unit = {
56 | val container = new SimpleContainer
57 |
58 | val consumer = new Thread(() => {
59 | println("[consumer] waiting...")
60 | container.synchronized {
61 | container.wait()
62 | }
63 |
64 | // container must have some value
65 | println("[consumer] I have consumed " + container.get)
66 | })
67 |
68 | val producer = new Thread(() => {
69 | println("[producer] Hard at work...")
70 | Thread.sleep(2000)
71 | val value = 42
72 |
73 | container.synchronized {
74 | println("[producer] I'm producing " + value)
75 | container.set(value)
76 | container.notify()
77 | }
78 | })
79 |
80 | consumer.start()
81 | producer.start()
82 | }
83 |
84 | // smartProdCons()
85 |
86 | /*
87 | producer -> [ ? ? ? ] -> consumer
88 | */
89 |
90 | def prodConsLargeBuffer(): Unit = {
91 | val buffer: mutable.Queue[Int] = new mutable.Queue[Int]
92 | val capacity = 3
93 |
94 | val consumer = new Thread(() => {
95 | val random = new Random()
96 |
97 | while(true) {
98 | buffer.synchronized {
99 | if (buffer.isEmpty) {
100 | println("[consumer] buffer empty, waiting...")
101 | buffer.wait()
102 | }
103 |
104 | // there must be at least ONE value in the buffer
105 | val x = buffer.dequeue()
106 | println("[consumer] consumed " + x)
107 |
108 | // hey producer, there's empty space available, are you lazy?!
109 | buffer.notify()
110 | }
111 |
112 | Thread.sleep(random.nextInt(250))
113 | }
114 | })
115 |
116 | val producer = new Thread(() => {
117 | val random = new Random()
118 | var i = 0
119 |
120 | while(true) {
121 | buffer.synchronized {
122 | if (buffer.size == capacity) {
123 | println("[producer] buffer is full, waiting...")
124 | buffer.wait()
125 | }
126 |
127 | // there must be at least ONE EMPTY SPACE in the buffer
128 | println("[producer] producing " + i)
129 | buffer.enqueue(i)
130 |
131 | // hey consumer, new food for you!
132 | buffer.notify()
133 |
134 | i += 1
135 | }
136 |
137 | Thread.sleep(random.nextInt(500))
138 | }
139 | })
140 |
141 | consumer.start()
142 | producer.start()
143 | }
144 |
145 | // prodConsLargeBuffer()
146 |
147 | /*
148 | Prod-cons, level 3
149 |
150 | producer1 -> [ ? ? ? ] -> consumer1
151 | producer2 -----^ ^---- consumer2
152 | */
153 |
154 |
155 | class Consumer(id: Int, buffer: mutable.Queue[Int]) extends Thread {
156 | override def run(): Unit = {
157 | val random = new Random()
158 |
159 | while(true) {
160 | buffer.synchronized {
161 | /*
162 | producer produces value, two Cons are waiting
163 | notifies ONE consumer, notifies on buffer
164 | notifies the other consumer
165 |
166 | */
167 | while (buffer.isEmpty) {
168 | println(s"[consumer $id] buffer empty, waiting...")
169 | buffer.wait()
170 | }
171 |
172 | // there must be at least ONE value in the buffer
173 | val x = buffer.dequeue() // OOps.!
174 | println(s"[consumer $id] consumed " + x)
175 |
176 | buffer.notifyAll()
177 | }
178 |
179 | Thread.sleep(random.nextInt(250))
180 | }
181 | }
182 | }
183 |
184 | class Producer(id: Int, buffer: mutable.Queue[Int], capacity: Int) extends Thread {
185 | override def run(): Unit = {
186 | val random = new Random()
187 | var i = 0
188 |
189 | while(true) {
190 | buffer.synchronized {
191 | while (buffer.size == capacity) {
192 | println(s"[producer $id] buffer is full, waiting...")
193 | buffer.wait()
194 | }
195 |
196 | // there must be at least ONE EMPTY SPACE in the buffer
197 | println(s"[producer $id] producing " + i)
198 | buffer.enqueue(i)
199 |
200 | buffer.notifyAll()
201 |
202 | i += 1
203 | }
204 |
205 | Thread.sleep(random.nextInt(500))
206 | }
207 | }
208 | }
209 |
210 | def multiProdCons(nConsumers: Int, nProducers: Int): Unit = {
211 | val buffer: mutable.Queue[Int] = new mutable.Queue[Int]
212 | val capacity = 20
213 |
214 | (1 to nConsumers).foreach(i => new Consumer(i, buffer).start())
215 | (1 to nProducers).foreach(i => new Producer(i, buffer, capacity).start())
216 | }
217 |
218 | // multiProdCons(3, 6)
219 |
220 | /*
221 | Exercises.
222 | 1) think of an example where notifyALL acts in a different way than notify?
223 | 2) create a deadlock
224 | 3) create a livelock
225 | */
226 |
227 | // notifyall
228 | def testNotifyAll(): Unit = {
229 | val bell = new Object
230 |
231 | (1 to 10).foreach(i => new Thread(() => {
232 | bell.synchronized {
233 | println(s"[thread $i] waiting...")
234 | bell.wait()
235 | println(s"[thread $i] hooray!")
236 | }
237 | }).start())
238 |
239 | new Thread(() => {
240 | Thread.sleep(2000)
241 | println("[announcer] Rock'n roll!")
242 | bell.synchronized {
243 | bell.notifyAll()
244 | }
245 | }).start()
246 | }
247 |
248 | testNotifyAll()
249 |
250 | // 2 - deadlock
251 | case class Friend(name: String) {
252 | def bow(other: Friend) = {
253 | this.synchronized {
254 | println(s"$this: I am bowing to my friend $other")
255 | other.rise(this)
256 | println(s"$this: my friend $other has risen")
257 | }
258 | }
259 |
260 | def rise(other: Friend) = {
261 | this.synchronized {
262 | println(s"$this: I am rising to my friend $other")
263 | }
264 | }
265 |
266 | var side = "right"
267 | def switchSide(): Unit = {
268 | if (side == "right") side = "left"
269 | else side = "right"
270 | }
271 |
272 | def pass(other: Friend): Unit = {
273 | while (this.side == other.side) {
274 | println(s"$this: Oh, but please, $other, feel free to pass...")
275 | switchSide()
276 | Thread.sleep(1000)
277 | }
278 | }
279 | }
280 |
281 | val sam = Friend("Sam")
282 | val pierre = Friend("Pierre")
283 |
284 | // new Thread(() => sam.bow(pierre)).start() // sam's lock, | then pierre's lock
285 | // new Thread(() => pierre.bow(sam)).start() // pierre's lock | then sam's lock
286 |
287 | // 3 - livelock
288 | // new Thread(() => sam.pass(pierre)).start()
289 | // new Thread(() => pierre.pass(sam)).start()
290 | }
291 |
--------------------------------------------------------------------------------
/src/lectures/part4implicits/ImplicitsIntro.scala:
--------------------------------------------------------------------------------
1 | package lectures.part4implicits
2 |
3 | /**
4 | * Created by Daniel.
5 | */
6 | object ImplicitsIntro extends App {
7 |
8 | val pair = "Daniel" -> "555"
9 | val intPair = 1 -> 2
10 |
11 | case class Person(name: String) {
12 | def greet = s"Hi, my name is $name!"
13 | }
14 |
15 | implicit def fromStringToPerson(str: String): Person = Person(str)
16 |
17 | println("Peter".greet) // println(fromStringToPerson("Peter").greet)
18 |
19 | // class A {
20 | // def greet: Int = 2
21 | // }
22 | // implicit def fromStringToA(str: String): A = new A
23 |
24 | // implicit parameters
25 | def increment(x: Int)(implicit amount: Int) = x + amount
26 | implicit val defaultAmount = 10
27 |
28 | increment(2)
29 | // NOT default args
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/lectures/part4implicits/JSONSerialization.scala:
--------------------------------------------------------------------------------
1 | package lectures.part4implicits
2 |
3 | import java.util.Date
4 |
5 | import lectures.part4implicits.JSONSerialization.JSONNumber
6 |
7 | /**
8 | * Created by Daniel.
9 | */
10 | object JSONSerialization extends App {
11 |
12 | /*
13 | Users, posts, feeds
14 | Serialize to JSON
15 | */
16 |
17 | case class User(name: String, age: Int, email: String)
18 | case class Post(content: String, createdAt: Date)
19 | case class Feed(user: User, posts: List[Post])
20 |
21 | /*
22 | 1 - intermediate data types: Int, String, List, Date
23 | 2 - type classes for conversion to intermediate data types
24 | 3 - serialize to JSON
25 | */
26 |
27 | sealed trait JSONValue { // intermediate data type
28 | def stringify: String
29 | }
30 |
31 | final case class JSONString(value: String) extends JSONValue {
32 | def stringify: String =
33 | "\"" + value + "\""
34 | }
35 |
36 | final case class JSONNumber(value: Int) extends JSONValue {
37 | def stringify: String = value.toString
38 | }
39 |
40 | final case class JSONArray(values: List[JSONValue]) extends JSONValue {
41 | def stringify: String = values.map(_.stringify).mkString("[", ",", "]")
42 | }
43 |
44 | final case class JSONObject(values: Map[String, JSONValue]) extends JSONValue {
45 | /*
46 | {
47 | name: "John"
48 | age: 22
49 | friends: [ ... ]
50 | latestPost: {
51 | content: "Scala Rocks"
52 | date: ...
53 | }
54 | }
55 | */
56 | def stringify: String = values.map {
57 | case (key, value) => "\"" + key + "\":" + value.stringify
58 | }
59 | .mkString("{", ",", "}")
60 |
61 | }
62 |
63 | val data = JSONObject(Map(
64 | "user" -> JSONString("Daniel"),
65 | "posts" -> JSONArray(List(
66 | JSONString("Scala Rocks!"),
67 | JSONNumber(453)
68 | ))
69 | ))
70 |
71 | println(data.stringify)
72 |
73 | // type class
74 | /*
75 | 1 - type class
76 | 2 - type class instances (implicit)
77 | 3 - pimp library to use type class instances
78 | */
79 |
80 | // 2.1
81 | trait JSONConverter[T] {
82 | def convert(value: T): JSONValue
83 | }
84 |
85 | // 2.3 conversion
86 |
87 | implicit class JSONOps[T](value: T) {
88 | def toJSON(implicit converter: JSONConverter[T]): JSONValue =
89 | converter.convert(value)
90 | }
91 |
92 | // 2.2
93 |
94 | // existing data types
95 | implicit object StringConverter extends JSONConverter[String] {
96 | def convert(value: String): JSONValue = JSONString(value)
97 | }
98 |
99 | implicit object NumberConverter extends JSONConverter[Int] {
100 | def convert(value: Int): JSONValue = JSONNumber(value)
101 | }
102 |
103 | // custom data types
104 | implicit object UserConverter extends JSONConverter[User] {
105 | def convert(user: User): JSONValue = JSONObject(Map(
106 | "name" -> JSONString(user.name),
107 | "age" -> JSONNumber(user.age),
108 | "email" -> JSONString(user.email)
109 | ))
110 | }
111 |
112 | implicit object PostConverter extends JSONConverter[Post] {
113 | def convert(post: Post): JSONValue = JSONObject(Map(
114 | "content" -> JSONString(post.content),
115 | "created:" -> JSONString(post.createdAt.toString)
116 | ))
117 | }
118 |
119 | implicit object FeedConverter extends JSONConverter[Feed] {
120 | def convert(feed: Feed): JSONValue = JSONObject(Map(
121 | "user" -> feed.user.toJSON,
122 | "posts" -> JSONArray(feed.posts.map(_.toJSON))
123 | ))
124 | }
125 |
126 | // call stringify on result
127 | val now = new Date(System.currentTimeMillis())
128 | val john = User("John", 34, "john@rockthejvm.com")
129 | val feed = Feed(john, List(
130 | Post("hello", now),
131 | Post("look at this cute puppy", now)
132 | ))
133 |
134 | println(feed.toJSON.stringify)
135 |
136 | }
137 |
--------------------------------------------------------------------------------
/src/lectures/part4implicits/MagnetPattern.scala:
--------------------------------------------------------------------------------
1 | package lectures.part4implicits
2 |
3 | import scala.concurrent.Future
4 | import scala.concurrent.ExecutionContext.Implicits.global
5 |
6 | /**
7 | * Created by Daniel.
8 | */
9 | object MagnetPattern extends App {
10 |
11 | // method overloading
12 |
13 | class P2PRequest
14 | class P2PResponse
15 | class Serializer[T]
16 |
17 |
18 | trait Actor {
19 | def receive(statusCode: Int): Int
20 | def receive(request: P2PRequest): Int
21 | def receive(response: P2PResponse): Int
22 | def receive[T : Serializer](message: T): Int
23 | def receive[T : Serializer](message: T, statusCode: Int): Int
24 | def receive(future: Future[P2PRequest]): Int
25 | // def receive(future: Future[P2PResponse]): Int
26 | // lots of overloads
27 | }
28 |
29 | /*
30 | 1 - type erasure
31 | 2 - lifting doesn't work for all overloads
32 |
33 | val receiveFV = receive _ // ?!
34 |
35 | 3 - code duplication
36 | 4 - type inferrence and default args
37 |
38 | actor.receive(?!)
39 | */
40 |
41 | trait MessageMagnet[Result] {
42 | def apply(): Result
43 | }
44 |
45 | def receive[R](magnet: MessageMagnet[R]): R = magnet()
46 |
47 | implicit class FromP2PRequest(request: P2PRequest) extends MessageMagnet[Int] {
48 | def apply(): Int = {
49 | // logic for handling a P2PRequest
50 | println("Handling P2P request")
51 | 42
52 | }
53 | }
54 |
55 | implicit class FromP2PResponse(response: P2PResponse) extends MessageMagnet[Int] {
56 | def apply(): Int = {
57 | // logic for handling a P2PResponse
58 | println("Handling P2P response")
59 | 24
60 | }
61 | }
62 |
63 | receive(new P2PRequest)
64 | receive(new P2PResponse)
65 |
66 | // 1 - no more type erasure problems!
67 | implicit class FromResponseFuture(future: Future[P2PResponse]) extends MessageMagnet[Int] {
68 | override def apply(): Int = 2
69 | }
70 |
71 | implicit class FromRequestFuture(future: Future[P2PRequest]) extends MessageMagnet[Int] {
72 | override def apply(): Int = 3
73 | }
74 |
75 | println(receive(Future(new P2PRequest)))
76 | println(receive(Future(new P2PResponse)))
77 |
78 | // 2 - lifting works
79 | trait MathLib {
80 | def add1(x: Int): Int = x + 1
81 | def add1(s: String): Int = s.toInt + 1
82 | // add1 overloads
83 | }
84 |
85 | // "magnetize"
86 | trait AddMagnet {
87 | def apply(): Int
88 | }
89 |
90 | def add1(magnet: AddMagnet): Int = magnet()
91 |
92 | implicit class AddInt(x: Int) extends AddMagnet {
93 | override def apply(): Int = x + 1
94 | }
95 |
96 | implicit class AddString(s: String) extends AddMagnet {
97 | override def apply(): Int = s.toInt + 1
98 | }
99 |
100 | val addFV = add1 _
101 | println(addFV(1))
102 | println(addFV("3"))
103 |
104 | // val receiveFV = receive _
105 | // receiveFV(new P2PResponse)
106 |
107 | /*
108 | Drawbacks
109 | 1 - verbose
110 | 2 - harder to read
111 | 3 - you can't name or place default arguments
112 | 4 - call by name doesn't work correctly
113 | (exercise: prove it!) (hint: side effects)
114 | */
115 |
116 | class Handler {
117 | def handle(s: => String) = {
118 | println(s)
119 | println(s)
120 | }
121 | // other overloads
122 | }
123 |
124 | trait HandleMagnet {
125 | def apply(): Unit
126 | }
127 |
128 | def handle(magnet: HandleMagnet) = magnet()
129 |
130 | implicit class StringHandle(s: => String) extends HandleMagnet {
131 | override def apply(): Unit = {
132 | println(s)
133 | println(s)
134 | }
135 | }
136 |
137 | def sideEffectMethod(): String = {
138 | println("Hello, Scala")
139 | "hahaha"
140 | }
141 |
142 | // handle(sideEffectMethod())
143 | handle {
144 | println("Hello, Scala")
145 | new StringHandle("magnet")
146 | }
147 | // careful!
148 | }
149 |
--------------------------------------------------------------------------------
/src/lectures/part4implicits/MyTypeClassTemplate.scala:
--------------------------------------------------------------------------------
1 | package lectures.part4implicits
2 |
3 | // TYPE CLASS
4 | trait MyTypeClassTemplate[T] {
5 | def action(value: T): String
6 | }
7 |
8 | object MyTypeClassTemplate {
9 | def apply[T](implicit instance: MyTypeClassTemplate[T]) = instance
10 | }
--------------------------------------------------------------------------------
/src/lectures/part4implicits/OrganizingImplicits.scala:
--------------------------------------------------------------------------------
1 | package lectures.part4implicits
2 |
3 | /**
4 | * Created by Daniel.
5 | */
6 | object OrganizingImplicits extends App {
7 |
8 | implicit def reverseOrdering: Ordering[Int] = Ordering.fromLessThan(_ > _)
9 | // implicit val normalOrdering: Ordering[Int] = Ordering.fromLessThan(_ < _)
10 |
11 | println(List(1,4,5,3,2).sorted)
12 |
13 | // scala.Predef
14 |
15 | /*
16 | Implicits (used as implicit parameters):
17 | - val/var
18 | - object
19 | - accessor methods = defs with no parentheses
20 | */
21 |
22 | // Exercise
23 | case class Person(name: String, age: Int)
24 |
25 | val persons = List(
26 | Person("Steve", 30),
27 | Person("Amy", 22),
28 | Person("John", 66)
29 | )
30 |
31 | // object Person {
32 | // implicit val alphabeticOrdering: Ordering[Person] = Ordering.fromLessThan((a, b) => a.name.compareTo(b.name) < 0)
33 | // }
34 | // implicit val ageOrdering: Ordering[Person] = Ordering.fromLessThan((a, b) => a.age < b.age)
35 | // println(persons.sorted)
36 |
37 | /*
38 | Implicit scope
39 | - normal scope = LOCAL SCOPE
40 | - imported scope
41 | - companions of all types involved in the method signature
42 | - List
43 | - Ordering
44 | - all the types involved = A or any supertype
45 | */
46 | // def sorted[B >: A](implicit ord: Ordering[B]): List[B]
47 |
48 | object AlphabeticNameOrdering {
49 | implicit val alphabeticOrdering: Ordering[Person] = Ordering.fromLessThan((a, b) => a.name.compareTo(b.name) < 0)
50 | }
51 |
52 | object AgeOrdering {
53 | implicit val ageOrdering: Ordering[Person] = Ordering.fromLessThan((a, b) => a.age < b.age)
54 | }
55 |
56 | import AgeOrdering._
57 | println(persons.sorted)
58 |
59 | /*
60 | Exercise.
61 |
62 | - totalPrice = most used (50%)
63 | - by unit count = 25%
64 | - by unit price = 25%
65 |
66 | */
67 | case class Purchase(nUnits: Int, unitPrice: Double)
68 | object Purchase {
69 | implicit val totalPriceOrdering: Ordering[Purchase] = Ordering.fromLessThan((a,b) => a.nUnits * a.unitPrice < b.nUnits * b.unitPrice)
70 | }
71 |
72 | object UnitCountOrdering {
73 | implicit val unitCountOrdering: Ordering[Purchase] = Ordering.fromLessThan(_.nUnits < _.nUnits)
74 | }
75 |
76 | object UnitPriceOrdering {
77 | implicit val unitPriceOrdering: Ordering[Purchase] = Ordering.fromLessThan(_.unitPrice < _.unitPrice)
78 | }
79 |
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/src/lectures/part4implicits/PimpMyLibrary.scala:
--------------------------------------------------------------------------------
1 | package lectures.part4implicits
2 |
3 | /**
4 | * Created by Daniel.
5 | */
6 | object PimpMyLibrary extends App {
7 |
8 | // 2.isPrime
9 |
10 | implicit class RichInt(val value: Int) extends AnyVal {
11 | def isEven: Boolean = value % 2 == 0
12 | def sqrt: Double = Math.sqrt(value)
13 |
14 | def times(function: () => Unit): Unit = {
15 | def timesAux(n: Int): Unit =
16 | if (n <= 0) ()
17 | else {
18 | function()
19 | timesAux(n - 1)
20 | }
21 |
22 | timesAux(value)
23 | }
24 |
25 | def *[T](list: List[T]): List[T] = {
26 | def concatenate(n: Int): List[T] =
27 | if (n <= 0) List()
28 | else concatenate(n - 1) ++ list
29 |
30 | concatenate(value)
31 | }
32 |
33 | }
34 |
35 | implicit class RicherInt(richInt: RichInt) {
36 | def isOdd: Boolean = richInt.value % 2 != 0
37 | }
38 |
39 | new RichInt(42).sqrt
40 |
41 | 42.isEven // new RichInt(42).isEven
42 | // type enrichment = pimping
43 |
44 | 1 to 10
45 |
46 | import scala.concurrent.duration._
47 | 3.seconds
48 |
49 | // compiler doesn't do multiple implicit searches.
50 | // 42.isOdd
51 |
52 | /*
53 | Enrich the String class
54 | - asInt
55 | - encrypt
56 | "John" -> Lqjp
57 |
58 | Keep enriching the Int class
59 | - times(function)
60 | 3.times(() => ...)
61 | - *
62 | 3 * List(1,2) => List(1,2,1,2,1,2)
63 | */
64 |
65 | implicit class RichString(string: String) {
66 | def asInt: Int = Integer.valueOf(string) // java.lang.Integer -> Int
67 | def encrypt(cypherDistance: Int): String = string.map(c => (c + cypherDistance).asInstanceOf[Char])
68 | }
69 |
70 | println("3".asInt + 4)
71 | println("John".encrypt(2))
72 |
73 | 3.times(() => println("Scala Rocks!"))
74 | println(4 * List(1,2))
75 |
76 | // "3" / 4
77 | implicit def stringToInt(string: String): Int = Integer.valueOf(string)
78 | println("6" / 2) // stringToInt("6") / 2
79 |
80 | // equivalent: implicit class RichAltInt(value: Int)
81 | class RichAltInt(value: Int)
82 | implicit def enrich(value: Int): RichAltInt = new RichAltInt(value)
83 |
84 | // danger zone
85 | implicit def intToBoolean(i: Int): Boolean = i == 1
86 |
87 | /*
88 | if (n) do something
89 | else do something else
90 | */
91 |
92 | val aConditionedValue = if (3) "OK" else "Something wrong"
93 | println(aConditionedValue)
94 | }
95 |
--------------------------------------------------------------------------------
/src/lectures/part4implicits/ScalaJavaConversions.scala:
--------------------------------------------------------------------------------
1 | package lectures.part4implicits
2 |
3 | import java.{util => ju}
4 | /**
5 | * Created by Daniel.
6 | */
7 | object ScalaJavaConversions extends App {
8 |
9 | import collection.JavaConverters._
10 |
11 | import scala.jdk.CollectionConverters._
12 |
13 | val javaSet: ju.Set[Int] = new ju.HashSet[Int]()
14 | (1 to 5).foreach(javaSet.add)
15 | println(javaSet)
16 |
17 | val scalaSet = javaSet.asScala
18 |
19 | /*
20 | Iterator
21 | Iterable
22 | ju.List - collection.mutable.Buffer
23 | ju.Set - collection.mutable.Set
24 | ju.Map - collection.mutable.Map
25 |
26 | */
27 |
28 | import collection.mutable._
29 | val numbersBuffer = ArrayBuffer[Int](1, 2, 3)
30 | val juNumbersBuffer = numbersBuffer.asJava
31 |
32 | println(juNumbersBuffer.asScala eq numbersBuffer)
33 |
34 | val numbers = List(1,2,3)
35 | val juNumbers = numbers.asJava
36 | val backToScala = juNumbers.asScala
37 | println(backToScala eq numbers) // false
38 | println(backToScala == numbers) // true
39 |
40 | // juNumbers.add(7)
41 |
42 | /*
43 | Exercise
44 | create a Scala-Java Optional-Option
45 | .asScala
46 | */
47 | class ToScala[T](value: => T) {
48 | def asScala: T = value
49 | }
50 |
51 | implicit def asScalaOptional[T](o: ju.Optional[T]): ToScala[Option[T]] = new ToScala[Option[T]](
52 | if (o.isPresent) Some(o.get) else None
53 | )
54 |
55 | val juOptional: ju.Optional[Int] = ju.Optional.of(2)
56 | val scalaOption = juOptional.asScala
57 | println(scalaOption)
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/lectures/part4implicits/TypeClasses.scala:
--------------------------------------------------------------------------------
1 | package lectures.part4implicits
2 |
3 | /**
4 | * Created by Daniel.
5 | */
6 | object TypeClasses extends App {
7 |
8 | trait HTMLWritable {
9 | def toHtml: String
10 | }
11 |
12 | case class User(name: String, age: Int, email: String) extends HTMLWritable {
13 | override def toHtml: String = s"
"
14 | }
15 |
16 | User("John", 32, "john@rockthejvm.com").toHtml
17 | /*
18 | 1 - for the types WE write
19 | 2 - ONE implementation out of quite a number
20 | */
21 |
22 | // option 2 - pattern matching
23 | object HTMLSerializerPM {
24 | def serializeToHtml(value: Any) = value match {
25 | case User(n, a, e) =>
26 | case _ =>
27 | }
28 | }
29 |
30 | /*
31 | 1 - lost type safety
32 | 2 - need to modify the code every time
33 | 3 - still ONE implementation
34 | */
35 |
36 | trait HTMLSerializer[T] {
37 | def serialize(value: T): String
38 | }
39 |
40 | implicit object UserSerializer extends HTMLSerializer[User] {
41 | def serialize(user: User): String = s"${user.name} (${user.age} yo)
"
42 | }
43 |
44 | val john = User("John", 32, "john@rockthejvm.com")
45 | println(UserSerializer.serialize(john))
46 |
47 | // 1 - we can define serializers for other types
48 | import java.util.Date
49 | object DateSerializer extends HTMLSerializer[Date] {
50 | override def serialize(date: Date): String = s"${date.toString()}
"
51 | }
52 |
53 | // 2 - we can define MULTIPLE serializers
54 | object PartialUserSerializer extends HTMLSerializer[User] {
55 | def serialize(user: User): String = s"${user.name}
"
56 | }
57 |
58 | // part 2
59 | object HTMLSerializer {
60 | def serialize[T](value: T)(implicit serializer: HTMLSerializer[T]): String =
61 | serializer.serialize(value)
62 |
63 | def apply[T](implicit serializer: HTMLSerializer[T]) = serializer
64 | }
65 |
66 | implicit object IntSerializer extends HTMLSerializer[Int] {
67 | override def serialize(value: Int): String = s"$value
"
68 | }
69 |
70 | println(HTMLSerializer.serialize(42))
71 | println(HTMLSerializer.serialize(john))
72 |
73 | // access to the entire type class interface
74 | println(HTMLSerializer[User].serialize(john))
75 |
76 |
77 | // part 3
78 | implicit class HTMLEnrichment[T](value: T) {
79 | def toHTML(implicit serializer: HTMLSerializer[T]): String = serializer.serialize(value)
80 | }
81 |
82 | println(john.toHTML) // println(new HTMLEnrichment[User](john).toHTML(UserSerializer))
83 | // COOL!
84 | /*
85 | - extend to new types
86 | - choose implementation
87 | - super expressive!
88 | */
89 |
90 | println(2.toHTML)
91 | println(john.toHTML(PartialUserSerializer))
92 |
93 | /*
94 | - type class itself --- HTMLSerializer[T] { .. }
95 | - type class instances (some of which are implicit) --- UserSerializer, IntSerializer
96 | - conversion with implicit classes --- HTMLEnrichment
97 | */
98 |
99 | // context bounds
100 | def htmlBoilerplate[T](content: T)(implicit serializer: HTMLSerializer[T]): String =
101 | s" ${content.toHTML(serializer)}"
102 |
103 | def htmlSugar[T : HTMLSerializer](content: T): String = {
104 | val serializer = implicitly[HTMLSerializer[T]]
105 | // use serializer
106 | s" ${content.toHTML(serializer)}"
107 | }
108 |
109 | // implicitly
110 | case class Permissions(mask: String)
111 | object Permissions {
112 | implicit val defaultPermissions: Permissions = Permissions("0744")
113 | }
114 |
115 | // in some other part of the code
116 | val standardPerms = implicitly[Permissions]
117 |
118 |
119 | }
120 |
121 |
--------------------------------------------------------------------------------
/src/lectures/part5ts/FBoundedPolymorphism.scala:
--------------------------------------------------------------------------------
1 | package lectures.part5ts
2 |
3 | /**
4 | * Created by Daniel.
5 | */
6 | object FBoundedPolymorphism extends App {
7 |
8 | // trait Animal {
9 | // def breed: List[Animal]
10 | // }
11 | //
12 | // class Cat extends Animal {
13 | // override def breed: List[Animal] = ??? // List[Cat] !!
14 | // }
15 | //
16 | // class Dog extends Animal {
17 | // override def breed: List[Animal] = ??? // List[Dog] !!
18 | // }
19 |
20 | // Solution 1 - naive
21 |
22 | // trait Animal {
23 | // def breed: List[Animal]
24 | // }
25 | //
26 | // class Cat extends Animal {
27 | // override def breed: List[Cat] = ??? // List[Cat] !!
28 | // }
29 | //
30 | // class Dog extends Animal {
31 | // override def breed: List[Cat] = ??? // List[Dog] !!
32 | // }
33 |
34 |
35 | // Solution 2 - FBP
36 |
37 | // trait Animal[A <: Animal[A]] { // recursive type: F-Bounded Polymorphism
38 | // def breed: List[Animal[A]]
39 | // }
40 | //
41 | // class Cat extends Animal[Cat] {
42 | // override def breed: List[Animal[Cat]] = ??? // List[Cat] !!
43 | // }
44 | //
45 | // class Dog extends Animal[Dog] {
46 | // override def breed: List[Animal[Dog]] = ??? // List[Dog] !!
47 | // }
48 | //
49 | // trait Entity[E <: Entity[E]] // ORM
50 | // class Person extends Comparable[Person] { // FBP
51 | // override def compareTo(o: Person): Int = ???
52 | // }
53 | //
54 | // class Crocodile extends Animal[Dog] {
55 | // override def breed: List[Animal[Dog]] = ??? // List[Dog] !!
56 | // }
57 |
58 | // Solution 3 - FBP + self-types
59 |
60 | // trait Animal[A <: Animal[A]] { self: A =>
61 | // def breed: List[Animal[A]]
62 | // }
63 | //
64 | // class Cat extends Animal[Cat] {
65 | // override def breed: List[Animal[Cat]] = ??? // List[Cat] !!
66 | // }
67 | //
68 | // class Dog extends Animal[Dog] {
69 | // override def breed: List[Animal[Dog]] = ??? // List[Dog] !!
70 | // }
71 |
72 | // class Crocodile extends Animal[Dog] {
73 | // override def breed: List[Animal[Dog]] = ??? // List[Dog] !!
74 | // }
75 | //
76 | // trait Fish extends Animal[Fish]
77 | // class Shark extends Fish {
78 | // override def breed: List[Animal[Fish]] = List(new Cod) // wrong
79 | // }
80 | //
81 | // class Cod extends Fish {
82 | // override def breed: List[Animal[Fish]] = ???
83 | // }
84 |
85 | // Exercise
86 |
87 | // Solution 4 type classes!
88 |
89 | // trait Animal
90 | // trait CanBreed[A] {
91 | // def breed(a: A): List[A]
92 | // }
93 | //
94 | // class Dog extends Animal
95 | // object Dog {
96 | // implicit object DogsCanBreed extends CanBreed[Dog] {
97 | // def breed(a: Dog): List[Dog] = List()
98 | // }
99 | // }
100 | //
101 | // implicit class CanBreedOps[A](animal: A) {
102 | // def breed(implicit canBreed: CanBreed[A]): List[A] =
103 | // canBreed.breed(animal)
104 | // }
105 | //
106 | // val dog = new Dog
107 | // dog.breed // List[Dog]!!
108 | // /*
109 | // new CanBreedOps[Dog](dog).breed(Dog.DogsCanBreed)
110 | // implicit value to pass to breed: Dog.DogsCanBreed
111 | // */
112 | //
113 | // class Cat extends Animal
114 | // object Cat {
115 | // implicit object CatsCanBreed extends CanBreed[Dog] {
116 | // def breed(a: Dog): List[Dog] = List()
117 | // }
118 | // }
119 | //
120 | // val cat = new Cat
121 | // cat.breed
122 |
123 | // Solution #5
124 |
125 | trait Animal[A] { // pure type classes
126 | def breed(a: A): List[A]
127 | }
128 |
129 | class Dog
130 | object Dog {
131 | implicit object DogAnimal extends Animal[Dog] {
132 | override def breed(a: Dog): List[Dog] = List()
133 | }
134 | }
135 |
136 | class Cat
137 | object Cat {
138 | implicit object CatAnimal extends Animal[Dog] {
139 | override def breed(a: Dog): List[Dog] = List()
140 | }
141 | }
142 |
143 | implicit class AnimalOps[A](animal: A) {
144 | def breed(implicit animalTypeClassInstance: Animal[A]): List[A] =
145 | animalTypeClassInstance.breed(animal)
146 | }
147 |
148 | val dog = new Dog
149 | dog.breed
150 |
151 | // val cat = new Cat
152 | // cat.breed
153 |
154 | }
155 |
--------------------------------------------------------------------------------
/src/lectures/part5ts/HigherKindedTypes.scala:
--------------------------------------------------------------------------------
1 | package lectures.part5ts
2 |
3 | import scala.concurrent.Future
4 | import scala.concurrent.ExecutionContext.Implicits.global
5 |
6 | /**
7 | * Created by Daniel.
8 | */
9 | object HigherKindedTypes extends App {
10 |
11 | trait AHigherKindedType[F[_]]
12 |
13 | trait MyList[T] {
14 | def flatMap[B](f: T => B): MyList[B]
15 | }
16 |
17 | trait MyOption[T] {
18 | def flatMap[B](f: T => B): MyOption[B]
19 | }
20 |
21 | trait MyFuture[T] {
22 | def flatMap[B](f: T => B): MyFuture[B]
23 | }
24 |
25 | // combine/multiply List(1,2) x List("a", "b") => List(1a, 1b, 2a, 2b)
26 |
27 | // def multiply[A, B](listA: List[A], listB: List[B]): List[(A, B)] =
28 | // for {
29 | // a <- listA
30 | // b <- listB
31 | // } yield (a, b)
32 | //
33 | // def multiply[A, B](listA: Option[A], listB: Option[B]): Option[(A, B)] =
34 | // for {
35 | // a <- listA
36 | // b <- listB
37 | // } yield (a, b)
38 | //
39 | // def multiply[A, B](listA: Future[A], listB: Future[B]): Future[(A, B)] =
40 | // for {
41 | // a <- listA
42 | // b <- listB
43 | // } yield (a, b)
44 |
45 | // use HKT
46 |
47 | trait Monad[F[_], A] { // higher-kinded type class
48 | def flatMap[B](f: A => F[B]): F[B]
49 | def map[B](f: A => B): F[B]
50 | }
51 |
52 | implicit class MonadList[A](list: List[A]) extends Monad[List, A] {
53 | override def flatMap[B](f: A => List[B]): List[B] = list.flatMap(f)
54 | override def map[B](f: A => B): List[B] = list.map(f)
55 | }
56 |
57 | implicit class MonadOption[A](option: Option[A]) extends Monad[Option, A] {
58 | override def flatMap[B](f: A => Option[B]): Option[B] = option.flatMap(f)
59 | override def map[B](f: A => B): Option[B] = option.map(f)
60 | }
61 |
62 | def multiply[F[_], A, B](ma: Monad[F, A], mb: Monad[F, B]): F[(A, B)] =
63 | for {
64 | a <- ma
65 | b <- mb
66 | } yield (a, b)
67 | /*
68 | ma.flatMap(a => mb.map(b => (a,b)))
69 | */
70 |
71 |
72 |
73 | val monadList = new MonadList(List(1,2,3))
74 | monadList.flatMap(x => List(x, x + 1)) // List[Int]
75 | // Monad[List, Int] => List[Int]
76 | monadList.map(_ * 2) // List[Int
77 | // Monad[List, Int] => List[Int]
78 |
79 | println(multiply(List(1,2), List("a", "b")))
80 | println(multiply(Some(2), Some("scala")))
81 | }
82 |
--------------------------------------------------------------------------------
/src/lectures/part5ts/PathDependentTypes.scala:
--------------------------------------------------------------------------------
1 | package advanced.part5ts
2 |
3 | /**
4 | * Created by Daniel.
5 | */
6 | object PathDependentTypes extends App {
7 |
8 | class Outer {
9 | class Inner
10 | object InnerObject
11 | type InnerType
12 |
13 | def print(i: Inner) = println(i)
14 | def printGeneral(i: Outer#Inner) = println(i)
15 | }
16 |
17 | def aMethod: Int = {
18 | class HelperClass
19 | type HelperType = String
20 | 2
21 | }
22 |
23 | // per-instance
24 | val o = new Outer
25 | val inner = new o.Inner // o.Inner is a TYPE
26 |
27 | val oo = new Outer
28 | // val otherInner: oo.Inner = new o.Inner
29 |
30 | o.print(inner)
31 | // oo.print(inner)
32 |
33 | // path-dependent types
34 |
35 | // Outer#Inner
36 | o.printGeneral(inner)
37 | oo.printGeneral(inner)
38 |
39 | /*
40 | Exercise
41 | DB keyed by Int or String, but maybe others
42 | */
43 |
44 | /*
45 | use path-dependent types
46 | abstract type members and/or type aliases
47 | */
48 |
49 | trait ItemLike {
50 | type Key
51 | }
52 |
53 | trait Item[K] extends ItemLike {
54 | type Key = K
55 | }
56 |
57 | trait IntItem extends Item[Int]
58 | trait StringItem extends Item[String]
59 |
60 | def get[ItemType <: ItemLike](key: ItemType#Key): ItemType = ???
61 |
62 | get[IntItem](42) // ok
63 | get[StringItem]("home") // ok
64 |
65 | // get[IntItem]("scala") // not ok
66 | }
67 |
--------------------------------------------------------------------------------
/src/lectures/part5ts/Reflection.scala:
--------------------------------------------------------------------------------
1 | package lectures.part5ts
2 |
3 |
4 | /**
5 | * Created by Daniel.
6 | */
7 | object Reflection extends App {
8 | // reflection + macros + quasiquotes => METAPROGRAMMING
9 |
10 | case class Person(name: String) {
11 | def sayMyName(): Unit = println(s"Hi, my name is $name")
12 | }
13 |
14 | // 0 - import
15 | import scala.reflect.runtime.{universe => ru}
16 |
17 | // 1 - MIRROR
18 | val m = ru.runtimeMirror(getClass.getClassLoader)
19 | // 2 - create a class object = "description"
20 | val clazz = m.staticClass("advanced.part5ts.Reflection.Person") // creating a class object by NAME
21 | // 3 - create a reflected mirror = "can DO things"
22 | val cm = m.reflectClass(clazz)
23 | // 4 - get the constructor
24 | val constructor = clazz.primaryConstructor.asMethod
25 | // 5 - reflect the constructor
26 | val constructorMirror = cm.reflectConstructor(constructor)
27 | // 6 - invoke the constructor
28 | val instance = constructorMirror.apply("John")
29 |
30 | println(instance)
31 |
32 | // I have an instance
33 | val p = Person("Mary") // from the wire as a serialized object
34 | // method name computed from somewhere else
35 | val methodName = "sayMyName"
36 | // 1 - mirror
37 | // 2 - reflect the instance
38 | val reflected = m.reflect(p)
39 | // 3 - method symbol
40 | val methodSymbol = ru.typeOf[Person].decl(ru.TermName(methodName)).asMethod
41 | // 4 - reflect the method = can DO things
42 | val method = reflected.reflectMethod(methodSymbol)
43 | // 5 - invoke the method
44 |
45 | method.apply()
46 |
47 | // type erasure
48 |
49 | // pp #1: differentiate types at runtime
50 | val numbers = List(1,2,3)
51 | numbers match {
52 | case listOfStrings: List[String] => println("list of strings")
53 | case listOfNumbers: List[Int] => println("list of numbers")
54 | }
55 |
56 | // pp #2: limitations on overloads
57 | // def processList(list: List[Int]): Int = 43
58 | // def processList(list: List[String]): Int = 45
59 |
60 | // TypeTags
61 |
62 | // 0 - import
63 | import ru._
64 |
65 | // 1 - creating a type tag "manually"
66 | val ttag = typeTag[Person]
67 | println(ttag.tpe)
68 |
69 | class MyMap[K, V]
70 |
71 | // 2 - pass type tags as implicit parameters
72 | def getTypeArguments[T](value: T)(implicit typeTag: TypeTag[T]) = typeTag.tpe match {
73 | case TypeRef(_, _, typeArguments) => typeArguments
74 | case _ => List()
75 | }
76 |
77 | val myMap = new MyMap[Int, String]
78 | val typeArgs = getTypeArguments(myMap)//(typeTag: TypeTag[MyMap[Int,String]])
79 | println(typeArgs)
80 |
81 | def isSubtype[A, B](implicit ttagA: TypeTag[A], ttagB: TypeTag[B]): Boolean = {
82 | ttagA.tpe <:< ttagB.tpe
83 | }
84 |
85 | class Animal
86 | class Dog extends Animal
87 | println(isSubtype[Dog, Animal])
88 |
89 | // I have an instance
90 |
91 |
92 | // 3 - method symbol
93 | val anotherMethodSymbol = typeTag[Person].tpe.decl(ru.TermName(methodName)).asMethod
94 | // 4 - reflect the method = can DO things
95 | val sameMethod = reflected.reflectMethod(anotherMethodSymbol)
96 | // 5 - invoke the method
97 | sameMethod.apply()
98 | }
99 |
--------------------------------------------------------------------------------
/src/lectures/part5ts/RockingInheritance.scala:
--------------------------------------------------------------------------------
1 | package lectures.part5ts
2 |
3 | /**
4 | * Created by Daniel.
5 | */
6 | object RockingInheritance extends App {
7 |
8 | // convenience
9 | trait Writer[T] {
10 | def write(value: T): Unit
11 | }
12 | trait Closeable {
13 | def close(status: Int): Unit
14 | }
15 | trait GenericStream[T] {
16 | // some methods
17 | def foreach(f: T => Unit): Unit
18 | }
19 |
20 | def processStream[T](stream: GenericStream[T] with Writer[T] with Closeable): Unit = {
21 | stream.foreach(println)
22 | stream.close(0)
23 | }
24 |
25 | // diamond problem
26 |
27 | trait Animal { def name: String }
28 | trait Lion extends Animal { override def name: String = "lion" }
29 | trait Tiger extends Animal { override def name: String = "tiger" }
30 | class Mutant extends Lion with Tiger
31 |
32 | val m = new Mutant
33 | println(m.name)
34 |
35 | /*
36 | Mutant
37 | extends Animal with { override def name: String = "lion" }
38 | with { override def name: String = "tiger" }
39 |
40 | LAST OVERRIDE GETS PICKED
41 | */
42 |
43 | // the super problem + type linearization
44 |
45 | trait Cold {
46 | def print = println("cold")
47 | }
48 |
49 | trait Green extends Cold {
50 | override def print: Unit = {
51 | println("green")
52 | super.print
53 | }
54 | }
55 |
56 | trait Blue extends Cold {
57 | override def print: Unit = {
58 | println("blue")
59 | super.print
60 | }
61 | }
62 |
63 | class Red {
64 | def print = println("red")
65 | }
66 |
67 | class White extends Red with Green with Blue {
68 | override def print: Unit = {
69 | println("white")
70 | super.print
71 | }
72 | }
73 |
74 | val color = new White
75 | color.print
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/src/lectures/part5ts/SelfTypes.scala:
--------------------------------------------------------------------------------
1 | package lectures.part5ts
2 |
3 | /**
4 | * Created by Daniel.
5 | */
6 | object SelfTypes extends App {
7 |
8 | // requiring a type to be mixed in
9 |
10 | trait Instrumentalist {
11 | def play(): Unit
12 | }
13 |
14 | trait Singer { this: Instrumentalist => // SELF TYPE whoever implements Singer to implement Instrumentalist
15 |
16 | // rest of the implementation or API
17 | def sing(): Unit
18 | }
19 |
20 | class LeadSinger extends Singer with Instrumentalist {
21 | override def play(): Unit = ???
22 | override def sing(): Unit = ???
23 | }
24 |
25 | // class Vocalist extends Singer {
26 | // override def sing(): Unit = ???
27 | // }
28 |
29 | val jamesHetfield = new Singer with Instrumentalist {
30 | override def play(): Unit = ???
31 | override def sing(): Unit = ???
32 | }
33 |
34 | class Guitarist extends Instrumentalist {
35 | override def play(): Unit = println("(guitar solo)")
36 | }
37 |
38 | val ericClapton = new Guitarist with Singer {
39 | override def sing(): Unit = ???
40 | }
41 |
42 | // self-types vs inheritance
43 | class A
44 | class B extends A // B IS AN A
45 |
46 | trait T
47 | trait S { self: T => } // S REQUIRES a T
48 |
49 | // CAKE PATTERN => "dependency injection"
50 |
51 | // DI
52 | class Component {
53 | // API
54 | }
55 | class ComponentA extends Component
56 | class ComponentB extends Component
57 | class DependentComponent(val component: Component)
58 |
59 | // CAKE PATTERN
60 | trait ScalaComponent {
61 | // API
62 | def action(x: Int): String
63 | }
64 | trait ScalaDependentComponent { self: ScalaComponent =>
65 | def dependentAction(x: Int): String = action(x) + " this rocks!"
66 | }
67 | trait ScalaApplication { self: ScalaDependentComponent => }
68 |
69 | // layer 1 - small components
70 | trait Picture extends ScalaComponent
71 | trait Stats extends ScalaComponent
72 |
73 | // layer 2 - compose
74 | trait Profile extends ScalaDependentComponent with Picture
75 | trait Analytics extends ScalaDependentComponent with Stats
76 |
77 | // layer 3 - app
78 | trait AnalyticsApp extends ScalaApplication with Analytics
79 |
80 |
81 |
82 | // cyclical dependencies
83 |
84 | // class X extends Y
85 | // class Y extends X
86 |
87 | trait X { self: Y => }
88 | trait Y { self: X => }
89 | }
90 |
--------------------------------------------------------------------------------
/src/lectures/part5ts/StructuralTypes.scala:
--------------------------------------------------------------------------------
1 | package lectures.part5ts
2 |
3 | import scala.language.reflectiveCalls
4 |
5 | /**
6 | * Created by Daniel.
7 | */
8 | object StructuralTypes extends App {
9 |
10 | // structural types
11 |
12 | type JavaCloseable = java.io.Closeable
13 |
14 | class HipsterCloseable {
15 | def close(): Unit = println("yeah yeah I'm closing")
16 | def closeSilently(): Unit = println("not making a sound")
17 | }
18 |
19 | // def closeQuietly(closeable: JavaCloseable OR HipsterCloseable) // ?!
20 |
21 | type UnifiedCloseable = {
22 | def close(): Unit
23 | } // STRUCTURAL TYPE
24 |
25 | def closeQuietly(unifiedCloseable: UnifiedCloseable): Unit = unifiedCloseable.close()
26 |
27 | closeQuietly(new JavaCloseable {
28 | override def close(): Unit = ???
29 | })
30 | closeQuietly(new HipsterCloseable)
31 |
32 |
33 |
34 | // TYPE REFINEMENTS
35 |
36 |
37 | type AdvancedCloseable = JavaCloseable {
38 | def closeSilently(): Unit
39 | }
40 |
41 | class AdvancedJavaCloseable extends JavaCloseable {
42 | override def close(): Unit = println("Java closes")
43 | def closeSilently(): Unit = println("Java closes silently")
44 | }
45 |
46 | def closeShh(advCloseable: AdvancedCloseable): Unit = advCloseable.closeSilently()
47 |
48 | closeShh(new AdvancedJavaCloseable)
49 | // closeShh(new HipsterCloseable)
50 |
51 | // using structural types as standalone types
52 | def altClose(closeable: { def close(): Unit }): Unit = closeable.close()
53 |
54 |
55 | // type-checking => duck typing
56 |
57 | type SoundMaker = {
58 | def makeSound(): Unit
59 | }
60 |
61 | class Dog {
62 | def makeSound(): Unit = println("bark!")
63 | }
64 |
65 | class Car {
66 | def makeSound(): Unit = println("vrooom!")
67 | }
68 |
69 | val dog: SoundMaker = new Dog
70 | val car: SoundMaker = new Car
71 |
72 | // static duck typing
73 |
74 | // CAVEAT: based on reflection
75 |
76 | /*
77 | Exercises
78 | */
79 |
80 | // 1.
81 | trait CBL[+T] {
82 | def head: T
83 | def tail: CBL[T]
84 | }
85 |
86 | class Human {
87 | def head: Brain = new Brain
88 | }
89 |
90 | class Brain {
91 | override def toString: String = "BRAINZ!"
92 | }
93 |
94 | def f[T](somethingWithAHead: { def head: T }): Unit = println(somethingWithAHead.head)
95 |
96 | /*
97 | f is compatible with a CBL and with a Human? Yes.
98 | */
99 |
100 | case object CBNil extends CBL[Nothing] {
101 | def head: Nothing = ???
102 | def tail: CBL[Nothing] = ???
103 | }
104 | case class CBCons[T](override val head: T, override val tail: CBL[T]) extends CBL[T]
105 |
106 | f(CBCons(2, CBNil))
107 | f(new Human) // ?! T = Brain !!
108 |
109 | // 2.
110 | object HeadEqualizer {
111 | type Headable[T] = { def head: T }
112 |
113 | def ===[T](a: Headable[T], b: Headable[T]): Boolean = a.head == b.head
114 | }
115 |
116 | /*
117 | is compatible with a CBL and with a Human? Yes.
118 | */
119 | val brainzList = CBCons(new Brain, CBNil)
120 | val stringsList = CBCons("Brainz", CBNil)
121 |
122 | HeadEqualizer.===(brainzList, new Human)
123 | // problem:
124 | HeadEqualizer.===(new Human, stringsList) // not type safe
125 |
126 | }
127 |
--------------------------------------------------------------------------------
/src/lectures/part5ts/TypeMembers.scala:
--------------------------------------------------------------------------------
1 | package lectures.part5ts
2 |
3 | /**
4 | * Created by Daniel.
5 | */
6 | object TypeMembers extends App {
7 |
8 |
9 | class Animal
10 | class Dog extends Animal
11 | class Cat extends Animal
12 |
13 | class AnimalCollection {
14 | type AnimalType // abstract type member
15 | type BoundedAnimal <: Animal
16 | type SuperBoundedAnimal >: Dog <: Animal
17 | type AnimalC = Cat
18 | }
19 |
20 | val ac = new AnimalCollection
21 | val dog: ac.AnimalType = ???
22 |
23 | // val cat: ac.BoundedAnimal = new Cat
24 |
25 | val pup: ac.SuperBoundedAnimal = new Dog
26 | val cat: ac.AnimalC = new Cat
27 |
28 | type CatAlias = Cat
29 | val anotherCat: CatAlias = new Cat
30 |
31 | // alternative to generics
32 | trait MyList {
33 | type T
34 | def add(element: T): MyList
35 | }
36 |
37 | class NonEmptyList(value: Int) extends MyList {
38 | override type T = Int
39 | def add(element: Int): MyList = ???
40 | }
41 |
42 | // .type
43 | type CatsType = cat.type
44 | val newCat: CatsType = cat
45 | // new CatsType
46 |
47 | /*
48 | Exercise - enforce a type to be applicable to SOME TYPES only
49 | */
50 | // LOCKED
51 | trait MList {
52 | type A
53 | def head: A
54 | def tail: MList
55 | }
56 |
57 | trait ApplicableToNumbers {
58 | type A <: Number
59 | }
60 |
61 | // NOT OK
62 | // class CustomList(hd: String, tl: CustomList) extends MList with ApplicableToNumbers {
63 | // type A = String
64 | // def head = hd
65 | // def tail = tl
66 | // }
67 |
68 | // OK
69 | class IntList(hd: Integer, tl: IntList) extends MList with ApplicableToNumbers {
70 | type A = Integer
71 | def head = hd
72 | def tail = tl
73 | }
74 |
75 | // Number
76 | // type members and type member constraints (bounds)
77 | }
78 |
--------------------------------------------------------------------------------
/src/lectures/part5ts/Variance.scala:
--------------------------------------------------------------------------------
1 | package lectures.part5ts
2 |
3 | /**
4 | * Created by Daniel.
5 | */
6 | object Variance extends App {
7 |
8 | trait Animal
9 | class Dog extends Animal
10 | class Cat extends Animal
11 | class Crocodile extends Animal
12 |
13 | // what is variance?
14 | // "inheritance" - type substitution of generics
15 |
16 | class Cage[T]
17 | // yes - covariance
18 | class CCage[+T]
19 | val ccage: CCage[Animal] = new CCage[Cat]
20 |
21 | // no - invariance
22 | class ICage[T]
23 | // val icage: ICage[Animal] = new ICage[Cat]
24 | // val x: Int = "hello"
25 |
26 | // hell no - opposite = contravariance
27 | class XCage[-T]
28 | val xcage: XCage[Cat] = new XCage[Animal]
29 |
30 | class InvariantCage[T](val animal: T) // invariant
31 |
32 | // covariant positions
33 | class CovariantCage[+T](val animal: T) // COVARIANT POSITION
34 |
35 | // class ContravariantCage[-T](val animal: T)
36 | /*
37 | val catCage: XCage[Cat] = new XCage[Animal](new Crocodile)
38 | */
39 |
40 | // class CovariantVariableCage[+T](var animal: T) // types of vars are in CONTRAVARIANT POSITION
41 | /*
42 | val ccage: CCage[Animal] = new CCage[Cat](new Cat)
43 | ccage.animal = new Crocodile
44 | */
45 |
46 | // class ContravariantVariableCage[-T](var animal: T) // also in COVARIANT POSITION
47 | /*
48 | val catCage: XCage[Cat] = new XCage[Animal](new Crocodile)
49 | */
50 | class InvariantVariableCage[T](var animal: T) // ok
51 |
52 | // trait AnotherCovariantCage[+T] {
53 | // def addAnimal(animal: T) // CONTRAVARIANT POSITION
54 | // }
55 | /*
56 | val ccage: CCage[Animal] = new CCage[Dog]
57 | ccage.add(new Cat)
58 | */
59 |
60 | class AnotherContravariantCage[-T] {
61 | def addAnimal(animal: T) = true
62 | }
63 | val acc: AnotherContravariantCage[Cat] = new AnotherContravariantCage[Animal]
64 | acc.addAnimal(new Cat)
65 | class Kitty extends Cat
66 | acc.addAnimal(new Kitty)
67 |
68 | class MyList[+A] {
69 | def add[B >: A](element: B): MyList[B] = new MyList[B] // widening the type
70 | }
71 |
72 | val emptyList = new MyList[Kitty]
73 | val animals = emptyList.add(new Kitty)
74 | val moreAnimals = animals.add(new Cat)
75 | val evenMoreAnimals = moreAnimals.add(new Dog)
76 |
77 | // METHOD ARGUMENTS ARE IN CONTRAVARIANT POSITION.
78 |
79 | // return types
80 | class PetShop[-T] {
81 | // def get(isItaPuppy: Boolean): T // METHOD RETURN TYPES ARE IN COVARIANT POSITION
82 | /*
83 | val catShop = new PetShop[Animal] {
84 | def get(isItaPuppy: Boolean): Animal = new Cat
85 | }
86 |
87 | val dogShop: PetShop[Dog] = catShop
88 | dogShop.get(true) // EVIL CAT!
89 | */
90 |
91 | def get[S <: T](isItaPuppy: Boolean, defaultAnimal: S): S = defaultAnimal
92 | }
93 |
94 | val shop: PetShop[Dog] = new PetShop[Animal]
95 | // val evilCat = shop.get(true, new Cat)
96 | class TerraNova extends Dog
97 | val bigFurry = shop.get(true, new TerraNova)
98 |
99 | /*
100 | Big rule
101 | - method arguments are in CONTRAVARIANT position
102 | - return types are in COVARIANT position
103 | */
104 |
105 | /**
106 | * 1. Invariant, covariant, contravariant
107 | * Parking[T](things: List[T]) {
108 | * park(vehicle: T)
109 | * impound(vehicles: List[T])
110 | * checkVehicles(conditions: String): List[T]
111 | * }
112 | *
113 | * 2. used someone else's API: IList[T]
114 | * 3. Parking = monad!
115 | * - flatMap
116 | */
117 | class Vehicle
118 | class Bike extends Vehicle
119 | class Car extends Vehicle
120 | class IList[T]
121 |
122 | class IParking[T](vehicles: List[T]) {
123 | def park(vehicle: T): IParking[T] = ???
124 | def impound(vehicles: List[T]): IParking[T] = ???
125 | def checkVehicles(conditions: String): List[T] = ???
126 |
127 | def flatMap[S](f: T => IParking[S]): IParking[S] = ???
128 | }
129 |
130 | class CParking[+T](vehicles: List[T]) {
131 | def park[S >: T](vehicle: S): CParking[S] = ???
132 | def impound[S >: T](vehicles: List[S]): CParking[S] = ???
133 | def checkVehicles(conditions: String): List[T] = ???
134 |
135 | def flatMap[S](f: T => CParking[S]): CParking[S] = ???
136 | }
137 |
138 | class CList[-T]
139 | class XParking[-T](vehicles: List[T]) {
140 | def park(vehicle: T): XParking[T] = ???
141 | def impound[R <: T](vehicles: CList[R]): XParking[R] = ???
142 | def checkVehicles[S <: T](conditions: String): List[S] = ???
143 |
144 | def flatMap[R <: T, S](f: Function1[R, XParking[S]]): XParking[S] = ???
145 | }
146 |
147 | /*
148 | Rule of thumb
149 | - use covariance = COLLECTION OF THINGS
150 | - use contravariance = GROUP OF ACTIONS
151 | */
152 |
153 | class CParking2[+T](vehicles: IList[T]) {
154 | def park[S >: T](vehicle: S): CParking2[S] = ???
155 | def impound[S >: T](vehicles: IList[S]): CParking2[S] = ???
156 | def checkVehicles[S >: T](conditions: String): IList[S] = ???
157 | }
158 |
159 | class XParking2[-T](vehicles: IList[T]) {
160 | def park(vehicle: T): XParking2[T] = ???
161 | def impound[S <: T](vehicles: IList[S]): XParking2[S] = ???
162 | def checkVehicles[S <: T](conditions: String): IList[S] = ???
163 | }
164 |
165 | // flatMap
166 | }
167 |
--------------------------------------------------------------------------------
/src/playground/JavaPlayground.java:
--------------------------------------------------------------------------------
1 | package playground;
2 |
3 | /**
4 | * Created by Daniel.
5 | */
6 | public class JavaPlayground {
7 | public static void main(String[] args) {
8 | System.out.println("Hello, Java");
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/playground/ScalaPlayground.scala:
--------------------------------------------------------------------------------
1 | package playground
2 |
3 | import scala.annotation.tailrec
4 |
5 | /**
6 | * Created by Daniel.
7 | */
8 | object ScalaPlayground extends App {
9 |
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/target/.history3:
--------------------------------------------------------------------------------
1 | 1695548901185:reload
2 | 1695549023073:;set _root_.scala.collection.Seq(historyPath := None,shellPrompt := { _ => "" },SettingKey[_root_.scala.Option[_root_.sbt.File]]("sbtStructureOutputFile") in _root_.sbt.Global := _root_.scala.Some(_root_.sbt.file("/private/var/folders/0_/l801qy2501d6655txswpw8lc0000gn/T/sbt-structure.xml")),SettingKey[_root_.java.lang.String]("sbtStructureOptions") in _root_.sbt.Global := "download, resolveClassifiers");apply -cp "/Users/daniel/Library/Application Support/JetBrains/IdeaIC2023.1/plugins/Scala/repo/org/jetbrains/scala/sbt-structure-extractor_2.12_1.0/2022.3.1/sbt-structure-extractor-2022.3.1.jar" org.jetbrains.sbt.CreateTasks;preferScala2;*/*:dumpStructure
3 |
--------------------------------------------------------------------------------
/target/scala-2.13/update/update_cache_2.13/inputs:
--------------------------------------------------------------------------------
1 | -1752903609
--------------------------------------------------------------------------------
/target/streams/_global/_global/csrLogger/_global/streams/out:
--------------------------------------------------------------------------------
1 | [debug] downloaded https://repo1.maven.org/maven2/org/scala-lang/scala-reflect_2.13/2.13.5/scala-reflect_2.13-2.13.5.pom
2 | [debug] downloaded https://repo1.maven.org/maven2/org/scala-lang/scala-reflect_2.13/2.13.5/scala-reflect_2.13-2.13.5.pom.sha1
3 |
--------------------------------------------------------------------------------
/target/streams/_global/_global/dumpStructure/_global/streams/out:
--------------------------------------------------------------------------------
1 | [info] Writing structure to /private/var/folders/0_/l801qy2501d6655txswpw8lc0000gn/T/sbt-structure.xml...
2 | [info] Done.
3 |
--------------------------------------------------------------------------------
/target/streams/_global/csrConfiguration/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/target/streams/_global/csrConfiguration/_global/streams/out
--------------------------------------------------------------------------------
/target/streams/_global/csrProject/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/target/streams/_global/csrProject/_global/streams/out
--------------------------------------------------------------------------------
/target/streams/_global/dependencyPositions/_global/streams/update_cache_2.13/input_dsp:
--------------------------------------------------------------------------------
1 | -1950826002
--------------------------------------------------------------------------------
/target/streams/_global/dependencyPositions/_global/streams/update_cache_2.13/output_dsp:
--------------------------------------------------------------------------------
1 | {"{\"organization\":\"org.scala-lang\",\"name\":\"scala-library\",\"revision\":\"2.13.5\",\"isChanging\":false,\"isTransitive\":true,\"isForce\":false,\"explicitArtifacts\":[],\"inclusions\":[],\"exclusions\":[],\"extraAttributes\":{},\"crossVersion\":{\"type\":\"Disabled\"}}":{"value":{"$fields":["path","startLine"],"path":"/Users/daniel/dev/rockthejvm/courses/scala-2-advanced/build.sbt","startLine":8},"type":"LinePosition"},"{\"organization\":\"com.novocode\",\"name\":\"junit-interface\",\"revision\":\"0.11\",\"configurations\":\"test\",\"isChanging\":false,\"isTransitive\":true,\"isForce\":false,\"explicitArtifacts\":[],\"inclusions\":[],\"exclusions\":[],\"extraAttributes\":{},\"crossVersion\":{\"type\":\"Disabled\"}}":{"value":{"$fields":["path","startLine"],"path":"/Users/daniel/dev/rockthejvm/courses/scala-2-advanced/build.sbt","startLine":8},"type":"LinePosition"},"{\"organization\":\"org.scala-lang.modules\",\"name\":\"scala-parallel-collections\",\"revision\":\"1.0.4\",\"isChanging\":false,\"isTransitive\":true,\"isForce\":false,\"explicitArtifacts\":[],\"inclusions\":[],\"exclusions\":[],\"extraAttributes\":{},\"crossVersion\":{\"type\":\"Binary\",\"prefix\":\"\",\"suffix\":\"\"}}":{"value":{"$fields":["path","startLine"],"path":"/Users/daniel/dev/rockthejvm/courses/scala-2-advanced/build.sbt","startLine":8},"type":"LinePosition"}}
--------------------------------------------------------------------------------
/target/streams/_global/ivyConfiguration/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/target/streams/_global/ivyConfiguration/_global/streams/out
--------------------------------------------------------------------------------
/target/streams/_global/ivySbt/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/target/streams/_global/ivySbt/_global/streams/out
--------------------------------------------------------------------------------
/target/streams/_global/moduleSettings/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/target/streams/_global/moduleSettings/_global/streams/out
--------------------------------------------------------------------------------
/target/streams/_global/projectDescriptors/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/target/streams/_global/projectDescriptors/_global/streams/out
--------------------------------------------------------------------------------
/target/streams/_global/ssExtractDependencies/_global/streams/out:
--------------------------------------------------------------------------------
1 | [error] sbt.librarymanagement.ResolveException: Error downloading org.scala-lang:scala-reflect_2.13:2.13.5
2 | [error] Not found
3 | [error] Not found
4 | [error] not found: /Users/daniel/.ivy2/local/org.scala-lang/scala-reflect_2.13/2.13.5/ivys/ivy.xml
5 | [error] not found: https://repo1.maven.org/maven2/org/scala-lang/scala-reflect_2.13/2.13.5/scala-reflect_2.13-2.13.5.pom
6 | [error] at lmcoursier.CoursierDependencyResolution.unresolvedWarningOrThrow(CoursierDependencyResolution.scala:344)
7 | [error] at lmcoursier.CoursierDependencyResolution.$anonfun$update$38(CoursierDependencyResolution.scala:313)
8 | [error] at scala.util.Either$LeftProjection.map(Either.scala:573)
9 | [error] at lmcoursier.CoursierDependencyResolution.update(CoursierDependencyResolution.scala:313)
10 | [error] at sbt.librarymanagement.DependencyResolution.update(DependencyResolution.scala:60)
11 | [error] at sbt.internal.LibraryManagement$.resolve$1(LibraryManagement.scala:59)
12 | [error] at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$12(LibraryManagement.scala:133)
13 | [error] at sbt.util.Tracked$.$anonfun$lastOutput$1(Tracked.scala:73)
14 | [error] at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$20(LibraryManagement.scala:146)
15 | [error] at scala.util.control.Exception$Catch.apply(Exception.scala:228)
16 | [error] at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$11(LibraryManagement.scala:146)
17 | [error] at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$11$adapted(LibraryManagement.scala:127)
18 | [error] at sbt.util.Tracked$.$anonfun$inputChangedW$1(Tracked.scala:219)
19 | [error] at sbt.internal.LibraryManagement$.cachedUpdate(LibraryManagement.scala:160)
20 | [error] at sbt.Classpaths$.$anonfun$updateTask0$1(Defaults.scala:3687)
21 | [error] at scala.Function1.$anonfun$compose$1(Function1.scala:49)
22 | [error] at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:62)
23 | [error] at sbt.std.Transform$$anon$4.work(Transform.scala:68)
24 | [error] at sbt.Execute.$anonfun$submit$2(Execute.scala:282)
25 | [error] at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:23)
26 | [error] at sbt.Execute.work(Execute.scala:291)
27 | [error] at sbt.Execute.$anonfun$submit$1(Execute.scala:282)
28 | [error] at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265)
29 | [error] at sbt.CompletionService$$anon$2.call(CompletionService.scala:64)
30 | [error] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
31 | [error] at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
32 | [error] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
33 | [error] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
34 | [error] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
35 | [error] at java.base/java.lang.Thread.run(Thread.java:833)
36 | [error] (ssExtractDependencies) sbt.librarymanagement.ResolveException: Error downloading org.scala-lang:scala-reflect_2.13:2.13.5
37 | [error] Not found
38 | [error] Not found
39 | [error] not found: /Users/daniel/.ivy2/local/org.scala-lang/scala-reflect_2.13/2.13.5/ivys/ivy.xml
40 | [error] not found: https://repo1.maven.org/maven2/org/scala-lang/scala-reflect_2.13/2.13.5/scala-reflect_2.13-2.13.5.pom
41 |
--------------------------------------------------------------------------------
/target/streams/_global/update/_global/streams/out:
--------------------------------------------------------------------------------
1 | [debug] not up to date. inChanged = true, force = false
2 | [debug] Updating ...
3 | [debug] Done updating
4 |
--------------------------------------------------------------------------------
/target/streams/_global/updateClassifiers/_global/streams/out:
--------------------------------------------------------------------------------
1 | [debug] not up to date. inChanged = true, force = false
2 | [debug] Updating ProjectRef(uri("file:/Users/daniel/dev/rockthejvm/courses/scala-2-advanced/"), "root")...
3 | [debug] Done updating ProjectRef(uri("file:/Users/daniel/dev/rockthejvm/courses/scala-2-advanced/"), "root")
4 |
--------------------------------------------------------------------------------
/target/streams/_global/updateClassifiers/_global/streams/update_cache_2.13/inputs:
--------------------------------------------------------------------------------
1 | -1536732559
--------------------------------------------------------------------------------
/target/streams/compile/externalDependencyClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 | /Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.5/scala-library-2.13.5.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/modules/scala-parallel-collections_2.13/1.0.4/scala-parallel-collections_2.13-1.0.4.jar
2 |
--------------------------------------------------------------------------------
/target/streams/compile/managedClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 | /Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.5/scala-library-2.13.5.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/modules/scala-parallel-collections_2.13/1.0.4/scala-parallel-collections_2.13-1.0.4.jar
2 |
--------------------------------------------------------------------------------
/target/streams/compile/scalacOptions/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/target/streams/compile/scalacOptions/_global/streams/out
--------------------------------------------------------------------------------
/target/streams/compile/unmanagedClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/target/streams/compile/unmanagedClasspath/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/target/streams/compile/unmanagedClasspath/_global/streams/out
--------------------------------------------------------------------------------
/target/streams/compile/unmanagedJars/_global/streams/export:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/target/streams/runtime/externalDependencyClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 | /Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.5/scala-library-2.13.5.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/modules/scala-parallel-collections_2.13/1.0.4/scala-parallel-collections_2.13-1.0.4.jar
2 |
--------------------------------------------------------------------------------
/target/streams/runtime/managedClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 | /Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.5/scala-library-2.13.5.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/modules/scala-parallel-collections_2.13/1.0.4/scala-parallel-collections_2.13-1.0.4.jar
2 |
--------------------------------------------------------------------------------
/target/streams/runtime/unmanagedClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/target/streams/runtime/unmanagedClasspath/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/target/streams/runtime/unmanagedClasspath/_global/streams/out
--------------------------------------------------------------------------------
/target/streams/runtime/unmanagedJars/_global/streams/export:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/target/streams/test/externalDependencyClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 | /Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.5/scala-library-2.13.5.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/com/novocode/junit-interface/0.11/junit-interface-0.11.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/modules/scala-parallel-collections_2.13/1.0.4/scala-parallel-collections_2.13-1.0.4.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/junit/junit/4.11/junit-4.11.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-sbt/test-interface/1.0/test-interface-1.0.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar
2 |
--------------------------------------------------------------------------------
/target/streams/test/managedClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 | /Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.5/scala-library-2.13.5.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/com/novocode/junit-interface/0.11/junit-interface-0.11.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/modules/scala-parallel-collections_2.13/1.0.4/scala-parallel-collections_2.13-1.0.4.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/junit/junit/4.11/junit-4.11.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-sbt/test-interface/1.0/test-interface-1.0.jar:/Users/daniel/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar
2 |
--------------------------------------------------------------------------------
/target/streams/test/unmanagedClasspath/_global/streams/export:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/target/streams/test/unmanagedClasspath/_global/streams/out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rockthejvm/scala-2-advanced/b36e0be212f44b7d1ec7099a65de930707c434b0/target/streams/test/unmanagedClasspath/_global/streams/out
--------------------------------------------------------------------------------
/target/streams/test/unmanagedJars/_global/streams/export:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------