Aula 03 - Memória, variáveis e constantes

Memória

Os computadores atuais se baseiam numa arquitetura conhecida como Arquitetura de von Neumann (pronuncia-se Nôimánn), desenhada pelo matemático húngaro John von Neumann, que consiste nos seguintes componentes: memórias, unidade aritmética e lógica, unidade central de processamento, unidade de controle, além de interfaces de entrada e saída de dados (TANENBAUM, 2007).

Nesta aula, vamos nos ater a discutir sobre a memória do computador e sobre como usá-la a fim de construir programas de computador mais sofisticados. É interessante notar como as memórias de computador foram desenvolvidas baseadas em dois tipos de memórias do cérebro humano: a memória de curto prazo e a memória de longo prazo.

Assim como as memórias do cérebro humano, as memórias de computador são mecanismos que permitem ao computador guardar informações de forma temporária ou permanente. As memórias temporárias, também conhecidas como memória principal, são equivalentes às nossas memórias de curto prazo, que guardam informações temporariamente. Um exemplo desse tipo de memória é a RAM. Quando o fornecimento de energia da memória temporária é cortado, os dados guardados nela são perdidos. Mas, qual seria a utilidade de uma memória que perde informações? A resposta para essa pergunta é simples: algumas informações não precisam ser guardadas de forma permanente. Por exemplo: quando você "decora" o endereço de um colega para ir visitá-lo, você só precisa dessa informação até chegar a casa dele. Você não precisa dessa informação para o resto da sua vida.

Já as memórias permanentes, também conhecidas como memória secundária ou de massa, são equivalentes às nossas memórias de longo prazo e guardam informações permanentemente. As informações guardadas nesse tipo de memória só serão descartadas se você excluí-las. Um exemplo desse tipo de memória é o HD (Hard Disk). Quando o fornecimento de energia é cortado, os dados guardados nesse tipo de memória são preservados. Conforme mencionado anteriormente, esse tipo de memória equivale à nossa memória de longo prazo, que guarda informações por longos períodos de tempo.

É interessante notar que qualquer informação guardada na memória permanente precisa, necessariamente, passar pela memória temporária antes, ou seja, primeiro, a informação é guardada na memória temporária e só depois ela é copiada para a memória permanente. Esse processo também acontece no nosso cérebro: quando estamos aprendendo algo, as informações são guardadas, inicialmente, na nossa memória temporária, portanto, são mais passíveis de esquecimento. Depois, à medida que estudamos e nos esforçamos mais para aprender, as informações passam da memória temporária para a memória permanente, e, a partir daí, podemos dizer que, de fato, aprendemos.

Existe um filme chamado "Como se fosse a primeira vez", estrelado por Adam Sandler e Drew Barrymore, que ilustra, de forma bem-humorada, a diferença entre a memória temporária e a memória permanente. No enredo do filme, Lucy (Drew Barrymore) sofreu um acidente que afetou seu cérebro de forma que ela não consegue mais reter novas informações em sua memória permanente. Ela armazena novas informações apenas na sua memória temporária, que é apagada quando ela dorme. O bom humor do filme ocorre quando Henry (Adam Sandler) tenta conquistá-la, mesmo sabendo que, no dia seguinte, ela não se lembrará dele.

Variáveis

Agora vamos aprender como guardar informações na memória temporária do nosso computador, ou seja, na nossa memória RAM. As variáveis são o mecanismo usado para guardar informações na memória temporária, ou seja, nosso programa pode guardar dados dentro das variáveis, que ficarão armazenadas na memória temporária. Vale salientar que esses dados são perdidos quando o nosso programa encerrar ou o computador for desligado.

Em Ruby, criar uma variável e armazenar um dado dentro dela é muito simples. Abra o IRB, digite o código abaixo e aperte ENTER.

  
    irb(main):001:0> numero = 3
    => 3
  

No exemplo anterior, criamos uma variável chamada numero (sem acento) e armazenamos o valor 3 dentro dela.

O primeiro detalhe a ser percebido no exemplo anterior é que as variáveis possuem nomes. Os nomes são usados para diferenciar as variáveis, portanto, lembre-se bem dos nomes das variáveis que você utilizou. Ao nomear uma variável, você precisa seguir algumas regras básicas.

Tabela 1 - Palavras reservadas pela linguagem Ruby
__ENCODING__ __LINE__ __FILE__ BEGIN END alias and begin break
case class def defined? do else elsif end ensure
false for if in module next nil not or
redo rescue retry return self super then true undef
unless until when while yield

Ao longo desse livro, iremos estudar e conhecer a maioria das palavras reservadas. Abaixo você pode conferir alguns exemplos válidos de criação de variáveis.

  
    irb(main):001:0> numero = 2
    => 2
    irb(main):002:0> nome_completo = "Adam Sandler"
    => "Adam Sandler"
    irb(main):003:0> idade = 26
    => 26
    irb(main):004:0> preco_promocional = 2.33
    => 2.33
  

Perceba que estamos usando nomes de variáveis que indicam o que está guardado nelas. É muito comum ver aqueles que estão aprendendo a linguagem usando péssimos nomes para variáveis, conforme ilustramos abaixo.

  
    irb(main):001:0> x = 2
    => 2
    irb(main):002:0> z = "Adam Sandler"
    => "Adam Sandler"
    irb(main):003:0> z2 = 26
    => 26
    irb(main):004:0> x1 = 2.33
    => 2.33
  

Os nomes das variáveis ilustrados no exemplo anterior não indicam o que elas estão guardando e, portanto, poderão confundi-lo ao construir seus programas.

Outro detalhe a ser percebido, nos exemplos anteriores, é que nós não apenas criamos novas variáveis, mas também guardamos valores dentro delas. Para guardar um valor dentro de uma variável, nós usamos o sinal de atribuição, que é o sinal de igual (=). Veja o exemplo abaixo.

  
    irb(main):001:0> numero = 2
    => 2
  

No exemplo acima, criamos uma variável chamada numero que armazena o número inteiro 2.

Você se lembra dos métodos puts e gets.chomp que aprendemos na aula anterior? Eles são comandos de entrada e saída de dados e também podem ser usados com variáveis! Observe o próximo exemplo.

  
    irb(main):001:0> numero = 2
    irb(main):002:0> puts numero
    2
    => nil
  

No exemplo acima, criamos uma variável chamada numero, armazenamos o valor 2 dentro dela e, em seguida, usamos o método puts para exibir o valor da variável na tela.

Como permitir que o usuário digite um dado no teclado e essa informação seja guardada numa variável? Observe o próximo exemplo.

  
    irb(main):002:0> nome = gets.chomp
    Drew Barrymore
    => "Drew Barrymore"
    irb(main):003:0> puts nome
    "Drew Barrymore"
    => nil
  

Na primeira linha do exemplo anterior, usamos os métodos gets.chomp para permitir que o usuário digite o seu nome. Os métodos gets.chomp irão retornar (devolver como resultado) o valor digitado pelo usuário (uma String), e esse valor será guardado na variável nome. Na quarta linha do exemplo, usamos o método puts para exibir o valor guardado na variável nome, que será o nome digitado por você. Agora observe o exemplo abaixo.

  
    irb(main):001:0> idade = gets.chomp
    29
    => 29
    irb(main):002:0> idade_em_10_anos = idade + 10
    TypeError: no implicit conversion of Fixnum into String
    from (irb):51:in `+’
    from (irb):51
    from C:/Ruby22-x64/bin/irb:11:in `<main>’
  

Algo deu errado. Você consegue perceber por quê? Na aula anterior, vimos que o retorno, ou seja, o resultado dado pelos métodos gets.chomp é uma String. Portanto, apesar do usuário digitar um valor numérico (sua idade), essa informação será guardada na variável idade como uma String. Quando tentamos calcular a idade do usuário daqui a 10 anos, tentamos somar a variável idade (que guarda uma String) com o valor inteiro 10 e, como já vimos na aula passada, não é possível somar uma String com um número. Portanto, para que o exemplo anterior funcione, é preciso converter o valor digitado pelo usuário para inteiro, e, só depois disso, poderemos somá-lo com 1010. Observe abaixo o exemplo corrigido.

  
    irb(main):001:0> idade = gets.chomp.to_i
    29
    => 29
    irb(main):002:0> idade_em_10_anos = idade + 10
    => 39
    irb(main):003:0> puts idade_em_10_anos
    39
    => nil
  

Lembra-se do método to_i que aprendemos na aula anterior? Ele está sendo usado na primeira linha do exemplo para converter o retorno (resultado) do método chomp, que é uma String, em um número inteiro. Portanto, o valor guardado na variável idade é um inteiro. Agora nós podemos fazer a operação de soma entre a variável idade e o valor 10.

Em alguns momentos, essa questão dos tipos das variáveis, ou seja, os tipos de dados que as variáveis guardam, pode ficar confusa. Isso ocorre porque Ruby é uma linguagem de "tipagem" dinâmica. Lembra que mencionamos isso na nossa primeira aula? Sendo o Ruby uma linguagem de tipagem dinâmica, você não precisa definir qual tipo de dado será guardado na variável ao criá-la. Um outro exemplo de tipagem é a estática, que exige que o programador, ao criar uma variável, informe qual tipo de dado será guardado nela. Observe o exemplo de código abaixo escrito na linguagem Java. Não tente fazer isso no IRB, pois esse exemplo está escrito em outra linguagem.

  
    int idade = 29;
  

Quais diferenças você consegue perceber entre a criação de uma variável em Java e em Ruby? A primeira delas é a presença do int antes do nome da variável. Isso indica que essa variável irá guardar um número inteiro, portanto, ela não será capaz de guardar outros tipos de dados. A segunda diferença é a presença do ponto e vírgula no final da linha. Em Java, o final de cada instrução deve ser marcado com ponto e vírgula.

Portanto, em linguagens de tipagem dinâmica como Ruby, você não precisa definir o tipo da variável ao criar uma. Já em linguagens de tipagem estática como Java, você precisa definir o tipo da variável ao criá-la. Em Ruby, você pode fazer algo do tipo:

  
    irb(main):001:0> variavel = 3
    => 3
    irb(main):002:0> variavel = "Ruby usa tipagem dinâmica"
    => "Ruby usa tipagem din\x83mica"
  

Observe que usamos a mesma variável para guardar um número inteiro e, em seguida, guardar uma String. Porém, toda essa flexibilidade tem um preço: em alguns momentos, pode ficar difícil saber qual tipo de dado está sendo guardado em cada variável. Para atenuar esse problema, existem meios de descobrir qual tipo de dado está guardado em cada variável. Observe o exemplo abaixo.

  
    irb(main):001:0> variavel_desconhecida = 20
    => 20
    irb(main):002:0> variavel_desconhecida.class
    => Fixnum
  

No exemplo de código acima, usamos o método class para descobrir o tipo de dado guardado na variável variavel_desconhecida. Perceba que o retorno (resultado) do método foi Fixnum, que é um tipo de dado inteiro. Observe mais exemplos abaixo.

  
    irb(main):001:0> variavel_desconhecida = "Tipo de dado desconhecido"
    => "Tipo de dado desconhecido"
    irb(main):002:0> variavel_desconhecida.class
    => String
  

Atividade 3.1

Usando o IRB, crie uma variável chamada nome e atribua o seu nome a ela. Crie outra variável chamada idade e atribua a sua idade a ela. Em seguida, mostre os valores de nome e idade na tela.

Atividade 3.2

Usando os métodos apresentados nesta aula, descubra os tipos de dados armazenados nas variáveis nome e idade criadas na Atividade 3.1.

Constantes

Uma constante é como uma variável, ou seja, um espaço na memória do computador na qual é possível guardar informações. Nas variáveis, esse valor pode mudar, enquanto nas constantes esse valor, tecnicamente, não pode ser alterado (por isso o nome). Contudo, o interpretador Ruby permite que você altere valores de constantes, mas ele dará um aviso para alertá-lo que você está alterando o valor de uma constante (GURU-SP, 2015).

Para criar uma constante, basta criar uma variável com a primeira letra maiúscula. Observe o exemplo abaixo.

  
    irb(main):001:0> Minha_constante = 2
    => 2
    irb(main):001:0> Minha_constante = 3
    (irb):3: warning: already initialized constant Minha_constante
    (irb):1: warning: previous definition of Minha_constante was here
  

No exemplo anterior, criamos uma constante chamada Minha_constante, na primeira linha, e atribuímos o valor 2 a ela. Em seguida, na linha 3, alteramos o valor da constante para 3 e recebemos o warning (alerta) do Ruby dizendo que a constante já havia sido criada e que o valor dela foi definido na linha 1.

Em Ruby e em várias outras linguagens de programação existem as convenções. Convenções são normas que são adotadas pelos desenvolvedores para melhor organizar o código. Mas as convenções não são regras da linguagem, portanto se você não segui-las, seu código funcionará perfeitamente, contudo, ele não irá atender a essa convenção (acordo). É uma boa prática de programação seguir todas as convenções da linguagem, e aqui vai uma delas: por convenção, as constantes são escritas com todas as letras em maiúsculas. Por exemplo: MINHA_CONSTANTE, IDADE, NOME, etc.

Atividade 3.3

Crie uma constante chamada IDADE e atribua a sua idade a ela. Em seguida, mostre na tela o valor da constante criada por você usando o método puts.

Referências

DOC, R. Keywords. Ruby Doc. 2015. Disponivel em: http://ruby-doc.org/core-2.2.3/doc/keywords_rdoc.html. Acesso em: 24 out. 2015.

FOUNDATION, P. S. Lexical Analysis. PyDoc. 2015. Disponivel em: http://ruby-doc.org/core-2.2.3/doc/keywords_rdoc.html. Acesso em: 13 out. 2015.

GURU-SP. Constantes. Tutorial de Ruby do GURU-SP. 2015. Disponivel em: http://guru-sp.github.io/tutorial_ruby/constantes.html. Acesso em: 27 out. 2015.

TANENBAUM, A. S. Organização Estruturada de Computadores. São Paulo: Pearson Prentice Hall, 2007.