Why does the third access to this array return null? - arrays

I'm writing tetris in Scala as an exercise and I came around this strange behavior:
abstract class Orientation(protected val index: Int) {
private[Orientation] val impls: Array[Orientation] = Array(OrientedLeft, OrientedUp, OrientedRight, OrientedDown)
def rotateCounterClockwise = impls(
if (index == 0) 3
else index - 1
)
def rotateClockwise = impls((index + 1) % 4)
}
object OrientedLeft extends Orientation(0) {
override def toString = "Left"
}
object OrientedUp extends Orientation(1) {
override def toString = "Up"
}
object OrientedRight extends Orientation(2) {
override def toString = "Right"
}
object OrientedDown extends Orientation(3) {
override def toString = "Down"
}
object Test extends Application {
var orientation: Orientation = OrientedUp
for (i <- 0 until 20) {
println("Oriented to: "+ orientation)
orientation = orientation.rotateClockwise
}
}
Running Test gives this output:
Oriented to: Up
Oriented to: Right
Oriented to: Down
Oriented to: null
Followed by an java.lang.NullPointerException obviously. I mean: What the hell is going on here?

Just move impls in a companion object:
object Orientation {
private val impls: Array[Orientation] = Array(OrientedLeft, OrientedUp, OrientedRight, OrientedDown)
}
abstract class Orientation(protected val index: Int) {
import Orientation._
def rotateCounterClockwise = impls(
if (index == 0) 3
else index - 1
)
def rotateClockwise = impls((index + 1) % 4)
}
The reason why you had this error is that you have circular initializaiton dependencies: everytime you instantiate Orientation, you access the four Orientation singletons.
Simply put, accessing OrientedUp forces its instantiation, which in turn forces the instantian of all four singletons, including OrientedUp itself, which is still being constructed.
This is why you get null for this "still being constructed" value.

This is probably an initialisation problem. Each instance of Orientation has an array of OrientedX-objects, who are themselves instances of Orientation. Scala objects are initialised lazily, but that triggers population the impls array with objects that are currently being initialised. Hence the null entry.
Do what RĂ©gis suggested or mark val impls as lazy.

Related

Set class property inside an array in swift

I was wondering if there is a possibility to set a class property via an array:
class Test {
var x: Int = 0
var y: Int = 0
var z: Int = 0
}
let newTest = Test()
let myArray = [newTest.x, newTest.y, newTest.z]
So I created an Array with the properties of a class. Now I want to access the property object itself and set it to a value, kind of like this (I know this sets the array at index 0 to 1, but I hope the general idea is clear):
myArray[0] = 1 // I want to set newTest.x = 1
The following one of course works but I need the property objects themself in the array:
let myArray = [newTest, newTest, newTest]
myArray[0].x = 1
UPDATE
What I have now is an array with integers, but I need the reference to the class property, so I can set its value.
The Use Case:
I have an TextField as a user input. The user input should be splitted by a ','. And I don't know in advance, how many items I will get.
And therefore I thought I run a for loop, so I can set class properties based on the number of items.
newItem = Item()
var myClassPorperties = [newItem.cat1, newItem.cat2, newItem.cat3]
if let categoriesArray = categoriesTextField.text?.components(separatedBy: ",") {
for i in 0...categoriesArray.count - 1 {
myClassProperties[i] = categoriesArray[i]
}
}
It seems a bit strange to take a list of comma separated values and use them to update an object but given that here is one way to do it.
Create a function to map between an index (in the array) and a property in your class
func update(at index: Int, with value: Int) {
switch index {
case 0:
x = value
case 1:
y = value
case 2:
z = value
default:
print("Value \(value) at \(index) igonred")
}
}
and use it like this
categoriesArray.compactMap(Int.init).enumerated().forEach(newTest.update)
Another solution is to work with KeyPath
func keyPath(for index: Int) -> WritableKeyPath<Test, Int>? {
switch index {
case 0:
return \.x
case 1:
return \.y
case 2:
return \.z
default:
return nil
}
}
and then use the following code to update the object using your array
categoriesArray.compactMap(Int.init).enumerated().forEach {
if let keyPath = keyPath(for: $0.offset) {
newTest[keyPath: keyPath] = $0.element
}
}
I still think it would be better to have one input field in the UI for every property in your class so you can have a direct one-to-one connection between them.

Summary of ArrayList ordering in Kotlin (Android)

I am trying to provide a summary of items within an ArrayList (where order matters). Basically, I am setting up an exercise plan with two different types of activities (Training and Assessment). I then will provide a summary of the plan after adding each training/assessment to it.
The structure I have is something along the lines of:
exercisePlan: [
{TRAINING OBJECT},
{TRAINING OBJECT},
{ASSESSMENT OBJECT},
{TRAINING OBJECT}
]
What I want to be able to do is summarise this in a format of:
2 x Training, 1 x Assessment, 1 x Training, which will be displayed in a TextView in a Fragment. So I will have an arbitrarily long string that details the structure and order of the exercise plan.
I have tried to investigate using a HashMap or a plain ArrayList, but it seems pretty messy so I'm looking for a much cleaner way (perhaps a MutableList). Thanks in advance!
ArrayList is just a specific type of MutableList. It's usually preferable to use a plain List, because mutability can make code a little more complex to work with and keep robust.
I'd create a list of some class that wraps an action and the number of consecutive times to do it.
enum class Activity {
Training, Assessment
}
data class SummaryPlanStep(val activity: Activity, val consecutiveTimes: Int) {
override fun toString() = "$consecutiveTimes x $activity"
}
If you want to start with your summary, you can create it and later convert it to a plain list of activities like this:
val summary: List<SummaryPlanStep> = listOf(
SummaryPlanStep(Activity.Training, 2),
SummaryPlanStep(Activity.Assessment, 1),
SummaryPlanStep(Activity.Training, 1),
)
val plan: List<Activity> = summary.flatMap { List(it.consecutiveTimes) { _ -> it.activity } }
If you want to do it the other way around, it's more involved because I don't think there's a built-in way to group consecutive duplicate elements. You could a write a function for that.
fun <T> List<T>.groupConsecutiveDuplicates(): List<Pair<T, Int>> {
if (isEmpty()) return emptyList()
val outList = mutableListOf<Pair<T, Int>>()
var current = first() to 1
for (i in 1 until size) {
val item = this[i]
current = if (item == current.first)
current.first to (current.second + 1)
else {
outList.add(current)
item to 1
}
}
outList.add(current)
return outList
}
val plan: List<Activity> = listOf(
Activity.Training,
Activity.Training,
Activity.Assessment,
Activity.Training
)
val summary: List<SummaryPlanStep> = plan.groupConsecutiveDuplicates().map { SummaryPlanStep(it.first, it.second) }
This is what I have set up to work for me at the moment:
if (exercisePlanSummary.isNotEmpty() && exercisePlanSummary[exercisePlanSummary.size - 1].containsKey(trainingAssessment)) {
exercisePlanSummary[exercisePlanSummary.size - 1][trainingAssessment] = exercisePlanSummary[exercisePlanSummary.size - 1][trainingAssessment]!! + 1
} else {
exercisePlanSummary.add(hashMapOf(trainingAssessment to 1))
}
var textToDisplay = ""
exercisePlanSummary.forEach {
textToDisplay = if (textToDisplay.isNotEmpty()) {
textToDisplay.plus(", ${it.values.toList()[0]} x ${it.keys.toList()[0].capitalize()}")
} else {
textToDisplay.plus("${it.values.toList()[0]} x ${it.keys.toList()[0].capitalize()}")
}
}
where trainingAssessment is a String of "training" or "assessment". exercisePlanSummary is a ArrayList<HashMap<String, Int>>.
What #Tenfour04 has written above is perhaps more appropriate, and a cleaner way of implementing this. But my method is quite simple.

backpressure is not properly handled in akka-streams

I wrote a simple stream using akka-streams api assuming it will handle my source but unfortunately it doesn't. I am sure I am doing something wrong in my source. I simply created an iterator which generate very large number of elements assuming it won't matter because akka-streams api will take care of backpressure. What am I doing wrong, this is my iterator.
def createData(args: Array[String]): Iterator[TimeSeriesValue] = {
var data = new ListBuffer[TimeSeriesValue]()
for (i <- 1 to range) {
sessionId = UUID.randomUUID()
for (j <- 1 to countersPerSession) {
time = DateTime.now()
keyName = s"Encoder-${sessionId.toString}-Controller.CaptureFrameCount.$j"
for (k <- 1 to snapShotCount) {
time = time.plusSeconds(2)
fValue = new Random().nextLong()
data += TimeSeriesValue(sessionId, keyName, time, fValue)
totalRows += 1
}
}
}
data.iterator
}
The problem is primarily in the line
data += TimeSeriesValue(sessionId, keyName, time, fValue)
You are continuously adding to the ListBuffer with a "very large number of elements". This is chewing up all of your RAM. The data.iterator line is simply wrapping the massive ListBuffer blob inside of an iterator to provide each element one at a time, it's basically just a cast.
Your assumption that "it won't matter because ... of backpressure" is partially true that the akka Stream will process the TimeSeriesValue values reactively, but you are creating a large number of them even before you get to the Source constructor.
If you want this iterator to be "lazy", i.e. only produce values when needed and not consume memory, then make the following modifications (note: I broke apart the code to make it more readable):
def createTimeSeries(startTime: Time, snapShotCount : Int, sessionId : UUID, keyName : String) =
Iterator.range(1, snapShotCount)
.map(_ * 2)
.map(startTime plusSeconds _)
.map(t => TimeSeriesValue(sessionId, keyName, t, ThreadLocalRandom.current().nextLong()))
def sessionGenerator(countersPerSession : Int, sessionID : UUID) =
Iterator.range(1, countersPerSession)
.map(j => s"Encoder-${sessionId.toString}-Controller.CaptureFrameCount.$j")
.flatMap { keyName =>
createTimeSeries(DateTime.now(), snapShotCount, sessionID, keyName)
}
object UUIDIterator extends Iterator[UUID] {
def hasNext : Boolean = true
def next() : UUID = UUID.randomUUID()
}
def iterateOverIDs(range : Int) =
UUIDIterator.take(range)
.flatMap(sessionID => sessionGenerator(countersPerSession, sessionID))
Each one of the above functions returns an Iterator. Therefore, calling iterateOverIDs should be instantaneous because no work is immediately being done and de mimimis memory is being consumed. This iterator can then be passed into your Stream...

Yield an ArrayBuffer (or other mutable Collection type) from a for loop in Scala

Within the confines of a single matrix related method that works with large multidimensional arrays performance and memory usage are critical. We have a need to mutate elements of the array in place and thus are working with ArrayBuffer's (not Array's).
Given this use case is there a way to use for .. yield that would generate an ArrayBuffer (or at the least a mutable collection) instead of immutable?
The following code displays the intent - though it does not compile:
def classify(inarr: Array[Double], arrarr: Array[Array[Double]], labels: Array[String], K: Int): String = {
...
var diffmat: ArrayBuffer[ArrayBuffer[Double]] = for (row <- arrarr) yield {
(ArrayBuffer[Double]() /: (row zip inarr)) {
(outrow, cell) => outrow += cell._1 - cell._2
}
}
The compilation error is :
Expression Array[ArrayBuffer[Double]] does not conform to expected type ArrayBuffer[ArrayBuffer[Double]]
Ah... a case for the "magick sprinkles" of breakOut. Not only does it give you the collection type you want - it does it efficiently, without wasting an extra transformation.
object Foo {
import scala.collection.mutable.ArrayBuffer
import scala.collection.breakOut
val inarr: Array[Double] = Array()
val arrarr: Array[Array[Double]] = Array()
var diffmat: ArrayBuffer[ArrayBuffer[Double]] = (for (row <- arrarr) yield {
(ArrayBuffer[Double]() /: (row zip inarr)) {
(outrow, cell) => outrow += cell._1 - cell._2
}
})(breakOut)
}
The definitive writeup (IMHO) of this is Daniel Sobral's answer.

Scala: how to specify type parameter bounds implying equality?

Don't be put off by the long text, the points are quite trivial but require a bit of code to illustrate the problem. :-)
The Setup:
Say I would like to create a trait, here modeled as a Converter of some kind, that itself is generic but has a typed method convert() that returns an appropriately typed result object, say a Container[T]:
trait Converter {
def convert[T]( input: T ) : Container[T]
}
trait Container[T] // details don't matter
My question is about type constraints on methods, in particular for enforcing equality, and has two closely related parts.
Part 1: Say now that there was a specialized container type that was particularly suitable for array-based contents, like so:
object Container {
trait ForArrays[U] extends Container[Array[U]]
}
Given this possibility, I'd now like to specialize the Converter and in particular the return type of the convert() method, to the specialized Container.ForArrays type:
object Converter {
trait ForArrays extends Converter {
// the following line is rubbish - how to do this right?
def convert[E,T <: Array[E]]( input: T ) : Container.ForArrays[E]
}
}
So that I can do something like this:
val converter = new Converter.ForArrays { ... }
val input = Array( 'A', 'B', 'C' )
val converted : Container.ForArrays[Char] = converter.convert( input )
Basically I want Scala, if the type of converter is known to be Converter.ForArrays, to also infer the specialized return type of convert[Char]() as Container.ForArrays[Char], i.e. the matching container type plus the array type of the input. Is this or something like it possible and if so, how do I do it? E.g. how do I specify the type parameters / bounds on convert() (what is provided is just a stand-in - I have no idea how to do this). Oh, and naturally so that it still overrides its super method, otherwise nothing is gained.
Part 2: As a fallback, should this not be possible, I could of course push the convert function down into the Array-focused variant, like so:
trait Converter // now pretty useless as a shared trait
object Converter {
trait ForValues extends Converter {
def convert[T]( input: T ) : Container[T]
}
trait ForArrays extends Converter {
def convert[E]( input: Array[E] ) : Container.ForArrays[E]
}
}
OK. Now say I have an even more specialized Converter.ForArrays.SetBased that can internally use a set of elements of type E (the same as the 'input' array element type) to do some particular magic during the conversion. The set is now a parameter of the trait, however, like so:
case class SetBased( set: Set[F] ) extends Converter.ForArrays {
// the following line is also rubbish...
def convert[E = F]( input: Array[E] ) : Container.ForArrays[E] = {...}
}
Again, this is about the type parameters of the convert() method. The difficulty here is: how do I glue the type parameter of the class - F - to the type parameter of the method - E - such that the Scala compiler will only let the user call convert() with an array whose elements match the elements of the set? Example:
val set = Set( 'X', 'Y', 'Z' )
val converter = new Converter.ForArrays.SetBased( set )
val input = Array( 'A', 'B', 'C' )
val converted : Container.ForArrays[Char] = converter.convert( input )
No, you can't. For the same reason you can't narrow argument types or widen return types when overriding a method (but can narrow return type). Here is what you can do, however (for your fallback solution):
trait Converter {
type Constraint[T]
}
trait ForArrays extends Converter {
def convert[E]( input: Array[E] )( implicit ev : Constraint[T] ) : Container.ForArrays[E]
}
case class SetBased[F](set: Set[F]) extends Converter {
type Constraint[T] = T =:= F
def convert[E]( input: Array[E] )( implicit ev : E =:= F ) = ...
}
I'm going to assume that Container.ForArrays is a subclass of Container, without this, Converter.ForArrays.convert won't match the signature of the overridden Converter.convert
Try writing it something like this:
object Converter {
trait ForArrays extends Converter {
def convert[E] (input: Array[E]): Container.ForArrays[E]
}
}
Regarding your fallback solution. If two types are the same, then just use the same type param!
case class SetBased (set: Set[F]) extends Converter.ForArrays {
def convert (input: Array[F]): Container.ForArrays[F] = {...}
}

Resources