从 门徒 到 训练日
这个标题我想了好久,今天终于写上去了。
两部电影都有惊人的相似。
两种叙事手法,两个不同国度,同一个故事。
让我感触多多。
故事背景:毒品。
黑道版:《门徒》
师父和徒弟的故事,
待续......
白道版:《训练日》
上司和下属的故事,
待续.......
无论你是谁,我就只有一个!
这个标题我想了好久,今天终于写上去了。
两部电影都有惊人的相似。
两种叙事手法,两个不同国度,同一个故事。
让我感触多多。
故事背景:毒品。
黑道版:《门徒》
师父和徒弟的故事,
待续......
白道版:《训练日》
上司和下属的故事,
待续.......
今天无事一个人在延安路上逛街。
我先去庆春路新华书店转了转,出来过天桥,有一人向我使眼神,
他靠近说了声“电脑要不要?”我没搭理他,接着一直走,
我来到银泰,据说同事在这儿做市场调查,我特意来观摩一下,从银泰一楼逛到8楼,没发现同事踪迹。
无趣的我又想起了刚才那个兜售电脑的,平时街上见是见多了,但没体验过。心想也许正一台崭新的T60等着我在,价格还便宜着,一般都是骗子,我还决定体验一把。
我故意走到刚才下天桥的位置,那人好像事先约好一样的迎了上来。
我问:“你卖什么电脑?”
他说:“笔记本”,还一阵微笑,貌似要让我这次捡个打便宜似的
我问:“啥牌子的?”
他用夹生的普通话念出了3个估计他一辈子都不知道含义的字母:“I B M”
我顿时眼睛一亮,忙道:“看看”
他很神秘的问了我一句:“你是不是确定想买?”当时我就断定他是个SB!^_^
我很高调的说道:“废话,不买我站大街上跟你搭个啥话,你的电脑在哪?”
他好像早有准备的带我去了街边:“就在这里看一下吧”
他从身上那个不起眼的×货NB包里掏出了眼熟的小黑,
可还没打开,我就觉得不对,因为事先他没报型号。我从屏幕接口发现和T23一样(头天我还用了一下同事的T23)有金属的方形结合位。而是和底板连在一起的宽宽的黑色接口。
他一打开,居然屏幕就亮了,没关机。屏幕下发赫赫的写着“T43 ” 。我心想,还不错类,如果便宜,可以买个先玩玩。
我仔细一看,键盘是英文+日文的。感觉奇怪的。他很熟练的打开我的电脑属性给我看,我一看迅驰一代2G,512M内存。看来是高配了。
他没让我多点一下,就关上了本本,放进了包包。
我没多想就问价格,他MD就是不说多少钱,问我是不是一定要买。
我一下火了,就说:“你不说价我怎么买,便宜的话我当玩具买个回去,贵了就算了。”,
他一下急了:“就开口3600”。
我说:“你这东西成色太久,而且型号都是两年前的货,放外边一分钱不值”
他说:“这个、、、、这个我也不太清楚,我不懂电脑,反正这个绝对好东西”
我说:“如果配件齐全,质量没问题,我最多出2000。”
他说:“那卖不起,你再加点”
当时我拿还有耐心扯这么多,心想即便是堆垃圾,2000也可以接受了
我让他再次拿出看看,这次我想看的是显卡。
他小心翼翼的拿出来,这次让我来操作:“我直入主题,打开设备管理器,显示卡。”
“ATI9600 128M”我靠,这么牛的配置,如果2000拿下,应该可以了。
他一见我的表情就知道我是想买了,便告诉我,如果想要可以便宜点,2800给我
虽然当时我还比较理智,
平时一直关注小黑,对小黑的配置都还算比较了解,基本都能背出来,
但这个时候又点迷糊了,毕竟一台可以开机正常运行而且高配的T43就在眼前,
我灵机一动,就跟他说:“现金我给你2000,你拿钱走人”
他说:“那不行,最低我再让点,2600”
我说:“如果你非要2600,也可以,我只能给你转帐”
他一下傻了:“怎么个转帐啊,你啥卡啊”
我说:“信用卡,提现手续费太高”
说着说着,我就一直向前走,他一直跟着旁边,几番下来他也不想让,我就说:“你不卖就走人”
他很自觉的停了下来,默默的看着我那高大的背影渐渐的远去,留下的却是他那台不知所云的T43。
我马上一个短信发给了上海一朋友,写道:“黑货,T43,ati9600,512RAM,2000块,如何?”
他小子还真回复的很及时,不到1分钟短信就发了过来:“T43没有听说ati9600的显卡”
妈的,我看完后头冒了一下汗,差点被忽悠了。这时才意识到T43是X300和X700的显卡。
回头再看看,那SB还站在离我三十米的地方向我挥挥手。操
这里我总结了一下我的体验 :
1、不要贪小便宜,虽然我当时也是怀着去体验一下的心态,但真正看到的时候,还是容易失去理智。
2、平时一定要熟背各代小黑配置清单及外观,这样才能以不变应万变,手动心不动。
3、平时逛街,身上一定不要带太多现金,最好钱包,卡也不带。我是老婆不在身边,一个人无所谓了,呵呵
4、小黑还是要到信誉好的X货商买(星星应该不错),二手看都不要看,90%都是拼装起来的,各位可以去淘宝搜一下,几十个本本堆地上,暴汗。
Ruby是一个敏捷的语言。它是”有延展性的( malleable )”
Ruby是一门解释性语言。当然,这可能是一个Ruby编译器最迟实现的原因,但我们认为,不仅快速成型,而且缩短整体开发周期
Ruby是一门表达对象语言。
Ruby是一门高级语言。
这是同事翻译的《Ruby Way》的第一段,可能语句还比较粗糙,但让人未见其面,先闻其声,真真切切的感受到了Ruby的强大和魅力。
说到Ruby,早在去年,我们团队就着手寻求一种高效,精炼,卓越的语言及框架。半年的时间全献给了PHP,直到接近年末由老唐最终决定还是用了Ruby,及 Rails框架。之前最成功的案例之一就是37signals,这也让我们看到的希望。马上我们就开始了Ruby的学习,几乎所有关于Ruby的资料我们都有,《Ruby way 2nd Edition 》就是其中的一本,幸运的是在不到2周的时间内我们自己翻译成了中文版。我真佩服抗战在第一线的翻译同志们,我深知翻译的痛苦,所以向你们致敬^_^,再整理一下,可以出版发行了。
来说正题,Ruby生来就个性十足的,可以用牛气冲天来形容。下面简单点的举两个例子,呵呵
这一个例子中,第一个程序总是Hello, world! 但在这里,让我们用高级一点的程序开始。这里是一个基于华氏度和摄氏度转换的例子:
print "Please enter a temperature and scale (C or F): "
str = gets
exit if str.nil? or str.empty?
str.chomp!
temp, scale = str.split(" ")
abort "#{temp} is not a valid number." if temp !~ /-?\d+/
temp = temp.to_f
case scale
when "C", "c"
f = 1.8*temp + 32
when "F", "f"
c = (5.0/9.0)*(temp-32)
else
abort "Must specify C or F."
end
if f.nil?
print "#{c} degrees C\n"
else
print "#{f} degrees F\n"
end
运行程序的例子:
Please enter a temperature and scale (C or F): 98.6 F
37.0 degrees C
Please enter a temperature and scale (C or F): 100 C
212.0 degrees F
Please enter a temperature and scale (C or F): 92 G
Must specify C or F.
Please enter a temperature and scale (C or F): junk F
junk is not a valid number.
第一个print语句,实际上是调用Kernel的print方法,写到标准输出设备上。
随后,我们调用gets(从标准输入设备上获取字符串), 赋值给变量str,然后作chomp!去掉尾部的换行。
出现的“标准”函数调用,像print和gets实际上都是Object的方法(原始在Kernel)。同样的方式, chop是一个带有str接收参数的方法。Ruby的方法调用通常可以省略圆括号; print “foo” 和 print(“foo”)是等价的。
变量str是一个字符串,但它不能用其他类型代替。在Ruby中,数据有类型,但变量没有。不存在“声明变量”.
调用exit方法终止程序。同行有个控制结构叫if修饰符。它像大多语言存在的if语句,但它放在了语句的后面; 在此后没有else语句,也没有结束修饰符。作为条件,我们检测两件事情:str有一个确定的值(非nil),是不是空串?
同样的语句也可以这样写:
exit if not str or not str[0]
这样写的原因是一个变量有一个nil值,在Ruby中nil是false。事实上,nil和false都是false,其他都为true。特别要注意的是,空串””和数值0不是false。
接下来在字符串上执行一个chomp!(去掉尾部换行)。
下一语句是多个赋值。Split方法使用空格分割字符串成一个数组,右边分割后的结果赋值给左边的两个变量。
随后的if语句使用简单的正则表达式确定是否为有效数字; 匹配一位或多位数字,如果匹配失败,就是一个无效的数字,程序终止。if语句以end关键字结束; 虽然在这不需要,在end前有else。关键字then是可选的; 在这本书中我们不使用它。
To_f方法将字符串转换为浮点数据。实际上,我们将这个浮点数赋给自身变量temp。
Case语句有三个条件,分别是C、F或无效单位。前面两个是计算; 第三个打印错误并终止程序。
在这个例子普遍可以看出Ruby的case语句。在数据类型上没有限制,表达式也是任意的,甚至可能是一个范围或一个正则表达式。
关于计算没什么神秘的。但考虑到变量c和f涉及到case的分支。实际上这些变量只能有一个是有效的。
让我们在控制结构上花点时间。我们已经看到了简单的例子,if语句和if 修饰符; 还有基于unless(else也是可选的)的关键字结构, if 和 unless是相反的。
| Table 1.1. Conditional Statements | |
| "if" Form | "unless" Form |
| if x <> statement1 end | unless x >= 5 then statement1 end |
| if x <> statement1 else statement2 end | unless x <> statement2 else statement1 end |
| statement1 if y == 3 | statement1 unless y != 3 |
| x = if a>0 then b else c end | x = unless a<=0 then c else b end |
Ruby中的case语句比大多数语言都强大。这个多分支甚至能测试条件,例如,一个匹配模式。Case语句的这个测试对应运算符(= = =),让我们看这个例子:
case "This is a character string." when "some value" puts "Branch 1" when "some other value" puts "Branch 2" when /char/ puts "Branch 3" else puts "Branch 4"end 上面的代码输出第三个分支。为什么呢?首先尝试检测”some value”或”some other value”; 这个失败,因此继续,第三个测试是一个模式; 匹配模式,所以成功,第三个print执行。当所有的case都不成功,执行else。
如果测试表达式是一个整型,比较值是个整型范围(如:3.8)。在这种情况下,表达式在这个范围内测试。在所有的实例中,总是执行满足条件的第一个分支。
至于循环机制,Ruby有很多种。wile和until控制结构是两个预测试的循环。
在表1.2的例子中,假设一个叫list的数组,定义:list = %w[alpha bravo Charlie delta echo]; 遍历数组的每个元素。
| Table 1. Looping Constructs | |
| # i=0 while i <> print "#{list[i]} " i += 1 end | # i=0 until i == list.size do print "#{list[i]} " i += 1 end |
| # for x in list do print "#{x} " end | # list.each do |x| print "#{x} " end |
| # i=0 n=list.size-1 loop do print "#{list[i]} " i += 1 break if i > n end | # i=0 n=list.size-1 loop do print "#{list[i]} " i += 1 break unless i <= n end |
| # n=list.size n.times do |i| print "#{list[i]} " end | # n=list.size-1 0.upto(n) do |i| print "#{list[i]} " end |
| # n=list.size-1 for i in 0..n do print "#{list[i]} " end | # list.each_index do |xt print "#{list[x]} " end |
让我们测试一下细节。循环1和2都是while和until的“标准”循环; 他们本质上是相同的,但它们的条件是互补的。循环3和4也是一样的。
在前面的例子中,我们没有强调while和until循环的”修饰符”。其实这也是很很用的,它们很简明。下面的例子,两者是等价的:
perform_task() until finished
perform_task() while not finished
在表1.2忽略了一个重大的事情:循环并不总是从开始运行到结束的,中间可能会迭代,或是终止循环。我们需要控制循环。
第一种方式是关键字break, 如上面的循环5和6.使用它跳出循环;在嵌套循环的情况下,只跳出它所在的循环。
关键字retry有两方面迭代上下文和begin end块的上下文。在任何迭代内容里(或for循环)
关键字redo是retry的广义。对于whilet和until循环作为retry的迭代
关键字next是跳出内层循环
在Ruby中,我们已经看到迭代器很重要,我们所未看到的是Ruby语言允许用户定义迭代器添加到预定义。
对于任何对象默认的迭代器是each。这就足够了,因为它允许for循环使用。但迭代器可能给定不同的名字和不同的用途
一个例子,多用途的迭代器。
def repeat(condition)
yield
retry if not condition
end
在这个例子中,当调用迭代器时,关键字yield调用块
j=0repeat (j >= 10) do j+=1 puts jend 也有可能通过yield传递参数,作为块的参数列表。有些例子,下面的迭代器只生成整数1到10,迭代器的调用生成10个数的立方:
def my_sequence
for i in 1..10 do
yield i
end
end
my_sequence {|x| puts x**3 }