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

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.

Related

Update random class attribute in Kotlin

I have a class with some attributes:
class DonutBox {
var glaze: Int = 0
var chocolate: Int = 0
var maple: Int = 0
var etc: Int = 0
}
fun addDonuts() {
val omNom = DonutBox()
}
How can I increment a random attribute of the instantiated class?
For instance, if the randomly selected attribute is chocolate, then effectively:
omNom.chocolate += 1
Because Kotlin's properties are statically declared, and you want to use them dynamically, most of the methods to do that will involve reflection, which can get pretty messy and difficult to understand.
When you want dynamic data, it's probably better to use a map:
val donutBox = mutableMapOf(
"glaze" to 0,
"chocolate" to 0,
"maple" to 0,
"etc" to 0,
)
val randomKey = donutBox.keys.random()
donutBox[randomKey] = donutBox.getValue(randomKey) + 1
println(donutBox)
Output:
{glaze=0, chocolate=0, maple=1, etc=0}
That said, if you really want to use reflection, you can do it like this:
data class DonutBox(
var glaze: Int = 0,
var chocolate: Int = 0,
var maple: Int = 0,
var etc: Int = 0,
)
fun addDonuts() {
val omNom = DonutBox()
val randomProperty = omNom::class.declaredMemberProperties.random() as KMutableProperty1<DonutBox, Int>
val existing = randomProperty.get(omNom)
randomProperty.set(omNom, existing + 1)
println(omNom)
}
fun main() {
addDonuts()
addDonuts()
addDonuts()
}
Output:
DonutBox(glaze=0, chocolate=1, maple=0, etc=0)
DonutBox(glaze=0, chocolate=0, maple=0, etc=1)
DonutBox(glaze=0, chocolate=1, maple=0, etc=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.

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

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
}

Assigning values to ArrayList using mapTo

Previously I was using this code:
private val mItems = ArrayList<Int>()
(1..item_count).mapTo(mItems) { it }
/*
mItems will be: "1, 2, 3, 4, 5, ..., item_count"
*/
Now, I am using a class instead of Int, but the class has Int member with name id.
class ModelClass(var id: Int = 0, var status: String = "smth")
So how can I use this method to fill the ArrayList in similar way?
//?
private val mItems = ArrayList<ModelClass>()
(1..item_count).mapTo(mItems) { mItems[position].id = it } // Something like this
//?
From the mapTo documentation:
Applies the given transform function to each element of the original collection and appends the results to the given destination.
Therefore, you just need to return the elements you want:
(1..item_count).mapTo(mItems) { ModelClass(it) }
If you are OK with any MutableList (which is often ArrayList or similar):
val mItems1 = MutableList(item_count) { i -> i }
val mItems2 = MutableList(item_count) { ModelClass(it) }

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.