Amigos, continuamos a entender programação funcional. Na segunda parte desta série de artigos, você aprenderá os princípios básicos desse paradigma de desenvolvimento e entenderá como essa abordagem difere da programação orientada a objetos ou imperativa.

Valores e Funções
Mais uma vez, considere esta função simples.
let add1 x = x + 1
O que x
significa aqui:
- Pegue algum valor do domínio (escopo).
- Use o nome "
x
" para fornecer esse valor para que ele possa ser acessado mais tarde.
Usar um nome para representar um valor é chamado de ligação. O nome " x
" é "vinculado" ao valor de entrada.
Portanto, se você calcular uma função com um valor de entrada de, digamos, 5, acontecerá o seguinte: sempre que " x
" estiver na definição original, o valor 5 será definido, semelhante à função "localizar e substituir" em um editor de texto.
let add1 x = x + 1 add1 5 // «x» with «5» // add1 5 = 5 + 1 = 6 // 6
É importante entender que isso não é uma tarefa. " x
" não é um "slot" e não é uma variável com um valor atribuído que pode ser alterado posteriormente. Esta é uma associação única do nome " x
" com um determinado valor. Este valor é um dos números inteiros predefinidos e não pode ser alterado. I.e. uma vez ligado x
não pode ser alterado . O rótulo, uma vez associado ao valor, é sempre associado a esse valor.
Este princípio é uma parte crítica do pensamento funcional: não existem "variáveis", apenas valores .
Funções como valores
Se você pensar um pouco mais, poderá ver que o nome “ add1
” em si é apenas uma ligação a “uma função que aumenta a entrada em um”. A função em si é independente do nome anexado a ela.
Ao introduzir let add1 x = x + 1
, dizemos ao compilador F # "toda vez que você vê o nome" add1
", substitua-o por uma função que adicione 1 à entrada". " add1
" é chamado de valor da função .
Para ver que a função não depende de seu nome, basta executar o seguinte código:
let add1 x = x + 1 let plus1 = add1 add1 5 plus1 5
Como você pode ver, " add
" e " plus
" são dois nomes vinculados à mesma função.
Você sempre pode identificar uma função de valor por sua assinatura, que possui o domain -> range
formulário padrão domain -> range
. A assinatura generalizada da função value:
val functionName : domain -> range
Valores simples
Imagine uma operação que não leva nada e sempre retorna 5.

Seria uma operação "constante".
Como isso pode ser descrito em F #? Queremos dizer ao compilador: “toda vez que você vir o nome c
, substitua-o por 5”. Assim:
let c = 5
Ao calcular retornará:
val c : int = 5
Desta vez, não há seta correspondente, apenas um int. Do novo - um sinal de igual com o valor real deduzido após ele. O compilador F # sabe que essa ligação possui um valor conhecido, que sempre será retornado, ou seja, o número 5.
Em outras palavras, acabamos de definir uma constante ou, em termos de F #, um valor simples.
Você sempre pode distinguir um valor simples de uma função de valor, porque todos os valores simples têm uma assinatura semelhante:
val aName: type = constant // -
Valores simples vs. valores de função | Significado simples vs. funções de valor
É importante entender que, em F #, diferentemente de outros idiomas como C #, há muito pouca diferença entre valores simples e funções de valor. Ambos os tipos são valores que podem ser associados a nomes (usando a palavra-chave let
), após os quais podem ser passados para qualquer lugar. De fato, veremos em breve que a idéia de que funções são valores que podem ser passados como entrada para outras funções é um dos aspectos principais do pensamento funcional.
Observe que há uma pequena diferença entre um valor simples e uma função de valor. Uma função sempre tem domínio e intervalo e deve ser "aplicada" ao argumento para retornar o resultado. Um valor simples não precisa ser calculado após a ligação. Usando o exemplo acima, se quisermos definir uma "função constante" que retorne 5, poderíamos usar:
let c = fun()->5 // or let c() = 5
A assinatura de tais funções tem a seguinte aparência:
val c : unit -> int
Não é assim:
val c : int = 5
Mais informações sobre a unit
, sintaxe da função e funções anônimas serão fornecidas posteriormente.
"Valores" vs. "Objetos"
Em linguagens de programação funcionais, como F #, a maioria das coisas é chamada de "valores". Em linguagens orientadas a objetos, como C #, a maioria das coisas é chamada de "objetos". Qual é a diferença entre "meaning" e "object"?
O valor, como vimos acima, é um membro do domínio. O domínio de números inteiros, o domínio de cadeias, o domínio de funções que mapeiam números inteiros em cadeias e assim por diante. Em princípio, os valores são imutáveis (não mutáveis). E os significados não têm o comportamento associado a eles.
Objetos na definição canônica são encapsulamento da estrutura de dados com comportamento associado (métodos). Em geral, os objetos devem ter um estado (ou seja, mutáveis) e todas as operações que alteram o estado interno devem ser fornecidas pelo próprio objeto (por meio de uma notação de "ponto").
No F #, mesmo os valores primitivos têm uma certa quantidade de comportamento de "objeto". Por exemplo, você pode obter o comprimento de uma string através de um ponto:
«abc».Length
Mas, em geral, evitaremos o termo "objeto" para valores padrão em F #, salvando-o para se referir a classes de pleno direito ou outros valores que fornecem métodos.
Nomeando valores
As convenções de nomenclatura padrão usadas para nomes de valores e funções são basicamente alfanuméricas + sublinhados. Mas há algumas adições:
- Você pode adicionar um apóstrofo em qualquer parte do nome, excluindo o primeiro caractere.
A'b'c begin' //
- O último caso é frequentemente usado como um rótulo para versões "diferentes" de um valor:
let f = x let f' = derivative f let f'' = derivative f'
ou para variáveis com o mesmo nome com palavras-chave existentes
let if' btf = if b then t else f
Você também pode usar backticks duplos para qualquer string para torná-lo um identificador válido.
``this is a name`` ``123`` //
Casos em que você pode precisar usar um truque de backtick duplo:
- Quando você precisar usar um identificador que corresponda à palavra-chave.
let ``begin`` = «begin»
- Quando você precisar usar linguagens naturais para regras de negócios, testes de unidade ou documentação executável no estilo BBD, como Cucumber.
let ``is first time customer?`` = true let ``add gift to order`` = () if ``is first time customer?`` then ``add gift to order`` // - let [<Test>] ``When input is 2 then expect square is 4``= // code here // BDD clause let [<Given>] ``I have (.*) N products in my cart`` (n:int) = // code here
Diferentemente do C #, a convenção de nomenclatura F # exige que as funções e os valores iniciem com uma letra minúscula e não maiúscula ( camelCase
, não PascalCase
), a menos que sejam projetados para interagir com outras linguagens .NET. No entanto, tipos e módulos usam letras maiúsculas (no início).
Recursos Adicionais
Existem muitos tutoriais para F #, incluindo materiais para quem vem com experiência em C # ou Java. Os links a seguir podem ser úteis à medida que você avança no F #:
Várias outras maneiras de começar a aprender F # também são descritas.
Finalmente, a comunidade F # é muito amigável para iniciantes. Há um bate-papo muito ativo no Slack, suportado pela F # Software Foundation, com salas para iniciantes nas quais você pode participar livremente . É altamente recomendável que você faça isso!
Não se esqueça de visitar o site da comunidade de língua russa F # ! Se você tiver alguma dúvida sobre o aprendizado de um idioma, teremos prazer em discuti-los nas salas de bate-papo:
Sobre autores de tradução
Traduzido por @kleidemos
As mudanças de tradução e editoriais foram feitas pelos esforços da comunidade de desenvolvedores de F # de língua russa . Agradecemos também a @schvepsss e @shwars pela preparação deste artigo para publicação.