The duck's backside

as a newcomer I miss method overloading with named parameters and types
(Objective-C!). Mainly because my code is riddled with ugly "case
argument.class" and "raise unless Integer". But maybe that's the problem.

You cannot expect to carry your Objective-C style of programming over
to Ruby. Instead, if you want to have overloading you need to either
use different method names (appropriate if the overloaded methods act
differently) or you can do it with a single method (e.g. if the
overloading was just there to adjust type - for example on version
accepts an int and another accepts a float and internally you continue
processing with a float).

What is the Duck way to check arguments? I have to because I'm passing
on to a rather fragile web service.

The duck way is to not check arguments.

I only need numbers (ids) and strings in my instance variables, but
considered making a class for each one to catch illegal data in
initialize.

It's difficult to answer on such a general scale. Usually, if there
are particular requirements you have on arguments passed to methods
you should check inside the method that receives them. Note, that for
integers there is to_int so you can do:

class Foo
  def doit length
    @l = length.to_int
  end
end

Can you give a more concrete example?

Kind regards

robert

···

2008/5/28 Tobias Weber <towb@gmx.net>:

--
use.inject do |as, often| as.you_can - without end

This is off the top of my head so the usual caveats apply:

  def doit a, b, c = nil
    begin
      case
      when b && c
        raise
      when b && b.respond_to?(:to_int)
        uaid = "ignore" if b.to_int > 0
      when c && c.respond_to?(:to_int)
        c = "ignore" if c.to_int > 0
      else
        raise
      end
    rescue
      raise ArgumentError, "need exactly one number"
    end
    @post("first=#{a}&second=#{b.to_int}&third=#{c.to_int}")
  end

This makes the exclusion of b and c more explicit, which will make it much easier for a maintainer to understand what's going on. I've also made integer conversion explicit and focused the filtering logic on making sure it's appropriate as that's what you're really trying to achieve, however this kind of belt-and-braces approach suggests that you're tackling the problem from the wrong angle and should look at the data-flow elsewhere in your code.

One possibility would be to rejig the whole thing as follows:

  def doit a, v, param = :second
    raise ArgumentError, "needs a numeric value" unless v.respond_to?(:to_int)
    v = "ignore" if (param == :third) && v > 0
    @post("first=#{a}&second=#{v if param == :second}&third=#{v if param == :third}")
  end

and then evolve it from there, although it's also pretty damn ugly.

Where this is called you could write something along the lines of:

  if b && c then
    raise ArgumentError, "needs exactly one additional argument"
  else
    doit a, (b || c), (b.nil? ? :third : :second)
  end

which could be further encapsulated as:

  doit a, b, c = nil
    raise ArgumentError, "needs exactly one additional argument" if b && c
    v = b || c
    raise ArgumentError, "need a numeric parameter" unless v.respond_to?(:to_int)
    param = b.nil? ? :third : :second
    v = "ignore" if (param == :third) && v > 0
    @post("first=#{a}&second=#{v if param == :second}&third=#{v if param == :third}")
  end

Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net

···

On 28 May 2008, at 11:01, Tobias Weber wrote:

def doit(a, b, c = nil)
begin
   if c.nil? and b > 0
     c = "ignore"
   elsif b.nil? and c > 0
     uaid = "ignore"
   else
     raise
   end
rescue RuntimeError, NoMethodError
   raise ArgumentError, "need exactly one number"
end
@http.post("first=#{a}&second=#{b}&third=#{c}")
end

----
raise ArgumentError unless @reality.responds_to? :reason

You can do

@post("first=#{a}&second=#{b.to_int rescue 'ignored'}&third=#{c.to_int
rescue 'ignored'}")

Of course, defining a method for this would be better. How about:

def intify(x)
  x.to_int rescue "ignored"
end

def doit(a, b, c = nil)
  (b, c = intify(b), intify(c)).select {|x| Numeric === x}.size != 1
and
    raise ArgumentError, "need exactly one number"
  @http.post("first=#{a}&second=#{b}&third=#{c}")
end

Cheers

robert

···

On 28 Mai, 15:14, Tobias Weber <t...@gmx.net> wrote:

In article
<9560F017-58CA-48EB-BCC3-3B1675851...@games-with-brains.com>,
Eleanor McHugh <elea...@games-with-brains.com> wrote:

> > uaid = "ignore"

Ups, shoulda been c =

> @post("first=#{a}&second=#{b.to_int}&third=#{c.to_int}")

Won't work as the web service actually expects either a number or the
string "ignored"

In article
<9560F017-58CA-48EB-BCC3-3B16758516C1@games-with-brains.com>,

    uaid = "ignore"

Ups, shoulda been c =

Which makes things simpler :wink:

  doit a, b, c = nil
    raise ArgumentError, "needs exactly one additional argument" if b && c
    v = b || c
    raise ArgumentError, "need a numeric parameter" unless v.respond_to?(:to_int)
    @post "first=#{a}&" + (b.nil? ? "second=ignored&third=#{v}" : "second=#{v}&third=ignored")
  end

So that doit() is only passed legal values? That should be the case, but
I want to make extra sure not to give that foreign web service something
it can't swallow.

  def doit a, v, param = :second
    raise ArgumentError, "needs a numeric value" unless v.respond_to?(:to_int)
    v = "ignore" if (param == :third) && v > 0

That is essentially overloading doit() for first or second parameter,
and a good idea! So far I just wrapped the http calls in convenience
methods one by one.

I'm not suggesting it's a good idea...

Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net

···

On 28 May 2008, at 14:15, Tobias Weber wrote:

Eleanor McHugh <eleanor@games-with-brains.com> wrote:

----
raise ArgumentError unless @reality.responds_to? :reason

This looks like a great solution!

But if you want to check for numeric parameters, would it be better just to use Numeric === v ? I know this isn't the ducky way, but it certainly seems more "intentional."

///ark

···

On May 28, 2008, at 8:24 AM, Eleanor McHugh wrote:

  doit a, b, c = nil
    raise ArgumentError, "needs exactly one additional argument" if b && c
    v = b || c
    raise ArgumentError, "need a numeric parameter" unless v.respond_to?(:to_int)
    @post "first=#{a}&" + (b.nil? ? "second=ignored&third=#{v}" : "second=#{v}&third=ignored")
  end

That'd be marginally more readable but to my mind it's overly cautious: what's the point of using Ruby if you're still going to follow static typing conventions?

Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net

···

On 28 May 2008, at 18:57, Mark Wilden wrote:

On May 28, 2008, at 8:24 AM, Eleanor McHugh wrote:

  doit a, b, c = nil
    raise ArgumentError, "needs exactly one additional argument" if b && c
    v = b || c
    raise ArgumentError, "need a numeric parameter" unless v.respond_to?(:to_int)
    @post "first=#{a}&" + (b.nil? ? "second=ignored&third=#{v}" : "second=#{v}&third=ignored")
  end

This looks like a great solution!

But if you want to check for numeric parameters, would it be better just to use Numeric === v ? I know this isn't the ducky way, but it certainly seems more "intentional."

----
raise ArgumentError unless @reality.responds_to? :reason

The only point of using Ruby (or any other tool in the universe) is to get a job done. :slight_smile: I would never use a Ruby feature just because Ruby makes it possible.

Numeric === v is not a static typing convention (see http://en.wikipedia.org/wiki/Type_system\). It's just OOP. It says in computer-understandable terms exactly what you expressed in English: "v is numeric."

I don't even know what the ability to respond to :to_int means. Does that mean the entity is numeric? Does a numeric string qualify? Does a floating point number qualify? Could Array support this method? Does every class that responds to to_int do semantically equivalent things? (think Cowboy#draw and Artist#draw). The only way to tell is to test it or look it up. This doesn't make it "marginally" less readable than Numeric === v, IMO.

Different strokes, of course...

///ark

···

On May 28, 2008, at 11:45 AM, Eleanor McHugh wrote:

But if you want to check for numeric parameters, would it be better just to use Numeric === v ? I know this isn't the ducky way, but it certainly seems more "intentional."

That'd be marginally more readable but to my mind it's overly cautious: what's the point of using Ruby if you're still going to follow static typing conventions?

> That'd be marginally more readable but to my mind it's overly
> cautious: what's the point of using Ruby if you're still going to
> follow static typing conventions?

The only point of using Ruby (or any other tool in the universe) is to
get a job done. :slight_smile: I would never use a Ruby feature just because Ruby
makes it possible.

Put it this way: What's the point of using, say, Erlang, if you never use its
concurrency features?

Granted, Ruby has a bit more going for it, but a lot of the joy of using Ruby
is how much less work you end up having to do when you don't have to think
about types too much.

. It's just OOP. It says in computer-understandable terms exactly what
you expressed in English: "v is numeric."

No, it says "v is of class Numeric." It's very explicit, and makes the
assumption that anything which acts like a number will eventually inherit
from Numeric.

I don't even know what the ability to respond to :to_int means.

I think it would be :to_i, actually... And I'd probably just call foo.to_i,
rather than testing for the existence of to_i.

Another possibility is: v.integer?

Does
that mean the entity is numeric?

In a sense.

Does a numeric string qualify?

Yes, it'll be parsed.

Does a
floating point number qualify?

Yes, it'll be rounded down.

Could Array support this method?

Anything could. Open classes mean you could add one to Array. But out of the
box, it doesn't appear to.

Does
every class that responds to to_int do semantically equivalent things?

Probably -- to_i is very much baked into the language, along with to_s and
friends.

Remember the above -- I could actually completely redefine Array, or Numeric,
etc. So even your assumption that "Numeric === foo" tests for Numeric is
really only based on convention -- you're assuming that no one, anywhere in
your code, is doing stuff like this:

Numeric = nil

(think Cowboy#draw and Artist#draw).

Yes, that is a downside of duck typing, as currently implemented, but doesn't
really apply to :to_i.

Also, context matters. If Cowboy and Artist are both in a GUI widget library,
that Cowboy is asking for trouble. And it's worth asking how the Cowboy came
to be in an art studio, or how the Artist came to be in a saloon -- there are
likely going to be more elegant solutions than

if Cowboy === bill
...

···

On Wednesday 28 May 2008 15:09:23 Mark Wilden wrote:

On May 28, 2008, at 11:45 AM, Eleanor McHugh wrote:

But if you want to check for numeric parameters, would it be better just to use Numeric === v ? I know this isn't the ducky way, but it certainly seems more "intentional."

That'd be marginally more readable but to my mind it's overly cautious: what's the point of using Ruby if you're still going to follow static typing conventions?

The only point of using Ruby (or any other tool in the universe) is to get a job done. :slight_smile: I would never use a Ruby feature just because Ruby makes it possible.

Numeric === v is not a static typing convention (see http://en.wikipedia.org/wiki/Type_system\). It's just OOP. It says in computer-understandable terms exactly what you expressed in English: "v is numeric."

No, it states that v inherits from the base class Numeric, and that is very much a static typing mindset, just projected onto an OO idiom. However Ruby is very much a dynamic language in which an instance of an object is not defined purely in terms of a chain of class inheritance, or even of mix-ins because an instance can have new methods directly attached to it. This being the case it makes much more sense to see if an instance responds to a given message of interest and then to act accordingly than to try and make assumptions based upon incomplete inheritance information.

I don't even know what the ability to respond to :to_int means. Does that mean the entity is numeric? Does a numeric string qualify? Does a floating point number qualify? Could Array support this method? Does every class that responds to to_int do semantically equivalent things? (think Cowboy#draw and Artist#draw). The only way to tell is to test it or look it up.

Yes. But as to_i, to_int, to_f, to_a, to_s and to_str are well known messages you can have a high confidence that when these are present in an instance they mean exactly what you expect them to mean. In practice this extends to a much larger vocabulary.

This doesn't make it "marginally" less readable than Numeric === v, IMO.

Different strokes, of course...

Exactly. If you don't like Duck Typing don't use it. It's perfectly possible to design code in Ruby similarly to the way you would in Java or C++ if that's what you're comfortable with. Just don't be surprised if you find yourself writing a lot more code than is necessary.

Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net

···

On 28 May 2008, at 21:09, Mark Wilden wrote:

On May 28, 2008, at 11:45 AM, Eleanor McHugh wrote:

----
raise ArgumentError unless @reality.responds_to? :reason

The only point of using Ruby (or any other tool in the universe) is to
get a job done. :slight_smile: I would never use a Ruby feature just because Ruby
makes it possible.

Put it this way: What's the point of using, say, Erlang, if you never use its
concurrency features?

All I can do is repeat what I said: the ONLY point to ANYthing (in programming) is as a means to accomplish some purpose. If using Erlang accomplishes a given purpose best, then it should be used, no matter what its concurrency capabilities. One reason might simply be that a given programmer is more comfortable in that language than another, and can therefore accomplish the task faster.

Granted, Ruby has a bit more going for it, but a lot of the joy of using Ruby
is how much less work you end up having to do when you don't have to think
about types too much.

I think you mean "classes," not "types." At any rate, I don't see how Numeric === v involves more work than the alternative, so I don't think that criterion applies here.

No, it says "v is of class Numeric." It's very explicit, and makes the
assumption that anything which acts like a number will eventually inherit
from Numeric.

Well, the desired goal is in fact to recognize objects that are numeric. One of the purposes of classes in OOP is to categorize things.

I don't even know what the ability to respond to :to_int means.

I think it would be :to_i, actually... And I'd probably just call foo.to_i,
rather than testing for the existence of to_i.

:to_i is actually rather different, as it will convert a string (even a non-numeric string like "2a"). That's an example of having to know the implementation of the method to determine whether testing responds_to? makes sense. For all I know, :to_i may in fact be the desired method, but Elizabeth used :to_int, and I assume it was for a reason.

Remember the above -- I could actually completely redefine Array, or Numeric,
etc. So even your assumption that "Numeric === foo" tests for Numeric is
really only based on convention -- you're assuming that no one, anywhere in
your code, is doing stuff like this:

Numeric = nil

That's not merely being unconventional--that's insanity. :slight_smile: Anyway, it applies even more so to methods, which aren't in the global namespace.

(think Cowboy#draw and Artist#draw).

Yes, that is a downside of duck typing, as currently implemented, but doesn't
really apply to :to_i.

Also, context matters. If Cowboy and Artist are both in a GUI widget library,
that Cowboy is asking for trouble.

That's true, but it wasn't my point. The question is whether all methods with the same name in all active classes should be semantically equivalent. I think that's a rather larger assumption than that Numeric means "numeric."

///ark

···

On May 28, 2008, at 1:44 PM, David Masover wrote:

> Put it this way: What's the point of using, say, Erlang, if you
> never use its
> concurrency features?

All I can do is repeat what I said: the ONLY point to ANYthing (in
programming) is as a means to accomplish some purpose. If using Erlang
accomplishes a given purpose best, then it should be used, no matter
what its concurrency capabilities. One reason might simply be that a
given programmer is more comfortable in that language than another,
and can therefore accomplish the task faster.

Even if the problem doesn't require concurrency, the main reason for choosing
Erlang in the first place is its threading model. If you don't like Erlang's
threading, chances are, the rest of it is done better in other languages.

I'm not saying that we don't want you if you won't do Ruby duck typing. Just
saying that I consider duck typing to be a major draw to Ruby in the first
place.

I kind of feel like you're doing the equivalent of this:

i = 0
while(i < some_array.length)
  do_something_with(some_array[i])
  i += 1
end

Yes, Ruby can do that, but I think most of us agree that a major appeal of
Ruby is being able to do this instead:

some_array.each { |item|
  do_something_with item
}

> No, it says "v is of class Numeric." It's very explicit, and makes the
> assumption that anything which acts like a number will eventually
> inherit
> from Numeric.

Well, the desired goal is in fact to recognize objects that are
numeric. One of the purposes of classes in OOP is to categorize things.

Given single inheritance, you're not going to force everything into the exact
category it belongs. I know I implemented a class to represent DNS serial
numbers and their associated math. It didn't inherit from Numeric, but it did
have to_i.

Maybe that was bad design on my part, but the point of duck typing is that we
don't need to care if it calls itself "Numeric". Instead, we care that it
acts like a Numeric -- it responds_to +, -, and probably to_i and integer?

You've probably heard all this before, of course.

> Remember the above -- I could actually completely redefine Array, or
> Numeric,
> etc. So even your assumption that "Numeric === foo" tests for
> Numeric is
> really only based on convention -- you're assuming that no one,
> anywhere in
> your code, is doing stuff like this:
>
> Numeric = nil

That's not merely being unconventional--that's insanity. :slight_smile: Anyway, it
applies even more so to methods, which aren't in the global namespace.

Alright, without altering the global namespace, and with very possibly a good
excuse, I could do something like this:

class IpAddress < Integer
  def to_s
    # return '12.34.56.78'
  end
end

Now, that actually won't work without a bit of massaging -- the numeric
classes don't have constructors. And there's already a built in IP address
class, so this would be pointless.

But I'm not sure there's any more reason to believe that something which is a
Numeric (or claims to be) is going to give you the semantics you want, than
to believe the same of something which supports to_i (or to_int, which is
probably more correct).

>> (think Cowboy#draw and Artist#draw).
>
> Yes, that is a downside of duck typing, as currently implemented,
> but doesn't
> really apply to :to_i.
>
> Also, context matters. If Cowboy and Artist are both in a GUI widget
> library,
> that Cowboy is asking for trouble.

That's true, but it wasn't my point. The question is whether all
methods with the same name in all active classes should be
semantically equivalent. I think that's a rather larger assumption
than that Numeric means "numeric."

The assumption you're making with Numeric isn't that Numeric means "numeric",
but that all possibly numeric values are contained in Numeric.

I think your use case had something to do with a fragile web service, so this
actually could make a lot of sense to you -- it might even be worth checking
if it's an Integer.

But in the general case, I like that much of my code is actually abstract
enough to swap something of an entirely different type (or class) in and have
it do something useful. Recently, I actually wrote an entire class for
storing things (a two-dimensional map) without knowing what kind of object
I'd be filling it with. I ended up filling it with Symbols.

···

On Wednesday 28 May 2008 17:23:30 Mark Wilden wrote:

On May 28, 2008, at 1:44 PM, David Masover wrote:

Not really, no. That reflects an attitude that has more to do with
C++ or Java than with OOP. Not everything which behaves as a number
will inherit from Numeric, so that makes it useless and potentially
misleading as a categorization tool.

If you want you know whether an object is in some category in an OO
way, you come up with a way to ask it. E.g. if you want to know if an
object is iterable, you ask it if it responds to #each. Or you simply
treat it as if it is in that category, and see what happens. If you
want to *assert* that object to must be in a category, you tell it to
convert itself (and it will tell you if it can't).

With that said, I'm not really on the fanatical duck-typing end of
things either. I believe there is value in doing proactive contract
checking at what I will call for lack of a better term "package
boundaries". Duck-typing errors are not always obvious or easy to
track down. I like to have firewalls that I can be fairly confident
will catch faulty assumptions in a straightforward and obvious way,
without having to work back along the chain from a secondary or even
tertiary side-effect of an object failing to quack. For this reason
I've been known to put pre- and post-condition assertions in layers of
code that interact with third-party code.

···

On Wed, May 28, 2008 at 6:23 PM, Mark Wilden <mark@mwilden.com> wrote:

Well, the desired goal is in fact to recognize objects that are numeric. One
of the purposes of classes in OOP is to categorize things.

--
Avdi

Home: http://avdi.org
Developer Blog: http://avdi.org/devblog/
Twitter: http://twitter.com/avdi
Journal: http://avdi.livejournal.com

I think it would be :to_i, actually... And I'd probably just call foo.to_i,
rather than testing for the existence of to_i.

:to_i is actually rather different, as it will convert a string (even a non-numeric string like "2a"). That's an example of having to know the implementation of the method to determine whether testing responds_to? makes sense. For all I know, :to_i may in fact be the desired method, but Elizabeth used :to_int, and I assume it was for a reason.

I used to_int because it happened to be the synonym that popped into my head at the time I was writing the code. It probably makes more sense to use to_i though as that's often implemented outside the Numeric class hierarchy for objects which can be represented by an integer.

Also, context matters. If Cowboy and Artist are both in a GUI widget library,
that Cowboy is asking for trouble.

That's true, but it wasn't my point. The question is whether all methods with the same name in all active classes should be semantically equivalent. I think that's a rather larger assumption than that Numeric means "numeric."

Numeric may well mean "numeric" in some particular sense, but that is only a subset of all objects which may have a valid numeric representation. As I said, you're applying a static typing mindset to a place where it's not necessary and whilst Ruby will let you do that, in the long term you'll find yourself doing much more work with very little (if any) gain in software robustness. In fact if you're writing a library you'll introduce additional fragility to code interfacing with it because Ruby programmers generally expect Duck Typing and write accordingly.

Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net

···

On 28 May 2008, at 23:23, Mark Wilden wrote:

On May 28, 2008, at 1:44 PM, David Masover wrote:

----
raise ArgumentError unless @reality.responds_to? :reason

One of the weaknesses of classic Booch, et al OOP is that one of the
purposes of classes in OOP is to categorize things.

Classes in classic OOP languages conflate a variety of concepts and cram
them into one structure which does none of them particularly well:

     1. Classes are the unit of state.
     2. Classes are the unit of access control.
     3. Classes are the unit of functional dispatch.

In extreme cases (Java, I'm looking at you here!) classes are also the
unit of packaging. (In other classic OOP language cases the unit of
packaging is an ad-hoc mess. C++ I'm looking at you here!)

I personally have always preferred the Dylan model (which I understand
comes from the CLOS model, watered-down somewhat):

     1. Classes are the unit of state.
     2. Modules (and, to a point, libraries) are the unit of access
        control.
     3. Generic functions are the unit of functional dispatch.
        (Multi-methods! Yay!)

And, unlike Java or C++, libraries are the unit of packaging.

I found that neatly layered structure of orthogonal concerns modelled by
separate mechanisms a breath of fresh air after coming from the bizarre
world of class OOP.

···

On Thu, 2008-05-29 at 07:23 +0900, Mark Wilden wrote:

One of the purposes of classes in OOP is to categorize things.

--
Michael T. Richter <ttmrichter@gmail.com> (GoogleTalk:
ttmrichter@gmail.com)
When debugging, novices insert corrective code; experts remove defective
code. (Richard Pattis)

Wasn't my use case. :slight_smile:

///ark

···

On May 28, 2008, at 6:25 PM, David Masover wrote:

I think your use case had something to do with a fragile web service, so this
actually could make a lot of sense to you -- it might even be worth checking
if it's an Integer.

Well, the desired goal is in fact to recognize objects that are numeric. One
of the purposes of classes in OOP is to categorize things.

Not really, no. That reflects an attitude that has more to do with
C++ or Java than with OOP.

I must respectfully disagree. I learned OOP (in 1989) before C++ was even hardly available on PCs, much less Java. The OOP language I learned was an amalgam of Smalltalk and Lisp. I cut my teeth on Bertrand Meyer, Adele Goldbert, Brad Cox, and Grady Booch. I can say quite categorically, that in OOP, classes are ways to generalize. You generalize based on characteristics and behaviors. A class is not simply a random collection of methods. It would be rather useless if class was unrelated to category.

But I'm finding these remarks about "attititude" kind of amusing. It's like Ruby isn't a tool, it's a "mindset." We don't forgo something like Numeric === v because it's _wrong_ (the OP in fact said it was slightly more readable), but because Ruby has duck-typing, and why use Ruby if you can't duck type? I hope I'm not the only person to see how totally back-asswords this kind of argument is.

Not everything which behaves as a number will inherit from Numeric, so that makes it useless and potentially misleading as a categorization tool.

And not everything that implements #to_int will be numeric, or can even be converted to a number in a meaningful way for a context that expects numbers. It's implementer's choice. However, the use case might be that any object with that method is fine and dandy. In that case, I totally agree that checking for response to it is reasonable, if not 100% reliable. But if we're looking for Fixnums, Floats, and other builtin classes, then checking again Numeric seems straightforward.

The presence of a method called #each does not make an object iterable. The only way that would be possible is if everyone who wrote an #each method decided that was what it meant. What does show far more accurately whether it's iterable is whether it includes Enumerable. Including Enumerable shows that the #each method is for iterating, rather than pricing, or something else.

If you want you know whether an object is in some category in an OO way, you come up with a way to ask it.

True. And often the most straightforward and fundamental way to do that is to call its #class method.

I like duck-typing. It distinguishes great OOP languages like Smalltalk and Ruby from wannabes like C++ and Java. But classes are not simply random collections of methods. Their power is indeed to categorize and generalize objects, which can be specialized with inheritance (another old school concept, I suppose). So if I can solve a programming problem simply by asking what builtin class an object is, as opposed to seeing if it responds to a certain method name, knowing nothing about what that method actually does, I'll go with the former. It's just the simplest thing that could possible work. But wait--maybe that hoary criterion is out of fashion too?

///ark

···

On May 28, 2008, at 8:59 PM, Avdi Grimm wrote:

On Wed, May 28, 2008 at 6:23 PM, Mark Wilden <mark@mwilden.com> wrote:

That's true, but it wasn't my point. The question is whether all
methods with the same name in all active classes should be
semantically equivalent. I think that's a rather larger assumption
than that Numeric means "numeric."

Numeric may well mean "numeric" in some particular sense, but that is
only a subset of all objects which may have a valid numeric
representation. As I said, you're applying a static typing mindset to
a place where it's not necessary and whilst Ruby will let you do that,
in the long term you'll find yourself doing much more work with very
little (if any) gain in software robustness. In fact if you're writing
a library you'll introduce additional fragility to code interfacing
with it because Ruby programmers generally expect Duck Typing and
write accordingly.

BTW, your code makes in fact two assumptions :

- The object has a valid numeric value (via .to_i(nt) in your case),
- But also that the object has a _string_ representation that happens to
    be that numeric value (via the #{} interpolation).
    
Wouldn't it be better to write this :

@post "first=#{a}&" + (b.nil? ?
                       "second=ignored&third=#{v.to_int}" :
                       "second=#{v.to_int}&third=ignored")

Ellie

Fred

···

Le 29 mai à 06:45, Eleanor McHugh a écrit :

On 28 May 2008, at 23:23, Mark Wilden wrote:

--
Steps have been taken, a silent uproar Has unleashed the dogs of war
You can't stop what has begun Signed, sealed, they deliver oblivion
We all have a dark side, to say the least And dealing in death is the
nature of the beast (Pink Floyd, Dogs of War)

These are simply the attributes of a type: a set of possible values and a set of possible operations.

///ark

···

On May 29, 2008, at 3:47 AM, Michael T. Richter wrote:

On Thu, 2008-05-29 at 07:23 +0900, Mark Wilden wrote:

One of the purposes of classes in OOP is to categorize things.

One of the weaknesses of classic Booch, et al OOP is that one of the purposes of classes in OOP is to categorize things.

Classes in classic OOP languages conflate a variety of concepts and cram them into one structure which does none of them particularly well:
Classes are the unit of state.
Classes are the unit of access control.
Classes are the unit of functional dispatch.

My mistake, sorry about that.

Nice talking, though! I've been on ruby-talk less than a day, and I'm happy to
be here.

···

On Wednesday 28 May 2008 21:45:25 Mark Wilden wrote:

On May 28, 2008, at 6:25 PM, David Masover wrote:

> I think your use case had something to do with a fragile web
> service, so this
> actually could make a lot of sense to you -- it might even be worth
> checking
> if it's an Integer.

Wasn't my use case. :slight_smile:

So if I can solve a programming problem simply by asking what builtin class an object is, as opposed to seeing if it responds to a certain method name, knowing nothing about what that method actually does, I'll go with the former.

There are more ducks in heaven and earth, Horatio, than are
dreamt of in your philosophy.

require 'delegate'

=> true

x = SimpleDelegator.new(123)

=> 123

x.class

=> SimpleDelegator

x.kind_of? Numeric

=> false

x.is_a? Numeric

=> false

x.respond_to? :to_int

=> true

x.to_int

=> 123

Regards,

Bill

···

From: "Mark Wilden" <mark@mwilden.com>