keke3.com
域名年龄: 11年9个月22天HTTP/1.1 301 永久重定向 访问时间:2015年01月22日 19:00:34 语言环境:PHP/5.4.30 X-Pingback: http://keke3.com/xmlrpc.php 目标网址:http://keke3.com/ 文件大小:0 连接:关闭 类型:text/html; charset=UTF-8 HTTP/1.1 200 OK 访问时间:2015年01月22日 19:00:34 语言环境:PHP/5.4.30 X-Pingback: http://keke3.com/xmlrpc.php 连接:关闭 Transfer-Encoding: chunked 类型:text/html; charset=UTF-8 网站编码:UTF-8
kekeの技術帳プログラミングやサーバー関係についてメモしたいときのための備忘録ですRubyで一度に複数の比較演算子を使えるようにする今回はRubyの小ネタ。どうも、kekeです。例えばソースコード上で数値の範囲を評価するのに「1 < x < 3」のような書き方ができれば、記述量も少ないし見やすい。ちなみにPythonだと何もしなくても普通にできる。>>> 1 < 2 < 3True>>> 1 < 5 < 3FalseでもRubyだと、irb(main):001:0> 1 < 2 < 3NoMethodError: undefined method `<' for true:TrueClassこんな感じで、Rubyでは一度に複数の比較演算子を繋げて書くことができない。まぁなんでかというと、まず「1 < 2」が評価されてその結果が真偽値として返ってくる。次に返ってきた真偽値と次の数値が「true < 3」のように評価され、真偽値と数値との比較演算ができずにエラーになる。そんな感じなので、Rubyで数値の範囲などを評価するには、irb(main):001:0> 1 < 2 && 2 < 3=> trueirb(main):002:0>みたいに書かなきゃいけない。ちょっとかっこ悪い。なので、今回はRubyでも「1 < 2 < 3」のように比較演算子を繋げて書けるように改造します。今回の環境Rubyのバージョン: 2.1.1p76 (2014-02-24 revision 45161)※今回のやり方ではRuby2.0から追加されたModule#prependを使うので、1.9系とか1.8系の環境では使えません。結局のところ、「true < 3」のように途中で真偽値との比較をしてしまいエラーになるので、これを何とかすることによって解決する。Rubyはすべてオブジェクトとメソッドでできているので、trueやfalseとかもオブジェクト(TrueClass、FalseClass)、比較演算子とかもメソッド。また、Rubyはメソッドを追加したり上書きしたりして、既存のクラスやモジュールを拡張することができる。ということで、これをうまいこと利用してやってみる。やり方としては、trueとfalseのクラスであるTrueClassとFalseClassに、比較の時の右項のオブジェクト(1 < 2でいう2)を保持しておくためのアクセサメソッドを定義TrueClassとFalseClassに比較演算子を追加(保持していた右項のオブジェクトと比較させる)FixnumやStringなど、既存クラス(または既存モジュール)の比較演算子をオーバーライド(というかラッピング?)boolean.rbclass TrueClassattr_accessor :right_obj[:<, :<=, :>, :>=].each{|c_operator|define_method(c_operator){|obj|if !self.right_objraise NoMethodError.new("undefined method `#{__method__}' for true:TrueClass", __method__)endresult = self.right_obj.send(c_operator, obj)result.right_obj = objreturn result}}endclass FalseClassattr_accessor :right_obj[:<, :<=, :>, :>=].each{|c_operator|define_method(c_operator){|obj|if !self.right_objraise NoMethodError.new("undefined method `#{__method__}' for false:FalseClass", __method__)endself.right_obj = objreturn self}}endcomparable.rbrequire_relative 'boolean'module CustomComparable[:<, :<=, :>, :>=].each{|c_operator|module_eval <<-EOSdef #{c_operator}(obj)result = superresult.right_obj = objreturn resultendEOS}end[Comparable, Fixnum, Bignum, Float, String, Symbol, Time].each{|c|c.class_eval{ prepend CustomComparable }}※比較演算子のメソッドをドバドバといっぱい書くの面倒だから、define_methodとかmodule_eval使ってるけど、見づらかったらごめんなさい。Comparableだけでなく、FixnumやFloatとかにもprependを使って比較演算子をオーバーライドしてるのは、これらのクラスはComparableで提供されてる比較演算子を使わずに、独自に比較演算子を実装しているから。では実際に試してみます。example.rbrequire_relative 'comparable'puts "------------数値------------"x = 2 #Fixnump 1 < x <= 2p 3 < x < 4x = 2.5 #Floatp 2.5 <= x < 3.14p 1.42 < x < 2.5puts "-----------文字列-----------"x = "b"p "a" < x < "c"p "b" < x < "e"puts "----------シンボル----------"x = :bp :a < x < :cp :b < x < :eputs "------------時間------------"x = Time.local(2001, 5, 20, 23, 59, 59)p Time.local(2001, 5, 20, 23, 59, 59) <= x < Time.local(2001, 5, 21, 0, 0, 0)p Time.local(2001, 5, 22, 0, 0, 0) < x < Time
© 2010 - 2020 网站综合信息查询 同IP网站查询 相关类似网站查询 网站备案查询网站地图 最新查询 最近更新 优秀网站 热门网站 全部网站 同IP查询 备案查询
2025-05-24 03:57, Process in 0.0086 second.