O operador pré / pós incremento / decremento ( ++
e --
) é uma sintaxe de linguagem de programação bastante padrão (pelo menos para linguagens procedurais e orientadas a objetos).
Por que Ruby não os suporta? Entendo que você poderia realizar a mesma coisa com +=
e -=
, mas parece estranhamente arbitrário excluir algo assim, especialmente porque é tão conciso e convencional.
Exemplo:
i = 0 #=> 0
i += 1 #=> 1
i #=> 1
i++ #=> expect 2, but as far as I can tell,
#=> irb ignores the second + and waits for a second number to add to i
Entendo que Fixnum
é imutável, mas se é +=
possível instanciar um novo Fixnum
e configurá-lo, por que não fazer o mesmo ++
?
A consistência nas tarefas que contêm o =
personagem é a única razão para isso ou estou faltando alguma coisa?
ruby
operators
language-design
Andy_Vulhop
fonte
fonte
+=
operador. No IC, tente usar++
/--
apenas dentro de condicionais, preferindo o mais literal+=
/-=
em uma instrução básica. Provavelmente porque eu aprendi Python (muito tempo depois C embora ...)Respostas:
Aqui está como Matz (Yukihiro Matsumoto) explica isso em um tópico antigo :
fonte
+=
/-=
ok? E não1+=1
seria tão ruim assim? (Falha no IRB comsyntax error, unexpected ASSIGNMENT
)+=
substitui o objeto que a variável faz referência por um objeto totalmente novo. Você pode verificar isso ligandoi.object_id
antes e depoisi+=1
. Por que isso seria tecnicamente mais complicado++
?++
método).Uma razão é que até agora todo operador de atribuição (ou seja, um operador que altera uma variável) possui um
=
. Se você adicionar++
e--
, esse não é mais o caso.Outra razão é que o comportamento
++
e--
muitas vezes confunde as pessoas. Caso em questão: o valor de retorno doi++
seu exemplo seria realmente 1, não 2 (o novo valor dei
seria 2, no entanto).fonte
=
neles" parece fazer sentido. Eu posso respeitar isso como uma adesão feroz à consistência.a.capitalize!
não reatribuia
, irá alterar a string a quea
se refere. Outras referências à mesma sequência serão afetadas e, se você fizer issoa.object_id
antes e depois da chamadacapitalize
, obterá o mesmo resultado (nenhum dos quais seria verdadeiro se você o fizessea = a.capitalize
).a.capitalize!
afetará outras referências à mesma string. Essa é uma diferença muito prática. Por exemplo, se você temdef yell_at(name) name.capitalize!; puts "HEY, #{name}!" end
e então o chama assim:,my_name = "luis"; yell_at(my_name)
o valor demy_name
será agora"LUIS"
, enquanto que não seria afetado se você tivesse usadocapitalize
e uma atribuição.Não é convencional em idiomas OO. De fato, não existe
++
no Smalltalk, a linguagem que cunhou o termo "programação orientada a objetos" (e a linguagem pela qual Ruby é mais fortemente influenciada). O que você quer dizer é que é convencional em C e linguagens que imitam muito o C. Ruby tem uma sintaxe parecida com o C, mas não é servil ao seguir as tradições do C.Por que não está em Ruby: Matz não queria. Essa é realmente a razão final.
O motivo de tal coisa não existir no Smalltalk é porque faz parte da filosofia dominante da linguagem que atribuir uma variável é fundamentalmente um tipo de coisa diferente do que enviar uma mensagem para um objeto - está em um nível diferente. Esse pensamento provavelmente influenciou Matz na criação de Ruby.
Não seria impossível incluí-lo no Ruby - você poderia escrever facilmente um pré-processador que transforma tudo
++
em+=1
. mas evidentemente Matz não gostou da idéia de um operador que fizesse uma "tarefa oculta". Também parece um pouco estranho ter um operador com um operando inteiro oculto dentro dele. Nenhum outro operador no idioma funciona dessa maneira.fonte
Eu acho que há outra razão:
++
no Ruby não seria remotamente útil como no C e seus sucessores diretos.A razão é a
for
palavra-chave: embora seja essencial em C, é principalmente supérfluo em Ruby. A maior parte da iteração no Ruby é feita através de métodos Enumerable, comoeach
emap
ao iterar através de alguma estrutura de dados eFixnum#times
método, quando você precisa repetir um número exato de vezes.Na verdade, até onde eu vi, na maioria das vezes
+=1
é usado por pessoas recém-migradas para o Ruby a partir de idiomas no estilo C.Em resumo, é realmente questionável se métodos
++
e--
seriam usados.fonte
Acho que o raciocínio de Matz para não gostar deles é que ele realmente substitui a variável por uma nova.
ex:
Agora, se alguém pudesse convencê-lo de que deveria chamar #succ! ou não, isso faria mais sentido e evitaria o problema. Você pode sugerir isso no ruby core.
fonte
Você pode definir um
.+
operador de auto incremento:Mais informações sobre "variável de classe" estão disponíveis em " Variável de classe para incrementar objetos Fixnum ".
fonte
E nas palavras de David Black de seu livro "The Rubyist Well-Grounded":
fonte
Não foi possível obter isso adicionando um novo método ao fixnum ou à classe Integer?
retorna 2
Os métodos "destrutivos" parecem ser anexados
!
para avisar possíveis usuários; portanto, adicionar um novo método chamadonext!
faria praticamente o que foi solicitado, ou seja.retorna 2 (uma vez que o numb foi incrementado)
Obviamente, o
next!
método precisaria verificar se o objeto era uma variável inteira e não um número real, mas isso deveria estar disponível.fonte
Integer#next
já existe (mais ou menos), exceto que é chamadoInteger#succ
(em vez de 'sucessor'). MasInteger#next!
(ouInteger#succ!
) seria um absurdo: lembre-se de que os métodos funcionam em objetos , não em variáveis ; portanto,numb.next!
seria exatamente igual a1.next!
, ou seja, mudaria 1 para ser igual a 2 .++
seria marginalmente melhor, pois poderia ser um açúcar sintático para uma tarefa, mas pessoalmente prefiro a sintaxe atual em que todas as tarefas são concluídas=
.Integer#pred
recuperar o antecessor.Verifique estes operadores da família C no irb de Ruby e teste-os:
fonte
(x++)
é uma declaração inválida no Ruby.