DRY when passing similar functions to Scala map() - scala

def doubleList(noList:List[Int]) = {
val result = noList.map{ number =>
number*2
}
result
}
def halfList(noList:List[Int]) = {
val result = noList.map{ number =>
number/2
}
result
}
def mapFunctionDRY(noList:List[Int])(codeBlock: () => Int) = {
}
println(halfList(List(1,2,3)))
println(doubleList(List(1,2,4)))
I was playing around with scala and noticed violation of DRY (Dont Repeat Yourself) in the above two functions doubleList and halfList. I want the code common in both the function to be isolated and just pass the code block which is different. That way my code would not be violating DRY principle. I know that you could pass in code block as argument in scala. That is what I intend to do in mapFunctionDRY
I want mapFunctionDRY to be in this way
def mapFunctionDRY(noList:List[Int])(codeBlock: () => Int) = {
noList.map{ number =>
codeBlock()
}
}
And code in doubleList and halfList to be similar to this
def doubleList(noList:List[Int]) = { mapFunctionDRY(noList){ () => number*2 } }
But I would get a compilation error if I do such thing. How can I make the code pass in as the parameter in this case to avoid violation of DRY. Can this code be reduced further to keep it DRY?

You don't need to reinvent job that map does quite DRY:
def double(x: Int) = x * 2
def half(x: Int) = x / 2
val xs = List(1,2,3,4)
xs.map(double)
// List[Int] = List(2, 4, 6, 8)
xs.map(half)
// List[Int] = List(0, 1, 1, 2)

The compilation error occurs because you want to map each Int to another Int. codeBlock: () => Int is a function that takes no argument.
codeBlock: Int => Int should do what you want. Then you can define something like this:
def doubleList(noList:List[Int]) = { mapFunctionDRY(noList){ (number : Int) => number*2 } }
Haven't tested it though.
Edit: And like the others said. This function is not really useful because it's like map but weaker in the sense that it can only be applied to List[Int]

Why are you building a wrapper around map, which actually provides the dry-est solution to your problem? I would suggest a different strategy:
val mapDouble = (x: Int) => x * 2
val mapHalf = (x: Int) => x / 2
List(1, 2, 3).map(mapDouble)
List(1, 2, 3).map(mapHalf)

Your functions operate on one element of a list. Therefore instead of codeBlock being a () => Int, I would change it to (Int) => Int. So given one element of a list what do you want to do with it.
This results in the following code:
def mapFunctionDRY(noList:List[Int])(elementFn: (Int) => Int) = {
noList.map{ number =>
elementFn(number)
}
}
And if you're into short code, then the equivalent code is:
def mapFunctionDRY(noList:List[Int])(elementFn: (Int) => Int) = noList.map(elementFn)
There are many other ways to keep being DRY. For an example your could define the operations separately to be able to reuse them:
val doubleOperation: Int => Int = _ * 2
val halfOperation: Int => Int = _ / 2
def doubleList(noList:List[Int]) = noList.map(doubleOperation)
def halfList(noList:List[Int]) = noList.map(halfOperation)
Or you could use function currying to save yourself one line of code:
def mapFunction(fn: (Int) => Int)(noList: List[Int]) = noList.map(fn)
val doubleList = mapFunction(_ * 2)
val halfList = mapFunction(_ / 2)

I think what you are looking for is Currying in this regard.
def func(factor:Double)(noList:List[Int]) ={
val result = noList.map{ number =>
number*factor
}
result
Now you can pass this function with func(0.5f)(noList) or func(1.0f)(noList)
You could even have References to the different Versions of your Function.
halfed = x:List[Int] => func(0.5f)(x)
doubled = x:List[Int] => func(2.0f)(x)

Related

Specifying the lambda return type in Scala

Note: this is a theoretical question, I am not trying to fix anything, nor am I trying to achieve any effect for a practical purpose
When creating a lambda in Scala using the (arguments)=>expression syntax, can the return type be explicitly provided?
Lambdas are no different than methods on that they both are specified as expressions, but as far as I understand it, the return type of methods is defined easily with the def name(arguments): return type = expression syntax.
Consider this (illustrative) example:
def sequence(start: Int, next: Int=>Int): ()=>Int = {
var x: Int = start
//How can I denote that this function should return an integer?
() => {
var result: Int = x
x = next(x)
result
}
}
You can always declare the type of an expression by appending : and the type. So, for instance:
((x: Int) => x.toString): (Int => String)
This is useful if you, for instance, have a big complicated expression and you don't want to rely upon type inference to get the types straight.
{
if (foo(y)) x => Some(bar(x))
else x => None
}: (Int => Option[Bar])
// Without type ascription, need (x: Int)
But it's probably even clearer if you assign the result to a temporary variable with a specified type:
val fn: Int => Option[Bar] = {
if (foo(y)) x => Some(bar(x))
else _ => None
}
Let say you have this function:
def mulF(a: Int, b: Int): Long = {
a.toLong * b
}
The same function can be written as lambda with defined input and output types:
val mulLambda: (Int, Int) => Long = (x: Int, y: Int) => { x.toLong * y }
x => x:SomeType
Did not know the answer myself as I never had the need for it, but my gut feeling was that this will work. And trying it in a worksheet confirmed it.
Edit: I provided this answer before there was an example above. It is true that this is not needed in the concrete example. But in rare cases where you'd need it, the syntax I showed will work.

How to extract filter code to local variable

I'm filtering a list using this code :
linkVOList = linkVOList.filter(x => x.getOpen().>=(100))
The type x is inferred by Scala which is why it can find the .getOpen() method.
Can the code 'x => x.getOpen()' be extracted to a local variable ? something like :
val xval = 'x => x.getOpen()'
and then :
linkVOList = linkVOList.filter(xval.>=(100))
I think this is difficult because the .filter method infers the type wheras I need to work out the type outside of the .filter method. Perhaps this can be achieved using instaneof or an alternative method ?
There are a couple of ways to do what you are asking, but both ways will explicitly have to know the type of object they are working with:
case class VO(open:Int)
object ListTesting {
def main(args: Array[String]) {
val linkVOList = List(VO(200))
val filtered = linkVOList.filter(x => x.open.>=(100))
val filterFunc = (x:VO) => x.open.>=(100)
linkVOList.filter(filterFunc)
def filterFunc2(x:VO) = x.open.>=(100)
linkVOList.filter(filterFunc2)
}
}
Since you haven't provided any such information, I'll imply the following preconditions:
trait GetsOpen { def getOpen() : Int }
def linkVOList : List[GetsOpen]
Then you can extract the function like this:
val f = (x : GetsOpen) => x.getOpen()
or this:
val f : GetsOpen => Int = _.getOpen()
And use it like this:
linkVOList.filter( f.andThen(_ >= 100) )
Just use
import language.higherKinds
def inferMap[A,C[A],B](c: C[A])(f: A => B) = f
scala> val f = inferMap(List(Some("fish"),None))(_.isDefined)
f: Option[String] => Boolean = <function1>
Now, this is not the value but the function itself. If you want the values, just
val opened = linkVOList.map(x => x.open)
(linkVOList zip opened).filter(_._2 >= 100).map(_._1)
but if you want the function then
val xfunc = inferMap(linkVOList)(x => x.open)
but you have to use it like
linkVOList.filter(xfunc andThen { _ >= 100 })
or
linkVOList.filter(x => xfunc(x) >= 100)
since you don't actually have the values but a function to compute the values.

Scala extending while loops to do-until expressions

I'm trying to do some experiment with Scala. I'd like to repeat this experiment (randomized) until the expected result comes out and get that result. If I do this with either while or do-while loop, then I need to write (suppose 'body' represents the experiment and 'cond' indicates if it's expected):
do {
val result = body
} while(!cond(result))
It does not work, however, since the last condition cannot refer to local variables from the loop body. We need to modify this control abstraction a little bit like this:
def repeat[A](body: => A)(cond: A => Boolean): A = {
val result = body
if (cond(result)) result else repeat(body)(cond)
}
It works somehow but is not perfect for me since I need to call this method by passing two parameters, e.g.:
val result = repeat(body)(a => ...)
I'm wondering whether there is a more efficient and natural way to do this so that it looks more like a built-in structure:
val result = do { body } until (a => ...)
One excellent solution for body without a return value is found in this post: How Does One Make Scala Control Abstraction in Repeat Until?, the last one-liner answer. Its body part in that answer does not return a value, so the until can be a method of the new AnyRef object, but that trick does not apply here, since we want to return A rather than AnyRef. Is there any way to achieve this? Thanks.
You're mixing programming styles and getting in trouble because of it.
Your loop is only good for heating up your processor unless you do some sort of side effect within it.
do {
val result = bodyThatPrintsOrSomething
} until (!cond(result))
So, if you're going with side-effecting code, just put the condition into a var:
var result: Whatever = _
do {
result = bodyThatPrintsOrSomething
} until (!cond(result))
or the equivalent:
var result = bodyThatPrintsOrSomething
while (!cond(result)) result = bodyThatPrintsOrSomething
Alternatively, if you take a functional approach, you're going to have to return the result of the computation anyway. Then use something like:
Iterator.continually{ bodyThatGivesAResult }.takeWhile(cond)
(there is a known annoyance of Iterator not doing a great job at taking all the good ones plus the first bad one in a list).
Or you can use your repeat method, which is tail-recursive. If you don't trust that it is, check the bytecode (with javap -c), add the #annotation.tailrec annotation so the compiler will throw an error if it is not tail-recursive, or write it as a while loop using the var method:
def repeat[A](body: => A)(cond: A => Boolean): A = {
var a = body
while (cond(a)) { a = body }
a
}
With a minor modification you can turn your current approach in a kind of mini fluent API, which results in a syntax that is close to what you want:
class run[A](body: => A) {
def until(cond: A => Boolean): A = {
val result = body
if (cond(result)) result else until(cond)
}
}
object run {
def apply[A](body: => A) = new run(body)
}
Since do is a reserved word, we have to go with run. The result would now look like this:
run {
// body with a result type A
} until (a => ...)
Edit:
I just realized that I almost reinvented what was already proposed in the linked question. One possibility to extend that approach to return a type A instead of Unit would be:
def repeat[A](body: => A) = new {
def until(condition: A => Boolean): A = {
var a = body
while (!condition(a)) { a = body }
a
}
}
Just to document a derivative of the suggestions made earlier, I went with a tail-recursive implementation of repeat { ... } until(...) that also included a limit to the number of iterations:
def repeat[A](body: => A) = new {
def until(condition: A => Boolean, attempts: Int = 10): Option[A] = {
if (attempts <= 0) None
else {
val a = body
if (condition(a)) Some(a)
else until(condition, attempts - 1)
}
}
}
This allows the loop to bail out after attempts executions of the body:
scala> import java.util.Random
import java.util.Random
scala> val r = new Random()
r: java.util.Random = java.util.Random#cb51256
scala> repeat { r.nextInt(100) } until(_ > 90, 4)
res0: Option[Int] = Some(98)
scala> repeat { r.nextInt(100) } until(_ > 90, 4)
res1: Option[Int] = Some(98)
scala> repeat { r.nextInt(100) } until(_ > 90, 4)
res2: Option[Int] = None
scala> repeat { r.nextInt(100) } until(_ > 90, 4)
res3: Option[Int] = None
scala> repeat { r.nextInt(100) } until(_ > 90, 4)
res4: Option[Int] = Some(94)

Polish notation evaluate function

I am new to Scala and I am having hard-time with defining, or more likely translating my code from Ruby to evaluate calculations described as Polish Notations,
f.e. (+ 3 2) or (- 4 (+ 3 2))
I successfully parse the string to form of ArrayBuffer(+, 3, 2) or ArrayBuffer(-, 4, ArrayBuffer(+, 3 2)).
The problem actually starts when I try to define a recursive eval function ,which simply takes ArrayBuffer as argument and "return" an Int(result of evaluated application).
IN THE BASE CASE:
I want to simply check if 2nd element is an instanceOf[Int] and 3rd element is instanceOf[Int] then evaluate them together (depending on sign operator - 1st element) and return Int.
However If any of the elements is another ArrayBuffer, I simply want to reassign that element to returned value of recursively called eval function. like:
Storage(2) = eval(Storage(2)). (** thats why i am using mutable ArrayBuffer **)
The error ,which I get is:
scala.collection.mutable.ArrayBuffer cannot be cast to java.lang.Integer
I am of course not looking for any copy-and-paste answers but for some advices and observations.
Constructive Criticism fully welcomed.
****** This is the testing code I am using only for the addition ******
def eval(Input: ArrayBuffer[Any]):Int = {
if(ArrayBuffer(2).isInstaceOf[ArrayBuffer[Any]]) {
ArrayBuffer(2) = eval(ArrayBuffer(2))
}
if(ArrayBuffer(3).isInstaceOf[ArrayBuffer[Any]]) {
ArrayBuffer(3) = eval(ArrayBuffer(3))
}
if(ArrayBuffer(2).isInstaceOf[Int] && ArrayBuffer(3).isInstanceOf[Int]) {
ArrayBuffer(2).asInstanceOf[Int] + ArrayBuffer(3).asInstanceOf[Int]
}
}
A few problems with your code:
ArrayBuffer(2) means "construct an ArrayBuffer with one element: 2". Nowhere in your code are you referencing your parameter Input. You would need to replace instances of ArrayBuffer(2) with Input(2) for this to work.
ArrayBuffer (and all collections in Scala) are 0-indexed, so if you want to access the second thing in the collection, you would do input(1).
If you leave the the final if there, then the compiler will complain since your function won't always return an Int; if the input contained something unexpected, then that last if would evaluate to false, and you have no else to fall to.
Here's a direct rewrite of your code: fixing the issues:
def eval(input: ArrayBuffer[Any]):Int = {
if(input(1).isInstanceOf[ArrayBuffer[Any]])
input(1) = eval(input(1).asInstanceOf[ArrayBuffer[Any]])
if(input(2).isInstanceOf[ArrayBuffer[Any]])
input(2) = eval(input(2).asInstanceOf[ArrayBuffer[Any]])
input(1).asInstanceOf[Int] + input(2).asInstanceOf[Int]
}
(note also that variable names, like input, should be lowercased.)
That said, the procedure of replacing entries in your input with their evaluations is probably not the best route because it destroys the input in the process of evaluating. You should instead write a function that takes the ArrayBuffer and simply recurses through it without modifying the original.
You'll want you eval function to check for specific cases. Here's a simple implementation as a demonstration:
def eval(e: Seq[Any]): Int =
e match {
case Seq("+", a: Int, b: Int) => a + b
case Seq("+", a: Int, b: Seq[Any]) => a + eval(b)
case Seq("+", a: Seq[Any], b: Int) => eval(a) + b
case Seq("+", a: Seq[Any], b: Seq[Any]) => eval(a) + eval(b)
}
So you can see that for the simple case of (+ arg1 arg2), there are 4 cases. In each case, if the argument is an Int, we use it directly in the addition. If the argument itself is a sequence (like ArrayBuffer), then we recursively evaluate before adding. Notice also that Scala's case syntax lets to do pattern matches with types, so you can skip the isInstanceOf and asInstanceOf stuff.
Now there definitely style improvements you'd want to make down the line (like using Either instead of Any and not hard coding the "+"), but this should get you on the right track.
And here's how you would use it:
eval(Seq("+", 3, 2))
res0: Int = 5
scala> eval(Seq("+", 4, Seq("+", 3, 2)))
res1: Int = 9
Now, if you want to really take advantage of Scala features, you could use an Eval extractor:
object Eval {
def unapply(e: Any): Option[Int] = {
e match {
case i: Int => Some(i)
case Seq("+", Eval(a), Eval(b)) => Some(a + b)
}
}
}
And you'd use it like this:
scala> val Eval(result) = 2
result: Int = 2
scala> val Eval(result) = ArrayBuffer("+", 2, 3)
result: Int = 5
scala> val Eval(result) = ArrayBuffer("+", 2, ArrayBuffer("+", 2, 3))
result: Int = 7
Or you could wrap it in an eval function:
def eval(e: Any): Int = {
val Eval(result) = e
result
}
Here is my take on right to left stack-based evaluation:
def eval(expr: String): Either[Throwable, Int] = {
import java.lang.NumberFormatException
import scala.util.control.Exception._
def int(s: String) = catching(classOf[NumberFormatException]).opt(s.toInt)
val symbols = expr.replaceAll("""[^\d\+\-\*/ ]""", "").split(" ").toSeq
allCatch.either {
val results = symbols.foldRight(List.empty[Int]) {
(symbol, operands) => int(symbol) match {
case Some(op) => op :: operands
case None => val x :: y :: ops = operands
val result = symbol match {
case "+" => x + y
case "-" => x - y
case "*" => x * y
case "/" => x / y
}
result :: ops
}
}
results.head
}
}

Storing an anonymous function passed as a parameter in a Map

I'm trying to implement a simple web application server as a personal project to improve my Scala, but I've hit upon a problem.
I'd like to be able to set up routes using code like the following:
def routes()
{
get("/wobble")
{
...many lines of code here...
}
get("/wibble")
{
...many lines of code here...
}
post("/wibble")
{
...many lines of code here...
}
post("/wobble")
{
...many lines of code here...
}
}
routes is called by the server when it starts and get and post are functions defined by me like this:
get(url:String)(func:()=>String)=addroute("GET",url,func)
post(url:String(func:()=>String)=addroute("POST",url,func)
addroute(method:String,url:String,f:()=>String)
{
routesmap+=(method->Map[String,()=>String](url,func))
}
Unfortunately, I've had nothing but problems with this. Could anyone tell me the correct way in Scala to add an anonymous function (as passed in as a parameter in the defined routes function above) to a Map (or any other Scala collection for that matter)?
Here is a working example:
scala> var funcs = Map[String,(Int)=>Int]()
funcs: scala.collection.immutable.Map[String,Int => Int] = Map()
scala> funcs += ("time10", i => i * 10 )
scala> funcs += ("add2", i => i + 2 )
scala> funcs("add2")(3)
res3: Int = 5
scala> funcs("time10")(10)
res4: Int = 100
You can also add a declared function:
val minus5 = (i:Int) => i - 5
funcs += ( "minus5", minus5)
Or a method:
def square(i: Int) = i*i
funcs += ("square", square)
In your case, you can have two maps, one for GET and one for POST. It should simplify the design (and at most, you will end with four maps if you include DEL and PUT).
May be, this one ? :
type Fonc = ( (=> String) => Unit)
var routesmap = Map[String,Map[String,()=>String]]()
def addRoute(method:String,url:String,f:()=>String) = {
routesmap+=(method-> (routesmap.getOrElse(method,Map[String,()=>String]()) + (url->f)))
}
def get(url:String):Fonc = (x => addRoute("GET",url,() => x))
def post(url:String):Fonc = (x => addRoute("POST",url,() => x))
def routes()
{
post("/wobble")
{
"toto"
}
get("/wibble")
{
"titi"
}
}
you can try this code :
def addRoute(method:String,url:String,f:()=>String) = {
routesmap+=(method-> (routesmap.getOrElse(method,Map[String,()=>String]()) + (url->f)))
}
def get(url:String,func:()=>String)= addRoute("GET",url,func)
def post(url:String,func:()=>String)= addRoute("POST",url,func)
def routes()
{
get("/wobble",()=>{"toto"})
get("/wibble",()=>{println("test")
"titi"})
}
and execute these commands
scala> routes
scala> routesmap.get("GET").get("/wibble")()