On 9/9/10 6:33 AM, "Martin J. Drst" wrote: > On 2010/09/09 3:50, Kurt Stephens wrote: > >> --------------------------------------------------- >> >> I'd like to implement: >> >> x // y # and x //= y >> >> => >> >> (tmp = x) != nil ? tmp : y Excuse my mistake, perhaps this should be: (tmp = x).nil? ? nil : y Thus: x //= y => (tmp = x).nil? ? (x = y) : tmp E.g.: x[:foo] //= 123 => (tmp2 = (tmp1 = x)[:foo]).nil? ? (tmp1[:foo] = y) : tmp2 Works like &&=, except will not clobber false lhs. This greatly simplifies setting non-nil defaults. I believe this is a also a perl6 construct. Since "//" and "//=" are binary operators they should not conflict with "//" as the empty Regexp. But they would certainly complicate the lexer/parser. > > One case that I remember having met frequently, and that seems to be > related to this, is: > In a method chain, apply methods successively, except if the receiver is > nil, in which case, just keep it as nil. > > As an example, I'd like to write something like: > > ((tmp1=a).nil? ? nil : tmp1.method1(args)) > > as something like: > > a.unless_nil.method1(args) See &&. below. > >> And >> >> x&&.y&&.z # and x//.y//.z >> >> => >> >> (tmp = x) && (tmp = tmp.y) && tmp.z > > Shouldn't that be > (tmp = x) && tmp.y && tmp.z ? That would make more sense to me. Also,is > there a way to express this as a binary operator? > rcvr &&. selector => (tmp = rcvr) && tmp.selector Consider: x&&.y&&.z similar to x.y.z but with false checks on each LHS expr. > And what's the semantics of x//.y//.z ? > rcvr //. selector => (tmp = rcvr).nil? ? nil : tmp.selector Thus: x//.y//.z is similar to: x.y.z but with nil checks on each LHS expr. This simplifies code like: if x && x.y && x.y.z ... end Which, if #x, X#y or Y#z are expensive methods, is sometimes rewritten: if (tmp = x) && (tmp = tmp.y) && (tmp = tmp.z) ... end This leads to a .= operator :) if (tmp = x) && (tmp .= y) && (tmp .= z) ... end lhs .= mcall(*margs) => lhs = lhs.mcall(*margs) i.e: lhs &&= val => lhs = lhs && val > Regards, Martin. KAS