Forum: Ruby Argument types

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Florian K. (Guest)
on 2009-04-14 19:30
(Received via mailing list)
The documentation of the standard classes/methods never mention of
what type/class an argument must be. For example let's look at the
subscript of an Array. There is the form "array[index]". But of what
Type must the index object be?
The ruby book tells me that programming ruby, types doesn't matter so
much, what matters is to what messages an object responds. Thus I
tried the following, thinking that to_i is needed so an object can be
used as an subscript index.

#!/usr/bin/ruby
class C
  def to_i
    0
  end
end
c = C.new
a = [0,1,2]
p a[c]

It doesn't work however:

./test:12:in `[]': can't convert C into Integer (TypeError)
  from ./test:12

So to which messages must C respond so objects of it can be used as
array index?

Flo
Michael N. (Guest)
on 2009-04-14 19:47
(Received via mailing list)
Florian K. wrote:

> class C
> ./test:12:in `[]': can't convert C into Integer (TypeError)
> from ./test:12
>
> So to which messages must C respond so objects of it can be used as
> array index?

An index is always a natural number. It is required to be either a
Fixnum or
Bignum. You can't pass arbitrary object to those methods. Why not:

  p a[c.to_i] ?

Regards,

  Michael
Pascal J. Bourguignon (Guest)
on 2009-04-14 20:00
(Received via mailing list)
Florian K. <removed_email_address@domain.invalid> writes:

> The documentation of the standard classes/methods never mention of
> what type/class an argument must be. For example let's look at the
> subscript of an Array. There is the form "array[index]". But of what
> Type must the index object be?
> The ruby book tells me that programming ruby, types doesn't matter so
> much, what matters is to what messages an object responds. Thus I
> tried the following, thinking that to_i is needed so an object can be
> used as an subscript index.

Indeed, it would be nice if the arguments "duck type" was documented.

> It doesn't work however:
>
> ./test:12:in `[]': can't convert C into Integer (TypeError)
>   from ./test:12
>
> So to which messages must C respond so objects of it can be used as
> array index?

In this case, probably it's not the result of a given method that is
used to index the array, but the argument itself!  So you are probably
expected to give integers as arguments, and no visible message is sent.

You would have to check the sources of ruby.

But let's make a thought experiment, let's implement Array.at using
Memory and Integer:

(class Array

  (def initialize( ... )
     (@size = ...)
     (@addressOfArray = (Memory.allocate @size))
     self
   end)

  (def addressOf(index)
     (@addressOfArray + index)
   end)

  (def at(index)
     (if (> 0 index)
        (index = (@size - index))
      end)
     (if (> 0 index)
         nil
      elsif (<= @size index)
         nil
      else
         (Memory.load (self . addressOf index))
      end)
   end)

end)


Basically, the index should behave as an integer, but in this
pseudo-implementation it is not sent any message.  It is passed as
argument to Integer.+, Integer.-, Integer.>, Integer.<= ; perhaps
these methods send some message to the index object, you'd have to
check Ruby sources to know.  Perhaps they only use the _identity_ of
the argument to let the processor compute the result, without sending
any message.
Yossef M. (Guest)
on 2009-04-14 20:13
(Received via mailing list)
Yay! Pascal's back! And just when I was suffering from parenthesis
withdrawal.

On Apr 14, 11:00 am, removed_email_address@domain.invalid (Pascal J. 
Bourguignon)
wrote:
> (class Array
>   (def at(index)
>      (if (> 0 index)
Woah, what?
>         (index = (@size - index))
>       end)
>      (if (> 0 index)
>          nil
>       elsif (<= @size index)
>          nil
>       else
>          (Memory.load (self . addressOf index))
You missed out on an opportunity for addresOf(index) there. Just
thought you should know.
>       end)
>    end)
>
> end)
>
> Basically, the index should behave as an integer, but in this
> pseudo-implementation

Pseudo- is right. I'm not sure what language this is. It has some sort
of Ruby feeling, but there are far too many parentheses. Also, some
comparisons are done in a totally whacked-out fashion involving insane
ordering. I'm willing to bet the person who wrote this code doesn't
actually know or care about Ruby, but is really some delusional Lisp
lover who harbors a deep resentment towards all languages that are not
"pure enough".

Am I right?
Charles J. (Guest)
on 2009-04-14 20:23
(Received via mailing list)
On Apr 14, 2009, at 11:13 AM, Yossef M. wrote:

>
> Am I right?
>
> --
> -yossef
>
((((((((((((((((yes, you are.)))))))))))))))

---
Charles J.
Advanced Computing Center for Research and Education
Vanderbilt University
removed_email_address@domain.invalid
Office: 615-343-2776
Cell: 615-478-8799
Jeremy H. (Guest)
on 2009-04-14 20:45
(Received via mailing list)
On 2009-04-14, Florian K. <removed_email_address@domain.invalid> wrote:

> The ruby book tells me that programming ruby, types doesn't matter so
> much, what matters is to what messages an object responds. Thus I
> tried the following, thinking that to_i is needed so an object can be
> used as an subscript index.

#to_i is not sufficient, but #to_int is:

$ irb
irb(main):001:0> foo = Object.new
=> #<Object:0xb7c14064>
irb(main):002:0> [ 34, 45 ][foo]
TypeError: can't convert Object into Integer
        from (irb):2:in `[]'
        from (irb):2
irb(main):003:0> def foo.to_int ; 1 ; end
=> nil
irb(main):004:0> [ 34, 45 ][foo]
=> 45

Regards,

Jeremy H.
Florian K. (Guest)
on 2009-04-14 21:10
(Received via mailing list)
> An index is always a natural number. It is required to be either a Fixnum or
> Bignum. You can't pass arbitrary object to those methods.

It seems that it is more complex than that. This works

%w(a b c)[1.2]

>  Why not:
>   p a[c.to_i] ?

Because I'd like to understand what I can do in general with ruby. I'd
like to be able to read the ruby doc and know for each of all those
hundred of methods what exactly I can pass as argument.

Flo
Robert D. (Guest)
on 2009-04-14 21:24
(Received via mailing list)
On Tue, Apr 14, 2009 at 6:22 PM, Charles J.
<removed_email_address@domain.invalid> wrote:
>
> On Apr 14, 2009, at 11:13 AM, Yossef M. wrote:
>
>>
>> Am I right?
>>
>> --
>> -yossef
>>
> ((((((((((((((((yes, you are.)))))))))))))))
you certainly mean
('('('('('('('('('('('('('('(' yes you are! <close them yourself, will
you?>
;)
R.
--
Si tu veux construire un bateau ...
Ne rassemble pas des hommes pour aller chercher du bois, préparer des
outils, répartir les tâches, alléger le travail… mais enseigne aux
gens la nostalgie de l’infini de la mer.

If you want to build a ship, don’t herd people together to collect
wood and don’t assign them tasks and work, but rather teach them to
long for the endless immensity of the sea.
Gary W. (Guest)
on 2009-04-14 21:40
(Received via mailing list)
On Apr 14, 2009, at 1:10 PM, Florian K. wrote:

>> An index is always a natural number. It is required to be either a
>> Fixnum or
>> Bignum. You can't pass arbitrary object to those methods.
>
> It seems that it is more complex than that. This works
>
> %w(a b c)[1.2]

Because Float#.to_int is defined, although I'm not quite sure why.

This caused me to notice:

Float#ceil   to greater (or equal) integer
Float#floor  to smaller (or equal) integer

Float#to_int floor but towards towards zero (i.e. smaller abs value)
  -0.5.to_int == 0, 0.5.to_int == 0
  -0.6.to_int == 0, 0.6.to_int == 0

Float#round  rounds away from zero:
  -0.5.round == -1, 0.5.round == 1
This topic is locked and can not be replied to.