Apa perbedaan antara "def" dan "val" untuk mendefinisikan fungsi
Apa perbedaan antara:
def even: Int => Boolean = _ % 2 == 0
dan
val even: Int => Boolean = _ % 2 == 0
Keduanya dapat disebut seperti bahkan(10)
.
205
8
Metode
def bahkan
mengevaluasi dan menciptakan fungsi baru setiap waktu (contoh baru dariFunction1
).Dengan
def
, anda bisa mendapatkan fungsi baru pada setiap panggilan:val
mengevaluasi bila didefinisikan,def
- ketika disebut:Perhatikan bahwa ada pilihan ketiga:
malas val
.Mengevaluasi saat dipanggil pertama kali:
Tapi kembali hasil yang sama (dalam hal ini contoh sama
FunctionN
) setiap kali:Kinerja
val
mengevaluasi ketika didefinisikan.def
mengevaluasi pada setiap panggilan, sehingga kinerja bisa lebih buruk darival
untuk beberapa panggilan. Anda'll mendapatkan kinerja yang sama dengan satu panggilan. Dan dengan tidak ada panggilan anda'll mendapatkan tidak ada biaya overhead daridef
, sehingga anda dapat menentukan hal itu bahkan jika anda tidak akan menggunakannya dalam beberapa cabang.Dengan
malas val
anda'll mendapatkan malas evaluasi: anda dapat menentukan hal itu bahkan jika anda tidak akan menggunakannya dalam beberapa cabang, dan mengevaluasi sekali atau tidak pernah, tapi anda'll mendapatkan sedikit overhead dari double check penguncian pada setiap akses ke andamalas val
.Seperti @SargeBorsch mencatat anda bisa menentukan metode, dan ini adalah pilihan tercepat:
Tetapi jika anda membutuhkan sebuah fungsi (metode tidak) untuk fungsi komposisi atau fungsi orde tinggi (seperti
filter(bahkan)
) compiler akan menghasilkan sebuah fungsi dari metode anda setiap kali anda menggunakannya sebagai fungsi, sehingga kinerja bisa sedikit lebih buruk dibandingkan denganval
.Pertimbangkan ini:
Apakah anda melihat perbedaan? Singkatnya:
def: Untuk setiap panggilan untuk
bahkan
, itu panggilan tubuhbahkan
metode lagi. Tapi denganeven2
yaitu val, fungsi ini dijalankan hanya sekali saat deklarasi (dan karena itu cetakanval
pada baris 4 dan tidak pernah lagi) dan output yang sama digunakan setiap kali diakses. Misalnya, coba lakukan ini:Ketika
x
diinisialisasi, nilai yang dikembalikan olehAcak.nextInt
ditetapkan sebagai nilai akhir darix
. Waktu berikutnyax
digunakan lagi, itu akan selalu mengembalikan nilai yang sama.Anda dapat juga malas menginisialisasi
x
. yaitu pertama waktu yang digunakan adalah diinisialisasi dan tidak saat deklarasi. Misalnya:Melihat ini:
Anehnya, ini akan mencetak 4 dan 9! val (bahkan var) dievaluasi dan segera ditetapkan.
Sekarang perubahan val untuk def.. itu akan mencetak 9! Def adalah fungsi call.. ini akan mengevaluasi setiap kali itu disebut.
val yaitu "sq" adalah dengan Scala definisi tetap. Hal ini dievaluasi tepat pada saat deklarasi, anda dapat't perubahan nanti. Dalam contoh-contoh lain, di mana even2 juga val, tapi hal ini dinyatakan dengan fungsi khas yaitu "(Int => Boolean)", sehingga tidak tipe Int. Ini adalah fungsi dan's nilai yang diatur oleh ekspresi berikut
Sesuai Scala val properti, anda bisa't menetapkan fungsi lain untuk even2, aturan yang sama seperti sq.
Tentang mengapa panggilan eval2 val fungsi tidak percetakan "val" lagi dan lagi ?
Orig kode:
Kita tahu, di Scala terakhir pernyataan di atas semacam ekspresi (dalam { .. }) adalah benar-benar kembali ke sisi kiri. Jadi anda akhirnya menetapkan even2 untuk "x => x % 2 == 0" fungsi, yang sesuai dengan tipe anda menyatakan untuk even2 val jenis yaitu (Int => Boolean), jadi compiler adalah bahagia. Sekarang even2 hanya poin untuk "(x => x % 2 == 0)" fungsi (tidak lain pernyataan sebelumnya yaitu println("val") dll. Memohon event2 dengan parameter yang berbeda akan benar-benar memanggil "(x => x % 2 == 0)" kode, seperti hanya yang disimpan dengan event2.
Hanya untuk memperjelas hal ini lebih lanjut, berikut adalah versi yang berbeda dari kode.
Apa yang akan terjadi ? di sini kita melihat "di dalam akhir fn" dicetak lagi dan lagi, ketika anda menelepon even2().
Pelaksana definisi seperti
def x = e
tidak akan mengevaluasi ekspresi e. Dalam - manfaat e dievaluasi setiap kali x dipanggil.Atau, Scala menawarkan nilai definisi
val x = e
,yang tidak mengevaluasi kanan-sisi sebagai bagian dari evaluasi dari definisi. Jika x maka digunakan kemudian, ia segera digantikan oleh pra-dihitung nilai e, sehingga ekspresi tidak perlu dievaluasi lagi.Di REPL,
def berarti
call-by-name
, dievaluasi sesuai permintaanval berarti
call-by-value
, dievaluasi saat inisialisasiSelain di atas bermanfaat balasan, temuan saya adalah:
Di atas menunjukkan bahwa "def" adalah metode (dengan nol argumen parameter) yang mengembalikan fungsi lain "Int => Int" ketika dipanggil.
Konversi metode untuk fungsi ini juga dijelaskan di sini: https://tpolecat.github.io/2014/06/09/methods-functions.html
juga, Val adalah dengan nilai evaluasi. Yang berarti sisi kanan ekspresi dievaluasi pada definisi. Dimana Def dengan nama evaluasi. Itu tidak akan mengevaluasi sampai's digunakan.