Create 1D array of objects

How can I create a strcut which can create a 1-D array for HuffmanEntry shown in the example. The copyinit function doesn't allow me to store data and gives the following error:
"error: no matching function in call to 'store':
self.data.store(i, elements[i])
~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
/home/talha/Desktop/mojo/jpeg/C-code/Mojo/test.mojo:1:1: note: candidate not viable: method argument #1 cannot bind AnyRegType type to memory-only type 'HuffmanEntry'
struct HuffmanEntry(CollectionElement):
^
/home/talha/Desktop/mojo/jpeg/C-code/Mojo/test.mojo:1:1: note: candidate not viable: callee expects 2 arguments, but 3 were specified
struct HuffmanEntry(CollectionElement):
^
mojo: error: failed to parse the provided Mojo"
"error: no matching function in call to 'store':
self.data.store(i, elements[i])
~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
/home/talha/Desktop/mojo/jpeg/C-code/Mojo/test.mojo:1:1: note: candidate not viable: method argument #1 cannot bind AnyRegType type to memory-only type 'HuffmanEntry'
struct HuffmanEntry(CollectionElement):
^
/home/talha/Desktop/mojo/jpeg/C-code/Mojo/test.mojo:1:1: note: candidate not viable: callee expects 2 arguments, but 3 were specified
struct HuffmanEntry(CollectionElement):
^
mojo: error: failed to parse the provided Mojo"
No description
11 Replies
taalhaataahir01022001
taalhaataahir01022001OP•12mo ago
Here's how I did. There's a register_passable thing in mojo:
No description
sora
sora•12mo ago
Hey, what prevents you from using DynamicVectors? You could also use @value and leave out the constructor all together
taalhaataahir01022001
taalhaataahir01022001OP•12mo ago
@sora I was using Dynamic Vectors previously but I was getting this issue. Here I've created an example code:
struct HuffmanEntry(CollectionElement):
var sz: Int
var codeword: Int
var decoded: Int

fn __init__(inout self, sz: Int, codeword: Int, decoded: Int):
self.sz = sz
self.codeword = codeword
self.decoded = decoded

fn __copyinit__(inout self, existing: Self):
print("CopyInit")
self.sz = existing.sz
self.codeword = existing.codeword
self.decoded = existing.decoded

fn __moveinit__(inout self, owned existing: Self):
self.sz = existing.sz
self.codeword = existing.codeword
self.decoded = existing.decoded


fn newfunc(inout arg: HuffmanEntry) -> Int:
arg.sz = 3
return 0

fn newfunc2(inout arg: DynamicVector[HuffmanEntry]) -> Int:
for i in range(3):
arg[i].sz = 4
return 0

fn main() raises:
var a = HuffmanEntry(0,0,0)
let b: Int = newfunc(a)

var c = DynamicVector[HuffmanEntry] ()

c.append(a)
c.append(a)
c.append(a)

let d:Int = newfunc2(c)
struct HuffmanEntry(CollectionElement):
var sz: Int
var codeword: Int
var decoded: Int

fn __init__(inout self, sz: Int, codeword: Int, decoded: Int):
self.sz = sz
self.codeword = codeword
self.decoded = decoded

fn __copyinit__(inout self, existing: Self):
print("CopyInit")
self.sz = existing.sz
self.codeword = existing.codeword
self.decoded = existing.decoded

fn __moveinit__(inout self, owned existing: Self):
self.sz = existing.sz
self.codeword = existing.codeword
self.decoded = existing.decoded


fn newfunc(inout arg: HuffmanEntry) -> Int:
arg.sz = 3
return 0

fn newfunc2(inout arg: DynamicVector[HuffmanEntry]) -> Int:
for i in range(3):
arg[i].sz = 4
return 0

fn main() raises:
var a = HuffmanEntry(0,0,0)
let b: Int = newfunc(a)

var c = DynamicVector[HuffmanEntry] ()

c.append(a)
c.append(a)
c.append(a)

let d:Int = newfunc2(c)
In the above code, the copyinit function is called 6 times. 3 times when I use the append function (which is completely fine). But when I send the DynamicVector "c" ti the nxt function i.e., newfunc2 and update the member variable "sz" , the copy constructor is called again. Why is it the case. According to my understanding when you use "in out" with the argument, the original object is sent to the function as a reference and not the copy of that object. Although the DynamicVector "c" is updated outside the "newfunc2" but why is it the case that new "HuffmanEntry" object is being created while updating the "sz" argument of the object which is already stored in vector c? And How to avoid this i.e., update the object store within the dynamic vector instead of creating a new object?
taalhaataahir01022001
taalhaataahir01022001OP•12mo ago
@sora This is the output for reference:
No description
sora
sora•12mo ago
Hmmm, it is indeed curious and surprising. Maybe you could reduce the example and write bug report?
taalhaataahir01022001
taalhaataahir01022001OP•12mo ago
sure thanks
taalhaataahir01022001
taalhaataahir01022001OP•12mo ago
Actually the issue is that I'm creating Jpeg decoder in mojo and I was comparing it with C and python. Using the perf profilling output I see the following: I.e., almost 87 percent of the time is being taken by the copy constructor because it is being invoked again and again when I try to update anything inside Dynamic Vecotrs 😦
No description
sora
sora•12mo ago
I can't make sense of it and i think it's a bug BTW, how did you profile your code?
taalhaataahir01022001
taalhaataahir01022001OP•12mo ago
There's a tool named perf It's pretty easy to use. just do

perf record ./executable

perf record ./executable
And it records the time taken inside each function. To view the output as shown above in the ss:
perf report
perf report
And you can download it using apt install perf. Maybe you might need 1-2 more dependencies which can easily be found on web
sora
sora•12mo ago
Ah, thanks for sharing your workflow! @Chris Lattner Sorry for pinging. Could you make sense of this example, and is it a bug that needs to be filed?
taalhaataahir01022001
taalhaataahir01022001OP•12mo ago
Plus it is not only the case when I update the Dynamic Vector of objects but it also creates new objects using the copy constructor even if I try to access any specific index. e.g.,
print(arg[0].sz)
print(arg[0].sz)
or
if arg[1].sz == 0
if arg[1].sz == 0
also invokes the copy constructors. And it has nothing to do with weather the vector is passed to a function via reference or not. Even If I access the vector of objects in the same scope where it's created, copy constructor is called. I tried to compare it with the C++ vectors to see if Dynamic Vectors are equivalent to vectors in C++:
class MyClass {
...
...
}
void printData(std::vector<MyClass>& myObjects) {
for (int i =0; i<3; i++) {
printf("%d\n",myObjects[i].getData());
}
}
int main() {
// Create a vector of objects of MyClass
std::vector<MyClass> myObjects;
myObjects.push_back(MyClass(1));
myObjects.push_back(MyClass(2));
myObjects.push_back(MyClass(3));
printf("%d\n", myObjects[0].getData())
printData(myObjects);
}
class MyClass {
...
...
}
void printData(std::vector<MyClass>& myObjects) {
for (int i =0; i<3; i++) {
printf("%d\n",myObjects[i].getData());
}
}
int main() {
// Create a vector of objects of MyClass
std::vector<MyClass> myObjects;
myObjects.push_back(MyClass(1));
myObjects.push_back(MyClass(2));
myObjects.push_back(MyClass(3));
printf("%d\n", myObjects[0].getData())
printData(myObjects);
}
Both printf("%d\n", myObjects[0].getData()) and printData function doesnot invoke any constructor which makes sense.
Want results from more Discord servers?
Add your server