Listener not reacting to second call - kotlin

I'm trying to learn Kotlin and I'm writing code to test and confirm my understanding. In the result of the following code, I expect to see "Property age changed from 37 to 38" near the end. Why am I not seeing that.
I tried writing the increment to age as age.plus initially, but that made the same result.
package ch07.ImplementingDelegatedProperties
import java.beans.PropertyChangeSupport
import java.beans.PropertyChangeListener
open class PropertyChangeAware {
protected val changeSupport = PropertyChangeSupport(this)
fun addPropertyChangeListener(listener: PropertyChangeListener) {
changeSupport.addPropertyChangeListener(listener)
}
fun removePropertyChangeListener(listener: PropertyChangeListener) {
changeSupport.removePropertyChangeListener(listener)
}
}
class Person(
val name: String, age: Int?, salary: Int
)
: PropertyChangeAware()
{
var age: Int? = age
set(newValue) {
println("age changed")
val oldValue = field
field = newValue
changeSupport.firePropertyChange(
"age", oldValue, newValue)
}
var salary: Int = salary
set(newValue) {
val oldValue = field
field = newValue
changeSupport.firePropertyChange(
"salary", oldValue, newValue)
}
operator fun plus (older: Int) :Person {
println("age changed by operator")
val oldValue = age
val newValue = (oldValue?: 0) + older
changeSupport.firePropertyChange( // don't know why this dosn't fire repeatedly
"age", oldValue, newValue)
println("age chg by operator, $oldValue -> $newValue")
this.age = (oldValue?: 0) + older
// this._attributes = _attributes
return Person(name, age = age, salary = salary)
}
}
fun main(args: Array<String>) {
var p = Person("Dmitry", 34, 2000)
p.addPropertyChangeListener(
PropertyChangeListener { event ->
println("Property ${event.propertyName} changed " +
"from ${event.oldValue} to ${event.newValue}")
}
)
println(p.age)
p.age = 35
println(p.age.toString())
p.age = 36
println(p.age.toString())
p = p + 1
println(p.age.toString())
p = p + 1
println(p.age.toString())
p.salary = 2100
}
Actual results:
34
age changed
Property age changed from 34 to 35
35
age changed
Property age changed from 35 to 36
36
age changed by operator
Property age changed from 36 to 37
age chg by operator, 36 -> 37
age changed
Property age changed from 36 to 37
37
age changed by operator
age chg by operator, 37 -> 38
age changed
38
Expected results:
34
age changed
Property age changed from 34 to 35
35
age changed
Property age changed from 35 to 36
36
age changed by operator
Property age changed from 36 to 37
age chg by operator, 36 -> 37
age changed
Property age changed from 36 to 37
37
age changed by operator
age chg by operator, 37 -> 38
age changed
Property age changed from 37 to 38 << This line expected but not appearing
38

The problem is that, at the end of your plus function, you create a brand new Person object (which copies the name and salary and increases the age) but importantly, it has a new changeSupport object which you haven't run addPropertyChangeListener on.
It looks like PropertyChangeSupport allows you to have no listeners defined, so won't error or give you a clue that there is not listener

Related

Grade book program comparing test scores

I have a gradebook, given two maps of test scores, update the students' grades only if they did better on the second exam. Now i need to enter second test scores into terminal and get final total from 2 tests. My problem is that i can only initialize score, but i need it in terminal. How can i do this?
class student{
lateinit var testScore: Any
var testScores: Int = 100
}
import java.util.*
fun main() {
val Andrew = student()
val Tom = student()
val Tobey = student()
Andrew.testScores = 67
print("Andrew's test score ")
println(Andrew.testScores)
Tom.testScores = 65
print("Tom's test score ")
println(Tom.testScores)
Tobey.testScores = 76
print("Tobey's test score ")
println(Tobey.testScores)
var input: String
var score1: Double
var score2: Double
var score3: Double
var repeat: Char
val keyboard = Scanner(System.`in`)
println(
"Enter second test's scores "
)
if(Andrew.testScores < score1){
var valid = false
Andrew.testScores = score1.toInt()
}
if(Tom.testScores < score2){
Tom.testScores = score2.toInt()
}
if(Tobey.testScores < score3){
Tobey.testScores = score3.toInt()
}
print("Andrew's test score ${Andrew.testScores} ")
print("Tom's test score ${Tom.testScores} ")
print("Tobey's test score ${Tobey.testScores} ")
do {
print("Enter score #1: ")
score1 = keyboard.nextDouble()
print("Enter score #2: ")
score2 = keyboard.nextDouble()
print("Enter score #3: ")
score3 = keyboard.nextDouble()
println(
("Would you enter new scores?")
)
print("Enter Y for yes or N for no: ")
input = keyboard.next()
repeat = input[0]
} while (repeat == 'Y' || repeat == 'y')
}

Basic Kotlin , Basic Kotlin Android Development

> 1 package com.linecorp.exam
> 2
> 3 import android.os.Bundle
> 4 import android.widget.TextView
> 5 import android.app.Activity
> 6 import android.graphics.Color
> 7 import android.view.Gravity
> 8 import android.view.View
> 9 import android.view.ViewGroup
> 10 import android.widget.BaseAdapter
> 11 import android.widget.ListView
> 12
> 13 class MainActivity : Activity() {
> 14
> 15 enum class taskstate {
> 16 todo,
> 17 done
> 18 }
> 19
> 20 var tasklist = mutableListOf<Pair<String, taskstate>>()
> 21
> 22 private lateinit var myadapter: Myadapter
> 23
> 24 override fun onCreate(savedInstanceState: Bundle?) {
> 25 super.onCreate(savedInstanceState)
> 26 setContentView(R.layout.activity_main)
> 27
> 28 myadapter = Myadapter()
> 29 val listView = findViewById<ListView>(R.id.list_view)
> 30 listView.adapter = myadapter
> 31
> 32 tasklist.clear()
> 33 var i = 0
> 34 todoRepository.instance.fetch_all().forEach { t ->
> 35 tasklist.add(i++, t)
> 36 myadapter.notifyDataSetChanged()
> 37 }
> 38 }
> 39
> 40 override fun onDestroy() {
> 41 tasklist.clear()
> 42 }
> 43
> 44 inner class Myadapter : BaseAdapter() {
> 45
> 46 private lateinit var convertView: View
> 47
> 48 override fun getCount(): Int {
> 49 return tasklist.size
> 50 }
> 51
> 52 override fun getItem(position: Int): Any {
> 53 val li = tasklist.filter { it.second == taskstate.todo } +
> 54 tasklist.filter { it.second == taskstate.done }
> 55 return li[position]
> 56 }
> 57
> 58 override fun getItemId(position: Int): Long {
> 59 return 0
> 60 }
> 61
> 62 override fun getView(position: Int, convertView: View?, container: ViewGroup?): View {
> 63 this.convertView = if (convertView == null) {
> 64 layoutInflater.inflate(R.layout.list_item, container, false)
> 65 } else {
> 66 convertView
> 67 }
> 68
> 69 val i = getItem(position) as Pair<String, taskstate>
> 70 this.convertView.findViewById<TextView>(R.id.item_label)
> 71 .apply {
> 72 when (i.second) {
> 73 taskstate.todo -> {
> 74 setText("TODO")
> 75 setBackgroundColor(Color.YELLOW)
> 76 }
> 77 else -> {
> 78 setText("DONE")
> 79 }
> 80 }
> 81 }
> 82 this.convertView.findViewById<TextView>(R.id.item_text)
> 83 .setText(i.first)
> 84
> 85 return convertView!!
> 86 }
> 87 }
> 88 }`enter code here`
This was a question I got when I appeared for an test. Unfortunately I failed :) The question was how to improve this Kotlin Android code and add necessary comments if needed. (please dont consider this line ipsum dfgsdndd gfnjfn vjfnvkf fjnvkfv vnkdkvd dndk. sds dshdsd shdahd sdiauhd basudsua saudhaus sahdsuahd ashdoahsd shdoahd ashdosahd asdhoaishd )
The problem here is you are returning total if s1<s2 while that's not the case. Even if you find one such case, that's not the end of string, you should continue processing. Instead of returning, you should increment i to i+2 as you have already processed i+1. Since you can't do such increment in between a for loop, so you will have to go with a while loop.
fun romanToInt(s: String): Int {
val map = mapOf('I' to 1, 'V' to 5, 'X' to 10, 'L' to 50, 'C' to 100, 'D' to 500, 'M' to 1000)
var total = 0
var i = 0
while (i < s.length) {
val current = map[s[i]]!!
val next = if (i != s.lastIndex) map[s[i + 1]]!! else 0
if (current >= next) {
total += current
i++
} else {
total += next - current
i += 2
}
}
return total
}

sigsegv compilation error of simple kotlin code

Following code generates error which looks like an error in compiler, its has nothing to do with the kotlin code, or maybe I am missing something? I have JDK error on macos and some more informative error (like pasted at the end of this post) from online compiler. How can I fix it?
Code: https://pl.kotl.in/CfdXHeDyn
import kotlin.math.pow
fun calculateNumberOfContainers(data: String): Int {
val containerSizes = mutableListOf<Int>()
data.lines().forEach { containerSizes.add(it.toInt()) }
var foundCorrect = 0
val maxSubSets = (2.0).pow(20).toULong()
for (n in 0UL until maxSubSets) {
var total = 0
for (k in 0 until 20) {
val mask = 1UL shl k
if ((mask and n) != 0UL) {
total += containerSizes[k]
if (total > 150)
break
}
}
if (total == 150)
foundCorrect++
}
return foundCorrect
}
fun runcode() {
val data =
"""
33
14
18
20
45
35
16
35
1
13
18
13
50
44
48
6
24
41
30
42
""".trimIndent()
calculateNumberOfContainers(data)
}
fun main() {
runcode()
}
Error:
Exception in thread "main" com.fasterxml.jackson.core.JsonParseException: Unexpected character ('#' (code 35)): was expecting double-quote to start field name
at [Source: (String)"{#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007fc646ef2eba, pid=1900, tid=0x00007fc6307f7700
#
# JRE version: OpenJDK Runtime Environment (8.0_201-b09) (build 1.8.0_201-b09)
# Java VM: OpenJDK 64-Bit Server VM (25.201-b09 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# V [libjvm.so+0x382eba]
#
# Core dump written. Default location: /var/task/core or core.1900
#
# An error report file with more information is saved as:
# /tmp/"[truncated 195 chars]; line: 1, column: 3]
at com.fasterxml.jackson.core.JsonParser._constructError (JsonParser.java:1851)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError (ParserMinimalBase.java:707)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar (ParserMinimalBase.java:632)
Update:
it works with 1.4.30, fails with 1.5.21, so its a bug in compiler
I changed from Unsigned Long to Unsigned Int and problem went away, code after changes looks as follows:
https://pl.kotl.in/XedacixZK
import kotlin.math.pow
fun calculateNumberOfContainers(data: String): Int {
val containerSizes = mutableListOf<Int>()
data.lines().forEach { containerSizes.add(it.toInt()) }
var foundCorrect = 0
val maxSubSets = (2.0).pow(20).toUInt()
for (n in 0U until maxSubSets) {
var total = 0
for (k in 0 until 20) {
val mask = 1U shl k
if ((mask and n) != 0U) {
total += containerSizes[k]
if (total > 150)
break
}
}
if (total == 150)
foundCorrect++
}
return foundCorrect
}
fun runcode() {
val data =
"""
33
14
18
20
45
35
16
35
1
13
18
13
50
44
48
6
24
41
30
42
""".trimIndent()
print(calculateNumberOfContainers(data))
}
fun main() {
runcode()
}

how to write a DSL without imports or val using kotlin

I'm trying to create a kotlin DSl following the example here https://github.com/zsmb13/VillageDSL
They write :
val v = village {
house {
person {
name = "Emily"
age = 31
}
person(name = "Hannah") {
age = 27
}
person("Alex", 21)
person(age = 17, name = "Daniel")
}
}
I would like to know if there is way to write it like with gradle, like this :
village {
house {
person {
name = "Emily"
age = 31
}
person(name = "Hannah") {
age = 27
}
person("Alex", 21)
person(age = 17, name = "Daniel")
}
}
And autogenerate imports (like in gradle).
I was thinking to wrap the file programmatically with a wildcard import followed by val result =, but it could be leaky and buggy, is there a better way ?
You may consider Kotlin Scripting for that. e.g. https://github.com/Kotlin/KEEP/blob/master/proposals/scripting-support.md
or
https://github.com/holgerbrandl/kscript

Remove item of record without knowing all item

I have this simulation:
init : (Model, Cmd Msg)
init = ({ dog = List Dog }, Cmd.none)
type alias Dog =
{ name : String
, age : Int
, price : Float
, extra = List Extra
}
type alias Extra =
{ allergies : List String
, wishes : List String
}
[{ name = "Hot"
, age = 1
, price = 300.5
, extra = [{...}]
},
{ name = "Dog"
, age = 3
, price = 150.0
, extra = [{...}]
}]
And I want to remove only 'extras' of Dog, in determined part of the code:
[{ name = "Hot"
, age = 1
, price = 300.5
},
{ name = "Dog"
, age = 3
, price = 150.0
}]
I can do this by mapping the entire list and generating a new one by removing 'extra' occurrence:
removeExtraOfDogs dogList =
(dogList |> List.map (\dog ->
{ name = dog.name
, age = dog.age
, price = dog.price
}
))
but I want to make it dynamic to just pass the extra to remove, without having to know what variables there are in the type and recreate it
Elm used to have this feature but it was removed a while ago. But, based on your use case described in a comment, I don't think you need this feature. You can instead use extensible record feature of Elm to allow passing different records into a function as long as they contain a fixed set of fields.
For example, let's say you have two types with name and age fields and having an extra incompatible field:
type alias Foo = { name : String, age : Int, extra : List String }
type alias Bar = { name : String, age : Int, extra : Int }
You can define a function that takes a record with a name field of type String and age of type Int and any extra fields:
encode : { r | name : String, age : Int } -> String
encode record = record.name ++ "," ++ toString record.age
You'll can now pass both Foo and Bar to this function because they both satisfy the requirements of the type signature.