Apakah suatu fungsi mendapatkan nilai dari fungsi lain dianggap murni?

9

Saya mencoba mencari cara untuk menangani nilai variabel default saat membuat fungsi tanpa efek samping dan berakhir dengan yang berikut:

function getDefaultSeparator() {
    return ':';
}

function process(input, separator) {
    var separator = separator || getDefaultSeparator();

    // Use separator in some logic

    return output;
}

Pemisah default akan digunakan dalam fungsi lain dan saya hanya ingin mendefinisikannya di satu tempat.

Jika ini adalah fungsi murni, apa bedanya dengan menggunakan konstanta DEFAULT_SEPARATOR global saja?

agost
sumber
5
Tidak ada perbedaan materi, kecuali jika Anda berencana menggunakan fungsi sebagai pengganti untuk beberapa logika yang akan ditambahkan nanti.
Robert Harvey
3
Kemungkinan rangkap dari Apakah fungsi segera tidak murni jika mengambil fungsi sebagai parameter? . Pertanyaannya bukan duplikat yang tepat, tetapi jawabannya harus sama. ("Itu tergantung pada kemurnian fungsi lainnya.")
jpmc26
1
Menggunakan konstanta global tidak membuat fungsi menjadi tidak murni. Menggunakan nilai global yang Anda asumsikan konstan tidak.
chepner
Btw, Anda dapat kari process(dengan urutan parameter terbalik) dan daripada mengkhususkan fungsi kari kevar processDefault = process(":")
bob

Jawaban:

22

Apakah suatu fungsi mendapatkan nilai dari fungsi lain dianggap murni?

Itu tergantung pada apa fungsi fungsi lain, dan apa fungsi fungsi panggil. Pengotor itu menular, kemurnian tidak.

Memanggil fungsi murni tidak mengubah kemurnian fungsi panggilan. Memanggil fungsi tidak murni secara otomatis juga membuat fungsi panggilan tidak murni.

Jadi, dalam contoh Anda, itu tergantung pada kemurnian bagian yang Anda tinggalkan: jika itu murni, maka seluruh fungsinya murni.

Jika ini adalah fungsi murni, apa bedanya dengan menggunakan konstanta DEFAULT_SEPARATOR global saja?

Tidak ada. Fungsi yang selalu mengembalikan nilai yang sama tidak dapat dibedakan dari konstanta. Bahkan, itulah bagaimana konstanta dimodelkan dalam λ-calculus.

Jörg W Mittag
sumber
2
"Memanggil fungsi najis secara otomatis membuat fungsi pemanggilan najis juga" Apakah Anda cukup yakin tentang itu? AFAICS, memanggil fungsi tidak murni tidak secara otomatis membuat pemanggil tidak murni, meskipun melakukannya mungkin.
Deduplicator
2
@Dupuplikator: tergantung seberapa banyak analisis statis yang dapat Anda lakukan (terganggu). Tentu, jika ada fungsi funcyang memiliki efek samping ketika Anda lulus dalam 0, tetapi tidak ketika Anda lulus dalam 1, maka Anda dapat mengatakan bahwa meskipun funcitu sendiri "tidak murni", sebuah fungsi menyebutnya sebagai func(1)(dan mengabaikan nilai kembali, mari kita katakanlah) belum tentu tidak murni. Memanggil funcsudah cukup untuk "mencemari" penelepon yang berpotensi tidak murni, tetapi fungsi yang tercemar dengan beberapa cara mungkin terbukti murni. Setidaknya dalam javascript, di mana murni / tidak murni tidak didefinisikan dalam bahasa.
Steve Jessop
6

Ya, keduanya adalah fungsi murni (dengan asumsi bagian yang elided juga murni) karena:

  1. Hasilnya hanya tergantung pada parameter.
  2. Tidak ada efek samping.

Perhatikan bahwa jika getDefaultSeparator()itu bukan fungsi murni, maka keduanya tidak akan process()murni.

Dalam Javascript, tidak ada perbedaan yang berarti antara menggunakan fungsi murni atau konstanta dan keduanya dapat digunakan oleh fungsi murni, selama kemampuan Javascript untuk mendefinisikan kembali fungsi atau mengubah nilai konstanta dihindari.

Konsep kunci di balik fungsi murni adalah bahwa mereka dapat diganti dengan nilai yang dikembalikan tanpa memengaruhi hasil program.

8bree
sumber
1

Seperti yang dikatakan orang lain, tentu saja, itu masih fungsi murni.

Namun, mari kita bicara tentang masalah desain. Anda benar untuk mencoba melakukan sesuatu untuk menjaga kode KERING, dengan meletakkan nilai hanya sekali tempat. Selain itu, yang menurut saya juga harus diperhatikan adalah level coupling yang tepat.

Menggunakan fungsi memberi Anda lebih banyak fleksibilitas untuk mengubah implementasi, yang berarti bahwa pendekatan fungsi menawarkan kopling yang lebih longgar daripada variabel global.

Pertanyaannya adalah apakah seseorang membutuhkannya atau tidak?

Jika konsumen dan penyedia berada dalam modul yang sama, dan penyedia adalah pribadi untuk modul, sulit untuk berpendapat bahwa tingkat longgar ini diperlukan, karena kenyataan bahwa jika penyedia memerlukan peningkatan dari variabel pribadi ke metode pribadi, refactoring sederhana dalam modul dapat diterapkan pada konsumen pada saat yang sama. Menggunakan metode / fungsi sebelum Anda benar-benar perlu bisa berada di bawah YAGNI.

Sekalipun konsumen (s) dan penyedia berada dalam modul yang berbeda, namun modul tersebut diversi versi bersama (misalnya, Anda menggunakan minifyer, sehingga modul konsumen dan penyedia berada di file yang sama), YAGNI juga dapat berlaku.

Di sisi lain, jika, misalnya, produsen berada di pustaka atau paket atau modul API yang diversi secara terpisah dari konsumen, maka menggunakan fungsi tersebut mungkin sesuai. Dalam hal ini kita harus melihat umur panjang API, dan prinsip-prinsip seperti OCP.

(Pada catatan lain, jika kode Anda memiliki ukuran yang signifikan, saya akan mendorong penggunaan modul dengan bidang dan metode daripada variabel dan fungsi global.)

Erik Eidt
sumber