I am new to coding in scala and I am curious about something and it has been hard to find an answer for online. I have this array that takes multiple arguments of different types (:Any)
val arguments= Array("Monday",10,20,Array("test","test2"), if(4 == 4){ "true"})
I iterated and printed the content inside of it. Everything prints properly except the Array at index 3. I get the object memory address I believe, which is understandable-- same thing with Java would happen. But I am curious, how would you access it?
I tried saving the value of arguments(3) in an array (val arr:Array[String] = arguments(3)) but it didn't work because there is a type mismatch (any != Array[String])
Any tips? It might be a gap in my understanding of functional programming.
What you are iterating through is an Array[Any], so you are able to perform functions that are available to an Any type. You can access the items in your array using pattern matching, which uses the unapply methods under the hood to see if it can turn your Any into something more specific:
val arguments= Array("Monday",10,20,Array("test","test2"), if(4 == 4){ "true"})
arguments foreach { arg =>
arg match {
case a:Array[String] => println(s"This is the array: ${a.mkString(",")}, and I can do array functions ${a.contains("test")}")
case _ => println(s"Otherwise I have this: $arg")
}
}
// stdout:
// Otherwise I have this: Monday
// Otherwise I have this: 10
// Otherwise I have this: 20
// This is the array: test,test2, and I can do array functions true
// Otherwise I have this: true
In swift 4 arrays are automatically comparable - but they check each element sequentially. Does element 1 match element 1, element 2 match element 2, etc.? - which is probably good standard behaviour.
But I'd like to extend / change this behaviour for a certain type Interval, so it doesn't matter what the order is of the elements, as long as the contents of the two arrays match. i.e. if both the arrays are sorted and match (using the original behaviour) then that should trigger comparable.
The trouble is, by defining my new behaviour, I 'override' and lose the existing behaviour (which I'd like ideally to keep so I can test once both arrays are sorted) - and so I get a warning 'All paths through this function will call itself'. Any ideas how to solve please
extension Array where Element == Interval {
static func == (lhs: [Interval], rhs: [Interval]) -> Bool {
return lhs.sorted() == rhs.sorted()
}
}
First make Interval conform to Hashable. Now you can coerce the arrays to Sets and compare for equality without order mattering.
What is the suitable way to compute hashCode of an Array that depends on its content?
Array.hashCode is for the array instance:
val h = a.hashCode
println(h == Array(1,2).hashCode) // false
a(0) = 42
println(h == a.hashCode) // true
Note: It'd be better to avoid copying the whole array, to a List for example, prior to computing the hashCode
Why I ask: I use an Array in a class (as a private field) because lookup time is critical, and its content is relevant to compute the hashCode of the class
from https://issues.scala-lang.org/browse/SI-1607, it says that the hashCode of Array is the hashCode from java, as scala Array are java Array. And scala could not changed it.
But it also says that scala has a suitable hashCode method in WrappedArray.
Thus:
val a = Array(1,2)
val h = a.toSeq.hashCode // wrapped it in a WrappedArray - no copy
println(h == Array(1,2).toSeq.hashCode) // true
a(0) = 42
println(h == a.toSeq.hashCode) // false
You can also use java.util.Arrays.hashCode(a), it's likely to be faster than a.toSeq.hashCode (since WrappedArray seems to inherit a non-array-specific implementation).
You can use the MurmurHash3 algorithm directly.
import scala.util.hashing.MurmurHash3
MurmurHash3.orderedHash(Array(1,2)))
Updated Question; Original below.
I am trying to create an array which represents a grid of cells, which have tuples containing the walls they are surrounded by.
I have come up with this:
rooms(Array) ->
Size = array:size(Array),
if
Size == ?HSIZE * ?VSIZE ->
Array;
true ->
HFactor = Size rem ?VSIZE,
VFactor = Size div ?HSIZE,
Room = {1+HFactor+11*VFactor,
7+HFactor+11*VFactor,
12+HFactor+11*VFactor,
6+HFactor+11*VFactor},
rooms(array:set(Size, Room, Array))
end.
When I run this with rooms(array:new()). I get the following array back:
{array,25,100,undefined,
{{{1,7,12,6},
{2,8,13,7},
{3,9,14,8},
{4,10,15,9},
{5,11,16,10},
{12,18,23,17},
{13,19,24,18},
{14,20,25,19},
{15,21,26,20},
{16,22,27,21}},
{{23,29,34,28},
{24,30,35,29},
{25,31,36,30},
{26,32,37,31},
{27,33,38,32},
{34,40,45,39},
{35,41,46,40},
{36,42,47,41},
{37,43,48,42},
{38,44,49,43}},
{{45,51,56,50},
{46,52,57,51},
{47,53,58,52},
{48,54,59,53},
{49,55,60,54},
undefined,undefined,undefined,undefined,undefined},
10,10,10,10,10,10,10,10}}
Which is quite close to the desired result, but there are two things I can't quite put my finger on (The numbers are correct). Why does it look like it is split up into multiple subarrays? What are those undefineds and 10's doing there? These are mostly due to my lack of erlang knowledge, because array:get produces the expected results, but I couldn't find anything which explains where they come from.
Original Question
rooms(Array) ->
Size = array:size(Array),
if
Size == 5 ->
Array;
Size rem 5 == 0 ->
rooms(array:set(Size, array:new(), Array));
true ->
In_Array = array:get(array:size(Array), Array),
In_Size = array:size(In_Array),
Room = {1+In_Size+11*In_Size,
7+In_Size+11*In_Size,
12+In_Size+11*In_Size,
6+In_Size+11*In_Size},
New_In = array:set(In_Size, Room, In_Array),
rooms(array:set(Size, New_In, Array))
end.
I call it with rooms(array:new()). but the result is
** exception error: bad argument
in function array:size/1 (array.erl, line 317)
in call from framework_kamer:rooms/1 (framework_kamer.erl, line 195)
Which makes sense because In_Array is not an array, but undefined. However, I can't figure out why.
Side question, is there an easier/cleaner/better way to do this?
You are (in the second call of the recursion) trying
In_Array = array:get(array:size(Array), Array),
As array is zero-indexed this will always fail, as the access will be always be off by one. Change this line to
In_Array = array:get(array:size(Array) - 1, Array),
and you are fine.
A few comments on your code:
Conventional variable naming in Erlang would be CamelCase without underscores (i.e. InArray)
Expressing a 2-dimensional array as nested arrays is almost never a good idea. Linearalise it by writing simple wrappers that recalculate a one-dimensional index from x and y as index = y * max_x + x.
Here is a simple code :
var a:Array = new Array( ins0, ins1, ins2, ins3,...., ins10000) ;
findIns( ins1500) ;
function findIns( ins:SomeInstance ) {
for ( var i = 0 ; i< a.length ; i++) {
if ( a[i] == ins ) {
trace ( "FOUND IT");
break;
}
}
}
In the above code there is NO "int" or "string". They are instances of some complex class. So is it sensible to use Vectors in place of arrays in this case.
In my opinion it should be sensible, because instances are "numerical-memory-locations" afterall ?
If the content of the array are all instances of the same class, then yes Vector will definitely performs better than Array.
See the documentation for more information:
Performance: array element access and iteration are much faster when using a Vector instance than they are when using an Array.
Type safety: in strict mode the compiler can identify data type errors. Examples of data type errors include assigning a value of the incorrect data type to a Vector or expecting the wrong data type when reading a value from a Vector. Note, however, that when using the push() method or unshift() method to add values to a Vector, the arguments' data types are not checked at compile time. Instead, they are checked at run time.
Reliability: runtime range checking (or fixed-length checking) increases reliability significantly over Arrays.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Vector.html
Yes, you are right. What gets stored inside the vector is a reference to your object, not your object itself. You can check that doing the following:
var ref:yourType = a[0];
a[0] = someOtherObjectInstance;
trace(ref.toString());
You will find that ref still points to your original object.