Why is overloading invalid in ruby

Infinity = 1.0/0

def read_data(num_in = nil, num_out = nil, num_lines = Infinity)
unless inFile.nil?
@count = 0

File\.foreach\(inFile\) do |line|

      # def read_data(num_in, num_out, num_lines)
break if @count >= num_lines

  arr = line\.chomp\.split\(','\)
  float\_array = arr\.map \{ |x| x\.to\_f \}

      # def read_data(num_in, num_out)
      if num_in and num_out
   arr_in =
arr_out =
for i in 0...num_in
arr_in << float_array[i]
end

    in\_data\.push\(arr\_in\)
    for j in num\_in\.\.\.\(num\_in\+num\_out\)
      arr\_out &lt;&lt; float\_array\[j\]
    end

   out_data.push(arr_out)
      elsif num_in or num_out
        raise ArgumentError
      else
        # def read_data
        file_data.push(float_array)
end

  @count = @count \+ 1
end

file\_data

  end
end

···

On Thu, Jan 27, 2011 at 9:52 PM, Ted Flethuseo <flethuseo@gmail.com> wrote:

David Masover wrote in post #978005:

On Thursday, January 27, 2011 02:55:24 pm Ted Flethuseo wrote:

Ah that's too bad... I knew I could put some default values for x and y
and z.. getting the same effect sort of...

but this isn't a solution if the methods that I want to "overload" (I
call it
overload, not sure what the proper term should be) are
completely different, and are not differentiated simply by different
values.

If they're not differentiated by different values, how were you
expecting
overloading to work? If the problem is that you need the behavior to be
different, I think default values still work -- for example:

def sum_or_inverse a, b=nil
if b.nil?
-a
else
a+b
end
end

But I don't really know what you were asking.
I agree with Jesús. We need more details.

Ok.. I didn't want to post so much code but you asked for it. I am
trying to read a file, with a number of different methods. The methods
allow you to interpret the file as an input and output matrices, input
only or both but with only a number of rows.

Good Evening,

David Masover wrote in post #978005:
>> Ah that's too bad... I knew I could put some default values for x and y
>> and z.. getting the same effect sort of...
>>
>> but this isn't a solution if the methods that I want to "overload" (I
>> call it
>> overload, not sure what the proper term should be) are
>> completely different, and are not differentiated simply by different
>> values.
>
> If they're not differentiated by different values, how were you
> expecting
> overloading to work? If the problem is that you need the behavior to be
> different, I think default values still work -- for example:
>
> def sum_or_inverse a, b=nil
> if b.nil?
> -a
> else
> a+b
> end
> end
>
> But I don't really know what you were asking.
> I agree with Jesús. We need more details.

Ok.. I didn't want to post so much code but you asked for it. I am
trying to read a file, with a number of different methods. The methods
allow you to interpret the file as an input and output matrices, input
only or both but with only a number of rows.

How about this - I'm unsure of some of the variables - they seem a little
strange but I'm sure you can debug any issues in that respect - I just used
pretty much what you provided.

def read_data(num_in = nil, num_out = nil, num_lines = nil)
  #This just looks a little nicer than the if .nil? == false
  unless @inFile.nil?
    #Either we are provided the number of lines to use or we use them all
    num_lines ||= @inFile.length
    #Instead of counting where we are we just limit our group to what we
want
    myFiles = @inFile[0...num_lines]
    #Use our limited dataset
    File.foreach(myFiles) do |line|
      arr = line.chomp.split(',')
      float_array = arr.map { |x| x.to_f }
      #Make a choice based on the num_in variable
      if num_in.nil?
        @file_data.push(float_array)
      else
        #Much simpler here - no need for the loops and temp vars
        #Just grab what we need and move along
        in_data << float_array[0...num_in]
        out_data << float_array[num_in...(num_in+num_out)]
      end
    end
  end

  return @file_data
end

···

On Thu, Jan 27, 2011 at 6:52 PM, Ted Flethuseo <flethuseo@gmail.com> wrote:

> On Thursday, January 27, 2011 02:55:24 pm Ted Flethuseo wrote:

Yeah, there's a lot of duplicate stuff there. Also, why are you doing this
when there's a CSV class in the standard library?

http://ruby-doc.org/stdlib/libdoc/csv/rdoc/index.html

Anyway, it looks like you're copying and pasting a _lot_ between those
methods, so it also looks like if you DRYed it up a bit, it'd work just fine
with default arguments. Also, there's a bunch of ways this could be more
idiomatic... Here's a rough guess at what you're trying to do, at least for
this one method:

def read_data num_in=nil, num_out=nil, num_lines=nil
  # This does what you said above. Are you sure that's right?
  # Shouldn't it raise an error or something?
  return file_data if inFile.nil?

  # If I were you, I'd have the 'count' method pass through to
  # file_data.length or something, so this could be a local...
  @count = 0

  # Object-oriented programming means letting the object
  # figure out what to do, instead of calling functions
  # with that object. The File.foreach was a code smell to me.
  inFile.each_line do |line|
    break if num_lines && @count >= num_lines

    # Note that, unlike a proper CSV parser, this won't handle escaped commas.
    arr = line.chomp.split(',').map(&:to_f)

    if num_in
      # An each would be better than a foreach IMO, but if you want
      # the best speed and readability, why not rely on stuff arrays
      # already know how to do instead of writing the loop yourself?
      arr_in.push arr[0...num_in]

      if num_out
        # num_in and num_out are both counts, right?
        arr_out.push arr[num_in,num_out]
      end
    end

    @count += 1
  end

  file_data
end

Warning: I haven't tested the above code at all, but it _looks_ like it can
replace the read_data methods you wrote. Let me know. Still, I mostly did it
as an exercise, because if you were planning to actually work with CSVs, I'd
think your code should start with:

require 'csv'

···

On Thursday, January 27, 2011 08:52:03 pm Ted Flethuseo wrote:

David Masover wrote in post #978005:
> On Thursday, January 27, 2011 02:55:24 pm Ted Flethuseo wrote:
>> Ah that's too bad... I knew I could put some default values for x and y
>> and z.. getting the same effect sort of...
>>
>> but this isn't a solution if the methods that I want to "overload" (I
>> call it
>> overload, not sure what the proper term should be) are
>> completely different, and are not differentiated simply by different
>> values.
>
> If they're not differentiated by different values, how were you
> expecting
> overloading to work? If the problem is that you need the behavior to be
> different, I think default values still work -- for example:
>
> def sum_or_inverse a, b=nil
>
> if b.nil?
>
> -a
>
> else
>
> a+b
>
> end
>
> end
>
> But I don't really know what you were asking.
> I agree with Jesús. We need more details.

Ok.. I didn't want to post so much code but you asked for it. I am
trying to read a file, with a number of different methods. The methods
allow you to interpret the file as an input and output matrices, input
only or both but with only a number of rows.

class CSVFile
  attr_accessor :inFile
  attr_accessor :file_data
  attr_accessor :in_data
  attr_accessor :out_data
  attr_reader :count

  def initialize(file)
    @inFile = file
    @file_data =
    @count = 0
    @in_data =
    @out_data =
  end

  def read_data
    if inFile.nil? == false
      @count = 0
      File.foreach(inFile) do |line|
        arr = line.chomp.split(',')
        float_array = arr.map { |x| x.to_f }
        file_data.push(float_array)
        @count = @count + 1
      end
    end
    return file_data
  end

  def read_data(num_in, num_out)
    if inFile.nil? == false
      @count = 0
      File.foreach(inFile) do |line|
        arr = line.chomp.split(',')
        float_array = arr.map { |x| x.to_f }
        arr_in =
        arr_out =
        for i in 0...num_in
          arr_in << float_array[i]
        end

        in_data.push(arr_in)
        for j in num_in...(num_in+num_out)
          arr_out << float_array[j]
        end
        out_data.push(arr_out)
        @count = @count + 1
      end
    end
    return file_data
  end

  def read_data(num_in, num_out, num_lines)
    if inFile.nil? == false
      @count = 0
      File.foreach(inFile) do |line|
        if @count >= num_lines
          break;
        end

        arr = line.chomp.split(',')
        float_array = arr.map { |x| x.to_f }
        arr_in =
        arr_out =
        for i in 0...num_in
          arr_in << float_array[i]
        end

        in_data.push(arr_in)
        for j in num_in...(num_in+num_out)
          arr_out << float_array[j]
        end
        out_data.push(arr_out)
        @count = @count + 1
      end
    end
    return file_data
  end
end

Not very quackish.

···

On Fri, Jan 28, 2011 at 5:13 PM, Charles Oliver Nutter <headius@headius.com>wrote:

And it would be even cooler if Ruby supported some form of type-driven
pattern matching, so you could have different method bodies for
different input types rather than checking them over and over again.
But that's a post for another day :slight_smile:

I think the original poster provided an example of overloading based on the number of parameters but not their type.
Even restricting yourself to overloading by arity is a bit problematic in Ruby because the arity still has to be determined (in some cases) dynamically:

Actually, arity of callsite is always calculated in Ruby to know if
you should throw an ArgumentError (3 for 0 specified sort of errors)
against the method you are calling. It seems like overloading based
on arity is not such a bad idea to me based on some of the common
arity parsing idioms people do by hand in the first few lines of their
methods. What implementing arity-based overloads would do is get rid
of most of this code we put at the top of methods and perform that
logic in the Ruby implementation itself (in MRI in C vs in Ruby).

I'd also add that in JRuby, if the source arity matches the target
(non-rest, non-optional) arity, we do no calculation at all (for
arities up to 3). So if Ruby supported multiple overloads, it would
basically just work like our core arity-split methods do right now and
automatically route to the correct body.

Stylistically, I think the biggest issue is not realizing there are n
overloads and then implementing less than n overloads in an overridden
class.

An *excellent* point. This bites overload-supporting static languages
very frequently too.

- Charlie

···

On Mon, Jan 31, 2011 at 1:27 PM, Thomas E Enebo <tom.enebo@gmail.com> wrote:

On Mon, Jan 31, 2011 at 9:00 AM, Gary Wright <gwtmp01@mac.com> wrote:

Well, you could reinterpret "type driven" to be "respond_to driven". Almost
the same sentiment, but more embracing of OO as described in Rick's talk (
http://confreaks.net/videos/461-rubyconf2010-objects-are-just-objects-aren-t-they
).

Personally, I found it weird to not have overloading when I came from Java,
because I had fallen into a series of patterns based around it that I really
liked (one canonical method, with several overload ones for convenience,
that just take their arguments and translate them to the appropriate method
call of the real one). But now, I think Ruby's bag of argument tricks are
much more powerful. Initialization blocks, optional params through hash
support, optional arguments, etc I think are very powerful (might be nice if
the language supported the hashes a bit better), and really, I almost never
miss overloading, and I think the things you would lose by supporting it
would not be worth it.

···

On Fri, Jan 28, 2011 at 11:41 AM, Adam Prescott <mentionuse@gmail.com>wrote:

On Fri, Jan 28, 2011 at 5:13 PM, Charles Oliver Nutter > <headius@headius.com>wrote:

> And it would be even cooler if Ruby supported some form of type-driven
> pattern matching, so you could have different method bodies for
> different input types rather than checking them over and over again.
> But that's a post for another day :slight_smile:
>

Not very quackish.

Neither are case/when statements like this:

case obj
when String ...
when Regexp ...
end

But sometimes that's what you need to do.

- Charlie

···

On Fri, Jan 28, 2011 at 11:41 AM, Adam Prescott <mentionuse@gmail.com> wrote:

On Fri, Jan 28, 2011 at 5:13 PM, Charles Oliver Nutter > <headius@headius.com>wrote:

And it would be even cooler if Ruby supported some form of type-driven
pattern matching, so you could have different method bodies for
different input types rather than checking them over and over again.
But that's a post for another day :slight_smile:

Not very quackish.

Adam Prescott wrote:

And it would be even cooler if Ruby supported some form of type-driven
pattern matching, so you could have different method bodies for
different input types rather than checking them over and over again.
But that's a post for another day :slight_smile:

Not very quackish.

But it's used all over the core and standard libraries.

I tried implementing my own version of Enumerable#inject, which has no
less than *four* overloads and is almost impossible to implement in
Ruby because of that:

    Enumerable[$A]#inject($B) {|$B, $A| $B } → $B
    Enumerable[$A]#inject {|$A, $A| $A } → $A
    Enumerable[$A]#inject($B, Symbol) → $B
    Enumerable[$A]#inject(Symbol) → $A

(For obvious reasons, Ruby doesn't have a standardized syntax for
talking about types, so I made one up. I hope you get what I mean.)

For example, the Rubinius implementation of Enumerable#inject contains
about 8 lines of actual code (ignoring comments, blank lines and lines
consisting only of 'end' or '}'). Two implement the actual behavior of
inject, the other six basically implement an ad hoc,
informally-specified, bug-ridden, slow implementation of half of
argument-based dispatch.

In fact, almost every method in kernel/common/enumerable.rb in
Rubinius contains at least one line that does not actually contribute
anything to the logic of the method but instead changes the behavior
of the method in some way, shape or form based on the number or class
of the arguments.

And I've seen that in other code as well, not just Rubinius's or my
own, and not just in code that tries to replicate stdlib behavior.

Several projects I know chose YARD over RDoc as their documentation
tool, because it allows them to at least document their overloads
easily, even if writing them is cumbersome.

Personally, I would enjoy being able to dispatch on arguments in
addition to receivers. Martin Odersky hinted that he is interested in
adding argument-based dispatch to Scala, it will be interesting to see
what he comes up with, although he also said that it's a very hard
problem (because of its interactions with overloading) and will take
many years if it happens at all.

Note that I avoided the use of the term "overloading" and used
"argument-based dispatch" instead. I'm pretty sure that's what the OP
meant, since overloading happens statically and simply doesn't make
sense in Ruby.

jwm

···

On Fri, Jan 28, 2011 at 5:13 PM, Charles Oliver Nutter > <headius@headius.com>wrote:

Maybe I'm overlooking something but I wasn't suggesting that you don't need to calculate arity but instead was pointing out that you can't just calculate it at parse time but sometimes need to calculate it at call time.

foo(1,2) # the call arity can be computed at parse time
foo(*a) # the call arity must be computed at call time

So in an 'overload-based-on-arity' scheme there might be some optimization opportunities for some call sites but not for every call site.

Seems like you can get pretty far though with just a little meta-programming with no special language support:

module Arity
  def overload(base)
    define_method(base) do |*args|
      argc = args.size
      method_name = "#{base}_#{argc}"
      if respond_to?(method_name)
        send(method_name, *args)
      else
        raise ArgumentError, "wrong number of arguments (no method for #{argc} arguments)"
      end
    end
  end
end

class A
  extend Arity

  overload :foo

  def foo_0
    puts "foo with no arguments"
  end

  def foo_1(arg1)
    puts "foo with 1 argument: #{arg1.inspect}"
  end

end

A.new.foo # dispatches to A#foo_0
A.new.foo(1) # dispatches to A#foo_1
A.new.foo(1,2) # ArgumentError

Gary Wright

···

On Jan 31, 2011, at 2:47 PM, Charles Oliver Nutter wrote:

On Mon, Jan 31, 2011 at 1:27 PM, Thomas E Enebo <tom.enebo@gmail.com> wrote:

On Mon, Jan 31, 2011 at 9:00 AM, Gary Wright <gwtmp01@mac.com> wrote:

I think the original poster provided an example of overloading based on the number of parameters but not their type.
Even restricting yourself to overloading by arity is a bit problematic in Ruby because the arity still has to be determined (in some cases) dynamically:

Actually, arity of callsite is always calculated in Ruby to know if
you should throw an ArgumentError (3 for 0 specified sort of errors)

Whenever the overloading topic comes up, I wonder about what the
future holds regarding true named arguments. Does anyone know?

Specifically, MacRuby has an extension to the usual hash parameters
that seems pretty complicated to me, but allows it to interact fairly
painlessly with Objective-C*. It basically allows you to define a
method with named parameters. It's bewildering because a method
invocation like "person.setFirstName('Gloria', { :lastName=>'Alvarez'
})" actually calls a *different* method from
"person.setFirstName('Gloria', lastName: 'Alvarez')" (the former is
the regular Ruby hash argument type; the latter uses the
MacRuby-specific keyed arguments. If no keyed-argument version of a
method exists, it will just translate it into a hash-argument form.)

Anyway, I wonder if there has been any talk between MacRuby and the
other Ruby implementations on getting this sort of keyed arguments
standardized.

* Objective-C, like Smalltalk, has methods with multi-part names,
where some of the arguments go inside the method name; e.g. you have a
method beginSheetModalForWindow: modalDelegate: didEndSelector:
contextInfo: where each colon marks a place where an argument should
go. Generally the word (or few words) right before the colon indicate
what the argument is supposed to be, semantically.

Gary Wright wrote in post #978791:

···

On Jan 31, 2011, at 2:47 PM, Charles Oliver Nutter wrote:

On Mon, Jan 31, 2011 at 1:27 PM, Thomas E Enebo <tom.enebo@gmail.com> wrote:

On Mon, Jan 31, 2011 at 9:00 AM, Gary Wright <gwtmp01@mac.com> wrote:

snip

Seems like you can get pretty far though with just a little
meta-programming with no special language support:

snip

That’s neat. Thanks!

--
Posted via http://www.ruby-forum.com/\.

I think the original poster provided an example of overloading based on the number of parameters but not their type.
Even restricting yourself to overloading by arity is a bit problematic in Ruby because the arity still has to be determined (in some cases) dynamically:

Actually, arity of callsite is always calculated in Ruby to know if
you should throw an ArgumentError (3 for 0 specified sort of errors)

Maybe I'm overlooking something but I wasn't suggesting that you don't need to calculate arity but instead was pointing out that you can't just calculate it at parse time but sometimes need to calculate it at call time.

foo(1,2) # the call arity can be computed at parse time
foo(*a) # the call arity must be computed at call time

So in an 'overload-based-on-arity' scheme there might be some optimization opportunities for some call sites but not for every call site.

Yeah, that is certainly true in the general sense even in existing
Ruby semantics. In your first example, we know that it is always a
two-arg call (at parse time) so we can go through a two-arity call
path and not 'box' the call parameters into an array. In the second
case we might be able to know arity at parse time if we know 'a' is a
literal array. If we don't then the optimizations we can do get
more limited.

You are correct that adding arity to the mix would make the
optimizations more complex, but I think it depends on the case and
what you get by supporting it. For example, in the second case if we
made our callsite cache lookup the methods foo and cache all of them
at the site, then dispatch to the appropriate one, we would have quite
a bit more complicated callsite cache (since we would need to
invalidate it if any arity version changed), but this would dispatch
much faster than doing things like you are showing in the example
later in your email (actually much faster than any pure-Ruby logic for
arity resolution). In the case where there was only one arity it
would behave more or less like it does currently. The main change
would be on any same-named method we would need to invalidate. [Note:
This is just one way this could be done and callsite invalidation
would be about the same as what it is now since it would invalidate
based on name. We could do it name+arity. We could do it both ways
even (perhaps name+arity for first case and only name for second).

With all this said, it seems like a good idea to me, but OTOH no
feature is without its caveats. I am more worried about Ruby
programming style than performance and though it seems to pass a smell
test for me...I don't think I am in the 'yeah let's do it camp' yet.
I am probably in the 'someone should play with this' camp.

···

On Mon, Jan 31, 2011 at 9:10 PM, Gary Wright <gwtmp01@mac.com> wrote:

On Jan 31, 2011, at 2:47 PM, Charles Oliver Nutter wrote:

On Mon, Jan 31, 2011 at 1:27 PM, Thomas E Enebo <tom.enebo@gmail.com> wrote:

On Mon, Jan 31, 2011 at 9:00 AM, Gary Wright <gwtmp01@mac.com> wrote:

Seems like you can get pretty far though with just a little meta-programming with no special language support:

module Arity
def overload(base)
define_method(base) do |*args|
argc = args.size
method_name = "#{base}_#{argc}"
if respond_to?(method_name)
send(method_name, *args)
else
raise ArgumentError, "wrong number of arguments (no method for #{argc} arguments)"
end
end
end
end

class A
extend Arity

overload :foo

def foo_0
puts "foo with no arguments"
end

def foo_1(arg1)
puts "foo with 1 argument: #{arg1.inspect}"
end

end

A.new.foo # dispatches to A#foo_0
A.new.foo(1) # dispatches to A#foo_1
A.new.foo(1,2) # ArgumentError

Gary Wright

--
blog: http://blog.enebo.com twitter: tom_enebo
mail: tom.enebo@gmail.com

Eric Christopherson wrote:

Whenever the overloading topic comes up, I wonder about what the
future holds regarding true named arguments. Does anyone know?

AFAIK, they are on the wishlist for Ruby 2.0, but I don't think there
has been any commitment made. There's no implementation that I know
of, not even a design.

Anyway, I wonder if there has been any talk between MacRuby and the
other Ruby implementations on getting this sort of keyed arguments
standardized.

AFAIK, Laurent Sansonetti did consult with matz to make sure that
MacRuby's extensions would be forward compatible.

So, while there does not exist a design, let alone an implementation
of named arguments for Ruby 2.0, it seems to be clear that whatever
design they come up with, will have to be compatible with MacRuby.

jwm

Laurent can correct me if I'm wrong, but I don't think ObjC's syntax
qualifies as true named arguments. In MacRuby/ObjC, a method call like

foo(bar:1, baz:2)

Is just a way of saying something like

foo_with_bar_with_baz(1, 2)

The method name and the argument names actually resolve to different
method bodies internally. In addition, the order is absolutely
crucial. The following two calls are not the same and will not end up
in the same target method:

foo(bar: 1, baz: 2)
foo(baz: 2, bar: 1)

Named arguments would allow you to call the *same* method with
different groups of names in any order.

- Charlie

···

On Sat, Jan 29, 2011 at 12:37 AM, Eric Christopherson <echristopherson@gmail.com> wrote:

Specifically, MacRuby has an extension to the usual hash parameters
that seems pretty complicated to me, but allows it to interact fairly
painlessly with Objective-C*. It basically allows you to define a
method with named parameters. It's bewildering because a method
invocation like "person.setFirstName('Gloria', { :lastName=>'Alvarez'
})" actually calls a *different* method from
"person.setFirstName('Gloria', lastName: 'Alvarez')" (the former is
the regular Ruby hash argument type; the latter uses the
MacRuby-specific keyed arguments. If no keyed-argument version of a
method exists, it will just translate it into a hash-argument form.)

Anyway, I wonder if there has been any talk between MacRuby and the
other Ruby implementations on getting this sort of keyed arguments
standardized.

AFAIK, Laurent Sansonetti did consult with matz to make sure that
MacRuby's extensions would be forward compatible.

I don't believe that's the case, and if I remember right Matz actually
expressed concern that MacRuby was adding syntax that might later
conflict with MRI.

So, while there does not exist a design, let alone an implementation
of named arguments for Ruby 2.0, it seems to be clear that whatever
design they come up with, will have to be compatible with MacRuby.

MacRuby has taken the risk of future syntax being incompatible. I
don't think their decision to add syntax no other Ruby impl supports
should limit future design of Ruby proper.

FWIW, I understand the justification for the MacRuby syntax (objc
interop), but it's pretty clear to me that adding incompatible syntax
puts MacRuby on its own wrt future standard syntax changes.

I've considered adding syntax to JRuby for some things (like to allow
static dispatch against Java objects, for perf) but in every case I've
only considered options that would be forward-compatible (like
comment-based annotation of types, etc).

- Charlie

···

2011/1/29 Jörg W Mittag <JoergWMittag+Ruby@googlemail.com>:

Charles Oliver Nutter wrote:

Specifically, MacRuby has an extension to the usual hash parameters
that seems pretty complicated to me, but allows it to interact fairly
painlessly with Objective-C*. It basically allows you to define a
method with named parameters. It's bewildering because a method
invocation like "person.setFirstName('Gloria', { :lastName=>'Alvarez'
})" actually calls a *different* method from
"person.setFirstName('Gloria', lastName: 'Alvarez')" (the former is
the regular Ruby hash argument type; the latter uses the
MacRuby-specific keyed arguments. If no keyed-argument version of a
method exists, it will just translate it into a hash-argument form.)

Laurent can correct me if I'm wrong, but I don't think ObjC's syntax
qualifies as true named arguments.

Yes. Objective-C inherits its syntax from Smalltalk, which just has
plain old boring standard positional arguments like every other
language, like C, like Ruby minus optional and splat arguments.

The only peculiarity is that the arguments get written between the
subroutine name instead of at the end. So, if you have a method named
foo:bar:baz: which takes three arguments, the way you would call it in
pretty much every other language is

    foo:bar:baz:(1, 2, 3)

whereas in Smalltalk it's

    foo: 1 bar: 2 baz: 3

This allows you to achieve some nice readability with clever method
naming, i.e. instead of

    dictionary.add(1, 2) # which one's the key and which is the value?

you get

    dictionary at: 1 put: 2.

But fundamentally, these are still positional arguments. I could, for
example, do this in Ruby:

    dictionary.at_first_put_second(1, 2)

In MacRuby/ObjC, a method call like

foo(bar:1, baz:2)

Is just a way of saying something like

foo_with_bar_with_baz(1, 2)

More precisely, your example (roughly) translates to the following
snippet of Smalltalk:

    temp := Dictionary new.
    temp at: #bar put: 1. 'No dictionary literals in Smalltalk'

    foo: temp baz: 2.

i.e. in Ruby:

    send(:'foo:baz:', { :bar => 1 }, 2)

A better example would be

    foo(1, bar: 2, baz: 3)

which translates to

    foo: 1 bar: 2 baz: 3.

or

    send(:'foo:bar:baz:', 1, 2, 3)

The method name and the argument names actually resolve to different
method bodies internally. In addition, the order is absolutely
crucial. The following two calls are not the same and will not end up
in the same target method:

foo(bar: 1, baz: 2)
foo(baz: 2, bar: 1)

Correct.

The only reason why you can say

    condition ifTrue: [doThis] ifFalse: [doThat].
    condition ifFalse: [doThat] ifTrue: [doThis].
    condition ifTrue: [doThis]; ifFalse: [doThat].

is because TrueClass and FalseClass define four methods

    ifTrue:ifFalse:
    ifFalse:ifTrue:
    ifTrue:
    ifFalse:

With named arguments (and optional arguments), you would have just one
method:

    def if(then=->{}, else=->{})

jwm

···

On Sat, Jan 29, 2011 at 12:37 AM, Eric Christopherson > <echristopherson@gmail.com> wrote: