O que é o estilo “sem pontos” (em Programação Funcional)?

101

Uma frase que notei recentemente é o conceito de estilo "ponto livre" ...

Primeiro, havia essa pergunta, e também essa .

Então, descobri aqui que eles mencionam "Outro tópico que pode valer a pena discutir é a aversão dos autores ao estilo livre de pontos".

O que é o estilo "sem pontos"? Alguém pode dar uma explicação concisa? Tem algo a ver com curry "automático"?

Para ter uma ideia do meu nível - tenho ensinado Scheme a mim mesmo e escrevi um interpretador Scheme simples ... Eu entendo o que é currying "implícito", mas não conheço nenhum Haskell ou ML.

Paul Hollingsworth
fonte
3
Apenas uma observação: para ver por que é chamado de pointfree visite Pointfree / Mas pointfree tem mais pontos! em HaskellWiki.
Petr Pudlák,

Respostas:

66

Basta olhar para o artigo da Wikipedia para obter sua definição:

A programação tácita (programação livre de pontos) é um paradigma de programação em que a definição de uma função não inclui informações sobre seus argumentos, utilizando combinadores e composição [...] de funções ao invés de variáveis.

Exemplo de Haskell:

Convencional (você especifica os argumentos explicitamente):

sum (x:xs) = x + (sum xs)
sum [] = 0

Livre de pontos ( sumnão tem argumentos explícitos - é apenas uma dobra +começando com 0):

 sum = foldr (+) 0

Ou ainda mais simples: em vez de g(x) = f(x), você pode apenas escrever g = f.

Então, sim: está intimamente relacionado ao currying (ou operações como composição de funções).

Dario
fonte
8
Ahh, entendi! Assim você constrói novas funções sempre combinando outras funções ao invés de declarar argumentos ... Muito elegante!
Paul Hollingsworth
22
Eu realmente não gosto de ter que criar novos nomes para variáveis ​​/ argumentos quando estou programando. Essa é uma grande razão pela qual eu amo o estilo sem pontos!
Martijn
2
De que forma ele está relacionado ao Currying?
kaleidic
1
@kaleidic: Porque sem ter nomes de variáveis, você precisa compor funções parcialmente aplicadas. Isso é o que chamamos de currying (ou, mais precisamente, o que é possível através do currying)
Dario
1
Você não quer dizer em sum (x:xs) ...vez de sum sum (x:xs) ...?
Ehtesh Choudhury
33

O estilo sem pontos significa que os argumentos da função que está sendo definida não são mencionados explicitamente, que a função é definida por meio da composição da função.

Se você tem duas funções, como

square :: a -> a
square x = x*x

inc :: a -> a
inc x = x+1

e se você quiser combinar essas duas funções com uma que calcule x*x+1, você pode defini-la como "ponto cheio" assim:

f :: a -> a
f x = inc (square x)

A alternativa livre de pontos seria não falar sobre o argumento x:

f :: a -> a
f = inc . square
sth
fonte
22
Estupidamente, em Haskell, o caminho 'sem pontos' é geralmente aquele que parece mais pontudo (mais pontos). Este incômodo é um excelente mnemônico. (O livro Real World Haskell comenta sobre isso.)
Dan
3
Em relação ao comentário de @Dan , a página Pointfree HaskellWiki oferece uma explicação de por que é chamada de pointfree .
Vincent Savard
2
@Dan: Não acho que seja estúpido, já que o ponto Haskell foi feito para ser "aquele operador de círculo" (embora deva ser mais parecido com °). Mas é confuso, especialmente quando você é novo em linguagens de programação funcionais; todo livro de introdução sobre haskell deve explicar o estilo sem pontos.
Sebastian Mach
12

Um exemplo de JavaScript:

//not pointfree cause we receive args
var initials = function(name) {
  return name.split(' ').map(compose(toUpperCase, head)).join('. ');
};

const compose = (...fns) => (...args) => fns.reduceRight((res, fn) => [fn.call(null, ...res)], args)[0];
const join = m => m.join();

//pointfree
var initials = compose(join('. '), map(compose(toUpperCase, head)), split(' '));

initials("hunter stockton thompson");
// 'H. S. T'

Referência

Brunno
fonte
5

O estilo livre de pontos significa que o código não menciona explicitamente seus argumentos, mesmo que eles existam e estejam sendo usados.

Isso funciona em Haskell por causa da maneira como as funções funcionam.

Por exemplo:

myTake = take

retorna uma função que leva um argumento, portanto, não há razão para digitar explicitamente o argumento, a menos que você apenas queira.

Rayne
fonte
1
Às vezes, não funciona em Haskell 98, como em myShow = show. Há mais sobre isso na wiki de Haskell
Ehtesh Choudhury
-1

Aqui está um exemplo em TypeScript sem qualquer outra biblioteca:

interface Transaction {
  amount: number;
}

class Test {
  public getPositiveNumbers(transactions: Transaction[]) {
    return transactions.filter(this.isPositive);

    //return transactions.filter((transaction: {amount: number} => transaction.amount > 0));
  }

  public getBigNumbers(transactions: Transaction[]) {
    // point-free
    return transactions.filter(this.moreThan(10));

    // not point-free
    // return transactions.filter((transaction: any) => transaction.amount > 10);
  }

  private isPositive(transaction: Transaction) {
    return transactions.amount > 0;
  }

  private moreThan(amount: number) {
    return (transaction: Transaction) => {
      return transactions.amount > amount;
    }
  }
}

Você pode ver que o estilo sem pontos é mais "fluente" e fácil de ler.

AZ.
fonte
Esse não é um estilo sem pontos, mas apenas uma distinção entre um lambda e uma função nomeada.
kralyk
@kralyk Acho que você perdeu o ponto, this.moreThan(10)não é uma função nomeada, é uma função curried, bem como uma função que implicitamente (portanto, sem pontos) terá a transactioncomo sua entrada.
AZ.