toString() in Kotlin - wrong output - kotlin

I have written some codes for printing out objects in array with toString()
but by using Option1 println(path.toString())
Output is [LRunningpath;#27973e9b
which is not what i want. Then i replace it with Option2 as follow
var i=0
for(i in 0 until path.size)
println(path[i].toString())
which is correct.
My questions are,
why Option 1 don't work?
what does the output in Option 1 mean?
any advice to avoid the same situation in the future?
Any hints is very appreciated. Thank you for the kindness.
my codes are as below:
fun main() {
println("Warming up")
val input1 = Runningpath("in Forest", 2000, "some houses")
val input2 = Runningpath("at lake", 1500, "a school")
val path = arrayOf(input1, input2 )
println(path.toString())
/* var i=0
for(i in 0 until path.size)
println(path[i].toString())
*/
}
class Runningpath(val name: String, val length: Int, val spot: String){
override fun toString(): String= "The Path $name ($length m) is near $spot"
}

Short answer: in most cases, it's better to use lists instead of arrays.
Arrays are mostly for historical reasons, for compatibility, and for implementing low-level data structures.  In Kotlin, you sometimes need them for interoperability with Java, and for handling vararg arguments.  But other than those, lists have many advantages.
The problem is that on the JVM, an array is very different from all other objects.  It has only the methods inherited from Object, and doesn't override those.  (And you can't create your own subclasses to override or add to them.)
In particular, it has the toString() method from Object.  That gives a code indicating the type — here [ for an array, L indicating that each element is a reference, Runningpath giving the type of reference, ; and # separators, and a hex representation of the array's hash code, which may be its address in memory or some other unique number.
So if you want some other way of displaying an array, you'll have to do it ‘manually’.
Other problems with arrays on the JVM result from them having run-time typing — they were part of Java long before generics were added, and interoperate badly with generics (e.g. you can't create an array of a generic type) — and being both mutable and covariant (and hence not type-safe in some cases).
Lists, like other Collections and data structures, are proper objects: they have methods such as toString(), which you can override; they can have generic type parameters; they're type-safe; they can have many implementations, including subclasses; and they're much better supported by the standard library and by many third-party libraries too.
So unless you have a particular need (vararg processing, Java interoperability, or a dire need to save every possible byte of memory), life will go easier if you use lists instead of arrays!

You can use the joinToString for that:
println(path.joinToString("\n"))
The joinToString() is actually available for both the List and the Array, but I'd recommend using the List as you'd have immutability and many other extensions on that, that will help your on manipulating the datas.

Related

Key-value store with only explicitly allowed keys

I need a key-value store (e.g. a Mapor a custom class) which only allows keys out of a previously defined set, e.g. only the keys ["apple", "orange"]. Is there anything like this built-in in Kotlin? Otherwise, how could one do this? Maybe like the following code?
class KeyValueStore(val allowedKeys: List<String>){
private val map = mutableMapOf<String,Any>()
fun add(key: String, value: Any) {
if(!allowedKeys.contains(key))
throw Exception("key $key not allowed")
map.put(key, value)
}
// code for reading keys, like get(key: String) and getKeys()
}
The best solution for your problem would be to use an enum, which provides exactly the functionality that you're looking for. According to the docs, you can declare an enum like so:
enum class AllowedKeys {
APPLE, ORANGE
}
then, you could declare the keys with your enum!
Since the keys are known at compile time, you could simply use an enum instead of String as the keys of a regular Map:
enum class Fruit {
APPLE, ORANGE
}
val fruitMap = mutableMapOf<Fruit, String>()
Instead of Any, use whatever type you need for your values, otherwise it's not convenient to use.
If the types of the values depend on the key (a heterogeneous map), then I would first seriously consider using a regular class with your "keys" as properties. You can access the list of properties via reflection if necessary.
Another option is to define a generic key class, so the get function returns a type that depends on the type parameter of the key (see how CoroutineContext works in Kotlin coroutines).
For reference, it's possible to do this if you don't know the set of keys until runtime. But it involves writing quite a bit of code; I don't think there's an easy way.
(I wrote my own Map class for this. We needed a massive number of these maps in memory, each with the same 2 or 3 keys, so I ended up writing a Map implementation pretty much from scratch: it used a passed-in array of keys — so all maps could share the same key array — and a private array of values, the same size. The code was quite long, but pretty simple. Most operations meant scanning the list of keys to find the right index, so the theoretic performance was dire; but since the list was always extremely short, it performed really well in practice. And it saved GBs of memory compared to using HashMap. I don't think I have the code any more, and it'd be far too long to post here, but I hope the idea is interesting.)

How can I define Map of String or Int in Kotlin?

Is there way to declare a Map that would accept both String and Int in Kotlin? Like:
var map: Map<String, String | Int>
There is no union type in Kotlin, so you can't directly express this.
A few options:
use TreeMap<String, Any>, which is the simplest of all, but it allows more types than just Int and String, and requires additional conversion boilerplate on the consumer side when accessing values.
use a custom sealed class to encapsulate your "Int or String" type, and use it in a regular TreeMap<String, IntOrString>. This will have some runtime overhead for wrapping/unwrapping the int/string objects for each insertion/access. Also, this puts the burden of (un)wrapping on the consumer side. That being said, maybe your domain can be better modeled with clearer names than Int or String, so it might actually improve the consumer's experience to define such types.
use a custom map type, with independent accessors for ints and strings, but backed by a single TreeMap<String, Any> behind the scenes. This has the advantage of encapsulating the logic and exposing a neat API for the consumers. If you extend TreeMap you will save some overhead as opposed to composition, but it shouldn't matter much.
I am wondering about the actual use case at hand, though. Usually the need for union types stems from using plain generic primitive types to represent meaningful domain data that could maybe better be expressed using more specific custom domain types.
Option 2 would therefore usually be my choice, but I would use a sealed class that actually represents my domain data instead of the generic "string or int".
You can use Any here, see this example:
import java.util.TreeMap
fun main() {
var map = TreeMap<String, Any>()
map.put("One", 1)
map.put("Two", "two")
println(map)
}
which outputs
{One=1, Two=two}
Please note:
This will allow more types than just the desired String and Int, because the Kotlin Docs state (...). Every Kotlin class has Any as a superclass..

Kotlin: Assert Immutability

I have class that internally maintains a mutable list, and I want to provide an immutable view on this list. Currently I'm using the following:
/**The list that actually stores which element is at which position*/
private val list: MutableList<T> = ArrayList()
/**Immutable view of [list] to the outside.*/
val listView: List<T> get() = list.toList()
First question: Can this be done easier
Second question: How can I test that listView is actually immutable. I guess reflections are necessary?
If you only needed the compile-time type to be immutable, you could simply upcast your list:
val listView: List<T> get() = list
(Though if you checked and downcast that to MutableList, you could make changes — and those would affect the original list.)
However, if you want full immutability, that's tricky.  I don't think there are any general-purpose truly immutable lists in the Kotlin stdlib.
Although List and MutableList look like two different types, in Kotlin/JVM they both compile down to the same type in the bytecode, which is mutable.  And even in Kotlin, while Iterable.toList() does return a new list, the current implementation* actually gives a MutableList that's been upcast to List.  (Though mutating it wouldn't change the original list.)
Some third-party libraries provide truly immutable collections, though; see this question.
And to check whether a List is mutable, you could use a simple type check:
if (listView is MutableList)
// …
No need to use reflection explicitly.  (A type check like that is considered to be implicit reflection.)
(* That can change, of course.  It's usually a mistake to read too much into the current code, if it's not backed up by the documentation.)

Why does the expert change MutableList to List?

I asked a question at How to design a complex class which incude some classes to make expansion easily in future in Kotlin? about how to design a complex class which incude some classes to make expansion easily in future in Kotlin.
A expert named s1m0nw1 give me a great answer as the following code.
But I don't know why he want to change MutableList to List at https://stackoverflow.com/posts/47960036/revisions , I can get the correct result when I use MutableList. Could you tell me?
The code
interface DeviceDef
data class BluetoothDef(val Status: Boolean = false) : DeviceDef
data class WiFiDef(val Name: String, val Status: Boolean = false) : DeviceDef
data class ScreenDef(val Name: String, val size: Long) : DeviceDef
class MDetail(val _id: Long, val devices: List<DeviceDef>) {
inline fun <reified T> getDevice(): T {
return devices.filterIsInstance(T::class.java).first()
}
}
Added
I think that mutableListOf<DeviceDef> is better than ListOf<DeviceDef> in order to extend in future.
I can use aMutableList.add() function to extend when I append new element of mutableListOf<DeviceDef>.
If I use ListOf<DeviceDef>, I have to construct it with listOf(mBluetoothDef1, mWiFiDef1, //mOther), it's not good. Right?
var aMutableList= mutableListOf<DeviceDef>()
var mBluetoothDef1= BluetoothDef(true)
var mWiFiDef1= WiFiHelper(this).getWiFiDefFromSystem()
aMutableList.add(mBluetoothDef1)
aMutableList.add(mWiFiDef1)
// aMutableList.add(mOther) //This is extension
var aMDetail1= MDetail(myID, aMutableList)
Sorry for not giving an explanation in the first place. The differences are explained in the docs.:
Unlike many languages, Kotlin distinguishes between mutable and immutable collections (lists, sets, maps, etc). Precise control over exactly when collections can be edited is useful for eliminating bugs, and for designing good APIs.
It is important to understand up front the difference between a read-only view of a mutable collection, and an actually immutable collection. Both are easy to create, but the type system doesn't express the difference, so keeping track of that (if it's relevant) is up to you.
The Kotlin List<out T> type is an interface that provides read-only operations like size, get and so on. Like in Java, it inherits from Collection<T> and that in turn inherits from Iterable<T>. Methods that change the list are added by the MutableList<T> interface. [...]
The List interface provides a read-only view so that you cannot e.g add new elements to the list which has many advantages for instance in multithreaded environments. There may be situations in which you will use MutableList instead.
I also recommend the following discussion:
Kotlin and Immutable Collections?
EDIT (added content):
You can do this is a one-liner without any add invocation:
val list = listOf(mBluetoothDef1, mWiFiDef1)

Scala Function vs Class Dichotomy

I have just started learning Scala. I am fairly comfortable with OO design, and less so with functional programming; although, I have been programming long enough that FP is not completely unnatural to me either. From the first day of my Scala adventure, I have had this, shall we say, unease with the apparent dialectic that is going on between OO and FP. Clearly, one can go all the way one way or the other. My first tendency was to see classes as sort of packages that hold the functions together that I want to pass around, which balances the scales towards functional side. I feel there has to be a better way of balancing the act. I am also unsure how to proceed with certain familiar situations under this scenario. For example, if I had the following (artificial) class:
class ValueGenerator {
def value() = {
"1"
}
def value(line: String) = {
line
}
}
in OO programming I would call the value with the proper signature when I needed, to get the result I need. The methods have the same signature, because they logically correspond to similar actions. In OO, I would pass around the object reference, and the methods that receive a ValueGenerator object would make the call to the right value depending on the situation. As far as I can see, at least it is my tendency, that in Scala the norm is to pass around the method. But in this case, although the methods do the same thing, they don't have the same signature, hence cannot be substituted for each other (or can they?). In other words, can the sender method decide the function to be sent regardless of the function's signature? This seems unlikely as the receiver would not know how to invoke it. What is the correct action in a situation like this. Or does one go with their gut instinct? Is there a rule of thumb you follow when it comes to OO vs FB?
As a side note, it was interesting to see that a friend of mine who is also learning Scala had the exact thoughts (or lack thereof) as me on this issue.
They don't have the same signature, and generally you want methods that don't have the same signature to have different names. Overloading buys you very little and costs you a lot (namely, type inference and implicit resolution).
That said, they cannot be substituted for one another since they don't have the same type. If you would convert these methods to functions, one would have type Function0[String] and the other would have type Function1[String, String].
In the code you've provided, there is no reason you need to have two separate method signatures:
class ValueGenerator {
def value(line: String = "1") = {
line
}
}
REPL session:
scala> new ValueGenerator()
res1: ValueGenerator = ValueGenerator#fa88fb
scala> res1.value("Foo")
res2: String = Foo
scala> res1.value()
res3: String = 1
Keep in mind you can only do this with methods. Functions don't support default arguments:
scala> val f = res1.value(_)
f: (String) => String = <function1>
scala> f("Bar")
res5: String = Bar
scala> f()
***Oops***
scala> val f = (line: String) => line
f: (String) => String = <function1>
scala> val f = (line: String = "1") => line
***Oops***
As far as I can see, at least it is my tendency, that in Scala the norm is to pass around the method.
I doubt that that's the norm (why do you think so?) or that there's even a norm for this at all in Scala.
But in this case, although the methods do the same thing, they don't have the same signature, hence cannot be substituted for each other (or can they?). In other words, can the sender method decide the function to be sent regardless of the function's signature?
They cannot be substituted for each other because they have different signatures, so they have different types.
The scenario that you describe sounds like a perfect fit for the OO way of doing things: just pass the ValueGenerator object and let the client decide which method to call in that object.