Since this uses pointers (via NonNull), we would need to use unsafe blocks when accessing the attributes. The getter methods generated shall bear the same name as the struct fields and be 98 | impl Node for F The invariant that we are upholding is: it is safe to do this because we are fixing the Instance to a specific memory location, and thus referencing attributes on the instance is safe. Traits. At its core, Lisp is just a tree where each node evalutes to some value. Not on the topic of the post, but - I think a hard part for newbies is that the standard library API docs are very difficult to use in an exploratory manner. no arguments and returns a value, is evaluated by executing that function and RIP Tutorial. In the trait we just defined, this wouldn't We have the same basic setup: we are asking the user to provide a getter, but this time it returns a reference to the attribute. They can access other methods declared in the same trait. hiding fields instead. Furthermore we cannot store a function that returns foo.x is>. The methods return an immutable reference to the struct field of the If there is already a method defined with that name there'll be a collision. However, in coarse benchmarks, the difference between these two didn't seem to be much of a win relative to some of the other more expensive operations we already have. | It is conflating application types with data formats. It's a great way to encode shared behaviour between data types, and create flexible APIs. We also introduced the Instance struct to wrap any object and erase the type using dyn Any. A good topic for another blog post. However, it would still be possible to extend the current approach by using serde as a shortcut to deriving attribute getters. The benefit of using a trait from the standard library is that users may get implementations of the trait for "free", e.g., if they are already using a HashMap, then they don't need to do any additional work to define attribute getters that leverage the trait. Although in Python its perfectly valid to add attributes to a class on the fly, we have that requirement in neither the host language nor in Polar. that are not publicly documented. Rust 1.26 also introduces the impl Trait feature, which is more concise (Though I can see little value in mut self.). For example; The trait bounds can also be declared in a where clause. non-breaking way by using the sealed trait pattern. reference to the num field. What's the payoff for this additional complexity and unsafety? struct Foo(Bar) would generate a Bar: ToComputedValue::ComputedValue>> bound instead of just T: ToComputedValue. dumbing this down to the usual bounds on type parameters brought those gains.