10  Funções

Status 🟦🟨🟨

10.1 Criando Funções

Funções podem ser criadas através do comando function.

fnSomar <- function(param1, param2) {
  param1 + param2
}

fnSomar(5, 8)
[1] 13

Para visualizar o código de uma função podemos usar seu nome sem os parênteses.

fnSomar
function(param1, param2) {
  param1 + param2
}

10.1.1 Argumentos - Valores Padrão

10.2 Função x Ambiente

As funções possuem seus próprios ambientes. Abaixo uma função criada para exibir seu ambiente e seu ambiente ‘pai’.

fnExibirEnvs <- function() {
  print('Ambiente atual:')
  print(environment())
  
  print(paste(
    'Ambiente Pai:', 
    environmentName(parent.env(environment()
                               ))))
}

fnExibirEnvs()
[1] "Ambiente atual:"
<environment: 0x0000023b2888dd60>
[1] "Ambiente Pai: R_GlobalEnv"

10.2.1 Objetos no Ambiente da Função

Objetos que são criados dentro de uma função existem apenas dentro do ambiente desta função. Abaixo um exemplo de variável criada dentro do ambiente da função e que não é acessível no GlobalEnv.

fnTeste <- function(){
  y <- 15
  x <- 80
  ls()
}

fnTeste()
[1] "x" "y"
y
Error in eval(expr, envir, enclos): objeto 'y' não encontrado

Objetos que existam no ambiente corrente não são alterados caso por estarem dentro do ambiente de fuma função. A variável x é inicializada com valor 10 no ambiente corrente. Ela pode ser acessada pela função mesmo não sendo informada em algum argumento.

x <- 10

fnTeste2 <- function(){
  y <- 15
  x + y
}

fnTeste2()
[1] 25
y
Error in eval(expr, envir, enclos): objeto 'y' não encontrado
x
[1] 10

Entretando, caso a variável x seja alterada no ambiente da função ela não é alterada no ambiente corrente.

x <- 10

fnTeste3 <- function(){
  y <- 15
  x <- 80
  x + y
}

fnTeste3()
[1] 95
x
[1] 10

10.2.1.1 Operador de Super Atribuição (<<-)

Usando o operador de super atribuição <<- é possível alterar objetos que estejam fora do ambiente de uma função. Neste caso a variável x é atualizada no ambiente que está acima do ambiente da função. A variável y continua não existindo fora da função, porém agora a variável x é atualizada em ambos ambientes.

ls(envir = globalenv())
[1] "fnExibirEnvs" "fnSomar"      "fnTeste"      "fnTeste2"     "fnTeste3"    
[6] "repo"         "x"           
x
[1] 10
fnTeste4 <- function(){
  y <- 15
  x <<- 80
  x + y
}

fnTeste4()
[1] 95
y
Error in eval(expr, envir, enclos): objeto 'y' não encontrado
x
[1] 80

Apesar de, neste caso, produzirem o mesmo retorno, as funções fnTeste3 e fnTeste4 impactam de formas distintas o ambiente do R.

10.3 Retorno

Na criação de funções, é possível utilizar o comando return a fim de definir o que será retornado pela função.

fnRetorno <- function(){
  return('Este é o retorno da função!')
}
fnRetorno()
[1] "Este é o retorno da função!"

10.4 Recursividade

Como outras linguagens de programação, R permite o uso recursivo de funções.

fnRecursividade <- function(x){
  if(x > 100) return('X ultrapassou 100. Fim!')
  x <- x + 1
  print(paste('Valor atual de x:', x))
  fnRecursividade(x)
}

fnRecursividade(95)
[1] "Valor atual de x: 96"
[1] "Valor atual de x: 97"
[1] "Valor atual de x: 98"
[1] "Valor atual de x: 99"
[1] "Valor atual de x: 100"
[1] "Valor atual de x: 101"
[1] "X ultrapassou 100. Fim!"

10.4.1 Buscar Ambiente Pai (Recursivamente)

Abaixo função que busca recursivamente os ambientes e seus ‘pais’ até que se chege no ‘último’ ambiente, o R_EmptyEnv.

fnBuscarEnvsPai <- function(ambiente, nivel = 1){
 
    if(environmentName(ambiente)=="R_EmptyEnv"){
    return ('Ambiente informado é R_EmptyEnv. Fim da busca.')
    }
    
    marcacao <- ''
    for (i in 1:nivel){
      
      marcacao <- paste0(' ', marcacao)
    }
    
    writeLines(paste0(marcacao, '|-- ', environmentName(parent.env(ambiente))))

    nivel <- nivel + 1
    fnBuscarEnvsPai(parent.env(ambiente), nivel = nivel)

}
fnBuscarEnvsPai(globalenv())
 |-- package:stats
  |-- package:graphics
   |-- package:grDevices
    |-- package:utils
     |-- package:datasets
      |-- package:methods
       |-- Autoloads
        |-- base
         |-- R_EmptyEnv
[1] "Ambiente informado é R_EmptyEnv. Fim da busca."

10.5 Funções Genéricas

Funções genéricas são funções que contém métodos associados. Os métodos são chamados de acordo com a classe do objeto informado.

Por exemplo a função print possui diversos métodos associados. Quando um data.frame é informado como argumento o R chama a função print.data.frame, ao passo que se o argumento da função for uma data o método invocado é print.Date.

mtcars[1:2, 1:5] |> print.data.frame()
              mpg cyl disp  hp drat
Mazda RX4      21   6  160 110  3.9
Mazda RX4 Wag  21   6  160 110  3.9
Sys.Date() |> print.Date()
[1] "2024-10-11"
# o mesmo que
mtcars[1:2, 1:5] |> print()
              mpg cyl disp  hp drat
Mazda RX4      21   6  160 110  3.9
Mazda RX4 Wag  21   6  160 110  3.9
Sys.Date() |> print()
[1] "2024-10-11"

10.6 Operadores Unários

A operador de soma + é na verdade uma função e é em geral utilizado na forma de operador unário, ou seja, recebe os valores da direita e da esquerda como seus argumentos. Veja o código que é reotrnado quando a função é chamada sem informação de argumentos e parênteses:

`+`
function (e1, e2)  .Primitive("+")

Você poderia usar a função de somar de outra formacom a função do.call ou mesmo chamando esta com uso de cráses. Obviamente não é a forma mais sucinta, mas serve para demosntrar que + não passa de uma função como as demais.

do.call(`+`, list(1,3))
[1] 4
`+`(8,7)
[1] 15

O mais interessante é que você também pode criar funções para serem usadas na forma de operador unário. Para isto basta criá-la com % ao início e ao fim do nome da função. Abaixo as duas formas de uso desta função:

`%fnSomar2%`<- function(x, y){
  x + y
}

10 %fnSomar2% 15
[1] 25
`%fnSomar2%`(2,5)
[1] 7

Grolemund (2014)

Última atualização: 11/10/2024 - 21:50:57