68

ruby で私が気に入っていることの 1 つは、ほとんどの場合、非常に読みやすい言語であることです (これは、自己文書化コードに最適です)。

しかし、次の質問に触発されて: Ruby Code Explainedと ruby ​​ でどのように||=機能するかについての説明、私は使用しない Ruby イディオムについて考えていました。

だから私の質問は、参照された質問の例と同様に、真に熟練したRubyプログラマーになるために知っておく必要がある、一般的であるが明白ではないRubyのイディオムは何ですか?

ちなみに参考にした質問より

a ||= b 

と同等です

if a == nil || a == false
  a = b
end

(修正してくれた Ian Terrell に感謝)

編集:この点は完全に議論の余地がないわけではない. 実は正しい展開は

(a || (a = (b))) 

理由については、次のリンクを参照してください。

これを指摘してくれた Jörg W Mittag に感謝します。

4

15 に答える 15

52

同じファイルをライブラリまたはスクリプトとして機能させるマジック if 句:

if __FILE__ == $0
  # this library may be run as a standalone script
end

配列のパッキングとアンパッキング:

# put the first two words in a and b and the rest in arr
a,b,*arr = *%w{a dog was following me, but then he decided to chase bob}
# this holds for method definitions to
def catall(first, *rest)
  rest.map { |word| first + word }
end
catall( 'franken', 'stein', 'berry', 'sense' ) #=> [ 'frankenstein', 'frankenberry', 'frankensense' ]

メソッド引数としてのハッシュの構文シュガー

this(:is => :the, :same => :as)
this({:is => :the, :same => :as})

ハッシュ初期化子:

# this
animals = Hash.new { [] }
animals[:dogs] << :Scooby
animals[:dogs] << :Scrappy
animals[:dogs] << :DynoMutt
animals[:squirrels] << :Rocket
animals[:squirrels] << :Secret
animals #=> {}
# is not the same as this
animals = Hash.new { |_animals, type| _animals[type] = [] }
animals[:dogs] << :Scooby
animals[:dogs] << :Scrappy
animals[:dogs] << :DynoMutt
animals[:squirrels] << :Rocket
animals[:squirrels] << :Secret
animals #=> {:squirrels=>[:Rocket, :Secret], :dogs=>[:Scooby, :Scrappy, :DynoMutt]}

メタクラス構文

x = Array.new
y = Array.new
class << x
  # this acts like a class definition, but only applies to x
  def custom_method
     :pow
  end
end
x.custom_method #=> :pow
y.custom_method # raises NoMethodError

クラスインスタンス変数

class Ticket
  @remaining = 3
  def self.new
    if @remaining > 0
      @remaining -= 1
      super
    else
      "IOU"
    end
  end
end
Ticket.new #=> Ticket
Ticket.new #=> Ticket
Ticket.new #=> Ticket
Ticket.new #=> "IOU"

ブロック、プロシージャ、およびラムダ。それらを生きて呼吸します。

 # know how to pack them into an object
 block = lambda { |e| puts e }
 # unpack them for a method
 %w{ and then what? }.each(&block)
 # create them as needed
 %w{ I saw a ghost! }.each { |w| puts w.upcase }
 # and from the method side, how to call them
 def ok
   yield :ok
 end
 # or pack them into a block to give to someone else
 def ok_dokey_ok(&block)
    ok(&block)
    block[:dokey] # same as block.call(:dokey)
    ok(&block)
 end
 # know where the parentheses go when a method takes arguments and a block.
 %w{ a bunch of words }.inject(0) { |size,w| size + 1 } #=> 4
 pusher = lambda { |array, word| array.unshift(word) }
 %w{ eat more fish }.inject([], &pusher) #=> ['fish', 'more', 'eat' ]
于 2009-03-05T09:27:09.010 に答える
11

このスライドショーは、次のように、主要な Ruby イディオムについて非常に完全です。

  • 2 つの値を交換します。

    x, y = y, x

  • 指定されていない場合、何らかのデフォルト値を取るパラメータ

    def somemethod(x, y=nil)

  • 不要なパラメータを配列にまとめます

    def substitute(re, str, *rest)

等々...

于 2009-03-05T09:22:29.347 に答える
8

さらにいくつかのイディオム:

%w%rおよび%(区切り文字の使用

%w{ An array of strings %}
%r{ ^http:// }
%{ I don't care if the string has 'single' or "double" strings }

caseステートメントのタイプ比較

def something(x)
  case x
    when Array
      # Do something with array
    when String
      # Do something with string
    else
      # You should really teach your objects how to 'quack', don't you?
  end
end

===...そしてcaseステートメントでのメソッドの全体的な乱用

case x
  when 'something concrete' then ...
  when SomeClass then ...
  when /matches this/ then ...
  when (10...20) then ...
  when some_condition >= some_value then ...
  else ...
end

Rubyistには自然に見えるはずですが、他の言語から来た人にはそうではないかもしれませんeachfor .. in

some_iterable_object.each{|item| ... }

Ruby 1.9以降、Rails、またはSymbol#to_procメソッドにパッチを適用することにより、これはますます人気のあるイディオムになりつつあります。

strings.map(&:upcase)

条件付きメソッド/定数定義

SOME_CONSTANT = "value" unless defined?(SOME_CONSTANT)

クエリメソッドと破壊的(バング)メソッド

def is_awesome?
  # Return some state of the object, usually a boolean
end

def make_awesome!
  # Modify the state of the object
end

暗黙のスプラットパラメータ

[[1, 2], [3, 4], [5, 6]].each{ |first, second| puts "(#{first}, #{second})" }
于 2010-07-04T21:47:35.723 に答える
7

私はこれが好き:

str = "Something evil this way comes!"
regexp = /(\w[aeiou])/

str[regexp, 1] # <- This

これは(おおよそ)以下と同等です:

str_match = str.match(regexp)
str_match[1] unless str_match.nil?

または、少なくともそれは、そのようなブロックを置き換えるために使用したものです。

于 2009-03-05T09:08:46.247 に答える
7

よくデザインされた人気のあるプラグインのコードや、あなたが賞賛し尊敬する人々の宝石を読むことをお勧めします。

私が遭遇したいくつかの例:

if params[:controller] == 'discussions' or params[:controller] == 'account'
  # do something here
end

対応する

if ['account', 'discussions'].include? params[:controller]
  # do something here
end

これは後でリファクタリングされます

if ALLOWED_CONTROLLERS.include? params[:controller]
  # do something here
end
于 2009-03-05T09:27:51.770 に答える
5

ちなみに参考にした質問より

a ||= b 

と同等です

if a == nil   
  a = b 
end

これは微妙に間違っており、初心者の Ruby アプリケーションのバグの原因となっています。

両方 (およびのみ)nilfalseがブール値の false に評価されるため、a ||= b実際には (ほぼ*) 以下と同等です。

if a == nil || a == false
  a = b
end

または、別の Ruby イディオムで書き直すと、次のようになります。

a = b unless a

(*すべてのステートメントには値があるため、技術的には と同等ではありませんa ||= b。ただし、ステートメントの値に依存していなければ、違いはわかりません。)

于 2009-03-05T15:23:49.120 に答える
5

さまざまな情報源から抜粋したいくつかを次に示します。

「if not」と「while not」の代わりに「unless」と「until」を使用してください。ただし、「else」条件が存在する場合は「unless」を使用しないようにしてください。

一度に複数の変数を割り当てることができることに注意してください。

a,b,c = 1,2,3

一時なしで変数をスワップすることさえできます:

a,b = b,a

必要に応じて末尾の条件を使用します。

do_something_interesting unless want_to_be_bored?

クラスメソッドを定義する一般的に使用されているが、すぐには明らかではない (少なくとも私には) 方法に注意してください。

class Animal
  class<<self
    def class_method
      puts "call me using Animal.class_method"
    end
  end
end

参考文献:

于 2009-03-05T09:47:55.433 に答える
4

私はいくつかのRubyイディオムとフォーマットをカバーするwikiページを維持しています:

https://github.com/tokland/tokland/wiki/RubyIdioms

于 2011-09-27T13:42:44.363 に答える
2

私はいつも、この if else ステートメントの正確な構文を忘れます (そして、演算子の名前. コメントはありますか?) Ruby 以外で広く使用されていると思いますが、他の誰かがこの構文を必要とする場合に備えて、次のようにします:

refactor < 3 ? puts("No need to refactor YET") : puts("You need to refactor this into a  method")

に展開します

if refactor < 3
  puts("No need to refactor YET")
else
  puts("You need to refactor this into a  method")
end

アップデート

三項演算子と呼ばれます:

myvar を返しますか? myvar.size: 0

于 2011-10-25T17:53:18.167 に答える
1
a = (b && b.attribute) || "default"

おおよそ次のとおりです。

if ( ! b.nil? && ! b == false) && ( ! b.attribute.nil? && ! b.attribute.false) a = b
else a = "default"

これは、b が見つかった場合と見つからなかった場合があるレコードであり、その属性の 1 つを取得する必要がある場合に使用します。

于 2011-03-09T20:13:42.867 に答える
1

Marshaling オブジェクトで簡単にディープコピーできます。- Ruby プログラミング言語から引用

def deepcopy(o)
  Marshal.load(Marshal.dump(o))
end

ファイルと I/O ストリーム、および Method オブジェクトと Binding オブジェクトは動的すぎてマーシャリングできないことに注意してください。それらの状態を復元する信頼できる方法はありません。

于 2010-07-04T21:13:23.980 に答える
1

If-then-elses または case-when は値を返すため、短縮できる点が気に入っています。

if test>0
  result = "positive"
elsif test==0
  result = "zero"
else
  result = "negative"
end

書き直せる

result = if test>0
  "positive"
elsif test==0
  "zero"
else
  "negative"
end

case-when にも同じことが適用できます。

result = case test
when test>0 ; "positive"
when test==0 ; "zero"
else "negative"
end
于 2012-02-09T00:51:51.967 に答える
0

バイナリ ファイルを操作するための Array.pack および String.unpack:

# extracts four binary sint32s to four Integers in an Array
data.unpack("iiii") 
于 2010-03-28T09:49:34.713 に答える
0

メソッドが見つからない

class Dummy  
  def method_missing(m, *args, &block)  
    "You just called method with name #{m} and arguments- #{args}"  
  end  
end

Dummy.new.anything(10, 20)
=> "You just called method with name anything and arguments- [10, 20]"

Rubyオブジェクトに存在しないメソッドを呼び出すと、Rubyインタープリターは「method_missing」というメソッドが定義されている場合に呼び出します。これを使用して、すべてのメソッドとパラメーターがわからないAPIラッパーやDSLを作成するなどのトリックを行うことができます名前

于 2014-06-20T10:13:42.753 に答える