O que é uma função em linguagens de programação

A ideia básica de uma função, implementada em alguma linguagem de programação, é encapsular um código que poderá ser invocado/chamado por qualquer outro trecho do programa. Seu significado e uso é muito parecido com o de funções matemáticas, ou seja, existe um nome, uma definição e posterior invocação à função.

Explicitando o paralelo com a matemática, tomemos como exemplo a função trigonétrica cosseno(x), que é impossível de ser implementada de modo exato em um computador digital, entretanto é viável obter boas aproximações utilizando a série de Taylor. Como examinado na referida página, a série que aproxima a função cosseno próximo à origem é: (1) cos(x) = 1 - x2 /2! + x4 /4! - x6 /6! + x8 /8! + ...

Note que o lado direito da equação (1) é a definição da função e ela está escrita em termos do parâmetro formal x. Ao "chamarmos" a função com parâmetros efetivos, é sobre o valor desses parâmetros que computamos o lado direito da expressão, por exemplo, computar cos(0.1) ou de cos(1.1).

Por que usar o conceito de função?

Assim, implementar códigos com objetivos específicos (como computar o cosseno de qualquer valor) apresentam três grandes vantagens:

  1. Facilita o desenvolvimento (desenvolvimento modular): desenvolve-se um unidade particular, concentrando-se nela, até que ela esteja funcionando com alto grau de confiabilidade;
  2. Organização: o código fica melhor organizado e portanto mais fácil de manter;
  3. Reaproveitamento: sempre que precisar aplicar o código encapsulado em qualquer outro trecho de código (ou noutro código), pode-se utilizar aquele que já foi implementado e é confiável.

Introdução ao uso de funções em C e em Python

Assim, agrupar trechos com objetivos específicos e implementá-los na forma de uma função que ajuda bastante o desenvolvimento e a organização dos códigos em programação.

Do ponto de vista prático, a estrutura básica de uma função em uma linguagem de programação está representada abaixo, com a declaração da função e sua lista de parâmetros formais, seguido de sua invocação (quando providenciamos os parâmetro efetivos).

Declaração: [enventual tipo de retorno] nome_da_funcao (lista_parametros_formais)
comando1
...
comandoN
return EXP
Uso: var = nome_da_funcao(lista_parametros_efetivos)

A lista de parâmetros pode conter vários nomes de variáveis, geralmente, separadas por vírgula. Por exemplo, se houver necessidade de uma função que realiza vários cálculos com três variáveis pode-se usar como declaração da função algo como: nome_da_funcao (var1, var2, var3).

Parâmetros formais e efetivos

De modo geral, a diferença entre os parâmetros formais e efetivos é que o primeiro corresponde ao nome da variável utilizada dentro da função, enquanto o segundo é o nome da variável que será usado para iniciar o parâmetro formal ao iniciar a execução da função.

Assim durante a execução, ao encontrar uma chamada à função nome_da_funcao, o fluxo de execução segue a partir do código da função. Mas antes de executar a primeira linha de código da função, os valores dos parâmetros efetivos servem para inicializar os parâmetros formais (que são também variáveis locais à função). Após esta inicialização, inicia-se a execução do código da função e geralmente ao final, encontra-se um comando do tipo "retorne devolvendo um valor" (return).

Ilustrando a execução de um trecho de programa com 3 chamadas à mesma função

Suponhamos que precisemos computar o valor da combinação de N tomado k a k, ou seja, C(N,k) = N! / ( k! (N-k)!). Para isso percebe-se que é necessário implementar o cômputo de fatorial que será utilizado 3 vezes. Para facilitar a compreensão, podemos escrever um código com 3 variáveis auxiliares para armazenar, respectivamente, N!, k! e (N-k)!.

Na figura acima ilustra a execução do código para computar C(N,k), com o retângulo à esquerda contendo o código que invoca a função fat e à direita a função fat. Para entender o fluxo de execução destaremos a execução da linha 2, b = fat(k);. Como b = fat(k); é uma atribuição, primeiro computa-se o valor do lado direito da atribuição e só depois atribui-se à variável do lado esquerdo da atribuição o seu valor, ou seja,
  1. primeiro executa-se o cômputo de fat(k), para isso
  2. pega-se o valor do parâmetro efetivo k e usa-o para iniciar o parâmetro formal n da função
  3. então inicia-se a execução da função fat
  4. ao final da função fat, pega-se o valor da variável local ft e
  5. atribui-se este valor para a variável b
  6. então segue-se execução da próxima linha (3).
Vale notar que a execução da atribuição c = fat(N-k); seguirá um fluxo análogo aos 6 passos acima.

Uma vez entendido como é executado uma chamada á função, podemos novamente comparar com o conceito usual de função matemática. Existe a declaração da função, com seu parâmetro formal

   fat : IN -> IN  (nome 'fat', com domínio e imagem nos naturais)
   fat(n) = { 1, se n=0, n x fat(n-1), se n>0 }
E existe o uso da função, como em
   C(N,k) = fat(N) / (fat(k) x fat(N-k)

Exemplo concreto em C e em Python

Para ilustrar o uso e sintaxe de funções em C e em Python, examinemos um exemplo em que implementamos uma função para cômputo do fatorial de um natural n, que será o nome de seu único parâmetro formal.

C Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
int fat (int n) { // define funcao com 1 parametro  
  int ft = 1; int i=1;
  while (i < n) {
    i = i + 1;    
    ft = ft * i;  
    }      
  return ft;
  } // chave indica final da funcao 'fat(...)'
...
// supondo existir neste contexto variaveis: N e k
printf("Combinacao = %f\n", fat(N) / (fat(k) * fat(N-k));
def fat (int n) : # define funcao com 1 parametro  
  ft = 1; int i=1 
  while (i < n) {   
    i = i + 1;     
    ft = ft * i;   
  return ft;
  # Final da funcao 'fat(...)' - em Python,
  # basta a indentacao da proxima linha ser recuada
...
# supondo existir neste contexto variaveis: N e k
print("Combinacao = ", fat(N) / (fat(k) * fat(N-k))
  
Variáveis locais

Note na linha 2 do código acima que são declaradas duas novas variáveis, ft e i, dentro da fução fat. Isso significa que as variáveis ft e i são variáveis locais à função, ou seja, pode-se utilizar variáveis com os mesmos nomes em outras funções sendo que elas não terão qualquer relação. Em particular, na 11 do código em C ou na 9 do código em Python, poderia-se usar uma variável com nome n, ft ou i e ainda assim, está variável não teria qualquer relação com as correspondentes da função fat.

Para que serve função?

A partir do exemplo acima, para cômputo de C(n,k) = n! / (k! (n-k)!), imagine como seria o código para computar a combinção se a linguagem de programação NÂO dispusesse do conceito de funções: em resumo, precisariamos repetir as linhas 2 a 5 (ou 6), que computam fatorial, três vezes. Portanto, o uso de função simplifica o código.

Mas existe uma outra razão para usar funções, que não tão óbvia, a maior facilidade para escrever um programa. E isso se deve à vários fatores, mas principalmente à quebra de um problema maior em vários menores. Isso facilita o desenvolvimento e reduz a incidência de erros de programação.

Por exemplo, pode-se implementar a função separadamente, testando-a até que ela fique pronta e sem erros. Assim, o código fica mais fácil de ser entendido, pois ao usar a função pode-se abstrair, o trecho fica curto (apenas a chamada à função) e pode-se concentrar em saber se o restante do código está correto.

Leônidas de Oliveira Brandão
http://line.ime.usp.br