Pertanyaan Tidak ada parameter bernama di Ruby?


Ini sangat sederhana sehingga saya tidak percaya itu menangkap saya.

def meth(id, options = "options", scope = "scope")
  puts options
end

meth(1, scope = "meh")

-> "meh"

Saya cenderung menggunakan hash untuk opsi argumen hanya karena itu adalah bagaimana kawanan melakukannya - dan itu cukup bersih. Saya pikir itu standar. Hari ini, setelah sekitar 3 jam berburu bug, saya menelusuri kesalahan pada permata ini saya kebetulan menggunakannya berasumsi parameter bernama akan dihormati. Mereka tidak.

Jadi, pertanyaan saya adalah ini: Apakah parameter bernama resmi tidak dihormati di Ruby (1.9.3), atau apakah ini merupakan efek samping dari sesuatu yang saya lewatkan? Jika tidak, mengapa tidak?


32
2018-03-08 03:30


asal


Jawaban:


Apa yang sebenarnya terjadi:

# Assign a value of "meh" to scope, which is OUTSIDE meth and equivalent to
#   scope = "meth"
#   meth(1, scope)
meth(1, scope = "meh")

# Ruby takes the return value of assignment to scope, which is "meh"
# If you were to run `puts scope` at this point you would get "meh"
meth(1, "meh")

# id = 1, options = "meh", scope = "scope"
puts options

# => "meh"

Tidak ada dukungan * untuk parameter bernama (lihat di bawah untuk pembaruan 2.0). Apa yang Anda lihat hanyalah hasil dari penetapan "meh" untuk scope dilewatkan sebagai options nilai dalam meth. Nilai dari tugas itu, tentu saja, adalah "meh".

Ada beberapa cara melakukannya:

def meth(id, opts = {})
  # Method 1
  options = opts[:options] || "options"
  scope   = opts[:scope]   || "scope"

  # Method 2
  opts = { :options => "options", :scope => "scope" }.merge(opts)

  # Method 3, for setting instance variables
  opts.each do |key, value|
    instance_variable_set "@#{key}", value
    # or, if you have setter methods
    send "#{key}=", value
  end
  @options ||= "options"
  @scope   ||= "scope"
end

# Then you can call it with either of these:
meth 1, :scope => "meh"
meth 1, scope: "meh"

Dan seterusnya. Mereka semua adalah solusi, karena kurangnya parameter bernama.


Sunting (15 Februari 2013):

* Yah, setidaknya hingga Ruby 2.0 mendatang, yang mendukung argumen kata kunci! Pada tulisan ini ada di rilis kandidat 2, yang terakhir sebelum rilis resmi. Meskipun Anda perlu mengetahui metode di atas untuk bekerja dengan 1.8.7, 1.9.3, dll., Mereka yang dapat bekerja dengan versi yang lebih baru sekarang memiliki opsi berikut:

def meth(id, options: "options", scope: "scope")
  puts options
end

meth 1, scope: "meh"
# => "options"

38
2018-03-08 04:32



Saya pikir 2 hal sedang terjadi di sini:

  1. Anda mendefinisikan parameter pada metode bernama 'lingkup' dengan nilai "cakupan" default
  2. Ketika Anda memanggil metode, Anda menetapkan nilai "meh" ke yang baru lokal variabel bernama 'scope', yang tidak terkait dengan nama parameter pada metode yang Anda panggil.

5
2018-03-08 03:35



Meskipun parameter bernama tidak didukung oleh bahasa Ruby, Anda dapat mensimulasikannya dengan meneruskan argumen fungsi Anda melalui hash. Sebagai contoh:

def meth(id, parameters = {})
  options = parameters["options"] || "options"
  scope = parameters["scope"] || "scope"

  puts options
end

Yang bisa digunakan sebagai berikut:

meth(1, scope: "meh")

Kode Anda yang ada hanya menetapkan varaible, kemudian meneruskan variabel tersebut ke fungsi Anda. Untuk informasi lebih lanjut, lihat: http://deepfall.blogspot.com/2008/08/named-parameters-in-ruby.html.


3
2018-03-08 04:01



Ruby tidak memiliki parameter bernama.

Contoh definisi metode memiliki parameter dengan nilai default.

Contoh situs panggilan memberikan nilai ke variabel lokal pemanggil-lingkup bernama cakupan dan kemudian melewati nilainya (meh) ke pilihan parameter.


0
2018-03-08 03:35