Summary
Add a match_class! macro for implementing behavior that varies based on the built-in type of an object.
Detailed Explanation
Doing this currently with downcast is a bit awkward. Because it consumes the Rc,
you have two options:
- Clone the object and then do a series of
ifs.
impl PyFloat {
fn eq(self: PyRef<Self>, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
if let Some(i @ PyInt { .. }) = other.clone().downcast() {
Ok(PyInt::new(&self.value + i.as_bigint()).into_ref(vm))
} else if let Some(f @ PyFloat { .. }) = other.downcast() {{
let output = self.value + f.value.to_bigint().unwrap();
Ok(PyFloat::new(output))
} else {
Ok(vm.ctx.not_implemented())
}
}
}
- Use the returned
Err(obj) of downcast to avoid the clone.
match other.downcast() {
Ok(i @ PyInt { ..}) => {
Ok(PyInt::new(&self.value + ).into_ref(vm))
},
Err(obj) => match obj.downcast() {
Ok(f @ PyFloat { .. }) => {
let output = self.value + f.value.to_bigint().unwrap();
Ok(PyFloat::new(output))
},
_ => Ok(vm.ctx.not_implemented()),
}
}
This avoids a pointless clone at the cost of adding undesirable rightward drift. What we really want is to be able to use a match-like syntax that expands to the efficient version above:
impl PyFloat {
fn eq(self: PyRef<Self>, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
match_object!(other,
i @ PyInt { .. } => {
Ok(PyInt::new(&self.value + i.as_bigint()).into_ref(vm))
},
f @ PyFloat { .. } => {
let output = self.value + f.value.to_bigint().unwrap();
Ok(PyFloat::new(output))
},
_ => Ok(vm.ctx.not_implemented()),
)
}
}
Drawbacks, Rationale, and Alternatives
The main drawback is that it is another macro. It should be very straightforward to implement and to understand though.
Unresolved Questions
Will allowing a full pattern in each match clause encourage making struct fields public, when they really should not be? An alternative would be to just allow the type name in each match arm.
Summary
Add a
match_class!macro for implementing behavior that varies based on the built-in type of an object.Detailed Explanation
Doing this currently with
downcastis a bit awkward. Because it consumes theRc,you have two options:
ifs.Err(obj)ofdowncastto avoid the clone.This avoids a pointless clone at the cost of adding undesirable rightward drift. What we really want is to be able to use a
match-like syntax that expands to the efficient version above:Drawbacks, Rationale, and Alternatives
The main drawback is that it is another macro. It should be very straightforward to implement and to understand though.
Unresolved Questions
Will allowing a full pattern in each match clause encourage making struct fields public, when they really should not be? An alternative would be to just allow the type name in each match arm.