Ruby para programadores PHP

03/08/07

A maneira mais fácil de se aprender uma nova linguagem é comparando-a com uma linguagem que você já conhece. Pelo menos é assim que faço! Para os que são como eu, aqui vai uma série de comparações/equivalências entre as linguagens Ruby e PHP.

Estruturas de controle

Condicionais

# php
# setting some variables
$n1 = 1;
$n2 = 2;
$n3 = 3;
 
# if condition
if ($n1 > $n2)
  echo 'n1 > n2',"\n";
elseif ($n1 > $n3)
  echo 'n1 > n3', "\n";
else
  echo 'n1 =< n2; n1 =< n3', "\n";
 
# one-line if
echo n3 > n2? "n3 > n2\n" : "n3 <= n2\n";
 
# switch..case
switch($n1) {
    case 1:
        echo "n1 = 1", "\n";
        break;
    case 2:
        echo "n1 = 2", "\n";
        break;
    default:
        echo "n1 = {$n1}", "\n";
}
# ruby
# setting some variables
n1 = 1
n2 = 2
n3 = 3
 
# if condition
if n1 > n2
  puts 'n1 > n2'
elsif n1 > n3
  puts 'n1 > n3'
else
  puts 'n1 =< n2; n1 =< n3'
end
 
# one-line if
puts n3 > n2 ? 'n3 > n2' : 'n3 <= n2'
 
# unless condition
unless n3 > n2
  puts 'n3 > n2'
end
 
# different structure
puts 'n1 > n3' if n1 > n3
puts 'n1 =< n2' unless n1 > n2
 
# switch..case
case n1
  when 1
    puts 'n1 = 1'
  when 2
    puts 'n1 = 2'
  else
    puts 'n1 = %d' % n1
end

Estruturas de repetição

# php
# while
$i = 1;
while ($i < 5) {
  echo $i, "\n";
  $i += 1;
}
 
# do..while
$i = 1;
do {
    echo $i, "\n";
    $i += 1;
} while ($i < 5);
 
# for i++
for ($i = 1; $i <= 5; $i++) {
    echo $i, "\n";
}
 
# for i--
for ($i = 5; $i >= 1; $i--) {
    echo $i, "\n";
}
 
# each
foreach (range(1,5) as $i) {
    echo $i, "\n";
}
 
# break/continue
$i = 0;
while ($i < 10) {
    $i++;
 
    # break
    if ($i == 9) {
        break;
    }
 
    # continue
    if ($i % 2 == 0) {
        continue;
    }
 
    echo $i, "\n";
}
# ruby
# while
i = 1
while i < 5
  puts i
  i += 1
end
 
# until
i = 1
until i > 5
  puts i
  i += 1
end
 
# loop
i = 1
loop do
  break if i > 5
  puts i
  i += 1
end
 
# do..while
i = 1
begin
  puts i
  i += 1
end while i < 5
 
# do..until
i = 1
begin
  puts i
  i += 1
end until i > 5
 
# upto (for i++)
1.upto(5) do |i|
  puts i
end
 
# downto (for i--)
5.downto(1) do |i|
  puts i
end
 
# for..in (foreach)
for i in (1..5)
  puts i
end
 
# each
(1..5).each do |i|
  puts i
end
 
# break/next
i = 0
while i < 10 do
    i += 1
 
    break if i == 9     # break
    next if i % 2 == 0  # next (continue)
 
    puts i
end

Strings

Particularmente, penso que o PHP é muito mais completo para se lidar com strings quando o assunto é biblioteca padrão. Na maioria das vezes você possui alternativas — estender a classe, por exemplo — mas é um trabalho que alguém terá que fazer.

Manipulando strings

# php
# interpolate variables
$text = "php";
echo "i love $text", "\n";
echo "i love {$text}", "\n";
printf("i love %s\n", $text);
 
# basic functions
$text = 'i love php';
echo strtolower('I LOVE PHP'), "\n";    # lowercase text
echo strtoupper($text), "\n";           # uppercase text
echo ucfirst($text), "\n";              # capitalize text
echo strlen($text), "\n";               # string size
echo strrev($text), "\n";               # reversing text
echo str_repeat("php ", 3), "\n";       # repeat text
echo ord("a"), "\n";                    # get ASCII value
echo chr("97"), "\n";                   # get char from ASCII value
 
# remove spaces
$text = '  i love php  ';
echo trim($text), "\n";     # both sides
echo ltrim($text), "\n";    # just left side
echo rtrim($text), "\n";    # just right side
 
# remove characters
$text = '__i love php__';
echo trim($text, '_'), "\n";     # both sides
echo ltrim($text, '_'), "\n";    # just left side
echo rtrim($text, '_'), "\n";    # just right side
 
# slicing strings
$text = 'i love php';
echo substr($text, 0, 6), "\n";
echo $text[0], "\n";
 
# search characters
echo strpos("php", "h"), "\n";  # find position
# ruby
# interpolate variables
text = "ruby"
puts "i love #{text}";
puts "i love %s" % text;
printf("i love %s\n", text);
 
# basic functions
text = 'i love ruby';
puts 'I LOVE RUBY'.downcase  # lowercase text
puts text.upcase            # uppercase text
puts text.capitalize        # capitalize text
puts text.size              # string size
puts text.reverse           # reversing text
puts "ruby " * 3            # repeat text
puts "a"[0]                 # get ASCII value
puts 97.chr                 # get char from ASCII value
 
# remove spaces
text = '  i love ruby  ';
puts text.strip     # both sides
puts text.lstrip    # just left side
puts text.rstrip    # just right side
 
# remove characters
# ruby has no easy way of doing that besides regular expressions
# so we're gonna extend String class
# check this link out: http://simplesideias.com.br/
 
text = '||__i love ruby__||'
puts text.trim('_|')  # both sides
puts text.ltrim('_|') # just left side
puts text.rtrim('_|') # just right side
 
# slicing strings
text = 'i love ruby';
puts text[0,6]
puts text[0,1]
 
# search characters
puts "ruby" =~ /y/  # find position

Gerando hashes com MD5 e SHA1

# php
echo md5("php"), "\n";
echo sha1("php");
# ruby
require 'digest/md5'
require 'digest/sha1'
 
puts Digest::MD5.hexdigest("ruby")
puts Digest::SHA1.hexdigest("ruby")

Expressões regulares

No PHP temos uma série de funções que lidam com expressões regulares como eregi, preg_match, preg_replace, dentre outras. O Ruby também tem métodos equivalentes:

preg_match vs match

Verificar se uma determinada string obedece um padrão
#php
if(preg_match("/^\d{2}\/\d{2}\/\d{4}$/", '01/01/2007')) {
    print 'valid format'
} else {
    print 'invalid format'
}
# ruby - method 1
if '01/01/2007' =~ /^\d{2}\/\d{2}\/\d{4}$/
  puts 'valid format'
else
  puts 'invalid format'
end
 
# ruby - method 2
if '01/01/2007'.match(/^\d{2}\/\d{2}\/\d{4}$/)
  puts 'valid format'
else
  puts 'invalid format'
end
Acessando os matches de uma expressão regular
# php
preg_match("/like/", "i like php", $matches);
print "match: " . $matches[0];
# ruby
matches = "i like ruby".match(/like/)
puts matches[0]
Atribuindo os matches de uma expressão regular à variáveis
# php
preg_match("/(\b\w+\b) (\b\w+\b)/", "nando vieira", $matches);
list($full_name, $first_name, $last_name) = $matches;
 
print $full_name . "\n";
print $first_name . "\n";
print $last_name;
# ruby
full_name, first_name, last_name = *"nando vieira".match(/(\b\w+\b) (\b\w+\b)/)
 
puts full_name
puts first_name
puts last_name

preg_replace vs gsub

Substituíndo padrões
# php
print preg_replace("/like/", "love", "i like php")
# ruby
puts "i like ruby".gsub(/like/, 'love')
Utilizando retrovisores (backreferences)
# php
print preg_replace("/(duck)/", "\$1 and one chicken", "one duck")
# ruby
puts "one duck".gsub(/(duck)/, "\\1 and one chicken")

preg_match_all vs scan

# php
$text = "item 1\nitem 2\nitem 3";
preg_match_all("/item (\d+)/sim", $text, $matches);
 
print_r($matches[1]);
# ruby
text = "item 1\nitem 2\nitem 3"
matches = text.scan(/item (\d+)/)
 
puts matches

Array e Hash

Utilizando arrays

# php
$companies = array('apple', 'microsoft', 'red hat', 'canonical');
 
echo count($companies), "\n";       # how many items?
echo $companies[0], "\n";           # first item
echo end($companies), "\n";         # last item
echo (int)empty($companies), "\n";  # size > 0?
 
# sorting array
sort($companies);
 
# removing duplicate items
$companies = array_unique($companies);
 
# applying a function
$companies = array_map('strtoupper', $companies);
 
# reversing
$companies = array_reverse($companies);
 
# joining
echo join(", ", $companies), "\n";
 
# slicing
echo join(", ", array_slice($companies, 1, 3)), "\n";
 
# removing last item
echo array_pop($companies), "\n";
 
# removing first item
echo array_shift($companies), "\n";
 
# adding item at the end
array_push($companies, 'ADOBE');
 
# adding item at the beginning
array_unshift($companies, 'NOVELL');
# ruby
companies = ['apple', 'microsoft', 'red hat', 'canonical']
 
puts companies.size    # how many items?
puts companies.first   # first item
puts companies.last    # last item
puts companies.empty?  # size > 0?
 
# sorting array
companies.sort!
 
# removing duplicate items
companies.uniq!
 
# applying a function
companies.map! { |company| company.upcase }
 
# reversing
companies.reverse!
 
# joining
puts companies.join(", ")
 
# slicing
puts companies[1..3].join(", ")
puts companies.slice(1, 3).join(", ")
 
# removing last item
puts companies.pop
 
# removing first item
puts companies.shift
 
# adding item at the end
companies.push 'ADOBE'
 
# adding item at the beginning
companies.unshift 'NOVELL'

Arrays associativos

No Ruby, os arrays associativos são definidos como Hash e tem sua sintaxe ligeiramente diferente. Vale lembrar que, ao iterar um hash, os valores apresentados geralmente não os mesmos da ordem de inserção.

# php
$companies = array(
    'apple' => 'mac os x',
    'microsoft' => 'windows vista',
    'canonical' => 'ubuntu'
);
 
echo $companies['apple'], "\n";
 
# getting the keys
echo join(", ", array_keys($companies)), "\n";
 
# iterating through array
foreach ($companies as $company => $so) {
    printf("%s: %s\n", $company, $so);
}
 
# removing a item
unset($companies['microsoft']);
 
# checking if array has a key
if (!array_key_exists('novell', $companies)) {
    echo "Novell not found\n";
}
# ruby
companies = {
    'apple' => 'mac os x',
    'microsoft' => 'windows vista',
    'canonical' => 'ubuntu'
}
 
puts companies['apple']
 
# getting the keys
puts companies.keys.join(", ")
 
# iterating through array
companies.each do |company, so|
    puts "%s: %s" % [company, so]
end
 
# removing a item
companies.delete('microsoft')
 
# checking if array has a key
puts 'Novell not found' if not companies.key?('novell')

Arquivos e diretórios

Arquivos

Criar novo novo arquivo e adicionar conteúdo
# php
$file = fopen('newfile.txt', 'w+');
fwrite($file, str_repeat("i love php\n", 10));
fclose($file);
# ruby
file = File.new('newfile.txt', 'w+')
file << "i love ruby\n" * 10
file.close
Lendo arquivos
# php
$file = fopen('newfile.txt', 'r');
echo fwrite($file, ('newfile.txt')), "\n";
fclose($file);
# ruby
file = File.new('newfile.txt')
puts file.read
file.close
Iterando nas linhas do arquivo
# php
$lines = file('newfile.txt');
foreach ($lines as $num => $line) {
    echo $num+1, ': ', $line;
}
# ruby
file = File.new('newfile.txt')
file.each_with_index do |line, num|
  puts "%d: %s" % [num+1, line]
end
file.close
Outras funções
# php
# check if file exists
echo (int)file_exists('newfile.txt'), "\n";
 
# print file size in bytes
echo filesize('newfile.txt'), "\n";
 
# write permission?
echo (int)is_writable('newfile.txt'), "\n";
 
# read permission?
echo (int)is_readable('newfile.txt'), "\n";
 
# is file?
echo (int)is_file('newfile.txt'), "\n";
 
# remove file
unlink('newfile.txt');
# ruby
# check if file exists
puts File.exists?('newfile.txt')
 
# print file size in bytes
puts File.size('newfile.txt')
 
# write permission?
puts File.writable?('newfile.txt')
 
# read permission?
puts File.readable?('newfile.txt')
 
# is file?
puts File.file?('newfile.txt')
 
# remove file
File.unlink('newfile.txt')

Diretórios

# php
# creating new directory
mkdir('newdir');
 
# listing files
$dir = opendir("newdir");
 
while (false !== ($entry = readdir($dir))) {
    echo $entry, "\n";
}
closedir($dir);
 
# directory?
echo (int)is_dir('newdir'), "\n";
 
# remove non-empty directory
# php have no such function
# check this link out for alternatives
# http://php.net/rmdir
 
# remove empty directory
rmdir('newdir');
# ruby
# creating new directory
dir = Dir.mkdir('newdir')
file = File.new('newdir/newfile.txt', 'w+')
 
# listing files
dir = Dir.new('newdir')
dir.entries.each do |entry|
  puts entry
end
 
# directory?
puts File.directory?('newdir')
 
# remove non-empty directory
require 'fileutils'
FileUtils.rm_rf('newdir')
 
# remove empty directory
Dir.mkdir('newdir')
Dir.rmdir('newdir')

Classes

# php
class Vehicle {
    # read/write attribute
    public $name;
 
    # private attribute
    private $color;
 
    # constructor
    function __construct($name)
    {
        $this->name = $name;
    }
 
    # setter
    function setColor($colorName)
    {
        $this->color = $colorName;
    }
 
    # getter
    function getColor()
    {
        return $this->color;
    }
 
    # static
    function getWheels()
    {
        return 0;
    }
}
 
class Car extends Vehicle {
    function __construct($name)
    {
        parent::__construct($name);
    }
 
    function getWheels()
    {
        return 4;
    }
}
 
$car = new Car('Stilo');
echo $car->name, "\n";      # name attribute
echo get_class($car), "\n"; # object class
 
$car->setColor('graffiti');
echo $car->getColor(), "\n";
 
echo Car::getWheels(), "\n"; # static method
# ruby
class Vehicle
  # read/write attribute
  attr_accessor :name
 
  # class variable
  @@wheels = 0
 
  # contructor
  def initialize(name)
    @name = name
  end
 
  # color getter
  def color
    @color
  end
 
  # color setter
  def color=(color_name)
    @color = color_name
  end
 
  def self.wheels
    @@wheels
  end
end
 
class Car < Vehicle
  @@wheels = 4
 
  def initialize(name)
    super(name)
  end
end
 
car = Car.new('Stilo')
puts car.name   # name attribute
puts car.class  # object class
 
car.color = 'yellow'
puts car.color
 
puts Car::wheels  # class method (static method on PHP)

Lendo páginas da web (scraping)

Processando XML

# php
$curl = curl_init('http://del.icio.us/rss/fnando');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($curl);
 
$xml = new SimpleXMLElement($response);
 
foreach ($xml->item as $item) {
    $title = $item->title;
    $link = $item->link;
 
    printf("%s\n%s\n\n", $title, $link);
}
# ruby
require 'net/http'
require 'uri'
require 'rexml/document'
 
url = URI.parse('http://del.icio.us/rss/fnando')
response = Net::HTTP.get(url)
xml = REXML::Document.new(response)
 
xml.root.elements.to_a('//item').each do |item|
  title = item.elements['title'].text
  link = item.elements['link'].text
 
  puts "%s\n%s\n\n" % [title, link]
end

Processando HTML

# php
$curl = curl_init('http://www.google.com/trends/music');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($curl);
 
preg_match_all("/<a.*?href=\".*?&res=artist.*?>(.*?)<\/a>/sim", $response, $matches);
 
echo join("\n", array_unique($matches[1])), "\n";
require 'net/http'
require 'uri'
require 'rexml/document'
 
url = URI.parse('http://www.google.com/trends/music')
response = Net::HTTP.get(url)
regex = /<a.*?href=".*?&res=artist.*?>(.*?)<\/a>/sim
 
puts response.scan(regex).uniq.join("\n")

Se você acha que eu deveria ter abordado algum outro conjunto de funções, avise-me e atualizarei o artigo. Divirta-se!

Update: Adicionei estruturas de controle

Comentários #


#1 Leandro Vieira Pinho disse:
03 Ago 07, 12:03PM

Excelente post Nando,

Como você falou, é mais fácil aprender uma nova linguagem comparando-a com outra. No meu caso que utilizo o PHP, e nunca lidei com o Ruby, este artigo foi uma ótima iniciativa.

Um abraço.

#2 Junior disse:
03 Ago 07, 12:28PM

muito bom o artigo, é bem como voce disse..
é mais facil aprender uma linguagem comparando com uma que você ja domina.
parabéns

#3 Assunção Jr. disse:
03 Ago 07, 01:09PM

Legal a comparação. Pelo que percebi, o que muda é o Ruby é mais orientado a objeto que o Php. Mas como diria uma amigo meu: "o que muda é o nome das funções".

Pelo menos foi isso que percebi. Mas tenho que salientar que em alguns casos o Ruby ganha em simplicidade.

#4 André Taiar disse:
03 Ago 07, 01:19PM

Excelente artigo…
Tava mesmo precisando de uma comparação…
Juro que era isso que eu estava procurando!

Grande abraço!

#5 camilo vitorino da costa disse:
03 Ago 07, 01:21PM

olá nando! Hoje mesmo estava falando para um colega de trabalho que programa em PHP sobre ruby, mas não tinha tantos argumentos (sou designer [o que um designer faz num blog de ruby???]) agora vou passar esse link pra ele!!

muito bom, como você falou, melhor aprender comparando com algo que a gente já conheça!!

abraço

#6 Aguinelo Pedroso disse:
03 Ago 07, 02:31PM

Nando Perfeito, muito bom pra quem ta aprendendo Rails, parabéns

#7 Gabriel Falcão disse:
03 Ago 07, 03:05PM

Muito bom mesmo!
Agradeço à vc pelos minutos e gastos escrevendo este post, assim até me animo a dar uma estudada em ruby, para depois ganhar conforto ao partir pro rails.

Abraço!

#8 Walter Cruz disse:
03 Ago 07, 03:24PM

Belo post! Vamos ver se eu me animo a terminar meu texto sobre PHP e Lua :)

#9 Fill disse:
03 Ago 07, 04:57PM

Fala Nando… gostei muito do post, Faz muito tempo que eu queria dar uma olhada em Ruby mas tava meio sem vontade sem tempo. =) Agora eu tenho uma duvida. O Ruby serve para internet também? Forte abraço.

#10 Klaus Paiva disse:
03 Ago 07, 07:46PM

Show de bola Ferdinando!
Já que a documentação do PHP é tão rica e a comunidade PHP é grande, esses exemplos são ótimos para pegar o "fio da meada" de uma linguagem pra outra!

PS: Precisa acertar o tabindex do "captcha" aqui embaixo. Um tab aqui nos comentários vai direto para o submit. =)

[]'s

#11 Newton Wagner disse:
04 Ago 07, 09:04AM

Bem interessante.. não tinha visto ainda essa comparação.

Linguagens são linguagens.. sintaxes diferentes para a mesma lógica. E o Ruby tem uma sintaxe agradável. Só achei estranha a definição da classe, principalmente os atributos da classe.

#12 Rodrigo Urubatan disse:
05 Ago 07, 01:33AM

Muito bom este post, ajuda bastante gente a começar a se aventurar com o RoR :D
Com a mesma idéia acho que o pessoal sente um pouco de falta de uma IDE para isto …
então comecei a escrever uma série de posts sobre IDEs para RoR (o primeiro é este sobre o RadRails http://www.urubatan.com.br/2007/08/05/ruby-on-rails-ide-war-1-aptana-rad-rails/ )

E se você se interessar, gostaria de deixar um convite também, para que você escreva um post descrevendo o seu ambiente de desenvolvimento …

Se quiser publicar aqui eu coloco um link la no meu blog, ou se quiser publicar la no meu blog mesmo sera muito bem vindo … )

Abraço

#13 Nando Vieira disse:
05 Ago 07, 02:02AM

#12 Rodrigo: O que eu uso está aqui: http://simplesideias.com.br/tags/gedit ;)

#14 Arthur Furlan disse:
06 Ago 07, 08:17AM

"A maneira mais fácil de se aprender uma nova linguagem é comparando-a com uma linguagem que você já conhece."

Perfeito, excelente post! :)

#15 diogo lopes disse:
07 Ago 07, 03:38PM

ual…
fántastico.
De tempos em tempo você nos presenteia com posts como esse.

#16 Silveira Neto disse:
08 Ago 07, 07:52PM

Nossa muito bom! Precisava disso mesmo.

#17 felipe tonello disse:
11 Ago 07, 11:43AM

Muito legal mesmo.
Nunca tinha visto ruby. Muito parecido com python hein.
Apesar de não ver necessidade de trocar php por ruby, ainda mais com agora a vinda do Zend Framework, estou confiante no PHP.
Mas uma coisa que com certeza o ruby ganha de php é na facilidade da sintaxe, coisinhas simples é muito mais facil de fazer. Que provavelmente puxou do python isso. hehe

Abraços

#18 Salvador Camino disse:
14 Ago 07, 12:49PM

Muito bom mesmo, salvei nos delicious.
A muito já venho flertando com o ruby, mas estou adiando ainda… quando eu for começar a bricar com ror vou dar uma olhada aqui novamente. Parabens

#19 Ruby para Programadores PHP @ Just another blog… disse:
07 Set 07, 04:56PM

[...] http://simplesideias.com.br/ruby-para-programadores-php [...]

#20 links for 2007-09-09 | betohayasida.net disse:
09 Set 07, 08:30PM

[...] Simples Idéias. Por Nando Vieira. » Arquivo » Ruby para programadores PHP (tags: programming:ruby programming:php) [...]

#21 Ruby para Programadores PHP « My Scripts' place disse:
10 Set 07, 05:01PM

[...] Ruby para Programadores PHP Setembro 10, 2007 at 8:01 pm | In Rapidinha, Dicas, ruby | Eis aqui um ótimo post para quem sabe PHP e está querendo aprender Ruby (como no meu caso), o autor do Post faz uma analogia entre as duas linguagens utilizando diversos recursos do PHP e implementando em Ruby, e da forma como foi escrito não tem como não aprender, para saber mais basta seguir o link. [...]

#22 Felipe Santiago disse:
05 Out 07, 04:18PM

Parabéns!! Ótima iniciativa!

#23 Vasco Arralde disse:
21 Nov 07, 08:18AM

Parabéns Fernando,

Muito bom esse material.

#24 Anselmo Battisti disse:
02 Jan 08, 06:04PM

Poxa legal!

#25 Luciana disse:
22 Fev 08, 04:15PM

Parabens!! era exatamente o q estava procurando!!!
muito bom mesmo!!!!!!

#26 Michael Mafort disse:
01 Mar 08, 11:17AM

Excelente post.

A comparação foi muito bem conduzida por você, facilitou muito o meu aprendizado nesta nova linguagem que estou me aventurando. Durante as comparações acabei comparando alem do php com o Action Script, que no termo de OO está bem similar.

Grande abraço.

#27 Vilmondes Eracton disse:
30 Jul 08, 01:30PM

Ótimo post. Eu estava procurando exemplo de curl+xml e o achei.

Parabéns! =]

#28 Rafael Dohms » Cantos arredondados no Ruby on Rails - Um es... disse:
28 Ago 08, 09:10AM

[...] dedicada ao Ruby on Rails, decidi que ao invés de começa nos principios do RoR (o Nando Viera do Simples Ideias já fez isso bem o bastante) vou iniciar com umas das primeiras peças que criei que podem ser [...]

#29 Rafael disse:
30 Ago 08, 09:31PM

Excelente texto gostei do unless do Ruby, mas por enquanto continuo no PHP.

Abraços

Deixe um comentário




Este blog usa o Gravatar.


Não é aceito código HTML:
adicione-o no pastie.caboo.se ou paste.milk-it.net e poste apenas o link.

Se este é seu primeiro comentário, ele terá que ser aprovado antes de ser exibido.