[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

invasive parameters as method mode variables

Trans

12/6/2006 3:50:00 PM

Working on a method where I would like one part of it's operations to
be optional. Here's the crux of the code:

def parse_multicommand( line=nil, arity={} )
argv = parse_line(line)
argv = multi_flag(argv) # optional?

# ...
end

I would prefer not to add another parameter to the method signiture to
signify this option b/c its rare and it would complexify the call to
much, especially if there is more than one optional part --which is
possible. But other tahn that I don't have much choice, I'll probably
have to create an extra method called
#parse_multicommand_without_multi_flag. Yuk!

Not that helps me presently, but this did get me to thinking of using a
"global" flag that can be set external to the method. That would work
but it wouldn't be thread safe. Then it occured to me the
Binding.of_caller could be helpful here. Using the Binding#[] extension
for local variable access:

def parse_multicommand( line=nil, arity={} )
argv = parse_line(line)
argv = multi_flag(argv) unless Binding.of_caller[:no_multi_flag]

# ...
end

Then to use:

no_multi_flag = true
parse_multicommand( line )

I know this breaks the whole idea of function encapsulation, but it has
it's advantages in certain cases like mine. It also might be of usedin
a few other places like String#each's separator. So that got me to
thinking of a cleaner way to provided this capability of invasive
parameters as "method mode variables".

def parse_multicommand( line=nil, arity={} )
argv = parse_line(line)
argv = multi_flag(argv) unless --no_multi_flag

# ...
end

# '--' indicates a method mode variable
--no_multi_mode = true
parse_multicommand( line )

Thouhgts?

T.


12 Answers

James Gray

12/6/2006 3:58:00 PM

0

On Dec 6, 2006, at 9:49 AM, Trans wrote:

> Thouhgts?

My thoughts on your current suggestion: Yuck. You really want this
to become so common that the language itself supports it? I
definitely don't. The whole usage case is a code smell, in my opinion.

My thoughts on your suggestions in general: You sure spend a lot of
time trying to rewrite Ruby's syntax. ;)

James Edward Gray II


Ara.T.Howard

12/6/2006 4:02:00 PM

0

Trans

12/6/2006 5:38:00 PM

0


ara.t.howard@noaa.gov wrote:

> method + state => object

good point. though it moves me away from the simplicity of single call.
also i wonder about things like String#each. the global default for
separator is not really the ideal implementation, but #each can't be
made a class.

Thanks,
T.


Trans

12/6/2006 5:55:00 PM

0


James Edward Gray II wrote:
> On Dec 6, 2006, at 9:49 AM, Trans wrote:
>
> > Thouhgts?
>
> My thoughts on your current suggestion: Yuck. You really want this
> to become so common that the language itself supports it? I
> definitely don't. The whole usage case is a code smell, in my opinion.

perhaps. just exploring the idea. certainly Binding.of_caller allows
this kind of thing more or less. and I think there are good occassions
to use Binding.of_caller. in this case the no_multi_key option would
rarely be used. so having to turn the whole thing into a class, as ara
suggests, for one (or two) uncommon parameter seems like overkill,
although maybe it is better to do so.

I did think of one other way it could be done, inspried by an idea _why
had long ago:

#

def no_multi_flag
class << self
def multi_flag(argv); argv; end
end
yield
class << self
undef_method :multi_flag
end
end

though that sort of smells worse in my opinion.

> My thoughts on your suggestions in general: You sure spend a lot of
> time trying to rewrite Ruby's syntax. ;)

I know. It's sort or a hobby of mine. I have a general interest in
understanding the human <-> programming language interface.

T.


Robert Klemme

12/6/2006 6:38:00 PM

0

On 06.12.2006 18:37, Trans wrote:
> ara.t.howard@noaa.gov wrote:
>
>> method + state => object

I would have put it differently: command pattern. Your method seems
pretty complex so you can change it into a command object. If the
problem at hand is complex then it probably needs a complex solution.
But I would not go down the metaprogramming route.

> good point. though it moves me away from the simplicity of single call.
> also i wonder about things like String#each. the global default for
> separator is not really the ideal implementation, but #each can't be
> made a class.

Really?

>> require 'enumerator'
=> true
>> %w{foo bar baz}.to_enum(:each)
=> #<Enumerable::Enumerator:0x3a6b00>

Cheers

robert

David Vallner

12/6/2006 9:49:00 PM

0

Trans wrote:
> ara.t.howard@noaa.gov wrote:
>
>> method + state => object
> #each can't be made a class.
>

Callable objects anyone?

(Yes, I've been too deep in the Python sugar bin recently :) Transparent
coroutines are prettiful.)

David Vallner

Trans

12/6/2006 10:57:00 PM

0


Robert Klemme wrote:
> On 06.12.2006 18:37, Trans wrote:
> > ara.t.howard@noaa.gov wrote:
> >
> >> method + state => object
>
> I would have put it differently: command pattern. Your method seems
> pretty complex so you can change it into a command object. If the
> problem at hand is complex then it probably needs a complex solution.
> But I would not go down the metaprogramming route.
>
> > good point. though it moves me away from the simplicity of single call.
> > also i wonder about things like String#each. the global default for
> > separator is not really the ideal implementation, but #each can't be
> > made a class.
>
> Really?
>
> >> require 'enumerator'
> => true
> >> %w{foo bar baz}.to_enum(:each)
> => #<Enumerable::Enumerator:0x3a6b00>

Sure. But I would think it preferable to just call str.each. Not have
to resort to Enumerators. Doing...

"this is a string".to_enum(:each, //).select { |c| ..

is less efficent and less readable (once you know what $/ is) then

$/ = // ; "this is a string".select { |c| ...

And if we can do it gloablly, which is not ideal, then why not do it
better with a local "method mode variable"?

Of course, I'm still not sure why it's such a bad idea to allow
Enumberable to pass thru a parameter to #each.

T.


Louis J Scoras

12/7/2006 1:52:00 AM

0

On 12/6/06, Trans <transfire@gmail.com> wrote:

> And if we can do it gloablly, which is not ideal, then why not do it
> better with a local "method mode variable"?

Because you commit a gross violation of encapsulation for zero
increase in expressiveness? =)


--
Lou.

Trans

12/7/2006 3:11:00 AM

0


Louis J Scoras wrote:
> On 12/6/06, Trans <transfire@gmail.com> wrote:
>
> > And if we can do it gloablly, which is not ideal, then why not do it
> > better with a local "method mode variable"?
>
> Because you commit a gross violation of encapsulation for zero
> increase in expressiveness? =)

The violation is much worse with a global var. With a local var the
violation is very minimal, plus the varaible can be specifically
designated as "method mode". So it's actually very similar to keyword
arguments. Eg.

each(:separator => //)

Just with a little extra flexability in that the method mode can apply
to multiple calls in the same local scope and the mode variable doesn't
have to intermingle with true data parameters.

As for expressiveness. I'm not sure how youre measuring that, the
to_enum version is clearly more convoluted (with exception of the $/
var, but that could be called $input_separator or some such name
instead too).

In anycase, perhaps any breakage of the local encapsulation is too
much, and matz will never grant us Binding.of_caller. But then why does
this global default on String#each persist?

T.

Louis J Scoras

12/7/2006 1:45:00 PM

0

On 12/6/06, Trans <transfire@gmail.com> wrote:

> The violation is much worse with a global var. With a local var the
> violation is very minimal, plus the varaible can be specifically
> designated as "method mode".

You are exactly right: it is _less_ of a violation. However, I think
this is the part where I'm supposed to mention something about a
``slippery slope.''

> So it's actually very similar to keyword arguments. Eg.
>
> each(:separator => //)
>
> Just with a little extra flexability in that the method mode can apply
> to multiple calls in the same local scope and the mode variable doesn't
> have to intermingle with true data parameters.

Again, you are right, but why do this when you already have an
objects, whose entire reason for existence is to track state
information. Why not make it an honest to goodness part of the
interface?

enumerable.separator = //
# use each

> As for expressiveness. I'm not sure how youre measuring that, the
> to_enum version is clearly more convoluted (with exception of the $/
> var, but that could be called $input_separator or some such name
> instead too).

No, it's perfectly clear. What it lacks is concision, and while
concision is a desirable quality, it is not worth trading for clarity
and transparency. Saving a few keystrokes is not a good reason for
adding a new mechanism that acts at a distance.

> In anycase, perhaps any breakage of the local encapsulation is too
> much, and matz will never grant us Binding.of_caller. But then why does
> this global default on String#each persist?

I can't offer much insight on that, but I'd suspect it's historical.


--
Lou.