From: Derek Wyatt Date: 2005-09-08T23:10:23+09:00 Subject: Re: The Laziest Variable in the Whooole World -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 It's an interesting idea but it may be considered a slight perversion of the language. I would expect that dataflow would be handled better with pipes or sockets or shared objects or the like. ~ At the very least, run your example with -w :) Still, it's kind of an interesting little reverse-event registration bit of code (i.e. the source doesn't broadcast to the sinks, but the sinks simply read from the source when it becomes available -- i'm not happy with a busy-wait loop tho). Regs, D Daniel Nugent wrote: | Hello fellow Rubyists, | | Something got to niggling me in the back of my mind last week during a | lecture in my Programming Languages class about laziness in functions. | Basically, the point is that functions that don't evaluate until they | need to are cool. | | We can be pretty lazy right now with code generators that will let us | fake infinite series and stuff like that, but I think we can be even | LAZIER if we put our minds to it. | | Along these lines, I came up with this: | | class Lazy | | #DESTROY ALL METHODS! DESTROY ALL INSTANCE METHODS! | instance_methods.each { |m| undef_method m unless m =~ /^__/ } | | def initialize(switch = :one_eval, &block) | @code_block = block | @mode = switch | end | | def method_missing(symbol, *args) | if @mode == :one_eval | @real_obj ||= @code_block.call | @real_obj.__send__(symbol, *args) | else | @code_block.call().__send__(symbol, *args) | end | end | end | | What this does is let us wait until a value is really, actually needed | before the code that would provide it is evaluated. This is nice if | you wanted to put off that expensive retrieval operation until it was | actually needed, if at all, and if you're tricky about it, you can get | non-deterministic results just like the bastiche you want to be (just | set the switch to something besides :one_eval, now the block is called | ALL the time!). | | With a little bit of tricksyness, we can use this to let us turn | regular variables into dataflow variables, which, instead of causing | all sorts of errors because they're not ready yet, merely make the | program wait until they're darned well not nil (or whatever condition | you happen to need). For example: | | #Dataflow example | foo = Lazy.new do | while $data_flow_variable.nil? | end | $data_flow_variable | end | | bar = Thread.new {print foo} | baz = Thread.new {sleep(3);$dfv = "Hello World, sorry I'm late"} | | bar.join | baz.join | | This is, of course, trivial, but it demonstrates how you might employ | data flow for fun and profit (Especially if you could abstract | laziness and dataflowism into functions that did all the boring object | creation work for you, which, of course, you could). | | The question, of course, is where are the gaps here? Where does this | idea just fall apart and spew, SPEW all over the floor? I'm | reasonably sure you're all much more masterful at Ruby than I am and | stand a better chance at figuring out what could explode (I personally | expect that assignment will botch it up, but I can't be sure.) And, | if explosion is imminent, can it be fixed? | | Thanks for reading! | | PS: Thanks to Aria and binary42 for smacking me around a little and | pointing me to {|one, step, back|} and the BlankSlate idea there. - -- Derek Wyatt - C++ / Ruby / Unix Programmer http://derekwyatt.org -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.4 (MingW32) iD8DBQFDIEZLwwHFeC88e2IRAhdEAJ9xcxubLshcNKJpyV8TWZpKavPxOACfYZPE onAKgZDEDaJ0PJlAkY+Mbbc= =t54M -----END PGP SIGNATURE-----