Exemplo: http://en.wikipedia.org/wiki/Factorial
A definição formal é dada por:
Isso é fácil de traduzir para Haskell:
fact 0 = 1
fact n = n * fact (n - 1)
Em duas linhas a implementação fica aderente à definição matemática. Pode-se utilizar em funções de probabilidade tais como Arranjo:
arranjo n p = fact n / fact (n - p)
No entanto, conhecemos essas fórmulas de uma maneira mais natural como:
A(n,p) = n! / (n - p)!
Em Scala é possível utilizar a notação ! para fatorial, utilizando métodos implícitos. O trecho de código abaixo mostra como fazer isso:
[AdvancedMath.scala]
package factorial
class AdvancedMath {
def factorial(a: Long):
Long = if (a == 0) 1 else a * factorial(a - 1) //1
}
object AdvancedMath extends AdvancedMath {
implicit def AdvancedMath = new AdvancedMath
}
[meuTesteFatorial.sc]
package myBulkScalaProject;
object meuTeste {
implicit class AddFact(val num: Long) extends AnyVal { //2
def ! = AdvancedMath.factorial(num) //3
}
def arranjo(n:Long, p:Long):
Long = (n!) / ((n-p)!) //4
//> arranjo: (n: Long, r: Long)Long
def combinacao(n:Long, p:Long):
Long = (n!) / ((p!) * ((n - p)!)) //5
//> combinacao: (n: Long, r: Long)Long
4 .! //> res0: Long = 24
5 ! //> res1: Long = 120
6! //> res2: Long = 720
(3!) + (4!) //> res3: Long = 30
(3 + 4)! //> res4: Long = 5040
7! //> res5: Long = 5040
arranjo(4,2) //> res6: Long = 12
combinacao(4,2) //> res7: Long = 6
}
Nesse código temos algumas coisas que eu gostaria de ressaltar:
- Defino meu método factorial em uma classe Scala diferente
- Em um arquivo worksheet, uso a palavra chave implicit para adicionar um método à classe AnyVal, que recebe um Long como parâmetro
- Defino o método "!" e faço uma chamada para o método factorial, que recebe um Long
- Defino o método de arranjo de uma forma mais natural
- Defino o método de combinação de uma forma mais natural
O restante do código, mostro algumas utilizações possíveis e é pura diversão!
Teste esse código para você poder ver funcionar em sua máquina e aprenda um conceito importante nessa linguagem funcional!