好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

rails best particseceeeeeeeeeeee

rails best particseceeeeeeeeeeee

Ruby有不少惯用法,这里略作一些介绍,也方便阅读他人代码: 

迭代  
一般写法: 

for i in (1..10) 
puts i 
end 

习惯写法: 

Java代码 

( 1 .. 10 ).each{|i| puts i}   或   1 .upto( 10 ){|i| puts i} # from njmzhang  




||=赋值  
一般写法: 

Java代码 

number =  1   if  number.nil?   number =  1  unless number  


习惯写法: 

Java代码 

number ||=  1   




程序入口  

Java代码 

if  __FILE__ == $ 0    或   if  $PROGRAM_NAME == __FILE__  


这个相当于main(), 逻辑判断的意思当程序名($0或另一个)和当前文件名(__FILE__)一致时,也就是当前文件是被单独执行的而不是被别的文件调用。这个方法还有个用法是作为unit test使用。 


预设变量和特殊记号  
类似$0的Perl风格预设常量还有很多,参见Programming Ruby p319 

其中比较常用的如$:代表库搜索路径,修改方法常见有: 

Java代码 

$:.unshift( 'buildscript' )  # from gigix   或   $: << File.join(File.dirname(__FILE__),  'CurrentClass' )   


后一种方法使用了相对路径,因为Ruby的module不要求namespace和文件目录结构要对应一致,很多时候统统放一个目录里 

%w格式化命令(from qiezi) 可以少打几个引号 

Java代码 

%w{a b c d} #等价 [ 'a' ,  'b' ,  'c' ,  'd' ]   



``(~键下的撇号)用来执行shell外部命令,如: 

Java代码 

`help`  




inject  
一般写法: 

Java代码 

result = []   ( 1 .. 10 ).each{|item| result << item}  


习惯写法: 

Java代码 

( 1 .. 10 ).inject([]){|array, item| array << item}  


inject有点难理解,相当于python的reduce和一些FP里的fold。inject的块变量有两个(这里是array和item),第二个变量(item)用来枚举被inject的集合(这里是(1..10)这个range), 而第一个变量(array)由inject的参数初始化(这里是[],可选),并在block被反复执行时保持持久(相当于静态变量),而item则在每次枚举时被更新为下一个值。我们再看一下inject的另一种通常用法就会更明白了:求和 

Java代码 

( 1 .. 10 ).inject{|sum, item| sum += item}   这个等于   ( 1 .. 10 ).inject( 0 ){|sum, item| sum += item}  


也就是块变量sum被初始化成0然后反复迭代执行块的内容,最后返回sum 


并行赋值  
这个很多人都知道了,比如: 

Java代码 

a,b =  0 ,  1    a,b = b, a # 交换a,b  


当然可以延伸出一些很诡异的变化,不提倡使用阿 

还有一个用法是让函数返回“多个结果”(不是多个对象),如: 

Java代码 

def test      1 , 2    end   x, y = test #x =  1 , y =  2      


这个njmzhang说的很对,其实函数返回的是一个array,然后再并行匹配到变量上去。(所以我对多个结果特别加了引号) 
这显然是个syntax sugar,你随便用逗号分割几个变量是不会自动组成array的。 

注意这种并行匹配当两遍不平衡时会造成的问题: 

Java代码 

a,b = [ 1 , 2 , 3 ] # a =  1 , b =  2 ,  3 被丢弃   a,b,c = [ 1 , 2 ] # a =  1 , b =  2 , c = nil 被初始化成nil   




*的匹配  
一般来说*用于把一个array展开: 

Java代码 

a, *b = [ 1 , 2 , 3 ]  #a =  1 , b = [ 2 , 3 ]  


类似FP里的x:xs(haskell), x::xs(ocaml), [a | b] (erlang from 布娃娃) 


rescue简单用法  

Java代码 

begin     1 / 0    rescue     puts  'wrong'    end  


可以简化为 

Java代码 

1 / 0  rescue puts  'wrong'   




命名参数的默认值  
ruby有默认参数,但其实没有所谓keyword argument,而是提供一个syntax sugar用hash模拟。但是怎么像Rails的方法那样同时利用命名参数和默认参数值呢? 

Java代码 

def image(opt={})       default_opt = {:height =>  25 , :width =>  10 }       default_opt.merge! opt #opt中同样key的内容会覆盖default_opt中key的value   end  




精细duck typing控制  
duck typing的精神就是行为决定类型,而不是相反 

Java代码 

a = []   #不用   if  a.kind_of? Array then a <<  1    if  a.instance_of? Array then a <<  1    #而用   if  a.respond_to? :<< then a <<  1   




获取metaclass  
这也比较常见了,各种动态伎俩的开始 

Java代码 

sing =  class  << self; self; end  




符号转换到Proc  
一般写法: 

Java代码 

( 1 .. 10 ).map{|item| item.succ}  


习惯写法: 

Java代码 

( 1 .. 10 ).map(&:succ)  


map(fun(x))般的FP风格 

注意这是Rails特有的,通过ActiveSupport对Symbol插入to_proc方法。 
不用Rails怎么办呢?一种办法是借助Ruby Facets库(gem install facets): 

Java代码 

require 'facet/symbol/to_proc‘  



Facets库包括大量对Ruby核心类的扩展,是个有趣而又危险的大杂烩,也许我以后会另外再专门介绍一下。 

Java代码 

  

返回顶楼

         

  qiezi 等级:  性别:  文章: 809 积分: 893 来自: 上海

   发表时间:2006-09-19  

这么全啊。inject我看了几次没理解,干脆不看了。 

ruby函数调用可以省括号,方便是方便,不过一些FP用法也看不见了,这方面python还比较好。 

从facet可以看出来,ruby里面使劲往一个类里塞东西还是有传统的。

返回顶楼

          回帖地址

0   0  请登录后投票

  buaawhl 等级:  性别:  文章: 3391 积分: 5214 来自: china

   发表时间:2006-09-19  

第一份收藏品。学习中。受益匪浅。great thanks。 
另外,源文件/目录/namespace 管理、引入等有什么best practice? 
我知道一个require,load 啥的。 
还看到有些人实现了ruby import module。 

另外,一点疑惑。 

引用


(1..10).inject([]){|array, item| array << item} 
inject有点难理解,相当于python的reduce和一些FP里的fold。inject的块变量有两个(这里是array和 item),第二个变量(item)用来枚举被inject的集合(这里是(1..10)这个range), 而第一个变量(array)由inject的参数初始化(这里是[],可选),并在block被反复执行时保持持久(相当于静态变量),而item则在每次枚举时被更新为下一个值。是不是越看越晕呼呢?哈哈哈 



这个地方虽然没有太看懂,但是感觉和List Comprehension有些像。因为这里产生的结果是一个Array ( like List)。 
而Reduce, Fold的结果一般是积累成一个总值。比如,sum。 
当然,这只是我的印象。我对ruby inject, Reduce/Fold, List Comprehension了解都不深。 
提出疑惑,盼高手解惑。 

再看一眼,仿佛这Ruby Inject很符合Reduce/Fold的形式,都是把当前结果和下一个元素作为两个参数继续向下执行。 

respond to 确实是个 best practice。 

引用


命名参数的默认值 
ruby其实没有所谓keyword argument,而是提供一个syntax sugar用hash模拟。但是怎么像Rails的方法那样同时利用命名参数和默认参数值呢? 

def image(opt={}) 
    default_opt = {:height => 25, :width => 10} 
    default_opt.merge! opt 
end 



这个解答了我看RoR book 时候的疑惑,keyword argument 果然是 hash 模拟的。重点学习。 

引用


获取metaclass 
这也比较常见了,各种动态伎俩的开始 
sing = class << self; self; end 



没看懂,重点学习。 

返回顶楼

          回帖地址

0   0  请登录后投票

  gigix 等级:  资深会员 性别:  文章: 4824 积分: 2991 来自: 北京

   发表时间:2006-09-19  

buaawhl 写道

第一份收藏品。学习中。受益匪浅。great thanks。 
另外,源文件/目录/namespace 管理、引入等有什么best practice? 
我知道一个require,load 啥的。 
还看到有些人实现了ruby import module。 

另外,一点疑惑。 

引用


(1..10).inject([]){|array, item| array << item} 
inject有点难理解,相当于python的reduce和一些FP里的fold。inject的块变量有两个(这里是array和 item),第二个变量(item)用来枚举被inject的集合(这里是(1..10)这个range), 而第一个变量(array)由inject的参数初始化(这里是[],可选),并在block被反复执行时保持持久(相当于静态变量),而item则在每次枚举时被更新为下一个值。是不是越看越晕呼呢?哈哈哈 



这个地方虽然没有太看懂,但是感觉和List Comprehension有些像。因为这里产生的结果是一个Array ( like List)。 
而Reduce, Fold的结果一般是积累成一个总值。比如,sum。 
当然,这只是我的印象。我对ruby inject, Reduce/Fold, List Comprehension了解都不深。 
提出疑惑,盼高手解惑。 

再看一眼,仿佛这Ruby Inject很符合Reduce/Fold的形式,都是把当前结果和下一个元素作为两个参数继续向下执行。 

respond to 确实是个 best practice。 

引用


命名参数的默认值 
ruby其实没有所谓keyword argument,而是提供一个syntax sugar用hash模拟。但是怎么像Rails的方法那样同时利用命名参数和默认参数值呢?

def image(opt={}) 
    default_opt = {:height => 25, :width => 10} 
    default_opt.merge! opt 
end 



这个解答了我看RoR book 时候的疑惑,keyword argument 果然是 hash 模拟的。重点学习。 

引用


获取metaclass 
这也比较常见了,各种动态伎俩的开始 
sing = class << self; self; end 



没看懂,重点学习。 



inject就是reduce,map就是map……后面这句是废话。 
源文件管理的惯用法如下 

Ruby代码 

# to import buildscript/javascripttest.rb ...    $:.unshift( 'buildscript' )   require  'javascripttest'   

返回顶楼

          回帖地址

0   0  请登录后投票

  njmzhang 等级:  文章: 71 积分: 146

   发表时间:2006-09-19  

loop的写法有多种,
1.upto(10) {...}
10.downto(1) {...}
1.step(10, 2) {...}

返回顶楼

          回帖地址

0   0  请登录后投票

  buaawhl 等级:  性别:  文章: 3391 积分: 5214 来自: china

   发表时间:2006-09-19  

gigix 写道


inject就是reduce,map就是map……后面这句是废话。 
源文件管理的惯用法如下 
[code=Ruby] 
# to import buildscript/javascripttest.rb ... 
$:.unshift('buildscript') 
require 'javascripttest' 



这个unshift不错。 

有点类似于Python的 
from Sound.Effects import echo 

不过,Python还可以直接 import 到 Function 级别 (对应Java的Class Static Method? ) 
from Sound.Effects.echo import echofilter 

搜索了一下,ruby unshift,结果出来很多 array unshift 的结果。 
到底是没有找到 $:.unshift('buildscript') 的具体说明。

返回顶楼

          回帖地址

0   0  请登录后投票

  njmzhang 等级:  文章: 71 积分: 146

   发表时间:2006-09-19  

buaawhl 写道


搜索了一下,ruby unshift,结果出来很多 array unshift 的结果。 
到底是没有找到 $:.unshift('buildscript') 的具体说明。



这个不就是把buildscript加到$:路径里吗

查看更多关于rails best particseceeeeeeeeeeee的详细内容...

  阅读:40次