Custom "let" expression in Scala - scala

I'd love to have let construct similar to the one in Haskell in Scala. I tried a few ways, but none seems to be good. Here's some code:
object CustomLet extends App {
val data = for (i <- 1 to 1024; j <- 1 to 512) yield (i % j) * i * (i + 1) - 1
def heavyCalc() = { println("heavyCalc called"); data.sum }
def doSomethingWithRes(res: Int) = {
println(s"${res * res}")
1
}
def cond(value: Int): Boolean = value > 256
// not really usable, even though it's an expression (2x heavyCalc calls)
def withoutLet() = if (cond(heavyCalc())) doSomethingWithRes(heavyCalc()) else 0
// not an expression
def letWithVal(): Int = {
val res = heavyCalc()
if (cond(res)) doSomethingWithRes(res)
else 0
}
// a lot of code to simulate "let", at least it is an expression
def letWithMatch(): Int = heavyCalc() match {
case res => if (cond(res)) doSomethingWithRes(res) else 0
}
// not perfect solution from
// http://stackoverflow.com/questions/3241101/with-statement-equivalent-for-scala/3241249#3241249
def let[A, B](param: A)(body: A => B): B = body(param)
// not bad, but I'm not sure if it could handle more bindings at once
def letWithApp(): Int = let(heavyCalc()) {res => if (cond(res)) doSomethingWithRes(res) else 0}
List[(String, () => Int)](
("withoutLet", withoutLet),
("letWithVal", letWithVal),
("letWithMatch", letWithMatch),
("letWithApp", letWithApp)
).foreach(
item => item match {
case (title, func) => {
println(s"executing $title")
val ret = func()
println(s"$title finished with $ret")
println()
}
}
)
}
This is the ideal look of it (with only one binding, more could be separated by ,; not sure about the in keyword):
// desired look
def letTest(): Int =
let res = heavyCalc() in
if (cond(res)) doSomethingWithRes(res) else 0
I'm not sure if it's possible, but I have no experience with most of advanced Scala stuff like macros, so I can't really tell.
EDIT1: To be clear, the main things I'm expecting from it are: being expression and relatively simple syntax (like the one outlined above).

You could use a forward pipe:
object ForwardPipeContainer {
implicit class ForwardPipe[A](val value: A) extends AnyVal {
def |>[B](f: A => B): B = f(value)
}
}
to be used like this:
import ForwardPipeContainer._
def f(i: Int) = i * i
println( f(3) |> (x => x * x) )
You can put multiple arguments in a tuple:
println( (f(2), f(3)) |> (x => x._1 * x._2) )
which looks better if combined with partial function synatx:
println( (f(2), f(3)) |> { case (x, y) => x * y } )
This answer is a variation of What is a good way of reusing function result in Scala, and both are based on Cache an intermediate variable in an one-liner where I got the initial idea from.

def letTest(): Int =
let res = heavyCalc() in
if (cond(res)) doSomethingWithRes(res) else 0
I would write this:
def letTest(): Int = {
val res = heavyCalc()
if (cond(res)) doSomethingWithRes(res) else 0
}
Ignoring laziness, let is just a construct that introduces a lexical scope, binds some terms to some names then returns an expression. So in Scala you would do
{ // new lexical scope
// bind terms section
val a = f()
def b = a + g() // may be I don't want g to be evaluated unless b is needed
val c = h()
// result expression
if (c) b else a
}
Macros should be able to enforce this syntactic layout if you want to ensure that there is nothing else going on in the block. There is actually a SIP (Scala Improvement Process) proposal called Spores that would enforce some of the same constraints (and an additional one: that you don't capture a reference of an enclosing object unknowingly).
Note that blocks in Scala are expressions that evaluate to the last expression in the block. So let me take a random let example from Haskell:
aaa = let y = 1+2
z = 4+6
in let f = 3
e = 3
in e+f
This translates to:
val aaa = {
val y = 1 + 2
val z = 4 + 6
val u = {
val f = 3
val e = 3
e + f
}
u
}
As you can see the block statement can be used as an expression.

Related

Monadic approach to estimating PI in scala

I'm trying to understand how to leverage monads in scala to solve simple problems as way of building up my familiarity. One simple problem is estimating PI using a functional random number generator. I'm including the code below for a simple stream based approach.
I'm looking for help in translating this to a monadic approach. For example, is there an idiomatic way convert this code to using the state (and other monads) in a stack safe way?
trait RNG {
def nextInt: (Int, RNG)
def nextDouble: (Double, RNG)
}
case class Point(x: Double, y: Double) {
val isInCircle = (x * x + y * y) < 1.0
}
object RNG {
def nonNegativeInt(rng: RNG): (Int, RNG) = {
val (ni, rng2) = rng.nextInt
if (ni > 0) (ni, rng2)
else if (ni == Int.MinValue) (0, rng2)
else (ni + Int.MaxValue, rng2)
}
def double(rng: RNG): (Double, RNG) = {
val (ni, rng2) = nonNegativeInt(rng)
(ni.toDouble / Int.MaxValue, rng2)
}
case class Simple(seed: Long) extends RNG {
def nextInt: (Int, RNG) = {
val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL
val nextRNG = Simple(newSeed)
val n = (newSeed >>> 16).toInt
(n, nextRNG)
}
def nextDouble: (Double, RNG) = {
val (n, nextRNG) = nextInt
double(nextRNG)
}
}
}
object PI {
import RNG._
def doubleStream(rng: Simple):Stream[Double] = rng.nextDouble match {
case (d:Double, next:Simple) => d #:: doubleStream(next)
}
def estimate(rng: Simple, iter: Int): Double = {
val doubles = doubleStream(rng).take(iter)
val inside = (doubles zip doubles.drop(3))
.map { case (a, b) => Point(a, b) }
.filter(p => p.isInCircle)
.size * 1.0
(inside / iter) * 4.0
}
}
// > PI.estimate(RNG.Simple(10), 100000)
// res1: Double = 3.14944
I suspect I'm looking for something like replicateM from the Applicative monad in cats but I'm not sure how to line up the types or how to do it in a way that doesn't accumulate intermediate results in memory. Or, is there a way to do it with a for comprehension that can iteratively build up Points?
Id you want to iterate using monad in a stack safe way, then there is a tailRecM method implemented in Monad type class:
// assuming random generated [-1.0,1.0]
def calculatePi[F[_]](iterations: Int)
(random: => F[Double])
(implicit F: Monad[F]): F[Double] = {
case class Iterations(total: Int, inCircle: Int)
def step(data: Iterations): F[Either[Iterations, Double]] = for {
x <- random
y <- random
isInCircle = (x * x + y * y) < 1.0
newTotal = data.total + 1
newInCircle = data.inCircle + (if (isInCircle) 1 else 0)
} yield {
if (newTotal >= iterations) Right(newInCircle.toDouble / newTotal.toDouble * 4.0)
else Left(Iterations(newTotal, newInCircle))
}
// iterates until Right value is returned
F.tailRecM(Iterations(0, 0))(step)
}
calculatePi(10000)(Future { Random.nextDouble }).onComplete(println)
It uses by-name param because you could try to pass there something like Future (even though the Future is not lawful), which are eager, so you would end up with evaluating the same thing time and time again. With by name param at least you have the chance of passing there a recipe for side-effecting random. Of course, if we use Option, List as a monad holding our "random" number, we should also expect funny results.
The correct solution would be using something that ensures that this F[A] is lazily evaluated, and any side effect inside is evaluated each time you need a value from inside. For that you basically have to use some of Effects type classes, like e.g. Sync from Cats Effects.
def calculatePi[F[_]](iterations: Int)
(random: F[Double])
(implicit F: Sync[F]): F[Double] = {
...
}
calculatePi(10000)(Coeval( Random.nextDouble )).value
calculatePi(10000)(Task( Random.nextDouble )).runAsync
Alternatively, if you don't care about purity that much, you could pass side effecting function or object instead of F[Int] for generating random numbers.
// simplified, hardcoded F=Coeval
def calculatePi(iterations: Int)
(random: () => Double): Double = {
case class Iterations(total: Int, inCircle: Int)
def step(data: Iterations) = Coeval {
val x = random()
val y = random()
val isInCircle = (x * x + y * y) < 1.0
val newTotal = data.total + 1
val newInCircle = data.inCircle + (if (isInCircle) 1 else 0)
if (newTotal >= iterations) Right(newInCircle.toDouble / newTotal.toDouble * 4.0)
else Left(Iterations(newTotal, newInCircle))
}
Monad[Coeval].tailRecM(Iterations(0, 0))(step).value
}
Here is another approach that my friend Charles Miller came up with. It's a bit more direct since it uses RNG directly but it follows the same approach provided by #Mateusz Kubuszok above that leverages Monad.
The key difference is that it leverages the State monad so we can thread the RNG state through the computation and generate the random numbers using the "pure" random number generator.
import cats._
import cats.data._
import cats.implicits._
object PICharles {
type RNG[A] = State[Long, A]
object RNG {
def nextLong: RNG[Long] =
State.modify[Long](
seed ⇒ (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL
) >> State.get
def nextInt: RNG[Int] = nextLong.map(l ⇒ (l >>> 16).toInt)
def nextNatural: RNG[Int] = nextInt.map { i ⇒
if (i > 0) i
else if (i == Int.MinValue) 0
else i + Int.MaxValue
}
def nextDouble: RNG[Double] = nextNatural.map(_.toDouble / Int.MaxValue)
def runRng[A](seed: Long)(rng: RNG[A]): A = rng.runA(seed).value
def unsafeRunRng[A]: RNG[A] ⇒ A = runRng(System.currentTimeMillis)
}
object PI {
case class Step(count: Int, inCircle: Int)
def calculatePi(iterations: Int): RNG[Double] = {
def step(s: Step): RNG[Either[Step, Double]] =
for {
x ← RNG.nextDouble
y ← RNG.nextDouble
isInCircle = (x * x + y * y) < 1.0
newInCircle = s.inCircle + (if (isInCircle) 1 else 0)
} yield {
if (s.count >= iterations)
Right(s.inCircle.toDouble / s.count.toDouble * 4.0)
else
Left(Step(s.count + 1, newInCircle))
}
Monad[RNG].tailRecM(Step(0, 0))(step(_))
}
def unsafeCalculatePi(iterations: Int) =
RNG.unsafeRunRng(calculatePi(iterations))
}
}
Thanks Charles & Mateusz for your help!

how to return value from a if block in scala

I want to return an integer type from an if block like in this sample code:
def a {
val res = if (1 == 1) {
val x = 1
b(x)
}
}
def b(x:Int) = {
20
}
Here the type of res is val res: AnyVal
How can I change it to Int?
If you don't have a default value to return, then you could return an Option[Int] instead, and combine this with getOrElse:
def a(n: Int): Option[Int] = {
if (n < 100) {
Some(n * 2)
} else {
None
}
}
a(10).getOrElse("Something else")
Another possibility is to use partial functions, because in your case your first function does not cover all cases, and you want to have a fallback:
val a: PartialFunction[Int, Int] = {
case n if n < 100 =>
n * 2
}
val b: PartialFunction[Int, String] = {
case _ =>
"Something else"
}
Then you can use applyOrElse:
// If function a is not defined for the input, then call function b
val result = a.applyOrElse(10, b)
or combine both partial functions into another function, and call that one:
// Combine a and b
val cf = a.orElse(b)
// Call
val result = cf(10)
You have to add else alternative, for example:
def a {
val res = if (1 == 1) {
val x = 1
b(x)
} else 0
}
This happens because for absent else case compiler uses Unit. And nearest common type for Int and Unit is AnyVal.
The reason you didn't get a determined int is that: your if block miss some code path. So if you change to:
val res = if (i == 1) {
val x = 1
b(x)
} else {
0 // some default value
}
That will be fine.
To have an immutable value val res well-defined with an if-else expression, both parts of the expression need be declared, as aforementioned. Even in the case of a mutable variable
var res: Int = _
the compiler instantiates it to a default 0. Thereafter it is valid for instance to
if (1 == 1) res = 20
without having to define the else part.

What is the type for scala.util.Random.shuffle?

Background
I started out with a Shuffler class that does two things:
Shuffles n:Int indexes
Puts them into n_tranches:Int
I am trying to refactor this code such that almost the entire implementation is in Trancheur, which puts the indexes into n_tranches.
For example, I may want to put 50 cards into 6 stacks, which I call tranches.
Original Code
class Shuffler( n:Int, n_tranches:Int )
{
val v = scala.util.Random.shuffle( (0 to n-1).toVector )
// returns tranche[0,n_tranches-1] which we live in
def tranche( i:Int ) = idxs(i).map( v ).sorted.toVector
private val idxs = cut( 0 to (n-1), n_tranches ).toVector
private def cut[A](xs: Seq[A], n: Int) = {
val (quot, rem) = (xs.size / n, xs.size % n)
val (smaller, bigger) = xs.splitAt(xs.size - rem * (quot + 1))
smaller.grouped(quot) ++ bigger.grouped(quot + 1)
}
}
New Code
class Shuffler( n:Int, n_tranches:Int )
extends Trancheur( n, n_tranches, scala.util.Random.shuffle )
{
}
class Trancheur( n:Int, n_tranches:Int, shuffler ) // WHAT SHOULD I PUT HERE?!?!?!?
{
val v = shuffler( (0 to n-1).toVector )
// returns tranche[0,n_tranches-1] which we live in
def tranche( i:Int ) = idxs(i).map( v ).sorted.toVector
private val idxs = cut( 0 to (n-1), n_tranches ).toVector
private def cut[A](xs: Seq[A], n: Int) = {
val (quot, rem) = (xs.size / n, xs.size % n)
val (smaller, bigger) = xs.splitAt(xs.size - rem * (quot + 1))
smaller.grouped(quot) ++ bigger.grouped(quot + 1)
}
}
Problem
I want Shuffler to call Trancheur with the functor scala.util.Random.shuffle. I think the call is fine.
But as a default, I want the Trancheur to have an identity functor which does nothing: it just returns the same results as before. I am having trouble with the constructor signature and with what to define as the identity functor.
NOTE: I apologize in advance if I have used the wrong term in calling scala.util.Random.shuffle a functor - that's what we call it in C++. Not sure if Functor means something else in Scala.
shuffle is a function. So shuffler (the parameter) should expect a function. For your case Seq[Int] => Seq[Int] should be sufficient. Scala also provides a predefined identity function.
This should do it:
class Trancheur( n:Int, n_tranches:Int, shuffler: Seq[Int] => Seq[Int] = identity)

Value assignment inside for-loop in Scala

Is there any difference between this code:
for(term <- term_array) {
val list = hashmap.get(term)
...
}
and:
for(term <- term_array; val list = hashmap.get(term)) {
...
}
Inside the loop I'm changing the hashmap with something like this
hashmap.put(term, string :: list)
While checking for the head of list it seems to be outdated somehow when using the second code snippet.
The difference between the two is, that the first one is a definition which is created by pattern matching and the second one is a value inside a function literal. See Programming in Scala, Section 23.1 For Expressions:
for {
p <- persons // a generator
n = p.name // a definition
if (n startsWith "To") // a filter
} yield n
You see the real difference when you compile sources with scalac -Xprint:typer <filename>.scala:
object X {
val x1 = for (i <- (1 to 5); x = i*2) yield x
val x2 = for (i <- (1 to 5)) yield { val x = i*2; x }
}
After code transforming by the compiler you will get something like this:
private[this] val x1: scala.collection.immutable.IndexedSeq[Int] =
scala.this.Predef.intWrapper(1).to(5).map[(Int, Int), scala.collection.immutable.IndexedSeq[(Int, Int)]](((i: Int) => {
val x: Int = i.*(2);
scala.Tuple2.apply[Int, Int](i, x)
}))(immutable.this.IndexedSeq.canBuildFrom[(Int, Int)]).map[Int, scala.collection.immutable.IndexedSeq[Int]]((
(x$1: (Int, Int)) => (x$1: (Int, Int) #unchecked) match {
case (_1: Int, _2: Int)(Int, Int)((i # _), (x # _)) => x
}))(immutable.this.IndexedSeq.canBuildFrom[Int]);
private[this] val x2: scala.collection.immutable.IndexedSeq[Int] =
scala.this.Predef.intWrapper(1).to(5).map[Int, scala.collection.immutable.IndexedSeq[Int]](((i: Int) => {
val x: Int = i.*(2);
x
}))(immutable.this.IndexedSeq.canBuildFrom[Int]);
This can be simplified to:
val x1 = (1 to 5).map {i =>
val x: Int = i * 2
(i, x)
}.map {
case (i, x) => x
}
val x2 = (1 to 5).map {i =>
val x = i * 2
x
}
Instantiating variables inside for loops makes sense if you want to use that variable the for statement, like:
for (i <- is; a = something; if (a)) {
...
}
And the reason why your list is outdated, is that this translates to a foreach call, such as:
term_array.foreach {
term => val list= hashmap.get(term)
} foreach {
...
}
So when you reach ..., your hashmap has already been changed. The other example translates to:
term_array.foreach {
term => val list= hashmap.get(term)
...
}

Why do I get an infinite loop when using implicit conversions?

Context
object Fibonacci {
final val Threshold = 30
def fibonacci(n: Int)(implicit implementation: Fibonacci): Int = implementation match {
case f: functional.type if n > Threshold => fibonacci(n)(imperativeWithLoop)
case f: imperativeWithRecursion.type => f(n)
case f: imperativeWithLoop.type => f(n)
case f: functional.type => f(n)
}
sealed abstract class Fibonacci extends (Int => Int)
object functional extends Fibonacci {
def apply(n: Int): Int =
if (n <= 1) n else apply(n - 1) + apply(n - 2)
}
object imperativeWithRecursion extends Fibonacci {
def apply(n: Int) = {
#scala.annotation.tailrec
def recursion(i: Int, f1: Int, f2: Int): Int =
if (i == n) f2 else recursion(i + 1, f2, f1 + f2)
if (n <= 1) n else recursion(1, 0, 1)
}
}
implicit object imperativeWithLoop extends Fibonacci {
def apply(n: Int) = {
def loop = {
var res = 0
var f1 = 0
var f2 = 1
for (i <- 2 to n) {
res = f1 + f2
f1 = f2
f2 = res
}
res
}
if (n <= 1) n else loop
}
}
}
Example
object Main extends App { // or REPL
import Fibonacci._
println(fibonacci(6)(imperativeWithRecursion)) // 8
println(fibonacci(6)(imperativeWithLoop)) // 8
println(fibonacci(6)(functional)) // 8
println(fibonacci(6)) // 8
println(fibonacci(40)(functional)) // 102334155
}
Explanation
I was playing with Scala and ended up with this code. It compiles and runs, but...
Questions:
1) Is there any difference (readbility, performance, known bugs, anything) between
case f: functional.type => f(n)
and
case `functional` => functional(n)
This is supposed to be more of a discussion, so I'm not only interested in facts. Any opinion is welcomed.
2) Look at the first line of the fibonacci method. Here it is:
case f: functional.type if n > Threshold => fibonacci(n)(imperativeWithLoop)
If I leave the 2nd parameter list (imperativeWithLoop) out, the code compiles but enters an infinite loop when I run it. Does anyone know why? The default implementation imperativeWithLoop is known to the compiler (no errors are produced). So why doesn't it get implicitly invoked? (I assume it doesn't)
Regarding the first question, there are small differences, but none that matter here. But it would be better if you uppercased the objects, in which case you could write this:
case Functional => Functional(n)
Regarding the second question, if you leave out imperativeWithLoop, it will select the implicit Fibonacci closest in scope -- implementation (which has already be found to be equal to funcional). So it will call itself with the exact same parameters as it had called before, and, therefore, enter an infinite loop.