เห็น python เขาครึกครื้น ส่วน ruby เราชั่งเหงาหงอย
งั้นมาเรียนรู้ ruby ผ่านโจทย์กันดีกว่า
เริ่มด้วย
ลองเขียน method ที่รับ input
[1,2,3,4,5,6,7,8,9]
แล้วให้ผลลัพท์เป็น
[[1,2,3],[4,5,6],[7,8,9]]
โดยจำนวนใน sub array เป็น parameter ที่ระบุได้
(เพื่อให้เกิดการเรียนรู้ข้ามภาษา
python ก็สามารถ submit code ได้ครับ)
กระทู้เก่าๆ จะย้ายตามไปในภายหลัง ตอนนี้ปิดการโพสต์กระทู้ไว้ เหลือไว้เฉพาะอ้างอิงเท่านั้น
ฝากตรวจการบ้าน Python ด้วยครับ http://www.codenone.com/node/22
เพิ่มเติม: อยากเห็น Erlang จังเลยครับ
ทำตั้งนาน :-P (ก็รู้สึกว่ายังไม่เท่ห์เท่าไหร่ แบบมันมีข้างหน้ายาวๆ)
แก้นิดนึง
แย่กว่าเดิมเปล่าเนี่ย -_-!
อธิบายหน่อยดิ
([nil] * (l.length / n.to_f).ceil).collect{|i| l.slice!(0,n) }collectนี่มันทำอะไร|i| l.slice!(0,n)นี่เอาไว้ทำอะไรa.collect{|i| func(i) } น่าจะคล้ายๆกับ map(func, a) ของ python ส่วน a.slice(0,n) ก็ประมาณ a[0:n] ของ python
a.slice! ก็คล้าย a.slice แต่ว่า จะแก้ค่าของ a ให้เป็น a[n:] ด้วย
ในที่สุด veer ก็ช่วย post :)
ค่อยยังชั่ว นึกว่าต้องถามเองตอบเองแล้ว
ยกตัวอย่างเพิ่มเติมให้คุณ sugree
method map กับ collect เหมือนกัน
operator
*ถูก define ใน Array classส่วน slice! กับ slice
ลองดู ที่คนอื่นเขาทำ แบบที่ 1 (แสดงว่ายังมีอีกหลายแบบ)
เขา define method
/สำหรับคนที่ยังไม่คุ้นกับ method
injectสำหรับแฟนไพธอน inject ก็คงจะคล้ายๆกับ reduce
ข้อดีของ Ruby ที่เห็นชัดๆ ในนี้ คือมันแก้ Array กันสดๆ เห็นแล้วทึ่งมาก Python หมดสิทธิ์
ว่าแต่ผมยังสงสัยเรื่อง Scope น่ะครับ ผลของการปรับแต่ง Array ครั้งนี้จะ
กรณี Array ที่เรา add method เข้าไป
ผลของมันจะ effect ทั้ง process ที่กำลังทำอยู่เลยครับ
effect จะเริ่มทันทีหลังจาก evaluate class definition
มีการ define อีกแบบ ที่มีผลเฉพาะ scope ของ Instance นั้นๆ
โอ้ ทำได้ทั้งสองแบบ มันน่าทึ่งมาก
ลืมบอกไป คนคิดอันที่ 1 คือคนที่ใช้ชื่อ nickname why ใน Redhanded.hobix.com
ส่วนแบบที่ 2 คน post ชื่อ Yxhuvud
เจ๋งมาก
อันนี้นี่เห็นแล้วต้องเพ่งซักพัก ;-)
ผมว่าอันนี้ดูง่ายสุดเลยนะ
อันบนๆ ผมแพ่งนานมั๊กๆ
เห็นแล้วปิ๊ง ใน Python 2.2 ทำแบบนี้ไม่ได้ แต่ 2.3 เป็นต้นมาก็ทำได้บ้างละน่า
enumerate()จะให้ index และ element ออกมาพร้อมๆ กันจึงมั่นใจได้ว่าจะได้ค่าปัจจุบันเสมอrange()ใช้ไม่ได้เพราะทำงานแค่ครั้งเดียวจริงๆคุณ sugree
พรุ่งนี้ผมจะ post solution ที่เป็น erlang ให้ครับ
ผมเก็บ code ใน thumb drive
แต่คุณลูกผมโชมย thumbdrive ไปนอนด้วยเสียนี่
ขอก็ไม่ยอมให้ กำแน่นเชียว
ลืมบอกไป
solution ของคุณ sugree, กับ ruby แบบที่ 1
เป็นวิธีที่ไม่ได้ใช้ destructive method
นั่นคือ state ของ list หลังจากที่เรียกใช้ method
จะยังเหมือนเดิมอยู่
ส่วนวิธีของ veer กับ ruby แบบที่ 2
เป็น destructive method
state ของ list จะเปลี่ยนไปหลังจากถูกเรียกใช้
ที่เขานิยมกัน ก็คือพยายามหลีกเลี่ยง destructive method
เพราะจะทำให้มีโอกาสเกิด bug ในอนาคตได้น้อยกว่า
ขอบคุณครับ มีสรุปเทคนิคให้ด้วย :-D
แบบที่ 3
อู๊ย เห็นแล้วใจสลาย
อ่านไม่รู้เรื่องเลย... ท่าจะมีอะไรเล่นเยอะ... ":each_slice"!!!
อันนี้ผมว่าเข้าใจง่ายดี แต่ว่าให้อยู่มานั่งนึกก็คงนึกแบบนี้ไม่ออก :-P
สุดท้าย จบลงด้วย benchmark ว่า 4 แบบข้างบน
อันไหนมี performance ดีกว่ากัน
ทดสอบ benchmark ตัด [1,2,3,4,5,6,7,8,9,10] ด้วย ขนาด sub array = 3
5000 ครั้ง
user system total real veer 0.150000 0.000000 0.150000 ( 0.094876) #1 0.316667 0.033333 0.350000 ( 0.206514) #2 0.116667 0.000000 0.116667 ( 0.070286) #3 0.166667 0.016667 0.183333 ( 0.104720)(python เร็วกว่าอยู่แล้ว กรุณาอย่ามาเปรียบเทียบให้ช้ำใจ)
เกิดความสงสัยทันทีที่เห็นโค้ดสวยๆ ไม่สามารถว่า
{}มันหมายถึงอะไรครับ inline function? รบกวนช่วยอธิบายวิธีทำงานของ บรรทัด 3 4 ซักนิด เท่าที่ผมเข้าใจBenchmarkเป็นโมดูล ส่วนbmเป็นฟังก์ชั่นdo |x|นี่แปลว่าเอาbmมาใช้ในชื่อxx.reportคือbm.reportนั่นเองn.timesคือ loop n ครั้งแต่
{}นี่งงแฮะ เห็นใช้ตอนcollectทีนึงแล้วnote: ผมเคยอ่าน Ruby ผ่านเมื่อหลายปีก่อน จำไม่ได้ซักอย่าง
{ } เป็น syntactic sugar ของ ruby ครับ
จริงๆมันก็คือ Proc Object หรือ lambda อันหนึ่งที่ pass เข้าไปใน method หรือ function ด้วย
เพียงแต่เราไม่ต้อง declare parameter ขึ้นมารับ
ปกติที่เขาเอาไปใช้กัน มันจะใช้คู่กับคำสั่ง yield
โดย yield คือการเรียกใช้ block ที่ pass เข้ามา
ถ้าเราลอง implement method collect เอง
มันก็น่าจะออกมาประมาณนี้