![]() |
Muhammad ibn Musa al-Khwarizmi |
#include <stdio.h> int main() /* Implementação do algoritmo de Euclides */ { int m, n, x, y ; printf(">> ") ; scanf("%d %d", &m, &n) ; x = m ; y = n ; do { if( x > y ) x = x - y ; else if( x < y ) y = y - x ; } while( x != y ) ; printf("mdc(%d,%d) = %d\n", m, n, x) ; return 0 ; }
Na verdade, uma linguagem não pode deixar de se comprometer com algum conjunto de mecanismos primitivos para processar informação. Ao efetuar essa escolha, a linguagem adere a um paradigma de programação particular.
É surpreendente a grande variedade de paradigma de programação que têm sido inventados: PARADIGMAS.
let nAdd (x,y) = x+y ;; nAdd: (int * int) -> int let nAdd3 (x,y,z) = x+y+z ;; nAdd3: (int * int * int) -> int nAdd (3,4) = 7 nAdd3 (2,8,1) = 11Tecnicamente, a função nAdd tem apenas um parâmetro, de tipo int*int. Mas claro, através desse único parâmetro conseguimos passar duas unidades de informação.
let cAdd x y = x+y ;; cAdd: int -> int -> int let cAdd x y z = x+y+z ;; cAdd: int -> int -> int -> int cAdd 3 4 = 7 cAdd 2 8 1 = 11Escrever funções curried não tem nada que saber: basta separar os parâmetros por espaços em branco, na cabeça de cada função. Contudo o tipo destas funções afigura-se surpreendente para quem o observa pela primeira vez. Isso é resultado da representação interna das funções em OCaml. Segue-se a explicação...
Por exemplo, a função
let cAdd x y = x+y ;;é internamente convertida em:
let cAdd = fun x -> (fun y -> x+y) ;;Repare na engenhosa a ideia que está por detrás do esquema de tradução.
Vejamos mais alguns exemplos de tradução, lado a lado:
let cAdd x y z = x+y+z ;; let cAdd = fun x -> (fun y -> (fun z -> x+y+z)) ;; let f x = x+1 ;; let f = fun x -> x+1 ;; let nAdd (x,y) = x+y ;; let nAdd = fun (x,y) -> x+y ;;
nAdd (2,3) = (fun (x,y) -> x+y) (2,3) = 2 + 3 = 5 cAdd 2 3 = (fun x -> (fun y -> x+y)) 2 3 = (fun y -> 2+y) 3 = 2 + 3 = 5
let succ = cAdd 1 ;; succ: int -> int
let f x y = x + y ;; (* formato externo preferido *) let f x = (fun y -> x+y) ;; (* formato externo *) let f = (fun x y -> x+y) ;; (* formato externo *) let f = (fun x -> (fun y -> x+y)) ;; (* formato interno *)Todas são convertidas para a mesma forma interna.
Concretamente, numa linguagem funcional as funções podem ...
let compose f g = fun x -> f (g x) ;; compose : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'bTambém se pode escrever:
let compose f g x = f (g x) ;;Exemplo 2. Função para converter do formato não-curried para o formato curried.
let curry f = fun x -> fun y -> f (x,y) ;; curry : ('a * 'b -> 'c) -> 'a -> 'b -> 'cTambém se pode escrever:
let curry f x y = f (x,y) ;;Exercício: Escrever a função inversa uncurry.
Exercício: Que funções são as seguintes e quais os seus tipos:
Um conjunto é uma entidade cuja principal característica é a possibilidade de se poder saber se um valor lhe pertence ou não lhe pertence. Assim vamos representar cada conjunto por uma função booleana. Essa função, quando aplicada a um valor produz true se esse valor pertence ao conjunto e false se não pertence. Trata-se da chamada função característica do conjunto.
Exemplo 4. Estrutura de dados com funções: lista de funções.
let mylist = [(fun x -> x+1); (fun x -> x*x)] ;;
# (fun x -> x+1) = (fun x -> x+1) ;; Exception: Invalid_argument "equal: functional value".