how to link variables so when i modify one of them both are modified? or just the top level one - variables

I have 3 variables A,b and c in a class called ONE
var a = 0
var b = 0
var c = 0
that class(class ONE) is abstract and is used by 3 classes(TWO, THREE, FOUR). the variable selected changes by using a when statement.
var chosenVariable:Long
chosenVariable= when (sign){
1-> a
2-> b
3-> c
else -> a
}
note that sign is what the user inputs to decide which variable is chosen.
my question is. when i modify chosenVariable I want it to change whatever variable it was set a, b or c.
is this possible? I thought it might be called instancing, but I can't seem to come up with anything searching that way. I think i need to do it somehow with a setter and getter?

You can use KMutableProperty0<> class to hold reference to primitive variables:
var chosenVariable: KMutableProperty0<Long> = when (sign) {
1-> ::a
2-> ::b
3-> ::c
else -> ::a
}
// set value
chosenVariable.set(7)
It is currently available only for global variables. Here is some useful info.

If you mean chosenVariable is the sign, either:
there can be another function to set/get chosen variables (a, b, c), such as:
var chosenVariable : Long = 0 // init value
fun set ( value : Int ) {
when ( chosenVariable ) {
// 1 -> a = value
2 -> b = value
3 -> c = value
else -> a = value
}
}
fun get ( ) {
return when ( chosenVariable ) {
// 1 -> a
2 -> b
3 -> c
else -> a
}
}
or maybe use MutableMap instead:
val variables = mutableMapOf <Long /* sign */, Int /* value */> (
1 to 0, // a
2 to 0, // b
3 to 0, // c
)
// still with getter/setter like before, but with map
fun get ( ) = variables [ chosenVariable ]
fun set ( value : Int ) {
variables [ chosenVariable ] = value
}

Related

problems with index of array

I'm writing a function that allows you to remove certain numbers from an int arraylist.
My code
for (i in 1 until 4) {
divider = setDivider(i)
for(index in 0 until numbers.size){
if(index <= numbers.size){
if (numbers[index] % divider == 0 && !isDone) {
numbers.removeAt(index)
}
}else{
isDone = true
}
}
if(isDone)
break
}
the function to set the divider
fun setDivider(divider: Int): Int {
when (divider) {
1 -> return 2
2 -> return 3
3 -> return 5
4 -> return 7
}
return 8
}
I do not know why the ide is giving me the error Index 9 out of bounds for length 9.
Author explained in the comments that the goal is to remove all numbers that are divisible by 2, 3, 5 and 7.
It can be achieved much easier by utilizing ready to use functions from stdlib:
val dividers = listOf(2, 3, 5, 7)
numbers.removeAll { num ->
dividers.any { num % it == 0 }
}
It removes elements that satisfy the provided condition (is divisible) for any of provided dividers.
Also, it is often cleaner to not modify a collection in-place, but to create an entirely new collection:
val numbers2 = numbers.filterNot { num ->
dividers.any { num % it == 0 }
}

Mutating a value in an array list in Zig

Noob question:
I want to mutate a value that exists in an array list. I initially tried to just grab the indexed item and directly change its field value.
const Foo = struct {
const Self = #This();
foo: u8,
};
pub fn main() anyerror!void {
const foo = Foo {
.foo = 1,
};
const allocator = std.heap.page_allocator;
var arr = ArrayList(Foo).init(allocator);
arr.append(foo) catch unreachable;
var a = arr.items[0];
std.debug.warn("a: {}", .{a});
a.foo = 2;
std.debug.warn("a: {}", .{a});
std.debug.warn("arr.items[0]: {}", .{arr.items[0]});
//In order to update the memory in [0] I have to reassign it to a.
//arr.items[0] = a;
}
However, the result is unexpected to me:
a: Foo{ .foo = 1 }
a: Foo{ .foo = 2 }
arr.items[0]: Foo{ .foo = 1 }
I would have thought that arr.items[0] would now equal Foo{ .foo = 2 }.
This is probably because I misunderstand slices.
Does a not point to the same memory as arr.items[0]?
Does arr.items[0] return a pointer to a copied item?
var a = arr.items[0];
That is making a copy of the item in arr.items[0].
If you want a reference, write var a = &arr.items[0]; instead.

Kotlin - Convert while loop to functional style

I have the following Kotlin function:
fun func(n: Int): Int {
var count = 1
var m = n
while(m != 1) {
m = if(m.isOdd()) 3 * m + 1 else m / 2
count++
}
return count
}
I would like to write that simple algorithm in a "functional" style, using Kotlin's operators like map(), count(), etc. The closest thing I could come up with was this:
fun func(n: Int): Int {
return n.toList()
.map{ if(it.isOdd()) 3*it+1 else it/2 }
.takeWhile { it != 1 }
.count()
}
Obviously, the above code does not work because map is executed only once, but you get the idea of what I am trying to achieve.
PS: toList() is just an extension function that converts an int to a list containing that int:
fun Int.toList() = listOf(this)
Since you do not know how many items there will be, you can construct a (possibly infinite) sequence where each item is calculated based on the previous one, then limit it with your condition it != 1 and count how many items there are:
return generateSequence(n) { if (it.isOdd()) 3 * it + 1 else it / 2 }
.takeWhile { it != 1 }
.count()
Here, generateSequence(n) { ... }, constructs a Sequence<Int> that has n for its first element, and each of the following elements is calculated by the code passed as a lambda (it is called on the previous element, and only when another item is queried, i.e. lazily).

How to merge node in yaml-cpp

I have two node object, like this:
school:
grade:
class:
name: bob
school:
grade:
class:
age: 18
I want to merge it, the result like this:
school:
grade:
class:
name: bob
age: 18
How to merge it? when the node size and depth do not kown.
Here is my attempt:
#include <yaml-cpp/yaml.h>
inline const YAML::Node & cnode(const YAML::Node &n) {
return n;
}
YAML::Node merge_nodes(YAML::Node a, YAML::Node b)
{
if (!b.IsMap()) {
// If b is not a map, merge result is b, unless b is null
return b.IsNull() ? a : b;
}
if (!a.IsMap()) {
// If a is not a map, merge result is b
return b;
}
if (!b.size()) {
// If a is a map, and b is an empty map, return a
return a;
}
// Create a new map 'c' with the same mappings as a, merged with b
auto c = YAML::Node(YAML::NodeType::Map);
for (auto n : a) {
if (n.first.IsScalar()) {
const std::string & key = n.first.Scalar();
auto t = YAML::Node(cnode(b)[key]);
if (t) {
c[n.first] = merge_nodes(n.second, t);
continue;
}
}
c[n.first] = n.second;
}
// Add the mappings from 'b' not already in 'c'
for (auto n : b) {
if (!n.first.IsScalar() || !cnode(c)[n.first.Scalar()]) {
c[n.first] = n.second;
}
}
return c;
}
For non-scalar keys I have opted to ignore node equivalence. Please note that this version does not modify a. It returns a new map c which is a merge of b into a. Values from b will replace identically keyed non-map values from a in the c map.
I found an issue with md5i's answer that it doesn't merge the second node's unique sub nodes. My fix was calling the function again in the for loop of node b (which I renamed the override node). I also made everything const, because I'm not editing anything here, and so I don't have to cast it. I'm also reinforcing the fact the second node is overriding the other.
const YAML::Node mergeNodes(const YAML::Node& defaultNode, const YAML::Node& overrideNode)
{
if (!overrideNode.IsMap()) {
// If overrideNode is not a map, merge result is overrideNode, unless overrideNode is null
return overrideNode.IsNull() ? defaultNode : overrideNode;
}
if (!defaultNode.IsMap()) {
// If defaultNode is not a map, merge result is overrideNode
return overrideNode;
}
if (!defaultNode.size()) {
return YAML::Node(overrideNode);
}
// Create a new map 'newNode' with the same mappings as defaultNode, merged with overrideNode
auto newNode = YAML::Node(YAML::NodeType::Map);
for (auto node : defaultNode) {
if (node.first.IsScalar()) {
const std::string& key = node.first.Scalar();
if (overrideNode[key]) {
newNode[node.first] = mergeNodes(node.second, overrideNode[key]);
continue;
}
}
newNode[n.first] = node.second;
}
// Add the mappings from 'overrideNode' not already in 'newNode'
for (auto node : overrideNode) {
if (!node.first.IsScalar()) {
const std::string& key = node.first.Scalar();
if (defaultNode[key]) {
newNode[node.first] = mergeNodes(defaultNode[key], node.second);
continue;
}
}
newNode[node.first] = node.second;
}
return YAML::Node(newNode);
}
This will probably not do the N thingy any favours, but it will take the nodes from node b/overrideNode even if they have no instance in node a/defaultNode.

A function inside a class modifies prototype instead of just returning an object

I have this code in LiveScript (1.1.1):
class A
b = -> { a: 1 b: 2 }
It compiles into this:
var A;
A = (function(){
A.displayName = 'A';
var b, prototype = A.prototype, constructor = A;
b = function(){
return prototype.a = 1, prototype.b = 2, prototype;
};
function A(){}
return A;
}());
Why does b() modify prototype? I expected it to just return a { a: 1, b: 2 } associative array.
It's because of this :
https://github.com/gkz/LiveScript/commit/d49b3ee8e8e2d5d7b9f128fa98c210b582e095fe
Which should probably be removed then, mmh.