Artikel ini saya translate dari sini. Tujuan saya translate artikel ini sebagai latihan saya dalam mempelajari bahasa inggris, disamping selain memahami isi materi artikel tersebut. Saya akui, saya belum memiliki izin dalam melakukan translate artikel tersebut :).

Pertanyaan

Pertanyaan ini di ajukan oleh Jam

Seperti yang saya pahami, di Scala,fungsi dapat dipanggil dengan 2 cara:

  • by-value, atau
  • by-name

Misalnya, diberi deklarasi berikut, apakah kita tahu bagaimana fungsi akan dipanggil?

1
def f(x: Int, y:Int) = x;

Panggil

1
2
3
f (1,2)
f (23+55,5)
f (12+3, 44*11)

Apa ketentuannya?

Jawaban

jawaban dari dhg

Contoh yang telah anda berikan hanya menggunakan call-by-value, jadi saya akan memberikan yang baru, sederhana, contoh yang menunjukkan perbedaan.

Pertama, mari kita asumsikan kita memiliki fungsi dengan side-effect. Fungsi ini mencetak sesuatu dan kemudian mengembalikan sebuah Int.

1
2
3
4
def something() = {
  println("calling something")
  1 //return value
}

Sekarang kita akan mendefinisikan dua fungsi yang menerima argumen Int yang persis sama kecuali yang satu membutuhkan argumen dalam gaya call-by-value (x: Int) dan yang lainnya dalam gaya call-by-name (x: => Int)

call-by-value
1
2
3
4
def callByValue(x: Int) = {
  println("x1=" + x)
  println("x2=" + x)
}
call-by-name
1
2
3
4
def callByName(x: => Int) = {
  println("x1=" + x)
  println("x2=" + x)
}

Sekarang apa yang terjadi ketika kita memanggilnya dengan fungsi side-effect kita?

call-by-name
1
2
3
4
5
6
7
8
9
10
scala> callByValue(something())
calling something
x1=1
x2=1

scala> callByName(something())
calling something
x1=1
calling something
x2=1

Sehingga anda dapat melihat bahwa dalam versi call-by-value, side-effect dari pemanggilan fungsi something() hanya terjadi sekali. Namun, dalam versi call-by-name, side-effect terjadi dua kali.

Hal ini karena fungsi call-by-value menghitung nilai ekspresi yang diberikan sebelum memanggil fungsi, sehingga nilai yang sama setiap kali diakses. Namun, fungsi call-by-name menghitung ulang nilai ekspresi yang diberikan setiap kali ia diakses.

jawaban dari Behrooz Tabesh

Berikut ini adalah contoh dari Martin Odersky (penemu scala)

1
def test (x: Int, y: Int) = x * x

Kita ingin tahu evaluasi mana yang lebih cepat (langkah sedikit) dalam kondisi ini:

test (2, 3)

call-by-value
1
2
3
test(2, 3)
2 * 2
4
call-by-name
1
2
3
test(2, 3)
2 * 2
4

jadi 2 evaluasi disini sama

test(3+4, 8)

call-by-value
1
2
3
4
test(3+4, 8)
test(7, 8)
7 * 7
49
call-by-name
1
2
3
4
5
test(3+4, 8)
(3+4) * (3 + 4)
7 * (3 + 4)
7 * 7
49

disini call-by-value lebih cepat

test(7, 2*4)

call-by-value
1
2
3
4
test(7, 2*4)
test(7, 8)
7 * 7
49
call-by-name
1
2
3
test(7, 2*4)
7 * 7
49

disini, call-by-name lebih cepat

test(3+4, 2*4)

call-by-value
1
2
3
4
5
test(3+4, 2*4)
test(7, 2*4)
test(7, 8)
7 * 7
49
call-by-name
1
2
3
4
5
test(3+4, 2*4)
(3+4) * (3+4)
7 * (3+4)
7 * 7
49

lagi, keduanya sama.

jawaban dari kaos12

Dalam kasus conton mu semua parameter akan dievaluasi sebelum fungsi tersebut dipanggil, karena kamu hanya mendefiniskan mereka by-value. Jika kamu ingin mendefinisikan parameter kamu by-name, kamu harus melewatkan kode block:

1
def f(x: => Int, y:Int) =x

Dengan cara ini parameter x akan dievaluasi sampai dipanggil dalam fungsi.

Comments