This code gives me an error. Can anyone help me fix it?
struct MyInt:
var n: Int
fn __init__(out self, x: Int):
self.n = x
fn __copyinit__(out self, existing: Self):
self.n = existing.n
fn __moveinit__(out self, owned existing: Self):
self.n = existing.n
fn __contains__(self, other: MyInt) -> Bool:
if self.n == other.n:
return True
else:
return False
def main():
var list1: List [MyInt] = []
var myint: MyInt = MyInt(1)
print(myint in list1)
Error:
life.mojo:100:17: error: invalid call to '__contains__': could not deduce positional-only parameter #2 of callee '__contains__'
print(myint in list1)
~~~~~~^~~~~~~~
life.mojo:100:20: note: failed to infer parameter #2, argument type 'MyInt' does not conform to trait 'EqualityComparable & Copyable & Movable'
print(myint in list1)
^~~~~
The error message is giving you the correct direction. The signature for __contains__ should look like this: List | Modular
I don’t believe there is a trait that corresponds to __contains__ yet, (stdlib traits enumerated here). I don’t believe there is another way to get the expected signature of a “special method” other than looking for an example in the stdlib yet. Discussed in docs here.
Implementing the suggested traits on your struct fixes the problem:
struct MyInt(EqualityComparable, Copyable, Movable):
var n: Int
fn __init__(out self, x: Int):
self.n = x
fn __eq__(read self, read other: Self) -> Bool:
return self.n == other.n
fn __ne__(read self, read other: Self) -> Bool:
return not self == other
fn __copyinit__(out self, existing: Self):
self.n = existing.n
fn __moveinit__(out self, owned existing: Self):
self.n = existing.n
fn __contains__(self, other: MyInt) -> Bool:
if self.n == other.n:
return True
else:
return False
def main():
var list1: List[MyInt] = []
var myint: MyInt = MyInt(1)
print(myint in list1)
__ne__ and __eq__ satisfy EqualityComparable, which means that self type now satisfies the signature for contains: __contains__[U: EqualityComparable & Copyable & Movable, //](self: List[U, hint_trivial_type], value: U) -> Bool which has the infer-only parameter U that must implement EqualityComparable & Copyable & Movable.
When you use syntax that invokes special methods (in, [index], +, etc.), it’s equivalent to calling a method on the left-hand side (LHS) operand. Example: lhs.__special__(rhs) in the case of binary operators.
The expected method signature is defined by the type of the LHS and varies by type (but sometimes by the RHS when it’s reversable.
What I said earlier is misleading. To determine how in works for a given type like List, you should check the docs for List itself. There is no universal signature for __contains__—it is type-specific.