Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

11 เทคนิค Ruby ขั้นสูงที่คุณอาจพลาด

หา Ruby tricks ที่เก๋ๆ? เจอแล้ว! ในบทความนี้จะแชร์โปรดของผม

สารบัญ

  • 1 Deep copy
  • 2 วิธีต่างๆ เรียก lambda
  • 3 สร้าง pre-filled array
  • 4 True, false และ nil เป็น objects
  • 5 Lambdas strict เรื่อง arguments แต่ Procs ไม่สนใจ
  • 6 รันโค้ดโดยตรงโดยไม่ต้อง irb หรือไฟล์
  • 7 Mini-irb ของตัวเองในคำสั่งเดียว
  • 8 Unfreeze object (อันตราย!)
  • 9 Objects ที่มี special identity
  • 10 หลีกเลี่ยง big output ใน irb หรือ pry
  • 11 ใช้ caller method ดึง call stack ปัจจุบัน
  • 12 Bonus! แปลงค่าใดๆ เป็น boolean
  • 13 Bonus! ใช้ Keyword เป็น Variable Name
  • 14 สรุป
    • 14.1 Related

Deep copy

ตอน copy object ที่มี object อื่นอยู่ภายใน เช่น Array จะ copy แค่ reference ของ object เหล่านั้น

เห็นได้ที่นี่:

food = %w( bread milk orange )
food.map(&:object_id) # [35401044, 35401020, 35400996]
food.clone.map(&:object_id) # [35401044, 35401020, 35400996]

ใช้ class Marshal (ปกติใช้ serialization) สร้าง 'deep copy' ได้:

def deep_copy(obj)
  Marshal.load(Marshal.dump(obj))
end

ผลลัพธ์:

deep_copy(food).map(&:object_id) # [42975648, 42975624, 42975612]

วิธีต่างๆ เรียก lambda

my_lambda = -> { puts 'Hello' }
my_lambda.call
my_lambda[]
my_lambda.()
my_lambda.===

ถ้าเป็นไปได้ควรใช้ตัวแรก (call) เพราะคนส่วนใหญ่รู้จัก

สร้าง pre-filled array

Array class รับ argument + block ให้สร้าง array n elements ค่า default เป็น nil แต่ถ้ามี block ค่าจะมาจาก block

ตัวอย่าง:

Array.new(10) { rand 300 }

สร้าง array 10 ตัวเลขสุ่มระหว่าง 0-299

True, false และ nil เป็น objects

true.class # TrueClass
false.class # FalseClass
nil.class # NilClass

มีเพียงหนึ่ง copy ของ objects เหล่านี้ สร้างเพิ่มไม่ได้แม้จะอยาก นี่คือ singleton pattern ในการทำงาน

Lambdas strict เรื่อง arguments แต่ Procs ไม่สนใจ

my_lambda = ->(a, b) { a + b }
my_proc = Proc.new { |a, b| a + b }
my_lambda.call(2) # ArgumentError: wrong number of arguments (1 for 2)
my_proc.call(2) # TypeError: nil can't be coerced into Fixnum

รันโค้ดโดยตรงโดยไม่ต้อง irb หรือไฟล์

คำสั่ง ruby มี options น่าสนใจ เช่น flag -e ส่ง code snippet ให้ execute

ruby -e '5.times { puts "Fun with Ruby" }'

หาเพิ่มได้ด้วย flag -h

Mini-irb ของตัวเองในคำสั่งเดียว

เคยอยากรู้ irq ทำงานอย่างไร? นี่คือ super-simple version จำว่า 'REPL' ย่อมาจาก: Read-Eval-Print Loop

ruby -n -e 'p eval($_)'

ไม่ได้ prompt แต่ไป ahead พิมพ์ Ruby code ได้

"A" * 5
"AAAAA"

ทำงานเพราะ flag -n ทำอย่างนี้:

-n assume 'while gets(); ... end' loop around your script

และ $_ เป็น global variable มีค่า:

The last input line of string by gets or readline.

Unfreeze object (อันตราย!)

ไม่มี Ruby method unfreeze object แต่用 Fiddle class เข้า Ruby internals ทำได้

require 'fiddle'
str = 'water'.freeze
str.frozen? # true
memory_address = str.object_id * 2
Fiddle::Pointer.new(memory_address)[1] &= ~8
str.frozen? # false

อย่าลองที่บ้าน!

Objects ที่มี special identity

Ruby objects มี identifier หรือ 'id' number เข้าถึงได้ด้วย object_id บาง objects มี fixed id: Fixnums, true, false, nil

false.object_id # 0
true.object_id # 2
nil.object_id # 4
1.object_id # 3
2.object_id # 5

Fixnum ids ใช้สูตร: (number * 2) + 1 Bonus: Fixnum สูงสุดคือ 1073741823 หลังนั้นได้ Bignum object

หลีกเลี่ยง big output ใน irb หรือ pry

ถ้าทำงานใน irb อยากหลีกเลี่ยงเติมหน้าจอด้วย huge array หรือ string ให้ append ; ท้ายโค้ด

ตัวอย่าง:

require 'rest-client'
RestClient.get('www.rubyguides.com');

ลองอีกครั้งไม่มี ; ดูความต่าง 🙂

ใช้ caller method ดึง current call stack

ตัวอย่างโค้ด:

def foo
  bar
end
def bar
  puts caller
end
foo

Output:

-:3:in 'foo'
-:10:in '<main>'

ถ้าต้องการ current method name ใช้ __method__ หรือ __callee__

Bonus! แปลงค่าใดๆ เป็น boolean

!!(1) # true
!!(nil) # false

Bonus! ใช้ Keyword เป็น Variable Name

def foo (if: nil)
  binding.local_variable_get(:if)
end
foo(if: true)

สรุป

หวังว่าจะชอบ Ruby tricks นี้! แชร์ให้เพื่อนๆ และ สมัครรับ blog ในฟอร์มด้านล่างเพื่อไม่พลาดโพสต์ถัดไป 🙂