Swapping tuples of different types in Scala - scala

I'm trying to write a simple function that will swap a (Int, String) tuple in Scala. I've tried a number of things and I keep getting compiler errors, for example:
def swap (p:(Int,String)) : (String,Int) = {
var s = p._1
var t = p._2
var u = (p._2, p.1)
}
[error] found : Unit
[error] required: (String, Int)
[error] }
[error] ^
[error] one error found
Why does it keep saying it finds a "Unit" type? I've tried different variations, and even using the "swap" function built into Scala, but I keep getting these kinds of errors stating that my return type isn't (String, Int). Any suggestions are appreciated. Thank you!

The return value of a method (or more generally, the value of any block) is the value of the last expression inside the block. The last expression in your block is
var u = (p._2, p.1)
The value of an assignment is () (which is the singleton value of the Unit type): an assignment is a side-effect, it doesn't have a value, and () is the value (and Unit the type) which denotes the absence of a value (think "void" if you are familiar with C, C++, D, Objective-C, Objective-C++, Java, or Cā™Æ); ergo, your method returns (), which is of type Unit.
Here's a more Scala-ish way to write your method:
def swap[A, B](p: (A, B)) = (p._2, p._1)

All you need is this:
def swap(p: (Int,String)): (String,Int) = (p._2, p._1)
And to make it work on any tuple (of size 2):
def swap[A,B](p: (A,B)): (B,A) = (p._2, p._1)
In Scala, the last expression in a function is the returned value. It also supports an explicit return expression, that would be like this:
def swap(p: (Int,String)): (String,Int) = {
return (p._2, p._1)
}
or more like what you intended:
def swap(p: (Int,String)): (String,Int) = {
val result = (p._2, p._1)
return result
}
Keep in mind this explicit return syntax is not recommended.
Because Scala is a functional language, everything is an expression. Expressions are anything you can evaluate and get back a resulting value, which, being a value, has a type.
Even things that you would think more like "statements", like println("a") or var a = 1 are expressions. When evaluated, they return a meaningless/empty value, that is of type Unit. Therefore, your function returns the last statement, that is a variable assignment, which has a value of type Unit.

You can also achieve it using pattern matching and function literal:
def swap[X,Y]: ((X,Y)) => ((Y,X)) = { case (x, y) => (y, x) }

Related

What is the Unit Type Behavior in Scala

Why does this code works:
val f: String => Unit = {(_:String) => 2}
//or more succinctly
val f: String => Unit = _ => 2
Clearly the body of my function return an int. However the type expected is Unit
But if i do
implicitly[String <:< Unit]
//Cannot prove that String <:< Unit.
Hence i am a bit confused as to how the cast is happening ? Why is it even allowed in the first place
This is called Value Discarding, see 6.26.1 Value Conversions, sub-section Value Discarding of the Scala Language Specification:
If š‘’ has some value type and the expected type is Unit, š‘’ is converted to the expected type by embedding it in the term { š‘’; () }.
In other words, your code is compiled as-if you had written
val f: String => Unit = {(_:String) => { 2; () }}
//or more succinctly
val f: String => Unit = _ => { 2; () }
I guess the intention behind this feature is familiarity for programmers coming from imperative programming languages, where it is often possible to discard values.
E.g. in C, it is legal to write
printf("Hello");
and discard the return value, even though printf returns an int. This goes together with the idea of expression statements and statement expressions that many imperative programming languages have.
In Scala any type A can be transformed into type Unit. It's not subtyping, it's transforming. Like type A means some possible side effect plus returning A while Unit means we disregard return value but keep the side effect.

Why I can't apply just an underscore to first parameter in Scala?

I don't know why pattern d is bad in this list below.
Why need expicit type declaration?
def adder1(m:Int,n:Int) = m + n
val a = adder1(2,_) //OK
val b = adder1(_,2) //OK
def adder2(m:Int)(n:Int) = m + n
val c = adder2(2)(_) //OK
val d = adder2(_)(2) //NG:missing parameter type
val e = adder2(_:Int)(2) //OK
I just want to know the reason pattern d needs parameter type.
Very welcome just showing citation language spec.
So I believe this comes from the concept of Partial Application.
Intuitively, partial function application says "if you fix the first arguments of the function, you get a function of the remaining arguments"
...
Scala implements optional partial application with placeholder, e.g. def add(x: Int, y: Int) = {x+y}; add(1, _: Int) returns an incrementing function. Scala also support multiple parameter lists as currying, e.g. def add(x: Int)(y: Int) = {x+y}; add(1) _.
Lets take a look at adder2
From the REPL:
scala> def adder2(m:Int)(n:Int) = m + n
def adder2(m: Int)(n: Int): Int
Lets get a value to represent this:
scala> val adder2Value = adder2
^
error: missing argument list for method adder2
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `adder2 _` or `adder2(_)(_)` instead of `adder2`.
Ok, let's try:
val adder2Value = adder2 _
val adder2Value: Int => (Int => Int) = $Lambda$1382/0x0000000840703840#4b66a923
Ahha!
In English: "A function that takes an Int and returns a function that takes an Int and returns an Int"
How can we bind the second argument using this signature? How can we access the inner function unless we first have gone through the outer one?
As far as I know, this is not possible to do using this signature, unless you explicitly define the type of your first argument.
(But what about adder2(_)(_)?)
scala> adder2(_)(_)
^
error: missing parameter type for expanded function ((<x$1: error>, x$2) => adder2(x$1)(x$2))
^
error: missing parameter type for expanded function ((<x$1: error>, <x$2: error>) => adder2(x$1)(x$2))
(Maybe this hints at our solution?)
Notice what happens if we explicitly define both arguments:
val adder2Value2= adder2Value (_:Int) (_:Int)
val adder2Value2: (Int, Int) => Int = $Lambda$1394/0x000000084070d840#32f7d983
This is much more manageable, we can now fix either argument, and get a simplified partial function:
scala> val adder2FirstArg = adder2Value (_:Int) (10)
val adder2FirstArg: Int => Int = $Lambda$1395/0x000000084070d040#47f5ddf4
scala> val adder2SecondArg = adder2Value (5) (_:Int)
val adder2SecondArg: Int => Int = $Lambda$1396/0x000000084070c840#21ed7ce
So what's really going on here?
When you bind an argument to a value, you have explicitly expressed the type (maybe it's inferred, but it's definitely that type, in this case, Ints). It's sugar so we don't need to write it. But under the hood, these are composed functions, and how they are composed is very important. To be able to match and simplify the function signature, the compiler requires us to provide this information in an outside-in manner. Otherwise, we need to give it some help to get there.
EDIT:
I think that this question serves as more of a Scala language spec. puzzle exercise, however. I can't think of any good reason, from a design perspective, for which you would need to implement a curried function in such a way that you cannot order the parameters such that the last parameters are the ones being inferred.

Assign values of a tuple to single variables in Scala

is there a nice possibilyt to assign the values of a tuple to single variables? Here is what i want to do but it throws an error:
var a : Int = _
var b : Int = _
def init() {
(a,b) = getTuple() // returns (Int, Int)
}
def someFunction = {
// use a here
}
def someOtherFunction = {
// use b here
}
Error: ';' expected but '=' found.
(a, b) = getTuple()
Do i really have to do this ._1 and ._2 thing?
val tuple = getTuple() // returns (Int, Int)
a = tuple._1
b = tuple._2
Thanks for answering.
As you can see in Section 6.15 Assignments of the Scala Language Specification, the lefthand-side of an assignment expression must be either a bare identifier:
foo = ???
// either an assignment to a local mutable `var` or syntactic sugar for:
foo_=(???)
a member access:
foo.bar = ???
// syntactic sugar for:
foo.bar_=(???)
or a method call:
foo(bar) = ???
// syntactic sugar for:
foo.update(bar, ???)
Pattern Matching is only available for value definitions (see Section 4.1 Value Declarations and Definitions) and variable definitions (see Section 4.2 Variable Declarations and Definitions).
So, both of the following would be legal:
var (a, b) = getTuple()
val (a, b) = getTuple()
By the way, there are a number of highly non-idiomatic things in your code:
It is highly unusual to pass an empty argument list to a method call. Normally, methods that have no parameters should have no parameter lists instead of an empty parameter list. The only exception are methods that have side-effects, where the empty parameter list serves as kind of a "warning flag", but methods which have side-effects are highly non-idiomatic as well. So, getTuple should be defined and called like this:
def getTuple = ???
getTuple
instead of
def getTuple() = ???
getTuple()
On the other hand, if the method does have side-effects, it shouldn't be called getTuple because that implies that the method "gets" something, and there is no indication that it also changes something.
In Scala, getters and setters are not called getFoo and setFoo but rather foo and foo_=, so the method should rather be called tuple.
Mutable variables are highly non-idiomatic as well, they should probably rather be vals.
Tuple destructuring is an opaque call to unapply method of TupleN[T1, ..., Tn] companion object, aka extractor object.
As the documentation suggests, one can only have a variable initialization with an extractor object, but not assignment.
So, the only possible way is to use it like this:
def getTuple = (1,2)
def main() = {
val (a,b) = getTuple
// use a,b
}
The fact that you use a var may be the sign you have a design flaw. Try to refactor your code or specify the exact problem you're trying to solve with the var to justify its usage (although what you're trying to do with extractor is still impossible)

Type parameters applied to Scala Function

I am trying to understand the type parameters when applied to a function.
I would like to use Generic Types in the below method but using String and Int for my understanding.
When I define a function as below
def myfunc[Int](f:String => Int):Int = {
Integer.min(1,2)
}
it complains
found : scala.this.Int
required: Int&0
Integer.min(1,2)
However if I remove the return type of the function ( which I understand is not required), it compiles fine.
I am not able to infer why removing the return type makes the compilation successful.
Appreciate your help.
-Amit
Try
def myfunc(f:String => Int):Int = {
Integer.min(1,2)
}
When you write def myfunc[Int](f:String => Int):Int you declare type parameter Int, which hides standard type scala.Int. This is the same as if you declared def myfunc[A](f:String => A):A. When you remove return type it's inferred to be scala.Int, i.e. def myfunc[A](f:String => A) is def myfunc[A](f:String => A):Int
If you want to use generics, first you have to understand that the name of the variable types starts capitalized and they are names, just that so [Int] in your function is the name of the type variable, an example:
object Main extends App{
val f: String => Int = s => 4
println(myfunc(f, "nothing useful"))
def myfunc[A,B](f:A => B, x: A):B = {
f(x)
}
}
here the names are A and B and the return type is of type B
Question: What's the difference between these 3 methods?
def myfunc1[X](f:String => X):X =
Integer.min(1,2)
def myfunc2[Int](f:String => Int):Int =
Integer.min(1,2)
def myfunc3[IDontGetTypeParameters](f:String => IDontGetTypeParameters):IDontGetTypeParameters =
Integer.min(1,2)
Answer: Nothing. From the compiler's point of view they are the same, and they fail to compile for the same reason: each is defined to return the type of the type parameter but tries to return an integer (Scala.Int) instead.
A quick one liner:
def myfunc(f:String => Int):Int = Integer.min(1,2)
It's good trying to make your own examples, but have you tried any examples from books, articles or tutorials? There's probably a good one in Scala for the Impatient by Cay Horstmann.
Here's a decent example from the Tour de Scala:
def listOfDuplicates[A](x: A, length: Int): List[A] = {
if (length < 1)
Nil
else
x :: listOfDuplicates(x, length - 1)
}
Sometimes you can omit the type parameter, but let's ignore that for now and declare the types explicitly:
listOfDuplicates[Int](43, 5) // Should give a list with 43 five times
listOfDuplicates[String]("Hello, world! ", 3) // "Hello, world!" thrice
listOfDuplicates[(Int, Int)]((0, 1), 8) // The pair (0, 1) eight times
This shows that A can be Int, String, (Int, Int) or just about anything else we can think of. Not sure you'd ever have a practical need for this, but you can even do something like this:
def wrapLength(str: String): Int = str.length
listOfDuplicates[String => Int](wrapLength(_), 2)
Here's a Scastie snippet in which you can play around with this.
Your generic type name shouldn't be one of the reserved words in Scala. Int itself is a reserved word for a type.
In this cases, for simplicity and understanding, we use some basic characters like T or R as the generic type if you really keen to use generics for other functions.

the scala compiler cannot find the correct generic function parameter

I have scala code as following
object Main extends App {
def getFun[T, U](x: Array[T] => U, p: Array[T]): U = { x(p) }
def getFun2(x: Array[Int] => Double, p: Array[Int]): Double = { x(p) }
val arr = Array(1, 2, 3, 4)
println(getFun((x: Array[Int]) => x.sum, arr))
// println(getFun(_.sum, arr)) // error, why!
// println(getFun(x = _.sum, arr)) // error, why!
println(getFun2(_.sum.toDouble, p = arr))
}
Why getFun cannot be used as simple as getFun2.
I think use the "x = _.sum", the scala compiler can find the correct type, but it seems that it failed.
Can any body explain the reason of the error.
Thanks!
getFun uses type variables whereas getFun2 uses explicit types.
So, for getFun2, the compiler knows that it is calling the sum function on an Array[Int]. It knows how to sum up Integers, things work.
For getFun the compiler only knows that there is an array of something (T stands for some type). It does not how to sum up something, we have to help the compiler here and tell it what T is. One possibility is what you did in the first line, specifying the array type in the function lambda. Another would be to pass along type parameter values like this:
println(getFun[Int,Double](_.sum, arr))