Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ruby / Yukihiro Matsumoto_Programming Ruby.doc
Скачиваний:
122
Добавлен:
06.06.2015
Размер:
2.71 Mб
Скачать

Collecting Hash Arguments

Some languages feature ``keyword arguments''---that is, instead of passing arguments in a given order and quantity, you pass the name of the argument with its value, in any order. Ruby 1.6 does not have keyword arguments (although they are scheduled to be implemented in Ruby 1.8).

In the meantime, people are using hashes as a way of achieving the same effect. For example, we might consider adding a more powerful named-search facility to our SongList.

class SongList

  def createSearch(name, params)

    # ...

  end

end

aList.createSearch("short jazz songs", {

                   'genre'            => "jazz",

                   'durationLessThan' => 270

                   } )

The first parameter is the search name, and the second is a hash literal containing search parameters. The use of a hash means that we can simulate keywords: look for songs with a genre of ``jazz'' and a duration less than 4 1/2 minutes. However, this approach is slightly clunky, and that set of braces could easily be mistaken for a block associated with the method. So, Ruby has a short cut. You can place key=>valuepairs in an argument list, as long as they follow any normal arguments and precede any array and block arguments. All these pairs will be collected into a single hash and passed as one argument to the method. No braces are needed.

aList.createSearch("short jazz songs",

                   'genre'            => "jazz",

                   'durationLessThan' => 270

                   )

Expressions

So far we've been fairly cavalier in our use of expressions in Ruby. After all, a=b+cis pretty standard stuff. You could write a whole heap of Ruby code without reading any of this chapter.

But it wouldn't be as much fun ;-).

One of the first differences with Ruby is that anything that can reasonably return a value does: just about everything is an expression. What does this mean in practice?

Some obvious things include the ability to chain statements together.

a = b = c = 0

»

0

[ 3, 1, 7, 0 ].sort.reverse

»

[7, 3, 1, 0]

Perhaps less obvious, things that are normally statements in C or Java are expressions in Ruby. For example, the ifandcasestatements both return the value of the last expression executed.

songType = if song.mp3Type == MP3::Jazz

             if song.written < Date.new(1935, 1, 1)

               Song::TradJazz

             else

               Song::Jazz

             end

           else

             Song::Other

           end

 rating = case votesCast

          when 0...10    then Rating::SkipThisOne

          when 10...50   then Rating::CouldDoBetter

          else                Rating::Rave

          end

We'll talk more about ifandcasestarting on page 79.

Operator Expressions

Ruby has the basic set of operators (+, -, *, /, and so on) as well as a few surprises. A complete list of the operators, and their precedences, is given in Table 18.4 on page 219.

In Ruby, many operators are actually method calls. When you write a*b+cyou're actually asking the object referenced byato execute the method ``*'', passing in the parameterb. You then ask the object that results from that calculation to execute ``+'', passingcas a parameter. This is exactly equivalent to writing

(a.*(b)).+(c)

Because everything is an object, and because you can redefine instance methods, you can always redefine basic arithmetic if you don't like the answers you're getting.

class Fixnum

  alias oldPlus +

  def +(other)

    oldPlus(other).succ

  end

end

1 + 2

»

4

a = 3

a += 4

»

8

More useful is the fact that classes that you write can participate in operator expressions just as if they were built-in objects. For example, we might want to be able to extract a number of seconds of music from the middle of a song. We could using the indexing operator ``[]'' to specify the music to be extracted.

class Song

  def [](fromTime, toTime)

    result = Song.new(self.title + " [extract]",

                      self.artist,

                      toTime - fromTime)

    result.setStartTime(fromTime)

    result

  end

end

This code fragment extends class Songwith the method ``[]'', which takes two parameters (a start time and an end time). It returns a new song, with the music clipped to the given interval. We could then play the introduction to a song with code such as:

aSong[0, 0.15].play

Соседние файлы в папке Ruby