More elegant scala code - scala

I am starting to learn scala. Wonder if anyone has a better way to re-write below code in a more functional way. I know there must be one.
val buf = ((addr>>24)&0xff) + "." + ((addr>>16)&0xff) + "." + ((addr>>8)&0xff) + "." + ((addr)&0xff)

This generates the Range(24, 16, 8, 0) with (24 to 0 by -8) and then applies the function addr >> _ & 0xff to each number using map. Lastly, the mapped Range of numbers is "joined" with . to create a string.
The map is more functional than using the + operator but the rest is just syntactic sugar and a library call to mkString.
val addr = 1024
val buf = (24 to 0 by -8).map(addr >> _ & 0xff).mkString(".")
buf: java.lang.String = 0.0.4.0

val buf = List(24,16,8,0).map(addr >> _).map(_ & 0xff).mkString(".")
Here's how I would do it, similar to Brian's answer but with a short list of values and two simple map() methods using Scala's famous '_' operator. Great question!

Some would find the for comprehension a little bit more readable:
(for (pos <- 24 to 0 by -8) yield addr >> pos & 0xff) mkString "."

The advantage is that input - can be ANY number of integers
// trick
implicit class When[F](fun: F) {
def when(cond: F => Boolean)(tail: F => F) = if (cond(fun)) tail(fun) else fun
}
// actual one-liner
12345678.toHexString.when(1 to 8 contains _.length % 8)
(s => "0" * (8 - s.length % 8) + s ).reverse.grouped(2).map
(Integer.parseInt(_, 16)).toList.reverse.mkString(".")
// 0.203.22.228
// a very big IPv7
BigInt("123456789012345678901").toString(16).when(1 to 8 contains _.length % 8)
(s => "0" * (8 - s.length % 8) + s ).reverse.grouped(2).map
(Integer.parseInt(_, 16)).toList.reverse.mkString(".")
// 0.0.0.96.27.228.249.24.242.99.198.83
EDIT
Explanation because of downvotes. implicit class When can be just a library class, it works in 2.10 and allows conditionally execute some of functions in a calls chain. I did not measure performance, and don't care, because an example itself is meant to be an illustration of what is possible, elegant or not.

Related

Scala stream to find primes in specific interval

Problem:
I need to create a Scala program which uses Stream class and finds n-th prime number from interval [i, j] (whereas 1 <= i < j).
More information:
I am completely new in Scala but I've looked for various examples on how to find primes in Scala using Stream. None of them helped me to achieve my goal.
I can't seem to understand how to make stream a finite list in interval [i, j] and how to take n-th prime number from that interval.
My code so far:
def primeStream(args: Array[String], s: Stream[Int]): Stream[Int] =
Stream.cons(s.head, primeStream(args,s.tail filter {_ % s.head != 0 }))
if (args(0).toInt < 1) {
println("Entered parameter i does not meet requirements 1<=i<j (1<=" + args(0) + "<" + args(1) + ")")
sys.exit(1)
} else if (args(1).toInt < args(0).toInt) {
println("Entered parameter j does not meet requirements 1<=i<j (1<=" + args(0) + "<" + args(1) + ")")
sys.exit(1)
}
val primes = primeStream(args,Stream.from(args(0).toInt)) // start from i element
primes take args(1).toInt foreach println //Take j elements
Any help would be appreciated!
SOLUTION:
def primeStream(s: Stream[Int]): Stream[Int] =
Stream.cons(s.head, primeStream(s.tail filter {_ % s.head != 0 }))
if (args(0).toInt < 1) {
println("Entered parameter i does not meet requirements 1<=i<j (1<=" + args(0) + "<" + args(1) + ")")
sys.exit(1)
} else if (args(1).toInt < args(0).toInt) {
println("Entered parameter j does not meet requirements 1<=i<j (1<=" + args(0) + "<" + args(1) + ")")
sys.exit(1)
} else if (args(0).toInt == 1) {
println("1 is not a prime by definition!")
sys.exit(1) // if args(0) is 1 then function hangs up - didn't come up with a better solution for this
}
val primes = primeStream(Stream.from(args(0).toInt)) // get primes starting from given parameter
println(primes.takeWhile( _ < args(1).toInt).take(args(2).toInt).last) // get n-th prime and print it out
You just need to have your stream generate values while a certain condition holds:
primes takeWhile(_ < j) take n foreach println
and, of course, you need to get the primeStream function right.
For the algorithmic part, you'd better search on stackoverflow:
Calculating prime numbers in Scala: how does this code work?
Is this a learning exercise, or do you need this in production? For the latter, I would suggest using spire.math.prime.stream from the spire library. It is using a Segmented Stream of Eratosthenes implementation which is probably better than what you will come up with yourself in a short time. It also uses arbitrary precision integers, so it works for numbers larger than 2^64.
scala> import spire.math._
import spire.math._
scala> prime.stream.drop(10).take(10).toArray
res16: Array[spire.math.SafeLong] = Array(31, 37, 41, 43, 47, 53, 59, 61, 67, 71)

Scala - Convert Seq[Int] to a single number consisting numbers in the Seq

In Scala, how can I convert a Seq[Int] to a single number consisting of the numbers in the Seq.
e.g.
Seq(2,3,45,10) to 234510 as a number
A straightforward method is
Seq(2,3,45,10).mkString.toLong
Is there a better and perhaps more performant/functional way?
Seq(2,3,45,10).reduce((x,y) => x * math.pow(10,math.floor(math.log10(y)) + 1).toInt + y)
or
Seq(2,3,45,10).map(BigDecimal(_)).reduce((x,y) => x * BigDecimal(10).pow(y.precision) + y)
But actually i think _.mkString.toLong is the most performant, only problem it will work only for decimal representaion. For arbitrary radix you could do
BigInt(Seq(0x2,0x3,0x45,0x10).map(BigInt(_).toString(16)).mkString, 16)
def toNumber(seq:Seq[Int]):Int = {
def append(scale:Int)(n:Int, m:Int):Int = if(m>=scale) append(scale*10)(n, m) else n*scale + m
seq.foldLeft(0)(append(1))
}

Equivalent of Haskell do-notation or F# Computation Expressions in Scala?

F# Computation Expressions allow to hide the complexity of monadic syntax behind a thick layer of syntactic sugar. Is there something similar available in Scala?
I think it's for comprehensions ...
Example:
val f = for {
a <- Future(10 / 2) // 10 / 2 = 5
b <- Future(a + 1) // 5 + 1 = 6
c <- Future(a - 1) // 5 - 1 = 4
} yield b * c // 6 * 4 = 24
val result = f.get
But it doesn't really feel right. Is there a better syntax?
for exemple in haskell you would have
main = do fromHandle <- getAndOpenFile "Copy from: " ReadMode
toHandle <- getAndOpenFile "Copy to: " WriteMode
contents <- hGetContents fromHandle
hPutStr toHandle contents
hClose toHandle
putStr "Done."
this unlike scala doesn't look like a foreach loops.
Scala syntax seem to have too strong coupling with List comprehension which is a distinct concept. Which prevent me from writing internal DSL (monad) that doesn't look strange.
The missing piece is probably the use of = is scala's for-comprehensions:
val f = for {
a <- Future(10 / 2) // 10 / 2 = 5
b <- Future(a + 1) // 5 + 1 = 6
c <- Future(a - 1) // 5 - 1 = 4
d = b * c // 6 * 4 = 24
} yield d
val result = f.get
With judicious mixing of both <- and =, you should have all the flexibility you need.
It seem like there is no such syntax available in scala and we would need to implement it ourself using the compiler plugin architecture.

Why do I have to explicitly state Tuple2(a, b) to be able to use Map add in a foldLeft?

I wish to create a Map keyed by name containing the count of things with that name. I have a list of the things with name, which may contain more than one item with the same name. Coded like this I get an error "type mismatch; found : String required: (String, Int)":
//variation 0, produces error
(Map[String, Int]() /: entries)((r, c) => { r + (c.name, if (r.contains(c.name)) (c.name) + 1 else 1) })
This confuses me as I though (a, b) was a Tuple2 and therefore suitable for use with Map add. Either of the following variations works as expected:
//variation 1, works
(Map[String, Int]() /: entries)((r, c) => { r + Tuple2(c.name, if (r.contains(c.name)) (c.name) + 1 else 1) })
//variation 2, works
(Map[String, Int]() /: entries)((r, c) => {
val e = (c.name, if (r.contains(c.name)) (c.name) + 1 else 1) })
r + e
I'm unclear on why there is a problem with my first version; can anyone advise. I am using Scala-IDE 2.0.0 beta 2 to edit the source; the error is from the Eclipse Problems window.
When passing a single tuple argument to a method used with operator notation, like your + method, you should use double parentheses:
(Map[String, Int]() /: entries)((r, c) => { r + ((c.name, r.get(c.name).map(_ + 1).getOrElse(1) )) })
I've also changed the computation of the Int, which looks funny in your example…
Because + is used to concatenate strings stuff with strings. In this case, parenthesis are not being taken to mean a tuple, but to mean a parameter.
Scala has used + for other stuff, which resulted in all sorts of problems, just like the one you mention.
Replace + with updated, or use -> instead of ,.
r + (c.name, if (r.contains(c.name)) (c.name) + 1 else 1)
is parsed as
r.+(c.name, if (r.contains(c.name)) (c.name) + 1 else 1)
So the compiler looks for a + method with 2 arguments on Map and doesn't find it. The form I prefer over double parentheses (as Jean-Philippe Pellet suggests) is
r + (c.name -> if (r.contains(c.name)) (c.name) + 1 else 1)
UPDATE:
if Pellet is correct, it's better to write
r + (c.name -> r.getOrElse(c.name, 0) + 1)
(and of course James Iry's solution expresses the same intent even better).

Suggest a cleaner functional way

Here is some imperative code:
var sum = 0
val spacing = 6
var x = spacing
for(i <- 1 to 10) {
sum += x * x
x += spacing
}
Here are two of my attempts to "functionalize" the above code:
// Attempt 1
(1 to 10).foldLeft((0, 6)) {
case((sum, x), _) => (sum + x * x, x + spacing)
}
// Attempt 2
Stream.iterate ((0, 6)) { case (sum, x) => (sum + x * x, x + spacing) }.take(11).last
I think there might be a cleaner and better functional way to do this. What would be that?
PS: Please note that the above is just an example code intended to illustrate the problem; it is not from the real application code.
Replacing 10 by N, you have spacing * spacing * N * (N + 1) * (2 * N + 1) / 6
This is by noting that you're summing (spacing * i)^2 for the range 1..N. This sum factorizes as spacing^2 * (1^2 + 2^2 + ... + N^2), and the latter sum is well-known to be N * (N + 1) * (2 * N + 1) / 6 (see Square Pyramidal Number)
I actually like idea of lazy sequences in this case. You can split your algorithm in 2 logical steps.
At first you want to work on all natural numbers (ok.. not all, but up to max int), so you define them like this:
val naturals = 0 to Int.MaxValue
Then you need to define knowledge about how numbers, that you want to sum, can be calculated:
val myDoubles = (naturals by 6 tail).view map (x => x * x)
And putting this all together:
val naturals = 0 to Int.MaxValue
val myDoubles = (naturals by 6 tail).view map (x => x * x)
val mySum = myDoubles take 10 sum
I think it's the way mathematician will approach this problem. And because all collections are lazily evaluated - you will not get out of memory.
Edit
If you want to develop idea of mathematical notation further, you can actually define this implicit conversion:
implicit def math[T, R](f: T => R) = new {
def ∀(range: Traversable[T]) = range.view map f
}
and then define myDoubles like this:
val myDoubles = ((x: Int) => x * x) ∀ (naturals by 6 tail)
My personal favourite would have to be:
val x = (6 to 60 by 6) map {x => x*x} sum
Or given spacing as an input variable:
val x = (spacing to 10*spacing by spacing) map {x => x*x} sum
or
val x = (1 to 10) map (spacing*) map {x => x*x} sum
There are two different directions to go. If you want to express yourself, assuming that you can't use the built-in range function (because you actually want something more complicated):
Iterator.iterate(spacing)(x => x+spacing).take(10).map(x => x*x).foldLeft(0)(_ + _)
This is a very general pattern: specify what you start with and how to get the next given the previous; then take the number of items you need; then transform them somehow; then combine them into a single answer. There are shortcuts for almost all of these in simple cases (e.g. the last fold is sum) but this is a way to do it generally.
But I also wonder--what is wrong with the mutable imperative approach for maximal speed? It's really quite clear, and Scala lets you mix the two styles on purpose:
var x = spacing
val last = spacing*10
val sum = 0
while (x <= last) {
sum += x*x
x += spacing
}
(Note that the for is slower than while since the Scala compiler transforms for loops to a construct of maximum generality, not maximum speed.)
Here's a straightforward translation of the loop you wrote to a tail-recursive function, in an SML-like syntax.
val spacing = 6
fun loop (sum: int, x: int, i: int): int =
if i > 0 then loop (sum+x*x, x+spacing, i-1)
else sum
val sum = loop (0, spacing, 10)
Is this what you were looking for? (What do you mean by a "cleaner" and "better" way?)
What about this?
def toSquare(i: Int) = i * i
val spacing = 6
val spaceMultiples = (1 to 10) map (spacing *)
val squares = spaceMultiples map toSquare
println(squares.sum)
You have to split your code in small parts. This can improve readability a lot.
Here is a one-liner:
(0 to 10).reduceLeft((u,v)=>u + spacing*spacing*v*v)
Note that you need to start with 0 in order to get the correct result (else the first value 6 would be added only, but not squared).
Another option is to generate the squares first:
(1 to 2*10 by 2).scanLeft(0)(_+_).sum*spacing*spacing