- 浏览: 647080 次
- 性别:
- 来自: Shanghai
文章分类
最新评论
-
107x:
不错,谢谢!
Vim多行缩进技巧 -
can007:
EC2是不负责储存???
体验Amazon EC2 -
vanxining:
书名是什么呢?
Neural Network依然不是理想的AI -
贾懂凯:
缩进的标准是tab,linux默认tab=8。在不同的平台会出 ...
Vim多行缩进技巧 -
edison0951:
貌似他的老师是波谱尔吧,和黑天鹅讲的东西差不多
索罗斯与因果论
Ruby有不少惯用法,这里略作一些介绍,也方便阅读他人代码:
迭代
一般写法:
for i in (1..10)
puts i
end
习惯写法:
||=赋值
一般写法:
习惯写法:
程序入口
这个相当于main(), 逻辑判断的意思当程序名($0或另一个)和当前文件名(__FILE__)一致时,也就是当前文件是被单独执行的而不是被别的文件调用。这个方法还有个用法是作为unit test使用。
预设变量和特殊记号
类似$0的Perl风格预设常量还有很多,参见Programming Ruby p319
其中比较常用的如$:代表库搜索路径,修改方法常见有:
后一种方法使用了相对路径,因为Ruby的module不要求namespace和文件目录结构要对应一致,很多时候统统放一个目录里
%w格式化命令(from qiezi) 可以少打几个引号
``(~键下的撇号)用来执行shell外部命令,如:
inject
一般写法:
习惯写法:
inject有点难理解,相当于python的reduce和一些FP里的fold。inject的块变量有两个(这里是array和item),第二个变量(item)用来枚举被inject的集合(这里是(1..10)这个range), 而第一个变量(array)由inject的参数初始化(这里是[],可选),并在block被反复执行时保持持久(相当于静态变量),而item则在每次枚举时被更新为下一个值。我们再看一下inject的另一种通常用法就会更明白了:求和
也就是块变量sum被初始化成0然后反复迭代执行块的内容,最后返回sum
并行赋值
这个很多人都知道了,比如:
当然可以延伸出一些很诡异的变化,不提倡使用阿
还有一个用法是让函数返回“多个结果”(不是多个对象),如:
这个njmzhang说的很对,其实函数返回的是一个array,然后再并行匹配到变量上去。(所以我对多个结果特别加了引号)
这显然是个syntax sugar,你随便用逗号分割几个变量是不会自动组成array的。
注意这种并行匹配当两遍不平衡时会造成的问题:
*的匹配
一般来说*用于把一个array展开:
类似FP里的x:xs(haskell), x::xs(ocaml), [a | b] (erlang from 布娃娃)
rescue简单用法
可以简化为
命名参数的默认值
ruby有默认参数,但其实没有所谓keyword argument,而是提供一个syntax sugar用hash模拟。但是怎么像Rails的方法那样同时利用命名参数和默认参数值呢?
精细duck typing控制
duck typing的精神就是行为决定类型,而不是相反
获取metaclass
这也比较常见了,各种动态伎俩的开始
符号转换到Proc
一般写法:
习惯写法:
map(fun(x))般的FP风格
注意这是Rails特有的,通过ActiveSupport对Symbol插入to_proc方法。
不用Rails怎么办呢?一种办法是借助Ruby Facets库(gem install facets):
Facets库包括大量对Ruby核心类的扩展,是个有趣而又危险的大杂烩,也许我以后会另外再专门介绍一下。
迭代
一般写法:
for i in (1..10)
puts i
end
习惯写法:
(1..10).each{|i| puts i} 或 1.upto(10){|i| puts i} # from njmzhang
||=赋值
一般写法:
number = 1 if number.nil? number = 1 unless number
习惯写法:
number ||= 1
程序入口
if __FILE__ == $0 或 if $PROGRAM_NAME == __FILE__
这个相当于main(), 逻辑判断的意思当程序名($0或另一个)和当前文件名(__FILE__)一致时,也就是当前文件是被单独执行的而不是被别的文件调用。这个方法还有个用法是作为unit test使用。
预设变量和特殊记号
类似$0的Perl风格预设常量还有很多,参见Programming Ruby p319
其中比较常用的如$:代表库搜索路径,修改方法常见有:
$:.unshift('buildscript') # from gigix 或 $: << File.join(File.dirname(__FILE__), 'CurrentClass')
后一种方法使用了相对路径,因为Ruby的module不要求namespace和文件目录结构要对应一致,很多时候统统放一个目录里
%w格式化命令(from qiezi) 可以少打几个引号
%w{a b c d} #等价 ['a', 'b', 'c', 'd']
``(~键下的撇号)用来执行shell外部命令,如:
`help`
inject
一般写法:
result = [] (1..10).each{|item| result << item}
习惯写法:
(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的另一种通常用法就会更明白了:求和
(1..10).inject{|sum, item| sum += item} 这个等于 (1..10).inject(0){|sum, item| sum += item}
也就是块变量sum被初始化成0然后反复迭代执行块的内容,最后返回sum
并行赋值
这个很多人都知道了,比如:
a,b = 0, 1 a,b = b, a # 交换a,b
当然可以延伸出一些很诡异的变化,不提倡使用阿
还有一个用法是让函数返回“多个结果”(不是多个对象),如:
def test 1,2 end x, y = test #x = 1, y = 2
这个njmzhang说的很对,其实函数返回的是一个array,然后再并行匹配到变量上去。(所以我对多个结果特别加了引号)
这显然是个syntax sugar,你随便用逗号分割几个变量是不会自动组成array的。
注意这种并行匹配当两遍不平衡时会造成的问题:
a,b = [1,2,3] # a = 1, b = 2, 3被丢弃 a,b,c = [1,2] # a = 1, b = 2, c = nil 被初始化成nil
*的匹配
一般来说*用于把一个array展开:
a, *b = [1,2,3] #a = 1, b = [2,3]
类似FP里的x:xs(haskell), x::xs(ocaml), [a | b] (erlang from 布娃娃)
rescue简单用法
begin 1/0 rescue puts 'wrong' end
可以简化为
1/0 rescue puts 'wrong'
命名参数的默认值
ruby有默认参数,但其实没有所谓keyword argument,而是提供一个syntax sugar用hash模拟。但是怎么像Rails的方法那样同时利用命名参数和默认参数值呢?
def image(opt={}) default_opt = {:height => 25, :width => 10} default_opt.merge! opt #opt中同样key的内容会覆盖default_opt中key的value end
精细duck typing控制
duck typing的精神就是行为决定类型,而不是相反
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
这也比较常见了,各种动态伎俩的开始
sing = class << self; self; end
符号转换到Proc
一般写法:
(1..10).map{|item| item.succ}
习惯写法:
(1..10).map(&:succ)
map(fun(x))般的FP风格
注意这是Rails特有的,通过ActiveSupport对Symbol插入to_proc方法。
不用Rails怎么办呢?一种办法是借助Ruby Facets库(gem install facets):
require 'facet/symbol/to_proc‘
Facets库包括大量对Ruby核心类的扩展,是个有趣而又危险的大杂烩,也许我以后会另外再专门介绍一下。
评论
24 楼 xly_971223 2007-05-13写法太灵活了是好事还是坏事呢?
一人一种写法 读起来会不会很吃力?23 楼 cino 2007-05-13楼主总结的很好,学习中,谢谢!22 楼 dazuiba 2007-05-12qiezi 写道Suninny 写道还有借鉴了Perl的:
names = %w[ruby rails java python cookoo firebody]
等同于:
names = ["ruby", "rails", "java", "python", "cookoo", "firebody"]
%w, %r, %Q, %q, %s, %x还挺多。
好像在哪里看到过这些惯用法的全称,但是记不得地址了,谁给个链接?21 楼 pilipala 2006-09-20qiezi 写道这么全啊。inject我看了几次没理解,干脆不看了。
ruby函数调用可以省括号,方便是方便,不过一些FP用法也看不见了,这方面python还比较好。
从facet可以看出来,ruby里面使劲往一个类里塞东西还是有传统的。
inject的确挺不太容易搞明白的,为了搞明白索性简单实现一下,这样理解应该会更深刻些,比如:(1..10).inject{|sum, item| sum += item}
可以用下面的代码简单实现
class Range def my_inject(x) each { |i| x = yield(x,i) } return x end end
仔细想想,ruby这种yield的机制真好,将通常的一个函数调用,变成了2个函数的组合调用。
这样一方面灵活性大大增加,变化更多。原来是写n个函数就是n种方式,现在变成写 n+m个函数就有了n*m种调用方式了。当然,别的语言也可以做到类似的实现,可是会造成太多的冗余代码,不但写得麻烦,读起来也累。
另一方面,更有利于把任务划分成更小的单位,这样会减少重复代码,让程序变得更简洁,尽量做到DRY( don't repeat yourself )
刚开始看ruby,感觉是一个不错的方向。
20 楼 cookoo 2006-09-20好用么?我看了一下,大部分都已经包含在facet/core里面了。
另外好像不能精细require? 这样的话在rails里用会引起一些命名冲突。19 楼 capitain 2006-09-20extionsions也是一个扩展包, cookoo 有没有在用?18 楼 qiezi 2006-09-20cookoo 写道
@@这个太离谱了吧。。。常用只有%w{},别的很少用,不就整个字符串嘛。
而且这个再加上字符串格式化那些%一堆或日期格式化里的%一堆,天哪,还是不要增加记忆负担了。
主要是用在正则表达式里。有时候正则表达式里要匹配'/'字符,为了不写成\/,就把默认的//改成%r{},如果里面还要匹配{},就可以改成%r()。圆括号和方括号又容易看错成正则表达式里面的东西,于是改成@。。。17 楼 cookoo 2006-09-20qiezi 写道Suninny 写道还有借鉴了Perl的:
names = %w[ruby rails java python cookoo firebody]
等同于:
names = ["ruby", "rails", "java", "python", "cookoo", "firebody"]
%w, %r, %Q, %q, %s, %x还挺多。
另外不光是括号、中括号,键盘上能看到的符号差不多都支持:
%w@ruby rails java python cookoo firebody@
%w#ruby rails java python cookoo firebody#
%w~ruby rails java python cookoo firebody~
...
真是方便。
@@这个太离谱了吧。。。常用只有%w{},别的很少用,不就整个字符串嘛。
而且这个再加上字符串格式化那些%一堆或日期格式化里的%一堆,天哪,还是不要增加记忆负担了。
16 楼 cookoo 2006-09-20njmzhang 写道cookoo 写道
python的list comprehension是我个人很喜欢的syntax sugar
我觉得Python的list comprehension很丑陋,英语单词太多,复杂一点的list comprehension就能写成一长串,反而不好阅读。
好像还是Haskell的list comprehension看着更明白
python的list comprehension语法偏自然语言,haskell的偏数学表达,两个各有千秋,但都比ruby没有强。当然list comprehension本身也不是万能,不能把什么都往里面塞,复杂的还是老实用map之类的好。15 楼 qiezi 2006-09-20Suninny 写道还有借鉴了Perl的:
names = %w[ruby rails java python cookoo firebody]
等同于:
names = ["ruby", "rails", "java", "python", "cookoo", "firebody"]
%w, %r, %Q, %q, %s, %x还挺多。
另外不光是括号、中括号,键盘上能看到的符号差不多都支持:
%w@ruby rails java python cookoo firebody@
%w#ruby rails java python cookoo firebody#
%w~ruby rails java python cookoo firebody~
...
真是方便。14 楼 thundercao 2006-09-20好东西,收藏一下13 楼 njmzhang 2006-09-20cookoo 写道
python的list comprehension是我个人很喜欢的syntax sugar
我觉得Python的list comprehension很丑陋,英语单词太多,复杂一点的list comprehension就能写成一长串,反而不好阅读。
好像还是Haskell的list comprehension看着更明白12 楼 Suninny 2006-09-20buaawhl 写道
。。。
搜索了一下,ruby unshift,结果出来很多 array unshift 的结果。
到底是没有找到 $:.unshift('buildscript') 的具体说明。
你没找错啊,$:是一个Array类型的全局变量,unshift是Array的一个实例变量。
找文档无需Google的,ri一下就OK了:ri Array#unshift11 楼 Suninny 2006-09-20还有借鉴了Perl的:
names = %w[ruby rails java python cookoo firebody]
等同于:
names = ["ruby", "rails", "java", "python", "cookoo", "firebody"]
10 楼 cookoo 2006-09-20谢谢大家的补充和斧正 :^) 我相应更新了一些内容
python的list comprehension是我个人很喜欢的syntax sugar,它主要是map和filter的复合化身,和inject/reduce/fold应该没瓜葛。
关于name space管理,最近关于Rails的controller和model为什么用name space分割很麻烦有不少争论。另外有些plugin也不注意合理使用name space包裹。Rails下Module.constants已经包含太多所谓根命名,这个数量越多冲突可能性越高。
firebody: 辛苦你翻译了,我想java的fp扩展里应该有类似功能。我原文说’返回两个结果‘确实容易让人困扰,已澄清。9 楼 njmzhang 2006-09-19firebody 写道
另外对于那个 函数可以返回多个值 。
函数不是返回多个值,
在Pickaxe里有写道:
"if you give return multiple parameters, the method returns
them in an array. You can use parallel assignment to collect this return value."8 楼 buaawhl 2006-09-19
a,b = 0, 1
a, *b = [1,2,3] #a = 1, b = [2,3]
这两条可以合起来看.
a,b = 0, 1
右边的 0, 1 类似于一个 tuple ( 可以理解为定长数组 )
对应到FP是,
{a, b} = {0, 1}
a, *b = [1,2,3]
对应到FP是,
[a | b] = [1, 2, 3]
7 楼 firebody 2006-09-19(1..10).inject([]){|array, item| array << item}
翻译成java code:package com.redsoft.jpa.query.nativequery; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; /** * * @author firebody * @since 2006-9-19 22:02:29 * */ public class Injecter { Iterator iter; public Injecter(Iterator iter) { super(); this.iter = iter; } public void kickoff(Class type, InjecterCodeBlack executeBlack) { Object instance = null; try { instance = type.newInstance(); } catch (InstantiationException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } while (iter.hasNext()) { executeBlack.executeCodeBlack(instance, iter.next()); } } interface InjecterCodeBlack { void executeCodeBlack(Object arg1, Object iteratedItem); } public static void main(String[] args) { new Injecter(Arrays.asList(new String[] { "1", "2", "3" }).iterator()) .kickoff(ArrayList.class, new InjecterCodeBlack() { public void executeCodeBlack(Object arg1, Object iteratedItem) { ((List) arg1).add(iteratedItem); System.out.println(arg1); } }); } }
另外对于那个 函数可以返回多个值 。
我想乱弹一下,哈哈,大家别笑话我这个ruby门外汉 。
这是我和某某人乱弹经过:
引用倪宏业 说:
def test
1,2
end
x, y = test #x = 1, y = 2
firebody(啊翔) 说:
感觉他名次上搞了一些技巧
firebody(啊翔) 说:
其实我认为这不是返回两个结果
倪宏业 说:
x,y=test 是赋值 ?
firebody(啊翔) 说:
对,这是一个分别赋值
倪宏业 说:
其实是这么理解的
x,y = test #;
x = 1;
y = 2;
三句?
firebody(啊翔) 说:
我分析有两种可能
firebody(啊翔) 说:
一种是 ruby本身有更进一步的分析引擎,分析出的单元执行语句就是你上面提到的
倪宏业 说:
晕#是注释吧?
firebody(啊翔) 说:
晕倒,当然了
倪宏业 说:
我还当成一个交换符,哈哈。。。
firebody(啊翔) 说:
一种是 ruby本身对这种并行负值作了特殊的支持 ,
firebody(啊翔) 说:
比如 x , y 是一个特殊对象,表示 一个变量集合域
firebody(啊翔) 说:
1,2表示一个对象,是一个值域
firebody(啊翔) 说:
x,y = 1,2
firebody(啊翔) 说:
两边是相同的对象类型(域类型)
firebody(啊翔) 说:
然后=在这个类型上作了特殊的定义
firebody(啊翔) 说:
可能就分别赋值得语义
firebody(啊翔) 说:
以为ruby可以把任意的对象从新组合成一个新的对象
firebody(啊翔) 说:
在这个新的对象上执行新的操作,符号赋写就被赋予更特殊的含义
firebody(啊翔) 说:
所以,后面的分析 我觉得更有可能一些
firebody(啊翔) 说:
如果是 后面的那种分析的话
倪宏业 说:
感觉复杂了
firebody(啊翔) 说:
cookoo说返回两个对象,就是感觉是一种“名次的欺骗? “
firebody(啊翔) 说:
其实就是返回一个对象
firebody(啊翔) 说:
哦,也可能是我胡思乱想,哈哈
firebody(啊翔) 说:
可能就是 ruby进行再解析了6 楼 njmzhang 2006-09-19buaawhl 写道
搜索了一下,ruby unshift,结果出来很多 array unshift 的结果。
到底是没有找到 $:.unshift('buildscript') 的具体说明。
这个不就是把buildscript加到$:路径里吗5 楼 buaawhl 2006-09-19gigix 写道
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') 的具体说明。发表评论
-
对Django的遗憾
2006-11-08 12:18 17128对django的错失良机我一直觉得很遗憾。我去年大概10月的时 ... -
Rails目前的一些局限
2006-11-08 12:17 2692robbin前面提到了一些局限,如遗留数据库是约定造成的,可以 ... -
Need for Speed
2006-11-06 07:38 6333Erb的渲染一直有人说慢,而c版本的eruby始终没有和Rai ... -
Ruby yield释疑
2006-11-01 03:10 4164context switch不足以表明coroutine,一般 ... -
Passing Parameters to before_filter
2006-10-30 07:23 1998I've just noticed that before_f ... -
ROR: the disruptive innovation
2006-09-29 22:13 1637I happen to read about a great ... -
Farewell, Java
2005-11-20 15:34 1881Evaluation: moving from Java t ... -
Try Ruby
2005-12-22 20:34 1741I'm systematically learning Rub ... -
10 Things Every Java Programmer Should Know About Ruby
2005-12-29 01:35 1662Happened to find this wonderful ... -
Heading fast on Rails~
2006-03-24 00:14 1513Not to mention the recent two S ... -
Ruby小窍门3则
2006-10-29 11:16 2649*怎么转16进制? class Integer de ... -
Ruby的根模块命名空间
2006-10-24 05:30 6827如果你要定制Rails的违例输出页面的话的,一般会用这样的代码 ... -
Rails Cache
2006-10-21 10:59 6488Rails提供三种页面cache方式: action ca ... -
加强版irb
2006-10-20 11:48 10313Ruby的irb和Unix shell一样,通过定制可以提供更 ... -
rake test:units在SQL和Ruby DSL两种schema模式下的差异
2006-10-10 01:16 2290sql方式,会复制development数据库中的外键。相反, ... -
有奖竞猜
2006-10-02 05:51 5041如下代码,第一位正确说出它的功能的我会给4星评价,第一个发现其 ... -
Ruby简化属性声明与初始化
2006-09-27 00:57 2721如果要一边声明一边初始化可以用这样的代码: class O ... -
Ruby和Python的语法差别
2006-09-25 18:35 23223布娃娃在另一个帖子提 ... -
对Robbin《ruby on rails为什么暂时无法成为企业应用开发的主流?》的一些思考
2006-09-17 20:19 2343对Rails开发方式我也在思考,对动态类型和meta prog ... -
RJS经验点滴
2006-09-14 14:54 2468所见即所得方式的问卷设计器终于搞定了,一些细节体会: * 任何 ...
相关推荐
### Ruby惯用法详解 #### 一、简介 Ruby是一种简单快捷的面向对象的脚本语言,具有丰富的类库和简洁的语法结构。在实际开发过程中,为了提高代码的可读性和可维护性,Ruby社区形成了一系列约定俗成的惯用法(idioms...
在Ruby社区中,惯用法(idioms)和最佳实践(best practices)是提高代码质量的关键。本文将深入探讨Ruby中的关键技巧、重构方法以及遵循的代码风格指南。 一、Ruby技巧 1. 块和迭代器:Ruby中的块(blocks)和...
在讲述Ruby知识的过程中,始终从Rails开发实战出发,揭示Rails和Puby之间的微妙关系,阐述Rails自身特有的技术、惯用法和设计理念,并用Rails开发了一个网上音乐店实例。最后还介绍了探索Rails源代码的各种技术,为...
1. **Ruby idioms**:书中将深入探讨Ruby的惯用法,这些是让代码更简洁、更具Ruby风格的关键。 2. **编程技巧**:如何利用Ruby的特性编写出高效且易于维护的代码,如上下文敏感的语法糖和内建函数的巧妙使用。 3. ...
6. 惯用法和语言扩展:书中还可能会介绍Ruby中的惯用法,以及如何通过元编程进行语言扩展和自定义。这些高级特性是Ruby语言灵活多变的重要原因,也是使Ruby成为一门值得学习的语言的关键特性之一。 7. 历史影响:...
通过学习Ruby,开发者可以更容易地理解和运用这些惯用法。 - **扩展性**:Ruby的强大之处在于其高度的灵活性和可扩展性。掌握了Ruby,开发者就能够根据自己的需求灵活地扩展Rails的功能,创造出更加符合业务场景的...
4. Rails技术、惯用法和设计理念:本书还涵盖了Rails特有的技术点、编程惯用法以及Rails的设计哲学,这些都是构建Rails应用时不可忽视的重要方面。 5. 实战项目:作者通过构建一个网上音乐店的实例来展示如何使用...
它实现了一种以声明方式编写某些类型的代码的惯用法。 特别是,这是为了使Rails控制器和视图更整洁。 安装BasicAssumption 这是一颗宝石,通常也是如此: [sudo] gem install basic_assumption 在Rails应用程序...
3. **惯用法(Idiomatic)**:在编程领域,惯用法是指在特定编程语言或社区中广泛接受的最佳实践,它有助于保持代码的一致性和可读性。 4. **Sublime Text**:Sublime Text是一款流行的文本编辑器,以其速度、简洁...
2. **构架建模惯用法**:为了确保构架模型的一致性和清晰性,通常会采用一套固定的建模惯用法。例如,在用例视图中,用例通常会被命名为描述性的动作短语,以便于理解其功能。 #### 八、结论 综上所述,技术框架在...
5. **C抽象惯用法**:在C语言中,有一些约定俗成的做法可以帮助提高代码的可读性和可维护性。 6. **C的抽象范式之OOP**:虽然C语言本身不支持面向对象编程,但可以通过指针等机制来模拟OOP的概念。 7. **C的观点:...