Note that there are some explanatory texts on larger screens.

plurals
  1. POSubscriber with lazy evaluation
    primarykey
    data
    text
    <p>I'm looking for a solution for subscribing to attribute changes in Go. Given the below structs I'd like to implement a derived attribute which subscribes to its source attributes, and only when being read it would reevaluate itself. It would know to do so due to being notified, or by checking a "dirty flag" (channel?) if one or more of the sources had changed. <strong>Edit</strong>: I'm not looking for a "getter" function, which would not cache the fetched values, instead fethcing them every time being read). See also an added DeriveAndSubscribe-method far below, illustrating what the derived FullName would do).</p> <p>I guess this resembles a fairly typical case. Se example below:</p> <pre><code>type Person struct { /FullName string // Derived, from the two below: FirstName string // persistent LastName string // persistent } </code></pre> <p>The concept must be "visible" for far subscriptions/fetches too, for example a User object deriving it's detailed user info from an underlaying Person object:</p> <pre><code>type User struct { person *Person /FullName string // Derived from person.FullName above } </code></pre> <p><em>(Ok, people's names don't change very often but the example must be simple).</em> </p> <p>My own first thoughts on this is, </p> <ol> <li><p><strong>Pull</strong> - The derived attributes (FullName) is to be "lazy" (evaluated only if someone is reading it/them). Therefore it seems the most natural to "pull" any subscriptions ("dirty" flag/notification) only when evaluating the Fullname string, that is, "ask" if any change has occured.</p></li> <li><p><strong>Cache</strong> - when the value has been derived, then store it in a (hidden) field (_fullName) so that the string can be reused at next read, if its subscribed values hasn't changed.</p></li> <li><p><strong>Lazy subscription</strong> - Not only the derive operation should be "lazy" when someone reads the FullName attribute, but also the subscription itself should be laid only the first time it is evaluated (when someone reads the attribute).</p></li> <li><p><strong>Good reasons for pull</strong> instead of push seems to be that the subscribing attribute(s) may or may not be present when the underlaying attributes change. If there's no "send-list" at the source then there's no need to "unregister" either if/when the end subscribing attributes/objects goes away. And further; in a distributed scenario (User and Person on different machines) it's better to update things only if the data is actually explicitly asked for (that goes for the subscription as well, which can be laid only at the first read of FullName).</p></li> <li><p><strong>Luxury would be</strong> if a goroutine (optionally) could update (reevaluate) the FullName attribute(s) when CPU isn't very busy, while reevaluation would be immediately enforced if someone reads the FullName attribute (could both be achieved in one solution?).</p></li> </ol> <p>In any case, here's the subscriptions that needs to be laid (ASCII model):</p> <pre><code>[Person]./FullName --&gt; [Person].FirstName // Subscribe 1 [Person].LastName // Subscribe 2 </code></pre> <p>and</p> <pre><code>[User]./FullName --&gt; [User].person./FullName // Subscribe 3 </code></pre> <p>That is, alltogether three (3) subscriptons to keep the User.FullName attrib updated. (Disregard for now the [User].person-link). Can something like this be achieved using channels, and if so, um... how?</p> <p>Below the above structs with the hidden fields inserted (used for caching the derived result until next time the source attributes gets "dirty"):</p> <pre><code>type Person struct { /FullName string // Derived _fullName string // "cache" FirstName string LastName string } </code></pre> <p>and:</p> <pre><code>type User struct { person *Person /FullName string // Derived _fullName string // "cache" } </code></pre> <p>Edit: The Person-FullName-attribute could be served by a method like this one (it could be packaged into typed attribute objects (structs) later):</p> <pre><code>func (p *Person) _FullName_DeriveAndSubscribe(Subscriber chan) string { if /* check if channel(s) is "dirty" */ { // // Keep an internal channel, and get hold of the channel, or // Chan of Chan(?) wich can notify us if any underlaying values change: // // _subscr = Subscriber // // Now, update the cache _fullName = FirstName + " " + LastName } return _fullName // return the cached value } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload