Calling methods from list indexes

When I try running update from here:
alias CptList = List[ComponentList]

struct Entity:
var components: CptList

fn __init__(inout self, components: CptList):
self.components = components

fn update(inout self):
for i in range(self.components.__len__()):
self.components[i].update()

fn addCpt(inout self, value: ComponentList):
self.components.append(value)
alias CptList = List[ComponentList]

struct Entity:
var components: CptList

fn __init__(inout self, components: CptList):
self.components = components

fn update(inout self):
for i in range(self.components.__len__()):
self.components[i].update()

fn addCpt(inout self, value: ComponentList):
self.components.append(value)
It returns this error:
error: 'Variant[BaseComponent]' value has no attribute 'update'
self.components[i].update()
~~~~~~~~~~~~~~~~~~^
error: 'Variant[BaseComponent]' value has no attribute 'update'
self.components[i].update()
~~~~~~~~~~~~~~~~~~^
ComponentList is defined here:
alias ComponentList = Variant[
BaseComponent,
]
alias ComponentList = Variant[
BaseComponent,
]
BaseComponent is defined here:
@value
struct BaseComponent: # example
fn __init__(inout self): print("hi!!!!!")

fn update(inout self): print("update method")
fn render(inout self): pass
@value
struct BaseComponent: # example
fn __init__(inout self): print("hi!!!!!")

fn update(inout self): print("update method")
fn render(inout self): pass
14 Replies
capt_falamer
capt_falamer4w ago
self.components[i][BaseComponent].update()
self.components[i][BaseComponent].update()
Mojo requires you to tell it which of the variant types it is Here's the example from the API docs for an example:
from utils import Variant
alias IntOrString = Variant[Int, String]
fn to_string(inout x: IntOrString) -> String:
if x.isa[String]():
return x[String][]
# x.isa[Int]()
return str(x[Int][])

# They have to be mutable for now, and implement CollectionElement
var an_int = IntOrString(4)
var a_string = IntOrString(String("I'm a string!"))
var who_knows = IntOrString(0)
import random
if random.random_ui64(0, 1):
who_knows.set[String]("I'm actually a string too!")

print(to_string(an_int))
print(to_string(a_string))
print(to_string(who_knows))
from utils import Variant
alias IntOrString = Variant[Int, String]
fn to_string(inout x: IntOrString) -> String:
if x.isa[String]():
return x[String][]
# x.isa[Int]()
return str(x[Int][])

# They have to be mutable for now, and implement CollectionElement
var an_int = IntOrString(4)
var a_string = IntOrString(String("I'm a string!"))
var who_knows = IntOrString(0)
import random
if random.random_ui64(0, 1):
who_knows.set[String]("I'm actually a string too!")

print(to_string(an_int))
print(to_string(a_string))
print(to_string(who_knows))
banananas
banananas4w ago
Ah seems a bit strange but i'll try it
capt_falamer
capt_falamer4w ago
Yeah, if I were to guess, the explicit call is for the strict typing and performance reasons
ModularBot
ModularBot4w ago
Congrats @capt_falamer, you just advanced to level 1!
banananas
banananas4w ago
That works fine, but what if you're using a Variant? ...[index][Variant[types...]]... throws an error
capt_falamer
capt_falamer4w ago
you'll need to have the Variant[types...] as one of the list of types in the original variant
alias my_variant_variant = Variant[Int,String,Variant[Int,String]]
alias list_of_variants = List[my_variant_variant]

def main():
var v = list_of_variants()
v.append(my_variant_variant(1))
v.append(my_variant_variant(str('hi')))
v.append(my_variant_variant( Variant[Int,String](str('variant of a variant') )))

var my_int = v[0][Int] #my_int is of type Int
var my_string = v[1][String] #my_string is of type String
var my_var = v[2][Variant[Int,String]] #my_var is of type Variant[Int, String]

print(my_int) #prints 1
print(my_string) #prints 'hi'
print(my_var[String]) #prints 'variant of a variant'
alias my_variant_variant = Variant[Int,String,Variant[Int,String]]
alias list_of_variants = List[my_variant_variant]

def main():
var v = list_of_variants()
v.append(my_variant_variant(1))
v.append(my_variant_variant(str('hi')))
v.append(my_variant_variant( Variant[Int,String](str('variant of a variant') )))

var my_int = v[0][Int] #my_int is of type Int
var my_string = v[1][String] #my_string is of type String
var my_var = v[2][Variant[Int,String]] #my_var is of type Variant[Int, String]

print(my_int) #prints 1
print(my_string) #prints 'hi'
print(my_var[String]) #prints 'variant of a variant'
banananas
banananas4w ago
That seems needlessly complicated but alright
capt_falamer
capt_falamer4w ago
It can be, depending on what you're trying to do you may not even need a variant
banananas
banananas4w ago
alias ComponentList = Variant[
BaseComponent, # example
Variant[BaseComponent],
]
alias ComponentList = Variant[
BaseComponent, # example
Variant[BaseComponent],
]
also brings up the same error
ModularBot
ModularBot4w ago
Congrats @banananas, you just advanced to level 3!
capt_falamer
capt_falamer4w ago
Think I may be missing what you are trying to do. On mobile right now and it will be a bit before I can write up working code. I think if you could explain the specific use case I might be able to better answer the root of your question
banananas
banananas4w ago
I'm making an ECS (or sort of ECS) and i'm calling the update method of every component in an entity by cycling through a components list using a for loop. I'm trying to get the i index of components but it needs a type as well, but every component is listed in a variant so you don't have to specify the types of components in each method of every entity hopefully that was clear enough
capt_falamer
capt_falamer4w ago
then what I first responded was what you were looking for. Here's a fleshed out example to clarify what I was trying to communicate
from utils import Variant
alias ComponentList = Variant[BaseComponent1,BaseComponent2]
alias CptList = List[ComponentList]

struct Entity:
var components: CptList

fn __init__(inout self, components: CptList):
self.components = components

fn update(inout self):
for i in range(len(self.components)):
if self.components[i].isa[BaseComponent1]():
self.components[i][BaseComponent1].update()
elif self.components[i].isa[BaseComponent2]():
self.components[i][BaseComponent2].update()
#continue elif statements for each additional variant

fn addCpt(inout self, value: ComponentList):
self.components.append(value)


@value
struct BaseComponent1: # example
fn __init__(inout self): print("hi!!!!!")

fn update(inout self): print("update method1")
fn render(inout self): pass

@value
struct BaseComponent2: # example
fn __init__(inout self): print("hi2!!!!!")

fn update(inout self): print("update method2")
fn render(inout self): pass

def main():
var b1 = BaseComponent1()
var b2 = BaseComponent2()
var comp_list_entity = Entity(CptList(b1,b2))
comp_list_entity.update()
from utils import Variant
alias ComponentList = Variant[BaseComponent1,BaseComponent2]
alias CptList = List[ComponentList]

struct Entity:
var components: CptList

fn __init__(inout self, components: CptList):
self.components = components

fn update(inout self):
for i in range(len(self.components)):
if self.components[i].isa[BaseComponent1]():
self.components[i][BaseComponent1].update()
elif self.components[i].isa[BaseComponent2]():
self.components[i][BaseComponent2].update()
#continue elif statements for each additional variant

fn addCpt(inout self, value: ComponentList):
self.components.append(value)


@value
struct BaseComponent1: # example
fn __init__(inout self): print("hi!!!!!")

fn update(inout self): print("update method1")
fn render(inout self): pass

@value
struct BaseComponent2: # example
fn __init__(inout self): print("hi2!!!!!")

fn update(inout self): print("update method2")
fn render(inout self): pass

def main():
var b1 = BaseComponent1()
var b2 = BaseComponent2()
var comp_list_entity = Entity(CptList(b1,b2))
comp_list_entity.update()
Unfortunately there is no shortcut currently to blanket apply a method by doing list[x].common_method() even if all the structs within the variant have the exact same method.
banananas
banananas4w ago
Alright, thanks
Want results from more Discord servers?
Add your server