Що таке "безточковий" стиль (у функціональному програмуванні)?


101

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

По-перше, було це питання, а також це .

Потім я виявив, що тут вони згадують: "Ще однією темою, яку, можливо, варто обговорити, є неприязнь авторів до стилю" без точки ".

Що таке "безточковий" стиль? Хтось може дати коротке пояснення? Чи це пов’язано з «автоматичним» каррі?

Щоб отримати уявлення про свій рівень - я навчав себе 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) ...?
Ехтеш Чоудхурі

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
По-дурному, у Хаскелі "безточковий" спосіб, як правило, виглядає вразливішим (більше періодів). Це роздратування робить чудовий мнемонічний. (Книга Real World Haskell коментує це.)
Ден,

3
Стосовно коментаря @ Dan, сторінка Pointfree HaskellWiki пропонує пояснення, чому її називають pointfree .
Вінсент Савард,

2
@Dan: Я не вважаю це дурним, оскільки точка Хаскелла має бути "тим оператором кола" (хоча має виглядати більше як °). Але це бентежить, особливо коли ви новачок у функціональних мовах програмування; кожна вступна книга про haskell повинна пояснювати безточковий стиль.
Себастьян Мах

12

Зразок 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

повертає функцію, яка приймає один аргумент, тому немає причин явно вводити аргумент, якщо ви просто цього теж не хочете.


1
Іноді це не працює в Haskell 98, як у myShow = show. Більше про це є у вікі Haskell
Ехтеш Чоудхурі

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

Ви бачите, що безточковий стиль більш "вільний" і легший для читання.


Це не безточковий стиль, це просто відмінність між лямбда і іменованою функцією.
кралик

@kralyk Я думаю, що ви пропустили суть, this.moreThan(10)це не іменована функція, це функція з каррією, а також функція, яка неявно (таким чином без точки) прийме a transactionяк свій вхід.
AZ.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.