Em Java quando eu entro num bloco (dentro de um loop por exemplo) é fácil saber se posso usar a variável x.
int x = 10;
// 50 linhas aqui de código...
for(int i=0;i<100;i++) {
int x = s.indexOf("a"); // vai dar erro, pois s já existe...
// mais código aqui...
}
Já em Ruby ou em uma linguagem sem tipos:
x = 10
# 50 linhas de código aqui...
100.times do
x = s.length
# outros códigos aqui...
end
Como vocês fazem para controlar o escopo numa linguagem sem tipos?
PS: Dá para exibir código Ruby no JForum ou ele só formata para Java?
[quote=Maurício Linhares]Em Ruby isso não tem jeito, você é que vai ter que ficar cuidando disso, mas convenhamos, você consegue imaginar algum caso onde isso vai acontecer?
[/quote]
Isso me parece que vai acontecer toda hora, ou seja, quando você entrar num escopo novo, seja um IF ou um LOOP, e você quer declarar uma variável para usar apenas ali dentro (e não fora), você vai ter que tomar cuidado para não usar uma variável já declarada, sem querer.
Se vc está se preocupando com escopo a esse ponto, deve ter algo de errado. Em geral, vc só usa uma variavel declarada 50 linhas antes se ela estiver no escopo da classe. No mais, o interessante é tentar manter métodos e blocos de código mais curtos: são mais fáceis de ler, entender e manter.
Acho que você ainda não pegou o jeito da linguagem
O for do Java em Ruby seria algo assim:
1..10.each do |x|
p "X é -> #{x}"
end
O x só foi declarado dentro da própria closure, como seria um x de um for em Java, não vai matar ninguém. Agora se o que você está se preocupando mesmo é o nome de variáveis talvez seja um problema dos nomes que você está dando. Nomes mais “explicativos” normalmente não tem esse problema.
Mas no meu caso o x não era do closure não… O x é algo que eu quero declarar DENTRO do closure. Se eu já declarei fora e me esqueci (ou estou no meio de um refactoring de um código que não foi nem que que fiz) estarei introduzindo um bug chato de pegar depois.
Isso que o jack falou faz sentido, mas num caso de um refactoring não ajuda não. Seria legal ter um var para declarar uma nova variável sem tipo.
Do jeito que é isso, se eu for criar uma variável x dentro de um block, eu tenho que procurar fora do código via CTRL+F mesmo se já existe um x. Isso me parece péssimo! Scala tem var! Talvez seja por causa dissol…
Ah companheiro, você não sabe da missa o terço :lol: :lol: :lol:
Um “control + f” não vai salvar a sua vida em Ruby, alguém pode ter adicionado o método lá na classe via metaprogramação com o mesmo nome da sua variável e você nunca iria saber até alguma coisa estourar
Lidar com linguagens que fazem mágica demais não é simples não :twisted:
Sem isso cada variável que eu declaro pode me assombrar depois…
Será que estou me preocupando a toa ou isso é realmente um problema.
Quando estou dentro de um escopo eu sempre penso assim:
“Vou declalar ‘index’ para usar aqui dentro. Mas será que eu já declarei isso antes?”
O compilador me avisaria se tivesse o diabo do ‘var’. Sem ele não tem como saber se você está declarando pela primeira vez ou reutilizando alguma coisa que já foi declarada antes.
Esqueça o compilador, mesmo que ele existisse, em Ruby você ainda ia cair nesse problema de um método definido em tempo de execução.
Eu, até agora, não tive problema nenhum quanto a isso, o negócio é manter os métodos simples, pequenos e dar as variáveis nomes decentes (além de saber quais as mágicas estão acontencendo nos seus objetos).
Isso pode ser um problema se você não tomar cuidado. Pelo menos em Lisp há uma convenção de nome adotada para variáveis globais, todas elas são declaradas assim: nome-da-variavel. Isso deixa o nome muito diferente das variáveis locais e não há perigo de você se confundir.
[quote=Thiagosc][quote=nadele]
Sem isso cada variável que eu declaro pode me assombrar depois…
Será que estou me preocupando a toa ou isso é realmente um problema.
[/quote]
Isso pode ser um problema se você não tomar cuidado. Pelo menos em Lisp há uma convenção de nome adotada para variáveis globais, todas elas são declaradas assim: nome-da-variavel. Isso deixa o nome muito diferente das variáveis locais e não há perigo de você se confundir.[/quote]
No ruby tb existem essas convenções, variáveis globais são @@nome, mas acho q uma convenção de projeto seria mais ideal.
E como os próprios alternativos de for do ruby disponibilizam a variável que incrementa acho bem difícil de acontecer isso seguindo uma arquitetura boa e deixando seu código bem limpo e dividido.
No mais, quando o desespero tiver batendo, o bug ainda estiver no programa e vc nem sabe onde ele está, vc pode fazer uma sessão de testes pra isolar o método ou classe q está bugando e dentro dela usar ObjectSpace.each_object para descobrir todos os objetos que estão em memória no momento.
No Ruby 1.9 (versão de teste, transicional para a próxima versão estável) uma variável não tem mais o mesmo escopo dentro e fora de um bloco.
Se tiveres uma variável com um valor, e dentro do bloco trocar o valor, ao sair do bloco o valor será o anterior ao bloco. A alteração vale apenas ao escopo do bloco.
Ainda não é uma certeza que vai existir isso, mas a próxima versão estável de ruby será baseada naquilo que realmente for substancial dentro da 1.9.
Mas haverá casos que eu quero utilizar a variável que eu declarei fora do bloco dentro do bloco, e casos onde eu quero criar uma nova variável para usar somente ali dentro.
A constatação é simples: “Em Ruby, eu não tenho como diferenciar uma criação de variável de uma mudança de valor dessa variável!”
Acho que a solução é ter métodos suficientemente pequenos para que você se lembre (ou veja se o seu monitor for suficientemente grande) quais as variáveis que você já declarou.
Um simples var resolveria o problema !!! Isso aí que o nbluis descreveu não faz muito sentido não…
var x = 2 # cria uma variável... se já existe então ERRO
x = 2 # muda o valor de uma variável que já existe... (ok, se não existir então cria ela por default)
Na verdade eu ainda não entrei muito nos detalhes das alterações no ruby 1.9 (afinal eu também trabalho).
Mas pelo que eu entendi, a variável existe dentro do bloco porém as alterações dentro do bloco não vão para fora dele. (Talvez seja engajada também uma maneira de fazer isso)
[quote=rubinelli]@@var na verdade é atributo de classe, @var é atributo do objeto, e $var é global igual ao do C.
O problema em potencial que o nadele descreveu nunca tive, mas já tive conflitos com varáveis locais com o mesmo nome de métodos.[/quote]
ah ehh. viajei ._.
Eu normalmente qdo vou chamar um método do próprio objeto costumo usar um self antes.
Nao tem tanta necessidade assim, acho q é mais uma questão de clareza do código, e se por exemplo vc precisasse acessar as variáveis dos dois escopos.
var x = 'teste'
1000.times do |i|
var x = 10
puts x if(x == i && x == 'teste')
end
Não há nenhuma clareza no código em ofuscar o escopo de variáveis locais em loops de qqer jeito.