Seeking advice on some method names

Hi all,

I'm preparing some methods for 'extensions' [1] and would like some
people's opinions on method names.

  Array#only
    [5].only -> 5
    [1,2,3].only -> exception

  Class.get_class
    Class.get_class("Test::Unit") -> Test::Unit
    Class.get_class("not-a-class") -> exception

    # Should 'get_class' be in Class or in Kernel?

  Class#bare_name
    Test::Unit.bare_name -> "Unit"

  String#line_wrap
    "the quick brown fox jumps ...".line_wrap(10)
       -> "the quick
           brown fox
           jumps ..."

Thanks,
Gavin

[1] http://extensions.rubyforge.org

  Array#only
    [5].only -> 5
    [1,2,3].only -> exception

I prefer: Array#one
to be complemented by
Array#one? #{|e| predicate(e)} true if exactly one match

and rounded out by
Array#any #=> return a random element, like Array#any?
Array#none # with addition of Array#none? {|e| predicate(e)}
Array#all #=> of questionable value

and separately
Array#include_all? (other_enumerable)

Gavin Sinclair wrote:

Hi all,

I'm preparing some methods for 'extensions' [1] and would like some
people's opinions on method names.

  Array#only
    [5].only -> 5
    [1,2,3].only -> exception

What is 'only' supposed to do?

James

  Class.get_class
    Class.get_class("Test::Unit") -> Test::Unit
    Class.get_class("not-a-class") -> exception

    # Should 'get_class' be in Class or in Kernel?

Why not String?
  "Test::Unit".to_class # => Test::Unit

My justification: it's analogous to String#to_sym.

Thanks,
Gavin

Sam

···

On Mon, 29 Nov 2004 11:31:06 +0900, Gavin Sinclair <gsinclair@soyabean.com.au> wrote:

[Gavin Sinclair <gsinclair@soyabean.com.au>, 2004-11-29 03.31 CET]

  Class.get_class
    Class.get_class("Test::Unit") -> Test::Unit
    Class.get_class("not-a-class") -> exception

Class.for_name, as in java.

    # Should 'get_class' be in Class or in Kernel?

in Module, maybe?

Hi all,

I'm preparing some methods for 'extensions' [1] and would like some
people's opinions on method names.

  Array#only
    [5].only -> 5
    [1,2,3].only -> exception

Maybe to_scalar would tell more clearly what it is doing?

  Class.get_class
    Class.get_class("Test::Unit") -> Test::Unit
    Class.get_class("not-a-class") -> exception

    # Should 'get_class' be in Class or in Kernel?

I'd call it Class.by_name(sym)

regards,

Brian

···

On Mon, 29 Nov 2004 11:31:06 +0900 Gavin Sinclair <gsinclair@soyabean.com.au> wrote:

--
Brian Schröder
http://www.brian-schroeder.de/

Should it be congruent with File.basename? Other suggestion: #rootname.

T.

···

On Sunday 28 November 2004 09:31 pm, Gavin Sinclair wrote:

  Class#bare_name
    Test::Unit.bare_name -> "Unit"

Return the _only_ element in an array. If there's not exactly one,
then "only" doesn't make sense, so an exception is raised. (At the
moment, the exception is RangeError, but I need to think about that.)

Gavin

···

On Monday, November 29, 2004, 2:06:25 PM, James wrote:

Gavin Sinclair wrote:

Hi all,

I'm preparing some methods for 'extensions' [1] and would like some
people's opinions on method names.

  Array#only
    [5].only -> 5
    [1,2,3].only -> exception

What is 'only' supposed to do?

  Array#only
    [5].only -> 5
    [1,2,3].only -> exception

I prefer: Array#one
to be complemented by
Array#one? #{|e| predicate(e)} true if exactly one match

and rounded out by

Array#any #=>> return a random element, like Array#any?

Array#none # with addition of Array#none? {|e| predicate(e)}

Array#all #=>> of questionable value

and separately
Array#include_all? (other_enumerable)

#any? and #all? are methods of Enumerable, not Array. I like the idea
of Enumerable#one? and Enumerable#none? to complement them.

But I don't think Enumerable#one? and Array#one are complementary;
they seem entirely different.

Likewise with Array#any: it's useful, but really has nothing to do
with #any? I'm implementing Array#rand, by the way.

Regarding Array#include_all?, you might want to look at Set.

Cheers,
Gavin

···

On Monday, November 29, 2004, 1:57:50 PM, itsme213 wrote:

Hi --

···

On Mon, 29 Nov 2004, Sam Stephenson wrote:

On Mon, 29 Nov 2004 11:31:06 +0900, Gavin Sinclair > <gsinclair@soyabean.com.au> wrote:
> Class.get_class
> Class.get_class("Test::Unit") -> Test::Unit
> Class.get_class("not-a-class") -> exception
>
> # Should 'get_class' be in Class or in Kernel?

Why not String?
  "Test::Unit".to_class # => Test::Unit

My justification: it's analogous to String#to_sym.

I'm not sure what either of these adds to const_get -- or, to put it
another way, why there should be a special method to do (essentially)
a const_get only for strings that represent class names.

David

--
David A. Black
dblack@wobblini.net

Good idea. I'm warming to Module.basename.

Thanks,
Gavin

···

On Monday, November 29, 2004, 11:55:38 PM, trans. wrote:

On Sunday 28 November 2004 09:31 pm, Gavin Sinclair wrote:

> Class#bare_name
> Test::Unit.bare_name -> "Unit"

Should it be congruent with File.basename? Other suggestion: #rootname.

#to_scalar is not really clear to me. I can foce my mind to think
that way, but it's not natural.

But obviously #only has attracted its fair share of comment as well.
It's very clear to me: return the _only_ element in the array.
Perhaps people have never felt the need for it, which I understand.

Gavin

···

On Monday, November 29, 2004, 9:56:12 PM, Brian wrote:

On Mon, 29 Nov 2004 11:31:06 +0900 > Gavin Sinclair <gsinclair@soyabean.com.au> wrote:

Hi all,

I'm preparing some methods for 'extensions' [1] and would like some
people's opinions on method names.

  Array#only
    [5].only -> 5
    [1,2,3].only -> exception

Maybe to_scalar would tell more clearly what it is doing?

David A. Black wrote:

Hi --

Class.get_class
   Class.get_class("Test::Unit") -> Test::Unit
   Class.get_class("not-a-class") -> exception

   # Should 'get_class' be in Class or in Kernel?

Why not String?
"Test::Unit".to_class # => Test::Unit

My justification: it's analogous to String#to_sym.

I'm not sure what either of these adds to const_get -- or, to put it
another way, why there should be a special method to do (essentially)
a const_get only for strings that represent class names.

Well, IIRC, const_get doesn't work with symbols that contain "::". In other words, const_get( "Test::Unit" ) would fail--you'd have to do const_get("Test").const_get("Unit"), which becomes cumbersome. I can think of several instances in my Net::SSH and Net::SFTP stuff alone where a standard #get_class method would have been useful (though far from necessary).

- Jamis

···

On Mon, 29 Nov 2004, Sam Stephenson wrote:

On Mon, 29 Nov 2004 11:31:06 +0900, Gavin Sinclair >><gsinclair@soyabean.com.au> wrote:

--
Jamis Buck
jgb3@email.byu.edu
http://www.jamisbuck.org/jamis

Hi --

> > Class.get_class
> > Class.get_class("Test::Unit") -> Test::Unit
> > Class.get_class("not-a-class") -> exception
> >
> > # Should 'get_class' be in Class or in Kernel?
>
> Why not String?
> "Test::Unit".to_class # => Test::Unit
>
> My justification: it's analogous to String#to_sym.

I'm not sure what either of these adds to const_get

AFAIK, const_get doesn't handle objects below its namespace, so you
can't const_get 'Foo::Bar', you have to Foo.const_get 'Bar'.

-- or, to put it
another way, why there should be a special method to do (essentially)
a const_get only for strings that represent class names.

I agree. Maybe String#to_const would be more appropriate?

David

--
David A. Black
dblack@wobblini.net

Sam

···

On Mon, 29 Nov 2004 13:34:24 +0900, David A. Black <dblack@wobblini.net> wrote:

On Mon, 29 Nov 2004, Sam Stephenson wrote:
> On Mon, 29 Nov 2004 11:31:06 +0900, Gavin Sinclair > > <gsinclair@soyabean.com.au> wrote:

Why? Because it is a common function that is easy to do wrong. The quick and
obvious choices (eval(string) and Object.const_get(string)) are flawed. And
the one-liner that does it correctly ...

   string.split("::").inject(Object) { |ns, n| ns.const_get(n) }

... is hardly transparent.

It is a common enough activity that having a standard and canonical way of
converting strings to classes would ease a number of tasks (e.g. anytime you
wish to specify a class in a config file, input stream or data base).

···

On Mon, 29 Nov 2004, Sam Stephenson wrote:
> Why not String?
> "Test::Unit".to_class # => Test::Unit

On Sunday 28 November 2004 11:34 pm, David A. Black wrote:

I'm not sure what either of these adds to const_get -- or, to put it
another way, why there should be a special method to do (essentially)
a const_get only for strings that represent class names.

--
-- Jim Weirich jim@weirichhouse.org http://onestepback.org
-----------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)

"Gavin Sinclair" <gsinclair@soyabean.com.au> wrote in message

#any? and #all? are methods of Enumerable, not Array.

Ah yes.

So now I think
   #one, #one?, #none, #none?, #any, #any?, #all, #all?
can all be on Enumerable, perhaps with overrides for Array.

I like the idea
of Enumerable#one? and Enumerable#none? to complement them.

I agree.

But I don't think Enumerable#one? and Array#one are complementary;
they seem entirely different.

Array#one {|x| pred} would complement Enumerable#one? {|x| pred}
so
Array#one
    is same as Array#one{|x|true}
    which complements Enumerable#one?{|x|true}

Likewise with Array#any: it's useful, but really has nothing to do
with #any?

Array#any{|x| pred} complements Enumerable#any? {|x| pred}
so
Array#any complements Enumerable#any?{|x|true}

This only problem I see is of course that:

  File.basename != "File"

But that's probably too insignificant to worry about.

T.

···

On Monday 29 November 2004 08:39 am, Gavin Sinclair wrote:

On Monday, November 29, 2004, 11:55:38 PM, trans. wrote:
> On Sunday 28 November 2004 09:31 pm, Gavin Sinclair wrote:
> > Class#bare_name
> > Test::Unit.bare_name -> "Unit"
>
> Should it be congruent with File.basename? Other suggestion: #rootname.

Good idea. I'm warming to Module.basename.

Hi --

David A. Black wrote:
> Hi --
>
>
>
>>
>>> Class.get_class
>>> Class.get_class("Test::Unit") -> Test::Unit
>>> Class.get_class("not-a-class") -> exception
>>>
>>> # Should 'get_class' be in Class or in Kernel?
>>
>>Why not String?
>> "Test::Unit".to_class # => Test::Unit
>>
>>My justification: it's analogous to String#to_sym.
>
>
> I'm not sure what either of these adds to const_get -- or, to put it
> another way, why there should be a special method to do (essentially)
> a const_get only for strings that represent class names.

Well, IIRC, const_get doesn't work with symbols that contain "::". In
other words, const_get( "Test::Unit" ) would fail--you'd have to do
const_get("Test").const_get("Unit"), which becomes cumbersome. I can
think of several instances in my Net::SSH and Net::SFTP stuff alone
where a standard #get_class method would have been useful (though far
from necessary).

Oh right, I forgot about that. There are some "deep" const_get
implementations floating around... along the lines of:

  def deep_const_get(str)
    str.split('::').inject(Object) {|a,b| a.const_get(b) }
  end

which might help.

David

···

On Mon, 29 Nov 2004, Jamis Buck wrote:

> On Mon, 29 Nov 2004, Sam Stephenson wrote:
>>On Mon, 29 Nov 2004 11:31:06 +0900, Gavin Sinclair > >><gsinclair@soyabean.com.au> wrote:

--
David A. Black
dblack@wobblini.net

Two equivalent code samples:

A)

    numbers.one { |n| n.prime? }
    numbers.any { |n| n.prime? }

B)

    numbers.select { |n| n.prime? }.only
    numbers.select { |n| n.prime? }.rand

I find (B) more intuitive. I'd rather see #select doing the
selection, instead of introducing yet more methods that select
elements. [1] Further, #rand and #only are telling me what
they're doing. #one and #any are "merely" complements of
#one? and #any?.

To expand further, I find #any quite reasonable, but #rand more so.
Array#rand is something I've implemented occasionally, and have seen
other requests and references. I find #one quite uncompelling,
because it sounds like #any: it doesn't express its one_and_only_one
meaning.

Cheers,
Gavin

[1] There are valid reasons to introduce more selection methods, but
these don't qualify, to my mind.

···

On Tuesday, November 30, 2004, 1:52:49 AM, itsme213 wrote:

But I don't think Enumerable#one? and Array#one are complementary;
they seem entirely different.

Array#one {|x| pred} would complement Enumerable#one? {|x| pred}
so
Array#one
    is same as Array#one{|x|true}
    which complements Enumerable#one?{|x|true}

Likewise with Array#any: it's useful, but really has nothing to do
with #any?

Array#any{|x| pred} complements Enumerable#any? {|x| pred}
so
Array#any complements Enumerable#any?{|x|true}

That's precisely how it's implemented in extensions. BTW it's now
Class.by_name.

  Class.by_name("::Test::Unit") -> Test::Unit

Gavin

···

On Monday, November 29, 2004, 3:53:43 PM, David wrote:

> I'm not sure what either of these adds to const_get -- or, to put it
> another way, why there should be a special method to do (essentially)
> a const_get only for strings that represent class names.

Well, IIRC, const_get doesn't work with symbols that contain "::". In
other words, const_get( "Test::Unit" ) would fail--you'd have to do
const_get("Test").const_get("Unit"), which becomes cumbersome. I can
think of several instances in my Net::SSH and Net::SFTP stuff alone
where a standard #get_class method would have been useful (though far
from necessary).

Oh right, I forgot about that. There are some "deep" const_get
implementations floating around... along the lines of:

  def deep_const_get(str)
    str.split('::').inject(Object) {|a,b| a.const_get(b) }
  end

which might help.