Commit 7cd82c63 authored by Everaldo Gomes's avatar Everaldo Gomes

commit inicial - 100 exemplos

parents
# 31/05/2016 - Everaldo Gomes - everaldo.gomes@gmail.com
#
# 001 - Alô Mundo
#
# O caractere # representa um comentário
"Alô mundo"
# A partir do Ruby 2.0 (estamos no 2.3) todas as Strings são
# UTF-8 por default, portanto pode utilizar acento sem problemas
# E caracteres especiais, caso deseje
# Para imprimir, utilize puts. O comando acima não imprime nada.
puts "Alô mundo"
# Após imprimir, o método puts imprime um separador de linha (\n)
# e retorna nil (valor nulo)
# 31/05/2016 - Everaldo Gomes - everaldo.gomes@gmail.com
#
# 001 - Top Object Main
#
# Na linguagem Ruby, um conceito muito importante é o de self.
# Semelhante ao self do Python e ao this do Java e Javascript,
# o self do Ruby indica o "receiver". Receiver é o objeto que
# recebe uma chamada de método.
#
# Dessa forma, quando executamos puts, no exemplo 001, esse
# método está sendo executado no receiver (self).
#
# Num script, self aponta inicialmente para um objeto especial
# chamado (main). Não confunda com o método main de linguagens
# como C e Java. Ruby não possui um método main e se você invocar
# uma variável main, sem tê-la declarado irá lançar um erro, de
# variável não declarada.
#
# O objeto main (top-Level Object) é uma instância da classe Object.
#
# A classe Object inclui o módulo Kernel, que inclui o módulo IO,
# que por sua vez define o método puts
#
# http://ruby-doc.org/core-2.3.1/Object.html
# http://ruby-doc.org/core-2.3.1/Kernel.html
# http://ruby-doc.org/core-2.3.1/IO.html#method-i-puts
#
# A classe Object não é a raiz da hierarquia de objetos. A partir do
# Ruby 1.9, Object herda da classe BasicObject
#
# http://ruby-doc.org/core-2.3.1/BasicObject.html
#
puts "Fora de classes e módulos self é #{self}"
puts "A classe do Top Level Object é #{self.class}"
# Dentro de um método definido fora de Módulos ou classes,
# self continua sendo main
def um_metodo
puts "Dentro de um método definido em Top-Level Object self é #{self}"
end
um_metodo
module UmModulo
def self.um_metodo
puts "Dentro de um método de um módulo self é #{self}"
end
end
UmModulo.um_metodo
#
# Dentro de um módulo, self será o nome do Módulo
# Se o Módulo for incluído dentro de uma classe,
# self será a classe que o incluiu
#
#
#
#
class UmaClasse
def self.um_metodo
puts "Dentro de um método definido numa classe self é #{self}"
end
end
UmaClasse.um_metodo
#
# Dentro de uma classe, self será o nome da Classe
#
#
#
# Method Dispatch
#
# Quando um método é invocado, se ele não for encontrado em self,
# Ruby automaticamente procura na hierarquia de classes
#
# Para descobrir essa hierarquia, use o método ancestors da
# classe do objeto
#
#
puts "Os ancestrais de Top-Level Object são #{self.class.ancestors}"
puts "Os anscestrais de um módulo são #{UmModulo.class.ancestors}"
puts "Os ancestrais de uma classe são #{UmaClasse.class.ancestors}"
#
# Dessa forma, entendemos como o método puts é invocado de acordo
# com self e a hierarquia de Objetos. Mesmo ele não estando presente
# num módulo ou classe, ele está presente em seus ancestrais
#
# 31/05/2016 - Everaldo Gomes - everaldo.gomes@gmail.com
#
# 003 - Expressões aritméticas são chamadas de métodos
#
# Na linguagem Ruby, números são objetos da classe Fixnum.
# A partir da versão 2.4, todos os números serão da classe Integer
# Atualmente, números muito grandes pertencem à classe Bignum.
#
# De qualquer forma, todos os números são objetos.
# E uma expressão aritmética é, na verdade, uma chamada de método
#
#
#
#
2 + 5 # => 7
2.send(:+, 5) # => 7
2.class # => Fixnum
# Você pode usar o caractere _ para tornar números grandes mais legíveis
1_000_000_000_000_000_000_000_000.class # => Bignum
2.public_methods # => [:%, :&, :*, :+, :-, :/, :<, :>, :^, :|, :~, :-@, :**, :<=>, :<<, :>>, :<=, :>=, :==, :===, :[], :inspect, :size, :succ, :to_s, :to_f, :div, :divmod, :fdiv, :modulo, :abs, :magnitude, :zero?, :odd?, :even?, :bit_length, :to_int, :to_i, :next, :upto, :chr, :ord, :integer?, :floor, :ceil, :round, :truncate, :downto, :times, :pred, :to_r, :numerator, :denominator, :rationalize, :gcd, :lcm, :gcdlcm, :+@, :eql?, :singleton_method_added, :coerce, :i, :remainder, :real?, :nonzero?, :step, :positive?, :negative?, :quo, :arg, :rectangular, :rect, :polar, :real, :imaginary, :imag, :abs2, :angle, :phase, :conjugate, :conj, :to_c, :pretty_print, :pretty_print_cycle, :between?, :pretty_print_instance_variables, :pretty_print_inspect, :instance_of?, :public_send, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :private_methods, :kind_of?, :instance_variables, :tap, :public_method, :singleton_method, :is_a?, :extend, :define_singleton_method, :method, :to_enum, :enum_for, :pretty_inspect, :=~, :!~, :respond_to?, :freeze, :display, :object_id, :send, :nil?, :hash, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :trust, :untrusted?, :methods, :protected_methods, :frozen?, :public_methods, :singleton_methods, :!, :!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]
# 31/05/2016 - Everaldo Gomes - everaldo.gomes@gmail.com
#
# 004 - Toda Expressão Retorna um Valor
#
#
# Em Ruby, todas as expressões retornam um valor.
# Além das expressões aritméticas, também são expressões:
#
#
# Atribuição
# Chamada de método
# Definição de classes e Módulos
# Comandos de Controle e blocos (if, for, while etc.)
#
# O método puts retorna nil, que quando impresso não retorna nada
# O objeto nil é uma instância da classe NilClass
retorno = puts("Uma mensagem qualquer")
puts "O valor de retorno é '#{retorno}'"
puts retorno.inspect
# Atribuição múltipla
a = b = c = d = e = f = 0 # => 0
puts "a=#{a}"
puts "b=#{b}"
puts "c=#{c}"
puts "d=#{d}"
puts "e=#{e}"
puts "f=#{f}"
a = if true
10
else
20
end
puts "a agora vale 10, porque o comando if também retorna valores.
O valor retornado é do último comando executado no bloco"
# Não é necessário usar ponto-e-vírgula em Ruby. A não ser que você queira
# definir uma classe ou método vazios numa mesma linha
uma_classe = class A ; end
puts uma_classe.inspect # => nil
# uma_classe é nulo, porque a classe não retornou nenhum valor em sua definição
# 31/05/2016 - Everaldo Gomes - everaldo.gomes@gmail.com
#
# 005 - Interpolação de Strings
#
#
# Nos exemplos anteriores, utilizamos interpolação de strings,
# sem explicá-la.
#
# A interpolação de strings (não funciona com strings de aspas simples)
# permite que objetos sejam automaticamente convertidos para strings
# sem a necessidade de invocar explicitamente operadores, como a concetanação
# e a conversão para strings
#
#
a = 0
puts '#{a}' # imprime #{a}, aspas simples
puts "#{a}" # imprime 0
puts "#{1 + 1}" # imprime 2. Use expressões dentro de #{}
# 31/05/2016 - Everaldo Gomes - everaldo.gomes@gmail.com
#
# 006 - Métodos de predicados terminam em ponto de interrogação
#
#
# Na linguagem Ruby, existe uma convenção de que métodos de predicados:
# métodos que retornam um valor booleano, verdadeiro ou falso, terminam
# com o caractere ponto de interrogação (ao contrário de outras linguagens,
# onde é um caractere inválido).
#
#
puts nil.nil?
puts false.nil?
puts "".nil?
puts 0.nil?
puts 0.even?
puts 1.odd?
puts -1.negative?
puts 42.positive?
puts "".empty?
puts "Mariana".include?("ana")
#
# Observe que nem false, nem string vazia e nem 0 são valores nulos
#
# Em Ruby, apenas dois valores são falsos: nil e false
# O restante é verdadeiro
# Mas se você comparar nil == false, retorna falso
#
# 31/05/2016 - Everaldo Gomes - everaldo.gomes@gmail.com
#
# 007 - Todo objeto possui uma identidade, que é seu endereço
#
#
# Objetos são armazenados em memória. Cada objeto em Ruby
# possui seu endereço, que pode ser acessado pelo método object_id.
#
#
# Fixnum, valores iguais compartilham o mesmo endereço (decisão de implementação).
# Bignum, valores iguais podem ter endereços distintos.
# O mesmo para Strings e todos os outros objetos.
# Existe apenas um objeto do tipo NilClass, TrueClass e FalseClass
#
puts 5.object_id
puts 5.object_id
cwb = "Curitiba"
curitiba = "Curitiba"
puts "Endereço de cwb=#{cwb.object_id}"
puts "Endereço de curitiba=#{curitiba.object_id}" # => nil
# Valores de cwb e curitiba são iguais, endereços são distintos
#
puts ObjectSpace.count_objects
# ObjectSpace#count_objects armazena o número total
# de objetos
#
#
cwb = :curitiba
curitiba = :curitiba
puts "Símbolos compartilham identidade" # => nil
puts "Endereço de cwb=#{cwb.object_id}"
puts "Endereço de curitiba=#{curitiba.object_id}" # => nil
# Símbolos são constantes strings, começam pelo caractere dois-pontos
#
#
#
# 02/06/2016 - Everaldo Gomes - everaldo.gomes@gmail.com
#
# 008 - Cuidado ao comparar valor e identidade
#
#
# Ao comparar dois objetos, cuidado com o tipo de comparação:
# de valor ou identidade (endereço / object_id)
#
#
# O método equal? compara identidade
# O método eql? ou == compara valor
#
#
## Fixnum
# =>
puts 5 == 5
puts 5.eql? 5
puts 5.equal? 5
## Bignum
puts 1_000_000_000_000_000_000_000_000 == 1_000_000_000_000_000_000_000_000
puts 1_000_000_000_000_000_000_000_000.eql? 1_000_000_000_000_000_000_000_000
puts 1_000_000_000_000_000_000_000_000.equal? 1_000_000_000_000_000_000_000_000 # retorna false
## Strings
cwb = "Curitiba"
curitiba = "Curitiba"
puts cwb == curitiba
puts cwb.eql? curitiba
puts cwb.equal? curitiba
## Símbolos
cwb = :curitiba # => :curitiba
curitiba = :curitiba
puts cwb == curitiba
puts cwb.eql? curitiba
puts cwb.equal? curitiba # retorna true, porque símbolos são constantes
# 02/06/2016 - Everaldo Gomes - everaldo.gomes@gmail.com
#
# 009 - Parênteses são opcionais quando não há ambiguidade
#
#
# Nos exemplos anteriores, fizemos uso de várias definições
# e chamadas de métodos sem o uso de parênteses.
#
# Isso porque, em Ruby, parênteses são necessários somente
# para evitar ambiguidades
#
puts("Alô Mundo")
puts "Alô mundo"
# É de bom tom utilizar parênteses na definição de métodos
def metodo1(a, b)
"(Metodo1: a=#{a} b=#{b})"
end
def metodo2(c, d) # ~> ArgumentError: wrong number of arguments (given 3, expected 2)
"(Metodo2: c=#{c} d=#{d})"
end
# As duas chamadas são equivalentes
puts metodo1 metodo2("val1", "val2"), "val3"
puts metodo1(metodo2("val1", "val2"), "val3")
##
## Esta linha abaixo causa o erro ArgumentError
## 3 argumentos dados, 2 esperados
##
## É necessário usar parênteses porque a chamada é ambígua
## Ruby não consegue distinguir que val3 pertence a método 1
##
#puts metodo1 metodo2 "val1", "val2", "val3" # =>
# Em casos de ambiguidades, somente os métodos "mais internos" precisam
# de parênteses.
# 02/06/2016 - Everaldo Gomes - everaldo.gomes@gmail.com
#
# 010 - O último comando é o valor de retorno
#
# Além dos parênteses opcionais e das expressões
# aritméticas que, em verdade, são chamadas de métodos,
# Ruby provê mais "açúcar sintático" (syntax sugar).
#
# O último comando de um bloco ou método é o valor
# de retorno. Esta funcionalidade é coerente com o
# princípio de que "toda expressão retorna um valor".
# Logo, blocos também são expressões.
#
#
# Caso deseje, pode explicitar um retorno com a palavra chave
# return
#
# Se a expressão for vazia, o valor retornado será nil
#
#
def alo_mundo
"Alô mundo"
end
puts alo_mundo # => nil
def metodo_vazio
end
puts "Método vazio=#{metodo_vazio}" # => nil
x = if true
1
else
2
end
# Imprime 1 # =>
puts x
## Imprime números de 0 a 9
## Depois x, vale 10, pois é o retorno do bloco
x = 10.times { |i| puts i }
puts "x vale 10, x=#{x}" # => nil
# 02/06/2016 - Everaldo Gomes - everaldo.gomes@gmail.com
#
# 011 - Atribuição com Operação
#
# Ruby também facilita a escrita de atribuições com
# operações de aritmética e lógica
#
#
x = 10
x += 1
# Imprime 11
puts x
a = true
a &&= false
# Imprime false
puts a
#
# Ruby não tem os operadores ++, como na linguagem c
#
# 02/06/2016 - Everaldo Gomes - everaldo.gomes@gmail.com
#
# 012 - Atribuição múltipla
#
# Ruby permite que inúmeras variáveis sejam atribuídas
# com um único operador de atribuição (=)
#
# Use o operador igual para separar os valores
#
x, y = 2, 3
# Imprime 2 e 3
puts x, y
# Você pode até mesmo trocar os valores, com um único comando
# e sem usar variáveis auxiliares
# Em C:
#
# aux = x;
# x = y;
# y = aux;
#
x, y = y, x
# Imprime 3 e 2, agora
puts x, y
a, b = 10
puts a, b
# Agora b é nulo
puts "#{b.nil?}"
c, d = 5, 6, 7
# Não gera nenhum erro. O valor 7 é descartado
puts c, d
# 02/06/2016 - Everaldo Gomes - everaldo.gomes@gmail.com
#
# 013 - Cuidado com Alias de Objetos
#
#
# Em linguagens orientadas a objetos, tais como Ruby, Python
# e Java, deve-se tomar cuidado com alias ou aliasing de
# objetos.
#
# Quando você faz uma cópia por atribuição ou argumento de
# método, deve-se estar ciente se o valor é realmente copiado
# para um novo objeto ou se a nova variável é apenas um alias
# de um objeto já existente.
#
#
# Lembre-se, uma variável é apenas uma referência que aponta
# para o endereço do objeto.
#
#
def um_metodo(y)
y = 20
end
x = 10
um_metodo(x)
# Imprime 10, porque y recebeu o valor que x referenciava,
# não o endereço real de x
puts x
def outro_metodo(s)
s.upcase!
end
abacaxi = "abacaxi"
outro_metodo(abacaxi)
# Imprime ABACAXI, pois o método upcase! modifica o receiver
# No caso, o receiver s, aponta para o mesmo valor que
# abacaxi aponta
#
#
puts abacaxi
laranja = "laranja"
outro_metodo(laranja.clone)
# Imprime laranja, pois invocamos o método clone, que criou
# um outro objeto para ser passado como argumento
puts laranja # => nil
# 02/06/2016 - Everaldo Gomes - everaldo.gomes@gmail.com
#
# 014 - inspect e o método p
#
#
# Vimos que o comando (método) puts imprime um objeto para a saída padrão.
# Ele retorna nil e aceita múltiplos parâmetros, separados por vírgula
#
#
# O método puts força o objeto a se converter para string, invocando
# o método to_s dos seus parâmetros.
#
#
# Já o método p invoca o método inspect dos objetos.
#
# inspect é a representação interna do objeto. Geralmente, nome da classe
# e endereço de memória para objetos que não sejam dos tipos básicos:
# Fixnum, String, Symbol, nil, false, true
#
#
# Quando um objeto não define o método to_s, por padrão ele invoca
# inspect. Mas não espere sempre os mesmos resultados.
# Lembre-se: inspect, representação interna; to_s coerção para String
#
#
#
puts 42 #equivalente a puts(42.to_s) ou puts(42.to_s)
puts 42.to_s
puts(42.to_s())
puts 42.to_s # como não recebe argumentos, não tem ambiguidade
o = Object.new # cria um novo objeto
# Imprime o endereço de memória e o nome da classe
# porque o objeto não define o método to_s
puts o
# Imprime o endereço de memória e o nome da classe # =>
p o
## Agora, vamos definir o método to_s somente para este objeto o
o.define_singleton_method :to_s do
"Representação String de o"
end
# Imprime Representação String de o
puts o
# Imprime o endereço de memória e o nome da classe
p o
# Vamos hackear o método inspect para provar