I'm trying to pass a tuple as an argument to function. Unfortunately i can't do this. Can you give me some tips?
val t = Tuple3(3, "abc", 5.5);
def fun(x: (Int, String, Double) = {
x.productIterator.foreach(i => println("Value: " + i));
}
def(t);
There's a missing closing parenthese and you called def(t) instead of fun(t). Note that you don't need to indicate the constructor Tuple3 :
val t = (3, "abc", 5.5);
def fun(x: (Int, String, Double)) = {
x.productIterator.foreach(i => println("Value: " + i));
}
fun(t);
You are missing a bracket after your method declaration. Also you need to run using fun(t).
val t = Tuple3(3, "abc", 5.5)
def fun(x: (Int, String, Double)) = {
x.productIterator.foreach(i => println("Value: " + i))
}
fun(t)
Related
I'm getting problems to understand the currying concept, or at least the SCALA currying notation.
wikipedia says that currying is the technique of translating the evaluation of a function that takes multiple arguments into evaluating a sequence of functions, each with a single argument.
Following this explanation, are the two next lines the same for scala?
def addCurr(a: String)(b: String): String = {a + " " + b}
def add(a:String): String => String = {b => a + " " + b}
I've run both lines with the same strings a and b getting the same result, but I don't know if they are different under the hood
My way of thinking about addCurr (and currying itself) is that it is a function that receives a string parameter a, and returns another function that also receives a string parameter b and returns the string a + " " + b?
So if I'm getting right, addCurr is only syntactic sugar of the function add and both are curryed functions?
According to the previous example, the next functions are also equivalent for scala?
def add(a: String)(b: String)(c: String):String = { a + " " + b + " " + c}
def add1(a: String)(b: String): String => String = {c => a + " " + b + " " + c}
def add2(a:String): (String => (String => String)) = {b => (c => a + " " + b + " " + c)}
They have a bit different semantics, but their use-cases are mostly the same, both practically and how it looks in the code.
Currying
Currying a function in Scala in that mathematical sense is a very straightforward:
val function = (x: Int, y: Int, z: Int) => 0
// function: (Int, Int, Int) => Int = <function3>
function.curried
// res0: Int => (Int => (Int => Int)) = <function1>
Functions & methods
You seem to be confused by the fact that in Scala, (=>) functions are not the same as (def) methods. Method isn't a first-class object, while function is (i.e. it has curried and tupled methods, and Function1 has even more goodness).
Methods, however, can be lifted to functions by an operation known as eta expansion. See this SO answer for some details. You can trigger it manually by writing methodName _, or it will be done implicitly if you give a method to where a function type is expected.
def sumAndAdd4(i: Int, j: Int) = i + j + 4
// sumAndAdd4.curried // <- won't compile
val asFunction = sumAndAdd4 _ // trigger eta expansion
// asFunction: (Int, Int) => Int = <function2>
val asFunction2: (Int, Int) => Int = sumAndAdd4
// asFunction2: (Int, Int) => Int = <function2>
val asFunction3 = sumAndAdd4: (Int, Int) => Int
// asFunction3: (Int, Int) => Int = <function2>
asFunction.curried
// res0: Int => (Int => Int) = <function1>
asFunction2.curried
// res1: Int => (Int => Int) = <function1>
asFunction3.curried
// res2: Int => (Int => Int) = <function1>
{sumAndAdd4 _}.tupled // you can do it inline too
// res3: Int => (Int => Int) = <function1>
Eta expansion of multiple parameter list
Like you might expect, eta expansion lifts every parameter list to its own function
def singleArgumentList(x: Int, y: Int) = x + y
def twoArgumentLists(x: Int)(y: Int) = x + y
singleArgumentList _ // (Int, Int) => Int
twoArgumentLists _ // Int => (Int => Int) - curried!
val testSubject = List(1, 2, 3)
testSubject.reduce(singleArgumentList) // Int (6)
testSubject.map(twoArgumentLists) // List[Int => Int]
// testSubject.map(singleArgumentList) // does not compile, map needs Int => A
// testSubject.reduce(twoArgumentLists) // does not compile, reduce needs (Int, Int) => Int
But it's not that currying in mathematical sense:
def hmm(i: Int, j: Int)(s: String, t: String) = s"$i, $j; $s - $t"
{hmm _} // (Int, Int) => (String, String) => String
Here, we get a function of two arguments, returning another function of two arguments.
And it's not that straightforward to specify only some of its argume
val function = hmm(5, 6) _ // <- still need that underscore!
Where as with functions, you get back a function without any fuss:
val alreadyFunction = (i: Int, j: Int) => (k: Int) => i + j + k
val f = alreadyFunction(4, 5) // Int => Int
Do which way you like it - Scala is fairly un-opinionated about many things. I prefer multiple parameter lists, personally, because more often than not I'll need to partially apply a function and then pass it somewhere, where the remaining parameters will be given, so I don't need to explicitly do eta-expansion, and I get to enjoy a terser syntax at method definition site.
Curried methods are syntactic sugar, you were right about this part. But this syntactic sugar is a bit different. Consider following example:
def addCur(a: String)(b: String): String = { a + b }
def add(a: String): String => String = { b => a + b }
val functionFirst: String => String = add("34")
val functionFirst2 = add("34")_
val functionSecond: String => String = add("34")
Generaly speaking curried methods allows for partial application and are necessary for the scala implicits mechanism to work. In the example above i provided examples of usage, as you can see in the second one we have to use underscore sign to allow compiler to do the "trick". If it was not present you would receive error similar to the following one:
Error:(75, 19) missing argument list for method curried in object XXX
Unapplied methods are only converted to functions when a function type
is expected. You can make this conversion explicit by writing curried_ or curried(_)(_) instead of curried.
Your question interested me so I tried this out my self. They actually desugar down to some very different constructs. Using
def addCurr(a: String)(b: String): String = {a + " " + b}
This actually compiles to
def addCurr(a: String, b: String): String = {a + " " + b}
So it completely removes any currying effect, making it a regular arity-2 method. Eta expansion is used to allow you to curry it.
def add(a:String): String => String = {b => a + " " + b}
This one works as you would expect, compiling to a method that returns a Function1[String,String]
I search a way to count the different chars from a string.
The problem is that's not allowed to use any functions from the scala-api or to use vars (only val).
I want same result like that
val fruit: String = "dasisteintest"
println(fruit.groupBy(identity).mapValues(_.size))
Map(e -> 2, s -> 3, n -> 1, t -> 3, a -> 1, i -> 2, d -> 1)
In every try I made, I have at the end a list[(Char,Int)] where I have to change the Int. But because it's an immutable list I can't change it.
How can I implement that counting char algorithm?
You can use the following snippet:
val fruit: String = "dasisteintest"
val map = scala.collection.mutable.HashMap.empty[Char, Int]
for (symbol <- fruit) {
if (map.contains(symbol))
map(symbol) = map(symbol) + 1
else
map.+=((symbol, 1))
}
println(map)
def countChars(str: String) = {
def loop(chars: List[Char], acc: Map[Char, Int]): Map[Char, Int] = {
chars match {
case Nil => acc
case char :: rest =>
loop(rest, acc + (char -> (acc(char) + 1)))
}
}
loop(str.toList, Map.empty[Char, Int] withDefaultValue 0)
}
Test:
# val fruit: String = "dasisteintest"
fruit: String = "dasisteintest"
# countChars(fruit)
res4: Map[Char, Int] = Map('e' -> 2, 's' -> 3, 'n' -> 1, 't' -> 3, 'a' -> 1, 'i' -> 2, 'd' -> 1)
Whatever you use here is from scala api, a Map.apply, or Map.empty or List.::. It would be difficult not to use any functions from scala api. My guess is that you aren't supposed to be using things like groupBy and you are supposed to do something a bit more low level. Folding is natural solution here, like foldLeft, but if that is considered "using a function from scala api", you can just implement foldLeft yourself, just like I did in my solution.
As for withDefaultValue you can replace it with explicit check if value is present and put a 1 there in that case.
You don't know how to change an in a list or map that is immutable? You just make a new list with that value changed.
For a map, given
val map = Map('a' -> 3)
you can update it doing
# map.updated('a', 4)
res6: Map[Char, Int] = Map('a' -> 4)
or
# map + ('a' -> 4)
res7: Map[Char, Int] = Map('a' -> 4)
Both do exact the same thing - insert or update - and return new map.
Here you can find how to update elements in a list
Replace element in List with scala
although you rarely want to access list by index, you rather just build a new list from old one while iterating over it somehow, e.g. with fold.
What do you mean by "no functions from Scala API"? Does that include no functions from the collections api? If so, then ignore my answer. However if we can't even use reduce methods, I don't see the point of this exercise.
Here's what I came up with:
val fruit: String = "dasisteintest"
fruit.foldLeft[Map[Char,Int]](Map.empty)((map, c) => map + (c -> (map.getOrElse(c, 0) + 1)))
Although can you expand what you mean by ""you have to change the Int"?
Here is the expected code.
First the function which returns the char from the list
def removeFromList(l: List[Char], l2: List[Char], toDelete: Char): List[Char] = {
if (l.isEmpty) l2
else {
if (l.head == toDelete)
removeFromList(l.tail, l2, toDelete)
else
removeFromList(l.tail, l2 :+ l.head, toDelete)
}
}
and then the function which counts the chars and calls removeFromList()
def zaehlZeichen(s: String): List[(Char, Int)] = {
val sl: List[Char] = s.toUpperCase().toList
if (sl.isEmpty) Nil
else {
val l: List[Char] = List()
val tupleList: List[(Char, Int)] = List();
val in: Int = countChar(sl, 0, sl.head)
val t: List[(Char, Int)] = tupleList :+ (sl.head, in)
val cutL: List[Char] = removeFromList(sl, l, sl.head)
t ::: zaehlZeichen(cutL.mkString);
}
}
object CountEachCharInString
{
//Counts the number of a specific character in the Input String
def characterCount(inputChar: Char, str: String): Unit =
{
var num: Int = 0
num = str.count(_ == inputChar);
/*
//Implementation of count method
for(i <- 0 to str.length - 1)
{
if(str(i) == inputChar)
{
num += 1
}
}
*/
println(s"$inputChar appears $num times")
}
def countAllChars(inputStr: String): Unit =
{
//To eliminate duplicates, need one loop inside the other. str(i) == str(j)
for(i <- 0 to inputStr.length - 1)
{
var occurence: Int = 0
for(j <- 0 to i-1)
{
if(inputStr(j) == inputStr(i))
occurence = occurence + 1
}
if(occurence == 0)
{
characterCount(inputStr(i), inputStr)
//var num = inputStr.count(_ == inputStr(i))
//println( inputStr(i) + s" appears $num times")
}
}
}
def main(args: Array[String]): Unit =
{
countAllChars("HelloforHello...^^&&&&")
}
}
How do I write an implicit conversion for the code below (simplified)? I understand that you need to convert (Int) => B to (String) => B.
List(1, 2, 3).map { s: String => "_" + s }
// expected: List("_1", "_2", "_3")
I think Simon's answer works best. In case that you still want to do the implicit conversion the following should do the trick.
implicit def convertFun[B](fun: String => B): (Int => B) = {
x: Int => fun(x.toString)
}
Actually you don't need, just do it like;
List(1, 2, 3) map { i: Int => "_" + i }
for(s <- List(1, 2, 3)) yield "_" + s
Is this what you're looking for?
In scala, how would i declare & instantiate a map that returns a function (for the sake of argument? A function that accepts two variables, one a String, one an Int)?
I am envisioning:
val myMap = Map[String, (String,Int)=>Boolean](
WHAT GOES HERE???
)
Let's just map the string "a" to this cool function. I don't care much about what the function does - returns true, perhaps?
Try this:
val myMap = Map[String, (String, Int) => Boolean](
"Test" -> ((s, i) => true)
)
you can do something like this:
val map = Map("key" -> { (str: String, n: Int) =>
str.indexOf(n) == -1
})
result:
> map: scala.collection.immutable.Map[String,(String, Int) => Boolean] = Map(key - <function2>)
Say I have a following class:
case class Mock(id: Int, pty1: String, pty2: String)
How can I instantiate it from a following map dynamically?
val params = Map("id" → 234, "pty1" → "asdf", "pty2" → "asdf")
LOL ) Found out that I had a solution already implemented in my lib. Requires Scala 2.10.
def instantiate[T <: AnyRef : Manifest](params: Map[String, Any]): T = {
instantiate(Mirror.classToType(manifest[T].erasure), params).asInstanceOf[T]
}
def instantiate(tpe: Mirror.Type, params: Map[String, Any]) = {
val p = constructorParams(tpe, params)
require(
params.size == p.size &&
p.forall(p => params.contains(p.nameString)),
"Params map `" + params + "` doesn't match `" + p + "`"
)
Option(Mirror.typeToJavaClass(tpe).getConstructor(p.map(p => Mirror.typeToJavaClass(p.tpe)): _*))
.getOrElse(throw new RuntimeException("No appropriate constructor of `" + tpe + "` found"))
.newInstance(p.map(p => params(p.nameString).asInstanceOf[Object]): _*)
}
private def constructorParams(tpe: Mirror.Type, params: Map[String, Any]) = {
tpe.members.find(_.isConstructor).get.paramss(0)
}
I don't think you can in a determistic way, since the names of the parameters are not part of the byte code and therefor at run time there is no way to know which String argument comes first and which second.