Ruby method parameters
Bài đăng này đã không được cập nhật trong 4 năm

Khi làm việc với các method trong ruby, các bạn có thể gặp các trường hợp tham số được định nghĩa trong method sẽ có dạng: *args, **kwargs, &block, ... Vậy chúng là gì, hôm nay ta sẽ tìm hiểu về vấn đề này thông qua ruby method parameters

Default parameters
- Khi định nghĩa một method, ta có thể chỉ ra giá trịdefault(mặc định) cho chúng. Khimethodđược gọi, nếu các giá trịarguments(đổi số) ít hơn những giá trịparameters(tham số) được khai báo trước đó thì những tham số mặc định sẽ sử dụng những giá trị được gán mặc định đó.def info(name, sex="male") puts "Name: #{name}, with sex: #{sex}" end info("huy", "female") # => Name: huy, with sex: female info("huy") # => Name: huy, with sex: male
- Nếu trong định nghĩa methodcó nhiều hơn mộtdefault parameterthì nhữngparametersnày phải được đặt liền kề nhau. Ví dụ, không thể đặt mộtparameterkhác nằm giữa haidefault parameterđược.
- methodcó nhiều hơn một- default parameterkhi được thực thi với một danh sách các- argumentsđược truyền vào, thì những- argumentsnày sẽ được gắn giá trị cho các- default parameterstừ trái sang phải:- def f(a, b=1, c=2) puts a, b, c end f(10) # => 10, 1, 2 f(10, 100) # => 10, 100, 2 f(10, 100, 200) # => 10, 100, 200
Parameter with splat operator (*)
- Tham số kiểu mảng được gắn dấu *phía trước được sử dụng khi muốn truyền một mảng các đối số bất kỳ:def f(first, *rest) puts rest, rest.class end f(1, 2, 3, 4) # => [2, 3, 4], Array
- Một methodcó không quá một tham số loại này, tham số kiểu mảng phải theo liền kề sau những tham số mặc định, và có thể đứng trước các tham số bình thường khác:def f(a=1, *args, b) puts "a: #{a}, args: #{args}, b: #{b}" end f(10, 20, 30, 40) # => a: 10, args: [20, 30], b: 40
- Ngoài ra, *còn được sử dụng khi ta muốn truyền một mảng các đối số khi gọimethod:
    def f(name, age, sex)
        puts name, age, sex
    end
    
    user = ["sherlock", 20, "male"]
    f(*user)
    # => sherlock, 20, male
Mapping arguments to parameters
Ta sẽ tìm hiểu cách ruby gán các đối số được truyền tới các tham số đã được định nghĩa trong method.
Giả sử một method có o tham số original (tham số thường), d tham số được gán giá trị mặc định, 1 tham số kiểu mảng. method được gọi với a đối số, khi đó:
- Nếu a < o: lỗiArgumentErrorxảy ra
- Nếu o <= a <= o+d:a-otham số mặc định sẽ được gán giá trị, phần còn lại,o+d-atham số mặc định sẽ sử dụng giá trị mặc định ban đầu.
- Nếu a > o+d:a-o-dđối số được truyền vào sẽ gán cho tham số mảng cuối cùng
Using hash for named arguments
Khi một method yêu cầu nhiều hơn 2 hoặc 3 tham số sẽ rất khó trong việc thực thi method này, ta cần phải nhớ hết thứ tự của tất cả các tham số này khi truyền các đối số vào. Đễ giải quyết vấn đề này, trong ruby ta có thể sử dụng hash argument:
  def f(opts)
    puts opts
  end
  
  f({name: "huy", age: 11}) 
  # => {:name=>"huy", :age=>11}
- Nếu trong methodtham số dạng hash nằm ở cuối cùng (hoặc theo sau nó là mộtblock), ta có thể bỏ qua dấu{}khi gọimethodđó:f(name: "huy", age: 11) # => {:name=>"huy", :age=>11}
Parameter with double splat (**) operator
Một cách nữa để khai báo tham số kiểu hash: dùng **:
  def f(**hash)
      puts hash
  end
  
  f(a: 1, b: 2)
  # => {:a=>1, :b=>2}
  f()
  # Nếu không truyền đối số nào, mặc định cho `hash` sẽ là `{}`
  # => {}
Block arguments with (&)
- Một blockcó thể được truyền vào khi gọimethod:
 Nếu trong danh sách tham số không códef f(name, &block) yield name end f("sherlock") { |name| puts name } # => sherlock&,blockvẫn có thể được truyền vào qua{}hoặcdo; ;end
- Lưu ý rằng tham số với &chỉ được định nghĩa một lần duy nhất, và nó phải được đặt ở vị trí cuối cùng trong danh sách:
  def f(&block, &other_block)
    ...
   end
  # => syntax error, unexpected ',', expecting ')'
  
  def f(&block, name)
    ...
   end
   
   # => syntax error, unexpected ',', expecting ')'
All rights reserved