Using the apply / (array subscripting) method in a builder pattern - arrays

Given a trivial function returning an array:
scala> def methodReturnsArray() = { Array(1.0, 2.0) }
methodReturnsArray: ()Array[Double]
We can go ahead and invoke the function:
scala> val myarr = methodReturnsArray
myarr: Array[Double] = Array(1.0, 2.0)
scala> myarr(0)
res21: Double = 1.0
However, it is not possible to use the apply ( / array index semantics) directly:
scala> methodReturnsArray(0)
<console>:53: error: too many arguments for method methodReturnsArray: ()Array[Double]
methodReturnsArray(0)
^
The request is to explain why that were not possible as given. Secondarily: is there some way to get an "inline" invocation. I.e. not requiring to separate out the steps: s
(a) invoke the method and
(b) access the specific element of the array (via apply())
on separate statements.

Aha! Seconds after posting this I arrived at the answer: need to include the parens on the function call: i.e methodReturnsArray () (0) :
scala> methodReturnsArray()(0)
res22: Double = 1.0

Related

MethodError: no method matching -(::Int64, ::Array{Int64,1})

I tried playing around with this example in the Julia documentation. My attempt was to make the cell split into two parts that have half of the amount of protein each.
using OrdinaryDiffEq
const α = 0.3
function f(du,u,p,t)
for i in 1:length(u)
du[i] = α*u[i]/length(u)
end
end
function condition(u,t,integrator) # Event when event_f(u,t) == 0
1-maximum(u)
end
function affect!(integrator)
u = integrator.u
idxs = findall(x->x>=1-eps(eltype(u)),u)
resize!(integrator,length(u)+length(idxs))
u[idxs] ./ 2
u[end-idxs:end] = 0.5
nothing
end
callback = ContinuousCallback(condition,affect!)
u0 = [0.2]
tspan = (0.0,10.0)
prob = ODEProblem(f,u0,tspan)
sol = solve(prob,Tsit5(),callback=callback)
I get the error: MethodError: no method matching -(::Int64, ::Array{Int64,1}). I know there is a problem with idxs = findall(x->x>=1-eps(eltype(u)),u), and my attempt was to put a dot between the 1 and eps, but that didn't fix it. I am using Julia 1.1.1.
Running your code the stacktrace points to the line
u[end-idxs:end] = 0.5
The issue here is that findall returns an array even when it only finds one element, e.g.
julia> findall(x -> x > 2, [1,2,3])
1-element Array{Int64,1}:
3
and you can't subtract an array from end in your indexing expression.
I don't understand enough about your code to figure out what idxs should be, but if you expect this to only return one element you could either use first(idxs) (or even only(idxs) in Julia 1.4), or replace findall with findfirst, which returns the index as an Integer (rather than an array).

Applying the filter function on an Array of Arrays returns an exception in Scala

I am learning Scala and tried practising some examples on Arrays. Below is the example:
scala>var arr = Array(Array(1,2,3), Array(4,5,6));
scala>arr.map(_.map(_ * 5))
res42: Array[Array[Int]] = Array(Array(5,10,15),Array(20,25,30))
When I tried doing the filter method the on above mentioned array in the same way, it resulted in an error. Below is the piece of code and the resulting error.
scala>arr.filter(_.filter(_ < 5))
<console>:15: error: type mismatch;
found : Array[Int]
required: Boolean
o.filter(_.filter(_ < 5))
^
Please tell why the filter operation isn't working what is the correct way to use the filter method on an array of Arrays ?
If the objective is to get Array(Array(1,2,3), Array(4)), then
arr.map(_.filter(_ < 5))
If the objective is to get Array(1,2,3,4), then
arr.flatten.filter(_ < 5)
First of all, you should read a good book if you're interested in Scala. Using vars is a very bad practice and should be avoided by beginners.
About your example, just to explain why it fails, filter requires as parameter a function with return type Boolean. In the inner filter you correctly use _ < 5 which is expanded to (x: Int) => x < 5, a function that returns true or false. But on the outer filter you used _.filter(_ < 5) which is expanded to (y: Array[Int]) => y.filter((x: Int) => x < 5). Here's the issue, y.filter((x: Int) => x < 5) will return a new Array, which means the function does not have a return type of Boolean, but of an Array[Int].
Take a look at the signature of the filter:
def filter(p: A => Boolean): Repr = filterImpl(p, isFlipped = false)
Filter method accepts a Predicate. You may map you internals arrays and then filter by your rules.

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.

Function defined with generic types

I searched for a while and I was not able to find a clear and satisfying answer to this question.
Suppose I have this little function to compute the mean value of an Array:
def meanofArray(s:Array[Double]) : Double = s.sum/s.length
the problem is that is Array has to be Double.
If for example I have this Array:
val x = Array( 1 , 2 , 3 , 4 )
and make the call :
println(meanofArray(x))
I get the error found : Array[Int]
required: Array[Double]
How can I implement meanofArray so as to be able to accept any type of Int , Long , Float and Double with no errors ?
My thought was Generic types :
def meanofArray(s:Array[T]) : Double = s.sum/s.length
but I could not get it working.
Any other idea is welcomed !
The issue you are running into demonstrates the beauty of type abstraction.
Based solely on the signature of the function you provided
def meanofArray(s:Array[T]) : T
we know quite a bit about what this function can and can not do, as long as it does not do shady things like reflection of course. It can not do things like sort the Array, find the sum, etc. Based on some unfortunate characteristics of Scala, there are some things which we can not be sure it does not do, like use equals or toString for some T.
You need to declare some additional information about the type T in the function signature.
def meanofArray[T](s: Array[T])(implicit ev: Numeric[T]): Double
Here we are declaring that T must have a definition of Numeric[T] defined and in scope at call sites. Numeric[T] provides the definitions of functions required in order to do the calculations you need. We are now declaring that this function may do more things like sort the array or find the sum.
And the implementation you are looking for...
def meanofArray[T](s: Array[T])(implicit ev: Numeric[T]): Double =
s.view.map(ev.toDouble).sum / s.length
EDIT: Map s to view of Array[Double] to decrease likelihood of overflow. Taken from #Eastsun's answer. Taking Numeric[T] implicitly is strongly preferred over implicit view from T => Double in my opinion though.
Here is what you want(The parameter's type of mean is Seq[A] so that you can use it as mean(List(1, 2, 3)) or mean("ABCDEFG")):
scala> def mean[A](arr: Seq[A])(implicit view: A => Double): Double =
(arr map view sum) / arr.size
mean: [A](arr: Seq[A])(implicit view: A => Double)Double
scala> mean(Array(1, 2, 3, 4))
res0: Double = 2.5
Compare with #drstevens 's solution:
scala> def meanofArray[T](s: Array[T])(implicit ev: Numeric[T]): Double =
| ev.toDouble(s.sum) / s.length
meanofArray: [T](s: Array[T])(implicit ev: scala.math.Numeric[T])Double
scala> meanofArray(Array[Byte](111, 111, 111, 111))
res3: Double = -17.0 //Wrong!!!
scala> mean((Array[Byte](111, 111, 111, 111)))
res4: Double = 111.0 //Right !!!
This is the cleanest solution i could come up for your question.
def mean[A <% Double : Numeric](seq:Seq[A]) = seq.sum/seq.length
Here, Seq.sum needs an evidence of A conforms to be a Numeric type. (: in the type parameter)
And that division to work, the result of seq.sum should be viewable as a Double. Altogether this results a result mean of Double type

incredible implicit Array conversion in scala

According to Scaladoc, there is no method named map in Array class, but there is an implicit function implicit def intArrayOps (xs: Array[Int]): ArrayOps[Int] defined in scala.Predef. So you can apply map on Array(1,2,3,4) if you like. But What I am confused about is that the map result is of type Array[Int], not ArrayOps[Int]. Here is my test:
scala> val array = Array(1,2,3,4)
array: Array[Int] = Array(1, 2, 3, 4)
scala> array.map(x => x)
res18: Array[Int] = Array(1, 2, 3, 4)
scala> res18.isInstanceOf[Array[Int]]
res19: Boolean = true
scala> res18.isInstanceOf[scala.collection.mutable.ArrayOps[Int]]
warning: there wre 1 unchecked warnings; re-run with -unchecked for details
res20: Boolean = false
It indeed returns an array, as intended and as is convenient, there is no reason you would need an ArrayOps, it is intended only to provide extra methods to arrays. The doc is wrong.
The routine is actually not implemented in ArrayOps. As most collection methods, it is inherited from TraversableLike. And you see two map methods in the doc:
def map [B] (f: (T) ⇒ B): ArrayOps[B]
def map [B, That] (f: (T) ⇒ B)(implicit bf: CanBuildFrom[Array[T], B, That]): That
Only the second one exists (inherited from TraversableLike). It is intended to allow implementation of map in just one place (traversable like) while allways giving the best possible behavior. For instance, a String is a of Seq[Char], if you map with a function from character to character, you get a String, but if you map from collection to say Int, the result cannot be a String and it will just be a Seq. This is explained in much detail in the paper fighting the bit rot with types.
However, this makes for a very complex signature, which does not reflect the simplicity of using the method, and makes very poor documentation most of the time (you normally would have to chase to which CanBuildFrom in implicit scope would work). This was discussed in this most famous scala question of stack overflow. So the tool scaladoc was extended so that a simpler entry, corresponding to intended usage, may appear. If you look at the source of GenTraversableLike, where the routine is introduced, you will see the following in the scaladoc for map (and a similar one in many methods)
#usecase def map[B](f: A => B): $Coll[B]
Subtypes add in their doc #define Coll <className>, and map (among others) appears with the simplified signature, marked [Use case]. In the source of ArrayOps, there is a #define Coll ArrayOps where it should be Array.
You can use the REPL with the -Xprint:typer option to see what's going on. Here is the output of the map method, reformatted for easier reading:
$ scala -Xprint:typer
scala> Array(1,2,3,4).map(x => x)
[[syntax trees at end of typer]]// Scala source: <console>
// some lines deleted
private[this] val res0: Array[Int] =
scala.this.Predef.intArrayOps(scala.Array.apply(1, 2, 3, 4))
.map[Int, Array[Int]]
(( (x: Int) => x ))
(scala.this.Array.canBuildFrom[Int](reflect.this.Manifest.Int));
So simplifying for package names here is what happens:
intArrayOps(Array(1,2,3,4)) // converts to ArrayOps
.map[Int, Array[Int]] // calls map with parameter lists below
((x:Int) => x) // pass identity function as fisrt param
(Array.canBuildFrom[Int]// pass builder for Array[Int] as second param
(Manifest.Int)) // pass class manifest for Int
So there is indeed a conversion to ArrayOps (first line). It returns ArrayOps[Int].
The ArrayOps.map[Int, Array[Int]] method is then called on it. Then as didierd explain, the original signature for map - not the simplified signature - indicates that the return type inferred will be Array[Int]

Resources