Apa itu gaya "point free" (dalam Pemrograman Fungsional)?

103

Frasa yang saya perhatikan baru-baru ini adalah konsep gaya "tanpa titik" ...

Pertama, ada pertanyaan ini , dan juga pertanyaan ini .

Kemudian, saya menemukan di sini mereka menyebutkan "Topik lain yang mungkin layak untuk didiskusikan adalah ketidaksukaan penulis terhadap gaya bebas poin."

Apa itu gaya "point free"? Bisakah seseorang memberikan penjelasan yang ringkas? Apakah ini ada hubungannya dengan kari "otomatis"?

Untuk mengetahui level saya - Saya telah belajar sendiri Skema, dan telah menulis juru bahasa Skema sederhana ... Saya mengerti apa itu kari "implisit", tetapi saya tidak tahu Haskell atau ML apa pun.

Paul Hollingsworth
sumber
3
Sekadar catatan: untuk melihat mengapa disebut pointfree kunjungi Pointfree / Tetapi pointfree memiliki lebih banyak poin! di HaskellWiki.
Petr Pudlák

Jawaban:

66

Lihat saja artikel Wikipedia untuk mendapatkan definisi Anda:

Pemrograman tacit (pemrograman tanpa titik) adalah paradigma pemrograman di mana definisi fungsi tidak menyertakan informasi mengenai argumennya, menggunakan kombinator dan komposisi fungsi [...] daripada variabel.

Contoh Haskell:

Konvensional (Anda menentukan argumen secara eksplisit):

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

Tanpa poin ( sumtidak memiliki argumen eksplisit - ini hanya lipatan dengan +memulai dengan 0):

 sum = foldr (+) 0

Atau bahkan lebih sederhana: Daripada g(x) = f(x), Anda bisa menulis g = f.

Jadi ya: Ini terkait erat dengan kari (atau operasi seperti komposisi fungsi).

Dario
sumber
8
Ahh begitu! Jadi, Anda selalu membangun fungsi baru hanya dengan menggabungkan fungsi lain daripada mendeklarasikan argumen ... Sangat elegan!
Paul Hollingsworth
22
Saya sangat tidak suka harus memberikan nama baru untuk variabel / argumen saat saya memprogram. Itulah salah satu alasan utama saya menyukai gaya tanpa poin!
Martijn
2
Dalam hal apa itu terkait dengan kari?
kaleidic
1
@kaleidic: Karena tanpa nama variabel, Anda perlu membuat fungsi yang diterapkan sebagian. Itulah yang kami sebut kari (atau, lebih tepatnya, apa yang dimungkinkan melalui kari)
Dario
1
Bukankah maksudmu sum (x:xs) ...bukan sum sum (x:xs) ...?
Ehtesh Choudhury
33

Gaya tanpa titik berarti argumen dari fungsi yang sedang didefinisikan tidak disebutkan secara eksplisit, bahwa fungsi tersebut ditentukan melalui komposisi fungsi.

Jika Anda memiliki dua fungsi, seperti

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

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

dan jika Anda ingin menggabungkan dua fungsi ini menjadi satu fungsi yang menghitung x*x+1, Anda dapat mendefinisikannya "point-full" seperti ini:

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

Alternatif tanpa tujuan adalah tidak membicarakan argumen x:

f :: a -> a
f = inc . square
sth
sumber
22
Bodohnya, di Haskell, cara 'point-free' biasanya yang terlihat lebih runcing (lebih banyak titik). Gangguan ini membuat mnemonik yang sangat baik. (Buku Real World Haskell mengomentari hal ini.)
Dan
3
Mengenai komentar @ Dan, halaman Pointfree HaskellWiki menawarkan penjelasan mengapa disebut pointfree .
Vincent Savard
2
@Dan: Saya tidak berpikir itu bodoh, karena titik Haskell dimaksudkan untuk menjadi "operator lingkaran itu" (harus lebih terlihat seperti °). Tetapi membingungkan, ini adalah, terutama ketika Anda baru mengenal bahasa pemrograman fungsional; setiap buku intro tentang haskell harus menjelaskan gaya bebas poin.
Sebastian Mach
13

Contoh 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'

Referensi

Brunno
sumber
5

Gaya bebas titik berarti bahwa kode tidak secara eksplisit menyebutkan argumennya, meskipun argumen itu ada dan sedang digunakan.

Ini berfungsi di Haskell karena cara kerja fungsi.

Misalnya:

myTake = take

mengembalikan fungsi yang membutuhkan satu argumen, oleh karena itu tidak ada alasan untuk mengetik argumen secara eksplisit kecuali Anda ingin juga.

Rayne
sumber
1
Terkadang, ini tidak berfungsi di Haskell 98, seperti di myShow = show. Ada lebih banyak tentang itu di wiki Haskell
Ehtesh Choudhury
-1

Berikut ini satu contoh di TypeScript tanpa pustaka lain:

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

Anda dapat melihat gaya tanpa poin lebih "lancar" dan lebih mudah dibaca.

AZ.
sumber
Itu bukan gaya tanpa titik, itu hanya perbedaan antara lambda dan fungsi bernama.
kralyk
@kralyk Saya pikir Anda melewatkan intinya, this.moreThan(10)bukan fungsi bernama, ini adalah fungsi kari serta fungsi yang secara implisit (jadi titik gratis) mengambil transactionsebagai inputnya.
AZ.