Skip to content

Commit 6eb5ab9

Browse files
Updates Project
1 parent 0661c89 commit 6eb5ab9

27 files changed

+236
-205
lines changed

.scalafmt.conf

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
version=2.4.2
12
style = defaultWithAlign
23
maxColumn = 100
34

@@ -19,5 +20,4 @@ docstrings = JavaDoc
1920
rewrite {
2021
rules = [SortImports, RedundantBraces]
2122
redundantBraces.maxLines = 1
22-
}
23-
23+
}

.travis.yml

-17
This file was deleted.

build.sbt

+13-22
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,16 @@
1-
import ProjectPlugin.autoImport._
2-
val scalaExercisesV = "0.6.0-SNAPSHOT"
1+
addCommandAlias("ci-test", "scalafmtCheckAll; scalafmtSbtCheck; test")
2+
addCommandAlias("ci-docs", "github; project-docs/mdoc; headerCreateAll")
33

4-
def dep(artifactId: String) = "org.scala-exercises" %% artifactId % scalaExercisesV
5-
6-
lazy val fpinscala = (project in file("."))
4+
lazy val exercises = (project in file("."))
5+
.settings(moduleName := "exercises-fpinscala")
6+
.settings(exercisesSettings)
77
.enablePlugins(ExerciseCompilerPlugin)
8-
.settings(
9-
name := "exercises-fpinscala",
10-
libraryDependencies ++= Seq(
11-
dep("exercise-compiler"),
12-
dep("definitions"),
13-
%%("shapeless", V.shapeless),
14-
%%("scalatest", V.scalatest),
15-
%%("scalacheck", V.scalacheck),
16-
"com.github.alexarchambault" %% "scalacheck-shapeless_1.14" % V.scalacheckShapeless,
17-
"org.scalatestplus" %% "scalatestplus-scalacheck" % V.scalatestplusScheck
18-
)
19-
)
20-
21-
// Distribution
228

23-
pgpPassphrase := Some(getEnvVar("PGP_PASSPHRASE").getOrElse("").toCharArray)
24-
pgpPublicRing := file(s"$gpgFolder/pubring.gpg")
25-
pgpSecretRing := file(s"$gpgFolder/secring.gpg")
9+
lazy val `project-docs` = (project in file(".docs"))
10+
.aggregate(exercises)
11+
.dependsOn(exercises)
12+
.settings(moduleName := "exercises-project-docs")
13+
.settings(mdocIn := file(".docs"))
14+
.settings(mdocOut := file("."))
15+
.settings(skip in publish := true)
16+
.enablePlugins(MdocPlugin)

project/ProjectPlugin.scala

+25-31
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,49 @@
1-
import de.heikoseeberger.sbtheader.License._
2-
import de.heikoseeberger.sbtheader.HeaderPlugin.autoImport._
31
import sbt.Keys._
42
import sbt._
5-
import sbtorgpolicies._
6-
import sbtorgpolicies.model._
7-
import sbtorgpolicies.OrgPoliciesPlugin.autoImport._
3+
import com.alejandrohdezma.sbt.github.SbtGithubPlugin
84

95
object ProjectPlugin extends AutoPlugin {
106

117
override def trigger: PluginTrigger = allRequirements
128

13-
override def requires: Plugins = plugins.JvmPlugin && OrgPoliciesPlugin
9+
override def requires: Plugins = plugins.JvmPlugin && SbtGithubPlugin
1410

1511
object autoImport {
1612

1713
lazy val V = new {
18-
val scala213: String = "2.13.1"
1914
val shapeless: String = "2.3.3"
20-
val scalatest: String = "3.1.1"
21-
val scalatestplusScheck: String = "3.1.0.0-RC2"
15+
val scala: String = "2.13.2"
16+
val scalaExercises: String = "0.6.0-SNAPSHOT"
2217
val scalacheck: String = "1.14.3"
2318
val scalacheckShapeless: String = "1.2.5"
19+
val scalatest: String = "3.1.1"
20+
val scalatestplusScheck: String = "3.1.1.1"
2421
}
25-
}
2622

27-
import autoImport._
23+
def dep(artifactId: String) = "org.scala-exercises" %% artifactId % V.scalaExercises
24+
25+
lazy val exercisesSettings = Seq(
26+
libraryDependencies ++= Seq(
27+
dep("exercise-compiler"),
28+
dep("definitions"),
29+
"com.chuusai" %% "shapeless" % V.shapeless,
30+
"org.scalatest" %% "scalatest" % V.scalatest,
31+
"org.scalacheck" %% "scalacheck" % V.scalacheck,
32+
"org.scalatestplus" %% "scalacheck-1-14" % V.scalatestplusScheck,
33+
"com.github.alexarchambault" %% "scalacheck-shapeless_1.14" % V.scalacheckShapeless
34+
)
35+
)
36+
}
2837

2938
override def projectSettings: Seq[Def.Setting[_]] =
3039
Seq(
31-
description := "Scala Exercises: The path to enlightenment",
32-
startYear := Option(2016),
33-
orgGithubSetting := GitHubSettings(
34-
organization = "scala-exercises",
35-
project = name.value,
36-
organizationName = "Scala Exercises",
37-
groupId = "org.scala-exercises",
38-
organizationHomePage = url("https://www.scala-exercises.org"),
39-
organizationEmail = "[email protected]"
40-
),
41-
orgLicenseSetting := ApacheLicense,
42-
scalaVersion := V.scala213,
43-
scalaOrganization := "org.scala-lang",
40+
organization := "org.scala-exercises",
41+
organizationName := "47 Degrees",
42+
organizationHomepage := Some(url("https://47deg.com")),
43+
scalaVersion := autoImport.V.scala,
4444
resolvers ++= Seq(
45-
Resolver.mavenLocal,
4645
Resolver.sonatypeRepo("snapshots"),
4746
Resolver.sonatypeRepo("releases")
48-
),
49-
scalacOptions := scalacCommonOptions ++ scalacLanguageOptions,
50-
headerLicense := Some(Custom(s"""| scala-exercises - ${name.value}
51-
| Copyright (C) 2015-2019 47 Degrees, LLC. <http://www.47deg.com>
52-
|
53-
|""".stripMargin))
47+
)
5448
)
5549
}

project/plugins.sbt

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
resolvers ++= Seq(
2-
Resolver.sonatypeRepo("snapshots")
3-
)
4-
5-
addSbtPlugin("org.scala-exercises" % "sbt-exercise" % "0.6.0-SNAPSHOT")
6-
addSbtPlugin("com.47deg" % "sbt-org-policies" % "0.12.0-M3")
1+
resolvers += Resolver.sonatypeRepo("snapshots")
2+
addSbtPlugin("org.scala-exercises" % "sbt-exercise" % "0.6.0-SNAPSHOT")
3+
addSbtPlugin("com.geirsson" % "sbt-ci-release" % "1.5.3")
4+
addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.1.5")
5+
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.3.4")
6+
addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.6.0")
7+
addSbtPlugin("com.alejandrohdezma" %% "sbt-github" % "0.8.0")
8+
addSbtPlugin("com.alejandrohdezma" % "sbt-github-header" % "0.8.0")
9+
addSbtPlugin("com.alejandrohdezma" % "sbt-github-mdoc" % "0.8.0")
10+
addSbtPlugin("com.alejandrohdezma" % "sbt-mdoc-toc" % "0.2")

pubring.gpg

-18
This file was deleted.

secring.gpg.enc

-1.81 KB
Binary file not shown.

src/main/scala/fpinscalalib/ErrorHandlingSection.scala

+6-3
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,8 @@ object ErrorHandlingSection
135135
def optionFilterAssert(
136136
res0: Some[Employee],
137137
res1: Option[Employee],
138-
res2: Option[Employee]): Unit = {
138+
res2: Option[Employee]
139+
): Unit = {
139140
lookupByName("Joe").filter(_.department != "IT") shouldBe res0
140141
lookupByName("Mary").filter(_.department != "IT") shouldBe res1
141142
lookupByName("Foo").filter(_.department != "IT") shouldBe res2
@@ -271,7 +272,8 @@ object ErrorHandlingSection
271272
e.manager match {
272273
case Some(e) => Right(e)
273274
case _ => Left("Manager not found")
274-
})
275+
}
276+
)
275277

276278
getManager(lookupByNameViaEither("Joe")) shouldBe res0
277279
getManager(lookupByNameViaEither("Mary")) shouldBe res1
@@ -298,7 +300,8 @@ object ErrorHandlingSection
298300
e.manager match {
299301
case Some(e) => Right(e)
300302
case _ => Left("Manager not found")
301-
})
303+
}
304+
)
302305

303306
getManager(lookupByNameViaEither("Joe")).orElse(Right("Mr. CEO")) shouldBe res0
304307
getManager(lookupByNameViaEither("Mary")).orElse(Right("Mr. CEO")) shouldBe res1

src/main/scala/fpinscalalib/FunctionalDataStructuresSection.scala

+4-2
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ object FunctionalDataStructuresSection
9191
res1: List[Int],
9292
res2: List[Int],
9393
res3: List[Int],
94-
res4: List[Int]) = {
94+
res4: List[Int]
95+
) = {
9596
def drop[A](l: List[A], n: Int): List[A] =
9697
if (n <= 0) l
9798
else
@@ -161,7 +162,8 @@ object FunctionalDataStructuresSection
161162
res7: Int,
162163
res8: Int,
163164
res9: Int,
164-
res10: Int) = {
165+
res10: Int
166+
) = {
165167
foldRight(Cons(1, Cons(2, Cons(3, Nil))), 0)((x, y) => x + y) shouldBe 6
166168
res0 + foldRight(Cons(2, Cons(3, Nil)), 0)((x, y) => x + y) shouldBe 6
167169
res1 + res2 + foldRight(Cons(3, Nil), 0)((x, y) => x + y) shouldBe 6

src/main/scala/fpinscalalib/FunctionalStateSection.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ object FunctionalStateSection
293293
Machine(false, candy, coin + res0)
294294
case (Turn, Machine(false, candy, coin)) =>
295295
Machine(true, candy - res1, coin)
296-
}
296+
}
297297

298298
def simulateMachine(inputs: List[Input]): State[Machine, (Int, Int)] =
299299
for {

src/main/scala/fpinscalalib/ParserCombinatorsSection.scala

+10-10
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ object ParserCombinatorsSection
108108
*/
109109
def parserManyAssert(
110110
res0: Either[ParseError, List[Char]],
111-
res1: Either[ParseError, List[Char]]): Unit = {
111+
res1: Either[ParseError, List[Char]]
112+
): Unit = {
112113
def many[A](p: Parser[A]): Parser[List[A]] =
113114
map2(p, many(p))(_ :: _) or fpinscalalib.customlib.parsing.Reference.succeed(List())
114115

@@ -276,14 +277,13 @@ object ParserCombinatorsSection
276277
def parserStringAssert(res0: String): Unit = {
277278
def string(w: String): Parser[String] = {
278279
val msg = "'" + w + "'"
279-
s =>
280-
{
281-
val i = firstNonmatchingIndex(s.loc.input, w, s.loc.offset)
282-
if (i == -1) // they matched
283-
Success(w, w.length)
284-
else
285-
Failure(s.loc.advanceBy(i).toError(msg), i != 0)
286-
}
280+
s => {
281+
val i = firstNonmatchingIndex(s.loc.input, w, s.loc.offset)
282+
if (i == -1) // they matched
283+
Success(w, w.length)
284+
else
285+
Failure(s.loc.advanceBy(i).toError(msg), i != 0)
286+
}
287287
}
288288

289289
val parseFunction = run(
@@ -329,7 +329,7 @@ object ParserCombinatorsSection
329329
p(s) match {
330330
case Success(_, n) => Success(s.slice(n), n)
331331
case f @ Failure(_, _) => f
332-
}
332+
}
333333

334334
val parserFunction = run(
335335
slice(many1(string("a")))

src/main/scala/fpinscalalib/PropertyBasedTestingSection.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -357,10 +357,10 @@ object PropertyBasedTestingSection
357357
* Let's show how we can test higher-order functions with `takeWhile` and `dropWhile` from `List`:
358358
*/
359359
def propTakeWhileDropWhile(res0: Result): Unit = {
360-
val prop = forAll(listOf(Gen.choose(0, 20)))(l => {
360+
val prop = forAll(listOf(Gen.choose(0, 20))) { l =>
361361
val index = Gen.choose(0, 20).sample.run(RNG.Simple(47))._1
362362
l.takeWhile(_ < index) ++ l.dropWhile(_ < index) == l
363-
})
363+
}
364364
prop.run(100, 100, RNG.Simple(System.currentTimeMillis)) shouldBe res0
365365
}
366366
}

src/main/scala/fpinscalalib/StrictnessAndLazinessSection.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@ object StrictnessAndLazinessSection
185185
res2: Stream[Int],
186186
res3: Int,
187187
res4: Stream[Int],
188-
res5: Int): Unit = {
188+
res5: Int
189+
): Unit = {
189190
val startingPoint = Stream(1, 2, 3, 4).map(_ + 10).filter(_ % 2 == 0).toList
190191

191192
// Apply map to the first element:

src/main/scala/fpinscalalib/customlib/functionaldatastructures/ListHelper.scala

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ object List { // `List` companion object. Contains functions for creating and wo
2424
ints match { // A function that uses pattern matching to add up a list of integers
2525
case Nil => 0 // The sum of the empty list is 0.
2626
case Cons(x, xs) =>
27-
x + sum(xs) // The sum of a list starting with `x` is `x` plus the sum of the rest of the list.
27+
x + sum(
28+
xs
29+
) // The sum of a list starting with `x` is `x` plus the sum of the rest of the list.
2830
}
2931

3032
def product(ds: List[Double]): Double = ds match {

src/main/scala/fpinscalalib/customlib/functionalparallelism/ParHelper.scala

+6-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ object Par {
2121

2222
def unit[A](a: A): Par[A] =
2323
(es: ExecutorService) =>
24-
UnitFuture(a) // `unit` is represented as a function that returns a `UnitFuture`, which is a simple implementation of `Future` that just wraps a constant value. It doesn't use the `ExecutorService` at all. It's always done and can't be cancelled. Its `get` method simply returns the value that we gave it.
24+
UnitFuture(
25+
a
26+
) // `unit` is represented as a function that returns a `UnitFuture`, which is a simple implementation of `Future` that just wraps a constant value. It doesn't use the `ExecutorService` at all. It's always done and can't be cancelled. Its `get` method simply returns the value that we gave it.
2527

2628
private case class UnitFuture[A](get: A) extends Future[A] {
2729
def isDone = true
@@ -34,7 +36,9 @@ object Par {
3436
(es: ExecutorService) => {
3537
val af = a(es)
3638
val bf = b(es)
37-
UnitFuture(f(af.get, bf.get)) // This implementation of `map2` does _not_ respect timeouts. It simply passes the `ExecutorService` on to both `Par` values, waits for the results of the Futures `af` and `bf`, applies `f` to them, and wraps them in a `UnitFuture`. In order to respect timeouts, we'd need a new `Future` implementation that records the amount of time spent evaluating `af`, then subtracts that time from the available time allocated for evaluating `bf`.
39+
UnitFuture(
40+
f(af.get, bf.get)
41+
) // This implementation of `map2` does _not_ respect timeouts. It simply passes the `ExecutorService` on to both `Par` values, waits for the results of the Futures `af` and `bf`, applies `f` to them, and wraps them in a `UnitFuture`. In order to respect timeouts, we'd need a new `Future` implementation that records the amount of time spent evaluating `af`, then subtracts that time from the available time allocated for evaluating `bf`.
3842
}
3943

4044
def fork[A](a: => Par[A]): Par[A] = // This is the simplest and most natural implementation of `fork`, but there are some problems with it--for one, the outer `Callable` will block waiting for the "inner" task to complete. Since this blocking occupies a thread in our thread pool, or whatever resource backs the `ExecutorService`, this implies that we're losing out on some potential parallelism. Essentially, we're using two threads when one should suffice. This is a symptom of a more serious problem with the implementation, and we will discuss this later in the chapter.

0 commit comments

Comments
 (0)