From: Daniel Nugent Date: 2005-09-09T01:21:04+09:00 Subject: Re: The Laziest Variable in the Whooole World Whoops, you're right, should have used ! defined? as the conditional test instead. (Not that you can't use whatever conditional that pleases you) Also, there's a mistake in the above code, $data_flow_variable and $dfv are supposed to be the same variable. (That'll teach me to not version control my discussion group email). If there's a better way of doing this, I'd like to hear about it. The reason I decided to go with this is that you can do the lazy evaluation and get data flow as a bonus (incidentally, I understand disgruntlement with the tight loop, I am, however, unaware of a better way). About the reverse-event registration thing: Yeah, it's kind of like RSS syndication like that. Maybe you could put a sleep in the loop? I dunno. On 9/8/05, Derek Wyatt wrote: > -----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----- > > -- -Dan Nugent