Code: Select all
unsafePerformIO $ print "help!!"Code: Select all
unsafePerformIO $ print "help!!"I really like the idea behind "write-only" globals and you've made me realize a lot of the globals I use are like that. Print is definitely a write-only global, at least in spirit (I don't care if you can access the internal buffer, nobody will).palas wrote: Sat Mar 14, 2026 12:40 am Types 1 and 2 are in the safe category, so spamming them won't hurt too much. When it comes to 3, they directly affect how well can one reason about the codebase locally.
This is still mostly unsolved for me. It's not about whether or not to use them (can't really gamedev much without at least some global scene/level manager), but how to design in a way to keep as much locality as possible. For example, if I'm storing references to game objects, they can still be deleted from anywhere else. What happens if they do get deleted? Idk
Code: Select all
if (SceneGraph.GetFirstEntityInGroup("Player") is not {} player) return;
Code: Select all
if (SceneGraph.GetFirstEntityInGroup("Player") is not {} player) return;
TweenManager.Spawn(..., tick: (t) => {
player.color = somethingSomething(t);
});
I really like the idea behind "write-only" globals and you've made me realize a lot of the globals I use are like that. Print is definitely a write-only global, at least in spirit (I don't care if you can access the internal buffer, nobody will).palas wrote: Sat Mar 14, 2026 12:40 am Types 1 and 2 are in the safe category, so spamming them won't hurt too much. When it comes to 3, they directly affect how well can one reason about the codebase locally.
This is still mostly unsolved for me. It's not about whether or not to use them (can't really gamedev much without at least some global scene/level manager), but how to design in a way to keep as much locality as possible. For example, if I'm storing references to game objects, they can still be deleted from anywhere else. What happens if they do get deleted? Idk
Code: Select all
if (SceneGraph.GetFirstEntityInGroup("Player") is not {} player) return;
Code: Select all
if (SceneGraph.GetFirstEntityInGroup("Player") is not {} player) return;
TweenManager.Spawn(..., tick: (t) => {
player.color = somethingSomething(t);
});
Code: Select all
fn Entity::handle(self) -> Handle<Self>;
fn Handle<T>::get(self) -> T?;
Code: Select all
fn Entity::handle(self) -> Handle<Self>;
fn Handle<T>::get(self) -> T?;
Code: Select all
(def ^:dynamic *user-session* nil)
(def auth-middleware [request, next-fn]
(if-let [session (validate-user-session (-> request :cookies :user-session-cookie))]
(binding [*user-session* session]
(next-fn))
#_else
(throw "somethingsomething unauthenticated")))
Code: Select all
(def ^:dynamic *user-session* nil)
(def auth-middleware [request, next-fn]
(if-let [session (validate-user-session (-> request :cookies :user-session-cookie))]
(binding [*user-session* session]
(next-fn))
#_else
(throw "somethingsomething unauthenticated")))
Oh yup! I have things like this. Not for entities (maybe I should?), but for components I have a ComponentRef thing that's basically this. Maybe I should add a similar thing for entities, though nothing would enforce using an entity handle over just passing an entity around, so I'm not fully convinced therePalas wrote: As for the API to handle potentially missing entities... The first thing that comes to mind is Handle<T> with the following api:Code: Select all
fn Entity::handle(self) -> Handle<Self>; fn Handle<T>::get(self) -> T?;
Oh yup! I have things like this. Not for entities (maybe I should?), but for components I have a ComponentRef thing that's basically this. Maybe I should add a similar thing for entities, though nothing would enforce using an entity handle over just passing an entity around, so I'm not fully convinced therePalas wrote: As for the API to handle potentially missing entities... The first thing that comes to mind is Handle<T> with the following api:Code: Select all
fn Entity::handle(self) -> Handle<Self>; fn Handle<T>::get(self) -> T?;
Code: Select all
if value.inner is Inner inner
&& inner.inner is Inner inner
&& inner.inner is Inner inner {...}
Code: Select all
if value?.inner?.inner is Inner inner {...}
Code: Select all
if value.inner is Inner inner
&& inner.inner is Inner inner
&& inner.inner is Inner inner {...}
Code: Select all
if value?.inner?.inner is Inner inner {...}
Code: Select all
if value?.inner?.inner is Inner inner {...}
Code: Select all
if value is Str(s) && s.trim().to_lower() == "potato" { ... }
Code: Select all
if value?.inner?.inner is Inner inner {...}
Code: Select all
if value is Str(s) && s.trim().to_lower() == "potato" { ... }