Vladimir Pavkin
assert(!list.isEmpty, "List must be empty")
try {
str.toInt
} catch {
case _:Throwable => 0
}
if(container == null)
if(container.isInstanceOf[ContainerA])
it should "throw NoSuchElementException for empty stack" in {
val emptyStack = new Stack[Int]
a [NoSuchElementException] should be thrownBy {
emptyStack.pop()
}
}
it should "not throw for empty stack" in {
val stackWrapper = StackWrapper(new Stack[Int])
noException should be thrownBy stackWrapper.pop()
}
scalacOptions ++= Seq(
"-Xlint",
"-deprecation",
"-Xfatal-warnings"
)
// Wrong number of args to format()
logger.error(
"Failed to open %s. Error: %d"
.format(file)
)
def becomeAMan(douchebag: Person): Man =
if(douchebag.weight > 70)
new Man(douchebag.renameTo("Arny"))
else
null
becomeAMan(vpavkin).name //vpavkin.weight < 70
var man = becomeAMan(person)
if(man != null)
name
else
//...
If you control the source code,
don't ever usenull
as a return result.
It's like farting in an elevator.
Some random guy at a random Scala forum
ManOrNull
Option
Option
sealed trait Option[T]
case class Some[T](x: T) extends Option[T]
case object None extends Option[Nothing]
def becomeAMan(douchebag: Person): Option[Man] =
if(douchebag.weight > 70)
Some(new Man(douchebag.renameTo("Arny")))
else
None
None
result at compile time.
def firstWorkout(douchebag: Person): Option[WorkoutResult] =
becomeAMan(douchebag).map(man => man.workout())
def willHaveASexyGirlfriend(douchebag: Person): Boolean =
becomeAMan(douchebag) match {
case Some(man) => true
case None => false
}
def workout(man: Man): WorkoutResult =
if(!man.hasShaker)
throw new Error("Not enough protein!!!!111")
else
// do some squats or stare in the mirror for 1h
try/catch
or fails at runtime!scala.Either
scalaz.\/
def workout(man:Man): ProteinFail \/ WorkoutResult =
if(!man.hasShaker)
ProteinFail("Not enough protein!!!!111").left
else
someWorkoutResult.right
scalaz.\/
sealed trait \/[E, R]
case class -\/[E](a: E) extends (E \/ Nothing)
case class \/-[R](a: R) extends (Nothing \/ R)
workout(man).map(result => submitToFacebook(result))
// type is
// ProteinFail \/ Future[List[FacebookLike]]
def tellAboutTheWorkout(w: ProteinFail \/ WorkoutResult): String =
w match {
case -\/(fail) => "F**k your proteins, I can do without it"
case \/-(result) =>
s"Dude, eat proteins, or you won't do like me: $result"
}
isInstanceOf[Man]
isInstanceOf[T]
trait GymClient
case class Man(name: String) extends GymClient
case class Douchebag(name: String) extends GymClient
def gymPrice(h: GymClient): Int =
if(h.isInstanceOf[Man]){
val man = h.asInstanceOf[Man]
if(man.name == "Arny") 0 else 100
} else {
200
}
// Add another client type
case class PrettyGirl(name:String) extends GymClient
isInstanceOf[T]
trait GymClient
case class Man(name: String) extends GymClient
case class Douchebag(name: String) extends GymClient
case class PrettyGirl(name:String) extends GymClient
def gymPrice(h: GymClient): Int =
if(h.isInstanceOf[Man]){
val man = h.asInstanceOf[Man]
if(man.name == "Arny") 0 else 100
} else {
200
}
sealed
ADTsealed
= can't be extended in other files
sealed trait GymClient
case class Man(name: String) extends GymClient
case class Douchebag(name: String) extends GymClient
def gymPrice(h: GymClient): Int = h match {
case Man("Arny") => 0
case _: Man => 100
case _: Douchebag => 200
}
// compiler checks, that match is exhaustive
sealed trait GymClient
case class Man(name: String) extends GymClient
case class Douchebag(name: String) extends GymClient
case class PrettyGirl(name:String) extends GymClient
def gymPrice(h: GymClient): Int = h match {
case Man("Arny") => 0
case _: Man => 100
case _: Douchebag => 200
}
// COMPILE ERROR! Match fails for PrettyGirl.
case class Beefcake(id: String,
name: String)
case class GymPass(id: String,
ownerId: String)
trait JustTag
def onlyTagged(value: String @@ JustTag): String
= s"Tagged string: $value"
// can use as plain String
onlyTagged("plain string") // Compiler error
val tagged = tag[JustTag]("tagged")
onlyTagged(tagged) // OK
case class Beefcake(id: String @@ Beefcake,
name: String)
case class GymPass(id: String @@ GymPass,
ownerId: String @@ Beefcake)
sealed trait PullUpState
final class Up extends PullUpState
final class Down extends PullUpState
class Beefcake[S <: PullUpState] private () {
def pullUp[T >: S <: Down]() =
this.asInstanceOf[Beefcake[Up]]
def pullDown[T >: S <: Up]() =
this.asInstanceOf[Beefcake[Down]]
}
object Beefcake {
def create() = new Beefcake[Down]
}
val fresh = Beefcake.create() //Beefcake[Down]
val heDidIt = fresh.pullUp() //Beefcake[Up]
val notAgainPlease = heDidIt.pullUp()
// CompileError:
// inferred type arguments [Up] do not conform
// to method pullUp's type parameter bounds
class Gym(val name: String)
class Beefcake(val gym: Gym){
def talkTo(other: Beefcake): Unit =
println("Wazzup, Hetch!")
}
val normalGym = new Gym("nicefitness")
val swagGym = new Gym("kimberly")
val normalGuy = new Beefcake(normalGym)
val swagGuy = new Beefcake(swagGym)
normalGuy.talkTo(swagGuy) // we don't want that
class Beefcake(val gym: Gym){
def talkTo(other: Beefcake): Unit = {
// throws IllegalArgumentException if false
require(this.gym == other.gym)
println("Wazzup, Hetch!")
}
}
class A {
class B
}
val a1 = new A
val a2 = new A
var b = new a1.B // type is a1.B
b = new a2.B // Compile Error: types don't match
class Gym(val name: String){
class Beefcake(val gym: Gym){
def talkTo(other: Beefcake): Unit =
println("Wazzup, Hetch!")
}
}
val normalGym = new Gym("nicefitness")
val swagGym = new Gym("kimberly")
val normalGuy = new normalGym.Beefcake(normalGym)
val swagGuy = new swagGym.Beefcake(swagGym)
normalGuy.talkTo(swagGuy) // doesn't compile, Yay!