Casting after comparison of two Array manifest in scala - arrays

I have some problem to cast my objeсt Variable[A] where A <: Array[_]
I create a function to compare manifest and cast data into Array to the good type.
My object Variable[A] store a Manifest[A] into the def 'type'
I make a plugin of an existent software, so it's not me which instanciate this Variable with good type.
Prototype object and class :
object Prototype {
def apply[T](n: String)(implicit t: Manifest[T]) = new Prototype[T] {
val name = n
val `type` = t
}
}
trait Prototype[T] {
def name: String
def `type`: Manifest[T]
}
Variable Object and Class :
object Variable {
def apply[T](p: Prototype[T], v: T) = new Variable[T] {
val prototype = p
val value = v
}
}
trait Variable[T] {
def prototype: Prototype[T]
def value: T
}
My class which use :
class XYDataReader[A <: Array[_]](var data: Iterable[Variable[A]]) {
def get[T](variable: Variable[A])(implicit m: Manifest[T]): Option[T] = {
if (variable.prototype.`type` <:< m) {
Some(variable.value.asInstanceOf[T])
} else {
None
}
}
}
There is probably a mistake of my part when i instanciate Variable object used to compare, so i give also the code of instanciation :
val v:List[Any] = List[Any](1.2,2,3)
val p = Prototype[Array[Any]]("col1")
val myVariable = Variable(p, v.toArray(ClassTag(p.`type`.runtimeClass)))
I don't understand why pattern matching failed when i call get[Array[Double]](myVariable) where myVariable.value contain an Array[Double]
When i println() the two manifest :
variable array type : Array[double]
m type : Array[Double]
It seem an Array[Double] is not an Array[double], how can i resolve/cast this ?

This started out as a comment, since it's not an answer, but it's too big and needs formatting (plus my browser tab's auto-reload caused it to be lost the first time...)
So... For starters, your snippet of code is incomplete and / or incorrect. Potentially there are imports in effect which could alter the meaning of that code. Secondly, as shown it would not compile 'cause what appears to be a formal type parameter, the A has no binding. Thus unless you have an actual type named A that won't compile.
Secondly, Double is potentially ambiguous. There is both scala.Double and java.lang.Double and they are distinct. Scala auto-boxes and -unboxes primitive types for you, typically when they're used to instantiate type parameters for generic methods (and specialization is not used). A consequence of this is that Array[scala.Double] is distinct from Array[java.lang.Double]. Scala will create arrays of primitive types when possible, but Array[java.lang.Double] is explicitly an array of boxed double-precision floating point.
E.g.:
scala> val d1: scala.Double = 123.456
d1: Double = 123.456
scala> val d2: java.lang.Double = 234.567
d2: Double = 234.567
scala> d1.getClass
res25: Class[Double] = double
scala> d2.getClass
res26: Class[_ <: Double] = class java.lang.Double
scala> val ad1: Array[scala.Double] = Array(123.456, 234.567)
ad1: Array[Double] = Array(123.456, 234.567)
scala> val ad2: Array[java.lang.Double] = Array(234.567, 345.678)
ad2: Array[Double] = Array(234.567, 345.678)
scala> ad1.getClass
res27: Class[_ <: Array[Double]] = class [D
scala> ad2.getClass
res28: Class[_ <: Array[Double]] = class [Ljava.lang.Double;
So please, if you would, fill in the missing details of your sample code?

Finally, with help of colleague methods to resursively unArrayify Array, i resolve my runtime type reification problem. Now i can compare equality between Array[double] with Array[Double].
// Convert unknow A en Array[T], so you need to call get with Type :
// example : get[Array[Double](myVariable)
// return an Array[Double] only if it's possible for this Variable, else it return None
def get[T](variable: Variable[A])(implicit m: Manifest[T]): Option[T] = {
if (ClassUtils.assignable(variable.prototype.`type`.runtimeClass, m.runtimeClass)) {
val casted = variable.prototype.`type`.runtimeClass.cast(variable.value)
Some(casted.asInstanceOf[T])
} else {
None
}
I hope these methods can help other people :)
You can see helping method ClassUtils.assignable here :
https://gist.github.com/4686167
and on the source forge project :
https://forge.iscpif.fr/projects/openmole/repository/revisions/master/entry/core/openmole/misc/org.openmole.misc.tools/src/main/scala/org/openmole/misc/tools/obj/ClassUtils.scala

Related

Creating a FloatArray from an Array<Float> object in Kotlin

I am trying to convert a Array object to a FloatArray using a spread operator:
val x = arrayOf(0.2f, 0.3f)
val y = floatArrayOf(*x)
Unfortunetly I get Type mismatch: inferred type is Array<Float> but FloatArray was expected
Why is there an error and how to make this work?
You cannot write that but instead you can do:
val y = x.toFloatArray()
toFloatArray is the obvious choice, but if for some reason you wanted to create a new float array without calling that, you could do the same thing it does internally: call the FloatArray constructor:
val x = arrayOf(0.2f, 0.3f)
val y = FloatArray(x.size) { x[it] }

Array declaration in Kotlin

The code below is an example for Array declaration in Kotlin,
fun main(args: Array<String>) {
var a = Array<Int>(2){0}
a[0] = 100
a[1] = 200
print(a[1])
}
Here variable a is an array of size 2 and having values 100 and 200 and it is printing the value of a[1] as 200.
My question is -> What is the role of "0" in var a = Array(2){0}?
I changed the value of "0" to some other integer value, still it is working fine, but i was not able to find the use case of it. Can anyone explain it?
Any help will be appreciated.
Thanks.
The 0 is what you initialize each element of your array (2 in your case) with, using the following constructor:
public inline constructor(size: Int, init: (Int) -> T)
You can make this visible by printing the array directly after its initialization:
var a = Array<Int>(2){0}
println(a.contentToString())
Please consider the use of arrayOf(0,0) for such a simple use case, which is more idiomatic.
Arrays in Kotlin are represented by the Array class, that has get and set functions (that turn into [] by operator overloading conventions), and size property, along with a few other useful member functions:
class Array<T> private constructor() {
val size: Int
operator fun get(index: Int): T
operator fun set(index: Int, value: T): Unit
operator fun iterator(): Iterator<T>
// ...
}
You can write
var a = Array(2){0}
Creates a new array with the specified [size], where each element is calculated by calling the specified
* [init] function. The [init] function returns an array element given its index.
public inline constructor(size: Int, init: (Int) -> T)
Read Arrays in Kotlin.

Sum array along dimension

In many languages (Fortran, Matlab/Octave, Julia, etc) an expression like sum(array,n) will sum the values of an array along the n:th dimension and outputting an array of one lower dimensionality. Is there something equivalent in Rust?
I tried:
fn main() {
let arr1: [f64; 5] = [1.1, 1.2, 2.3, 3.4, 4.5555];
println!("this {}", arr1.iter().sum())
}
with this error:
error[E0282]: unable to infer enough type information about `_`
--> src/main.rs:3:37
|
3 | println!("this {}", arr1.iter().sum())
| ^^^ cannot infer type for `_`
<std macros>:2:27: 2:58 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
src/main.rs:3:5: 3:43 note: in this expansion of println! (defined in <std macros>)
|
= note: type annotations or generic parameter binding required
In this case you have to explicitly specify type of the elements:
println!("this {}", arr1.iter().sum::<f64>())
You were very close :)
Another option that were suggested by #E_net4 is to use separate binding:
let res: f64 = arr1.iter().sum();
println!("this {}", res)
The "unable to infer enough type information about _" error message is explained in a few other questions. See Error: unable to infer enough type information about `_`; type annotations or generic parameter binding required and Unable to infer enough type information about _; type annotations or generic parameter binding required. Basically, it means that the compiler doesn't have enough information to specify all type parameters in a function or a data type.
Nevertheless, this particular case may arouse some confusion: why can't Iterator.sum() just infer the resulting sum's type to the iterator's Item? By supposedly adding up f64s, we'd be expecting f64 as an outcome, right? Well, the method sum is actually defined like this:
fn sum<S>(self) -> S
where S: Sum<Self::Item>
Where S implements another kind of sum function (see trait Sum) that takes an iterator:
pub trait Sum<A = Self> {
fn sum<I>(iter: I) -> Self where I: Iterator<Item=A>;
}
This trait gives us the freedom to sum numbers and references to numbers alike:
static MAGIC_CODE: u32 = 0xDEADBEEF;
static BLAND_CODE: u32 = 0x1234ABCD;
fn main() {
let sum1: u32 = vec![MAGIC_CODE, BLAND_CODE] // vec! infers to Vec<u32>
.into_iter().sum();
let sum2 = vec![&MAGIC_CODE, &BLAND_CODE] // vec! infers to Vec<&u32>
.into_iter().sum::<u32>();
assert_eq!(sum1, sum2);
}
On the other hand, this also means that the definition of a sum becomes more loose: any other data type implementing Sum<u32> (or Sum<&u32>) could take its place in the code above, which leads to the aforementioned ambiguity. For the purpose of demonstration, this code also compiles:
use std::iter::Sum;
struct Accumulator(bool);
impl Sum<u32> for Accumulator {
fn sum<I: Iterator<Item = u32>>(mut iter: I) -> Self {
Accumulator(iter.any(|v| v != 0))
}
}
fn main() {
let sum3: Accumulator = {
let data = vec![MAGIC_CODE, BLAND_CODE];
data.into_iter().sum()
};
assert!(sum3.0);
}
Full code on Playground.

Kotlin NDArray with a lambda constructor with generic return type

I'm trying to create a very simple generic NDArray class in Kotlin that takes a lambda expression as an init function.
class NDArray<T>(i: Int, j: Int, f: (Int) -> T) {
val values: Array<T> = Array(i * j, f)
}
A typical usage would be:
fun main(args: Array<String>){
val m = NDArray(4, 4, ::zero)
}
fun zero(i: Int) = 0.0
My problem is that the Kotlin compiler complains on the initialisation of values in the constructor
values = Array(i * j, f)
by saying "Cannot use 'T' as reified type parameter. Use class instead". Why ?
EDIT:
If I instead replace the Kotlin Array implementation with my own MyArray it compiles:
class NDArray<T>(i: Int, j: Int, f: (Int) -> T) {
val values: MyArray<T> = MyArray(i * j, f)
}
class MyArray<T>(i:Int, init: (Int) -> T) {
...
}
Not sure why Kotlin treats MyArray differently from a regular Array when both have the same constructor ?
Creating a Java array requires specifying an element type. In the case of your class, the element type is provided only as a type parameter of the class, and generics in Java are erased at runtime. Because of that, the element type of the array is not known, and it's not possible to create it.
If you would want to create a custom wrapper around standard Array<T>, it would have to look like the following:
class NDArray<reified T>(i:Int, j:Int, init: (Int) -> T) {
val arr = Array<T>(i * j, init)
}
The reified keyword means that your T is not erased, and may be used in places where a real class is needed, like calling the Array() constructor.
Note that this syntax is not supported for class constructors, but it is still useful for factory functions (must be inlined)
fun <reified T> arrayFactory(i:Int, j:Int, init: (Int) -> T) = Array<T>(i * j, init)
Based on input from yole and voddan this is the best solution I found to the problem so far:
class NDArray<T>(val values: Array<T> ){
companion object Factory{
inline operator fun <reified T>invoke(i: Int, j: Int, noinline init: (Int) -> T) = NDArray(Array(i * j,init))
}
}
This allows the usage of reified as a constructor by using a companion object. Construction calling convention can be done using operator invoke. This works now:
fun main(args: Array<String>){
val m = NDArray(4,4, ::zero)
}
fun zero(i:Int) = 0.0
The only problem ( except for the convoluted syntax invoke() ) is that the NDArray constructor need to be public. Is there a better way perhaps ?
NOTE! Following issues KT-11182 affects this design pattern

Swift Array: Cannot invoke 'append' with an argument list of type '(Int)'

I'm trying to implement a padding function for Array:
extension Array {
func dataWithPadding(offset: Int, length: Int, paddingLength: Int) -> NSData {
var arr = Array(self[offset..<(offset + length)])
arr = arr.reverse()
for (var i = 0; i < paddingLength; i++) {
arr.append(0)
}
let d = NSData(bytesNoCopy: &arr, length: length)
return d
}
}
This errors at arr.append with:
Cannot invoke 'append' with an argument list of type '(Int)'
I try to change the declaration into:
var arr[UInt8] = Array(self[offset..<(offset + length)])
However, this also errors:
Cannot assign to immutable expression of type '[UInt8].Type' (aka 'Array.Type')
The weird part: I try to run the original code with arr.append commented out, and use lldb to directly run arr.append(0), it actually works.
I'm using Xcode 7.2.
Since your Array extension puts no constraint on which types of arrays (element types) that can be used with it, .append(0) cannot be invoked; not all types can be converted into from integer literals. Hence, it's not weird that you cannot use .append(0) in the "generic" array extension, whereas you naturally can use it directly on an array that Swift can infer to have integer literal convertible elements, e.g. [Int]. Consider the following example:
var arr : [UInt8] = []
arr.append(0)
var arr2 : [String] = []
arr2.append(0) // error
In the example above, both arrays would have access to your extension dataWithPadding, but both can naturally not make use of arr.append(0) in the extension, hence the error message
Cannot invoke 'append' with an argument list of type '(Int)'
Now, a simple fix is to add a type constraint for the array elements to IntegerLiteralConvertible, after which you extension is valid, and accessible for all arrays that have elements which conform to IntegerLiteralConvertible.
extension Array where Element: IntegerLiteralConvertible {
func dataWithPadding(offset: Int, length: Int, paddingLength: Int) -> NSData {
var arr = Array(self[offset..<(offset + length)])
arr = arr.reverse()
for (var i = 0; i < paddingLength; i++) {
arr.append(0)
}
let d = NSData(bytesNoCopy: &arr, length: length)
return d
}
}
Alternatively, make use of the less general SignedNumberType, UnSignedIntegerType or IntegerType as type constraint for Element; these conform also to e.g. Comparable and Equatable, in case you'd like to compare and perform operations on your generic elements in the extension.
Finally note that you can naturally use your own custom protocol as type constraint for Element in your extension, allowing you to include additional blueprints (below, foo() method) accessible for your Element:s in the extension
protocol MyIntegerLiteralInitializableTypes: IntegerLiteralConvertible {
func foo()
}
extension MyIntegerLiteralInitializableTypes {
func foo() {
print("I am of type \(self.dynamicType)!")
}
}
/* For the Array<Type>:s you want to have access to .dataWithPadding,
extend those 'Type':s to MyIntegerLiteralInitializableTypes */
extension Int8 : MyIntegerLiteralInitializableTypes { }
extension UInt8 : MyIntegerLiteralInitializableTypes { }
extension Array where Element: MyIntegerLiteralInitializableTypes {
func dataWithPadding(offset: Int, length: Int, paddingLength: Int) -> NSData {
self.first?.foo() /* I am of type ...! */
var arr = Array(self[offset..<(offset + length)])
arr = arr.reverse()
for (var i = 0; i < paddingLength; i++) {
arr.append(0)
}
let d = NSData(bytesNoCopy: &arr, length: length)
return d
}
}
It's also probably a good idea to add #warn_unused_result to your dataWithPadding(...) function signature, as a call to it without assigning the return will yield a runtime exception ("... malloc: ...: pointer being freed was not allocated").

Resources