Что такое стиль «без точек» (в функциональном программировании)?

103

Фраза, которую я недавно заметил, - это концепция стиля «без точек» ...

Сначала был этот вопрос, а также этот .

Затем я обнаружил, что здесь упоминается: «Еще одна тема, которую, возможно, стоит обсудить, - это неприязнь авторов к безточечному стилю».

Что такое стиль «без точек»? Может кто-нибудь дать краткое объяснение? Это как-то связано с "автоматическим" каррированием?

Чтобы получить представление о моем уровне - я учил себя Scheme и написал простой интерпретатор Scheme ... Я понимаю, что такое «неявное» каррирование, но я не знаю ни Haskell, ни ML.

Пол Холлингсворт
источник
3
Просто примечание: чтобы понять, почему это называется Pointfree, посетите Pointfree / Но Pointfree имеет больше очков! в HaskellWiki.
Петр Пудлак

Ответы:

66

Просто посмотрите статью в Википедии, чтобы получить свое определение:

Молчаливое программирование (программирование без точек) - это парадигма программирования, в которой определение функции не включает информацию, касающуюся ее аргументов, с использованием комбинаторов и композиции функций [...] вместо переменных.

Пример на Haskell:

Обычный (вы указываете аргументы явно):

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

Бесточечный ( sumне имеет явных аргументов - просто складка, +начиная с 0):

 sum = foldr (+) 0

Или даже проще: вместо этого g(x) = f(x)вы можете просто написать g = f.

Так что да: это тесно связано с каррированием (или такими операциями, как композиция функций).

Дарио
источник
8
АА, вижу! Таким образом, вы всегда создаете новые функции, просто комбинируя другие функции, а не объявляя аргументы ... Очень элегантно!
Пол Холлингсворт
22
Мне действительно не нравится придумывать новые имена для переменных / аргументов при программировании. Это одна из главных причин, по которой я люблю стиль без очков!
Martijn
2
Каким образом это связано с каррированием?
kaleidic
1
@kaleidic: Потому что, не имея имен переменных, вам нужно составлять частично применяемые функции. Это то, что мы называем карри (или, точнее, то, что стало возможным благодаря карри)
Дарио
1
Разве вы не имеете в виду sum (x:xs) ...вместо sum sum (x:xs) ...?
Ehtesh Choudhury
33

Бесточечный стиль означает, что аргументы определяемой функции не упоминаются явно, что функция определяется посредством композиции функций.

Если у вас есть две функции, например

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

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

и если вы хотите объединить эти две функции в одну, которая вычисляет x*x+1, вы можете определить ее как «полная точка» следующим образом:

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

Бессмысленной альтернативой было бы не говорить о споре x:

f :: a -> a
f = inc . square
что-то
источник
22
Глупо, но в Haskell «без точек» обычно выглядит более острым (больше точек). Это раздражение - отличная мнемоника. (Это комментируется в книге Real World Haskell.)
Дэн
3
Что касается комментария @Dan, то страница Pointfree HaskellWiki предлагает объяснение того, почему она называется pointfree .
Винсент Савар
2
@Dan: Я не думаю, что это глупо, поскольку точка Haskell должна быть «оператором круга» (хотя должна больше походить на °). Но это сбивает с толку, особенно если вы новичок в функциональных языках программирования; каждая вводная книга по haskell должна объяснять безточечный стиль.
Себастьян Мах
13

Пример 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'

Ссылка

Брунно
источник
5

Точечный стиль означает, что в коде явно не упоминаются аргументы, даже если они существуют и используются.

Это работает в Haskell из-за того, как работают функции.

Например:

myTake = take

возвращает функцию, которая принимает один аргумент, поэтому нет причин явно вводить аргумент, если вы этого не хотите.

Rayne
источник
1
Иногда это не работает в Haskell 98, например myShow = show. Больше об этом можно
найти
-1

Вот один пример на TypeScript без какой-либо другой библиотеки:

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;
    }
  }
}

Вы можете видеть, что бесточечный стиль более «плавный» и его легче читать.

AZ.
источник
Это не бесточечный стиль, это просто различие между лямбдой и именованной функцией.
kralyk
@kralyk Я думаю, вы упустили суть, this.moreThan(10)это не именованная функция, это каррированная функция, а также функция, которая неявно (то есть без точки) принимает a в transactionкачестве входных данных.
АЗ.