Error: Not found: Value S (Scala) - arrays

val Array(k,s) = readLine.split(" ").map(_.toInt)
This code works fine. But not this:
val Array(k,S) = readLine.split(" ").map(_.toInt)
Capitalizing "s" here gives me an error: error: not found: value S
What is going on?

When you are creating the k and s identifiers with val Array(k,s) = ..., you are using pattern matching to define them.
From the Scala Specifications (1.1 Identifiers):
The rules for pattern matching further distinguish between variable
identifiers, which start with a lower case letter, and constant
identifiers, which do not.
That is, when you say val Array(k,S) = ..., you're actually matching S against a constant. Since you have no S defined, Scala reports error: not found: value S.
Note that Scala will throw a MatchError if the constant is defined but it still cannot find a match :
scala> val S = 3
S: Int = 3
scala> val Array(k, S) = Array(1, 3)
k: Int = 1
scala> val Array(k, S) = Array(1, 4)
scala.MatchError: [I#813ab53 (of class [I)
... 33 elided

When using extractors, symbols that begin with a lower case character will be interpreted as a variable to hold an extracted value. On the other hand, symbols that begin with an upper case character are used to refer to variables/values declared in an outer scope.
Another example:
val X = 2
something match {
case (X, y) => // matches if `something` is a pair whose first member is 2, and assigns the second member to `y`
case (x, y) => // matches if `something` is a pair, and extracts both `x` and `y`
}

Related

Type Mismatch in scala, Array[Int] and Array[Option[Int]]

First, I am new to Scala, So apologies if the following question is too simple.
I have written the following code to the find the values of the keys that I supply in an array from the map.
def stringToCountMap(inputArray: Array[String], inputMap:Map[String,Int]) : Array[Int] = {
return inputArray.map(x => inputMap.get(x))
}
I got the following error,
type mismatch;
found : Array[Option[Int]]
required: Array[Int]
return inputArray.map(x => inputMap.get(x))
Question:
1) Can anyone explain what is Option[Int]?
2) What is my mistake here ?
Thanks in advance.
Option is Scala's option type (also called a nullable type). It represents a case where the value may not exist.
Consider a map that doesn't contain a requested key. How would you handle a request for the key? One option is to result in an error, such as by throwing an exception. Another is to return a special value that indicates there is no value. Map.get does the latter, using Option as the special type and None as the value. This means the return type of Map.get isn't the value type of the map (Int), but Option applied to the value type (Option[Int]).
To correct the type declaration, change the return type:
def stringToCountMap(inputArray: Array[String], inputMap:Map[String,Int]) : Array[Option[Int]] = {
inputArray.map(x => inputMap.get(x))
}
You can leave out the return type of stringToCountMap and let type inference handle it:
def stringToCountMap(inputArray: Array[String], inputMap:Map[String,Int]) = {
inputArray.map(x => inputMap.get(x))
}
As a consequence, missing keys from the input map get carried through:
scala> stringToCountMap(Array("a", "def"), Map("a" -> 1, "bc" -> 2))
res0: Array[Option[Int]] = Array(Some(1), None)
Option[T] is a wrapper around a value of type T. Its purpose is to prevent NullPointerException, that you might know from Java. A value of type Option[T] might either be None, which, as the name implies is an object that represents nothing, or it might be Some(x: T), which represents an existing value.
inputMap(x) returns an Option[Int], since you have no guarantee that the x key exists in inputMap. If it does, it returns Some(value: Int), else it returns None.
Calling stringToCountMap(Array("a", "b", "c"), Map("a" -> 1, "c" -> 2)) results in Array(Some(1), None, Some(2))
If you want an Array[Int] instead, you might do something like inputArray.map(x => inputMap.getOrElse(x, 0)).get. The getOrElse method has two parameters, where the first one is the key, and the second one is the default value. inputArray.map(x => inputMap.get(x).getOrElse(0)) has the same effect, since calling getOrElse(value) on an Option either unwraps the Some object, or returns the default value.
Now, stringToCountMap(Array("a", "b", "c"), Map("a" -> 1, "c" -> 2)) results in Array(1, 0, 2).
You might also want to omit the keys missing in the input array. In that case, you might do inputArray.flatMap(x => inputMap.get(x)). flatMap is a function similar to map, but it returns strictly, as the name implies, flat collections. For example, calling flatMap(x => x) on an Array[Array[Int]] would return an Array of all the values in the 2D array in a single row.
Here, Option is a collection, as well. If it is of type Some, it contains a single value, if it is None, it is an empty collection. Thus, in the resulting array you would only have the values of the keys present in the map, and the keys not present in the map are skipped.
Now, stringToCountMap(Array("a", "b", "c"), Map("a" -> 1, "c" -> 2)) results in Array(1, 2).
First, there is no need to use 'return' in scala to return any value.
def stringToCountMap(inputArray: Array[String], inputMap:Map[String,Int]) = {
inputArray.map(x => inputMap.get(x))
}
When you get the value of key from Map, It returns result in Option.
For example:
scala> val map = Map(1-> "a",2 -> "b")
map: scala.collection.immutable.Map[Int,String] = Map(1 -> a, 2 -> b)
scala> map.get(1)
res0: Option[String] = Some(a)
scala> map.get(3)
res1: Option[String] = None
When you try to get the value of key, which does not exist. In java, you have encountered with NullPointerException. So when there is no value, it returns None to avoid exception.
For more info refer
In your method, you have given return type as Array[Int] but function returns Array[Option[Int]] that's why it throws compilation error.

Scala Array Slicing with Tuple

I try to slice an 1D Array[Double] using the slice method. I've written a method which returns the start and end index as a tuple (Int,Int).
def getSliceRange(): (Int,Int) = {
val start = ...
val end = ...
return (start,end)
}
How can I use the return value of getSliceRange directly?
I tried:
myArray.slice.tupled(getSliceRange())
But this gives my a compile-Error:
Error:(162, 13) missing arguments for method slice in trait IndexedSeqOptimized;
follow this method with `_' if you want to treat it as a partially applied function
myArray.slice.tupled(getSliceRange())
I think the problem is the implicit conversion from Array to ArrayOps (which gets slice from GenTraversableLike).
val doubleArray = Array(1d, 2, 3, 4)
(doubleArray.slice(_, _)).tupled
Function.tupled[Int, Int, Array[Double]](doubleArray.slice)
(doubleArray.slice: (Int, Int) => Array[Double]).tupled
Two options here, the first one is to call your function twice:
myArray.slice(getSliceRange()._1, getSliceRange()._2)
or to save your Tuple beforehand:
val myTuple: (Int, Int) = getSliceRange()
myArray.slice(myTuple._1, myTuple._2)
Edit: I leave this here just in case but Peter Neyens posted the expected answer.

How to define a zero element when using discriminated unions in F# Array functions

OK, a question, I would like to use an array of discriminated unions in the Array functions. In the code below, I define a type ResultVari that is either Unknown or a floating point value. I also define the infix plus operator for the type, which returns a value only if both args are not Unknown. This works fine.
type ResultVari =
| Unknown
| Value of float
static member (+) (a,b) = // add two ResultVari's together
match a,b with
| Value(av),Value(bv) -> Value(av + bv) // only has a value if both args do.
| _ -> Unknown
(* Summation of array of ResultVari, such that if any are unknown then the result is Unknown *)
let example1 = [| Value(4.0); Value(5.5); Value(3.1) |] // summation should be 12.6
let example2 = [| Value(4.0); Unknown; Value(3.1) |] // summation should be Unknown
let summation (varArray:ResultVari array) =
Array.sum (+) varArray //ERROR this value is not a function and cannot be applied
let summation2 (varArray:ResultVari array) =
Array.fold (+) (Value(0.0)) varArray // Works
let sum_example1 = summation2 example1
let sum_example2 = summation2 example2
printfn "%A" sum_example1 // 12.6
printfn "%A" sum_example2 // Unknown
Using summation2 the program works as expected with the sum for example1 being 12.6 and for example2 being Unknown.
But I don't understand why summation doesn't work - the compiler complains "this value is not a function and cannot be applied". In another attempt (not shown), I also got the error of a missing get_Zero element which I understand -- the sum function has to use some type of a zero definition to start the summation, and using the fold function with my Value(0.0) as the start value like in summation2 solves that.
So is there a way to define a get_Zero element for a discriminated union, or would I have to use a record type instead for ResultVari? Then I could use Array.sum instead of using Array.fold.
You need to add a zero element to use array.sum - like this:
type ResultVari =
| Unknown
| Value of float
static member (+) (a,b) = // add two ResultVari's together
match a,b with
| Value(av),Value(bv) -> Value(av + bv) // only has a value if both args do.
| _ -> Unknown
static member Zero with get() = Value(0.0)
Then the code becomes:
let summation (varArray:ResultVari array) =
Array.sum varArray
This makes sense because when you sum something you need to start from zero and without the zero member, the compiler doesn't know where to start.

Element-wise sum of arrays in Scala

How do I compute element-wise sum of the Arrays?
val a = new Array[Int](5)
val b = new Array[Int](5)
// assign values
// desired output: Array -> [a(0)+b(0), a(1)+b(1), a(2)+b(2), a(3)+b(3), a(4)+b(4)]
a.zip(b).flatMap(_._1+_._2)
missing parameter type for expanded function
Try:
a.zip(b).map { case (x, y) => x + y }
When you use an underscore as a placeholder in a function definition, it can only appear once (for each function argument position, that is, but in this case flatMap takes a Function1, so there's only one). If you need to refer to an argument more than once, you can't use the placeholder syntax—you'll need to give the argument a name.
As the other answers point out, you can use .map { case (x, y) => x + y } or the tuple accessor version, but it's also worth noting that if you want to avoid a bunch of tuple allocations in an intermediate collection, you can write the following:
scala> (a, b).zipped.map(_ + _)
res5: Array[Int] = Array(0, 0, 0, 0, 0)
Here zipped is a method that's available on pairs of collections that has a special map that takes a Function2, which means the only tuple that gets created is the (a, b) pair. The extra efficiency probably doesn't matter much in most cases, but the fact that you can pass a Function2 instead of a function from pairs means the syntax is often a little nicer as well.
// one D Array
val x = Array(1, 2, 3, 40, 55)
val x1 = Array(1, 2, 3, 40, 55)
x.indices.map(i=>x(i)+ x(i) )
// TWo D Array
val x1= Array((3,5), (5,7))
val x = Array((1,2), (3,4))
x.indices.map(i=>( x(i)._1 + x1(i)._1, x(i)._2 + x1(i)._2))

Can't declare table element with number from another table

Code is very simple. Declaring two tables, a simple and a multi-dimensional:
Player = {X_Pos = 1, Y_Pos = 1, Current_Sprite_Num = 100}
for j=1, Max_col_length do -- value ofMax_col_length doesn't matter here; positive integer anyway
MapLayer_B[j] = {}
for i=1, Max_row_length do --same here
MapLayer_B[j][i] = 1
end
end
Then I try to do this operation:
MapLayer_B[Player[X_Pos]][Player[Y_Pos]] = Player[Current_Sprite_Num]
It should replace the Player[X_Pos]th element of the Player[Y_Pos]th rowtable in MapLayer_B. Instead, I got this error with LÖVE compiler:
Error: attempt to index field '?' (a nil value)
I don't really get, why it happens, since all elements of both MapLayer_B andPlayer tables are declared and not kept in nil.
Any ideas?
You need to use Player.X_Pos instead of Player[X_Pos] and so on.
The brackets notation will interpret "X_Pos" as a variable and try to access taht key instead (the reason for the error is that undefined variables default to null)
t = {a = 17}
print( t.a ) --dot notation is simpler
print( t["a"] ) --bracket notation expects a string
key = "a" --that string can be from a variable
print( t[key] )

Resources