Like `<arrow>` and `<smart-arrow>`, but using `?set-model` instead of `set-model`.
"An exercise for the reader is to keep the original model around on the stack, and change its value to 6, observing that the label will immediately display 36."
} ;
+HELP: ?arrow
+{ $class-description "Like " { $link arrow } ", but only updates value if it is different from the last update. Arrows are constructed by " { $link <?arrow> } "." } ;
+
HELP: <arrow>
{ $values { "model" model } { "quot" { $quotation ( obj -- newobj ) } } { "arrow" "a new " { $link arrow } } }
{ $description "Creates a new instance of " { $link arrow } ". The value of the new arrow model is computed by applying the quotation to the value." }
{ $examples "See the example in the documentation for " { $link arrow } "." } ;
+HELP: <?arrow>
+{ $values { "model" model } { "quot" { $quotation ( obj -- newobj ) } } { "arrow" "a new " { $link ?arrow } } }
+{ $description "Creates a new instance of " { $link ?arrow } ". The value of the new arrow model is computed by applying the quotation to the value, but only set if the value actually changed. This prevents connected observers from being updated if the value did not change since the last update." }
+{ $examples "See the example in the documentation for " { $link arrow } "." } ;
+
ARTICLE: "models.arrow" "Arrow models"
"Arrow model values are computed by applying a quotation to the value of another model."
{ $subsections
TUPLE: arrow < model quot ;
-: <arrow> ( model quot -- arrow )
- f arrow new-model
- swap >>quot
+: new-arrow ( model quot class -- arrow )
+ f swap new-model
+ swap >>quot
[ add-dependency ] keep ;
+: <arrow> ( model quot -- arrow )
+ arrow new-arrow ;
+
+: compute-arrow-value ( model observer -- value )
+ [ value>> ] [ quot>> ] bi* call( old -- new ) ; inline
+
M: arrow model-changed
- [ [ value>> ] [ quot>> ] bi* call( old -- new ) ]
- [ set-model ] bi ;
+ [ compute-arrow-value ] [ set-model ] bi ;
M: arrow model-activated
[ dependencies>> ] keep [ model-changed ] curry each ;
+
+TUPLE: ?arrow < arrow ;
+
+: <?arrow> ( model quot -- ?arrow )
+ ?arrow new-arrow ;
+
+M: ?arrow model-changed
+ [ compute-arrow-value ] [ ?set-model ] bi ;
IN: models.arrow.smart
-USING: help.syntax help.markup models.product ;
+USING: help.syntax help.markup models.product models.arrow ;
HELP: <smart-arrow>
{ $values { "quot" { $quotation ( ... -- output ) } } }
}
} ;
+HELP: <?smart-arrow>
+{ $values { "quot" { $quotation ( ... -- output ) } } }
+{ $description "Like " { $link <smart-arrow> } ", but with the semantics of " { $link <?arrow> } "." } ;
+
ARTICLE: "models.arrow.smart" "Smart arrow models"
"The " { $vocab-link "models.arrow.smart" } " vocabulary generalizes arrows to arbitrary input arity. They're called “smart” because they resemble " { $link "combinators.smart" } "."
{ $subsections <smart-arrow> } ;
MACRO: <smart-arrow> ( quot -- quot' )
[ inputs dup ] keep
'[ _ narray <product> [ _ firstn @ ] <arrow> ] ;
+
+MACRO: <?smart-arrow> ( quot -- quot' )
+ [ inputs dup ] keep
+ '[ _ narray <product> [ _ firstn @ ] <?arrow> ] ;