From: Joel VanderWerf Date: 2006-10-27T03:01:36+09:00 Subject: Re: Pass block instead of here document? Rick DeNatale wrote: > On 10/26/06, Joel VanderWerf wrote: >> Rick DeNatale wrote: >> ... >> > But in Smalltalk if you write: >> > >> > obj msg1;msg2 >> > >> > the object referenced by obj is sent msg1 and then msg2 in sequence, >> > regardless of the value returned by obj msg1. >> >> Not quite the same, but this is something similar that's been floating >> around the ml for a while: >> >> class Object >> def then >> yield(self) >> self >> end >> end >> >> hash = Hash.new. >> then do |h| h[1] = 2 end. >> then do |h| h[3] = 4 end >> >> p hash >> >> That's much clunkier syntactically, but it is actually useful in one >> case: when working with classes whose #new method doesn't take a block >> that allows further configuration of the new object. For example, >> sockets: >> >> def socket >> @socket ||= UDPSocket.open.then do |s| >> s.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true) >> s.connect("192.168.255.255", 1234) >> end >> end > > Of course this relies on UDPSocket::open returning the new socket > rather than something else. UDPSocket.open is the same as UDPSocket.new, which returns the new socket, as is standard for all #new methods. Actually, UDPSocket *does* take a block, so you don't need this construct here. It's for those cases (getting rarer and rarer as ruby libs evolve) where someone defines an #initialize method that does not take a block (or takes a block but does not yield the object to it). >> It works particularly well with the ||= assignment operator. > > Which in turn relies on the block evaluating to the socket as well. Actually, no. The value of the block is discarded, and #then returns the receiver. That's the point of the #then method. It yields self and then returns self. > It's more of a variation on Smalltalk's yourself than a cascade. > > Nice nonetheless. Thanks! -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407