Blocks, Procs, Lambdas Dalam Ruby

Apa itu blocks?

Blocks adalah serangkaian kode di antara do-end atau kurung kurawal {}. Berikut adalah block yang diapit oleh do-end :

irb(main):001:0> 2.times do 
irb(main):002:1* puts "Muslih"
irb(main):003:1> end
Muslih
Muslih
=> 2

Dan dibawah ini adalah blocks yang diapit oleh kurung kurawal :”

irb(main):004:0> 2.times {p "Dodol"}
"Dodol"
"Dodol"
=> 2

Apa itu procs?

Proc adalah sebuah prosedur, atau boleh dibiliang serangkaian kode. Sintak Proc tampak seperti di bawah ini

irb(main):005:0> Proc.new{"Pray, eat, and code"}
=> #<Proc:0x89996b8@(irb):5>
irb(main):006:0> Proc.new{"Pray, eat, and code"}.call
=> "Pray, eat, and code"
irb(main):007:0> Proc.new{"Pray, eat, and code"}.class
=> Proc

Hmmm….lalu sama dong antara proc dan block?

Iya, sama-sama ada huruf C nya, hahaha…. Gini, anda pernah mendengar semua yang ada di ruby itu adalah objek? itu semua bohong!! Lho, kok bisa?

Jadi gini, semua yang ada di ruby itu memang objek, tapi blocks adalah pengecualian! Ya, block tidak dapat di simpan ke dalam variable, karena itulah anda tidak bisa menggunakan blocks tertentu lebih dari satu kali! seperti contoh di bawah ini :

irb(main):005:0> coba_block = 2.times {p "Budi makan batu!"}
"Budi makan batu!"
"Budi makan batu!"
=> 2
irb(main):006:0> coba_block
=> 2
irb(main):007:0> coba_block.class
=> Fixnum
irb(main):008:0> 

Berbeda dengan procs yang bisa menyimpan ke dalam variable, dan ini adalah objek pastinya, ini bisa dipakai berkali kali sesuka hati anda!

irb(main):011:0> proc = Proc.new{"Batu dimakan budi"}                                                                                          
=> #<Proc:0x8921334@(irb):11>
irb(main):012:0> proc.neww
irb(main):013:0> proc.call
=> "Batu dimakan budi"

Apa itu lambdas?

Lambdas adalah subtipe dari procs. Cara penulisan lambda bisa anda lihat dibawah ini:

irb(main):016:0> lambda {puts "saya sarapan di malam hari"}
=> #<Proc:0x88de430@(irb):16 (lambda)>
irb(main):017:0> lambda {puts "saya sarapan di malam hari"}.call
saya sarapan di malam hari
=> nil
irb(main):018:0> lambda {puts "saya sarapan di malam hari"}.class
=> Proc

Tuh kan, pas saya masukan method class yang keluar adalah proc, ini berarti Lambda adalah sebuah objek, dan tentunya bisa kita simpan sebagai variable, dan bisa digunakan kembali. Bila anda familiar dengan If you’re *anonymous functions/methods * pada bahasa pemograman lain, itulah lambda dalam Ruby :)

irb(main):002:0> contoh_lambda = lambda { return "hidup sederhana dan belajar selamanya"}
=> #<Proc:0x97fc4e4@(irb):2 (lambda)>
irb(main):003:0> contoh_tambda.call
=> "hidup sederhana dan belajar selamanya"
irb(main):004:0> 

Lalu apa yang membuat berbeda antara lambda dan Proc? bukankah mereka sama?!

Mereka berdua serupa tapi tak sama :D, perbedaan antara keduanya pun susah dilihat secara kasat mata, wkkkk… ya ada dua perbedaan yang mendasar selain perbedaan syntaks tentunya

1. Argument

Lambda akan mencek terlebih dahulu jumlah argumen-argumen yang dilauinya, berbeda dengan Procs yang masa bodo’ dengan jumlah argumen yang ada!

Bila anda coba untuk memasang beberapa argumen pada lambda, anda akan mendapatkan hadiah error.

irb(main):005:0> arg = lambda {|x| puts x}
=> #<Proc:0x929a488@(irb):5 (lambda)>
irb(main):006:0> arg.call(2)
2
=> nil
irb(main):007:0> arg.call
ArgumentError: wrong number of arguments (0 for 1)
        from (irb):5:in `block in irb_binding'
        from (irb):7:in `call'
        from (irb):7
        from /usr/local/bin/irb:12:in `<main>'
irb(main):008:0> arg.call(1,2,3)
ArgumentError: wrong number of arguments (3 for 1)
        from (irb):5:in `block in irb_binding'
        from (irb):8:in `call'
        from (irb):8
        from /usr/local/bin/irb:12:in `<main>'
irb(main):009:0> 

Namun, bila anda coba untuk untuk memasang beberapa argumen pada pada Proc, maka ia akan melakukan :

  • Mengambil keputusan dengan mengubah argumen lain menjadi nil
  • Menolak argumen tambahan, yah bisa dibilang yang lain dicuekin lah :D
  • Jalan normal seperti biasa
irb(main):009:0> proc = Proc.new { |x| puts x}
=> #<Proc:0x924c5bc@(irb):9>
irb(main):010:0> proc.call(2)
2
=> nil
irb(main):011:0> proc.call

=> nil
irb(main):012:0> proc.call(1,2,3)
1
=> nil
irb(main):013:0> 

2. Flow (alur)

Lambdas memiliki keuntungan kecil. Yap, sebuah lambda ketika di return , ia akan kembali mengontrol untuk memanggil block/method. Ketika Proc di return, ia akan segera berhenti memproses semua blok/method yang ada!!

irb(main):013:0> def lambda_coba
irb(main):014:1>   lam = lambda { return }
irb(main):015:1>   lam.call
irb(main):016:1>   puts "Halo dunia"
irb(main):017:1> end
=> nil
irb(main):018:0> lambda_coba
Halo dunia
=> nil
irb(main):019:0> def proc_coba
irb(main):020:1>   proc = Proc.new { return }
irb(main):021:1>   proc.call
irb(main):022:1>   puts "Hello world"
irb(main):023:1> end
=> nil
irb(main):024:0> proc_coba
=> nil

Masih bingung kan? Saya yakin anda masih bingung, tapi mari kita lihat contoh-contoh berikut ini agar kebingungan yang menimpa anda terobati :D

Mari kita lihat lambda yang menampilkan error :

irb(main):001:0> contoh_lambda = lambda {|nama| puts "nama saya #{nama}"}
=> #<Proc:0x961ff54@(irb):1 (lambda)>
irb(main):002:0> contoh_lambda.call("Muslih")
nama saya Muslih
=> nil
irb(main):003:0> contoh_lambda.call("Muslih", "Iwan","Wawan","Syairi","Ari")
ArgumentError: wrong number of arguments (5 for 1)
        from (irb):1:in `block in irb_binding'
        from (irb):3:in `call'
        from (irb):3
        from /usr/local/bin/irb:12:in `<main>'
irb(main):004:0> 

Dan ini Proc yang tidak menampilkan error :

irb(main):011:0> contoh_proc = Proc.new {|nama| puts "Nama saya #{nama}"}
=> #<Proc:0x95cc570@(irb):11>
irb(main):012:0> contoh_proc.call("Muslih")
Nama saya Muslih
=> nil
irb(main):013:0> contoh_proc.call("Muslih", "Iwan","Wawan","Syairi","Ari")
Nama saya Muslih
=> nil
irb(main):014:0> 

Coba anda lihat, siapa yang akan di dukung lambda bila terjadi perkelahian di sungai kalimantan :

irb(main):014:0> def perang
irb(main):015:1> menang = lambda{return "Palui menang melawan garbus di sungai"}
irb(main):016:1> menang.call
irb(main):017:1> return "Garbus menang melawan Palui di sungai"
irb(main):018:1> end
=> nil
irb(main):019:0> perang
=> "Garbus menang melawan Palui di sungai"
irb(main):020:0> 

dan siapakah yang akan di dukung Proc bila terjadi perkelahian di sungai kalimantan :

irb(main):020:0> def perang
irb(main):021:1> menang = Proc.new{return "Palui menang melawan garbus di sungai"}
irb(main):022:1> menang.call
irb(main):023:1> return "Garbus menang melawan Palui di sungai"
irb(main):024:1> end
=> nil
irb(main):025:0> perang
=> "Palui menang melawan garbus di sungai"
irb(main):026:0> 

Selamat berpusing ria, tapi menurut saya ga bikin pusing2 amat, amat aja ga pusing soalnya! :D Terakhir, seorang ex-biomedical engineer yang sekarang banting setir menjadi seorang web developer pernah berkata

Blocks, Procs, and lambdas are closures. Conquer these, and you conquer the world.

rss facebook twitter github youtube mail spotify instagram linkedin google pinterest medium vimeo