# Currying e Aplicação Parcial

Currying e aplicação parcial são dois conceitos bastante presentes na programação funcional. Os dois conceitos operam diretamente em funções com o objetivo de alterar seu tipo.

Primeiro vamos entender como exemplificar o tipo de uma função, para isso, vamos utilizar uma sintaxe parecida com a sintaxe utilizada na linguagem F#, também da plataforma .NET.

Em F# o tipo da função é definido por: `parâmetro -> retorno`

Logo, uma função com um parâmetro do tipo `int` e um retorno do tipo `bool` pode ser descrita como: `int -> bool`

Quando houverem múltiplos parâmetros iremos representar aqui (diferente do F#) como: `int, int, int -> bool`

Com isso, estabelecemos uma sintaxe para definir o tipo de uma função.

Agora vamos entender o problema que estas duas técnicas auxiliam na resolução.

A programação funcional é baseada principalmente no conceito de **funções**. Por definição, uma função matemática deve possuir apenas um parâmetro (domínio) e um retorno (alcance).

Logo, isso implicaria que, todas as funções escritas em um código funcional devem conter apenas um parâmetro, como fazer isso? - **Currying**

## Entendendo Currying

O processo de *currying* consiste em quebrar funções de N parâmetros em N funções, onde cada função irá receber apenas um parâmetro e retornar uma nova função que espera os parâmetros restantes.

Logo, uma função de soma, que seria representada por: `int, int -> int`

Ao passar pelo processo de currying pode ser representada por: `int -> int -> int`

Vamos realizar um passo-a-passo do processo de currying em uma função simples, que realiza a soma de 2 valores.

Primeiro vamos definir a função como:

```csharp
Func<int, int, int> add = 
    (value, value2) => value + value2;
```

Podemos utilizar esta função normalmente, conforme código:

```csharp
int result
Func<int, int, int> add = (value, value2) => value + value2;
result = add(2, 3);
//result = 5
```

Ao realizar o processo de currying na função `add` o retorno será uma função do tipo `Func<int, Func<int,int>>`, ou seja, será uma função que receberá um valor inteiro e retornará um nova função esperando o segundo valor inteiro.

Quando esta segunda função receber o último parâmetro ela irá realizar o processamento proposto por `add`.

Veja como podemos realizar o currying com a **Tango**.

```csharp
Func<int, int, int> add = 
    (value, value2) => value + value2;

Func<int, Func<int, int>> addCurried = Currying.Curry(add);
curriedResult = addCurried(2)(3);
//curriedResult = 5
```

Veja que a forma de informar os parâmetros na função `addCurried` é um pouco diferente, isso porque ele gera uma série de funções, onde cada uma espera apenas um parâmetro.

A **Tango** também fornece o `Curry` através de métodos de extensão para os delegates `Func`, portanto ao você também poderá realizar a operação descrita anteriormente da seguinte forma:

```csharp
Func<int, int, int> add =
(value, value2) => value + value2;

//Func<int, Func<int, int>> addCurried = Currying.Curry(add);
Func<int, Func<int, int>> addCurried = add.Curry();
curriedResult = addCurried(2)(3);
//curriedResult = 5
```

## Entendendo a Aplicação Parcial

A aplicação parcial é um pouco diferente do processo de Currying, mas também envolve a questão dos tipos de uma função.

Através da aplicação parcial é possível realizar a chamada de um método sem informarmos todos os parâmetros. Como resultado desta operação, será retornada uma nova função que espera todos os parâmetros restantes.

Veja as diferenças entre Currying e aplicação parcial em uma função que soma três números inteiros.

Esta seria o tipo da função de soma: `int, int, int -> int`

Ao realizar o Currying nesta função o resultado obtido seria: `int -> int -> int -> int`

Neste ponto a aplicação parcial funciona completamente diferente do processo de Currying, poderíamos inclusive, realizar diferentes aplicações parciais nesta função.

Ao informar apenas um parâmetro o resultado obtido seria: `int, int -> int`

Informando dois parâmetros o resultado obtido seria: `int -> int`

Similar ao processo de Currying, a operação fundamental descrita pela função só é executada quando todos os parâmetros forem informados, independente da quantidade de funções intermediárias geradas.

Veja a implementação descrita, primeiro através de currying:

```csharp
Func<int, int, int, int> add = 
    (value, value2) => value + value2;

Func<int, Func<int, Func<int, int>>> addCurried = add.Curry();
curriedResult = addCurried(2)(3)(5);
//curriedResult = 10
```

Utilizando aplicação parcial com apenas um parâmetro:

```csharp
Func<int, int, int, int> add = 
    (value, value2) => value + value2;

Func<int, int, int> addPartialApplied = add.PartialApply(2);
partialAppliedResult = addPartialApplied (3,5);
//partialAppliedResult = 10
```

Utilizando aplicação parcial com dois parâmetros:

```csharp
Func<int, int, int, int> add = 
    (value, value2) => value + value2;

Func<int, int> addPartialApplied = add.PartialApply(2,3);
partialAppliedResult = addPartialApplied(5);
//partialAppliedResult = 10
```

Todos os métodos disponíveis para aplicação parcial e Currying operam em métodos de até 4 parâmetros, podendo retornar qualquer tipo, inclusive `void`.

Além disso, eles podem ser utilizados como métodos estáticos das classes `Currying` e `PartialApplication` ou como extensões para `Func` e `Action`.
