บล็อคใน Ruby

posted on 01 Apr 2009 23:38 by wonam  in softdev

(ไม่ใช่การบล็อคเว็บนะครับ)

มีหลายสาเหตุที่ทำให้ผมชอบภาษา Ruby ทั้ง ๆ ที่หลายคนคิดว่าไวยากรณ์มันช่างประหลาดสิ้นดี

ขอยกตัวอย่างเล่น ๆ ตัวอย่างหนึ่ง สมมติผมเขียนโปรแกรมสำหรับพิมพ์ค่าในรายการไว้ เป็นดังด้านล่าง

def print_array(a)
  a.each do |x|
    puts "#{x}"
  end
end

อธิบาย: 1. คำสั่ง each จะเรียก block ด้านหลัง (ตั้งแต่ do ถึง end) โดยส่งสมาชิกของรายการไปให้ทีละตัว block ด้านหลังนี่จะรับตัวแปรหนึ่งตัวคือ x เขียนในกรอบขีดตั้ง
2. การใส่ #{x} ในสตริงคือการให้เอาค่าตัวแปร x ไปแทนในส่วนนั้นของสตริง

เวลาใช้ก็ไม่มีอะไรครับ เรียก print_array([1,2,3,4]) ก็จะพิมพ์ผลลัพธ์ออกมา

แต่สมมติว่าผมอยากให้เมท็อดดังกล่าวเรียกแบบนี้ได้เลย [1,2,3,4].print ผมก็เอาเมท็อดดังกล่าวนี่ไปเพิ่มในคลาส Array ได้เลยครับ ดังด้านล่าง

class Array
  def print
    self.each do |x|
      puts "#{x}"
    end
  end
end

(จริง ๆ ไม่ควรเพิ่มอะไรในคลาสมาตรฐานแบบพร่ำเพรื่อแต่ว่า อันนี้แสดงให้ดูเป็นตัวอย่างนะครับ)

ทีนี้ ถ้าผมอยากจะให้เมท็อดนี้ปรับวิธีในการพิมพ์ได้ เช่นถ้าผมอยากจะพิมพ์เลขสุ่มตามหลังเลขในรายการ ใน Ruby มีวิธีในการส่งส่วนของโปรแกรม (ซึ่งเรียกว่า block) เข้าไปในเมท็อดได้ โดยจะเรียกประมาณนี้

[1,2,3,4].print do |x|
  puts "#{x} #{rand(100)}"
end

ก็สามารถทำได้ โดยเมท็อดข้างต้นก็จะเปลี่ยนไปเป็น

  def print
    self.each do |x|
      if block_given?
        yield x
      else
        puts "#{x}"
      end
    end
  end

เมท็อดด้านบนถ้าไม่ส่ง block มาก็จะพิมพ์ด้วยวิธีธรรมดาปกติครับ

ตัวอย่างนี้อาจจะดูเป็นของเล่นสักหน่อย แต่ว่าความสามารถในการ "จิ้ม" เอา block เป็นพารามิเตอร์ในเมท็อดได้แบบแนบเนียนสนิทนี้ ทำให้เราทำอะไรน่าสนุกใน Ruby ได้มากมาย เช่นการพัฒนา Domain Specific Language บน Ruby ครับ (จะเขียนถึงภายหลังถ้ามีเวลาครับ)

Comment



smilebig smileopen-mounthed smileconfused smilesad smileangry smiletonguequestionembarrassedsurprised smilewinkdouble winkcry

Tweet

อ. ช่วงนี้หัดเขียน Objectivec อยู่อะ

โครงสร้างก้อประหลาดๆ งงดีเหมือนกันอะคับ

#1 By xnanoob on 2009-04-02 10:22

ชอบ ruby มากๆครับ โดยเฉพาะ meta-programming นี่สุดยอด feature ของ ruby เลย big smile

#2 By Infinite Loop on 2009-11-01 18:08