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.


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).


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

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


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.


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.


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.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.