Assign an array to a property in a Chapel Class - list-comprehension

Here is a Python-like pattern I need to re-create in Chapel.
class Gambler {
var luckyNumbers: [1..0] int;
}
var nums = [13,17,23,71];
var KennyRogers = new Gambler();
KennyRogers.luckyNumbers = for n in nums do n;
writeln(KennyRogers);
Produces the run-time error
Kenny.chpl:8: error: zippered iterations have non-equal lengths
I don't know how many lucky numbers Kenny will have in advance and I can't instantiate Kenny at that time. That is, I have to assign them later. Also, I need to know when to hold them, know when to fold them.

This is a good application of the array.push_back method. To insert lucky numbers one at a time you can do:
for n in nums do
KennyRogers.luckyNumbers.push_back(n);
You can also insert the whole array in a single push_back operation:
KennyRogers.luckyNumbers.push_back(nums);
There are also push_front and insert methods in case you need to put elements at the front or at arbitrary positions in the array.
I don't think I can help on when to hold them or when to fold them.

A way to approach this that simply makes things the right size from the start and avoids resizing/rewriting the array is to establish luckyNumbers in the initializer for Gambler. In order to do this without resizing, you'll need to declare the array's domain and set it in the initializer as well:
class Gambler {
const D: domain(1); // a 1D domain field representing the array's size
var luckyNumbers: [D] int; // declare lucky numbers in terms of that domain
proc init(nums: [?numsD] int) {
D = numsD; // make D a copy of nums's domain; allocates luckyNumbers to the appropriate size
luckyNumbers = nums; // initialize luckyNumbers with nums
super.init(); // mark the initialization of fields as being done
}
}
var nums = [13,17,23,71];
var KennyRogers = new Gambler(nums);
writeln(KennyRogers);

Related

Why can't I use removeAll on a list of objects?

I am trying to create an app that let's you type in what you want to eat and drink. It calculates all of that and then when you press the print button, I want it to count how often each item's in the list and give it back like this:
"9x Juice /n
5x Steaks /n
4x Salads"
The drinks and foods are objects in the new class Edibles:
class Edibles(val name: String, val price: Double):Serializable {
}
I track all of the objects in the MutableList order and can access the different members of the list and their attributes, but when I try to removeAll duplicates in my list, android studio complains and I don't know how to fix it.
My try to calculate how many members are in the list order:
var totalOrder = ""
for(i in order){
var number = order.count {it == order[0]}
totalOrder = totalOrder + "$number" + "x" + order[0].name + "\n"
order.removeAll(order[0])
}
The problem as far as I saw so far is, that Edibles doesn't have the interface Collection and when I try to implement that, it wants me to override a bunch of functions where I don't know what to do with it...
If anyone has an explanation or even a fix or an idea on how to do it differently, I would be very grateful
removeAll is meant to take a list or a predicate, not a single element. If you convert your element to a predicate checking for equality, it will remove all elements equal to that one.
order.removeAll { it == order[0] }
However, you'll also need to remember rule number one of iteration: Never delete while iterating. So what you really want to do is accumulate all of the "deletion" candidates into a list and then delete them after-the-fact.
In fact, what you're doing here can be done without mutating the list at all, using a built-in list combinator called groupBy.
var totalOrder = ""
for (entry in order.groupBy { it }) {
val item = entry.key
val count = entry.value.size
totalOrder += "${count}x${item.name}\n"
}
You're not allowed to mutate a collection while iterating it in a for loop anyway. One way to remove duplicates would be to create a temporary MutableSet and compare each item to it in a removeAll operation. removeAll takes a lambda predicate that is called on each item and the Boolean you return from the predicate. When you call add on a MutableSet, it returns a Boolean to tell you if the item already was in the set, so you can remove duplicates with the following.
Assuming you just want to compare names of items to determine if they are duplicates, you can create a MutableSet<String>.
with (mutableSetOf<String>()) {
order.removeAll { add(it.name) }
}

CP - OPL slicing input array

I think I need some help with the OPL language :/
My code is the following:
using CP;
int NbMchs = ...;
range Mchs = 0..NbMchs-1;
tuple Mode {
int opId;
int mch;
int pt;
};
{Mode} Modes = ...;
// Not Working...
int test[m in Mchs] = all(md in Modes: md.mch == m) md.opId;
What I want to do is to extract m 1D arrays from the Modes structure containing just the opId field of the tuple. Each test[m] array has to contain it's corresponding elements: that is the opId field of the tuple md where md.mch =m.
The error that I get from the above code is "Cannot use type int[] for int". It seems like the right hand side of the above function is returning a single integer, but I was thinking that the all() operator is the one that I can use to do the job.
Thanks in advance
In the general case, the number of opId depends on the machine m so you cannot really have a 2-D array here. I would use an array of sets:
{int} test[m in Mchs] = { md.opId | md in Modes: md.mch == m };
Note that it assumes that you only have one mode per opId,mch.

In my node application, why the same thing gives the different outputs?

var b = "pp.specifications.full_specs.";
var c = arr[i];
here the value of arr[i] is Memory
var a = b+c;
console.log(a);
it prints pp.specifications.full_specs.Memory on console
but when I use
console.log(pp.specifications.full_specs.Memory);
then prints an json object as:
{ Series: 'Inspiron',
Model: 'A562103SIN9',
Utility: 'Everyday Use',
OS: 'Windows 10 Home (64-bit)',
Dimensions: '274.73 x 384.9 x 25.44 mm',
Weight: '2.62 Kg',
Warranty: '1 Year Onsite Warranty' }
whenever the value of a contains pp.specifications.full_specs.Memory;
So what is the reason for getting different outputs?
There's a elementary difference between
console.log(pp.specifications.full_specs.Memory);
and
console.log("pp.specifications.full_specs.Memory");
Note the quotes!
So the expression: console.log(pp.specifications.full_specs.Memory); can be read from left to right:
Print to the output value of pp.specifications.full_specs.Memory and this is a value of pp object after taking its property specifications and then its property full_specs etc.
And the "pp.specifications.full_specs.Memory" means only a piece of text.
What is happening in your code should now be clearer:
// B is piece of text
var b = "pp.specifications.full_specs.";
// C is some other value - let's say also textual one
var c = arr[i]
// So b+c will mean add text to some other text
// It's expected that the result of such operations is concatenated text
// So then console.log(b+c) will mean
// Print the concatenated text from b and c
// And it's just plain text
console.log(b+c);
//It's the same as:
console.log("pp.specifications.full_specs.Memory");
// And this one means print some specific object attributes
// which is different operation!
console.log(pp.specifications.full_specs.Memory);
If you want to access objects by text you can do the following:
var d = eval(b+c);
It's pretty dangerous and eval should be avoided but I just wanted to demonstrate the basic idea. Eval executes strings as if they were code.
So string "pp.specifications.full_specs.Memory" will be evaluates (yep!) as value of the actual object.
As The eval can execute anything it should be always avoided and moreover it's superslow!
Instead if you want to access some property of pp basic on some text input you can do:
pp['specifications']['full_specs']['Memory']
As the pp.x notation is equivalent to expression: pp['x']
I hope my answer will help you understand Javascript mechanisms better :)

Inconsistencies when using UnsafeMutablePointer with String or Character types

I'm currently trying to implement my own DynamicArray data type in Swift. To do so I'm using pointers a bit. As my root I'm using an UnsafeMutablePointer of a generic type T:
struct DynamicArray<T> {
private var root: UnsafeMutablePointer<T> = nil
private var capacity = 0 {
didSet {
//...
}
}
//...
init(capacity: Int) {
root = UnsafeMutablePointer<T>.alloc(capacity)
self.capacity = capacity
}
init(count: Int, repeatedValue: T) {
self.init(capacity: count)
for index in 0..<count {
(root + index).memory = repeatedValue
}
self.count = count
}
//...
}
Now as you can see I've also implemented a capacity property which tells me how much memory is currently allocated for root. Accordingly one can create an instance of DynamicArray using the init(capacity:) initializer, which allocates the appropriate amount of memory, and sets the capacity property.
But then I also implemented the init(count:repeatedValue:) initializer, which first allocates the needed memory using init(capacity: count). It then sets each segment in that part of memory to the repeatedValue.
When using the init(count:repeatedValue:) initializer with number types like Int, Double, or Float it works perfectly fine. Then using Character, or String though it crashes. It doesn't crash consistently though, but actually works sometimes, as can be seen here, by compiling a few times.
var a = DynamicArray<Character>(count: 5, repeatedValue: "A")
println(a.description) //prints [A, A, A, A, A]
//crashes most of the time
var b = DynamicArray<Int>(count: 5, repeatedValue: 1)
println(a.description) //prints [1, 1, 1, 1, 1]
//works consistently
Why is this happening? Does it have to do with String and Character holding values of different length?
Update #1:
Now #AirspeedVelocity addressed the problem with init(count:repeatedValue:). The DynamicArray contains another initializer though, which at first worked in a similar fashion as init(count:repeatedValue:). I changed it to work, as #AirspeedVelocity described for init(count:repeatedValue:) though:
init<C: CollectionType where C.Generator.Element == T, C.Index.Distance == Int>(collection: C) {
let collectionCount = countElements(collection)
self.init(capacity: collectionCount)
root.initializeFrom(collection)
count = collectionCount
}
I'm using the initializeFrom(source:) method as described here. And since collection conforms to CollectionType it should work fine.
I'm now getting this error though:
<stdin>:144:29: error: missing argument for parameter 'count' in call
root.initializeFrom(collection)
^
Is this just a misleading error message again?
Yes, chances are this doesn’t crash with basic inert types like integers but does with strings or arrays because they are more complex and allocate memory for themselves on creation/destruction.
The reason it’s crashing is that UnsafeMutablePointer memory needs to be initialized before it’s used (and similarly, needs to de-inited with destroy before it is deallocated).
So instead of assigning to the memory property, you should use the initialize method:
for index in 0..<count {
(root + index).initialize(repeatedValue)
}
Since initializing from another collection of values is so common, there’s another version of initialize that takes one. You could use that in conjunction with another helper struct, Repeat, that is a collection of the same value repeated multiple times:
init(count: Int, repeatedValue: T) {
self.init(capacity: count)
root.initializeFrom(Repeat(count: count, repeatedValue: repeatedValue))
self.count = count
}
However, there’s something else you need to be aware of which is that this code is currently inevitably going to leak memory. The reason being, you will need to destroy the contents and dealloc the pointed-to memory at some point before your DynamicArray struct is destroyed, otherwise you’ll leak. Since you can’t have a deinit in a struct, only a class, this won’t be possible to do automatically (this is assuming you aren’t expecting users of your array to do this themselves manually before it goes out of scope).
Additionally, if you want to implement value semantics (as with Array and String) via copy-on-write, you’ll also need a way of detecting if your internal buffer is being referenced multiple times. Take a look at ManagedBufferPointer to see a class that handles this for you.

Question related to string

I have two statements:
String aStr = new String("ABC");
String bStr = "ABC";
I read in book that in first statement JVM creates two bjects and one reference variable, whereas second statement creates one reference variable and one object.
How is that? When I say new String("ABC") then It's pretty clear that object is created.
Now my question is that for "ABC" value to we do create another object?
Please clarify a bit more here.
Thank you
You will end up with two Strings.
1) the literal "ABC", used to construct aStr and assigned to bStr. The compiler makes sure that this is the same single instance.
2) a newly constructed String aStr (because you forced it to be new'ed, which is really pretty much non-sensical)
Using a string literal will only create a single object for the lifetime of the JVM - or possibly the classloader. (I can't remember the exact details, but it's almost never important.)
That means it's hard to say that the second statement in your code sample really "creates" an object - a certain object has to be present, but if you run the same code in a loop 100 times, it won't create any more objects... whereas the first statement would. (It would require that the object referred to by the "ABC" literal is present and create a new instance on each iteration, by virtue of calling the constructor.)
In particular, if you have:
Object x = "ABC";
Object y = "ABC";
then it's guaranteed (by the language specification) than x and y will refer to the same object. This extends to other constant expressions equal to the same string too:
private static final String A = "a";
Object z = A + "BC"; // x, y and z are still the same reference...
The only time I ever use the String(String) constructor is if I've got a string which may well be backed by a rather larger character array which I don't otherwise need:
String x = readSomeVeryLargeString();
String y = x.substring(5, 10);
String z = new String(y); // Copies the contents
Now if the strings that y and x refer to are eligible for collection but the string that z refers to isn't (e.g. it's passed on to other methods etc) then we don't end up holding all of the original long string in memory, which we would otherwise.

Resources