Introdução a Funções Funções Matemáticas • função é uma relação de um ou vários valores de argumentos de entrada em um ÚNICO resultado de saída. y z Fig I x f(x) = x2 • Fig II z = f(x,y) = x2+y2 x = 2 f(x) = 4 x y x=2 z=8 y=2 O conjunto de todos os valores de entrada de uma função é chamado de DOMÍNIO da função. O conjunto de todos os resultados é chamado de IMAGEM da função. Normalmente a IMAGEM é um subconjunto de um conjunto de resultados possíveis chamado de CONTRADOMÍNIO. A notação é: f: DomínioContradomínio. Para Fig I temos f: R R e para Fig II temos f: R R R , onde R é o conjunto dos números reais. Domínio f Contradomínio Funções e Procedimentos • • Uma função matemática lembra uma máquina que recebe valores para os seus argumentos de entrada, processa-os e retorna um valor como saída (Figs A e B). Em computação nós estendemos este conceito permitindo que estas “máquinas” produzam “efeitos colaterais” (como escrever uma mensagem no papel) (Fig. C). Eventualmente, até admitimos que a “máquina” não retorna valor (Fig. D) Fig A • Fig B Fig C Fig D Neste caso, podemos dizer que as máquinas deixam de ser equivalentes a funções matemáticas (i.e. deixam de ser FUNCIONAIS) e passam a ser PROCEDIMENTAIS, no sentido de que seguem um procedimento, claro, sequencial e com possíveis efeitos colaterais que afetam o ambiente. Funções e Procedimentos • • • Em C, um procedimento (retornando ou não valores) continua sendo chamado de função (function). “Funções” que não retornam valor não podem ser usadas em expressões ou como argumentos de outra função. g(f(1,2), 2) e 10+f(1,2) g(h(1,2), 2) , pois h não retorna valor – Por exemplo, é possível termos – mas, não é possível !!! Em C, o comando return define o que retorna float g(float x, float y) { float z = x*x + y*y; printf(“%f^2 + %f^2 igual a %f\n“,x,y,z); return z; } void h(float x, float y) { float z = x*x + y*y; printf(“%f^2 + %f^2 igual a %f\n“,x,y,z); } • A sintaxe é: tipo_de_retorno nomeFuncao(lista_de_argumentos) { corpo da função } Usando Funções • Funções em C recebem VALORES (e não nomes de variáveis) e retornam VALORES. float g(float x, float y) { float z = x*x + y*y; printf("%f^2 + %f^2 igual a %f\n",x,y,z); return z; } 3 4 int main(void) { float z = 1.0; float w = 2.0; printf("%f\n",10+g(z,w)); /* imprime 15 */ return 0; } 1 Numa área local e isolada de memória, x recebe o valor de 1.0 e y recebe o valor de 2.0 e g retorna o valor calculado de 5.0. Ao terminar, esta memória local é totalmente apagada ! 2 g é chamada com o primeiro argumento igual a 1.0 e o segundo argumento igual a 2.0 Usando Funções • Como são valores que são passados para a função, ela desconhece as variáveis que continham estes valores. Os nomes podem coincidir, mas são variáveis distintas. float dobra(float x) { x = 2 * x; return x; } int main(void) { float x = 5.0; printf("%f\n", dobra(x)); /* imprime 10.0 */ printf("%f\n", x); /* imprime 5.0 */ return 0; } • • são variáveis distintas o valor de x permanece inalterado !! Há uma maneira de fazer com que uma função em C altere o valor de uma variável que pertence ao código que a chamou. Este “efeito colateral” a torna um PROCEDIMENTO. Isto será visto mais adiante. A possibilidade de alterar valores de variáveis que pertencem a outras funções, torna as funções em C muito poderosas, mas também requerem atenção redobrada (pois alteram o ambiente). Considerações Importantes • Algumas linguagens de programação, chamadas LINGUAGENS FUNCIONAIS, como Lisp e Haskell, consideram o ato de computar como sendo o ato de avaliar funções matemáticas, sem que o estado do mundo (e.g. variáveis) seja alterado. Lisp, por exemplo, é uma linguagem que pode ser entendida como sendo simplesmente expressões dentro de expressões que sempre retornam valor. Em oposição, temos linguagens de programação denominadas de Linguagens Procedimentais (tais como C, C++ e Java), que definem PROCEDIMENTOS, isto é: comandos imperativos em uma ordem específica que podem alterar o estado do mundo (e.g. mudanças de valores de variáveis ou efeitos colaterais de uma maneira geral). Porém, todas as linguagens permitem uma fuga para o estilo que lhe é oposto por natureza. Por exemplo, podemos escrever procedimentos em Lisp e funções matemáticas em C. • Procedimentos são instrumentos poderosos, mas devem ser usados com cautela, porque as mudanças do estado do mundo podem ser sutis, silenciosas, e erros catastróficos podem passar desapercebidos. • ... Programar é uma arte poderosa e iniciantes são “aprendizes de feiticeiro” que devem treinar bastante todas as técnicas !