Binding precedence for first symbol arguments

I've been thinking about the last thread on module methods and
namespaces, and also the idea of method modifiers. There are times when
I just want one method that does a number of different but related
things. Th obligatory silly example,

class T
def dothis(sym, *args)
when :oneway
puts "One Way! #{args}"
when :another
puts "Another! #{args}"
end
end
end

t = T.new
t.dothis :oneway

But we can also do this without the space,

t.dothis:another

IMO that's nice. And allows me to get the effect that I want. What
would be even more convenient thgouh is if this later form, lacking the
space, would give the method precedence, so we could do,

t.dothis:another.upcase

and it would work, executing #dothis before #upcase. Then, also,
secondary parameters could be given without the initial comma. So,

t.dothis :oneway, 1

could instead be written,

t.dothis:oneway 1

I do not think this would present any ambiguity to the parser. In fact
I thnk it can be take to any number of initial symbols.

t.dothis:oneway:twoway:threeway
Where each subsequent symbol is another argument.

T

IthinktheresareasonwhyweputspacesinsentancesToomanywordsinarowmakesforverydifficultreading

PGP.sig (186 Bytes)

···

On 31 Jan 2005, at 18:40, Trans wrote:

I do not think this would present any ambiguity to the parser. In fact
I thnk it can be take to any number of initial symbols.

t.dothis:oneway:twoway:threeway
Where each subsequent symbol is another argument.

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

I gotta say wrt your original motivation, to me the need for this "feature" reeks of bad design. Even ignoring Eric's appeal for readability/separation of tokens, wanting a single method that "does a number of different but related things" says to me that maintainability and comprehensibility is going to be sacrificed in the medium-to-long run.

It encourages cramming another handler into an existing method when writing a new method is the appropriate thing to do. Documentation? Unit testing??? Gah.

And parsability??

You are asking the parser to differentiate var.method:arg.method between var.method(:arg).method and var.method(:arg.method) based on (I'm guessing) the context of already being within a method call. You'll break _all_ existing code that reads var.method arg.method.

I don't see how, given the original example and the followups, the benefits outweigh the costs.

···

On Jan 31, 2005, at 6:40 PM, Trans wrote:

...There are times when
I just want one method that does a number of different but related
things...

Eric,

There are the colons. So its not running all-together. Beside yous can
already do it for one symbol:

dothis:another

It already works, and the most common use case would be one initial
symbol. So typically you'll just see things like this:

str.inflect:plural

str.format:humanize

str.format:foreign_key true

This format is also more informative in that it tells you the method
(#format) takes a Symbol for the first argument.

How I proposed to do this in the last thread was to use a subclass. Eg.

class String
def inflect
Inflection.new( self )
end
class Inflection
def initialize( delegate )
super
@delegate = delegate
end
def plural
# ...
end
end
end

Thus...

str.inflect.plural

But the addtional object seems expensive in comparisson to a case
statement. Is it?

T

Ryan Davis wrote:

> ...There are times when
> I just want one method that does a number of different but related
> things...

I gotta say wrt your original motivation, to me the need for this
"feature" reeks of bad design. Even ignoring Eric's appeal for
readability/separation of tokens, wanting a single method that "does

a

number of different but related things" says to me that

maintainability

and comprehensibility is going to be sacrificed in the medium-to-long

run.

It encourages cramming another handler into an existing method when
writing a new method is the appropriate thing to do. Documentation?
Unit testing??? Gah.

Not necessarily. First off, if one takes this too its ends, one has a
whole lot more clutter in method name space. Moreover, there are a
number of methods that very only by a few variations.

For instance

File.new:ro( filename )

vs.

File.new( filname, FILE::READONLY )

or larger

File.new:creat:trunc:rdwr("newfile", 0644)

vs.

File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)

And parsability??

You are asking the parser to differentiate var.method:arg.method
between var.method(:arg).method and var.method(:arg.method) based on
(I'm guessing) the context of already being within a method call.

No, just on whether there's a space or not. Is there a third valid
interpetation that would make this impossible?

You'll break _all_ existing code that reads var.method arg.method.

? That should run jut as it does now as 'var.method(arg.method)'. You
must be trying to point out something else?

I don't see how, given the original example and the followups, the
benefits outweigh the costs.

Perhaps. It's just something that I have come across as a possibility.
At the moment I am preferring the use of an intermediary method, a
"methobox" in effect.

class String
def format
Format.new( self )
end
class Format
def self ; word ; end
def initialize( word )
@self = word
end
def jossle
r = ''
@self.each_char{ |c| r << ( c[0] % 2 == 0 ? c.upcase :
c.downcase ) }
r
end
end
end

"apple".format.jossle #=> aPpLe

In my mind, this sure beats the pants off of messing with modules and
keeps the namespace nice and clean and organized. Futher more, lower
routines that are considered more common can be "aliased" upward.
class String
    def jossle
      format.jossle
    end
  end

T

···

On Jan 31, 2005, at 6:40 PM, Trans wrote:

http://cgi.bramwell.plus.com/krblog/2004/07/avoid_boolean_p.html is a
thought provoking read on adding-to-the-api versus adding-to-the-arglist

martin

···

Ryan Davis <ryand-ruby@zenspider.com> wrote:

On Jan 31, 2005, at 6:40 PM, Trans wrote:

> ...There are times when
> I just want one method that does a number of different but related
> things...

I gotta say wrt your original motivation, to me the need for this
"feature" reeks of bad design. Even ignoring Eric's appeal for
readability/separation of tokens, wanting a single method that "does a
number of different but related things" says to me that maintainability
and comprehensibility is going to be sacrificed in the medium-to-long
run.

Yes... but it encourages bad habits of not putting spaces and commas.

PGP.sig (186 Bytes)

···

On 31 Jan 2005, at 20:05, Trans wrote:

Eric,

There are the colons. So its not running all-together. Beside yous can
already do it for one symbol:

dothis:another

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

Thanks martin,

Perhaps Kevin Rutherford is right. But her present such a limited use
case: a single true/false parameter. On the end of the spectrum is most
commonly used form of method invocation in the world, the Shell. And it
does not follow this. If it did we's have many more tools with names
like:

gzip
ungzip
gzip_force
ungzip_force
gzip_help
gzip_test
gzip_verbose
ungzip_verbose
gzip_force_verbose
ungzip_force_verbose
....
gzip_force_verbose_recusrvie_noname
....

Symbolic flags go a long way toward easing use for human beings. The
conditions they form within the function, while perhaps less efficient
in exectution, are not, as suggested, antithetical to good programming
as they have an avantage in creating DRYer code.

T

Hm. I think that in a language where you can't have any keyword-like
arguments, that makes total sense.

What T. is suggesting, I think, makes the API more verbose, but lets the
implementation treat it as booleans. . . which makes a lot of sense to
me. I've always hated code that had various factored out private helper
methods, or a large API of very similar functions. I can't see why

  def do_foo_with_arg(a)
    f = Foo.new
    f.arg = a
    f.run
  end

  def do_foo
    f = Foo.new
    f.run
  end

is any better than

  def do_foo(arg = nil)
    f = Foo.new
    f.arg = arg if arg
    f.run
  end

unless you needed to override the parts in a subclass. The second seems
far more succinct, though the example's nearly pathologically short.

For some reason, T.'s proposal makes a lot of sense to me -- I think of
whitespace as significant in that way already (the "foo.bar (baz)" vs
"foo.bar(baz)" distinction in the current parser makes total sense to
me) and I really like the way File.open:ro(filename) looks, and I would
enjoy an implementation that let me define it as

   def File.open(file, flags)

Or even, in a more overloaded method (line noise! Gasp!)

   def frob(arg, arg2, *args, **flags, &block)

Or, assuming it wasn't totally confusing to have some symbol overlap,
@flags.

Ari

···

On Tue, 2005-02-01 at 22:35 +0900, Martin DeMello wrote:

Ryan Davis <ryand-ruby@zenspider.com> wrote:
>
> On Jan 31, 2005, at 6:40 PM, Trans wrote:
>
> > ...There are times when
> > I just want one method that does a number of different but related
> > things...
>
> I gotta say wrt your original motivation, to me the need for this
> "feature" reeks of bad design. Even ignoring Eric's appeal for
> readability/separation of tokens, wanting a single method that "does a
> number of different but related things" says to me that maintainability
> and comprehensibility is going to be sacrificed in the medium-to-long
> run.

http://cgi.bramwell.plus.com/krblog/2004/07/avoid_boolean_p.html is a
thought provoking read on adding-to-the-api versus adding-to-the-arglist

----
Ruby web hosting?
http://theinternetco.net/offers/ruby