Skip to content

Instantly share code, notes, and snippets.

@sellout
Created November 4, 2010 03:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sellout/662106 to your computer and use it in GitHub Desktop.
Save sellout/662106 to your computer and use it in GitHub Desktop.
in-place modification
(include-component "library/characters")
;; all valid sequence operations are valid string operations, so we `load` the
;; component instead of using one of the `*-component operations`.
(load "library/sequences")
(trigger {upcase (list ?string {?rc}) up} ...)
A thought … if there's a
{location "some-string"}
We can modify the string "in-place" with
(trigger* {upcase {?channel}}
(trigger {channel ?string}
{upcase (list ?string {channel})}))
{upcase {location}}
Now, can we generalize that?
(trigger* {in-place {?operation {?channel}}}
(trigger {channel ?value}
{operation (list ?value {channel})}))
So now
{in-place {upcase {location}}}
will work, but if we want to do
{in-place {subseq (list {location} 10 20)}}
then we need to also create
(trigger* {in-place {?operation (list {?channel} ?param1 ?param2)}}
(trigger {channel ?value}
{operation (list ?value ?param1 ?param2 {channel})}))
and so on for any other number of parameters we want to support. Once we handle variable
args somehow, maybe with an extended pattern language. There are also other special
cases to handle – like what if the in-place channel isn't the first parameter, or what
if there are multiple channels you'd like to update in place. That last case is probably
pretty contrived – as there are also multiple response channels in that case, and not
all channel parameters are meant to be handled in-place, etc. So there might not be much
point in generalizing beyond the single-place operation. But it allows things like this:
(new (string done)
(par {string "foobar"}
{in-place {upcase {string}} {done}}
{in-place {subseq (list {string} 0 3)} {done}}
(trigger (par {done} {done} {string ?value})
{echo ?value})))
=> "FOO"
Because any motion through the operations gets to the same endpoint:
subseq
foobar -> foo
u
p
c | |
a v v
s
e
FOOBAR -> FOO
However, there's an issue with knowing when the operation is actually done – the
continuation is processed when the inner trigger is created, not when it's activated,
which means that the `echo` could be the first thing that's performed. You really want
to be able to pass along the continuation. There are a few options I can think of:
;;; This one won't work because you can't match on the continuation, even when
;;; it's just in the contents of a received message.
(trigger* {in-place {?operation {?channel} ?continuation}}
(trigger {channel ?value}
{operation (list ?value {channel}) ?continuation}))
;;; The following ones work, but are a bit ugly.
;;; The problem here is that you _always_ have to pass a continuation, even if
;;; it's just null
(trigger* {in-place (list {?operation {?channel}} ?continuation)}
(trigger {channel ?value}
{operation (list ?value {channel}) ?continuation}))
;;; This is effectively equivalent to the previous one, I think – it just
;;; activates the continuation when the message is consumed, rather than when
;;; the operation is performed.
(trigger* {in-place (list {?operation {?channel}} ?continuation)}
(trigger {channel ?value}
(par {operation (list ?value {channel})}
?continuation)))
;;; This one should really do the right thing – it captures the new value, and only
;;; fires off the continuation once that's in place.
;;;
;;; But is this really necessary? The previous version won't fire the continuation until
;;; the original value is consumed, so anything that depends an the value will have to
;;; wait around until the new one is added anyway.
(trigger* {in-place (list {?operation {?channel}} ?continuation)}
(new temp
(trigger {channel ?value}
(par {operation (list ?value {temp})}
(trigger {temp ?new-value}
(par {channel ?new-value}
?continuation))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment