Nested objects in Persistent? #105
|
I was experimenting with nested objects for state: type Mood = {
current : number;
}
type Character = {
mood : Mood;
}
type State = {
laura : Character;
};
export const state = new Persistent<State>("state", {
laura : {
mood : {
current : 10,
}
},
});When calling Persistent.get/set, etc., I can only directly access the top-level fields in State, e.g. state.evaluate("laura", (laura) => laura.mood.current >= 10)
function update_laura_mood_current (laura : Character) {
return { ...laura, mood : { ...laura.mood, current : laura.mood.current - 1 } };
}
// For some reason the spread expression doesn't compile inside the lambda.
state.set("laura", (laura) => update_laura_mood_current (laura));For now I just use lenses: // https://akheron.github.io/optics-ts/
import * as Lens from 'optics-ts'
export const laura_current_mood_lens = Lens.optic_<Character>()
.prop('mood')
.prop('current')
state.set("laura", (laura) => Lens.set(laura_current_mood_lens)(laura.mood.current - 1)(laura)),I'm just curious if there's a simpler/more idiomatic way to get/set nested object fields in a Persistent type. E.g.: state.evaluate("laura.mood.current", (current) => current >= 10)
state.set("laura.mood.current", (current) => current - 1);If not, it's not an issue. |
Replies: 2 comments 2 replies
|
Unfortunately, no. Persistent's Furthermore, if this behavior were implemented in a certain way, the game would need to handle more complex behavior when returning and assigning values to child items. For example, what happens when Alternatively, Callback-based Safer and more intuitive, using object assignment allows you to customize these behaviors and avoid overly complex, game-specific, and hard-to-remember behavioral conventions. While this idea doesn't fit the game's design philosophy, it's still fun! It's great to explore these ideas, thank you! |
|
Also, I noticed you mentioned the spread operator not compiling. I'm guessing you used: state.set("laura", (laura) => { ...laura, mood : { ...laura.mood, current : laura.mood.current - 1 } });But in JavaScript, this is the correct syntax: state.set("laura", (laura) => ({ ...laura, mood : { ...laura.mood, current : laura.mood.current - 1 } }));More conveniently, you can use: state.set("laura", (laura) => {
laura.mood.current = laura.mood.current - 1;
return laura;
}); |
Unfortunately, no.
Persistent's
setmethod takes a key and a value. The key can be any string, and there are no syntactic constraints. Using a dot-notated key like "parent.child.sub" introduces implicit structure that breaks the flat key-value intuition of Persistent.Furthermore, if this behavior were implemented in a certain way, the game would need to handle more complex behavior when returning and assigning values to child items. For example, what happens when
parent.childis null andparent.child.subis set to a value? Shouldnullbe discarded dangerously, or should an error be thrown when it shouldn't exist?Alternatively, Callback-based
setexpects a valid previous value. If the …