zoukankan      html  css  js  c++  java
  • rails best particseceeeeeeeeeeee

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

    迭代 
    一般写法: 

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

    习惯写法: 
    Java代码 
    1. (1..10).each{|i| puts i}  
    2. 或  
    3. 1.upto(10){|i| puts i} # from njmzhang  



    ||=赋值 
    一般写法: 
    Java代码 
    1. number = 1 if number.nil?  
    2. number = 1 unless number  

    习惯写法: 
    Java代码 
    1. number ||= 1  



    程序入口 
    Java代码 
    1. if __FILE__ == $0  
    2. 或  
    3. if $PROGRAM_NAME == __FILE__  

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


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

    其中比较常用的如$:代表库搜索路径,修改方法常见有: 
    Java代码 
    1. $:.unshift('buildscript')  # from gigix  
    2. 或  
    3. $: << File.join(File.dirname(__FILE__), 'CurrentClass')   

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

    %w格式化命令(from qiezi) 可以少打几个引号 
    Java代码 
    1. %w{a b c d} #等价 ['a''b''c''d']   


    ``(~键下的撇号)用来执行shell外部命令,如: 
    Java代码 
    1. `help`  



    inject 
    一般写法: 
    Java代码 
    1. result = []  
    2. (1..10).each{|item| result << item}  

    习惯写法: 
    Java代码 
    1. (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. (1..10).inject{|sum, item| sum += item}  
    2. 这个等于  
    3. (1..10).inject(0){|sum, item| sum += item}  

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


    并行赋值 
    这个很多人都知道了,比如: 
    Java代码 
    1. a,b = 01  
    2. a,b = b, a # 交换a,b  

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

    还有一个用法是让函数返回“多个结果”(不是多个对象),如: 
    Java代码 
    1. def test  
    2.   1,2  
    3. end  
    4. x, y = test #x = 1, y = 2     

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

    注意这种并行匹配当两遍不平衡时会造成的问题: 
    Java代码 
    1. a,b = [1,2,3] # a = 1, b = 23被丢弃  
    2. a,b,c = [1,2] # a = 1, b = 2, c = nil 被初始化成nil   



    *的匹配 
    一般来说*用于把一个array展开: 
    Java代码 
    1. a, *b = [1,2,3]  #a = 1, b = [2,3]  

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


    rescue简单用法 
    Java代码 
    1. begin  
    2.  1/0  
    3. rescue  
    4.   puts 'wrong'  
    5. end  

    可以简化为 
    Java代码 
    1. 1/0 rescue puts 'wrong'  



    命名参数的默认值 
    ruby有默认参数,但其实没有所谓keyword argument,而是提供一个syntax sugar用hash模拟。但是怎么像Rails的方法那样同时利用命名参数和默认参数值呢? 
    Java代码 
    1. def image(opt={})  
    2.     default_opt = {:height => 25, :width => 10}  
    3.     default_opt.merge! opt #opt中同样key的内容会覆盖default_opt中key的value  
    4. end  



    精细duck typing控制 
    duck typing的精神就是行为决定类型,而不是相反 
    Java代码 
    1. a = []  
    2. #不用  
    3. if a.kind_of? Array then a << 1  
    4. if a.instance_of? Array then a << 1  
    5. #而用  
    6. if a.respond_to? :<< then a << 1  



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



    符号转换到Proc 
    一般写法: 
    Java代码 
    1. (1..10).map{|item| item.succ}  

    习惯写法: 
    Java代码 
    1. (1..10).map(&:succ)  

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

    注意这是Rails特有的,通过ActiveSupport对Symbol插入to_proc方法。 
    不用Rails怎么办呢?一种办法是借助Ruby Facets库(gem install facets): 
    Java代码 
    1. require 'facet/symbol/to_proc‘  


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

    Java代码 
    1.   
     
       发表时间:2006-09-19  
    这么全啊。inject我看了几次没理解,干脆不看了。 

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

    从facet可以看出来,ruby里面使劲往一个类里塞东西还是有传统的。
    0  请登录后投票
     
       发表时间: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  请登录后投票
     
       发表时间: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代码 
    1. # to import buildscript/javascripttest.rb ...  
    2. $:.unshift('buildscript')  
    3. require 'javascripttest'  
    0  请登录后投票
     
       发表时间:2006-09-19  
    loop的写法有多种,
    1.upto(10) {...}
    10.downto(1) {...}
    1.step(10, 2) {...}
    0  请登录后投票
     
       发表时间: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  请登录后投票
     
       发表时间:2006-09-19  
    buaawhl 写道

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


    这个不就是把buildscript加到$:路径里吗
  • 相关阅读:
    Java虚拟机--编译那点事儿
    Java虚拟机--常用Java命令(二)
    Java虚拟机--常用Java命令(一)
    Java虚拟机--类加载机制
    Java虚拟机--JIT编译器
    Java虚拟机--垃圾回收机制
    Java虚拟机--对象模型
    Junit测试--多个测试接口如何产生业务联系
    Java虚拟机--内存模型
    Java虚拟机--内存结构
  • 原文地址:https://www.cnblogs.com/lexus/p/1881478.html
Copyright © 2011-2022 走看看