R é uma linguagem de tipagem dinâmica, por isso, em geral, não é necessário especificar o tipo de uma variável. O tipo predefinido é numeric, habitualmente implementado como um número de vírgula flutuante de precisão dupla. Para forçar a utilização de inteiros de 32 bits, usa o sufixo L (abreviatura de Long).
Obter o "tipo" de um objeto é (por razões históricas) potencialmente confuso.
As funções typeof() e class() são semelhantes, mas podem devolver resultados ligeiramente diferentes:
typeof(50)
#> [1] "double" # more specific: an implementation detail
typeof(50L)
##> [1] "integer"
class(50)
#> [1] "numeric" # less specific: ignores implementation details
class(50L)
#> [1] "integer"
Também podes encontrar referências a mode(), que é semelhante a typeof().
Ignora mode() e storage.mode().
São disponibilizados apenas para compatibilidade com versões anteriores.
O operador de atribuição preferido é <-.
Se estiveres a trabalhar no RStudio, podes introduzi-lo com o atalho de teclado Alt-minus.
x <- 42
avogadro <- 6.02e23
mystr <- "Hello, World!"
Usar = em vez de <- funciona muitas vezes, mas não sempre, e é desaconselhado por ser um mau estilo.
Os operadores são, na sua maioria, semelhantes aos de muitas outras linguagens, embora %% e %/% sejam mais invulgares.
Esta sintaxe com % é uma forma de chamar operadores infixos implementados como macros.
2 + 3 # 5
2 - 3 # -1
2 * 3 # 6
2 / 3 # 0.6666667
8 %/% 3 # 2 (integer division)
8 %% 3 # 2 (remainder)
2 ^ 3 # 8 (exponential)
Em R, # inicia um comentário de uma só linha.
Não existe uma sintaxe separada para comentários com várias linhas.
Para definir uma função:
squareit <- function(x) {
x * x
}
As funções podem ter zero ou mais argumentos, separados por vírgulas.
Os parênteses () são necessários com function(), mesmo que não haja parâmetros.
Podem especificar-se valores predefinidos para os argumentos de uma função, mas estes têm de vir depois de quaisquer argumentos sem valores predefinidos, e usar = e não <- para atribuir o valor predefinido.
Como exemplo bastante inútil:
squareit <- function(x = 42) {
x * x
}
squareit()
#> [1] 1764
As chavetas { } não são estritamente necessárias para corpos de função de uma só linha, mas incluí-las é considerado bom estilo.
R devolve automaticamente o valor final de uma função, como nos exemplos acima.
return() pode ser usado em qualquer parte do corpo da função para tornar explícito um valor devolvido.
Devolve imediatamente o valor especificado e termina a função sem executar as restantes expressões do corpo da função.
Uma chamada explícita a return() só costuma ser necessária se quisermos sair da função mais cedo e devolver um valor específico por alguma razão.
Um exemplo poderá ser dentro de uma cláusula if-else.
No entanto, alguns programadores preferem devoluções explícitas por uma questão de estilo de código.
Chamar uma função é igual ao que acontece em muitas outras linguagens:
squareit(3)
#> [1] 9
Vamos ver em Conceitos futuros que o resultado 9 é, na verdade, um vetor de comprimento 1 e não um número escalar.
Daí a inclusão de [1], para indicar que este é o início do vetor.
is.vector(9)
#> [1] TRUE
A maior parte das coisas em R é algum tipo de vetor!
A consola de R mostraria o exemplo acima como:
> squareit(3)
[1] 9
Os documentos deste plano de estudos seguem, na sua maioria, a convenção utilizada em vários manuais de R, removendo o prompt e comentando o resultado. Assim, é mais fácil copiar e colar exemplos de código na consola e executá-los.