「...の隠された機能」ミームを続けて、あまり知られていないが有用なRubyプログラミング言語の機能を共有しましょう。
この議論を、Ruby on Rails stuff。
こちらもご覧ください:
(回答ごとにone隠し機能のみを入力してください。)
ありがとうございました
From Ruby 1.9 Proc#===はProc#callのエイリアスです。つまり、Procオブジェクトは次のようなcaseステートメントで使用できます。
def multiple_of(factor)
Proc.new{|product| product.modulo(factor).zero?}
end
case number
when multiple_of(3)
puts "Multiple of 3"
when multiple_of(7)
puts "Multiple of 7"
end
Peter Cooperには、 良いリスト of Rubyトリックがあります。おそらく私のお気に入りは、単一のアイテムとコレクションの両方を列挙できるようにすることです。そのオブジェクトだけを含むコレクションとしてのコレクションオブジェクト。)次のようになります。
[*items].each do |item|
# ...
end
これがどのように隠されているかわかりませんが、1次元配列からハッシュを作成する必要があるときに便利だとわかりました。
fruit = ["Apple","red","banana","yellow"]
=> ["Apple", "red", "banana", "yellow"]
Hash[*fruit]
=> {"Apple"=>"red", "banana"=>"yellow"}
私が好きなトリックの1つは、感嘆符(*
)配列以外のオブジェクトのエキスパンダー。正規表現の一致の例を次に示します。
match, text, number = *"Something 981".match(/([A-z]*) ([0-9]*)/)
その他の例は次のとおりです。
a, b, c = *('A'..'Z')
Job = Struct.new(:name, :occupation)
tom = Job.new("Tom", "Developer")
name, occupation = *tom
うわー、誰もフリップフロップ演算子に言及していません:
1.upto(100) do |i|
puts i if (i == 3)..(i == 15)
end
Rubyの素晴らしい点の1つは、メソッドやクラスの定義など、他の言語が眉をひそめるような場所でメソッドを呼び出してコードを実行できることです。
たとえば、実行時までランダムな未知のスーパークラスを持つクラスを作成するには、次のようにします。
class RandomSubclass < [Array, Hash, String, Fixnum, Float, TrueClass].sample
end
RandomSubclass.superclass # could output one of 6 different classes.
これは1.9 Array#sample
メソッド(1.8.7のみ、Array#choice
を参照)を使用します。この例はかなり不自然ですが、ここでその威力を見ることができます。
別のクールな例は、固定されていないデフォルトのパラメーター値を配置する機能です(他の言語がしばしば要求するように):
def do_something_at(something, at = Time.now)
# ...
end
もちろん、最初の例の問題は、呼び出し時ではなく定義時に評価されることです。したがって、スーパークラスが選択されると、プログラムの残りの間、そのスーパークラスのままになります。
ただし、2番目の例では、do_something_at
を呼び出すたびに、at
変数はメソッドが呼び出された時間になります(まあ、非常に近い)
別の小さな機能-Fixnum
を最大36までの任意のベースに変換します。
>> 1234567890.to_s(2)
=> "1001001100101100000001011010010"
>> 1234567890.to_s(8)
=> "11145401322"
>> 1234567890.to_s(16)
=> "499602d2"
>> 1234567890.to_s(24)
=> "6b1230i"
>> 1234567890.to_s(36)
=> "kf12oi"
Huw Waltersがコメントしたように、他の方法を変換するのも同じくらい簡単です。
>> "kf12oi".to_i(36)
=> 1234567890
デフォルト値でハッシュ!この場合の配列。
parties = Hash.new {|hash, key| hash[key] = [] }
parties["Summer party"]
# => []
parties["Summer party"] << "Joe"
parties["Other party"] << "Jane"
メタプログラミングに非常に役立ちます。
Ruby 1.9ソースをダウンロードし、make golf
、次のようなことができます:
make golf
./goruby -e 'h'
# => Hello, world!
./goruby -e 'p St'
# => StandardError
./goruby -e 'p 1.tf'
# => 1.0
./goruby19 -e 'p Fil.exp(".")'
"/home/manveru/pkgbuilds/Ruby-svn/src/trunk"
読む golf_prelude.c
よりきちんとしたものを隠すために。
1.9 Proc機能のもう1つの楽しい追加機能は、Proc#curryです。これにより、n個の引数を受け入れるProcを、n-1を受け入れるものに変えることができます。ここで、上記のProc#=== tipと組み合わせます。
it_is_day_of_week = lambda{ |day_of_week, date| date.wday == day_of_week }
it_is_saturday = it_is_day_of_week.curry[6]
it_is_sunday = it_is_day_of_week.curry[0]
case Time.now
when it_is_saturday
puts "Saturday!"
when it_is_sunday
puts "Sunday!"
else
puts "Not the weekend"
end
非ブール値のブール演算子。
&&
および||
どちらも、最後に評価された式の値を返します。
||=
は、変数が未定義の場合、右側の値を返す式で変数を更新します。これは明示的に文書化されているのではなく、一般的な知識です。
しかし &&=
はあまり広く知られていません。
string &&= string + "suffix"
と同等です
if string
string = string + "suffix"
end
変数が未定義の場合、続行すべきではない破壊的な操作に非常に便利です。
Railsが提供するSymbol#to_proc関数は本当にクールです。
の代わりに
Employee.collect { |emp| emp.name }
あなたは書ける:
Employee.collect(&:name)
最後の1つ-Rubyでは、文字列を区切る任意の文字を使用できます。次のコードを使用します。
message = "My message"
contrived_example = "<div id=\"contrived\">#{message}</div>"
文字列内の二重引用符をエスケープしたくない場合は、単に別の区切り文字を使用できます。
contrived_example = %{<div id="contrived-example">#{message}</div>}
contrived_example = %[<div id="contrived-example">#{message}</div>]
区切り文字をエスケープする必要を回避するだけでなく、より良い複数行の文字列にこれらの区切り文字を使用できます。
sql = %{
SELECT strings
FROM complicated_table
WHERE complicated_condition = '1'
}
define_methodコマンドを使用して動的にメソッドを生成すると、非常に興味深く、あまり知られていないことがわかります。例えば:
((0..9).each do |n|
define_method "press_#{n}" do
@number = @number.to_i * 10 + n
end
end
上記のコードは「define_method」コマンドを使用して、「press1」から「press9」までのメソッドを動的に作成します。本質的に同じコードを含む10個のメソッドすべてを入力するのではなく、define methodコマンドを使用して、必要に応じてこれらのメソッドをオンザフライで生成します。
Rangeオブジェクトを無限の遅延リストとして使用します。
Inf = 1.0 / 0
(1..Inf).take(5) #=> [1, 2, 3, 4, 5]
詳細はこちら: http://banisterfiend.wordpress.com/2009/10/02/wtf-infinite-ranges-in-Ruby/
module_functionとして宣言されたモジュールメソッドは、モジュールを含むクラスでprivateインスタンスメソッドとして自身のコピーを作成します。
module M
def not!
'not!'
end
module_function :not!
end
class C
include M
def fun
not!
end
end
M.not! # => 'not!
C.new.fun # => 'not!'
C.new.not! # => NoMethodError: private method `not!' called for #<C:0x1261a00>
引数なしでmodule_functionを使用すると、module_functionステートメントの後に来るモジュールメソッドはすべて自動的にmodule_functionsになります。
module M
module_function
def not!
'not!'
end
def yea!
'yea!'
end
end
class C
include M
def fun
not! + ' ' + yea!
end
end
M.not! # => 'not!'
M.yea! # => 'yea!'
C.new.fun # => 'not! yea!'
警告:このアイテムは#12008年の最も恐ろしいハックに投票されたため、注意して使用してください。実際、ペストのようにそれを避けてください、しかしそれは最も確かに隠されたルビーです。
あなたのコードのユニークな操作のために、極秘のハンドシェイク演算子が必要ですか?コードゴルフをするのが好きですか? -〜+〜-または<---のような演算子を試してください。最後の演算子は、アイテムの順序を逆にするための例で使用されています。
Superators Project とは何の関係もありません。
私はパーティーに遅れていますが、:
2つの等しい長さの配列を簡単に取得し、1つの配列がキーを提供し、もう1つの配列が値を提供するハッシュに変換できます。
a = [:x, :y, :z]
b = [123, 456, 789]
Hash[a.Zip(b)]
# => { :x => 123, :y => 456, :z => 789 }
(これは、Array#Zipが2つの配列から値を「圧縮」するために機能します。
a.Zip(b) # => [[:x, 123], [:y, 456], [:z, 789]]
そして、Hash []はまさにそのような配列を取ることができます。私は人々がこれを行うのを見てきました:
Hash[*a.Zip(b).flatten] # unnecessary!
どちらが同じ結果をもたらしますが、スプラットとフラット化は完全に不要です-おそらくそれらは過去になかったのでしょうか?)
Rubyでのハッシュの自動有効化
def cnh # silly name "create nested hash"
Hash.new {|h,k| h[k] = Hash.new(&h.default_proc)}
end
my_hash = cnh
my_hash[1][2][3] = 4
my_hash # => { 1 => { 2 => { 3 =>4 } } }
これは便利です。
配列の破壊
(a, b), c, d = [ [:a, :b ], :c, [:d1, :d2] ]
どこで:
a #=> :a
b #=> :b
c #=> :c
d #=> [:d1, :d2]
この手法を使用すると、単純な割り当てを使用して、任意の深さのネストされた配列から必要な正確な値を取得できます。
Class.new()
実行時に新しいクラスを作成します。引数は派生元のクラスにすることができ、ブロックはクラス本体です。また、const_set/const_get/const_defined?
は、新しいクラスを適切に登録し、inspect
が数字ではなく名前を出力するようにします。
毎日必要なものではありませんが、必要なときに非常に便利です。
連続番号の配列を作成します。
x = [*0..5]
xを[0、1、2、3、4、5]に設定します
Rubylandで見られる多くの魔法は、メタプログラミングに関係しています。メタプログラミングとは、単にコードを書くコードを書くことです。 Rubyのattr_accessor
、attr_reader
、およびattr_writer
はすべて、単純なメタプログラミングであり、標準パターンに従って2行のメソッドを1行で作成します。 Railsは、has_one
やbelongs_to
などのリレーションシップ管理メソッドを使用して、多くのメタプログラミングを実行します。
ただし、class_eval
を使用して動的に記述されたコードを実行する独自のメタプログラミングトリックを作成するのは非常に簡単です。
次の例では、ラッパーオブジェクトが特定のメソッドを内部オブジェクトに転送できるようにします。
class Wrapper
attr_accessor :internal
def self.forwards(*methods)
methods.each do |method|
define_method method do |*arguments, &block|
internal.send method, *arguments, &block
end
end
end
forwards :to_i, :length, :split
end
w = Wrapper.new
w.internal = "12 13 14"
w.to_i # => 12
w.length # => 8
w.split('1') # => ["", "2 ", "3 ", "4"]
メソッドWrapper.forwards
は、メソッド名のシンボルを受け取り、methods
配列に格納します。次に、指定されたそれぞれに対して、define_method
を使用して、すべての引数とブロックを含めて、メッセージを一緒に送信する新しいメソッドを作成します。
メタプログラミングの問題に関する優れたリソースは、 なぜラッキースティフの「メタプログラミングを明確に見る」 です。
ケースの比較には、===(obj)
に応答するものをすべて使用します。
case foo
when /baz/
do_something_with_the_string_matching_baz
when 12..15
do_something_with_the_integer_between_12_and_15
when lambda { |x| x % 5 == 0 }
# only works in Ruby 1.9 or if you alias Proc#call as Proc#===
do_something_with_the_integer_that_is_a_multiple_of_5
when Bar
do_something_with_the_instance_of_Bar
when some_object
do_something_with_the_thing_that_matches_some_object
end
Module
(したがってClass
)、Regexp
、Date
、および他の多くのクラスはインスタンスメソッドを定義します:===(other)。利用される。
Farrel のおかげで、Proc#call
エイリアスとしてProc#===
in Ruby 1.9。
「Ruby」バイナリ(少なくともMRIの)は、Perlのワンライナーを非常に人気にした多くのスイッチをサポートします。
重要なもの:
put
sを使用しますいくつかの例:
# Print each line with its number:
Ruby -ne 'print($., ": ", $_)' < /etc/irbrc
# Print each line reversed:
Ruby -lne 'puts $_.reverse' < /etc/irbrc
# Print the second column from an input CSV (dumb - no balanced quote support etc):
Ruby -F, -ane 'puts $F[1]' < /etc/irbrc
# Print lines that contain "eat"
Ruby -ne 'puts $_ if /eat/i' < /etc/irbrc
# Same as above:
Ruby -pe 'next unless /eat/i' < /etc/irbrc
# Pass-through (like cat, but with possible line-end munging):
Ruby -p -e '' < /etc/irbrc
# Uppercase all input:
Ruby -p -e '$_.upcase!' < /etc/irbrc
# Same as above, but actually write to the input file, and make a backup first with extension .bak - Notice that inplace edit REQUIRES input files, not an input STDIN:
Ruby -i.bak -p -e '$_.upcase!' /etc/irbrc
「Ruby one-liners」と「Perl one-liners」をグーグルで検索して、より多くの実用的で実用的な例をご覧ください。基本的に、Rubyをawkとsedのかなり強力な代替として使用できます。
send()メソッドは、Rubyの任意のクラスまたはオブジェクトで使用できる汎用メソッドです。オーバーライドされない場合、send()はストリングを受け入れ、ストリングが渡されるメソッドの名前を呼び出します。たとえば、ユーザーが「Clr」ボタンをクリックすると、「press_clear」文字列がsend()メソッドに送信され、「press_clear」メソッドが呼び出されます。 send()メソッドにより、Rubyで関数を呼び出す楽しさと動的な方法が可能になります。
%w(7 8 9 / 4 5 6 * 1 2 3 - 0 Clr = +).each do |btn|
button btn, :width => 46, :height => 46 do
method = case btn
when /[0-9]/: 'press_'+btn
when 'Clr': 'press_clear'
when '=': 'press_equals'
when '+': 'press_add'
when '-': 'press_sub'
when '*': 'press_times'
when '/': 'press_div'
end
number.send(method)
number_field.replace strong(number)
end
end
Blogging Shoes:The Simple-Calc Application でこの機能について詳しく説明します
private unless Rails.env == 'test'
# e.g. a bundle of methods you want to test directly
Rubyのクールで(場合によっては)素敵で便利なハック/機能のように見えます。
Fixnum#to_s(base)
は、場合によっては非常に便利です。そのようなケースの1つは、36の基数を使用して乱数を文字列に変換することにより、ランダム(擬似)固有トークンを生成することです。
長さ8のトークン:
Rand(36**8).to_s(36) => "fmhpjfao"
Rand(36**8).to_s(36) => "gcer9ecu"
Rand(36**8).to_s(36) => "krpm0h9r"
長さ6のトークン:
Rand(36**6).to_s(36) => "bvhl8d"
Rand(36**6).to_s(36) => "lb7tis"
Rand(36**6).to_s(36) => "ibwgeh"
本当に必要のないものが必要だと言っているクラスやモジュールをだます:
$" << "something"
これは、たとえばBを必要とするAを必要とするが、コードでBを必要としない場合に役立ちます(Aはコードでも使用しません)。
たとえば、Backgroundrbのbdrb_test_helper requires
'test/spec'
、しかしあなたはそれをまったく使用しないので、あなたのコードで:
$" << "test/spec"
require File.join(File.dirname(__FILE__) + "/../bdrb_test_helper")
任意の数のパラメーターを受け入れ、それらをすべて破棄するメソッドの定義
def hello(*)
super
puts "hello!"
end
上記のhello
メソッドはputs
"hello"
画面でsuper
を呼び出しますが、スーパークラスhello
もパラメーターを定義するため、パラメーターを定義する必要があります-ただし、実際にパラメーター自体を使用する必要がないため、彼らに名前を付けなければなりません。
複数の正規表現を|
と組み合わせるには、次を使用できます。
Regexp.union /Ruby\d/, /test/i, "cheat"
次のような正規表現を作成するには:
/(Ruby\d|[tT][eE][sS][tT]|cheat)/
これはいくつかのスクリプトで役立ちます。シェルスクリプトやMakefileのように、環境変数を直接使用することができます。環境変数は、未定義Ruby定数のフォールバックとして使用されます。
>> class <<Object
>> alias :old_const_missing :const_missing
>> def const_missing(sym)
>> ENV[sym.to_s] || old_const_missing(sym)
>> end
>> end
=> nil
>> puts Shell
/bin/zsh
=> nil
>> TERM == 'xterm'
=> true
ARGV [0]に基づいてファイルを開くのはどうですか?
readfile.rb:
$<.each_line{|l| puts l}
Ruby readfile.rb testfile.txt
これは、1回限りのスクリプトを作成するための優れたショートカットです。ほとんどの人が知らない事前定義された変数の混乱があります。それらを賢く使用してください(読んでください:維持しようとしているコードベースを散らかさないでください。散らかってしまいます)。
私はのファンです:
%w{An Array of strings} #=> ["An", "Array", "of", "Strings"]
それがどれほど有用であるかは、ちょっとおかしいです。
def getCostAndMpg
cost = 30000 # some fancy db calls go here
mpg = 30
return cost,mpg
end
AltimaCost, AltimaMpg = getCostAndMpg
puts "AltimaCost = #{AltimaCost}, AltimaMpg = #{AltimaMpg}"
i = 0
j = 1
puts "i = #{i}, j=#{j}"
i,j = j,i
puts "i = #{i}, j=#{j}"
class Employee < Person
def initialize(fname, lname, position)
super(fname,lname)
@position = position
end
def to_s
super + ", #@position"
end
attr_writer :position
def etype
if @position == "CEO" || @position == "CFO"
"executive"
else
"staff"
end
end
end
employee = Employee.new("Augustus","Bondi","CFO")
employee.position = "CEO"
puts employee.etype => executive
employee.position = "Engineer"
puts employee.etype => staff
(メソッドが見つからず、エラーがスローされ、プログラムが停止するほとんどの言語。InRuby実際にこれらのエラーをキャッチし、状況に応じてインテリジェントな処理を行うことができます)
class MathWiz
def add(a,b)
return a+b
end
def method_missing(name, *args)
puts "I don't know the method #{name}"
end
end
mathwiz = MathWiz.new
puts mathwiz.add(1,4)
puts mathwiz.subtract(4,2)
5
減算方法がわからない
なし
James A. Rosenのヒントは素晴らしい([* items] .each)ですが、ハッシュが破壊されることがわかりました。
irb(main):001:0> h = {:name => "Bob"}
=> {:name=>"Bob"}
irb(main):002:0> [*h]
=> [[:name, "Bob"]]
処理するもののリストを受け入れますが、寛大であり、呼び出し元がリストを提供できるようにする場合、私はこのケースの処理方法を好みます:
irb(main):003:0> h = {:name => "Bob"}
=> {:name=>"Bob"}
irb(main):004:0> [h].flatten
=> [{:name=>"Bob"}]
これは、次のようにメソッドシグネチャと組み合わせることができます。
def process(*entries)
[entries].flatten.each do |e|
# do something with e
end
end
私はちょうどloveインラインキーワードrescueのように:
編集された例:
@user #=> nil (but I did't know)
@user.name rescue "Unknown"
link_to( d.user.name, url_user( d.user.id, d.user.name)) rescue 'Account removed'
これは私のアプリを壊すことを避け、Rails。try()でリリースされた機能よりもはるかに優れています
オーバーライドされた場合でも、継承チェーンのどこかで定義されたメソッドを呼び出す
ActiveSupportのオブジェクトは、組み込みオブジェクトになりすますことがあります。
require 'active_support' days = 5.days days.class#=> Fixnum days.is_a?(Fixnum)#=> true Fixnum === days#=> false(えっ?本当は何ですか?) Object.instance_method(:class).bind(days).call#=> ActiveSupport :: Duration(aha!) ActiveSupport :: Duration === days#=> true
もちろん、上記は、active_supportがObject#instance_methodを再定義しないという事実に依存しています。この場合、実際には小川になります。それから、サードパーティのライブラリがロードされる前に、Object.instance_method(:class)の戻り値をいつでも保存できます。
Object.instance_method(...)は、そのクラスのインスタンスにバインドできるUnboundMethodを返します。この場合、Objectの任意のインスタンス(サブクラスを含む)にバインドできます。
オブジェクトのクラスにモジュールが含まれる場合、それらのモジュールからUnboundMethodを使用することもできます。
module Mod def var_add(more); @ var + more; end end class Cla include Mod def initialize(var); @ var = var; end #override def var_add(more); @ var + more + more; end end cla = Cla.new( 'abcdef') cla.var_add( 'ghi')#=> "abcdefghighi" Mod.instance_method( :var_add).bind(cla).call( 'ghi')#=> "abcdefghi"
これは、オブジェクトが属するクラスのインスタンスメソッドをオーバーライドするシングルトンメソッドでも機能します。
class Foo def mymethod; '元の'; end end foo = Foo.new foo.mymethod#=> 'original' def foo.mymethod; 「シングルトン」; end foo.mymethod#=> 'singleton' Foo.instance_method(:mymethod).bind(foo).call#=> 'original' #シングルトンクラスで#instanceメソッドを呼び出すこともできます。 class << foo;自己; end.instance_method(:mymethod).bind(foo).call#=> 'singleton'
シンボルリテラルには、知っておくべき側面がいくつかあります。特殊なシンボルリテラルによって解決されるケースの1つは、通常のシンボルリテラル構文で何らかの理由で構文エラーが発生する名前のシンボルを作成する必要がある場合です。
:'class'
シンボル補間を行うこともできます。アクセサーのコンテキストでは、例えば:
define_method :"#{name}=" do |value|
instance_variable_set :"@#{name}", value
end
each_with_index列挙可能なオブジェクト(配列、ハッシュなど)のメソッドでしょうか?
myarray = ["la", "li", "lu"]
myarray.each_with_index{|v,idx| puts "#{idx} -> #{v}"}
#result:
#0 -> la
#1 -> li
#2 -> lu
他の回答よりもよく知られているかもしれませんが、すべてのRubyプログラマー:)
class A
private
def my_private_method
puts 'private method called'
end
end
a = A.new
a.my_private_method # Raises exception saying private method was called
a.send :my_private_method # Calls my_private_method and prints private method called'
Rubyには call/cc メカニズムがあり、スタックを自由に飛び降りることができます。
簡単な例を次に示します。これは確かにRubyでシーケンスを乗算する方法ではありませんが、call/ccを使用してスタックに到達してアルゴリズムを短絡させる方法を示しています。この場合、すべての数値が表示されるか、ゼロ(答えがわかっている2つのケース)が表示されるまで、数値のリストを再帰的に乗算します。ゼロの場合、リストの任意の深さで終了できます。
#!/usr/bin/env Ruby
def rprod(k, rv, current, *nums)
puts "#{rv} * #{current}"
k.call(0) if current == 0 || rv == 0
nums.empty? ? (rv * current) : rprod(k, rv * current, *nums)
end
def prod(first, *rest)
callcc { |k| rprod(k, first, *rest) }
end
puts "Seq 1: #{prod(1, 2, 3, 4, 5, 6)}"
puts ""
puts "Seq 2: #{prod(1, 2, 0, 3, 4, 5, 6)}"
出力はここで見ることができます:
スタック上の他の方向に移動する継続を特徴とするより複雑な例については、ソースを Generator に読みます。
私はすべての答えを読みました... 1つの顕著な省略は割り当ての破壊でした:
> (a,b),c = [[1,2],3]
=> [[1,2],3]
> a
=> 1
ブロックパラメーターに対しても機能します。これは、各要素が個別の何かを表すネストされた配列がある場合に便利です。 「array [0] [1]」のようなコードを記述する代わりに、そのネストされた配列を分解して、コードの1行で各要素に説明的な名前を付けることができます。
@user #=> nil (but I did't know)
@user.name rescue "Unknown"
私のお気に入りRuby機能。構文はformat_string % argument
"%04d" % 1 # => "0001"
"%0.2f" % Math::PI # => "3.14"
配列(format_string % array_of_arguments
)
"%.2f %.3f %.4f" % ([Math::PI]*3)
# => "3.14 3.142 3.1416"