`メソッド`メソッドを楽しむ
ブロックのみを受け取る関数にメソッドを渡したいと思ったことはありませんか?または、オブジェクトのどのスーパークラスが、呼び出そうとしているメソッドを壊したかを把握しますか?
これらはmethod
で簡単に実行できます メソッド。 これを上手に使用すると、依存関係について学び、デバッグの時間を節約し、コードを必要な場所に配置できます。
多くのRubyメソッドはブロックまたはラムダを取ります。ただし、ラムダの場合のように、メソッドを別のメソッドに直接渡すことはできません。 method
を使用する必要があります 最初:
irb(main):001:0> sin_method = Math.method(:sin)
=> #<Method: Math.sin>
irb(main):002:0> (1..10).map(&sin_method)
=> [0.8414709848078965, 0.9092974268256817, 0.1411200080598672, -0.7568024953079282, -0.9589242746631385, -0.27941549819892586, 0.6569865987187891, 0.9893582466233818, 0.4121184852417566, -0.5440211108893699]
では、ここで何が起こっているのでしょうか?
最初の行はメソッドMath.sin
を回します method
に 物体。 ラムダと同じように、`Method`オブジェクトは`call`に応答します。 method
オブジェクトはto_proc
に応答します (ありがとう、ブノワ)。したがって、ラムダを使用するのと同じ場所で使用できます:
irb(main):004:0> sin_method = -> (x) { Math.sin(x) }
=> #<Proc:0x007fe9f90a9bd8@(irb):4 (lambda)>
irb(main):005:0> (1..10).map(&sin_method)
=> [0.8414709848078965, 0.9092974268256817, 0.1411200080598672, -0.7568024953079282, -0.9589242746631385, -0.27941549819892586, 0.6569865987187891, 0.9893582466233818, 0.4121184852417566, -0.5440211108893699]
もう一度最初の行を見てください。ラムダを使用するこのコードは、method
を使用して、以前のコードと同じように機能します。 。
コードの記述方法に応じて、method
を入手します。 オブジェクトは、ラムダでラップするよりもはるかに簡単です。したがって、ラムダが必要で、メソッドしかない場合は、method
を覚えておいてください。 メソッド。
そのメソッドはどこから来たのですか?
オブジェクトに対してメソッドを呼び出しただけで、予期しないことを実行します。多分誰かがそれを覆したか、それをモンキーパッチしました。これをどのように理解しますか?
あなたはできた ソースコードを数時間掘り下げます。しかし、method
物事をスピードアップできる2つの方法があります。
呼び出しているメソッドを定義したクラスを特定するには、owner
を使用します :
irb(main):003:0> Task.new.method(:valid?).owner
=> ActiveRecord::Validations
もう少し深く行き、どこを正確に把握したい場合 メソッドが定義されました。source_location
を使用してください :
irb(main):004:0> Task.new.method(:valid?).source_location
=> ["/usr/local/lib/ruby/gems/2.1.0/gems/activerecord-4.2.0.beta2/lib/active_record/validations.rb", 55]
source_location
配列を返します。最初の要素はメソッドが定義されたファイルへのパスであり、2番目の要素は行番号です。これらを使用すると、次にどこを見ればよいかが正確にわかります。
ソースを読み取る(掘る必要なしに)
どこかがわかったら メソッドが定義されている場合は、方法を確認することをお勧めします 定義されています。
method
それだけではできません。 ただし、method_source
をインストールする場合 gem、コンソールから直接多くのメソッドのソースコードを見ることができます:
irb(main):002:0> puts Task.new.method(:valid?).source
def valid?(context = nil)
context ||= (new_record? ? :create : :update)
output = super(context)
errors.empty? && output
end
=> nil
コメントも見ることができます:
irb(main):003:0> puts Task.new.method(:valid?).comment
# Runs all the validations within the specified context. Returns +true+ if
# no errors are found, +false+ otherwise.
#
# Aliased as validate.
#
# If the argument is +false+ (default is +nil+), the context is set to <tt>:create</tt> if
# <tt>new_record?</tt> is +true+, and to <tt>:update</tt> if it is not.
#
# Validations with no <tt>:on</tt> option will run no matter the context. Validations with
# some <tt>:on</tt> option will only run in the specified context.
=> nil
かなりすごいですよね?ドキュメントはコンソールにあります!
私のお気に入りのRubyクラスのいくつかは、コード内からコードを検査できるクラスです。 Class
のようなクラス 、Module
、およびmethod
。これらを使用すると、実行中にコードについて多くのことを学び、その場でコードを変更できます。これらのクラスをよく学び、APIを学ぶと、Rubyですばらしいことができるようになります。
-
Ruby転置法を使用して行を列に変換する
今日は、Ruby転置法を使用してRubyでグリッドを処理する方法を学習します。 多次元配列の形をした完璧なグリッド、たとえば3×3の正方形があると想像してみてください。 そして、行を取得して列に変換する 。 なぜあなたはそれをしたいのですか? 1つの用途は、古典的なゲームであるtic-tac-toeです。 ボードをグリッドとして保存します。次に、勝利の動きを見つけるには、行を確認する必要があります 、列 &対角線 。 問題は、グリッドを配列として格納している場合、行に直接アクセスすることしかできないことです。 コラムズザハードウェイ 「直接アクセス」とは、配列を(eachで)調べ
-
メタプログラミングの隠れたコスト
メタプログラミングは非常に派手な言葉のように聞こえますが、それは何か良いことですか? 便利な場合もありますが、メタプログラミングの使用にはいくらかのコストがかかることに多くの人が気づいていません。 同じページにいるので… メタプログラミングとは 正確に? 私はメタプログラミングを次のような方法を使用するものとして定義しています: コードの構造を変更します(define_methodなど) ) 文字列を実際のRubyコードの一部であるかのように実行します(instance_evalなど)。 ) 何らかのイベントへの反応として何かを行います(method_missingなど) ) で