domingo, 27 de outubro de 2013

Exercitando com Ruby Parte 8 (Blocos (Lambda, Proc, Yield))

Depois de muito tempo resolvi voltar aqui, e mostrar algumas técnicas que são usadas em blocos, que realmente facilitam a vida do programador, vejamos algumas:

Yield
É usado para fazer uma passagem de bloco para um método (isso mesmo que você leu), usando "yield" dentro do método. Então lembrando quando usado o Yield, a chamada do método deve ser acompanhada de um bloco com as instruções.
  1. Um exemplo básico:
    def metodo
     yield
    end
    metodo {puts "diga olá"}
    => diga olá
  2. Várias chamadas:
    def metodo
       puts "você por aqui?"
       yield 
       puts "de novo aqui?"
       yield
    end
    metodo {puts "sim"}
    => você por aqui?
    => sim
    => de novo aqui?
    => sim
    
  3. Bloco com passagem de parâmetro:
    def metodo(val)
     yield(val)
    end
    metodo(4) {|val| puts "#{val}"}
    => 4
  4. Yield com condicional (Note que a segunda chamada não é efetuado pelo fato de não existir um bloco de código na chamada do método, pelo fato de usar um valor condicional "if block_given?"):
    def metodo(valor)
     yield(valor) if block_given?
    end
    metodo(10) {|val| puts val*val}
    metodo(20)
    => 100
    => 
Lambda
Bloco de código associado à uma variável. O método Lambda está presente no módulo Kernel do Ruby, portanto não precisa instanciar quando chama-lo.
  1. Chamada com um argumento (Para fazer a chamada use a função "call"):
    lambda = -> (v1) { 10 * v1}
    p lambda.call(10)
    =>100
  2. Chamada com um ou dois argumentos:
    lambda = ->(a,b=6){ a * b } 
    p lambda.call(2)
    p lambda.call('$')
    p lambda.call(10,10)
    =>12
    =>$$$$$$
    =>100
Proc
Também é um bloco de código associado à uma variável, similar ao Lambda, onde sua chamada é feita com instância.
  1. Exemplo prático:
    variavel = Proc.new {|valor| valor*3}
    p variavel.call(2)
    =>6

Darlan Dieterich

domingo, 5 de maio de 2013

Exercitando com Ruby Parte 7 (Expressões Regulares, Técnicas com Variáveis)

Expressões Regulares
Conhecida também como "regex", é uma técnica para "casar" caracteres, palavras, ou um grupo de palavras, podendo buscar ou substitui-los. Como outras linguagens, Ruby também suporta essa técnica. É aconselhado ter conhecimento sobre expressões regulares, pois o resto o Ruby complementa. 
  1. Primeiro passo. Uma expressão é inicializada com barra "/" e finalizada com outra barra. Usando o operador til "~" juntamente com igual "=" o seu retorno padrão diz que a expressão casou, e também retorna a posição da expressão:
    /existe/ =~ /existe algo?/
    => 0
  2. Usando o operador til "~" juntamente com interrogação "!" o seu retorno padrão diz que a expressão não casou (ou seja se existir algo diferente retorna true caso contrário false).
    /que tal/ != /existe algo?/
    => true
  3. Usando match (corresponde):
    exp = /existe/
    puts exp.match("existe algo?")
    => existe
  4. Usando um dos símbolos de gama de caracteres [a-z] (onde irá selecionar todos os caracteres de 'a' á 'z'),. Veja que a mesma expressão usada serviu para casar as duas frases:
    exp = /[a-z]aca/
    frase1 = "era uma vez uma vaca"
    frase2 = "deitei na maca"
    puts exp.match(frase1)
    =>vaca
    puts exp.match(frase2)
    =>maca
  5. Extraindo um valor de uma Tag (note que a expressão coleta todos os elementos entre as tag "> <"):
    tag = '<a href="https://google.com">Preciso de ti</a>'
    p />(.*)</.match(tag)
    =>Preciso de ti
  6. Obtendo data e hora. (A função match retorna um grupo, para acessar use o endereço desse vetor usando "[ ]"):
    datahora = "aqui tem data 06-05-2013 e hora 20:51:38 "
    exp = /(..-..-....).*(..:..:..)/
    val = exp.match(datahora)
    p val[1],val[2]
    => "06-05-2013"
    => "20:51:38"
  7. Trocando posição palavras. (Usei a global de substituição gsub para trocar a ordem das palavras):
    trocar =  "primeiro segundo terceiro".gsub(/(\w+)( )(\w+)/,'\3 \1')
    puts trocar
    => segundo primeiro terceiro
  8. Link muito bom, para editor de expressões regulares com Ruby:
    http://rubular.com/
Técnicas com Variáveis
Preparei algumas dicas para quem tem dúvidas em relação ao tratamento de variáveis em alguns casos distintos.

  1. Definindo tamanho da casa decimal de um numero flutuante. (Defini o numero de casas após a virgula, que seria 2):
    num = 1.23244040234
    p num.round(2)
    =>1.23
  2. Retornando pedaço de uma string. (Busco o carácter da 2 á 5 posição):
    palavra = 'pedaco'
    p palavra.slice(3..5)
    =>aco
  3. Substituindo palavras:
    palavra = "moto"
    p palavra.gsub("o","a")
    =>mata
  4. Caixa alta:
    palavra = "baixo"
    p palavra.upcase
    =>BAIXO
  5. Primeira letra maiúscula:
    palavra = "mundo"
    p palavra.capitalize
    =>Mundo
  6. Invertendo:
    palavra = "roma"
    p palavra.reverse
    =>amor
  7. Procurando algo (a cada resultado armazena em um vetor, no exemplo seguinte verifiquei a quantidade desse vetor):
    palavra = "segundo mundo"
    p palavra.scan('undo')
    =>["undo","undo"]
    p palavra.scan('undo').count
    =>2

terça-feira, 2 de abril de 2013

Exercitando com Ruby Parte 6 (Classes, Modulos)

Classes
Para iniciar uma classe usamos a expressão class em seguida o nome da classe, finalizada com end. Seguindo os padrões de desenvolvimento para classes em Ruby, é aconselhado trabalhar com o nome das classes, com a técnica CamelCase (as iniciais em maiúsculo todas juntas, sem espaços), EX: MinhaClasse; e para o nome dos métodos use caixa baixa e separe-as com sublinhado "_", EX: nome_metodo.
  1. Exemplo de uma simples classe com construtor denominado initialize. Para instanciar a classe use o operador new juntamente com o nome da classe.  Note que usei um Symbol, se você chegou até aqui, sabe para que serve ;):
  2. class Ola
       def initialize()
        puts :oi
       end
    end
    
    Ola.new
    =>oi
  3. Criando e chamando um método:
  4. class Ola
       def fale_algo(diga)
          puts diga
       end
    end
    a = Ola.new
    a.fale_algo('Barbaridade')
    =>Barbaridade
  5. Uma classe mais completa simulando leitura e escrita de atributos. Existem três tipos controle de acesso, attr_reader (somente leitura), attr_write (somente escrita), attr_accessor (leitura e escrita):
  6. 
    class Pessoa
     attr_reader :nome,:fone
     attr_writer :fone
     attr_accessor :email
    
     def initialize(nome,fone,email)
      @nome  = nome
      @fone  = fone
      @email = email
     end 
     
    end
    pes = Pessoa.new('Darlan Dieterich','7777-7777','d@d.com')
    pes.fone = '0000-0000'
    p pes.nome
    p pes.fone
    p pes.email
    =>Darlan Dieterich
    =>0000-0000
    =>d@d.com
    
  7. Mudando estrutura da classe sem alterar a original. Note que é usado Struct para redefinir a estrutura da classe:
  8. class Pessoa
     attr_reader   :nome,:fone
     attr_writer   :fone
     attr_accessor :email
    
     def initialize(nome,fone,email)
      @nome  = nome
      @fone  = fone
      @email = email
     end 
    end
    Pessoa = Struct.new(:nome,:email,:fone)
    pes = Pessoa.new('dieterich',77777777,'d@d.com')
    p pes
    =><struct Pessoa nome="dieterich", email=77777777, fone="d@d.com">
  9. Variaveis da classe. Em Ruby as variaveis da classe são definidas com @@ (dois arroba) juntamento com nome da classe, e também precisam ser inicializadas antes de seu uso:
  10. class Pessoa
     attr_reader   :nome,:fone
     attr_writer   :fone
     attr_accessor :email
     @@contador = 0
    
     def initialize(nome,fone,email)
      @nome  = nome
      @fone  = fone
      @email = email
      @@contador += 1
     end 
     def instancias
      @@contador
     end
    end
    pes1 = Pessoa.new('Laura',77777777,'l@l.com')
    pes2 = Pessoa.new('Darlan',77777777,'d@d.com')
    pes3 = Pessoa.new('Jenifer',77777777,'j@j.com')
    puts pes3.instancias
    =>3
  11. Herança. Trabalha de forma hierárquica  com objetivo de herdar as propriedades da classe antecessora, é usado '<' para definir a classe que sera herdada:
  12. class Pessoa
     attr_reader   :nome,:fone
     attr_writer   :fone
     attr_accessor :email 
    
     def initialize(nome,fone,email)
      @nome  = nome
      @fone  = fone
      @email = email  
     end
    end
    
    class Fisica < Pessoa
     def sou
      "pessoa fisica"
     end
    end
    
    f = Fisica.new('Darlan',987654321,'d@d.com')
    puts f.nome
    puts f.sou
    =>"Darlan"
    =>"pessoa fisica"
  13. Controle de acesso. Em Ruby public (público), protected (protegido), e private (privado), se aplicam somente a métodos. O public pode ser chamado a qualquer momento e lugar, o protected é usado na mesma ou na sua subclasse (acesso hierárquico), já o private somente pode ser chamado no objeto atual:
  14. class Pai  
     def publico
      puts 'sou o metodo publico'
     end 
     def protegido
      puts 'sou o metodo protegido'
     end  
     def privado
      puts 'sou o metodo privado'
     end
    
     public    :publico
     protected :protegido
     private   :privado
    end
    
    class Filho < Pai
     def diga
      puts protegido
     end
    end
    
    a = Filho.new
    a.publico
    a.diga
    a.privado
    =>sou o metodo publico
    =>sou o metodo protegido
    =>private method `privado' called for #<Filho:0x26adf98>
Módulos
Módulos não são Classes, porém com funcionalidades semelhantes. Por exemplo, Modulo não possui instâncias e subclasses. Um módulo é iniciado com bloco module e finalizado com end. Os módulos são divididos em dois tipos, métodos de módulo e métodos de instância.
  1. Método de módulo. Não precisa ser incluído em outro objeto. Note que usei o comando self, ele é usado para fazer referência ao receiver atual.:
  2. module Soma 
     def self.calcula(val1,val2)
      val1+val2
     end
    end
    
    puts Soma.calcula(16,50)
    =>66
    
  3. Método de instância. É usada na instância de um objeto:
  4. module Soma 
     def self.calcula(val1,val2)
      val1+val2
     end
    end
    
    class Calculadora
     def self.soma(val1,val2)
      Soma.calcula(val1,val2)
     end
    end 
    
    p x = Calculadora.soma(1,4)
    =>5
Autor: Darlan Dieterich

quinta-feira, 28 de fevereiro de 2013

Trabalhando com Ruby Parte 5 (Variáveis, Ranges, Hashes)

Primeiramente quero homenagear Ruby pelos seus 20 anos. Essa linguagem vem acolhendo a cada dia mais profissionais querendo aprender essa poderosa linguagem, ganhando mérito pela sua forma simplificada de programar para WEB. 

Variáveis
Todas as variáveis em Ruby são objetos, e vale lembrar que Ruby possui tipagem dinâmica e tipagem forte. Os nomes das variáveis ​​são compostas de letras, números e sublinhados. A grande sacada disso é, por exemplo, usar caracteres especiais para defini-las.
  1. Atribuição simples:
    variavel = 10
    =>10
  2. Caracter especial:
    ação = "funciona"
    =>funciona
  3. Atribuição paralela:
    assim, também, funciona = "nota 10", 777, [:diga=>'oi']
    =>["nota 10",777, [{:diga=>"oi"}]]
  4. Variavel global:
    $global = ''global"
    =>"global"
  5. Variavel constante. Toda constante deve ser definida caracteres CAIXA ALTA:
    CONCRETO = "ninguém meche aqui"
    =>"ninguém meche aqui"
  6. Variavel de instância (usada em Classes onde veremos em próximos artigos):
    @instancia = 123
    =>123
  7. Variavel da classe:
    @@classe = nil
    =>nil
  8. Descobrindo uma variável. Como Ruby tem tipagem dinâmica, é possível visualizar qual a tipagem que ele definiu a aquela determinada variável, para isso usamos a função class:
    var = 'teste'
    =>teste
    var.class
    =>String
  9. Exibindo erro, (Ruby tem sua tipagem forte, isso é, resulta em um erro caso algo for forçado)
    a = 1
    =>1
    b = 'teste'
    =>'teste'
    a+b
    =>TypeError: String can't be coerced into Fixnum 
    
Ranges
Ranges tem como objetivo trabalhar com valores em intervalos, declarando um valor inicial e um valor final, assim percorrendo de forma sequencial.
  1. Exemplo básico:
    range = 1..10
    =>1..10
    range.each {|x|
     puts x
    }
    => 1,2,3,4,5,6,7,8,9,10
    
  2. Todos menos o ultimo, (note que usei um ponto a mais, assim limita o ultimo elemento a ser anulado):
    range = 1...10
    =>1..10
    range.each {|x|
     puts x
    }
    => 1,2,3,4,5,6,7,8,9
    
  3. Evoluindo com palavras:
    nomes = ('a'..'z')
    =>'a'..'z'
    nomes.each {|n|
     puts n
    }
    => a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
    
    
  4. Verificando existencia de algo, (note que usei a função include para verificar a existencia de um elemento incluso no range):
    var = 1..10
    =>1..10
    if var.include?(6)
     p 'tem'
    else
     p 'nao tem'
    end
    => "tem"
    
Hashes
De forma parecida com Array, seu diferencial é um indice de Array mais completo com chaves e valores.
  1. Atribuição de Hash comum, (estou usando Symbol, String, Fixnum para determinar uma chave):
    hash = {:cao=>'late',:leao=>'ruge','papagaio'=>'fala',1=>'um'}
    =>{:cao=>'late',:leao=>'ruge','papagaio'=>'fala',1=>'um'}
  2. Retornando Hash determinado:
    hash = {:gato=>'mia',:cao=>'late',:leao=>'ruge'}
    =>{:gato=>'mia',:cao=>'late',:leao=>'ruge'}
    puts hash[:leao]
    =>'ruge'
  3. Retornando Chaves, (aconselho usar somente Symbol para determinar as chaves, por questão de desempenho):
    hash = {:gato=>'mia',:cao=>'late',:leao=>'ruge'}
    =>{:gato=>'mia',:cao=>'late',:leao=>'ruge'}
    puts hash.keys
    =>[:gato, :cao, :leao]
  4. Retornando Valores:
    hash = {:gato=>'mia',:cao=>'late',:leao=>'ruge'}
    =>{:gato=>'mia',:cao=>'late',:leao=>'ruge'}
    puts hash.values
    =>["mia", "late", "ruge"]
  5. Atribuindo novo elemento:
    hash = {:gato=>'mia',:cao=>'late',:leao=>'ruge'}
    =>{:gato=>'mia',:cao=>'late',:leao=>'ruge'}
    hash[:bode] = 'berra'
    =>"berra"
  6. Retornando tamanho:
    hash = {:gato=>'mia',:cao=>'late',:leao=>'ruge'}
    =>{:gato=>'mia',:cao=>'late',:leao=>'ruge'}
    puts hash.size
    =>3 
Autor: Darlan Dieterich

quarta-feira, 9 de janeiro de 2013

Exercitando com Ruby Parte 4 (Tipos de dados, Conversão de tipos, Tratamento de exceções)

Tipos de dados
Todas as variáveis são objetos (abstratos), todos tipos são classes. (nesse exemplo irei trabalhar com o IRB):
  • Object: é a classe principal
    • Numeric: classe de números;
      • Integer: classe de números inteiros;
        • Fixnum: números inteiros de precisão fixa, contém  31 bits de comprimento;
        1. Exemplo básico:
          1+1
          =>2
        2. Descobrindo o tipo de dado usando class
          (2*6).class
          =>Fixnum
          
        • Bignum: números inteiros de precisão infinita;
        1. Exemplo básico:
          (1234567890).class
          =>Bignum
      • Float: classe de números reais;
      1. Exemplo básico:
        6.66
        =>6.66
      2. Convertendo uma string em Float
        "7.123".to_f
        =>7.123
    • String: um conjunto de caracteres. Onde pode ser delimitado por apóstrofes ( ' ) ou aspas ( " );
    1. Exemplo básico:
      "String normal"
      =>"String normal"
    2. Bloco de texto:
      texto = <<TEXTO
       aqui escrevo
       o texto que eu
       quiser
      TEXTO
      =>"aqui escrevo \no texto que eu\n quiser"
    3. Substrings usando ranges:
      texto = "Dieterich"
      =>"Dieterich"
      texto[0..2]
      =>"Die"
      
    • Symbol: Symbol é o objeto mais básico que pode ser criado, seria o nome de variáveis de instância, nomes de métodos, nomes de classes. Semelhante a uma String, é usado como um nome consistente no código, então o objetivo do Symbol, é ter uma performance maior em relação a String, onde  símbolos compartilham o mesmo objeto, mas como Símbolos não liberam o espaço em memória diferentemente das Strings, futuramente pode ocorrer um esgotamento de memória. Cada vez que referenciar um mesmo Symbol, é usado o mesmo espaço alocado na memória. Ele é definido como dois pontos ( : );
    1. Exemplo:
      nome = :darlan
      =>:darlan
      nome.class
      =>Symbol
      
    • Array: pode ser vetor ou matriz. É delimitado por colchetes ( [ ] );
    1. Exemplo:
      vetor = [1,"dois"]
      =>[1,"dois"]
    2. Inserindo mais elementos: 
      vetor.push "mais um"
      =>[1,"vetor","mais um"]
      
    • Hash: vetor associativo (estrutura de dados), é usado para valores com índices, também conhecido como mapa, dicionário. É delimitado por ( { } );
    1. Exemplo:
      
      vetor = {"um"=>"elemento 1",:dois=>"elemento dois"}
      =>{"um"=>"elemento 1",:dois=>"elemento dois"}
      vetor['um']
      =>"elemento 1"
      
      
    • Regexp: expressões regulares, usadas para processamento de textos, e casamento de informações. É delimitado por ( // );
    1. Exemplo:
      er = /^[0-9]/
      =>/^[0-9]/
      puts "casou" if er =~ '321'
      =>casou
      
Conversão de tipos
Conversão de tipos, é uma técnica na qual você 'força' a conversão de algum tipo de dado, transformando por exemplo, um inteiro em uma string.

Método
De
Para
Exemplo
to_i
String
Inteiro
"777".to_i => 777
to_f
String
Flutuante
"777".to_f => 777.0
to_s
Inteiro
String
1.to_s => "1"
to_a
Range
Array
(1..4).to_a => [1,2,3,4]
to_sym
String
Simbolo
"nome".to_sym => :nome
join
Array
String
["vetor",1,"dois"].join(",") => "vetor",1,"dois"









Tratamento de exceções

Erros ocorrem as vezes de forma inesperada. Para retornar um erro mais 'limpo' ao usuário final, de forma simplificada, para que entenda o que esta ocorrendo, assim evitando disparar informações sigilosas na tela, e também entender o que esta acontecendo, então precisamos tratar esse código usando tratamentos de exceções.

  1. Especificando o tipo de exceção. Note que usei um operador matemático (*) para forçar o erro, o rescue é responsável por retornar o erro. 
    begin
     string1 = "eu nao sou"
     string2 = "cauteloso"
     
     string1*string2
    
    rescue StandardError => excecao
     puts "Houve um erro: #{excecao}"
    end
    =>Houve um erro: can't convert String into Integer
autor: Darlan Dieterich