r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[!Liquid] any questions about liquid dataflow core.

Maxim
7-Mar-2009
[748x2]
I have a newer version which has the "ability modifiers" added as 
extra labels to the right of the abilites... it took me 5 minutes 
to do, and it only needs one new simple !plug derivative:

;- !ability-mod
!ability-mod: make !plug [
	valve: make valve [
		type: 'ability-mod
		;-----------------
		;-     process()
		;-----------------
		process: func [
			plug
			data
		][
			vin [{!ability-mod/process()}]
			plug/liquid: 0
			vprobe data
			if integer? data: pick data 1 [
				plug/liquid: to-integer (data - 11 / 2)
			]
			vout
		]
	]
]


and necessary linkage within the !character setup, and appropriate 
faces in the window layout.
currently preparing 2 liquid modules for distribution on rebol.org 
:
  * LIQUID-VID : adding liquid functionality to ANY vid face

  * GLUE : a (hopefully growing) set of reusable core !plug classes 
   (like !sum and !subtract, in blood example).
Ammon
7-Mar-2009
[750]
Well, I just got home from work.  I'm cooking some dinner which I 
will eat while watching last night's episode of Battlestar Galactica 
and then I will download Blood and play with it a bit.
Maxim
7-Mar-2009
[751]
cool
Maxim
8-Mar-2009
[752x4]
just thought I'd share this list I built while coaching someone in 
using liquid last night...

SANITY PRESERVING KNOWLEDGE WHEN USING LIQUID:
--------------------------------------------


#1:  liquid isn't a bully  - liquid shares its state, but asks for 
data (pulls, observes, etc) from its subordinates ("parents"), not 
the other way around (it doesn' push or force feed, like a highly 
inneficient signal messaging engine).


#2:  liquid is lazy by default - unless a plug or one of its observers 
 ("children") is stainless, nothing will process automatically (thus, 
faces usually are set to stainless, so that they refresh automatically).

#3:  liquid has several computing modes in a single base class.  
  * linking is for once sided dependencies
  * piping is for inter-dependencies or synchronisation
  * containment is for data storage
  * linked-containment is for processed data storage   


#4:  liquid mutates - plugs automatically change computing modes 
when you call some methods like linking, piping and filling.  depending 
on the order of these operations, a plug may "stick" to its previous 
computing mode.  e.g. a piped node remains piped, even you attempt 
to link it to something.


#5:  liquid is alive - remember that as you are setting up a liquid 
network, your plugs will start receiving messages as you are building 
up the tree, meaning that the process() (and other) functions might 
be triggered before every expected connections are done. always verify 
the integrity of the data before starting the process.  (i just got 
stumped by this one again, 5 minutes ago).


#6:  liquid is a collection of droplets - each plug should do one 
thing or manage one step of a process.  the more you break up the 
network, the better you will be at making it stable, reusable, flexible, 
and fast.


#7:  liquid is highly memory efficient - !plug uses shared classes. 
 so all the liquid operations are in a sub-object called a valve. 
 Thus, when you call internal functions, remember they are within 
the valve, and you must supply the plug as its first argument.  my-plug/valve/stats 
my-plug


#8:  liquid is volubile - its slim-based verbose & indented console 
printing engine (vprint) is YOUR BEST FRIEND.  use it profusely, 
to understand the chain of events and what the hell is going on.
SANITY PRESERVING KNOWLEDGE WHEN USING LIQUID:
--------------------------------------------


#1:  liquid isn't a bully  - liquid shares its state, but asks for 
data (pulls, observes, etc) from its subordinates ("parents"), not 
the other way around (it doesn' push or force feed, like a highly 
inneficient signal messaging engine).


#2:  liquid is lazy by default - unless a plug or one of its observers 
 ("children") is stainless, nothing will process automatically (thus, 
faces usually are set to stainless, so that they refresh automatically).

#3:  liquid has several computing modes in a single base class.  
  * linking is for once sided dependencies
  * piping is for inter-dependencies or synchronisation
  * containment is for data storage
  * linked-containment is for processed data storage   


#4:  liquid mutates - plugs automatically change computing modes 
when you call some methods like linking, piping and filling.  depending 
on the order of these operations, a plug may "stick" to its previous 
computing mode.  e.g. a piped node remains piped, even you attempt 
to link it to something.


#5:  liquid is alive - remember that as you are setting up a liquid 
network, your plugs will start receiving messages as you are building 
up the tree, meaning that the process() (and other) functions might 
be triggered before every expected connections are done. always verify 
the integrity of the data before starting the process.  (i just got 
stumped by this one again, 5 minutes ago).


#6:  liquid is a collection of droplets - each plug should do one 
thing or manage one step of a process.  the more you break up the 
network, the better you will be at making it stable, reusable, flexible, 
and fast.


#7:  liquid is highly memory efficient - !plug uses shared classes. 
 so all the liquid operations are in a sub-object called a valve. 
 Thus, when you call internal functions, remember they are within 
the valve, and you must supply the plug as its first argument.  my-plug/valve/stats 
my-plug


#8:  liquid is volubile - its slim-based verbose & indented console 
printing engine (vprint) is YOUR BEST FRIEND.  use it profusely, 
to understand the chain of events and what the hell is going on.
adding a substantial feature to liquid.  the ability to "freeze" 
nodes.  the nice thing is that the freeze state can be set as a function... 
so a node could potentially disactivate itself on the fly, when it 
detects some impending error is about to occur.


it can also stay dead until its dependencies are sufficient... making 
it a highly efficient at preventing useless processing until all 
its dependencies are linked up.
you could even cause its to process only after a time lapse occured... 
automatically preventing useless processing within live animation 
nodes  :-)
Josh
8-Mar-2009
[756]
What is vin / vout?
Maxim
8-Mar-2009
[757x3]
part of vprint system.

vin = vprint/indent
vout = vprint/outdent
they cause the console messaging to go in or out one tab for all 
further vprint/vprobe calls.
this is embeded within the slim manager and is added to any slim 
library automatically
Josh
8-Mar-2009
[760]
That makes sense.   I will be  working on extending your blood to 
be as featured as the other char gen I made over the course of the 
week, so I"m sure I will run into all sorts of fun questions during 
the process
Maxim
8-Mar-2009
[761x3]
the vprint engine I mean... the actual vin/vout code is written manually
just passed all night helping ammon add new functionality to the 
+/- buttons... hehe the learning curve is steep, but gradually flatens.
hense the 8 rules above.... they really explain about 90% of all 
stumps even I fall over occasionally.
Ammon
8-Mar-2009
[764]
So I'm trying to create a plug, !color, that simply forces it's content 
to be a tuple, here's what I thought would work:

!color: make !plug [
	stainless?: true
	valve: make valve [
		type: 'color
		;-----------------
		;-     process()
		;-----------------
		process: func [
			plug
			data
			/value ; faster than:  /local value  
		][
			vin [{!color/process()}]
			plug/liquid: 0.0.0
			unless empty? data [
				if tuple? data/1 plug/liquid: data/1
			]
			vout
		]
	]
]

c: liquify/piped !color
fill c  255.255.255
fill c [0 0 0]



at this point c's content should be 255.255.255 not [0 0 0] which 
it is.
Maxim
8-Mar-2009
[765x2]
one note...  you might want to wait for me to release liquid-vid 
and glue... they will both simplify coding of things a lot.  and 
liquid-vid will even have a few dynamically adjusting faces like 
row and column.


funny thing is that its taking me far less energy (and code) to implement 
more dynamic and smart faces than glayout so far.  its also taking 
a lot less code to do a lot of the same things in glayout.
rule # 7


once you piped the color, processing is by passed.  this is a philosophical 
design decision.
Ammon
8-Mar-2009
[767]
Well, initially I tried it without /piped but FILL threw an error.
Maxim
8-Mar-2009
[768]
pipes and containers are like storage.  their value is to be used 
as-is.  if you wanted to clean ANOTHER plug to a color, your code 
is correct
Ammon
8-Mar-2009
[769x2]
interesting...

p: liquify/piped !plug
c: liquify !color
link c p
fill p  255.255.255
fill p [0 0 0]

does what I want it to.
Sweet.
Maxim
8-Mar-2009
[771x3]
btw, I am now building up a series of sample files for use as a tutorial 
as you guys ask questions and post examples.  so from now on, most 
of the question will be compiled into a great collection, used for 
an eventual tutorial!


so keep the questions comming.  independent and explicit code examples 
like the above are excellent.
exactly.
ammon in the above, the /piped is superfluous  ( and in fact a waste, 
since the p plug only needs to contain data)
Ammon
8-Mar-2009
[774]
Result of the same code minus the /piped ...

>> fill p green
liquid/!plug(1)/fill [
** Script Error: pipe expected plug argument of type: object
** Where: fill
** Near: either any [
    plug/valve/pipe
    plug/pipe?
] [
    plug: plug/valve/pipe/always plug
] [
    plug/pipe?: 'simple
]
Maxim
8-Mar-2009
[775x3]
sorry that is a BUG in liquid! hahahaha discovered it last night... 
well at 5am before I went to power nap.
its fixed and I wonder when that bug got inserted in the first place. 
 there is another tiny bug which I squashed, which was added with 
a brand-new (and not very teste) feature .
what version of liquid do you have on your system?
Ammon
8-Mar-2009
[778x2]
Whatever Blood.r pulled down...  One second...
0.7.0
Maxim
8-Mar-2009
[780x9]
darn, I just checked... I was sure I had updated the version late 
last night to include the fix... but seems not
my bad. give me a second... I will upload v0.7.1
ok, verified that the freeze extension works properly with blood, 
so its a valid release for now.
will also make sure that my reply to your original question (built 
a little example in my tutorial folder) also is functional
almost done...
version 0.7.1 released on rebol.org.
so, working now?
!color: make !plug [
	valve: make valve [
		type: 'color
		;-----------------
		;-     process()
		;-----------------
		purify: func [
			plug
		][
			vin [{!color/purify()}]
			if integer? plug/liquid [
				; convert integer to b/w gradient
				plug/liquid: to-tuple head insert/dup copy [] plug/liquid 3
			]
			unless tuple? plug/liquid [
				plug/liquid: 0.0.0
			]
			vout

   ; this is ESSENTIAL determines if plug is dirty or not... basically

   ; if you return false, the node stays dirty... and is re-evaluated 
   everytime.
			; if you forget to return a value, liquid causes an error. 
			true
		]
	]
]

print "----"
c: liquify !color
fill c  255.255.255
probe content c
fill c  none
probe content c
fill c  11
probe content c

p: liquify !plug
link/reset c p 

; /reset is used to reset the state of the plug as 
; virgin plug before linking. (all links removed, 
; pipes and containers are forgotten/ignored)
; if /reset isn't used, the plug c WILL be linked
; but its links are ignored, since the plug is 
fill p 55



output:

255.255.255
0.0.0
11.11.11
55.55.55
oops missing last probe in the above:

probe content c
Ammon
8-Mar-2009
[789]
Yes, my code is working but it's capable of a bit more than that...
Maxim
8-Mar-2009
[790x2]
do you understand the example I give?
btw purification always occurs after processing... which is why it 
uses plug/liquid directly... at that point any processing would have 
occured... if any
Ammon
8-Mar-2009
[792]
Yes, I understand it.   I'll be modifying my code to use both process() 
and purify() as I'm currently capable of linking multiple plugs to 
!color to set r.g.b separately and I need process for that but purify 
to ensure I have a tuple.
Maxim
8-Mar-2009
[793x2]
that's exactly the point of separating them :-)
btw adding node freezing, a very fundamental change to the engine, 
took  a huge 4 lines and about 40 bytes to implement!
Maxim
9-Mar-2009
[795x3]
announcing stream !  I am in the midst of  adding some more functionality 
to liquid which allows it to act as a signal processor (push method 
data-flow) the nice thing is that its incorporated  in the same plug, 
again, and using message stream will retain 100% compatibility with 
all the current plug featureset.
this will allow us to use window events directly within a lazy computing 
environment, for example, or provide dependency notification of child 
to parent changes.  this will allows a node to send a manual signal 
"downstream" and possibly take processing/setup decisions based on 
those messages.  downstream nodes should be able to return data in 
order to feedback the effects of the signal to its author, which 
might then, also activate some code.
so for liquid, this means a processing decision can be based on downstream 
nodes capability to handle it,  its like look-ahead processing