Tendo examinado algumas linguagens para programação funcional, sempre me perguntei por que algumas linguagens fp usam um ou mais caracteres de espaço em branco para aplicação de funções (e definição), enquanto a maioria (todas?) De linguagens imperativas / orientadas a objetos usa parênteses, o que parece ser a maneira mais matemática. Eu também acho que o último estilo é muito mais claro e legível do que sem os parênteses.
Portanto, se tivermos uma função f (x) = x², existem duas alternativas para chamá-la:
FP:
f x
Exemplos:
- ML, Ocaml, F #
- Haskell
- LISP, esquema (de alguma forma)
Não FP:
f(x)
Exemplos:
- Quase todas as línguas imperativas (eu sei, veja os comentários / respostas)
- Erlang
- Scala (também permite "notação do operador" para argumentos únicos)
Quais são as razões para "deixar de fora" os parênteses?
x²
como exemplo?Respostas:
linguagens funcionais são inspiradas no cálculo lambda . Nesse campo, parênteses não são usados para aplicação de função.
A legibilidade está nos olhos de quem vê. Você não está acostumado a lê-lo. É um pouco como operadores matemáticos. Se você entende a associatividade, precisa apenas de alguns parênteses para esclarecer a estrutura de sua expressão. Muitas vezes você não precisa deles.
O curry também é um bom motivo para usar esta convenção. No haskell, você pode definir o seguinte:
Com parens, você pode usar duas convenções:
f(5, 6)
(sem curry) ouf(5)(6)
(curry). A sintaxe haskell ajuda a se acostumar com o conceito de currying. Você ainda pode usar uma versão sem curry, mas é mais doloroso usá-la com combinadoresObserve como a segunda versão obriga a registrar x como uma variável e que a subexpressão é uma função que pega um número inteiro e adiciona 5 a ele? A versão ao curry é muito mais leve, mas também é considerada por muitos como mais legível.
O programa Haskell faz uso extensivo de aplicativos e combinadores parciais como um meio de definir e compor abstrações, portanto esse não é um exemplo de brinquedo. Uma boa interface de funções será aquela em que a ordem dos parâmetros forneça um uso amigável de curry.
Outro ponto: uma função sem parâmetros deve ser chamada com
f()
. Em haskell, como você manipula apenas valores imutáveis de avaliação preguiçosa, basta escreverf
e considerá-lo como um valor que precisará executar alguns cálculos quando necessário. Como sua avaliação não terá efeito colateral, não faz sentido ter uma notação diferente para a função sem parâmetros e seu valor retornado.Existem também outras convenções para aplicação de funções:
fonte
f(a, ,b)
ouadd(a, )
ouadd(, b)
pareceria mais flexível por padrão.A idéia básica é tornar a operação mais importante (aplicativo de funções) mais fácil de ler e mais fácil de escrever. Um espaço é muito pouco intrusivo para ler e muito fácil de digitar.
Observe que isso não é específico para linguagens funcionais, por exemplo, no Smalltalk , um dos primeiros idiomas OO e idiomas inspirados por ele ( Self , Newspeak , Objective-C), mas também em Io e idiomas inspirados por ele (Ioke, Seph), espaço em branco é usado para chamadas de método.
Estilo Smalltalk:
(No último caso, o nome do método é
replace:with:
.)Estilo Io:
Scala também permite espaço em branco para chamadas de método:
E deixando de fora os parênteses se houver apenas um argumento:
O Ruby também permite que você pare os parênteses:
Na verdade não:
A notação matemática evoluiu por um longo tempo de uma maneira terrivelmente inconsistente.
Se houver, as linguagens funcionais se inspiram no cálculo λ, onde a aplicação da função é escrita usando espaço em branco.
fonte
O parêntese para a aplicação de funções é apenas uma das muitas selas que Euler nos deixou. Como qualquer outra coisa, a matemática precisa de convenções quando existem várias maneiras de fazer alguma coisa. Se a sua educação matemática se estende apenas a uma disciplina não matemática na universidade, provavelmente você não está familiarizado com os muitos campos em que a aplicação de funções acontece felizmente sem nenhum desses colchetes sem sentido (por exemplo, Geometria Diferencial, Álgebra Abstrata). E você nem menciona funções aplicadas infixo (quase todas as linguagens), "outfix", como adotar uma norma ou diagramaticamente (Befunge, Algebraic Topology).
Então, em resposta, eu diria que é devido a uma proporção muito maior de programadores funcionais e designers de linguagem que possuem extensa educação matemática. Von Neumann diz: "Jovem, em matemática, você não entende as coisas. Você apenas se acostuma com elas.", Certamente isso é verdade para a notação.
fonte
f(x)
vs.sin x
vs.x²
vs.|x|
vs.x!
vs.x + y
vs.xy
vs.½
vs. um somatório vs. uma vs. integrante ...Embora exista muita verdade na resposta de Simon, acho que também há uma razão muito mais prática. A natureza da programação funcional tende a gerar muito mais parênteses do que a programação imperativa, devido ao encadeamento e composição de funções. Esses padrões de encadeamento e composição também costumam ser capazes de ser inequivocamente representados sem parênteses.
A linha inferior é, todos esses parênteses ficam irritantes para ler e acompanhar. É provavelmente o principal motivo pelo qual o LISP não é mais popular. Portanto, se você pode obter o poder da programação funcional sem o incômodo de excesso de parênteses, acho que os designers de linguagem tendem a seguir esse caminho. Afinal, os designers de idiomas também são usuários de idiomas.
Até o Scala permite que o programador omita parênteses em determinadas circunstâncias, que aparecem com bastante frequência ao programar em um estilo funcional, para que você obtenha o melhor dos dois mundos. Por exemplo:
As parênteses no final são necessárias para associatividade, e as demais são deixadas de fora (assim como os pontos). Escrever dessa maneira enfatiza a natureza encadeada das operações que você está executando. Pode não ser familiar para um programador imperativo, mas para um programador funcional parece muito natural e fluente escrever dessa maneira, sem ter que parar e inserir sintaxe que não agrega significado ao programa, mas existe apenas para deixar o compilador feliz .
fonte
Ambas as premissas estão erradas.
Essas linguagens funcionais não usam espaço para aplicação de funções. O que eles fazem é simplesmente analisar qualquer expressão que vem depois de uma função como argumento.
é claro que se você não usar um espaço nem parênteses, normalmente não funcionará, simplesmente porque a expressão não está adequadamente tokenizada
Mas se esses idiomas fossem restritos a nomes de variáveis de 1 caractere, também funcionaria.
As convenções de matemática também normalmente não exigem parênteses para a aplicação da função. Os matemáticos não apenas escrevem frequentemente sin x - para funções lineares (normalmente chamadas de operadores lineares) também é muito comum escrever o argumento sem parênteses, talvez porque (assim como qualquer função na programação funcional) as funções lineares sejam frequentemente tratadas sem fornecer diretamente um argumento.
Realmente, sua pergunta se resume a: por que alguns idiomas exigem parênteses para a aplicação de funções? Bem, aparentemente algumas pessoas, como você, consideram isso mais legível. Eu discordo totalmente disso: um par de parênteses é bom, mas assim que você tem mais dois aninhados, começa a ficar confuso. O código Lisp demonstra isso melhor e praticamente todas as linguagens funcionais pareceriam desordenadas se você precisasse de parênteses em todos os lugares. Isso não acontece tanto em linguagens imperativas, mas principalmente porque essas linguagens não são expressivas o suficiente para escrever uma linha concisa e clara em primeiro lugar.
fonte
object method: args
, Objective C[object method: args]
, e Ruby e Perl permitem omitir parênteses nas chamadas de função e método, exigindo apenas que resolvam a ambiguidade.Um pequeno esclarecimento histórico: a notação original em matemática estava sem parênteses !
A notação fx para uma função arbitrária de x foi introduzida por Johan Bernoulli por volta de 1700, logo após Leibniz começar a falar sobre funções (na verdade, Bernoulli escreveu x ). Porém, antes disso, muitas pessoas já usavam notações como sin x ou lx (o logaritmo de x ) para funções específicas de x , sem parênteses. Eu suspeito que essa seja a razão pela qual muitas pessoas hoje ainda escrevem pecado x em vez de pecado (x) .
Euler, que era aluno de Bernoulli, adotou a orientação de Bernoulli. x de e transformou o grego em uma letra latina, escrevendo fx . Mais tarde, ele percebeu que seria fácil confundir f para uma "quantidade" e acreditava que fx era um produto, então ele começou a escrever f: x . Portanto, a notação f (x) não se deve a Euler. É claro que Euler precisava de parênteses pela mesma razão, ainda precisamos de parênteses em linguagens de programação funcional: para distinguir, por exemplo (fx) + y de f (x + y) . Eu suspeito que as pessoas depois de Euler adotaram o parêntese como padrão porque viram principalmente Euler escrever expressões compostas como f (ax + b). Ele raramente escrevia apenas fx .
Para mais informações, veja: Euler já escreveu f (x) entre parênteses? .
Não sei se os designers de linguagens de programação funcional ou os inventores do cálculo lambda estavam cientes das raízes históricas de sua notação. Pessoalmente, acho a notação sem parênteses mais natural.
fonte