论坛首页 编程语言技术论坛

Ruby Tricks 大全

浏览 9255 次
精华帖 (9) :: 良好帖 (8) :: 新手帖 (1) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-06-24   最后修改:2009-06-25

下面所有用法都是1.8.6里的,同时欢迎补充1.9和rails里面的tricks...


一.神奇的*
1.String#*

  "Hello!" * 2
 #=> "Hello!Hello!"
 


2.Array#*

   %w{one two three} * 2
  #=> ["one", "two", "three", "one", "two", "three"]
 


3.Shortcut for Array#join

   %w{one two three} * ", "
  #=> "one, two, three"
 

 

 %w{this is a test} * ", "                 # => "this, is, a, test"
 h = { :name => "Fred", :age => 77 }
 h.map { |i| i * "=" } * "&"              # => "age=77&name=Fred"
 


4.explore to enumerator

  a = %w{a b}
b = %w{c d}
[a + b]                              # => [["a", "b", "c", "d"]]
[*a + b]                             # => ["a", "b", "c", "d"]
 

 

 a = { :name => "Fred", :age => 93 }
[a]                                  # => [{:name => "Fred", :age =>93}]
[*a]                                 # => [[:name, "Fred"], [:age, 93]]
  

 

  a = %w{a b c d e f g h}
b = [0, 5, 6]
a.values_at(*b).inspect              # => ["a", "f", "g"]
 

 

  fruit = ["apple","red","banana","yellow"]
#=> ["apple", "red", "banana", "yellow"]

Hash[*fruit]    
#=> {"apple"=>"red", "banana"=>"yellow"}
 


5.*arg作为参数

 def my_method(*args)
  a, b, c, d = args
end 


6.Object#*

 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



二.默认返回值.
Array#[]在index超出array范围时会默认返回nil(如果不想要默认值或是要扩展默认值可以用Array#fetch):

 irb(main):074:0> a = [1 ,2, 3]
=> [1, 2, 3]
irb(main):075:0> a[5]
=> nil
irb(main):076:0> a.fetch(8)
IndexError: index 8 out of array
        from (irb):76:in `fetch'
        from (irb):76
        from :0
irb(main):077:0> a.fetch(8,nil)
=> nil
irb(main):078:0> a.fetch(8,"index out of array!")
=> "index out of array!"
 


Hash也是在key不存在的时候返回默认值nil,也可以自己设置默认值或default_proc

 irb(main):008:0> hash = Hash.new{|hash,key| hash[key] = key.upcase if key.kind_o
f? String}
=> {}
irb(main):009:0> hash[1]
=> nil
irb(main):010:0> hash["key"]
=> "KEY"



Regex也可以有默认返回值:

 email = "Fred Bloggs <fred@bloggs.com>"
email.match(/<(.*?)>/)[1]            # => "fred@bloggs.com"
email[/<(.*?)>/, 1]                  # => "fred@bloggs.com"
email.match(/(x)/)[1]                # => NoMethodError 
email[/(x)/, 1]                      # => nil


当然最强大的还是method_missing了....

三.习以为常的single line method
在ruby里一行代码完成一个方法是很常见的....这主要归功于enumerable模块里面定义的神奇方法,还有if,unless等

 queue = []
%w{hello x world}.each do |word|
  queue << word and puts "Added to queue" unless word.length <  2
end
puts queue.inspect

# Output:
#   Added to queue
#   Added to queue
#   ["hello", "world"]



三元操作符:

 def is_odd(x)
  x % 2 == 0 ? false : true
end

 

 all?, any?, collect, detect, each_cons, each_slice,
 each_with_index, entries, enum_cons, enum_slice, enum_with_index,
 find, find_all, grep, include?, inject, inject, map, max, member?,
 min, partition, reject, select, sort, sort_by, to_a, to_set, zip

 

 

  p queue = %w{hello x world}.select { |word| word.length >= 2 }


四.其他
1.Format decimal amounts quickly

 money = 9.5
"%.2f" % money                       # => "9.50"


2.Surround text quickly

"[%s]" % "same old drag"             # => "[same old drag]"


3.Delete trees of files

require 'fileutils'
FileUtils.rm_r 'somedir'


4.Cut down on local variable definitions

 (z ||= []) << 'test'



5.Using non-strings or symbols as hash keys

 does = is = { true => 'Yes', false => 'No' }
does[10 == 50]                       # => "No"
is[10 > 5]                           # => "Yes"



6.Do something only if the code is being implicitly run, not required

 if __FILE__ == $0
  # Do something.. run tests, call a method, etc. We're direct.
end



7.Use ranges instead of complex comparisons for numbers

#让 if x > 1000 && x < 2000 歇菜吧
 year = 1972
puts  case year
        when 1970..1979: "70后"
        when 1980..1989: "80后"
        when 1990..1999: "90后"
      end



8.See the whole of an exception's backtrace

  def do_division_by_zero; 5 / 0; end
begin
  do_division_by_zero
rescue => exception
  puts exception.backtrace
end



9.Rescue blocks don't need to be tied to a 'begin'

 def x
  begin
    # ...
  rescue
    # ...
  end
end

 

 def x
  # ...
rescue
  # ...
end


10.Rescue to the rescue

 h = { :age => 10 }
h[:name].downcase                         # ERROR
h[:name].downcase rescue "No name"        # => "No name"


11.convert a Fixnum into any base up to 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"



12.module_function

#让module更class
  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 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!'


13.use  here document and any character you want to delimit strings 

 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'
}
sql = <<-SQL
    SELECT strings 
    FROM complicated_table
    WHERE complicated_condition = '1'
SQL


14.define_method

 ((0..9).each do |n|
    define_method "press_#{n}" do
      @number = @number.to_i * 10 + n
    end
  end


15.create Class at run time..

class Array
#define Array#rand
  def rand
    self.fetch Kernel.rand(self.size)
  end
end
class RandomSubclass < [Array, Hash, String, Fixnum, Float, TrueClass].rand

end

RandomSubclass.superclass # could output one of 6 different classes.


16.call private methods of class with send.

 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'


16.__END__

p DATA #=>#<File:tt.rb>
p DATA.read #=> "line1\nline2\nline3"

__END__
line1
line2
line3


17.FX和NS两位大神提供...目前不知道是做什么的.......

gets gets

 

 

   发表时间:2009-06-24  
hash作参数:
def m option={}
  arg2 = option[:arg2]
  arg1 = option[:arg1]
  print arg2,arg1
end

m :arg2 =>"Hi", :arg1 => "hooopo"
#Hihooopo

0 请登录后投票
   发表时间:2009-06-24   最后修改:2009-06-24
1.9 的源代码目录下 (n)make golf,产生的 goruby(.exe) 可以用很多诡异的写法。
譬如世界上最短的 hello world :
h

输出:Hello, world!

1.9 的正则命名分组,不需要 $1 .. $9 了,显式匹配命名组 =~ 会自动赋予局部变量,但是如果不是 /xxx/ =~ 'xxx',就不会产生这堆局部变量。再 但是,用 Regexp#match 产生的 matchdata 是一组类似 hash 的东西,键是命名的符号,值是匹配串,不好的一点就是这个东西虽然类似 hash,但不是 hash ……
re = /^
      \s*(?<template>   template\s*\<.*\>)?
      (?<modifiers>     (?:\s*\b\w+|\s*\"C\")*?)
      \s*\b(?<type>     \w+[\s\*\&\[\]]*)
      \s*\b(?<c2>       __declspec|__stdcall|__fastcall|WINAPI|CALLBACK|const|const\s\*|const\*)?
      \s*\b(?<name>     [\w\:]+)
      \s*\((?<params>   .*)\)
      \s*(?<const_tail> const)?
      \s*\{\s*
$/x 
m = re.match 'int hoho(){'
h = {}
m.names.each do |n|  # 这东西只有 each 可以用
  h[n] = m[n]
end


关于一些 trick,可以瞧瞧 爆栈这个帖爆栈那个帖 …… 充分利用 Perl 相容全局量和 golf 是挺不错的加密混淆手段 ……

引用
If anyone every uses any of those Ruby "hidden features" in code I have to work on, I will stab them in the eye.

x . x 不过貌似作这段评论的兄弟不是搞 ruby 的,所以眼睛保住了 ……
0 请登录后投票
   发表时间:2009-06-24  
这有点茴香豆的n种写法的味道了....

昨天学了Nemerle之后,觉得这些东西都可以是不必要的,让客户用Marco自由创造远比系统这些糖糖果果好多了。
0 请登录后投票
   发表时间:2009-06-24   最后修改:2009-06-25
爆栈,,,,这个网站不错..刚要订阅之,结果google reader 宕了.

1.9的正则支持Named Regexp Groups了很爽呀!!

要说变态看看人如其名的BrainFvck语言:
brainfvck语言是最简单的程序语言之一,只有8个有效字符,每个字符都有一个特定的含义。这8个字符控制一个指针在线性表里进行移动、读写、循环等操作。所有其它的字符都当作注释处理。
++++++++++[>+++++++++++<-]>-.
<+++[>----<-]>.<+++++[>++++<-]>-.--.
<+++[>---<-]>.<+++++[>+++<-]>.
>+++++[>+++++++++++<-]>-.+.<+++[>---<-]>.<<
<+++++[>----<-]>-.<+++[>++++<-]>.--.


Befunge:
Befunge语言 http://quadium.net/funge/spec98.html
Befunge的代码是二维的。它用 < > v ^这四个符号来控制一个指针在代码中移动,指针经过一个字符或数字则把它压入一个栈,四则运算符号的功能就是弹出栈顶两个元素进行计算后把结果压回去。用_ 和 | 来表示有条件的方向选择:当栈顶元素为0时向右(上)走,否则向左(下)走。& 和 ~分别用于读入数字或字符并压入栈,句号和逗号分别表示将栈顶元素作为整数或字符输出。最后以一个@符号表示程序结束。Befunge代码的注释不需要任何符号标明,你可以把注释写在程序的任何地方,只要运行时指针不会经过它就行了。你甚至可以把注释写在程序正中间,然后写代码时绕开注释写成一圈。Befunge的Hello World程序如下:
复制内容到剪贴板
代码:
                v
>v"Hello world!"0<
,:
^_25*,@
看一个复杂的例子。我找了一个算圆周率的Befunge程序,看起来非常壮观。
复制内容到剪贴板
代码:
aa*       v                +------------------------+
vp*9920p*9930<                | Pi generator in Bef-97 |
>:09a*pa*3/1+19a*p09a*g:09b*v |                      |
v_@# g*b90 p*b910        < p< | 7/2/1997, Kevin Vigor   |
>19a*g:+1-29b*p19a*g::09v    +------------------------+
v*a90g*b90*g*b91: _v#p*9<
>g-#v_ 2a*+\$   v   :$
>\1-aa*ga*+v   p
v1:/g*b92p*991:<   *
>9b*p29b*g*199*g\v9
v*b92p*aa-1g*990-<9
>g2-29b*p099*g1-:0^
v -9p*b92:%ag*991   <
>#v_ 299*g1+299*p>    ^
   >09b*g:#v_$v
v93p*b90-1<
>9*g199*ga/+.v
    v:g*992 <p*9 92-<
v_29b*g399*p ^
>09b*g:#v_v    1
vp*b90-1 < $    g
>199*g9`#v_'9,v    *
      >'0, >' ,299^

via:http://blog.xiaonei.com/GetEntry.do?id=283579963&owner=80288196
0 请登录后投票
   发表时间:2009-06-24  
跑题广告一下:爆栈是架设在ASP.NET的应用哦~
然后Jon Skeet在爆栈上超有名……经常能看到他的身影,特别是关于C#的问题的话

回到主题:楼主加上
gets gets
大法~跟NS学的一招
0 请登录后投票
   发表时间:2009-06-25   最后修改:2009-06-25
ray_linn 写道
这有点茴香豆的n种写法的味道了....

昨天学了Nemerle之后,觉得这些东西都可以是不必要的,让客户用Marco自由创造远比系统这些糖糖果果好多了。


嗯…… Nemerle 相当有才…… 有个好地方是模式匹配,譬如这个 (取自 99 杯马尿有几种写法
def beers(n) {
  | 0 => "no more bottles of beer"
  | 1 => "1 more bottle of beer"
  | _ => $"$n bottles of beer"
}


还有就是高级 eval —— 卫生宏(这个翻译一直让我觉得很囧) ……

不过 Ruby 做 Macro 也很强,因为 compile time ? runtime ? anytime
给客户用最好还是外部 DSL 吧(内部 DSL 最方便程序员使用),感觉内部 DSL 没必要把语法自由得太彻底 ……
0 请登录后投票
   发表时间:2009-06-25  
iya……说起语法自由,得要体会过“什么是自由”才好说必要不必要,有没有用云云。
兄弟们一定要看看Katahdin,传送门
同样是毕业设计,我的就弱小多了……|||| 好吧人家那是硕士毕设,我的是本科……
0 请登录后投票
   发表时间:2009-06-25   最后修改:2009-06-25
RednaxelaFX 写道
iya……说起语法自由,得要体会过“什么是自由”才好说必要不必要,有没有用云云。
兄弟们一定要看看Katahdin,传送门
同样是毕业设计,我的就弱小多了……|||| 好吧人家那是硕士毕设,我的是本科……


你的毕设…… 不能怪你,只能怪微软更新的太慢 ……

o,想用什么语言就载入对应的 .kat …… 无差别格斗流果然很 nb ……

我想起 programing paradigms for dummies 了。
如果把编程范式做成小包,按需要加载和卸载 …… 譬如并发部分就把"不确定性可观测"(observable undeterminism,这个词很量子 ……)这个内涵去掉,写完就加回来 ……

另外一个 nb 的地方就是编写标准库不用重复发明轮子了,直接挑其它语言里实现得最完美的 ……
0 请登录后投票
   发表时间:2009-06-25  
<dtml-comment>
   Zope-DTML version of 99 Bottles of beer (Bottles.html)
   See @ http://www.stowasser.tv/algo/Bottles.html
   Harald Stowasser
</dtml-comment>

<dtml-var standard_html_header>
   <dtml-in "_.range(99, 0, -1)" prefix=bottle>
     <dtml-var bottle_item> bottle(s) of beer on the wall<br>
     <dtml-var bottle_item> bottle(s) of beer.<br>
     Take one down, pass it around<br>
     <dtml-var "bottle_item-1"> bottle(s) of beer on the wall."<br><br>
   </dtml-in>
<dtml-var standard_html_footer>


ms这个也很强。
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics