ns nr::train use object::{assign, Props, props!} pub int Train name: String primaryColor: Color fld destination: String fld volume: Int fn blowHorn() -> IO end pub enum Color White, Blue, Red end pub type Printer = fn (message: String) -> IO pub fn create(props: obj Props + { printer: Printer }) -> Train = SimpleTrain(props).with { volume = 80 } class SimpleTrain : Train props!::() printer: Printer ctor(props: obj Props + { printer: Printer }) assign(self, props) end impl fn blowHorn() -> IO printer("Train ${name} is blowing its horn at volume ${volume}!") end end pub fn createViaObj(props: obj Props, printer: Printer) -> obj Train obj { ...props, printer, blowHorn: fn () -> IO printer("Dynamic object Train ${train} is blowing its horn at volume ${self.volume}!") end } end // props lib file ns std::core::object pub fn assign(target: obj, source: obj) for [key, value] source.props() do target[key] = value end end pub type Props = obj { [K in keyof T]: T[K] } pub macro fn props!(_: TokenStream) -> TokenStream let result = TokenStream() for [key, type] in std::intrinsics::propsAndTypes::() do result << quote! { #key: #type } end result end // io lib file ns std::core pub enum IO : fn () -> IO Success(stream: S) impl () try doCall(stream) catch (e: E) Failure(e) end end end, Failure(_) impl () self end end; int fn doCall(stream: S) -> IO end end // main example file ns nr::example use nr::train::{create, createViaObj, Train, Color} fn main() let train = create(obj { name: 'Test Train', primaryColor: Color::Blue, destination: 'Nonavosa Central', printer: println }) train.blowHorn() train.volume = 100 train.blowHorn() let objTrain: obj Train = createViaObj(obj { name: 'Obj Train', primaryColor: Color::Red, destination: 'Durandana', printer: println }) // Since it's an obj, we can dynamically add properties and override methods, similar to JS objTrain.secondaryColor = Color::White let originalBlowHorn = objTrain.blowHorn objTrain.blowHorn = fn () originalBlowHorn() println "Hello again! The train's colors are ${self.primaryColor} and ${self.secondaryColor}!" end objTrain.blowHorn() end