[RCR] array or with non-array

Hi,

I know but it is a matter of cost both efficiency and implementation.
Since current "restriction" covers 99.99% usage of strings, it is
kinda hard to pay cost to implement full polymorphic arguments like
you mentioned.

Right now, it probably covers 100%. I think it is hard to
determine the usefulness of many features like this until it
they are implemented.

But you need to convince its usefulness before someone implement it.

Convenience is important, sometimes more than pure duck typing.

I'm more of a purist and thus prefer the purity over the
convenience. And I know there may not be many in my camp.

I don't know about numbers, but a purist were not able to create Ruby.
He would create something very different from Ruby.

It would definitely increase the code size. But, it shouldn't
change the run-time efficiency.

I wasn't talking about performance cost. It was implementation cost.

              matz.

···

In message "Re: [RCR] array or with non-array" on Thu, 4 Aug 2005 00:03:44 +0900, Eric Mahurin <eric_mahurin@yahoo.com> writes:

Hi --

>But, this wasn't really what my #1 above was about. It was
>about overloaded methods where the functionality is
determined
>by looking at the type of the arguments. One example would
be
>String#[arg]:
>
>str[fixnum] => fixnum or nil
>str[range] => new_str or nil
>str[regexp] => new_str or nil
>str[other_str] => new_str or nil
>
>All of these behave very different. The way you figure out
>what to do is based on type - which goes against the
>duck-typing philosophy. I think the only advantage of
>combining all of these functions into one method is
>convenience. But, by doing so you loose the ability to
handle
>more general duck-typed/polymorphic arguments.

class != type. Type is at the heart of duck-typing; class isn't :slight_smile:

Convenience is important, sometimes more than pure duck
typing.
There still be a room for improvement though.

I'm more of a purist and thus prefer the purity over the
convenience. And I know there may not be many in my camp.

I'm not clear on how you define purity or purism, but it doesn't
bother me that array[1] and array[1..3] do different things. Maybe
it's because a few core methods where a few core classes are
hard-coded allows for so much richness later, or something along those
lines -- a kind of bootstrapping.

David

···

On Thu, 4 Aug 2005, Eric Mahurin wrote:

--
David A. Black
dblack@wobblini.net

David A. Black wrote:

I'm not sure I agree conceptually with the idea of
matching an IO object to a pattern.

You need this to be able to do fancy parsing/lexing in ruby.

It actually feels to me like
there *should* be an explicit, intervening string representation.

And in this string would be what? The entire file contents? That works
well for small files, and I've done it many times myself. It doesn't
scale well, tho. If your explicit string contains only part of the
file, you get other problems.

Eric Mahurin wrote:

If Regexp#match(obj) used just obj[pos], we could match a
Regexp across a file with the above.

Yes, and it would be orders of magnitude slower. This kind of thing is
the major performance issue in Cursor at the moment. Efficiency is a
tin god, but some attention needs be paid to it, to make sure that you
don't define interfaces that are inherently inefficent, for example.

Yukihiro Matsumoto wrote:

Again, it's a matter of cost. For example, full duck typing
Regexp#match likely requires re-implementation of a regular expression
matching engine in Ruby.

Not really, no. You can read into a buffer and match against the
buffer. This works pretty well for every pattern without anchors.
Supporting anchors too requires a smidge of rewriting the Regexp at
runtime. My current implementation interprets ^ and \A (or $ and \Z
when matching backward) as matching at the current file position,
rather than the beginning of file.

It's a minor pain, but I have most of the necessary code already.
There's a compromise or two that have to be made: an upper limit on
the length of a single match, ^ won't work right in some rarer cases
until regexp lookback in ruby 1.9. I don't like this, but these
restrictions seem minor enough, considering the massive increase in
functionality otherwise.

···

On 8/3/05, David A. Black <dblack@wobblini.net> wrote:

Hi --

On Wed, 3 Aug 2005, Eric Mahurin wrote:

> --- "David A. Black" <dblack@wobblini.net> wrote:
>
>> Hi --
>>
>> On Wed, 3 Aug 2005, Eric Mahurin wrote:
>>
>>> I think a primary example where I would really like real
>>> duck-typing in a built-in would be Regexp#match(str). This
>>> requires the arg to be a String. I would really like to
>> have
>>> this be able to operate on a file. If I implement a class
>> that
>>> walks like, talks like, quacks like a String but really
>>> accesses a file (practically did that in my rubyforge
>> cursor
>>> project), it wouldn't do any good because Regexp#match only
>>> takes a String - period.
>>
>> You can define #to_str on your object to get Regexp#match to
>> accept
>> it as an argument:
>>
>> irb(main):006:0> o = Object.new
>> => #<Object:0x401f3db4>
>> irb(main):007:0> def o.to_str; "hi"; end
>> => nil
>> irb(main):008:0> /i/.match(o)
>> => #<MatchData:0x401eec60>
>
> This doesn't really help in the polymorphism department. This
> is no different than writing:
>
> /i/.match(o.to_str)

I think it's quite different, certainly in appearance and to some
extent in logic. I'm not sure how much more polymorphic one could
get, unless one had every object present its .to_s representation for
matching, which would not be good.

>>> The Regexp#match method could be implemented to take ANY
>> object
>>> that implemented a some subset of the String API.
>>
>> I think there's a semantic or perhaps definitional issue
>> here, though.
>> What does it mean for a regular expression to "match" an
>> arbitrary
>> object? I don't think it's just a matter of what methods the
>> object
>> has. The object has to match the pattern, and the patterns
>> are
>> descriptions of strings. I'm not sure how you would detect a
>> pattern
>> like /[A-Z]{3}(\d\d)?/ in something that wasn't a string.
>
> By the same methods used in String. It could get away with
> just one method to accomplish the task: #[positive_int]. We
> could put this in IO for example:
>
> class IO
> def (i)
> self.pos = i
> if eof? # pos can go beyond the eof
> self.pos = i-1
> return(nil) if eof?
> self.pos = i
> end
> getc
> end
> end
>
> If Regexp#match(obj) used just obj[pos], we could match a
> Regexp across a file with the above.

scanf.rb does something along those lines. (It gets tricky with
scanf, because of whitespace and stuff, but it's basically position
and index manipulation.) Then again, scanf has always been
stream-oriented. I'm not sure I agree conceptually with the idea of
matching an IO object to a pattern. It actually feels to me like
there *should* be an explicit, intervening string representation.

Nor do I think this is a sign of failure or rejection of the principle
of duck typing or anything like that. Everything doesn't have to do
everything. For instance, you can't do File.rename on an integer, or
divide a hash by a float. And yes, I know that the reductio ad
absurdum is not proof of anything :slight_smile: I just think there's some
nuance to some of the cases, including the specificity of the
pattern/string connection. I don't see pattern matching as strictly a
matter of integer indexability.

David

--
David A. Black
dblack@wobblini.net

Huh? Where do you get that? Duck-typing is about not caring
about what the type/class the object is. Duck-typing in the
purest sense is calling the methods of the arguments without
regard to what the class of the object is.

In the above, the functionality is clearly affected by the
class. If you wrote the single arg String# above you'd have
something like this:

def (i)
    if Fixnum===i
        # retrieve character at index i
    elsif Range===i
        # retrieve slice designated by the Range i
    elsif Regexp===i
        # retrieve slice found by the Regexp i
    elsif String===i
        # retrieve slice that is the same as String i
    else
        raise
    end
end

That is far from duck-typing. This very much cares about the
type/class of the argument. It both restricts the class and
makes decisions about what functionality to have based on that
type. You could use respond_to? instead of klass=== to help,
but that would like just introduce ambiguities about what
functional branch to take - you'd have to favor one case over
another. Implementation-wise, I don't have a problem with
choosing how to operate based on class, but this decision
should not affect functionality - only performance.

···

--- "David A. Black" <dblack@wobblini.net> wrote:

Hi --

On Thu, 4 Aug 2005, Eric Mahurin wrote:

>> >But, this wasn't really what my #1 above was about. It
was
>> >about overloaded methods where the functionality is
>> determined
>> >by looking at the type of the arguments. One example
would
>> be
>> >String#[arg]:
>> >
>> >str[fixnum] => fixnum or nil
>> >str[range] => new_str or nil
>> >str[regexp] => new_str or nil
>> >str[other_str] => new_str or nil
>> >
>> >All of these behave very different. The way you figure
out
>> >what to do is based on type - which goes against the
>> >duck-typing philosophy. I think the only advantage of
>> >combining all of these functions into one method is
>> >convenience. But, by doing so you loose the ability to
>> handle
>> >more general duck-typed/polymorphic arguments.

class != type. Type is at the heart of duck-typing; class
isn't :slight_smile:

____________________________________________________
Start your day with Yahoo! - make it your home page
http://www.yahoo.com/r/hs

Hi,

···

In message "Re: array or with non-array" on Thu, 4 Aug 2005 00:58:51 +0900, Caleb Clausen <vikkous@gmail.com> writes:

Yukihiro Matsumoto wrote:

Again, it's a matter of cost. For example, full duck typing
Regexp#match likely requires re-implementation of a regular expression
matching engine in Ruby.

Not really, no. You can read into a buffer and match against the
buffer. This works pretty well for every pattern without anchors.
Supporting anchors too requires a smidge of rewriting the Regexp at
runtime. My current implementation interprets ^ and \A (or $ and \Z
when matching backward) as matching at the current file position,
rather than the beginning of file.

It's a minor pain, but I have most of the necessary code already.
There's a compromise or two that have to be made: an upper limit on
the length of a single match, ^ won't work right in some rarer cases
until regexp lookback in ruby 1.9. I don't like this, but these
restrictions seem minor enough, considering the massive increase in
functionality otherwise.

It's good to hear it's not impossible. Although I'm not agree very
much about "massive" increase of functionality.

              matz.

class != type. Type is at the heart of duck-typing; class
isn't :slight_smile:

Huh? Where do you get that? Duck-typing is about not caring
about what the type/class the object is. Duck-typing in the

Class is irrelevant, but you'd be well-advised to care about what the
type is, or you'll find yourself with a lot of NoMethodErrors :slight_smile:

purest sense is calling the methods of the arguments without
regard to what the class of the object is.

An object's type is the sum of all of its capabilities. Duck typing
involves focusing on an object's capabilities -- its type -- and not
worrying about its class. You also don't have to "worry" about its
type (and I agree with those who say that duck typing does not mean
sticking respond_to? everywhere). But you are dealing with type --
dealing with it, in the sense of making assumptions about it, writing
code governed by those assumptions, etc. -- and not dealing with
class.

I like Jim Weirich's characterization of Ruby as "a duck-typed
language", because it captures the fact that, in a sense, one is
always doing duck typing in Ruby. That's also why I always feel
uneasy with meta-concepts like the "duck type" of an object. What
people sometimes call the "duck type" of an object, I call simply the
type of the object. Duck typing, in that respect, is a way of
describing an approach to programming that arises very organically
from Ruby.

David

···

On Thu, 4 Aug 2005, Eric Mahurin wrote:

--- "David A. Black" <dblack@wobblini.net> wrote:

--
David A. Black
dblack@wobblini.net

Whatever your definition of type is, a method should not care
(i.e. check) about the types of its arguments. It should just
assume that the arguments have the capabilities that it wants.
That is is core of duck-typing, is it not?

I also think your definition of type (or duck-type) is too
restrictive. Instead of "An object's type is the sum of all of
its capabilities", it should be "An argument's type is the sum
of its capabilities that the method uses or documents that it
may use". Every method argument has its own duck-type.

But, back to the original thing that spawned this discussion -
the String# method. I claim that this violates the spirit of
duck-typing all over the place because of the class (or type)
checking done to accomplish multiple functions. Do you claim
it is duck-typed? If so, show me how you could get the
multiple functions that it has and still be duck-typed.

My point is that when coding ruby, we are encouraged to use
duck-typing, but the ruby library itself does not. Seems kind
of hypocritical.

···

--- "David A. Black" <dblack@wobblini.net> wrote:

On Thu, 4 Aug 2005, Eric Mahurin wrote:

> --- "David A. Black" <dblack@wobblini.net> wrote:
>
>> class != type. Type is at the heart of duck-typing; class
>> isn't :slight_smile:
>
>
> Huh? Where do you get that? Duck-typing is about not
caring
> about what the type/class the object is. Duck-typing in
the

Class is irrelevant, but you'd be well-advised to care about
what the
type is, or you'll find yourself with a lot of NoMethodErrors
:slight_smile:

> purest sense is calling the methods of the arguments
without
> regard to what the class of the object is.

An object's type is the sum of all of its capabilities. Duck
typing
involves focusing on an object's capabilities -- its type --
and not
worrying about its class. You also don't have to "worry"
about its
type (and I agree with those who say that duck typing does
not mean
sticking respond_to? everywhere). But you are dealing with
type --
dealing with it, in the sense of making assumptions about it,
writing
code governed by those assumptions, etc. -- and not dealing
with
class.

I like Jim Weirich's characterization of Ruby as "a
duck-typed
language", because it captures the fact that, in a sense, one
is
always doing duck typing in Ruby. That's also why I always
feel
uneasy with meta-concepts like the "duck type" of an object.
What
people sometimes call the "duck type" of an object, I call
simply the
type of the object. Duck typing, in that respect, is a way
of
describing an approach to programming that arises very
organically
from Ruby.

____________________________________________________
Start your day with Yahoo! - make it your home page
http://www.yahoo.com/r/hs

David A. Black wrote:

class != type. Type is at the heart of duck-typing; class
isn't :slight_smile:

Huh? Where do you get that? Duck-typing is about not caring
about what the type/class the object is. Duck-typing in the

Class is irrelevant, but you'd be well-advised to care about what the
type is, or you'll find yourself with a lot of NoMethodErrors :slight_smile:

purest sense is calling the methods of the arguments without
regard to what the class of the object is.

An object's type is the sum of all of its capabilities. Duck typing
involves focusing on an object's capabilities -- its type -- and not
worrying about its class. You also don't have to "worry" about its
type (and I agree with those who say that duck typing does not mean
sticking respond_to? everywhere). But you are dealing with type --
dealing with it, in the sense of making assumptions about it, writing
code governed by those assumptions, etc. -- and not dealing with
class.

I like Jim Weirich's characterization of Ruby as "a duck-typed
language", because it captures the fact that, in a sense, one is
always doing duck typing in Ruby. That's also why I always feel
uneasy with meta-concepts like the "duck type" of an object. What
people sometimes call the "duck type" of an object, I call simply the
type of the object. Duck typing, in that respect, is a way of
describing an approach to programming that arises very organically
from Ruby.

David

warn "philosophical pootling ahead"

Maybe we need to begin talking about ruby not just as a language with
formal, constructive meanings, but as a "language game" in the sense of
Wittgenstein, with meaning accruing through use.[1]

Obviously, any particular ruby program has a constructive meaning
assigned by the interpreter. But that doesn't capture the way meanings
change as a library is used in different ways over time. I can write a
library that works in one way with all the inputs I've considered, but
because those inputs are "duck typed", there exist future
interpretations of my library, based on inputs with unforseen
implementations, that cannot be explained in terms of the "types" I was
thinking of when I wrote my library.

[1] Ludwig Wittgenstein (Stanford Encyclopedia of Philosophy)

···

On Thu, 4 Aug 2005, Eric Mahurin wrote:

--- "David A. Black" <dblack@wobblini.net> wrote:

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Eric Mahurin said:

My point is that when coding ruby, we are encouraged to use
duck-typing, but the ruby library itself does not. Seems kind
of hypocritical.

It seems to me that much of this encouragement to use duck-typing comes
from other "purists" like yourself, and not from Matz himself, who seems
to care more about pragmatic, usable code and not just purity. While
maintaining some amount of purity is certainly a worthwhile goal, it
should not eclipse usability.

I think that flexible methods like String# can be pretty useful, though
I'll admit the semantics can sometimes break the POLS. But not very often.

Ryan

Hi --

Whatever your definition of type is, a method should not care
(i.e. check) about the types of its arguments. It should just
assume that the arguments have the capabilities that it wants.
That is is core of duck-typing, is it not?

I guess it usually involves method arguments, though only indirectly
-- meaning, it's about how objects are treated, and what assumptions
are made about them, whether or not they arrived on the scene as
method arguments (though I guess that's the usual scenario).

I also think your definition of type (or duck-type) is too
restrictive. Instead of "An object's type is the sum of all of
its capabilities", it should be "An argument's type is the sum
of its capabilities that the method uses or documents that it
may use". Every method argument has its own duck-type.

My definition of "type" isn't restricted to method arguments, so your
definition doesn't work as a drop-in replacement :slight_smile:

I don't find the concept of a "duck-type" very useful. *Type* in
Ruby, without the duck, already reflects something dynamic, flexible,
unrestricted by class/module ancestry, and so on. Duck typing is a
way of leveraging type, in this sense.

But, back to the original thing that spawned this discussion -
the String# method. I claim that this violates the spirit of
duck-typing all over the place because of the class (or type)

(definitely class, in this case)

checking done to accomplish multiple functions. Do you claim
it is duck-typed? If so, show me how you could get the
multiple functions that it has and still be duck-typed.

My point is that when coding ruby, we are encouraged to use
duck-typing, but the ruby library itself does not. Seems kind
of hypocritical.

You're turning it into a game of "Simon Says" -- "Uh oh, you branched
on class membership: you're out!" :slight_smile: I think it's a little more
subtle than that. As I said before, I tend to be accepting of
hard-coded class-based things when they're in the core, since it
provides such a flexible and powerful programming environment and
there's no mandate to base one's Ruby style on the class-name checks
in the C source.

David

···

On Thu, 4 Aug 2005, Eric Mahurin wrote:

--
David A. Black
dblack@wobblini.net