SlideShare uma empresa Scribd logo
1 de 161
Baixar para ler offline
Tutorial de Ruby

Eust´quio “TaQ” Rangel (eustaquiorangel@yahoo.com)
    a

                19 de julho de 2005
Este trabalho est´ licenciado sob uma Licen¸a Creative Commons Atribui¸˜o-Uso N˜o-
                 a                         c                          ca       a
Comercial-Compatilhamento pela mesma licen¸a.
                                           c

Para ver uma c´pia desta licen¸a, visite
              o               c
http://creativecommons.org/licenses/by-nc-sa/2.5/br/
ou envie uma carta para

Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.




                        Este documento foi feito usando L TEX.
                                                        A

                                        Vers˜o 0.1
                                             a
           Para atualiza¸˜es, visite http://beam.to/taq/tutorialruby.php
                        co
   A figura do logotipo de Ruby acima ´ de minha livre autoria, n˜o representando um
                                        e                       a
                                      logotipo oficial




                                          2
Sum´rio
   a

1 Introdu¸˜o
         ca                                                                                              9
  1.1 O que ´ Ruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
            e
  1.2 Onde encontro Ruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2 Arrumando as coisas                                                                                 11
  2.1 Preparando sua fonte de consultas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
  2.2 Preparando o ambiente de trabalho . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

3 Conhecendo o b´sico da linguagem
                    a                                                                                                                                               13
  3.1 Vari´veis . . . . . . . . . . . . . . . . . . .
           a                                            .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   13
      3.1.1 Escopo das vari´veis . . . . . . . .
                                a                       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   14
  3.2 Tipos b´sicos . . . . . . . . . . . . . . . .
              a                                         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   15
      3.2.1 Blocos de c´digo . . . . . . . . . .
                           o                            .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   15
      3.2.2 N´meros . . . . . . . . . . . . . . .
                u                                       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   15
      3.2.3 Booleanos . . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   16
      3.2.4 Strings . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   16
      3.2.5 Constantes . . . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   19
      3.2.6 Ranges . . . . . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   19
      3.2.7 Arrays . . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   20
      3.2.8 Hashes . . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   22
      3.2.9 S´ ımbolos . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   23
      3.2.10 Express˜es regulares . . . . . . . .
                      o                                 .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   23
      3.2.11 Procs . . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   26
      3.2.12 M´todos . . . . . . . . . . . . . . .
                e                                       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   26
             Retornando valores . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   26
             Recebendo parˆmetros . . . . . . .
                               a                        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   27
             Como os parˆmetros s˜o enviados
                             a         a                .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   29
             M´todos destrutivos . . . . . . . .
                e                                       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   35
             M´todos predicados . . . . . . . .
                e                                       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   35
             M´todos ou fun¸˜es . . . . . . . .
                e               co                      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   35
      3.2.13 Operadores . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   36
      3.2.14 Juntando tudo . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   37
  3.3 Estruturas de controle . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   41
      3.3.1 Condicionais . . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   41
             if . . . . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   41
             unless . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   41
             case . . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   42
      3.3.2 Loops . . . . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   42
             while . . . . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   42
             for . . . . . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   43
             until . . . . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   44
             begin . . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   44
             loop . . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   44
  3.4 Coment´rios no c´digo . . . . . . . . . . .
              a          o                              .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   45

                                                        3
4 Classes                                                                                                                                                                                    47
  4.1 Vari´veis de instˆncia . . . . . . . . .
           a           a                                                 .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   47
  4.2 Vari´veis de classe . . . . . . . . . . .
           a                                                             .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   52
  4.3 M´todos de classe . . . . . . . . . . . .
        e                                                                .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   55
  4.4 Executando m´todos da classe pai . .
                     e                                                   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   55
  4.5 Redefinindo operadores . . . . . . . .                              .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   57
  4.6 Heran¸a . . . . . . . . . . . . . . . . .
             c                                                           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   58
  4.7 Duplicando . . . . . . . . . . . . . . .                           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   61
  4.8 Controle de acesso . . . . . . . . . . .                           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   65
      4.8.1 M´todos p´blicos . . . . . . . .
                e        u                                               .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   65
      4.8.2 M´todos privados . . . . . . . .
                e                                                        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   66
      4.8.3 M´todos protegidos . . . . . .
                e                                                        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   67
      4.8.4 Especificando o tipo de acesso .                              .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   68
  4.9 Classes e m´todos singleton . . . . . .
                  e                                                      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   71

5 Entrada e sa´ıda                                                                                                                                                                           73
  5.1 Fluxos simples . . . . . . . . .                   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   73
  5.2 Fluxos mais complexos . . . . .                    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   74
      5.2.1 Arquivos . . . . . . . .                     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   74
             Lendo arquivos . . . . .                    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   74
             Escrevendo em arquivos                      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   76
      5.2.2 Fluxos . . . . . . . . . .                   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   76
             TCP . . . . . . . . . . .                   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   77
             UDP . . . . . . . . . . .                   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   77
             HTTP . . . . . . . . . .                    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   78

6 Exce¸˜es
      co                                                                                                        81
  6.1 Begin . . . rescue . . . ensure . . . end . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
  6.2 Throw . . . catch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

7 M´dulos
   o                                                                                                                                                                                         87

8 Threads                                                                                                                                                                                    91
  8.1 Timeout . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   92
  8.2 Criando usando Proc        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   92
  8.3 Sincroniza¸˜o . . . .
                ca               .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   93
  8.4 Condition variables .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   96

9 Acessando banco de dados                                                                                                                                                                    99
  9.1 Abrindo a conex˜o . . . . . . . . . . . . . . . . . . .
                      a                                                                                  .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    99
  9.2 Executando queries que n˜o retornam resultado . . .
                               a                                                                         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   100
  9.3 Recuperando dados do banco de dados . . . . . . . .                                                .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   100
  9.4 Preparando comandos e usando parametros vari´veis a                                                .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   101
  9.5 Metadados . . . . . . . . . . . . . . . . . . . . . . .                                            .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   103
  9.6 Trabalhando com blocos . . . . . . . . . . . . . . . .                                             .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   104
  9.7 Output especializado . . . . . . . . . . . . . . . . . .                                           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   105
      9.7.1 Tabular . . . . . . . . . . . . . . . . . . . . .                                            .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   105
      9.7.2 XML . . . . . . . . . . . . . . . . . . . . . . .                                            .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   106

10 XML                                                                                                   109
   10.1 Lendo arquivos XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
   10.2 Criando arquivos XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

11 YAML                                                                                                 113
   11.1 Lendo arquivos YAML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
   11.2 Gravando arquivos YAML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

                                                                                 4
12 XSLT                                                                                                                                                                                    117

13 Usando Ruby na web                                                                                                                                                                      119
   13.1 mod ruby . . . . . . . . . . . . . . . . .                         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   119
        13.1.1 Instalando o mod ruby . . . . . .                           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   119
        13.1.2 Configurando o servidor Apache                               .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   119
        13.1.3 Testando o mod ruby . . . . . .                             .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   120
   13.2 eruby . . . . . . . . . . . . . . . . . . .                        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   121
        13.2.1 Instalando o eruby . . . . . . . .                          .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   121
        13.2.2 Configurando o servidor Apache                               .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   121
        13.2.3 Testando o eruby . . . . . . . . .                          .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   121
        13.2.4 Sintaxe do eruby . . . . . . . . .                          .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   123
   13.3 CGI . . . . . . . . . . . . . . . . . . . .                        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   124
        13.3.1 Forms . . . . . . . . . . . . . . .                         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   124
        13.3.2 Cookies . . . . . . . . . . . . . .                         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   125
        13.3.3 Sess˜es . . . . . . . . . . . . . .
                   o                                                       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   126

14 Interface Gr´fica
                 a                                                                                                                                                                         131
   14.1 Obtendo e compilando o m´dulo GTK2
                                    o                                      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   131
   14.2 Hello, GUI world! . . . . . . . . . . . . .                        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   131
   14.3 Eventos . . . . . . . . . . . . . . . . . .                        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   132
   14.4 Packing . . . . . . . . . . . . . . . . . .                        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   132
   14.5 Posicionamento usando tabelas . . . . .                            .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   135
   14.6 Mais alguns componentes . . . . . . . .                            .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   137
        14.6.1 CheckButton . . . . . . . . . . .                           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   137
        14.6.2 ComboBox . . . . . . . . . . . .                            .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   137
        14.6.3 Campos texto . . . . . . . . . . .                          .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   138
        14.6.4 Radio buttons . . . . . . . . . .                           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   138

15 Garbage collector                                                                                                                                                                       141
   15.1 O algoritmo utilizado: mark-and-sweep .                            .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   141
   15.2 Como funciona, na teoria . . . . . . . .                           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   142
   15.3 Como funciona, na pr´tica . . . . . . . .
                              a                                            .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   143
   15.4 Otimizando . . . . . . . . . . . . . . . .                         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   143

16 Unit Testing                                                                                                                                                                            147
   16.1 A classe a ser testada     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   147
   16.2 Unidade de testes . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   147
   16.3 Falhas nos testes . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   149
   16.4 Novas funcionalidades      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   151

17 XML-RPC                                                                                                    155
   17.1 Servidor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
   17.2 Cliente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
   17.3 Acessando de outras linguagens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156




                                                                               5
6
Um pouco de bate-papo . . .

Eu comecei a fazer esse tutorial como sempre come¸o fazendo as minhas coisas: necessidade de me lem-
                                                 c
brar depois.

Como estou come¸ando a aprender a programar em Ruby agora (Nov/2004), quero fazer algumas
                  c
anota¸˜es, me perdoem se em algum ponto eu fizer alguma bobagenzinha, mas depois de rirem disso me
     co
enviem um email (eustaquiorangel@yahoo.com) para que eu possa corrigir o que estiver errado. :-)

Tenho experiˆncia como programador j´ faz alguns bons anos, e j´ passei por v´rias linguagens, e no
             e                       a                         a             a
decorrer do manual vou citar algumas compara¸˜es entre o Ruby e Java —, Python, PHP, etc. Estou
                                             co
presumindo que vocˆ tamb´m programe em alguma linguagem, sendo que esse n˜o ´ um tutorial para
                   e      e                                                a e
aprender a programar, e sim para aprender a programar em Ruby, com experiˆncia de programa¸˜o
                                                                             e                  ca
j´ adquirida em outras linguagens.
 a

Ao mesmo tempo, n˜o vou me ater muito em explicar as entranhas da linguagem aqui, apesar de mostrar
                    a
algumas coisinhas. :-)

Alguns c´digos tamb´m podem n˜o estar com sua otimiza¸˜o “no talo”, mas para efeito de tutorial,
        o          e         a                       ca
´ melhor assim.
e

E sobre linguagens, deixe-me fazer um singelo protesto aqui. N˜o vou falar sobre qual ´ melhor ou
                                                              a                       e
n˜o, por que discutir isso para mim ´ perda de tempo.
 a                                  e

N˜o por que eu saiba a resposta de qual ´, mas por que acho que s˜o todas linguagens boas e o que
  a                                        e                         a
difere nesse ponto s˜o como as pessoas as veˆm e as utilizam. Tenho v´rias cita¸˜es de outras linguagens
                    a                        e                       a         co
no decorrer do texto, mas em car´ter puramente comparativo/informativo, e n˜o nos termos de “aquela
                                 a                                             a
porcaria de XYZ faz isso dessa maneira”.

                c a          e                      e ˜
Esse tipo de ca¸a `s bruxas ´ justamente o que vocˆ NAO vai encontrar aqui. J´ perdi muito tempo com
                                                                               a
esse tipo de coisa, e espero que ao inv´s de vocˆ perder tamb´m sente e escreva c´digo na sua linguagem
                                       e        e            e                   o
preferida do que ficar fazendo flamewars por a´ :-)
                                                ı.

Ent˜o, vamos nessa.
   a


     Dedico esse trabalho ` minha filhinha Ana Isabella, que me ilumina todos os dias.
                          a




                                                   7
8
Cap´
   ıtulo 1

Introdu¸˜o
       ca

1.1     O que ´ Ruby
              e
Para explicar o que ´ Ruby, eu fa¸o uma tradu¸˜o livre do que Yukihiro “Matz” Matsumoto, seu criador,
                     e           c           ca
diz a respeito dela em http://www.ruby-lang.org/en/20020101.html:

Ruby ´ uma linguagem de script interpretada para programa¸˜o orientada a objetos de um modo f´cil e
       e                                                    ca                                    a
r´pido. Ela tem v´rios recursos para processar arquivos de texto e para fazer tarefas de gerenciamento
 a                a
de sistema (assim como o Perl). Ela ´ simples, direto ao ponto, extens´ e port´vel.
                                    e                                 ıvel      a

Oh, preciso mencionar, ´ totalmente livre, o que significa n˜o s´ livre de precisar pagar para us´-la,
                       e                                   a o                                  a
mas tamb´m a liberdade de usar, copiar, modificar e distribu´
         e                                                 ı-la.

Recursos do Ruby
   ˆ Ruby tem uma sintaxe simples, parcialmente inspirada por Eiffel e Ada.
   ˆ Ruby tem recursos de tratamento de exce¸˜es, assim como Java —e Python, para deixar mais f´cil
                                            co                                                 a
     o tratamento de erros.
   ˆ Os operadores do Ruby s˜o a¸ucar sint´tico para os m´todos. Vocˆ pode redefini-los facilmente.
                            a c           a              e          e
   ˆ Ruby ´ uma linguagem completa e pura orientada ` objetos. Isso significa que todo dado em Ruby
          e                                          a
     ´ um objeto, n˜o do jeito de Python e Perl, mas mais do jeito do SmallTalk: sem exce¸˜es. Por
     e             a                                                                      co
     exemplo, em Ruby, o n´mero 1 ´ uma instˆncia da classe Fixnum.
                           u       e         a
   ˆ A orienta¸˜o ` objetos do Ruby ´ desenhada cuidadosamente para ser completa e aberta ` me-
               ca a                   e                                                      a
     lhorias. Por exemplo, Ruby tem a habilidade de adicionar m´todos em uma classe, ou at´ mesmo
                                                               e                          e
     em uma instˆncia durante o runtime! Ent˜o, se necess´rio, a instˆncia de uma classe *pode* se
                  a                            a           a         a
     comportar diferente de outras instˆncias da mesma classe.
                                       a
   ˆ Ruby tem heran¸a unica, de prop´sito. Mas entende o conceito de m´dulos (chamados de Categories
                    c ´             o                                 o
     no Objective-C). M´dulos s˜o cole¸˜es de m´todos. Toda classe pode importar um m´dulo e pegar
                        o      a      co       e                                       o
     seus m´todos. Alguns de n´s acham que isso ´ um jeito mais limpo do que heran¸a m´ltipla, que
           e                   o                 e                                  c    u
     ´ complexa e n˜o ´ usada tanto comparado com heran¸a unica (n˜o conte C++ aqui, pois l´ n˜o
     e             a e                                     c ´        a                       a a
     se tem muita escolha devido a checagem forte de tipo!).
   ˆ Ruby tem closures verdadeiras. N˜o apenas fun¸˜es sem nome, mas com bindings de v´riaveis
                                     a            co                                  a
     verdadeiras.
   ˆ Ruby tem blocos em sua sintaxe (c´digo delimitado por ’{’. . . ’}’ ou ’do’. . . ’end’). Esses blocos
                                      o
     podem ser passados para os m´todos, ou convertidos em closures.
                                 e
   ˆ Ruby tem um garbage collector que realmente ´ do tipo marca-e-limpa. Ele atua em todos os
                                                   e
     objetos do Ruby. Vocˆ n˜o precisa se preocupar em manter contagem de referˆncias em libraries
                          e a                                                  e
               ´
     externas. E melhor para a sua sa´de. ;-)
                                     u

                                                   9
ˆ Escrever extens˜es em C para Ruby ´ mais f´cil que em Perl ou Python, em grande parte por
                    o                      e       a
     causa do garbage collector, e em parte pela boa API de extens˜es. A interface SWIG tamb´m est´
                                                                  o                         e     a
     dispon´
           ıvel.

   ˆ Inteiros em Ruby podem (e devem) ser usados sem contar sua representa¸˜o interna. Existem
                                                                              ca
     inteiros pequenos (instˆncias da classe Fixnum) e grandes (Bignum), mas vocˆ n˜o precisa se
                            a                                                      e a
     preocupar em qual est´ sendo utilizado atualmente. Se um valor ´ pequeno o bastante, um inteiro
                           a                                        e
     ´ um Fixnum, do contr´rio ´ um Bignum. A convers˜o ocorre automaticamente.
     e                      a   e                       a

   ˆ Ruby n˜o precisa de declara¸˜o de vari´veis. Apenas usa a conven¸˜o de nomenclatura para
             a                      ca         a                              ca
     delimitar o escopo das vari´veis. Por exemplo: ’var’ = vari´vel local, ’@var’ = vari´vel de instˆncia,
                                a                               a                        a           a
     ’$var’= vari´vel global. E n˜o precisa do uso cansativo do ’self’ em cada membro da instˆncia.
                 a                a                                                               a

   ˆ Ruby pode carregar bibliotecas de extens˜o dinamicamente, se o sistema operacional permitir.
                                             a

   ˆ Ruby tem um sistema de threading independente do sistema operacional. Ent˜o, para cada plata-
                                                                                 a
     forma que vocˆ roda o Ruby, vocˆ tem multithreading de qualquer jeito, at´ no MS-DOS! ;-)
                  e                 e                                         e

   ˆ Ruby ´ altamente port´vel: ela ´ desenvolvida em sua maioria no Linux, mas funciona em muitos
           e              a         e
     tipos de UNIX, DOS, Windows 95/98/Me/NT/2000/XP, MacOS, BeOS, OS/2, etc.


1.2     Onde encontro Ruby
Vocˆ pode encontrar Ruby no seu site oficial na internet:
   e

http://www.ruby-lang.org

L´ vocˆ encontra o c´digo-fonte e vers˜es para Windows —. Compilar o c´digo ´ r´pido e f´cil, no
 a     e            o                 o                               o     e a         a
velho esquema

      tar xvzf ruby-$<versao>$.tgz
      ./configure
      make
      make install

Procure na sua distribui¸˜o (se vocˆ usa GNU/Linux) algum pacote do Ruby. Se n˜o encontrar, compile-
                        ca         e                                           a
o e o disponibilize em algum lugar. Eu fiz um pacote para o Slackware, est´ dispon´ aqui:
                                                                         a       ıvel

http://beam.to/taq/downloads.php

Se vocˆ pegar o pacote, pegue tamb´m a assinatura PGP do arquivo, importe a minha chave p´blica
      e                           e                                                      u
(784988BB) e fa¸a a conferˆncia.
               c          e




                                                    10
Cap´
   ıtulo 2

Arrumando as coisas

2.1     Preparando sua fonte de consultas
´
E sempre bom ter uma referˆncia das classes, m´dulos e m´todos dispon´
                           e                  o           e           ıveis em uma linguagem quando
se est´ aprendendo.
      a
Ruby vem com um utilit´rio chamado ri que facilita a sua consulta ´ essa documenta¸˜o. Mas para ele
                       a                                          a                 ca
poder consultar alguma coisa, primeiro temos que gera-l´.
                                                       a

Depois de instalado o Ruby, v´ para o diret´rio onde vocˆ instalou os fontes e digite, por exemplo:
                             a             o            e
      [taq@/usr/src/ruby-1.8.1]rdoc --ri *.c lib/*.rb
Isso vai produzir a documenta¸˜o do core do Ruby, que vai ser armazenada no seu diret´rio /.rdoc.
                             ca                                                      o

Ap´s isso podemos utilizar o ri dessa maneira, por exemplo:
  o
      [taq@ ]ri File
      ----------------------------------------------------------- Module:               File
      A File is an abstraction of any file object accessible by the
      program and is closely associated with class IO File includes the
      methods of module FileTest as class methods, allowing you to write
      (for example) File.exist?("foo").
      ...
Se utilizarmos um console que tenha suporte a cores, podemos criar um alias:
      alias ri=ri -f ansi -T
Assim o exemplo acima fica
      [taq@ ]ri File
      ----------------------------------------------------------- Module: File
      A File is an abstraction of any file object accessible by the
      program and is closely associated with class IO File includes the
      methods of module FileTest as class methods, allowing you to write
      (for example) File.exist?("foo").
      ...


2.2     Preparando o ambiente de trabalho
N˜o tem jeito melhor de aprender a programar em uma linguagem do que j´ ir colocando a m˜o na
 a                                                                           a              a
massa. Ruby tem um programinha muito bom para ir testando o c´digo, o irb (interactive Ruby shell).
                                                                 o
Estilo do Python, que podemos chamar e j´ ir digitando as coisas e vendo os resultados.
                                        a

Antes de abrirmos o irb, vamos alterar o arquivo .irbrc, que fica no seu diret´rio home.
                                                                             o

                                                  11
¸˜
         ATENCAO
         Estou usando GNU/Linux durante todo esse tutorial, e presumo que voc^ est´ usando
                                                                             e    a
         tamb´m. L´gico que voc^ pode rodar Ruby em qualquer dos sistemas operacionais
             e     o            e
         citados acima, mas eu realmente n~o tenho param^tros para lhe dizer como fazer
                                          a             e
         as configura¸~es em outro sistema.
                     co

Insira

         require ’irb/completion’

no arquivo.

Ok, agora chame o irb simplesmente digitando irb no terminal:

         [taq@~]irb
         irb(main):001:0$>$

Agora o irb j´ est´ pronto para ser usado. Vamos conhecer mais um pouco dele:
             a    a
         irb(main):001:0>   i = 10
         => 10
         irb(main):002:0>   if i > 5
         irb(main):003:1>      puts "maior que 5"
         irb(main):004:1>   else
         irb(main):005:1*      puts "menor que 5"
         irb(main):006:1>   end
         maior que 5
         => nil
         irb(main):007:0>

Separando o prompt pelos dois pontos (:), temos algumas se¸˜es:
                                                          co

   ˆ O nome do programa que estamos rodando (main)

   ˆ O n´mero de linhas que digitamos (e estamos!) no irb
        u

   ˆ O n´ de profundidade que estamos
        ıvel

O n´ de profundidade ´ incrementado sempre que abrimos uma express˜o que precisa de fechamento.
    ıvel                 e                                              a
Sempre que o irb verificar que o c´digo precisa ser fechado, ele vai trocar o final do prompt por um
                                    o
asterisco, ou aspas-duplas se n˜o fechamos uma String:
                               a

         [taq@~]irb
         irb(main):001:0> s = "um teste
         irb(main):002:0" do irb"
         => "um teste ndo irb"
         irb(main):003:0>
Olhem o n´ de profundidade alterado:
         ıvel

         [taq@~]irb
         irb(main):001:0> def teste(n)
         irb(main):002:1>    if n > 10
         irb(main):003:2>        puts "teste"
         irb(main):004:2>    end
         irb(main):005:1> end
         => nil
         irb(main):006:0>




                                                 12
Cap´
   ıtulo 3

Conhecendo o b´sico da linguagem
              a

3.1     Vari´veis
            a
Vamos destrinchar aqui alguns tipos b´sicos do Ruby, e como usar vari´veis com eles.
                                     a                               a

Apesar de ter sido dito que TUDO em Ruby ´ um objeto, vari´veis n˜o s˜o objetos, mas referˆncias para
                                         e                a      a a                      e
esses.

As vari´veis do Ruby s˜o muito simples de serem utilizadas pois utilizam a “duck typing”, como
       a              a
´ chamada carinhosamente a tipagem dinˆmica do Ruby. Para os que vieram do Java —, que tem uma
e                                      a
tipagem est´tica, um bom exemplo seria
             a
      [taq@~]irb
      irb(main):001:0>    v = "teste"
      => "teste"
      irb(main):002:0>    v.class
      => String
      irb(main):003:0>    v = 1
      => 1
      irb(main):004:0>    v.class
      => Fixnum
      irb(main):005:0>
Vale lembrar que Ruby tamb´m tem tipagem forte, isso ´, vamos receber um erro se tentarmos fazer
                          e                          e
isso:
      [taq@~]irb
      irb(main):001:0> i = 1
      => 1
      irb(main):002:0> s = "oi"
      => "oi"
      irb(main):003:0> x = i+s
      TypeError: String can’t be coerced into Fixnum
        from (irb):3:in ‘+’
        from (irb):3
      irb(main):004:0>
Ent˜o, n˜o inventem de misturar uma coisa com a outra. :-)
   a    a

Vamos dar uma olhadinha ali no output do irb. S´ para dar uma “coceirinha”, reparem que depois
                                                      o
que declarei a primeira vari´vel, pedi para ele verificar o valor do atributo class da vari´vel. Foi retor-
                             a                                                            a
nado String, l´gico, pois a vari´vel v vale “teste” nesse caso.
              o                 a

Agora olhem na segunda atribui¸˜o de valor. Indiquei que o valor de v ´ 1, e verificando o class foi
                              ca                                      e

                                                   13
retornado Fixnum, provando que o que o Matz disse na descri¸˜o do Ruby no come¸o desse tutorial ´
                                                           ca                 c                 e
verdade: TUDO ´ objeto em Ruby.
               e

Duvidam? Olhem que legal:

     [taq@~]irb
     irb(main):001:0> i = 1
     => 1
     irb(main):002:0> i.methods
     => ["%", "between?", "send", "<<", "prec", "&", "object_id", ">>", "size",
     "singleton_methods", "__send__", "round", "equal?", "taint", "method",
     "id2name", "*", "next", "frozen?", "instance_variable_get", "divmod", "+",
     "kind_of?", "integer?", "chr", "to_a", "instance_eval", "-", "prec_i",
     "/", "type", "protected_methods", "extend", "truncate", "to_sym", "|",
     "eql?", "modulo", "instance_variable_set", "~", "hash", "zero?", "is_a?",
     "to_s", "prec_f", "singleton_method_added", "class", "tainted?",
     "private_methods", "^", "step", "untaint", "+@", "upto", "-@", "remainder",
     "id", "**", "nonzero?", "to_i","<", "inspect", "<=>", "==", "floor", ">",
     "===", "succ", "clone", "public_methods", "quo", "display", "downto", ">=",
     "respond_to?", "<=", "freeze", "abs", "to_f", "__id__", "coerce", "=~",
     "methods", "ceil","nil?", "dup", "to_int", "div", "instance_variables",
     "[]", "instance_of?", "times"]

Esses s˜o os m´todos p´ blicos da instˆncia da classe (seria equivalente ` uma chamada i.public methods).
       a      e       u               a                                  a

Para vermos os m´todos privados da instˆncia da classe, podemos usar i.private methods.
                e                          a
Lembrem-se que estamos falando de m´todos da instˆncia da classe, mais tarde vamos falar dos
                                      e              a
m´todos da classe, sendo eles p´blicos, privados e protegidos. Mas isso mais tarde.
  e                            u

Agora vamos continuar a falar de vari´veis.
                                     a

3.1.1    Escopo das vari´veis
                        a
Para declarar uma vari´vel no escopo privado, ´ s´ fazer isso:
                      a                       e o

     [taq@~]irb
     irb(main):001:0> i = 1
     => 1
     irb(main):002:0> puts i
     1
     => nil
     irb(main):003:0>

Aqui tem um m´todo novo, o puts, que ´ um m´todo de kernel do Ruby. Isso implica que pode-
                 e                         e      e
mos o utilizar sem precisar especificar o objeto ` que ele faz parte (Kernel). A declara¸˜o completa ´
                                                a                                      ca           e
Kernel.puts. O puts nada mais faz que imprimir o resultado da express˜o que vocˆ passou para ele,
                                                                         a          e
quebrando a linha no final.
Para declarar uma v´riavel p´ blica, utilizamos
                    a        u

     [taq@~]irb
     irb(main):001:0> $i = 1
     => 1
     irb(main):002:0>

e pronto. Declarando a vari´vel com um caracter $ na frente do nome j´ a torna p´blica.
                           a                                         a          u

Tem mais um tipo de vari´vel, que ´ a de instˆncia de classe, mas s´ vamos falar nela quando che-
                          a       e          a                     o
garmos no assunto de classes. :-)

                                                   14
3.2        Tipos b´sicos
                  a
3.2.1       Blocos de c´digo
                       o
Antes de apresentar qualquer um dos tipos, quero mostrar uma coisa essencial em Ruby, que s˜o os
                                                                                              a
blocos de c´digo.
           o
Blocos de c´digo s˜o umas das boas sacadas de Ruby, e podem ser peda¸os de c´digo delimitados por {
           o      a                                                 c       o
e }:

      {puts ’Oi mundo!’}

ou, para blocos maiores, delimitados por do e end:

      do
            puts ’Oi mundo!’
            puts ’Aqui tem mais espa¸o’
                                    c
      end

A conven¸˜o ´ usar as chaves para blocos de uma linha e do . . . end para blocos maiores.
        ca e

Vamos ver muita coisa sobre blocos de c´digo mais adiante. Blocos de c´digo, juntamente com ite-
                                           o                               o
rators, s˜o muito utilizados em Ruby, s˜o uma das pe¸as-chaves da linguagem e v˜o aparecer em muitos
         a                              a            c                          a
exemplos dos tipos b´sicos abaixo. Se vocˆ n˜o entendeu muita coisa, n˜o tem problema, vamos ter uma
                    a                     e a                         a
explica¸˜o mas extensa sobre isso logo.
        ca

3.2.2       N´ meros
             u
Podemos ter vari´veis dos tipos inteiro ou ponto flutuante.
                a
Exemplos de inteiros:

      [taq@~]irb
      irb(main):001:0>   i1 = 1
      => 1
      irb(main):002:0>   i2 = 123
      => 123
      irb(main):003:0>   i3 = -1000
      => -1000
      irb(main):004:0>   i4 = 3_000_000_000
      => 3000000000
      irb(main):005:0>   puts i1.class
      Fixnum
      => nil
      irb(main):006:0>   puts i2.class
      Fixnum
      => nil
      irb(main):007:0>   puts i3.class
      Fixnum
      => nil
      irb(main):008:0>   puts i4.class
      Bignum
      => nil
      irb(main):009:0>

N˜o podemos usar v´
 a                 ırgulas em vari´veis, mas se acharmos que fica mais leg´
                                  a                                      ıvel, podemos usar subli-
nhado para separar os milhares, como no exemplo dos 3 bilh˜es acima (algu´m tem isso na conta? :-).
                                                          o              e

Outra coisa que eu fiz ali foi mostrar o tipo de cada vari´vel. Como o Matz disse tamb´m na des-
                                                           a                               e
cri¸˜o inicial, dependendo do n´mero que vocˆ utiliza, o Ruby j´ troca automaticamente o tipo. As trˆs
   ca                           u           e                  a                                    e
primeiras vari´veis s˜o do tipo Fixnum, enquanto a ultima n˜o coube no Fixnum e foi automaticamente
                a    a                              ´       a

                                                 15
usado o Bignum.

Exemplos de ponto flutuante:

     [taq@~]irb
     irb(main):001:0>     f1 = 1.23
     => 1.23
     irb(main):002:0>     f2 = -57.08
     => -57.08
     irb(main):003:0>     f3 = 15.058e-4
     => 0.0015058
     irb(main):004:0>     f1.class
     => Float
     irb(main):005:0>     f2.class
     => Float
     irb(main):006:0>     f3.class
     => Float
     irb(main):007:0>

Tamb´m podemos criar n´meros usando as formas hexadecimal, octal e bin´ria:
    e                 u                                               a

     [taq@~]irb
     irb(main):001:0> hex = 0xFF
     => 255
     irb(main):002:0> oct = 0377
     => 255
     irb(main):003:0> bin = 0b11111111
     => 255
     irb(main):004:0>

3.2.3    Booleanos
S˜o os valores true e false. Reparem que est˜o em min´ sculas.
 a                                            a           u
Aproveitando o gancho dos booleanos, o valor nulo em Ruby ´ definido como nil, sendo que false e nil s˜o
                                                            e                                         a
os unicos valores que s˜o reconhecidos como valores indicando falso, mas s˜o de classes e comportamentos
   ´                   a                                                  a
diferentes:

     [taq@~]irb
     irb(main):001:0>     t = true
     => true
     irb(main):002:0>     f = false
     => false
     irb(main):003:0>     n = nil
     => nil
     irb(main):004:0>     t.class
     => TrueClass
     irb(main):005:0>     f.class
     => FalseClass
     irb(main):006:0>     n.class
     => NilClass
     irb(main):007:0>

A recomenda¸˜o ´ que m´todos predicados (que terminam com ? no final, mais sobre isso depois) retornem
              ca e      e
true ou false, enquanto outros m´todos que precisam indicar falha retornem nil.
                                e

3.2.4    Strings
Qualquer “palavra” ou conjunto de palavras podem ser armazenados como uma String:

                                                  16
[taq@~]irb
     irb(main):001:0>     s1 = "oi"
     => "oi"
     irb(main):002:0>     s2 = "oi, amigo!"
     => "oi, amigo!"
     irb(main):003:0>     s3 = "oi, ’mano’!"
     => "oi, ’mano’!"
     irb(main):004:0>     s1.class
     => String
     irb(main):005:0>
Vamos aproveitar que estamos falando de Strings e lembrar que, como foi dito acima, vari´veis s˜o
                                                                                        a      a
referˆncias para objetos. Para ter uma prova disso, vamos ver um exemplo:
     e
     [taq@~]irb
     irb(main):001:0>     my_nick = "TaQ"
     => "TaQ"
     irb(main):002:0>     my_nick_copy = my_nick
     => "TaQ"
     irb(main):003:0>     my_nick[0] = ’S’
     => "S"
     irb(main):004:0>     puts my_nick
     SaQ
     => nil
     irb(main):005:0>     puts my_nick_copy
     SaQ
     => nil
     irb(main):006:0>
O que aconteceu aqui? Eu s´ troquei o primeiro caracter da vari´vel my nick, n˜o da my nick copy
                             o                                  a              a
(falando nisso, vocˆ pode manipular Strings usando [] da mesma maneira que em outras linguagens)!
                   e

Bom, nesse caso, my nick copy aponta para o mesmo lugar onde se encontra o valor de my nick, por isso
que quando vocˆ alterou uma, alterou a outra junto.
               e

Se n˜o quisermos que um objeto seja alterado, podemos usar o m´todo freeze nele:
    a                                                         e
     [taq@~]irb
     irb(main):001:0> my_nick = "TaQ"
     => "TaQ"
     irb(main):002:0> my_nick_copy = my_nick
     => "TaQ"
     irb(main):003:0> my_nick.freeze
     => "TaQ"
     irb(main):004:0> my_nick[0] = ’S’
     TypeError: can’t modify frozen string
       from (irb):4:in ‘[]=’
       from (irb):4
     irb(main):005:0> my_nick_copy[0] = ’S’
     TypeError: can’t modify frozen string
       from (irb):5:in ‘[]=’
       from (irb):5
     irb(main):006:0> my_nick
     => "TaQ"
     irb(main):007:0> my_nick_copy
     => "TaQ"
     irb(main):008:0>
Para ter resultados distintos entre as vari´veis, baseando o valor de uma na outra, ter´
                                           a                                           ıamos que fazer:

                                                   17
[taq@~]irb
     irb(main):001:0>   my_nick = "TaQ"
     => "TaQ"
     irb(main):002:0>   my_nick_copy = my_nick.dup
     => "TaQ"
     irb(main):003:0>   my_nick[0] = ’S’
     => "S"
     irb(main):004:0>   puts my_nick
     SaQ
     => nil
     irb(main):005:0>   puts my_nick_copy
     TaQ
     => nil
     irb(main):006:0>
O m´todo dup duplica o objeto, criando uma nova c´pia, que foi atribu´ ` vari´vel my nick copy.
    e                                            o                   ıda a   a
Ent˜o, quando trocamos o primeiro caracter de my nick, estamos alterando somente ela e n˜o mais
   a                                                                                     a
my nick copy junto.

Podemos usar uma feature chamada de heredoc para criar “stringonas”:
     [taq@~]irb
     irb(main):001:0> s = <<FIM
     irb(main):002:0" Uma String realmente
     irb(main):003:0" grande com alguns
     irb(main):004:0" saltos de linhas, para
     irb(main):005:0" demonstrar o heredoc!
     irb(main):006:0" FIM
     => "Uma String realmentengrande com algunsnsaltos de linhas, parandemonstrar o heredoc!n"
     irb(main):007:0> puts s
     Uma String realmente
     grande com alguns
     saltos de linhas, para
     demonstrar o heredoc!
     => nil
     irb(main):008:0>
Definimos uma vari´vel, que tem seu valor atribu´ logo ap´s encontrarmos uma string semelhante `
                   a                           ıdo      o                                       a
que vem depois de <<. No caso usei FIM, mas fica a seu crit´rio qual string usar de terminador. Se
                                                          e
quiser escrever PINDAMONHANGABA, pode. :-)

Para concatenar Strings, podemos usar + ou << (lembraram de C++?):
     [taq@~/trash]irb
     irb(main):001:0> s = "Oi, "
     => "Oi, "
     irb(main):002:0> s + "mundo!"
     => "Oi, mundo!"
     irb(main):003:0> s << "mundo!"
     => "Oi, mundo!"
     irb(main):004:0>
Fica a dica que << ´ mais r´pido, pois n˜o gera um novo objeto como +:
                   e       a            a
     [taq@~]irb
     irb(main):001:0> s = "teste"
     => "teste"
     irb(main):002:0> s.object_id
     => -605086198

                                               18
irb(main):003:0> s += " concatenado"
     => "teste concatenado"
     irb(main):004:0> s
     => "teste concatenado"
     irb(main):005:0> s.object_id
     => -605094768
     irb(main):006:0> s2 = "teste"
     => "teste"
     irb(main):007:0> s2.object_id
     => -605105148
     irb(main):008:0> s2 << " concatenado"
     => "teste concatenado"
     irb(main):009:0> s2
     => "teste concatenado"
     irb(main):010:0> s2.object_id
     => -605105148
     irb(main):011:0>
No caso de s += “concatenado”, ´ interpretado como s = s + “concatenado”, por isso que gera
                               e
um novo objeto.

3.2.5    Constantes
Constantes s˜o vari´veis que tem seu nome come¸ado com uma letra mai´ scula.
             a      a                          c                       u
“O que? S´ isso?” vocˆ poderia me perguntar. S´.
           o           e                       o
“Mas n˜o fica meio confuso com nomes de classes que come¸am em mai´sculas?” uhnnn at´ fica, mas
        a                                                 c          u                e
´ pr´tico.
e a
“Ent˜o, por exemplo, ao inv´s de eu ter em Java —: public static final double Pi = 3.1415926; eu
     a                      e
 o                          ´
s´ teria que escrever Pi?”. E isso a´
                                    ı.
“Tem certeza que isso ´ uma constante?”. Ok, vamos ver:
                       e
     [taq@~]irb
     irb(main):001:0> Pi = 3.1415926
     => 3.1415926
     irb(main):002:0> Pi = 10
     (irb):2: warning: already initialized constant Pi
     => 10
     irb(main):003:0>
Viu? Declarei a vari´vel, e quando fui alterar seu conte´do, fui informado que n˜o deveria, pois ´ uma
                    a                                   u                       a                e
constante.
Fica um fato curioso que Ruby, diferente de outras linguagens, permite que vocˆ altere a constante,
                                                                                  e
(“mas n˜o era uma constante?”) mas gera um warning alertando sobre isso.
        a

3.2.6    Ranges
Intervalos. Podemos declarar de duas maneiras: incluindo ou n˜o o ultimo valor a que nos referimos em
                                                             a    ´
sua declara¸ao. Por exemplo:
            c˜
     [taq@~/code/java]irb
     irb(main):001:0> r = 0..10
     => 0..10
     irb(main):002:0> r2 = 0...10
     => 0...10
     irb(main):003:0>
No primeiro caso, a range vai conter n´meros de 0 at´ 10, incluindo o 10. No segundo caso, vai de 0 at´
                                      u             e                                                 e
9.
Como regrinha dos pontinhos, menos ´ mais, quando se tem menos pontos, se tem mais valores na range.
                                     e

                                                  19
3.2.7    Arrays
Arrays podem conter v´rios tipos de objetos (ou n˜o):
                     a                           a

     [taq@~]irb
     irb(main):001:0> a = [’apenas’,1,’teste’]
     => ["apenas", 1, "teste"]
     irb(main):002:0>

Para Arrays com somente Strings, podemos usar o atalho %w, ficaria assim:

     [taq@~]irb
     irb(main):001:0> a = %w(homer marge bart lisa maggie o bebezinho)
     => ["homer", "marge", "bart", "lisa", "maggie o bebezinho"]
     irb(main):002:0>

Se precisarmos de uma String com mais de uma palavra, usamos o caracter como mostrado acima.

Inserir elementos no Array ´ facil, usando push:
                           e

     [taq@~]irb
     irb(main):001:0> a = []
     => []
     irb(main):002:0> a.push "um"
     => ["um"]
     irb(main):003:0> a.push "dois"
     => ["um", "dois"]
     irb(main):004:0> a.push "tres"
     => ["um", "dois", "tres"]
     irb(main):005:0> a.push "quatro"
     => ["um", "dois", "tres", "quatro"]
     irb(main):006:0>

ou usando o operador <<:

     [taq@~]irb
     irb(main):001:0> a = []
     => []
     irb(main):002:0> a << "um"
     => ["um"]
     irb(main):003:0> a << "dois"
     => ["um", "dois"]
     irb(main):004:0> a << "tres"
     => ["um", "dois", "tres"]
     irb(main):005:0>

Podemos fazer com um Array algo semelhante `s list comprehensions do Python, que ´ processar
                                              a                                     e
os elementos do Array e criar um novo, baseado em uma condi¸˜o. Por exemplo, quero processar os
                                                             ca
elementos pares de um Array e criar um novo com o dobro dos valores pares:

     [taq@~]irb
     irb(main):001:0> a = [1,2,3,4,5]
     => [1, 2, 3, 4, 5]
     irb(main):002:0> a2 = a.find_all {|v| v%2==0}.map{|v| v*2}
     => [4, 8]
     irb(main):003:0>

Podemos usar collect tamb´m no lugar de map, ´ uma quest˜o de gosto ali. :-)
                         e                   e          a

Ordenando um array:

                                                   20
[taq@~]irb
     irb(main):001:0> a = ["um","dois","tres"]
     => ["um", "dois", "tres"]
     irb(main):002:0> a.sort
     => ["dois", "tres", "um"]
     irb(main):003:0>
Podemos usar o m´todo sort assim tamb´m:
                e                    e
     [taq@~]irb
     irb(main):001:0> a = ["um","dois","tres"]
     => ["um", "dois", "tres"]
     irb(main):002:0> a.sort {|e1,e2| e1[0]<=>e2[0]}
     => ["dois", "tres", "um"]
     irb(main):003:0>
Usando o m´todo sort com um bloco, s˜o enviados dois parˆmetros para o bloco, que os compara usando
           e                         a                  a
o operador <=>. Podemos tamb´m utilizar o m´todo sort by, que ´ mais r´pido e eficiente quando
                                e              e                   e        a
precisamos ordenar por alguma propriedade ou express˜o do valor sendo avaliado:
                                                    a
     [taq@~]irb
     irb(main):001:0> a = ["um","dois","tres"]
     => ["um", "dois", "tres"]
     irb(main):002:0> a.sort_by {|e| e[0]}
     => ["dois", "tres", "um"]
     irb(main):003:0>
Nesse caso, foi avaliado a ordem alfab´tica das palavras. Se eu quisesse ordenar o Array pelo tamanho
                                      e
das palavras, poderia usar:
     [taq@~]irb
     irb(main):001:0> a = ["tres","dois","um"]
     => ["tres", "dois", "um"]
     irb(main):002:0> a.sort_by {|e| e.length}
     => ["um", "dois", "tres"]
     irb(main):003:0>
Podemos usar o m´todo any? para verificar se tem algum elemento de um Array que se encaixe em uma
                 e
condi¸˜o determinada por um bloco:
     ca
     [taq@~]irb
     irb(main):001:0> a = [1,2,50,3]
     => [1, 2, 50, 3]
     irb(main):002:0> a.any? {|v| v>10}
     => true
     irb(main):003:0> a.any? {|v| v>100}
     => false
     irb(main):004:0>
Se quisermos testar se todos os elementos do Array satisfazem uma condi¸˜o, podemos utilizar o m´todo
                                                                       ca                       e
all?:
     [taq@~]irb
     irb(main):001:0> a = [1,2,3,4,5]
     => [1, 2, 3, 4, 5]
     irb(main):002:0> a.all? {|v| v>0}
     => true
     irb(main):003:0> a.all? {|v| v>10}
     => false
     irb(main):004:0>

                                                 21
Tamb´m podemos particionar um Array, usando o m´todo partition:
    e                                          e

     [taq@~]irb
     irb(main):001:0> a = [1,2,3,4,5,6,7,8,9,10]
     => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
     irb(main):002:0> par,impar = a.partition {|e| e%2==0}
     => [[2, 4, 6, 8, 10], [1, 3, 5, 7, 9]]
     irb(main):003:0> par
     => [2, 4, 6, 8, 10]
     irb(main):004:0> impar
     => [1, 3, 5, 7, 9]
     irb(main):005:0>

O que aconteceu ´ que foram retornados dois novos Arrays, o primeiro com elementos que atendiam a
                 e
condi¸˜o especificada no bloco, e o segundo com os elementos que n˜o atendiam a condi¸˜o.
     ca                                                          a                  ca

3.2.8   Hashes
Um Hash ´ basicamente um Array com ´
         e                          ındices para seus elementos (uma analogia com Java —seriam os
objetos HashMap e Hashtable). Vejamos um exemplo:

     [taq@~/code/ruby]irb
     irb(main):001:0> h = {1=>"elemento 1","um"=>"elemento um"}
     => {"um"=>"elemento um", 1=>"elemento 1"}
     irb(main):002:0> h[1]
     => "elemento 1"
     irb(main):003:0> h["um"]
     => "elemento um"
     irb(main):004:0>

Podemos utilizar tamb´m s´
                     e   ımbolos para a chave do Hash:

     [taq@~/code/ruby]irb
     irb(main):001:0> h = {:um=>"elemento 1",:dois=>"elemento 2"}
     => {:um=>"elemento 1", :dois=>"elemento 2"}
     irb(main):002:0> h[:um]
     => "elemento 1"
     irb(main):003:0> h[:dois]
     => "elemento 2"
     irb(main):004:0>

     Uma pequena compara¸˜o
                        ca

     Primeiro, xˆ, flamewar. Vou fazer uma compara¸˜o com Arrays e Hashes aqui de uma
                o                                ca
     maneira saud´vel.
                  a

     Eu tive que fazer um pequeno teste com alguns Arrays em PHP, para um programa que
     fiz aqui, onde eu copiava o primeiro Array para mais dois, removia os elementos do primeiro
     usando pop, depois invertia e usava pop no segundo, e finalmente removia os elementos do
     terceiro usando shift.

     No meu teste, Arrays de 15000 elementos foram preenchidos e tiveram seus elementos remo-
     vidos com pop praticamente instantˆneamente, invertendo e removendo idem, mas usando
                                       a
     reverse/shift foram 31 segundos.

     Fiz o mesmo teste com Ruby. Foi instantˆneo! Resolvi aumentar o tamanho dos Array
                                               a
     para 10 vezes mais, 150000 elementos. Levou 4 segundos!


                                                22
Curioso com o teste, fui verificar a causa disso e descobri: ao contr´rio de Ruby (e ou-
                                                                         a
     tras linguagens tamb´m) todos os Arrays em PHP s˜o na verdade, Hashes!. Isso d´
                          e                                a                               a
     praticidade, mas d´ para ver o pre¸o que se paga e o que se ganha usando uma linguagem
                       a               c
     com distin¸˜o entre os dois.
                ca

3.2.9    S´
          ımbolos
Pense em s´
          ımbolos como “String levinhas”. Eles representam nomes e algumas Strings dentro do inter-
pretador do Ruby, e s˜o sempre o mesmo objeto durante a execu¸˜o de um programa.
                     a                                        ca
S´
 ımbolos s˜o criados usando : na frente do seu nome, como em:
          a

     :um
     :dois

Como demonstrado acima.
Vamos dar uma olhada no fato de serem sempre o mesmo objeto, pegando o exemplo da documenta¸˜o
                                                                                           ca
do Ruby:

     module One
       class Fred
       end
       $f1 = :Fred
     end
     module Two
       Fred = 1
       $f2 = :Fred
     end
     def Fred()
     end
     $f3 = :Fred
     $f1.id   #=> 2514190
     $f2.id   #=> 2514190
     $f3.id   #=> 2514190

Mesmo id! :-)

3.2.10    Express˜es regulares
                 o
Express˜es regulares s˜o facilmente criadas, delimitando-as com /:
       o              a

     [taq@~]irb
     irb(main):001:0> er = /^[0-9]/
     => /^[0-9]/
     irb(main):002:0>

E facilmente testadas, usando o operador de correspondˆncia =˜ ou de n˜o-correspondˆncia !˜:
                                                      e               a            e

     [taq@~]irb
     irb(main):001:0>    er = /^[0-9]/
     => /^[0-9]/
     irb(main):002:0>    "123" =~ er
     => 0
     irb(main):003:0>    "123" !~ er
     => false
     irb(main):004:0>    "abc" =~ er
     => nil
     irb(main):005:0>    "abc" !~ er
     => true
     irb(main):006:0>

                                                  23
Express˜es regulares tamb´m podem ser criadas usando o construtor da classe ou %r:
       o                 e
     [taq@~]irb
     irb(main):001:0> er = Regexp.new("^[0-9]")
     => /^[0-9]/
     irb(main):002:0> er2 = %r{^[0-9]}
     => /^[0-9]/
     irb(main):003:0>
Vamos fazer um teste mais pr´tico, usando a express˜o regular acima, “se a linha come¸ar com um
                             a                      a                                    c
n´mero”, usando um if para deixar mais claro (mas tem jeitos de fazer isso mais eficientemente):
 u
     [taq@~]irb
     irb(main):001:0>     er = /^[0-9]/
     => /^[0-9]/
     irb(main):002:0>     if "123" =~ er
     irb(main):003:1>        puts "casou!"
     irb(main):004:1>     else
     irb(main):005:1*        puts "N~O casou!"
                                    A
     irb(main):006:1>     end
     casou!
     => nil
     irb(main):007:0>     if "abc" =~ er
     irb(main):008:1>        puts "casou!"
     irb(main):009:1>     else
     irb(main):010:1*        puts "N~O casou!"
                                    A
     irb(main):011:1>     end
     N~O casou!
      A
     => nil
Isso poderia ser escrito como:
     [taq@~]irb
     irb(main):001:0> er = /^[0-9]/
     => /^[0-9]/
     irb(main):002:0> puts ("123" =~ er ? "":"n~o ")+"casou"
                                               a
     casou
     => nil
     irb(main):003:0> puts ("abc" =~ er ? "":"n~o ")+"casou"
                                               a
     n~o casou
      a
Mas se vocˆ n˜o sabe o que ´ aquela constru¸˜o (condi¸˜o?verdadeiro:falso) talvez se eu mostrasse assim
          e a              e               ca        ca
de primeira pudesse confundir um pouco a coisa aqui.

Podemos utilizar o m´todo match para pegarmos os tokens de uma string que “casa” com nossa ex-
                    e
press˜o regular:
     a
     [taq@~]irb
     irb(main):001:0> er = /(..)/(..)/(....)/
     => /(..)/(..)/(....)/
     irb(main):002:0> mt = er.match("20/06/2005")
     => #<MatchData:0xb7dd5dd0>
     irb(main):003:0> mt.length
     => 4
     irb(main):004:0> mt[0]
     => "20/06/2005"
     irb(main):005:0> mt[1]
     => "20"
     irb(main):006:0> mt[2]

                                                  24
=> "06"
     irb(main):007:0> mt[3]
     => "2005"
     irb(main):008:0> mt = er.match("20062005")
     => nil
     irb(main):009:0>
No exemplo, se a string “casar” com a express˜o, vai ser retornado um objeto do tipo MatchData ,
                                                a
ou nil se n˜o “casar”. No objeto retornado podemos verificar o seu tamanho, que inclui a string que
           a
pesquisamos, seguida por seus tokens (iniciando em 1).

Podemos procurar em uma String onde uma express˜o regular “casa” usando index :
                                               a
     [taq@~]irb
     irb(main):001:0> "eustaquio".index(/taq/)
     => 3
     irb(main):002:0>
Tamb´m podemos usar o m´todo gsub da String para trocar seu conte´do utilizando uma express˜o
      e                e                                         u                         a
regular:
     [taq@~]irb
     irb(main):001:0> "eustaquio".gsub(/qu/,’c’)
     => "eustacio"
     irb(main):002:0>
Troquei meu nome ali por “Eust´cio” (que ´ o nome de um tiozinho ranzinza que vive assustando um
                              a          e
pobre cachorrinho em um desenho animado que tem por a´ :-)
                                                      ı).

Express˜es regulares tamb´m s˜o uma m˜o-na-roda quando usadas com iterators, como por exemplo:
       o                 e   a       a
     [taq@~]irb
     irb(main):001:0> a = %w(um dois tres quatro cinco seis sete oito nove dez)
     => ["um", "dois", "tres", "quatro", "cinco", "seis", "sete", "oito", "nove", "dez"]
     irb(main):002:0> a.grep(/s$/)
     => ["dois", "tres", "seis"]
Nesse caso usei o m´todo grep no array, que por ter um m´todo each, torna dispon´
                   e                                      e                        ıvel os m´todos
                                                                                            e
adicionais do m´dulo Enumerable, entre eles, grep. No exemplo eu pedi para filtrar os elementos que
               o
eram terminados com “s”.

Outro exemplo seria se tivermos um arquivo com os dados:
     [taq@~]cat teste.txt
     um
     dois
     tres
     quatro
     cinco
     seis
     sete
     oito
     nove
     dez
     [taq@~]irb
     irb(main):001:0> File.open("teste.txt").grep(/s$/) do |r|
     irb(main):002:1*    puts r
     irb(main):003:1> end
     dois
     tres
     seis

                                               25
3.2.11    Procs
Procs s˜o blocos de c´digo associados ` uma vari´vel:
       a             o                a         a
     [taq@~]irb
     irb(main):001:0> vezes3 = Proc.new {|n| n*3}
     => #<Proc:0xb7de21fc@(irb):1>
     irb(main):002:0> vezes3.call(1)
     => 3
     irb(main):003:0> vezes3.call(2)
     => 6
     irb(main):004:0> vezes3.call(3)
     => 9
     irb(main):005:0>
Podemos transformar um bloco de c´digo em uma Proc usando lambda:
                                 o
     [taq@~]irb
     irb(main):001:0> vezes3 = lambda {|n| n*3}
     => #<Proc:0xb7dd96c0@(irb):1>
     irb(main):002:0> vezes3.call(1)
     => 3
     irb(main):003:0> vezes3.call(2)
     => 6
     irb(main):004:0> vezes3.call(3)
     => 9
     irb(main):005:0>

3.2.12    M´todos
           e
M´todos tamb´m s˜o muito f´ceis de serem declarados. S˜o definidos usando def, terminando com end
  e            e   a        a                         a
(mais sobre isso na pr´xima se¸˜o):
                      o       ca
     [taq@~]irb
     irb(main):001:0> def diga_oi
     irb(main):002:1>    puts "oi!"
     irb(main):003:1> end
     => nil
     irb(main):004:0> diga_oi
     oi!
     => nil
     irb(main):005:0>

Retornando valores
Olhem que legal:
     [taq@~]irb
     irb(main):001:0> def vezes(n1,n2)
     irb(main):002:1>    n1*n2
     irb(main):003:1> end
     => nil
     irb(main):004:0> vezes(3,4)
     => 12
     irb(main):005:0>
U´! Cadˆ o return ali? N˜o precisa. O valor do retorno do m´todo nesse caso ´ a ultima express˜o
  e      e                  a                              e                e ´               a
avaliada, no caso, 3 vezes 4.

Tamb´m podemos retornar mais de um resultado (na verdade, apenas um objeto, complexo ou n˜o,
      e                                                                                  a
´ retornado, mas d´-se a impress˜o que s˜o v´rios):
e                 a             a       a a

                                                 26
[taq@~]irb
     irb(main):001:0> def cinco_multiplos(n)
     irb(main):002:1>    (1..5).map {|v| n*v}
     irb(main):003:1> end
     => nil
     irb(main):004:0> n1, n2, n3, n4, n5 = cinco_multiplos(5)
     => [5, 10, 15, 20, 25]
     irb(main):005:0> puts "m´ltiplos de 5: #{n1},#{n2},#{n3},#{n4},#{n5}"
                             u
     m´ltiplos de 5: 5,10,15,20,25
      u
     => nil
     irb(main):006:0>

Recebendo parˆmetros
             a
M´todos tamb´m recebem parˆmetros (que novidade ehehe) e retornam valores:
 e          e             a

     [taq@~]irb
     irb(main):001:0> def vezes(n1,n2)
     irb(main):002:1>    return n1*n2
     irb(main):003:1> end
     => nil
     irb(main):004:0> vezes(3,4)
     => 12
     irb(main):005:0>

M´todos tamb´m podem receber, como no PHP, argumentos com valores default, por exemplo:
 e          e

     [taq@~]irb
     irb(main):001:0> def hello(s="Desconhecido")
     irb(main):002:1>    puts "Oi, #{s}!"
     irb(main):003:1> end
     => nil
     irb(main):004:0> hello("TaQ")
     Oi, TaQ!
     => nil
     irb(main):005:0> hello
     Oi, Desconhecido!
     => nil
     irb(main):006:0>

Ent˜o, se n˜o passarmos um argumento, ele assume o que foi especificado como default.
   a       a

Tamb´m podemos ter parˆmetros vari´veis, por exemplo:
    e                 a           a

     [taq@~]irb
     irb(main):001:0> def vargars(*args)
     irb(main):002:1>    args.each {|v| puts "parametro recebido:#{v}"}
     irb(main):003:1> end
     => nil
     irb(main):004:0> vargars(1,2)
     parametro recebido:1
     parametro recebido:2
     => [1, 2]
     irb(main):005:0> vargars(1,2,3,4,5)
     parametro recebido:1
     parametro recebido:2
     parametro recebido:3
     parametro recebido:4

                                                27
parametro recebido:5
     => [1, 2, 3, 4, 5]
     irb(main):006:0>
Os parˆmetros vari´veis vem na forma de um Array, e para indicar no m´todo esse tipo de parˆmetro,
       a           a                                                 e                     a
´ s´ colocar um asterisco (*) na frente do nome do parˆmetro.
e o                                                   a

Podemos passar um bloco para o m´todo, executando-o com yield:
                                e
     [taq@~]irb
     irb(main):001:0>   def teste(n)
     irb(main):002:1>      yield(n)
     irb(main):003:1>   end
     => nil
     irb(main):004:0>   teste(2) {|i| i*i}
     => 4
     irb(main):005:0>   teste(3) {|i| i*i}
     => 9
     irb(main):006:0>   teste(4) {|i| i*i}
     => 16
     irb(main):007:0>
Para testar se o m´todo recebeu um bloco, podemos usar block given?:
                  e
     [taq@~]irb
     dirb(main):001:0> def teste(n)
     irb(main):002:1>    if block_given?
     irb(main):003:2>        yield(n)
     irb(main):004:2>    else
     irb(main):005:2*        puts "n~o foi passado um bloco!"
                                    a
     irb(main):006:2>    end
     irb(main):007:1> end
     => nil
     irb(main):008:0> teste(2) {|i| i*i}
     => 4
     irb(main):009:0> teste(3) {|i| i*i}
     => 9
     irb(main):010:0> teste(4) {|i| i*i}
     => 16
     irb(main):011:0> teste(5)
     n~o foi passado um bloco!
      a
     => nil
     irb(main):012:0>
E se passarmos o ultimo argumento de um m´todo com um & na frente, um bloco passado como parˆmetro
                 ´                       e                                                  a
ser´ convertido em uma Proc e associado ao parˆmetro:
   a                                          a
     [taq@~]irb
     irb(main):001:0>   def teste(n,&b)
     irb(main):002:1>      puts b.call(n)
     irb(main):003:1>   end
     => nil
     irb(main):004:0>   teste(2) {|i| i*i}
     4
     => nil
     irb(main):005:0>   teste(3) {|i| i*i}
     9
     => nil
     irb(main):006:0>   teste(4) {|i| i*i}

                                               28
16
     => nil
     irb(main):007:0>
Para converter uma Proc em um bloco de c´digo em um parˆmetro do m´todo, vocˆ pode usar o caracter
                                        o              a          e         e
& antes do nome da Proc:
     [taq@~]irb
     irb(main):001:0> quadrado = Proc.new {|i| i*i}
     => #<Proc:0xb7de2080@(irb):1>
     irb(main):002:0> def teste(n)
     irb(main):003:1>    puts yield(n)
     irb(main):004:1> end
     => nil
     irb(main):005:0> teste(3,&quadrado)
     9
     => nil
     irb(main):006:0>

Como os parˆmetros s˜o enviados
           a        a
Os parˆmetros s˜o passados por c´pia da referˆncia do objeto, ent˜o, se alterarmos um objeto que
       a       a                o            e                   a
foi passado como parˆmetro, dentro de um m´todo, e ele puder ser mut´vel, ele refletir´ fora do
                    a                      e                            a              a
m´todo. Por exemplo:
  e
     [taq@~]irb
     irb(main):001:0>     s = "Oi, mundo!"
     => "Oi, mundo!"
     irb(main):002:0>     s.object_id
     => -605086718
     irb(main):003:0>     def maiusculas(s)
     irb(main):004:1>        s.upcase!
     irb(main):005:1>     end
     => nil
     irb(main):006:0>     maiusculas(s)
     => "OI, MUNDO!"
     irb(main):007:0>     s
     => "OI, MUNDO!"
     irb(main):008:0>     s.object_id
     => -605086718
     irb(main):009:0>
Foi criada uma String (s), e logo depois verifiquei seu id. Dentro do m´todo alterei o parˆmetro usando o
                                                                      e                  a
m´todo upcase! verifiquei seu valor (que foi alterado para maiusc´las) e seu id, que continua o mesmo,
  e                                                                 u
ent˜o, o objeto foi alterado dentro do m´todo, usando como referˆncia o objeto que ele apontava, que
    a                                     e                         e
pode ser mut´vel.
             a
     ATENCAO!¸˜
     M´todos que alteram o valor e estado de um objeto geralmente tem um outro m´todo de
       e                                                                           e
     mesmo nome, por´m com um ! no final. Esses s˜o os chamados m´todos destrutivos. A
                      e                             a                e
     vers˜o sem ! pega uma c´pia da referˆncia, faz a mudan¸a, e retorna um novo objeto. Os
         a                    o           e                c
     m´todos destrutivos alteram o pr´prio objeto.
       e                             o
Se n˜o us´ssemos o !, somente retornando o valor convertido, ter´
    a     a                                                        ıamos retornado outro objeto, criado
dentro do m´todo, no seu retorno (pelo fato de s.upcase ser a ultima express˜o avaliada no m´todo). Se
            e                                                 ´             a               e
us´ssemos o !, o objeto retornado seria o mesmo que foi alterado.
  a

No exemplo abaixo, o parˆmetro n˜o foi alterado, mas foi retornado um novo objeto na chamada do
                         a       a
m´todo, atribu´ ` referˆncia anterior, s. Isso pode ser comprovado verificando seu id:
 e            ıdo a    e

                                                  29
[taq@~]irb
     irb(main):001:0>    s = "Oi, mundo!"
     => "Oi, mundo!"
     irb(main):002:0>    s.object_id
     => -605086718
     irb(main):003:0>    def maiusculas(s)
     irb(main):004:1>       s.upcase
     irb(main):005:1>    end
     => nil
     irb(main):006:0>    maiusculas(s)
     => "OI, MUNDO!"
     irb(main):007:0>    s
     => "Oi, mundo!"
     irb(main):008:0>    s.object_id
     => -605086718
     irb(main):009:0>    s = maiusculas(s)
     => "OI, MUNDO!"
     irb(main):010:0>    s
     => "OI, MUNDO!"
     irb(main):011:0>    s.object_id
     => -605122958
     irb(main):012:0>

Para alterar o valor de vari´veis do tipo Fixnum (Fixnum’s s˜o imut´veis), precisar´
                            a                               a      a               ıamos fazer do se-
gundo modo, retornando um novo objeto para a sua vari´vel apontando para o seu Fixnum, pois eles
                                                       a
n˜o podem ser alterados.
 a

Deixa eu tentar deixar mais vis´ aqui:
                               ıvel

     def teste1(s)
         print "Rodando TESTE1n"
         print "valor #{s}, id #{s.object_id}n"
         # Aqui ele cria um novo objeto com o valor da referencia em maiusculas
         # e aponta a referencia de s (ATENC~O! ele troca a refer^ncia de s,
                                           ¸A                    e
         # definida localmente aqui, para a localiza¸~o do novo objeto, e n~o
                                                    ca                     a
         # interfere com a vari´vel externa do m´todo que gerou s como
                               a                 e
         # par^metro!
              a
         s = s.upcase
         print "valor #{s}, id #{s.object_id} (aqui tem que ter um id diferente)nn"
     # Aqui ele retorna s, com sua nova refer^ncia, apontando para o novo objeto
                                              e
     s
     end

     def teste2(s)
         print "Rodando TESTE2n"
         print "valor #{s}, id #{s.object_id}n"
     # M´todo destrutivo ` frente! Vai agir direto no objeto
         e                a
     # que se encontra na refer^ncia apontada por s
                                e
         s.upcase!
         print "valor #{s}, id #{s.object_id}nn"
         s
     end

     s1 = "teste" # s1 aponta para um objeto do tipo String, com conte´do "teste"
                                                                      u
     s2 = s1 # s2 aponta para s1
     sd = s1.dup # duplica para outro


                                                 30
print   "Vamos verificar os objetos:n"
     print   "s1 id:#{s1.object_id}, vale #{s1}n"
     print   "s2 id:#{s2.object_id}, vale #{s2}n"
     print   "sd id:#{sd.object_id}, vale #{sd} (objeto duplicado, id diferente!)nn"

     s3 = teste1(s1)
     print "Vamos verificar os objetos:n"
     print "s1 id:#{s1.object_id}, vale #{s1}n"
     print "s2 id:#{s2.object_id}, vale #{s2}n"
     print "s3 id:#{s3.object_id}, vale #{s3} (aqui tem que ter um id diferente)n"
     print "sd id:#{sd.object_id}, vale #{sd} (objeto duplicado, id diferente!)nn"

     s4 = teste2(s1)
     print "Vamos verificar os objetos:n"
     print "s1 id:#{s1.object_id}, vale #{s1}n"
     print "s2 id:#{s2.object_id}, vale #{s2}n"
     print "s3 id:#{s3.object_id}, vale #{s3}n"
     print "s4 id:#{s4.object_id}, vale #{s4}n"
     print "sd id:#{sd.object_id}, vale #{sd} (objecto duplicado, id diferente, valor original!)n"

Resultado:

     Vamos verificar os objetos:
     s1 id:-604854218, vale teste
     s2 id:-604854218, vale teste
     sd id:-604854228, vale teste (objeto duplicado, id diferente!)

     Rodando TESTE1
     valor teste, id -604854218
     valor TESTE, id -604854348 (aqui tem que ter um id diferente)

     Vamos verificar os objetos:
     s1 id:-604854218, vale teste
     s2 id:-604854218, vale teste
     s3 id:-604854348, vale TESTE (aqui tem que ter um id diferente)
     sd id:-604854228, vale teste (objeto duplicado, id diferente!)

     Rodando TESTE2
     valor teste, id -604854218
     valor TESTE, id -604854218

     Vamos verificar os objetos:
     s1 id:-604854218, vale TESTE
     s2 id:-604854218, vale TESTE
     s3 id:-604854548, vale TESTE
     s4 id:-604854218, vale TESTE
     sd id:-604854228, vale teste (objecto duplicado, id diferente, valor original!)

Tentando expressar isso graficamente:




                                            31
Figura 3.1: Representa¸˜o de referˆncias aos objetos
                                            ca          e


Vamos analisar detalhadamente o que ocorre aqui.
ˆ Criei uma vari´vel, s1, que aponta para um objeto tipo String (vari´veis n˜o s˜o objetos, lembre-
                 a                                                   a      a a
  se!). Esse objeto foi criado e armazenado em uma determinada ´rea da mem´ria (vejam para onde
                                                                a            o
  s1 aponta).
ˆ Criei uma segunda vari´vel, s2, apontando para o mesmo lugar (mesmo objeto) que s1.
                        a
ˆ Criei outra vari´vel, sd, duplicando s1, isso ´, criando um novo objeto do tipo de s1 (String), usando
                  a                             e
  como ponto de partida o valor referenciado por s1.
ˆ Verifiquei os ids das vari´veis. As vari´veis s1 e s2 tem ids idˆnticos, enquanto sd tem um diferente,
                           a             a                       e
  tudo certo, pois sd aponta para outro objeto.
ˆ Criei uma nova vari´vel s3 com o resultado do m´todo teste1, que recebe uma c´pia da re-
                      a                             e                                o
  ferˆncia do objeto, como uma vari´vel local no escopo do m´todo corrente, executa uma opera¸˜o
     e                               a                       e                               ca
  criando um novo objeto, cuja referˆncia ´ retornada pelo m´todo e armazenada em s3. Vejam no
                                    e     e                 e
  gr´fico o objeto para onde s3 aponta.
    a
ˆ Dentro de teste1 isso fica expl´
                                ıcito na primeira chamada, onde o id do objeto ´ o mesmo de s1,
                                                                                 e
  e quando retornado (poderia ter retornado direto, sem a vari´vel s, que ia dar na mesma, fiz assim
                                                              a
  s´ para ficar mais claro) temos o id do novo objeto.
   o
ˆ Criei uma nova vari´vel s4 com o resultado do m´todo teste2, que recebe uma c´pia da referˆncia
                     a                            e                            o            e
  do objeto, como uma vari´vel local no escopo do m´todo corrente, e altera diretamente o
                             a                           e
  objeto referenciado pela vari´vel, convertendo-o para mai´ sculas, nesse caso. Reparem
                                  a                                u
  em teste2 como os valores est˜o diferentes, mas os ids s˜o os mesmos.
                               a                          a
ˆ A vari´vel s4, ent˜o, aponta para o mesmo objeto originalmente referenciado por s1 e s2, enquanto
        a           a
  s3 continua sossegada apontando para o objeto criado por teste1, e sd, que foi duplicada no come¸o,
                                                                                                  c
  continua a mesma tamb´m. e

                                                 32
Podemos pensar em vari´veis como umas caixinhas com v´rios bilhetinhos dentro, com as coordenadas
                        a                                a
de uma cidade. Quando vocˆ passa a vari´vel como parˆmetro, vamos imaginar que vocˆ est´ despejando
                           e           a             a                                e a
na caixa vazia do seu amigo um dos bilhetinhos de uma de suas caixas.
O bilhetinho fica no espa¸o f´
                        c ısico (escopo) da caixa do seu amigo, e pode ser utilizado para dois motivos:

   ˆ Apontar para outra cidade (ou at´ para uma panela, se vocˆ quiser, levando em conta que isso
                                        e                         e
     alterar´ o tipo original da referˆncia que vocˆ pegar de volta da caixinha do seu amigo, e vocˆ
            a                         e            e                                               e
     pode ficar surpreso de n˜o encontrar uma cidade l´). O n´mero est´ escrito ` l´pis, pegue uma
                              a                         a      u         a        a a
     borracha, apague e escreva um novo n´mero l´, desde que o lugar novo exista, mesmo que
                                            u      a
     tenha que ser criado ali na hora.

   ˆ Atrav´s de um telefone no verso do bilhetinho, ligar l´ na cidade e dizer “ei, pintem as ruas a´ de
           e                                                 a                                      ı
     verde-lim˜o”, se isso for poss´ naquela cidade (se ela tiver um m´todo para isso). Nesse caso, o
              a                     ıvel                                   e
     tipo apontado pelo bilhetinho ´ mantido, ou seja, continua a ser uma cidade no mesmo lugar, mas
                                      e
     alguma caracter´ıstica foi alterada no local (as ruas est˜o pintadas de verde-lim˜o arrrrgh!).
                                                              a                       a

Para exemplificar e complicar um pouco mais, vamos ver esses exemplos:

     [taq@~/code/ruby]irb
     irb(main):001:0> i1 = 1
     => 1
     irb(main):002:0> i2 = 1
     => 1
     irb(main):003:0> i3 = 1
     => 1
     irb(main):004:0> i4 = 2
     => 2
     irb(main):005:0> i5 = 2
     => 2
     irb(main):006:0> i1.object_id
     => 3
     irb(main):007:0> i2.object_id
     => 3
     irb(main):008:0> i3.object_id
     => 3
     irb(main):009:0> i4.object_id
     => 5
     irb(main):010:0> i5.object_id
     => 5
     irb(main):011:0>

Olhem que legal! As vari´veis dos Fixnum’s apontam sempre para o mesmo objeto (verificando isso
                          a
usando o object id) do tipo Fixnum que foi atribu´ ` elas. Isso por que Fixnum s˜o “immediate va-
                                                 ıdo a                           a
lues”, que armazenam o valor, e n˜o a referˆncia do objeto, assim como true, false, nil e s´
                                 a         e                                               ımbolos.

N˜o se esque¸am que objetos do tipo Fixnum s˜o imut´veis, e s˜o immediate values (est˜o l´ e ningu´m
 a          c                               a      a         a                       a a          e
muda!).

Fazendo uma compara¸˜o com nosso exemplo de Strings acima, se vocˆ criasse outra vari´vel valendo
                      ca                                               e                  a
“teste”, al´m das que estavam l´, seria outra String com valor “teste”, ao contr´rio dos Fixnum’s que
           e                   a                                                a
s˜o sempre o mesmo objeto:
 a

     [taq@~/latex/ruby]irb
     irb(main):001:0> s1 = "teste"
     => "teste"
     irb(main):002:0> s2 = s1
     => "teste"
     irb(main):003:0> sd = s1.dup

                                                  33
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa
Apostila ruby-completa

Mais conteúdo relacionado

Mais procurados

Tutorial ruby eustaquio taq rangel
Tutorial ruby   eustaquio taq rangelTutorial ruby   eustaquio taq rangel
Tutorial ruby eustaquio taq rangelWalker Maidana
 
Aprenda computação com python 3.0 (1)
Aprenda computação com python 3.0 (1)Aprenda computação com python 3.0 (1)
Aprenda computação com python 3.0 (1)intaum
 
Python
PythonPython
PythonTiago
 
Caelum csharp-dotnet-fn13
Caelum csharp-dotnet-fn13Caelum csharp-dotnet-fn13
Caelum csharp-dotnet-fn13Moisés Moura
 
História da criptografia
História da criptografiaHistória da criptografia
História da criptografiatiojoffre
 
Programming Languages Paradigms
Programming Languages ParadigmsProgramming Languages Paradigms
Programming Languages Paradigmsrodrigovmoraes
 
Apostila de Java: Orientação a Objetos
Apostila de Java: Orientação a ObjetosApostila de Java: Orientação a Objetos
Apostila de Java: Orientação a ObjetosK19 Treinamentos
 
Desenvolvimento-web-com-html-css-e-javascript
Desenvolvimento-web-com-html-css-e-javascriptDesenvolvimento-web-com-html-css-e-javascript
Desenvolvimento-web-com-html-css-e-javascriptManuel Fernando
 
Caelum java-testes-xml-design-patterns-fj16
Caelum java-testes-xml-design-patterns-fj16Caelum java-testes-xml-design-patterns-fj16
Caelum java-testes-xml-design-patterns-fj16Caique Moretto
 
Tcc Mauricio Bento Ghem 2009 - Versão Final
Tcc Mauricio Bento Ghem 2009 - Versão FinalTcc Mauricio Bento Ghem 2009 - Versão Final
Tcc Mauricio Bento Ghem 2009 - Versão Finalimpalador69
 
K19 k03-sql-e-modelo-relacional
K19 k03-sql-e-modelo-relacionalK19 k03-sql-e-modelo-relacional
K19 k03-sql-e-modelo-relacionalJean Lopes
 

Mais procurados (16)

Estrutura de dados 2
Estrutura de dados 2Estrutura de dados 2
Estrutura de dados 2
 
Tutorial ruby eustaquio taq rangel
Tutorial ruby   eustaquio taq rangelTutorial ruby   eustaquio taq rangel
Tutorial ruby eustaquio taq rangel
 
Aprenda computação com python 3.0 (1)
Aprenda computação com python 3.0 (1)Aprenda computação com python 3.0 (1)
Aprenda computação com python 3.0 (1)
 
Python
PythonPython
Python
 
Caelum csharp-dotnet-fn13
Caelum csharp-dotnet-fn13Caelum csharp-dotnet-fn13
Caelum csharp-dotnet-fn13
 
História da criptografia
História da criptografiaHistória da criptografia
História da criptografia
 
Perl
PerlPerl
Perl
 
Pascal
PascalPascal
Pascal
 
Php
PhpPhp
Php
 
Programming Languages Paradigms
Programming Languages ParadigmsProgramming Languages Paradigms
Programming Languages Paradigms
 
Apostila de Java: Orientação a Objetos
Apostila de Java: Orientação a ObjetosApostila de Java: Orientação a Objetos
Apostila de Java: Orientação a Objetos
 
Desenvolvimento-web-com-html-css-e-javascript
Desenvolvimento-web-com-html-css-e-javascriptDesenvolvimento-web-com-html-css-e-javascript
Desenvolvimento-web-com-html-css-e-javascript
 
Material LINUX
Material LINUXMaterial LINUX
Material LINUX
 
Caelum java-testes-xml-design-patterns-fj16
Caelum java-testes-xml-design-patterns-fj16Caelum java-testes-xml-design-patterns-fj16
Caelum java-testes-xml-design-patterns-fj16
 
Tcc Mauricio Bento Ghem 2009 - Versão Final
Tcc Mauricio Bento Ghem 2009 - Versão FinalTcc Mauricio Bento Ghem 2009 - Versão Final
Tcc Mauricio Bento Ghem 2009 - Versão Final
 
K19 k03-sql-e-modelo-relacional
K19 k03-sql-e-modelo-relacionalK19 k03-sql-e-modelo-relacional
K19 k03-sql-e-modelo-relacional
 

Semelhante a Apostila ruby-completa

Introdução à programação em R
Introdução à programação em RIntrodução à programação em R
Introdução à programação em RMonica Barros
 
Matematica fcul
Matematica fculMatematica fcul
Matematica fculemantunes
 
algebra vetorial
algebra vetorialalgebra vetorial
algebra vetorial182423
 
Analise real cattai_uneb
Analise real cattai_unebAnalise real cattai_uneb
Analise real cattai_unebjecyjs
 
Analise real cattai_uneb
Analise real cattai_unebAnalise real cattai_uneb
Analise real cattai_unebSaulo Maggot
 
Analise real
Analise realAnalise real
Analise realDelerre
 
Ap apostila arduino-rev4
Ap   apostila arduino-rev4Ap   apostila arduino-rev4
Ap apostila arduino-rev4ariferreira3
 
Apostila de Robotica
Apostila de RoboticaApostila de Robotica
Apostila de RoboticaIsvaldo Souza
 
Curso de robotica movel
Curso de robotica movelCurso de robotica movel
Curso de robotica movelRibeiro Baieta
 
BEY, Hakim (2003) - Caos terrorismo poético e outros crimes exemplares
BEY, Hakim (2003) - Caos terrorismo poético e outros crimes exemplaresBEY, Hakim (2003) - Caos terrorismo poético e outros crimes exemplares
BEY, Hakim (2003) - Caos terrorismo poético e outros crimes exemplaresFabio Pedrazzi
 
Apostila completa de eletronica digita(fct)
Apostila completa de eletronica digita(fct)Apostila completa de eletronica digita(fct)
Apostila completa de eletronica digita(fct)Edaplo
 
8º apostila dos números de 1 a 9 simone helen drumond
8º apostila dos números de 1 a 9 simone helen drumond8º apostila dos números de 1 a 9 simone helen drumond
8º apostila dos números de 1 a 9 simone helen drumondSimoneHelenDrumond
 
7º apostila dos números de 1 a 9 simone helen drumond
7º apostila dos números de 1 a 9 simone helen drumond7º apostila dos números de 1 a 9 simone helen drumond
7º apostila dos números de 1 a 9 simone helen drumondSimoneHelenDrumond
 

Semelhante a Apostila ruby-completa (20)

Introdução à programação em R
Introdução à programação em RIntrodução à programação em R
Introdução à programação em R
 
Matematica fcul
Matematica fculMatematica fcul
Matematica fcul
 
Apostila tex
Apostila texApostila tex
Apostila tex
 
Apostila latex
Apostila latexApostila latex
Apostila latex
 
algebra vetorial
algebra vetorialalgebra vetorial
algebra vetorial
 
Analise real cattai_uneb
Analise real cattai_unebAnalise real cattai_uneb
Analise real cattai_uneb
 
Analise real cattai_uneb
Analise real cattai_unebAnalise real cattai_uneb
Analise real cattai_uneb
 
Analise real
Analise realAnalise real
Analise real
 
Ap apostila arduino-rev4
Ap   apostila arduino-rev4Ap   apostila arduino-rev4
Ap apostila arduino-rev4
 
Apostila de Robotica
Apostila de RoboticaApostila de Robotica
Apostila de Robotica
 
Curso de robotica movel
Curso de robotica movelCurso de robotica movel
Curso de robotica movel
 
33.novembro 2011 revista
33.novembro 2011 revista33.novembro 2011 revista
33.novembro 2011 revista
 
BEY, Hakim (2003) - Caos terrorismo poético e outros crimes exemplares
BEY, Hakim (2003) - Caos terrorismo poético e outros crimes exemplaresBEY, Hakim (2003) - Caos terrorismo poético e outros crimes exemplares
BEY, Hakim (2003) - Caos terrorismo poético e outros crimes exemplares
 
Apostila completa de eletronica digita(fct)
Apostila completa de eletronica digita(fct)Apostila completa de eletronica digita(fct)
Apostila completa de eletronica digita(fct)
 
Calculo integral e_diferencial_3[1]
Calculo integral e_diferencial_3[1]Calculo integral e_diferencial_3[1]
Calculo integral e_diferencial_3[1]
 
Tutorial ruby
Tutorial rubyTutorial ruby
Tutorial ruby
 
Catalogo stamaco 2012
Catalogo stamaco 2012Catalogo stamaco 2012
Catalogo stamaco 2012
 
Tutorial de Uppaal
Tutorial de UppaalTutorial de Uppaal
Tutorial de Uppaal
 
8º apostila dos números de 1 a 9 simone helen drumond
8º apostila dos números de 1 a 9 simone helen drumond8º apostila dos números de 1 a 9 simone helen drumond
8º apostila dos números de 1 a 9 simone helen drumond
 
7º apostila dos números de 1 a 9 simone helen drumond
7º apostila dos números de 1 a 9 simone helen drumond7º apostila dos números de 1 a 9 simone helen drumond
7º apostila dos números de 1 a 9 simone helen drumond
 

Apostila ruby-completa

  • 1. Tutorial de Ruby Eust´quio “TaQ” Rangel (eustaquiorangel@yahoo.com) a 19 de julho de 2005
  • 2. Este trabalho est´ licenciado sob uma Licen¸a Creative Commons Atribui¸˜o-Uso N˜o- a c ca a Comercial-Compatilhamento pela mesma licen¸a. c Para ver uma c´pia desta licen¸a, visite o c http://creativecommons.org/licenses/by-nc-sa/2.5/br/ ou envie uma carta para Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. Este documento foi feito usando L TEX. A Vers˜o 0.1 a Para atualiza¸˜es, visite http://beam.to/taq/tutorialruby.php co A figura do logotipo de Ruby acima ´ de minha livre autoria, n˜o representando um e a logotipo oficial 2
  • 3. Sum´rio a 1 Introdu¸˜o ca 9 1.1 O que ´ Ruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 e 1.2 Onde encontro Ruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2 Arrumando as coisas 11 2.1 Preparando sua fonte de consultas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.2 Preparando o ambiente de trabalho . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3 Conhecendo o b´sico da linguagem a 13 3.1 Vari´veis . . . . . . . . . . . . . . . . . . . a . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.1.1 Escopo das vari´veis . . . . . . . . a . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 3.2 Tipos b´sicos . . . . . . . . . . . . . . . . a . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.2.1 Blocos de c´digo . . . . . . . . . . o . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.2.2 N´meros . . . . . . . . . . . . . . . u . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.2.3 Booleanos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3.2.4 Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3.2.5 Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3.2.6 Ranges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3.2.7 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 3.2.8 Hashes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 3.2.9 S´ ımbolos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3.2.10 Express˜es regulares . . . . . . . . o . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3.2.11 Procs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.2.12 M´todos . . . . . . . . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Retornando valores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Recebendo parˆmetros . . . . . . . a . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Como os parˆmetros s˜o enviados a a . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 M´todos destrutivos . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 M´todos predicados . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 M´todos ou fun¸˜es . . . . . . . . e co . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 3.2.13 Operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 3.2.14 Juntando tudo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 3.3 Estruturas de controle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.3.1 Condicionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 unless . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 3.3.2 Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 until . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 begin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3.4 Coment´rios no c´digo . . . . . . . . . . . a o . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 3
  • 4. 4 Classes 47 4.1 Vari´veis de instˆncia . . . . . . . . . a a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 4.2 Vari´veis de classe . . . . . . . . . . . a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 4.3 M´todos de classe . . . . . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 4.4 Executando m´todos da classe pai . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 4.5 Redefinindo operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 4.6 Heran¸a . . . . . . . . . . . . . . . . . c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 4.7 Duplicando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 4.8 Controle de acesso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 4.8.1 M´todos p´blicos . . . . . . . . e u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 4.8.2 M´todos privados . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 4.8.3 M´todos protegidos . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 4.8.4 Especificando o tipo de acesso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 4.9 Classes e m´todos singleton . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 5 Entrada e sa´ıda 73 5.1 Fluxos simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 5.2 Fluxos mais complexos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 5.2.1 Arquivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Lendo arquivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Escrevendo em arquivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 5.2.2 Fluxos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 TCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 UDP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 6 Exce¸˜es co 81 6.1 Begin . . . rescue . . . ensure . . . end . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 6.2 Throw . . . catch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 7 M´dulos o 87 8 Threads 91 8.1 Timeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 8.2 Criando usando Proc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 8.3 Sincroniza¸˜o . . . . ca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 8.4 Condition variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 9 Acessando banco de dados 99 9.1 Abrindo a conex˜o . . . . . . . . . . . . . . . . . . . a . . . . . . . . . . . . . . . . . . . . . 99 9.2 Executando queries que n˜o retornam resultado . . . a . . . . . . . . . . . . . . . . . . . . . 100 9.3 Recuperando dados do banco de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 9.4 Preparando comandos e usando parametros vari´veis a . . . . . . . . . . . . . . . . . . . . . 101 9.5 Metadados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 9.6 Trabalhando com blocos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 9.7 Output especializado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 9.7.1 Tabular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 9.7.2 XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 10 XML 109 10.1 Lendo arquivos XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 10.2 Criando arquivos XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 11 YAML 113 11.1 Lendo arquivos YAML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 11.2 Gravando arquivos YAML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 4
  • 5. 12 XSLT 117 13 Usando Ruby na web 119 13.1 mod ruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 13.1.1 Instalando o mod ruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 13.1.2 Configurando o servidor Apache . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 13.1.3 Testando o mod ruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 13.2 eruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 13.2.1 Instalando o eruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 13.2.2 Configurando o servidor Apache . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 13.2.3 Testando o eruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 13.2.4 Sintaxe do eruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 13.3 CGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 13.3.1 Forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 13.3.2 Cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 13.3.3 Sess˜es . . . . . . . . . . . . . . o . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 14 Interface Gr´fica a 131 14.1 Obtendo e compilando o m´dulo GTK2 o . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 14.2 Hello, GUI world! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 14.3 Eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 14.4 Packing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 14.5 Posicionamento usando tabelas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 14.6 Mais alguns componentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 14.6.1 CheckButton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 14.6.2 ComboBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 14.6.3 Campos texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 14.6.4 Radio buttons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 15 Garbage collector 141 15.1 O algoritmo utilizado: mark-and-sweep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 15.2 Como funciona, na teoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 15.3 Como funciona, na pr´tica . . . . . . . . a . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 15.4 Otimizando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 16 Unit Testing 147 16.1 A classe a ser testada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 16.2 Unidade de testes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 16.3 Falhas nos testes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 16.4 Novas funcionalidades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 17 XML-RPC 155 17.1 Servidor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 17.2 Cliente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 17.3 Acessando de outras linguagens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 5
  • 6. 6
  • 7. Um pouco de bate-papo . . . Eu comecei a fazer esse tutorial como sempre come¸o fazendo as minhas coisas: necessidade de me lem- c brar depois. Como estou come¸ando a aprender a programar em Ruby agora (Nov/2004), quero fazer algumas c anota¸˜es, me perdoem se em algum ponto eu fizer alguma bobagenzinha, mas depois de rirem disso me co enviem um email (eustaquiorangel@yahoo.com) para que eu possa corrigir o que estiver errado. :-) Tenho experiˆncia como programador j´ faz alguns bons anos, e j´ passei por v´rias linguagens, e no e a a a decorrer do manual vou citar algumas compara¸˜es entre o Ruby e Java —, Python, PHP, etc. Estou co presumindo que vocˆ tamb´m programe em alguma linguagem, sendo que esse n˜o ´ um tutorial para e e a e aprender a programar, e sim para aprender a programar em Ruby, com experiˆncia de programa¸˜o e ca j´ adquirida em outras linguagens. a Ao mesmo tempo, n˜o vou me ater muito em explicar as entranhas da linguagem aqui, apesar de mostrar a algumas coisinhas. :-) Alguns c´digos tamb´m podem n˜o estar com sua otimiza¸˜o “no talo”, mas para efeito de tutorial, o e a ca ´ melhor assim. e E sobre linguagens, deixe-me fazer um singelo protesto aqui. N˜o vou falar sobre qual ´ melhor ou a e n˜o, por que discutir isso para mim ´ perda de tempo. a e N˜o por que eu saiba a resposta de qual ´, mas por que acho que s˜o todas linguagens boas e o que a e a difere nesse ponto s˜o como as pessoas as veˆm e as utilizam. Tenho v´rias cita¸˜es de outras linguagens a e a co no decorrer do texto, mas em car´ter puramente comparativo/informativo, e n˜o nos termos de “aquela a a porcaria de XYZ faz isso dessa maneira”. c a e e ˜ Esse tipo de ca¸a `s bruxas ´ justamente o que vocˆ NAO vai encontrar aqui. J´ perdi muito tempo com a esse tipo de coisa, e espero que ao inv´s de vocˆ perder tamb´m sente e escreva c´digo na sua linguagem e e e o preferida do que ficar fazendo flamewars por a´ :-) ı. Ent˜o, vamos nessa. a Dedico esse trabalho ` minha filhinha Ana Isabella, que me ilumina todos os dias. a 7
  • 8. 8
  • 9. Cap´ ıtulo 1 Introdu¸˜o ca 1.1 O que ´ Ruby e Para explicar o que ´ Ruby, eu fa¸o uma tradu¸˜o livre do que Yukihiro “Matz” Matsumoto, seu criador, e c ca diz a respeito dela em http://www.ruby-lang.org/en/20020101.html: Ruby ´ uma linguagem de script interpretada para programa¸˜o orientada a objetos de um modo f´cil e e ca a r´pido. Ela tem v´rios recursos para processar arquivos de texto e para fazer tarefas de gerenciamento a a de sistema (assim como o Perl). Ela ´ simples, direto ao ponto, extens´ e port´vel. e ıvel a Oh, preciso mencionar, ´ totalmente livre, o que significa n˜o s´ livre de precisar pagar para us´-la, e a o a mas tamb´m a liberdade de usar, copiar, modificar e distribu´ e ı-la. Recursos do Ruby ˆ Ruby tem uma sintaxe simples, parcialmente inspirada por Eiffel e Ada. ˆ Ruby tem recursos de tratamento de exce¸˜es, assim como Java —e Python, para deixar mais f´cil co a o tratamento de erros. ˆ Os operadores do Ruby s˜o a¸ucar sint´tico para os m´todos. Vocˆ pode redefini-los facilmente. a c a e e ˆ Ruby ´ uma linguagem completa e pura orientada ` objetos. Isso significa que todo dado em Ruby e a ´ um objeto, n˜o do jeito de Python e Perl, mas mais do jeito do SmallTalk: sem exce¸˜es. Por e a co exemplo, em Ruby, o n´mero 1 ´ uma instˆncia da classe Fixnum. u e a ˆ A orienta¸˜o ` objetos do Ruby ´ desenhada cuidadosamente para ser completa e aberta ` me- ca a e a lhorias. Por exemplo, Ruby tem a habilidade de adicionar m´todos em uma classe, ou at´ mesmo e e em uma instˆncia durante o runtime! Ent˜o, se necess´rio, a instˆncia de uma classe *pode* se a a a a comportar diferente de outras instˆncias da mesma classe. a ˆ Ruby tem heran¸a unica, de prop´sito. Mas entende o conceito de m´dulos (chamados de Categories c ´ o o no Objective-C). M´dulos s˜o cole¸˜es de m´todos. Toda classe pode importar um m´dulo e pegar o a co e o seus m´todos. Alguns de n´s acham que isso ´ um jeito mais limpo do que heran¸a m´ltipla, que e o e c u ´ complexa e n˜o ´ usada tanto comparado com heran¸a unica (n˜o conte C++ aqui, pois l´ n˜o e a e c ´ a a a se tem muita escolha devido a checagem forte de tipo!). ˆ Ruby tem closures verdadeiras. N˜o apenas fun¸˜es sem nome, mas com bindings de v´riaveis a co a verdadeiras. ˆ Ruby tem blocos em sua sintaxe (c´digo delimitado por ’{’. . . ’}’ ou ’do’. . . ’end’). Esses blocos o podem ser passados para os m´todos, ou convertidos em closures. e ˆ Ruby tem um garbage collector que realmente ´ do tipo marca-e-limpa. Ele atua em todos os e objetos do Ruby. Vocˆ n˜o precisa se preocupar em manter contagem de referˆncias em libraries e a e ´ externas. E melhor para a sua sa´de. ;-) u 9
  • 10. ˆ Escrever extens˜es em C para Ruby ´ mais f´cil que em Perl ou Python, em grande parte por o e a causa do garbage collector, e em parte pela boa API de extens˜es. A interface SWIG tamb´m est´ o e a dispon´ ıvel. ˆ Inteiros em Ruby podem (e devem) ser usados sem contar sua representa¸˜o interna. Existem ca inteiros pequenos (instˆncias da classe Fixnum) e grandes (Bignum), mas vocˆ n˜o precisa se a e a preocupar em qual est´ sendo utilizado atualmente. Se um valor ´ pequeno o bastante, um inteiro a e ´ um Fixnum, do contr´rio ´ um Bignum. A convers˜o ocorre automaticamente. e a e a ˆ Ruby n˜o precisa de declara¸˜o de vari´veis. Apenas usa a conven¸˜o de nomenclatura para a ca a ca delimitar o escopo das vari´veis. Por exemplo: ’var’ = vari´vel local, ’@var’ = vari´vel de instˆncia, a a a a ’$var’= vari´vel global. E n˜o precisa do uso cansativo do ’self’ em cada membro da instˆncia. a a a ˆ Ruby pode carregar bibliotecas de extens˜o dinamicamente, se o sistema operacional permitir. a ˆ Ruby tem um sistema de threading independente do sistema operacional. Ent˜o, para cada plata- a forma que vocˆ roda o Ruby, vocˆ tem multithreading de qualquer jeito, at´ no MS-DOS! ;-) e e e ˆ Ruby ´ altamente port´vel: ela ´ desenvolvida em sua maioria no Linux, mas funciona em muitos e a e tipos de UNIX, DOS, Windows 95/98/Me/NT/2000/XP, MacOS, BeOS, OS/2, etc. 1.2 Onde encontro Ruby Vocˆ pode encontrar Ruby no seu site oficial na internet: e http://www.ruby-lang.org L´ vocˆ encontra o c´digo-fonte e vers˜es para Windows —. Compilar o c´digo ´ r´pido e f´cil, no a e o o o e a a velho esquema tar xvzf ruby-$<versao>$.tgz ./configure make make install Procure na sua distribui¸˜o (se vocˆ usa GNU/Linux) algum pacote do Ruby. Se n˜o encontrar, compile- ca e a o e o disponibilize em algum lugar. Eu fiz um pacote para o Slackware, est´ dispon´ aqui: a ıvel http://beam.to/taq/downloads.php Se vocˆ pegar o pacote, pegue tamb´m a assinatura PGP do arquivo, importe a minha chave p´blica e e u (784988BB) e fa¸a a conferˆncia. c e 10
  • 11. Cap´ ıtulo 2 Arrumando as coisas 2.1 Preparando sua fonte de consultas ´ E sempre bom ter uma referˆncia das classes, m´dulos e m´todos dispon´ e o e ıveis em uma linguagem quando se est´ aprendendo. a Ruby vem com um utilit´rio chamado ri que facilita a sua consulta ´ essa documenta¸˜o. Mas para ele a a ca poder consultar alguma coisa, primeiro temos que gera-l´. a Depois de instalado o Ruby, v´ para o diret´rio onde vocˆ instalou os fontes e digite, por exemplo: a o e [taq@/usr/src/ruby-1.8.1]rdoc --ri *.c lib/*.rb Isso vai produzir a documenta¸˜o do core do Ruby, que vai ser armazenada no seu diret´rio /.rdoc. ca o Ap´s isso podemos utilizar o ri dessa maneira, por exemplo: o [taq@ ]ri File ----------------------------------------------------------- Module: File A File is an abstraction of any file object accessible by the program and is closely associated with class IO File includes the methods of module FileTest as class methods, allowing you to write (for example) File.exist?("foo"). ... Se utilizarmos um console que tenha suporte a cores, podemos criar um alias: alias ri=ri -f ansi -T Assim o exemplo acima fica [taq@ ]ri File ----------------------------------------------------------- Module: File A File is an abstraction of any file object accessible by the program and is closely associated with class IO File includes the methods of module FileTest as class methods, allowing you to write (for example) File.exist?("foo"). ... 2.2 Preparando o ambiente de trabalho N˜o tem jeito melhor de aprender a programar em uma linguagem do que j´ ir colocando a m˜o na a a a massa. Ruby tem um programinha muito bom para ir testando o c´digo, o irb (interactive Ruby shell). o Estilo do Python, que podemos chamar e j´ ir digitando as coisas e vendo os resultados. a Antes de abrirmos o irb, vamos alterar o arquivo .irbrc, que fica no seu diret´rio home. o 11
  • 12. ¸˜ ATENCAO Estou usando GNU/Linux durante todo esse tutorial, e presumo que voc^ est´ usando e a tamb´m. L´gico que voc^ pode rodar Ruby em qualquer dos sistemas operacionais e o e citados acima, mas eu realmente n~o tenho param^tros para lhe dizer como fazer a e as configura¸~es em outro sistema. co Insira require ’irb/completion’ no arquivo. Ok, agora chame o irb simplesmente digitando irb no terminal: [taq@~]irb irb(main):001:0$>$ Agora o irb j´ est´ pronto para ser usado. Vamos conhecer mais um pouco dele: a a irb(main):001:0> i = 10 => 10 irb(main):002:0> if i > 5 irb(main):003:1> puts "maior que 5" irb(main):004:1> else irb(main):005:1* puts "menor que 5" irb(main):006:1> end maior que 5 => nil irb(main):007:0> Separando o prompt pelos dois pontos (:), temos algumas se¸˜es: co ˆ O nome do programa que estamos rodando (main) ˆ O n´mero de linhas que digitamos (e estamos!) no irb u ˆ O n´ de profundidade que estamos ıvel O n´ de profundidade ´ incrementado sempre que abrimos uma express˜o que precisa de fechamento. ıvel e a Sempre que o irb verificar que o c´digo precisa ser fechado, ele vai trocar o final do prompt por um o asterisco, ou aspas-duplas se n˜o fechamos uma String: a [taq@~]irb irb(main):001:0> s = "um teste irb(main):002:0" do irb" => "um teste ndo irb" irb(main):003:0> Olhem o n´ de profundidade alterado: ıvel [taq@~]irb irb(main):001:0> def teste(n) irb(main):002:1> if n > 10 irb(main):003:2> puts "teste" irb(main):004:2> end irb(main):005:1> end => nil irb(main):006:0> 12
  • 13. Cap´ ıtulo 3 Conhecendo o b´sico da linguagem a 3.1 Vari´veis a Vamos destrinchar aqui alguns tipos b´sicos do Ruby, e como usar vari´veis com eles. a a Apesar de ter sido dito que TUDO em Ruby ´ um objeto, vari´veis n˜o s˜o objetos, mas referˆncias para e a a a e esses. As vari´veis do Ruby s˜o muito simples de serem utilizadas pois utilizam a “duck typing”, como a a ´ chamada carinhosamente a tipagem dinˆmica do Ruby. Para os que vieram do Java —, que tem uma e a tipagem est´tica, um bom exemplo seria a [taq@~]irb irb(main):001:0> v = "teste" => "teste" irb(main):002:0> v.class => String irb(main):003:0> v = 1 => 1 irb(main):004:0> v.class => Fixnum irb(main):005:0> Vale lembrar que Ruby tamb´m tem tipagem forte, isso ´, vamos receber um erro se tentarmos fazer e e isso: [taq@~]irb irb(main):001:0> i = 1 => 1 irb(main):002:0> s = "oi" => "oi" irb(main):003:0> x = i+s TypeError: String can’t be coerced into Fixnum from (irb):3:in ‘+’ from (irb):3 irb(main):004:0> Ent˜o, n˜o inventem de misturar uma coisa com a outra. :-) a a Vamos dar uma olhadinha ali no output do irb. S´ para dar uma “coceirinha”, reparem que depois o que declarei a primeira vari´vel, pedi para ele verificar o valor do atributo class da vari´vel. Foi retor- a a nado String, l´gico, pois a vari´vel v vale “teste” nesse caso. o a Agora olhem na segunda atribui¸˜o de valor. Indiquei que o valor de v ´ 1, e verificando o class foi ca e 13
  • 14. retornado Fixnum, provando que o que o Matz disse na descri¸˜o do Ruby no come¸o desse tutorial ´ ca c e verdade: TUDO ´ objeto em Ruby. e Duvidam? Olhem que legal: [taq@~]irb irb(main):001:0> i = 1 => 1 irb(main):002:0> i.methods => ["%", "between?", "send", "<<", "prec", "&", "object_id", ">>", "size", "singleton_methods", "__send__", "round", "equal?", "taint", "method", "id2name", "*", "next", "frozen?", "instance_variable_get", "divmod", "+", "kind_of?", "integer?", "chr", "to_a", "instance_eval", "-", "prec_i", "/", "type", "protected_methods", "extend", "truncate", "to_sym", "|", "eql?", "modulo", "instance_variable_set", "~", "hash", "zero?", "is_a?", "to_s", "prec_f", "singleton_method_added", "class", "tainted?", "private_methods", "^", "step", "untaint", "+@", "upto", "-@", "remainder", "id", "**", "nonzero?", "to_i","<", "inspect", "<=>", "==", "floor", ">", "===", "succ", "clone", "public_methods", "quo", "display", "downto", ">=", "respond_to?", "<=", "freeze", "abs", "to_f", "__id__", "coerce", "=~", "methods", "ceil","nil?", "dup", "to_int", "div", "instance_variables", "[]", "instance_of?", "times"] Esses s˜o os m´todos p´ blicos da instˆncia da classe (seria equivalente ` uma chamada i.public methods). a e u a a Para vermos os m´todos privados da instˆncia da classe, podemos usar i.private methods. e a Lembrem-se que estamos falando de m´todos da instˆncia da classe, mais tarde vamos falar dos e a m´todos da classe, sendo eles p´blicos, privados e protegidos. Mas isso mais tarde. e u Agora vamos continuar a falar de vari´veis. a 3.1.1 Escopo das vari´veis a Para declarar uma vari´vel no escopo privado, ´ s´ fazer isso: a e o [taq@~]irb irb(main):001:0> i = 1 => 1 irb(main):002:0> puts i 1 => nil irb(main):003:0> Aqui tem um m´todo novo, o puts, que ´ um m´todo de kernel do Ruby. Isso implica que pode- e e e mos o utilizar sem precisar especificar o objeto ` que ele faz parte (Kernel). A declara¸˜o completa ´ a ca e Kernel.puts. O puts nada mais faz que imprimir o resultado da express˜o que vocˆ passou para ele, a e quebrando a linha no final. Para declarar uma v´riavel p´ blica, utilizamos a u [taq@~]irb irb(main):001:0> $i = 1 => 1 irb(main):002:0> e pronto. Declarando a vari´vel com um caracter $ na frente do nome j´ a torna p´blica. a a u Tem mais um tipo de vari´vel, que ´ a de instˆncia de classe, mas s´ vamos falar nela quando che- a e a o garmos no assunto de classes. :-) 14
  • 15. 3.2 Tipos b´sicos a 3.2.1 Blocos de c´digo o Antes de apresentar qualquer um dos tipos, quero mostrar uma coisa essencial em Ruby, que s˜o os a blocos de c´digo. o Blocos de c´digo s˜o umas das boas sacadas de Ruby, e podem ser peda¸os de c´digo delimitados por { o a c o e }: {puts ’Oi mundo!’} ou, para blocos maiores, delimitados por do e end: do puts ’Oi mundo!’ puts ’Aqui tem mais espa¸o’ c end A conven¸˜o ´ usar as chaves para blocos de uma linha e do . . . end para blocos maiores. ca e Vamos ver muita coisa sobre blocos de c´digo mais adiante. Blocos de c´digo, juntamente com ite- o o rators, s˜o muito utilizados em Ruby, s˜o uma das pe¸as-chaves da linguagem e v˜o aparecer em muitos a a c a exemplos dos tipos b´sicos abaixo. Se vocˆ n˜o entendeu muita coisa, n˜o tem problema, vamos ter uma a e a a explica¸˜o mas extensa sobre isso logo. ca 3.2.2 N´ meros u Podemos ter vari´veis dos tipos inteiro ou ponto flutuante. a Exemplos de inteiros: [taq@~]irb irb(main):001:0> i1 = 1 => 1 irb(main):002:0> i2 = 123 => 123 irb(main):003:0> i3 = -1000 => -1000 irb(main):004:0> i4 = 3_000_000_000 => 3000000000 irb(main):005:0> puts i1.class Fixnum => nil irb(main):006:0> puts i2.class Fixnum => nil irb(main):007:0> puts i3.class Fixnum => nil irb(main):008:0> puts i4.class Bignum => nil irb(main):009:0> N˜o podemos usar v´ a ırgulas em vari´veis, mas se acharmos que fica mais leg´ a ıvel, podemos usar subli- nhado para separar os milhares, como no exemplo dos 3 bilh˜es acima (algu´m tem isso na conta? :-). o e Outra coisa que eu fiz ali foi mostrar o tipo de cada vari´vel. Como o Matz disse tamb´m na des- a e cri¸˜o inicial, dependendo do n´mero que vocˆ utiliza, o Ruby j´ troca automaticamente o tipo. As trˆs ca u e a e primeiras vari´veis s˜o do tipo Fixnum, enquanto a ultima n˜o coube no Fixnum e foi automaticamente a a ´ a 15
  • 16. usado o Bignum. Exemplos de ponto flutuante: [taq@~]irb irb(main):001:0> f1 = 1.23 => 1.23 irb(main):002:0> f2 = -57.08 => -57.08 irb(main):003:0> f3 = 15.058e-4 => 0.0015058 irb(main):004:0> f1.class => Float irb(main):005:0> f2.class => Float irb(main):006:0> f3.class => Float irb(main):007:0> Tamb´m podemos criar n´meros usando as formas hexadecimal, octal e bin´ria: e u a [taq@~]irb irb(main):001:0> hex = 0xFF => 255 irb(main):002:0> oct = 0377 => 255 irb(main):003:0> bin = 0b11111111 => 255 irb(main):004:0> 3.2.3 Booleanos S˜o os valores true e false. Reparem que est˜o em min´ sculas. a a u Aproveitando o gancho dos booleanos, o valor nulo em Ruby ´ definido como nil, sendo que false e nil s˜o e a os unicos valores que s˜o reconhecidos como valores indicando falso, mas s˜o de classes e comportamentos ´ a a diferentes: [taq@~]irb irb(main):001:0> t = true => true irb(main):002:0> f = false => false irb(main):003:0> n = nil => nil irb(main):004:0> t.class => TrueClass irb(main):005:0> f.class => FalseClass irb(main):006:0> n.class => NilClass irb(main):007:0> A recomenda¸˜o ´ que m´todos predicados (que terminam com ? no final, mais sobre isso depois) retornem ca e e true ou false, enquanto outros m´todos que precisam indicar falha retornem nil. e 3.2.4 Strings Qualquer “palavra” ou conjunto de palavras podem ser armazenados como uma String: 16
  • 17. [taq@~]irb irb(main):001:0> s1 = "oi" => "oi" irb(main):002:0> s2 = "oi, amigo!" => "oi, amigo!" irb(main):003:0> s3 = "oi, ’mano’!" => "oi, ’mano’!" irb(main):004:0> s1.class => String irb(main):005:0> Vamos aproveitar que estamos falando de Strings e lembrar que, como foi dito acima, vari´veis s˜o a a referˆncias para objetos. Para ter uma prova disso, vamos ver um exemplo: e [taq@~]irb irb(main):001:0> my_nick = "TaQ" => "TaQ" irb(main):002:0> my_nick_copy = my_nick => "TaQ" irb(main):003:0> my_nick[0] = ’S’ => "S" irb(main):004:0> puts my_nick SaQ => nil irb(main):005:0> puts my_nick_copy SaQ => nil irb(main):006:0> O que aconteceu aqui? Eu s´ troquei o primeiro caracter da vari´vel my nick, n˜o da my nick copy o a a (falando nisso, vocˆ pode manipular Strings usando [] da mesma maneira que em outras linguagens)! e Bom, nesse caso, my nick copy aponta para o mesmo lugar onde se encontra o valor de my nick, por isso que quando vocˆ alterou uma, alterou a outra junto. e Se n˜o quisermos que um objeto seja alterado, podemos usar o m´todo freeze nele: a e [taq@~]irb irb(main):001:0> my_nick = "TaQ" => "TaQ" irb(main):002:0> my_nick_copy = my_nick => "TaQ" irb(main):003:0> my_nick.freeze => "TaQ" irb(main):004:0> my_nick[0] = ’S’ TypeError: can’t modify frozen string from (irb):4:in ‘[]=’ from (irb):4 irb(main):005:0> my_nick_copy[0] = ’S’ TypeError: can’t modify frozen string from (irb):5:in ‘[]=’ from (irb):5 irb(main):006:0> my_nick => "TaQ" irb(main):007:0> my_nick_copy => "TaQ" irb(main):008:0> Para ter resultados distintos entre as vari´veis, baseando o valor de uma na outra, ter´ a ıamos que fazer: 17
  • 18. [taq@~]irb irb(main):001:0> my_nick = "TaQ" => "TaQ" irb(main):002:0> my_nick_copy = my_nick.dup => "TaQ" irb(main):003:0> my_nick[0] = ’S’ => "S" irb(main):004:0> puts my_nick SaQ => nil irb(main):005:0> puts my_nick_copy TaQ => nil irb(main):006:0> O m´todo dup duplica o objeto, criando uma nova c´pia, que foi atribu´ ` vari´vel my nick copy. e o ıda a a Ent˜o, quando trocamos o primeiro caracter de my nick, estamos alterando somente ela e n˜o mais a a my nick copy junto. Podemos usar uma feature chamada de heredoc para criar “stringonas”: [taq@~]irb irb(main):001:0> s = <<FIM irb(main):002:0" Uma String realmente irb(main):003:0" grande com alguns irb(main):004:0" saltos de linhas, para irb(main):005:0" demonstrar o heredoc! irb(main):006:0" FIM => "Uma String realmentengrande com algunsnsaltos de linhas, parandemonstrar o heredoc!n" irb(main):007:0> puts s Uma String realmente grande com alguns saltos de linhas, para demonstrar o heredoc! => nil irb(main):008:0> Definimos uma vari´vel, que tem seu valor atribu´ logo ap´s encontrarmos uma string semelhante ` a ıdo o a que vem depois de <<. No caso usei FIM, mas fica a seu crit´rio qual string usar de terminador. Se e quiser escrever PINDAMONHANGABA, pode. :-) Para concatenar Strings, podemos usar + ou << (lembraram de C++?): [taq@~/trash]irb irb(main):001:0> s = "Oi, " => "Oi, " irb(main):002:0> s + "mundo!" => "Oi, mundo!" irb(main):003:0> s << "mundo!" => "Oi, mundo!" irb(main):004:0> Fica a dica que << ´ mais r´pido, pois n˜o gera um novo objeto como +: e a a [taq@~]irb irb(main):001:0> s = "teste" => "teste" irb(main):002:0> s.object_id => -605086198 18
  • 19. irb(main):003:0> s += " concatenado" => "teste concatenado" irb(main):004:0> s => "teste concatenado" irb(main):005:0> s.object_id => -605094768 irb(main):006:0> s2 = "teste" => "teste" irb(main):007:0> s2.object_id => -605105148 irb(main):008:0> s2 << " concatenado" => "teste concatenado" irb(main):009:0> s2 => "teste concatenado" irb(main):010:0> s2.object_id => -605105148 irb(main):011:0> No caso de s += “concatenado”, ´ interpretado como s = s + “concatenado”, por isso que gera e um novo objeto. 3.2.5 Constantes Constantes s˜o vari´veis que tem seu nome come¸ado com uma letra mai´ scula. a a c u “O que? S´ isso?” vocˆ poderia me perguntar. S´. o e o “Mas n˜o fica meio confuso com nomes de classes que come¸am em mai´sculas?” uhnnn at´ fica, mas a c u e ´ pr´tico. e a “Ent˜o, por exemplo, ao inv´s de eu ter em Java —: public static final double Pi = 3.1415926; eu a e o ´ s´ teria que escrever Pi?”. E isso a´ ı. “Tem certeza que isso ´ uma constante?”. Ok, vamos ver: e [taq@~]irb irb(main):001:0> Pi = 3.1415926 => 3.1415926 irb(main):002:0> Pi = 10 (irb):2: warning: already initialized constant Pi => 10 irb(main):003:0> Viu? Declarei a vari´vel, e quando fui alterar seu conte´do, fui informado que n˜o deveria, pois ´ uma a u a e constante. Fica um fato curioso que Ruby, diferente de outras linguagens, permite que vocˆ altere a constante, e (“mas n˜o era uma constante?”) mas gera um warning alertando sobre isso. a 3.2.6 Ranges Intervalos. Podemos declarar de duas maneiras: incluindo ou n˜o o ultimo valor a que nos referimos em a ´ sua declara¸ao. Por exemplo: c˜ [taq@~/code/java]irb irb(main):001:0> r = 0..10 => 0..10 irb(main):002:0> r2 = 0...10 => 0...10 irb(main):003:0> No primeiro caso, a range vai conter n´meros de 0 at´ 10, incluindo o 10. No segundo caso, vai de 0 at´ u e e 9. Como regrinha dos pontinhos, menos ´ mais, quando se tem menos pontos, se tem mais valores na range. e 19
  • 20. 3.2.7 Arrays Arrays podem conter v´rios tipos de objetos (ou n˜o): a a [taq@~]irb irb(main):001:0> a = [’apenas’,1,’teste’] => ["apenas", 1, "teste"] irb(main):002:0> Para Arrays com somente Strings, podemos usar o atalho %w, ficaria assim: [taq@~]irb irb(main):001:0> a = %w(homer marge bart lisa maggie o bebezinho) => ["homer", "marge", "bart", "lisa", "maggie o bebezinho"] irb(main):002:0> Se precisarmos de uma String com mais de uma palavra, usamos o caracter como mostrado acima. Inserir elementos no Array ´ facil, usando push: e [taq@~]irb irb(main):001:0> a = [] => [] irb(main):002:0> a.push "um" => ["um"] irb(main):003:0> a.push "dois" => ["um", "dois"] irb(main):004:0> a.push "tres" => ["um", "dois", "tres"] irb(main):005:0> a.push "quatro" => ["um", "dois", "tres", "quatro"] irb(main):006:0> ou usando o operador <<: [taq@~]irb irb(main):001:0> a = [] => [] irb(main):002:0> a << "um" => ["um"] irb(main):003:0> a << "dois" => ["um", "dois"] irb(main):004:0> a << "tres" => ["um", "dois", "tres"] irb(main):005:0> Podemos fazer com um Array algo semelhante `s list comprehensions do Python, que ´ processar a e os elementos do Array e criar um novo, baseado em uma condi¸˜o. Por exemplo, quero processar os ca elementos pares de um Array e criar um novo com o dobro dos valores pares: [taq@~]irb irb(main):001:0> a = [1,2,3,4,5] => [1, 2, 3, 4, 5] irb(main):002:0> a2 = a.find_all {|v| v%2==0}.map{|v| v*2} => [4, 8] irb(main):003:0> Podemos usar collect tamb´m no lugar de map, ´ uma quest˜o de gosto ali. :-) e e a Ordenando um array: 20
  • 21. [taq@~]irb irb(main):001:0> a = ["um","dois","tres"] => ["um", "dois", "tres"] irb(main):002:0> a.sort => ["dois", "tres", "um"] irb(main):003:0> Podemos usar o m´todo sort assim tamb´m: e e [taq@~]irb irb(main):001:0> a = ["um","dois","tres"] => ["um", "dois", "tres"] irb(main):002:0> a.sort {|e1,e2| e1[0]<=>e2[0]} => ["dois", "tres", "um"] irb(main):003:0> Usando o m´todo sort com um bloco, s˜o enviados dois parˆmetros para o bloco, que os compara usando e a a o operador <=>. Podemos tamb´m utilizar o m´todo sort by, que ´ mais r´pido e eficiente quando e e e a precisamos ordenar por alguma propriedade ou express˜o do valor sendo avaliado: a [taq@~]irb irb(main):001:0> a = ["um","dois","tres"] => ["um", "dois", "tres"] irb(main):002:0> a.sort_by {|e| e[0]} => ["dois", "tres", "um"] irb(main):003:0> Nesse caso, foi avaliado a ordem alfab´tica das palavras. Se eu quisesse ordenar o Array pelo tamanho e das palavras, poderia usar: [taq@~]irb irb(main):001:0> a = ["tres","dois","um"] => ["tres", "dois", "um"] irb(main):002:0> a.sort_by {|e| e.length} => ["um", "dois", "tres"] irb(main):003:0> Podemos usar o m´todo any? para verificar se tem algum elemento de um Array que se encaixe em uma e condi¸˜o determinada por um bloco: ca [taq@~]irb irb(main):001:0> a = [1,2,50,3] => [1, 2, 50, 3] irb(main):002:0> a.any? {|v| v>10} => true irb(main):003:0> a.any? {|v| v>100} => false irb(main):004:0> Se quisermos testar se todos os elementos do Array satisfazem uma condi¸˜o, podemos utilizar o m´todo ca e all?: [taq@~]irb irb(main):001:0> a = [1,2,3,4,5] => [1, 2, 3, 4, 5] irb(main):002:0> a.all? {|v| v>0} => true irb(main):003:0> a.all? {|v| v>10} => false irb(main):004:0> 21
  • 22. Tamb´m podemos particionar um Array, usando o m´todo partition: e e [taq@~]irb irb(main):001:0> a = [1,2,3,4,5,6,7,8,9,10] => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] irb(main):002:0> par,impar = a.partition {|e| e%2==0} => [[2, 4, 6, 8, 10], [1, 3, 5, 7, 9]] irb(main):003:0> par => [2, 4, 6, 8, 10] irb(main):004:0> impar => [1, 3, 5, 7, 9] irb(main):005:0> O que aconteceu ´ que foram retornados dois novos Arrays, o primeiro com elementos que atendiam a e condi¸˜o especificada no bloco, e o segundo com os elementos que n˜o atendiam a condi¸˜o. ca a ca 3.2.8 Hashes Um Hash ´ basicamente um Array com ´ e ındices para seus elementos (uma analogia com Java —seriam os objetos HashMap e Hashtable). Vejamos um exemplo: [taq@~/code/ruby]irb irb(main):001:0> h = {1=>"elemento 1","um"=>"elemento um"} => {"um"=>"elemento um", 1=>"elemento 1"} irb(main):002:0> h[1] => "elemento 1" irb(main):003:0> h["um"] => "elemento um" irb(main):004:0> Podemos utilizar tamb´m s´ e ımbolos para a chave do Hash: [taq@~/code/ruby]irb irb(main):001:0> h = {:um=>"elemento 1",:dois=>"elemento 2"} => {:um=>"elemento 1", :dois=>"elemento 2"} irb(main):002:0> h[:um] => "elemento 1" irb(main):003:0> h[:dois] => "elemento 2" irb(main):004:0> Uma pequena compara¸˜o ca Primeiro, xˆ, flamewar. Vou fazer uma compara¸˜o com Arrays e Hashes aqui de uma o ca maneira saud´vel. a Eu tive que fazer um pequeno teste com alguns Arrays em PHP, para um programa que fiz aqui, onde eu copiava o primeiro Array para mais dois, removia os elementos do primeiro usando pop, depois invertia e usava pop no segundo, e finalmente removia os elementos do terceiro usando shift. No meu teste, Arrays de 15000 elementos foram preenchidos e tiveram seus elementos remo- vidos com pop praticamente instantˆneamente, invertendo e removendo idem, mas usando a reverse/shift foram 31 segundos. Fiz o mesmo teste com Ruby. Foi instantˆneo! Resolvi aumentar o tamanho dos Array a para 10 vezes mais, 150000 elementos. Levou 4 segundos! 22
  • 23. Curioso com o teste, fui verificar a causa disso e descobri: ao contr´rio de Ruby (e ou- a tras linguagens tamb´m) todos os Arrays em PHP s˜o na verdade, Hashes!. Isso d´ e a a praticidade, mas d´ para ver o pre¸o que se paga e o que se ganha usando uma linguagem a c com distin¸˜o entre os dois. ca 3.2.9 S´ ımbolos Pense em s´ ımbolos como “String levinhas”. Eles representam nomes e algumas Strings dentro do inter- pretador do Ruby, e s˜o sempre o mesmo objeto durante a execu¸˜o de um programa. a ca S´ ımbolos s˜o criados usando : na frente do seu nome, como em: a :um :dois Como demonstrado acima. Vamos dar uma olhada no fato de serem sempre o mesmo objeto, pegando o exemplo da documenta¸˜o ca do Ruby: module One class Fred end $f1 = :Fred end module Two Fred = 1 $f2 = :Fred end def Fred() end $f3 = :Fred $f1.id #=> 2514190 $f2.id #=> 2514190 $f3.id #=> 2514190 Mesmo id! :-) 3.2.10 Express˜es regulares o Express˜es regulares s˜o facilmente criadas, delimitando-as com /: o a [taq@~]irb irb(main):001:0> er = /^[0-9]/ => /^[0-9]/ irb(main):002:0> E facilmente testadas, usando o operador de correspondˆncia =˜ ou de n˜o-correspondˆncia !˜: e a e [taq@~]irb irb(main):001:0> er = /^[0-9]/ => /^[0-9]/ irb(main):002:0> "123" =~ er => 0 irb(main):003:0> "123" !~ er => false irb(main):004:0> "abc" =~ er => nil irb(main):005:0> "abc" !~ er => true irb(main):006:0> 23
  • 24. Express˜es regulares tamb´m podem ser criadas usando o construtor da classe ou %r: o e [taq@~]irb irb(main):001:0> er = Regexp.new("^[0-9]") => /^[0-9]/ irb(main):002:0> er2 = %r{^[0-9]} => /^[0-9]/ irb(main):003:0> Vamos fazer um teste mais pr´tico, usando a express˜o regular acima, “se a linha come¸ar com um a a c n´mero”, usando um if para deixar mais claro (mas tem jeitos de fazer isso mais eficientemente): u [taq@~]irb irb(main):001:0> er = /^[0-9]/ => /^[0-9]/ irb(main):002:0> if "123" =~ er irb(main):003:1> puts "casou!" irb(main):004:1> else irb(main):005:1* puts "N~O casou!" A irb(main):006:1> end casou! => nil irb(main):007:0> if "abc" =~ er irb(main):008:1> puts "casou!" irb(main):009:1> else irb(main):010:1* puts "N~O casou!" A irb(main):011:1> end N~O casou! A => nil Isso poderia ser escrito como: [taq@~]irb irb(main):001:0> er = /^[0-9]/ => /^[0-9]/ irb(main):002:0> puts ("123" =~ er ? "":"n~o ")+"casou" a casou => nil irb(main):003:0> puts ("abc" =~ er ? "":"n~o ")+"casou" a n~o casou a Mas se vocˆ n˜o sabe o que ´ aquela constru¸˜o (condi¸˜o?verdadeiro:falso) talvez se eu mostrasse assim e a e ca ca de primeira pudesse confundir um pouco a coisa aqui. Podemos utilizar o m´todo match para pegarmos os tokens de uma string que “casa” com nossa ex- e press˜o regular: a [taq@~]irb irb(main):001:0> er = /(..)/(..)/(....)/ => /(..)/(..)/(....)/ irb(main):002:0> mt = er.match("20/06/2005") => #<MatchData:0xb7dd5dd0> irb(main):003:0> mt.length => 4 irb(main):004:0> mt[0] => "20/06/2005" irb(main):005:0> mt[1] => "20" irb(main):006:0> mt[2] 24
  • 25. => "06" irb(main):007:0> mt[3] => "2005" irb(main):008:0> mt = er.match("20062005") => nil irb(main):009:0> No exemplo, se a string “casar” com a express˜o, vai ser retornado um objeto do tipo MatchData , a ou nil se n˜o “casar”. No objeto retornado podemos verificar o seu tamanho, que inclui a string que a pesquisamos, seguida por seus tokens (iniciando em 1). Podemos procurar em uma String onde uma express˜o regular “casa” usando index : a [taq@~]irb irb(main):001:0> "eustaquio".index(/taq/) => 3 irb(main):002:0> Tamb´m podemos usar o m´todo gsub da String para trocar seu conte´do utilizando uma express˜o e e u a regular: [taq@~]irb irb(main):001:0> "eustaquio".gsub(/qu/,’c’) => "eustacio" irb(main):002:0> Troquei meu nome ali por “Eust´cio” (que ´ o nome de um tiozinho ranzinza que vive assustando um a e pobre cachorrinho em um desenho animado que tem por a´ :-) ı). Express˜es regulares tamb´m s˜o uma m˜o-na-roda quando usadas com iterators, como por exemplo: o e a a [taq@~]irb irb(main):001:0> a = %w(um dois tres quatro cinco seis sete oito nove dez) => ["um", "dois", "tres", "quatro", "cinco", "seis", "sete", "oito", "nove", "dez"] irb(main):002:0> a.grep(/s$/) => ["dois", "tres", "seis"] Nesse caso usei o m´todo grep no array, que por ter um m´todo each, torna dispon´ e e ıvel os m´todos e adicionais do m´dulo Enumerable, entre eles, grep. No exemplo eu pedi para filtrar os elementos que o eram terminados com “s”. Outro exemplo seria se tivermos um arquivo com os dados: [taq@~]cat teste.txt um dois tres quatro cinco seis sete oito nove dez [taq@~]irb irb(main):001:0> File.open("teste.txt").grep(/s$/) do |r| irb(main):002:1* puts r irb(main):003:1> end dois tres seis 25
  • 26. 3.2.11 Procs Procs s˜o blocos de c´digo associados ` uma vari´vel: a o a a [taq@~]irb irb(main):001:0> vezes3 = Proc.new {|n| n*3} => #<Proc:0xb7de21fc@(irb):1> irb(main):002:0> vezes3.call(1) => 3 irb(main):003:0> vezes3.call(2) => 6 irb(main):004:0> vezes3.call(3) => 9 irb(main):005:0> Podemos transformar um bloco de c´digo em uma Proc usando lambda: o [taq@~]irb irb(main):001:0> vezes3 = lambda {|n| n*3} => #<Proc:0xb7dd96c0@(irb):1> irb(main):002:0> vezes3.call(1) => 3 irb(main):003:0> vezes3.call(2) => 6 irb(main):004:0> vezes3.call(3) => 9 irb(main):005:0> 3.2.12 M´todos e M´todos tamb´m s˜o muito f´ceis de serem declarados. S˜o definidos usando def, terminando com end e e a a a (mais sobre isso na pr´xima se¸˜o): o ca [taq@~]irb irb(main):001:0> def diga_oi irb(main):002:1> puts "oi!" irb(main):003:1> end => nil irb(main):004:0> diga_oi oi! => nil irb(main):005:0> Retornando valores Olhem que legal: [taq@~]irb irb(main):001:0> def vezes(n1,n2) irb(main):002:1> n1*n2 irb(main):003:1> end => nil irb(main):004:0> vezes(3,4) => 12 irb(main):005:0> U´! Cadˆ o return ali? N˜o precisa. O valor do retorno do m´todo nesse caso ´ a ultima express˜o e e a e e ´ a avaliada, no caso, 3 vezes 4. Tamb´m podemos retornar mais de um resultado (na verdade, apenas um objeto, complexo ou n˜o, e a ´ retornado, mas d´-se a impress˜o que s˜o v´rios): e a a a a 26
  • 27. [taq@~]irb irb(main):001:0> def cinco_multiplos(n) irb(main):002:1> (1..5).map {|v| n*v} irb(main):003:1> end => nil irb(main):004:0> n1, n2, n3, n4, n5 = cinco_multiplos(5) => [5, 10, 15, 20, 25] irb(main):005:0> puts "m´ltiplos de 5: #{n1},#{n2},#{n3},#{n4},#{n5}" u m´ltiplos de 5: 5,10,15,20,25 u => nil irb(main):006:0> Recebendo parˆmetros a M´todos tamb´m recebem parˆmetros (que novidade ehehe) e retornam valores: e e a [taq@~]irb irb(main):001:0> def vezes(n1,n2) irb(main):002:1> return n1*n2 irb(main):003:1> end => nil irb(main):004:0> vezes(3,4) => 12 irb(main):005:0> M´todos tamb´m podem receber, como no PHP, argumentos com valores default, por exemplo: e e [taq@~]irb irb(main):001:0> def hello(s="Desconhecido") irb(main):002:1> puts "Oi, #{s}!" irb(main):003:1> end => nil irb(main):004:0> hello("TaQ") Oi, TaQ! => nil irb(main):005:0> hello Oi, Desconhecido! => nil irb(main):006:0> Ent˜o, se n˜o passarmos um argumento, ele assume o que foi especificado como default. a a Tamb´m podemos ter parˆmetros vari´veis, por exemplo: e a a [taq@~]irb irb(main):001:0> def vargars(*args) irb(main):002:1> args.each {|v| puts "parametro recebido:#{v}"} irb(main):003:1> end => nil irb(main):004:0> vargars(1,2) parametro recebido:1 parametro recebido:2 => [1, 2] irb(main):005:0> vargars(1,2,3,4,5) parametro recebido:1 parametro recebido:2 parametro recebido:3 parametro recebido:4 27
  • 28. parametro recebido:5 => [1, 2, 3, 4, 5] irb(main):006:0> Os parˆmetros vari´veis vem na forma de um Array, e para indicar no m´todo esse tipo de parˆmetro, a a e a ´ s´ colocar um asterisco (*) na frente do nome do parˆmetro. e o a Podemos passar um bloco para o m´todo, executando-o com yield: e [taq@~]irb irb(main):001:0> def teste(n) irb(main):002:1> yield(n) irb(main):003:1> end => nil irb(main):004:0> teste(2) {|i| i*i} => 4 irb(main):005:0> teste(3) {|i| i*i} => 9 irb(main):006:0> teste(4) {|i| i*i} => 16 irb(main):007:0> Para testar se o m´todo recebeu um bloco, podemos usar block given?: e [taq@~]irb dirb(main):001:0> def teste(n) irb(main):002:1> if block_given? irb(main):003:2> yield(n) irb(main):004:2> else irb(main):005:2* puts "n~o foi passado um bloco!" a irb(main):006:2> end irb(main):007:1> end => nil irb(main):008:0> teste(2) {|i| i*i} => 4 irb(main):009:0> teste(3) {|i| i*i} => 9 irb(main):010:0> teste(4) {|i| i*i} => 16 irb(main):011:0> teste(5) n~o foi passado um bloco! a => nil irb(main):012:0> E se passarmos o ultimo argumento de um m´todo com um & na frente, um bloco passado como parˆmetro ´ e a ser´ convertido em uma Proc e associado ao parˆmetro: a a [taq@~]irb irb(main):001:0> def teste(n,&b) irb(main):002:1> puts b.call(n) irb(main):003:1> end => nil irb(main):004:0> teste(2) {|i| i*i} 4 => nil irb(main):005:0> teste(3) {|i| i*i} 9 => nil irb(main):006:0> teste(4) {|i| i*i} 28
  • 29. 16 => nil irb(main):007:0> Para converter uma Proc em um bloco de c´digo em um parˆmetro do m´todo, vocˆ pode usar o caracter o a e e & antes do nome da Proc: [taq@~]irb irb(main):001:0> quadrado = Proc.new {|i| i*i} => #<Proc:0xb7de2080@(irb):1> irb(main):002:0> def teste(n) irb(main):003:1> puts yield(n) irb(main):004:1> end => nil irb(main):005:0> teste(3,&quadrado) 9 => nil irb(main):006:0> Como os parˆmetros s˜o enviados a a Os parˆmetros s˜o passados por c´pia da referˆncia do objeto, ent˜o, se alterarmos um objeto que a a o e a foi passado como parˆmetro, dentro de um m´todo, e ele puder ser mut´vel, ele refletir´ fora do a e a a m´todo. Por exemplo: e [taq@~]irb irb(main):001:0> s = "Oi, mundo!" => "Oi, mundo!" irb(main):002:0> s.object_id => -605086718 irb(main):003:0> def maiusculas(s) irb(main):004:1> s.upcase! irb(main):005:1> end => nil irb(main):006:0> maiusculas(s) => "OI, MUNDO!" irb(main):007:0> s => "OI, MUNDO!" irb(main):008:0> s.object_id => -605086718 irb(main):009:0> Foi criada uma String (s), e logo depois verifiquei seu id. Dentro do m´todo alterei o parˆmetro usando o e a m´todo upcase! verifiquei seu valor (que foi alterado para maiusc´las) e seu id, que continua o mesmo, e u ent˜o, o objeto foi alterado dentro do m´todo, usando como referˆncia o objeto que ele apontava, que a e e pode ser mut´vel. a ATENCAO!¸˜ M´todos que alteram o valor e estado de um objeto geralmente tem um outro m´todo de e e mesmo nome, por´m com um ! no final. Esses s˜o os chamados m´todos destrutivos. A e a e vers˜o sem ! pega uma c´pia da referˆncia, faz a mudan¸a, e retorna um novo objeto. Os a o e c m´todos destrutivos alteram o pr´prio objeto. e o Se n˜o us´ssemos o !, somente retornando o valor convertido, ter´ a a ıamos retornado outro objeto, criado dentro do m´todo, no seu retorno (pelo fato de s.upcase ser a ultima express˜o avaliada no m´todo). Se e ´ a e us´ssemos o !, o objeto retornado seria o mesmo que foi alterado. a No exemplo abaixo, o parˆmetro n˜o foi alterado, mas foi retornado um novo objeto na chamada do a a m´todo, atribu´ ` referˆncia anterior, s. Isso pode ser comprovado verificando seu id: e ıdo a e 29
  • 30. [taq@~]irb irb(main):001:0> s = "Oi, mundo!" => "Oi, mundo!" irb(main):002:0> s.object_id => -605086718 irb(main):003:0> def maiusculas(s) irb(main):004:1> s.upcase irb(main):005:1> end => nil irb(main):006:0> maiusculas(s) => "OI, MUNDO!" irb(main):007:0> s => "Oi, mundo!" irb(main):008:0> s.object_id => -605086718 irb(main):009:0> s = maiusculas(s) => "OI, MUNDO!" irb(main):010:0> s => "OI, MUNDO!" irb(main):011:0> s.object_id => -605122958 irb(main):012:0> Para alterar o valor de vari´veis do tipo Fixnum (Fixnum’s s˜o imut´veis), precisar´ a a a ıamos fazer do se- gundo modo, retornando um novo objeto para a sua vari´vel apontando para o seu Fixnum, pois eles a n˜o podem ser alterados. a Deixa eu tentar deixar mais vis´ aqui: ıvel def teste1(s) print "Rodando TESTE1n" print "valor #{s}, id #{s.object_id}n" # Aqui ele cria um novo objeto com o valor da referencia em maiusculas # e aponta a referencia de s (ATENC~O! ele troca a refer^ncia de s, ¸A e # definida localmente aqui, para a localiza¸~o do novo objeto, e n~o ca a # interfere com a vari´vel externa do m´todo que gerou s como a e # par^metro! a s = s.upcase print "valor #{s}, id #{s.object_id} (aqui tem que ter um id diferente)nn" # Aqui ele retorna s, com sua nova refer^ncia, apontando para o novo objeto e s end def teste2(s) print "Rodando TESTE2n" print "valor #{s}, id #{s.object_id}n" # M´todo destrutivo ` frente! Vai agir direto no objeto e a # que se encontra na refer^ncia apontada por s e s.upcase! print "valor #{s}, id #{s.object_id}nn" s end s1 = "teste" # s1 aponta para um objeto do tipo String, com conte´do "teste" u s2 = s1 # s2 aponta para s1 sd = s1.dup # duplica para outro 30
  • 31. print "Vamos verificar os objetos:n" print "s1 id:#{s1.object_id}, vale #{s1}n" print "s2 id:#{s2.object_id}, vale #{s2}n" print "sd id:#{sd.object_id}, vale #{sd} (objeto duplicado, id diferente!)nn" s3 = teste1(s1) print "Vamos verificar os objetos:n" print "s1 id:#{s1.object_id}, vale #{s1}n" print "s2 id:#{s2.object_id}, vale #{s2}n" print "s3 id:#{s3.object_id}, vale #{s3} (aqui tem que ter um id diferente)n" print "sd id:#{sd.object_id}, vale #{sd} (objeto duplicado, id diferente!)nn" s4 = teste2(s1) print "Vamos verificar os objetos:n" print "s1 id:#{s1.object_id}, vale #{s1}n" print "s2 id:#{s2.object_id}, vale #{s2}n" print "s3 id:#{s3.object_id}, vale #{s3}n" print "s4 id:#{s4.object_id}, vale #{s4}n" print "sd id:#{sd.object_id}, vale #{sd} (objecto duplicado, id diferente, valor original!)n" Resultado: Vamos verificar os objetos: s1 id:-604854218, vale teste s2 id:-604854218, vale teste sd id:-604854228, vale teste (objeto duplicado, id diferente!) Rodando TESTE1 valor teste, id -604854218 valor TESTE, id -604854348 (aqui tem que ter um id diferente) Vamos verificar os objetos: s1 id:-604854218, vale teste s2 id:-604854218, vale teste s3 id:-604854348, vale TESTE (aqui tem que ter um id diferente) sd id:-604854228, vale teste (objeto duplicado, id diferente!) Rodando TESTE2 valor teste, id -604854218 valor TESTE, id -604854218 Vamos verificar os objetos: s1 id:-604854218, vale TESTE s2 id:-604854218, vale TESTE s3 id:-604854548, vale TESTE s4 id:-604854218, vale TESTE sd id:-604854228, vale teste (objecto duplicado, id diferente, valor original!) Tentando expressar isso graficamente: 31
  • 32. Figura 3.1: Representa¸˜o de referˆncias aos objetos ca e Vamos analisar detalhadamente o que ocorre aqui. ˆ Criei uma vari´vel, s1, que aponta para um objeto tipo String (vari´veis n˜o s˜o objetos, lembre- a a a a se!). Esse objeto foi criado e armazenado em uma determinada ´rea da mem´ria (vejam para onde a o s1 aponta). ˆ Criei uma segunda vari´vel, s2, apontando para o mesmo lugar (mesmo objeto) que s1. a ˆ Criei outra vari´vel, sd, duplicando s1, isso ´, criando um novo objeto do tipo de s1 (String), usando a e como ponto de partida o valor referenciado por s1. ˆ Verifiquei os ids das vari´veis. As vari´veis s1 e s2 tem ids idˆnticos, enquanto sd tem um diferente, a a e tudo certo, pois sd aponta para outro objeto. ˆ Criei uma nova vari´vel s3 com o resultado do m´todo teste1, que recebe uma c´pia da re- a e o ferˆncia do objeto, como uma vari´vel local no escopo do m´todo corrente, executa uma opera¸˜o e a e ca criando um novo objeto, cuja referˆncia ´ retornada pelo m´todo e armazenada em s3. Vejam no e e e gr´fico o objeto para onde s3 aponta. a ˆ Dentro de teste1 isso fica expl´ ıcito na primeira chamada, onde o id do objeto ´ o mesmo de s1, e e quando retornado (poderia ter retornado direto, sem a vari´vel s, que ia dar na mesma, fiz assim a s´ para ficar mais claro) temos o id do novo objeto. o ˆ Criei uma nova vari´vel s4 com o resultado do m´todo teste2, que recebe uma c´pia da referˆncia a e o e do objeto, como uma vari´vel local no escopo do m´todo corrente, e altera diretamente o a e objeto referenciado pela vari´vel, convertendo-o para mai´ sculas, nesse caso. Reparem a u em teste2 como os valores est˜o diferentes, mas os ids s˜o os mesmos. a a ˆ A vari´vel s4, ent˜o, aponta para o mesmo objeto originalmente referenciado por s1 e s2, enquanto a a s3 continua sossegada apontando para o objeto criado por teste1, e sd, que foi duplicada no come¸o, c continua a mesma tamb´m. e 32
  • 33. Podemos pensar em vari´veis como umas caixinhas com v´rios bilhetinhos dentro, com as coordenadas a a de uma cidade. Quando vocˆ passa a vari´vel como parˆmetro, vamos imaginar que vocˆ est´ despejando e a a e a na caixa vazia do seu amigo um dos bilhetinhos de uma de suas caixas. O bilhetinho fica no espa¸o f´ c ısico (escopo) da caixa do seu amigo, e pode ser utilizado para dois motivos: ˆ Apontar para outra cidade (ou at´ para uma panela, se vocˆ quiser, levando em conta que isso e e alterar´ o tipo original da referˆncia que vocˆ pegar de volta da caixinha do seu amigo, e vocˆ a e e e pode ficar surpreso de n˜o encontrar uma cidade l´). O n´mero est´ escrito ` l´pis, pegue uma a a u a a a borracha, apague e escreva um novo n´mero l´, desde que o lugar novo exista, mesmo que u a tenha que ser criado ali na hora. ˆ Atrav´s de um telefone no verso do bilhetinho, ligar l´ na cidade e dizer “ei, pintem as ruas a´ de e a ı verde-lim˜o”, se isso for poss´ naquela cidade (se ela tiver um m´todo para isso). Nesse caso, o a ıvel e tipo apontado pelo bilhetinho ´ mantido, ou seja, continua a ser uma cidade no mesmo lugar, mas e alguma caracter´ıstica foi alterada no local (as ruas est˜o pintadas de verde-lim˜o arrrrgh!). a a Para exemplificar e complicar um pouco mais, vamos ver esses exemplos: [taq@~/code/ruby]irb irb(main):001:0> i1 = 1 => 1 irb(main):002:0> i2 = 1 => 1 irb(main):003:0> i3 = 1 => 1 irb(main):004:0> i4 = 2 => 2 irb(main):005:0> i5 = 2 => 2 irb(main):006:0> i1.object_id => 3 irb(main):007:0> i2.object_id => 3 irb(main):008:0> i3.object_id => 3 irb(main):009:0> i4.object_id => 5 irb(main):010:0> i5.object_id => 5 irb(main):011:0> Olhem que legal! As vari´veis dos Fixnum’s apontam sempre para o mesmo objeto (verificando isso a usando o object id) do tipo Fixnum que foi atribu´ ` elas. Isso por que Fixnum s˜o “immediate va- ıdo a a lues”, que armazenam o valor, e n˜o a referˆncia do objeto, assim como true, false, nil e s´ a e ımbolos. N˜o se esque¸am que objetos do tipo Fixnum s˜o imut´veis, e s˜o immediate values (est˜o l´ e ningu´m a c a a a a a e muda!). Fazendo uma compara¸˜o com nosso exemplo de Strings acima, se vocˆ criasse outra vari´vel valendo ca e a “teste”, al´m das que estavam l´, seria outra String com valor “teste”, ao contr´rio dos Fixnum’s que e a a s˜o sempre o mesmo objeto: a [taq@~/latex/ruby]irb irb(main):001:0> s1 = "teste" => "teste" irb(main):002:0> s2 = s1 => "teste" irb(main):003:0> sd = s1.dup 33