庄周梦蝶

生活、程序、未来
   :: 首页 ::  ::  :: 聚合  :: 管理


4.38,谜题就有翻译错误,问题更是错的离谱。原题是这样的:
Baker, Cooper, Fletcher, Miller, and Smith live on different floors of an apartment house
that contains only five floors. Baker does not live on the top floor. Cooper does not live on
the bottom floor. Fletcher does not live on either the top or the bottom floor. Miller lives on
a higher floor than does Cooper. Smith does not live on a floor adjacent to Fletcher's.
Fletcher does not live on a floor adjacent to Cooper's. Where does everyone live?

其中说Miller住的比Cooper高,却翻译成了Miller住的比Cooper高一层,如果按照这个翻译来谜题是没有答案的。
回到4.38,题目是这样的:
Modify the multiple-dwelling procedure to omit the requirement that Smith and Fletcher do
not live on adjacent floors. How many solutions are there to this modified puzzle?

翻译却成了增加Smith和Fletcher不住在相邻层这个条件,谜题本来就是如此,何来的增加?错将omit翻译成了“增加”。
这道题很简单咯,将
(require (not (= (abs (- smith fletcher)) 1)))
注释掉即可,答案增加到5个:
> (multiple-dwelling)
((baker 
1) (cooper 2) (fletcher 4) (miller 3) (smith 5))
> (amb)
((baker 
1) (cooper 2) (fletcher 4) (miller 5) (smith 3))
>  (amb)
((baker 
1) (cooper 4) (fletcher 2) (miller 5) (smith 3))
>  (amb)
((baker 
3) (cooper 2) (fletcher 4) (miller 5) (smith 1))
>  (amb)
((baker 
3) (cooper 4) (fletcher 2) (miller 5) (smith 1))

4.39,约束条件的顺序肯定是有影响的,能缩小搜索范围的强约束条件排在前面,弱约束条件排在后面,可以减少整体的判断次数。在DrScheme中,可以启用profile来分析顺序带来的影响,打开language->R5RS->Show Details,选择Debugging and Profiling 即可。运行scheme程序,然后在View->Show Profile中查看具体分析结果,在该视图中将详细列出各个函数调用的时间和次数。
在没有调整顺序前:
Msec      Calls      Function
40            1               multiple-dwelling
0              1716         require
4              2524          distinct?

说明multiple-dwelling调用了一次,花费了40毫秒,而require和distinct?函数分别被调用了1716次和2524次。
然后我将
(require
     (distinct? (list baker cooper fletcher miller smith)))

这个我认为弱约束条件放到了最后,测试的结果并不让人满意:
Msec      Calls      Function
44            1               multiple-dwelling
4              6035         require
0              129          distinct?

并没有大的提高,甚至反而所下降。猜测问题在于我使用的amb实现是call/cc、宏实现的,待俺完成amb求值器再测试一下。

4.40,题目都提示咯,嵌套let语句,我的解答:
(define (multiple-dwelling2)
  (let ((baker   (amb 
1 2 3 4 5)))
     (require (not (
= baker 5)))
      (let ((cooper  (amb 
1 2 3 4 5)))
        (require (not (
= cooper 1)))
        (let ((fletcher (amb 
1 2 3 4 5)))
          (require (not (
= fletcher 5))) 
          (require (not (
= fletcher 1)))
          (require (not (
= (abs (- fletcher cooper)) 1)))
          (let ((miller (amb 
1 2 3 4 5)))
             (require (
> miller cooper))
             (let ((smith   (amb 
1 2 3 4 5)))
                (require (not (
= (abs (- smith fletcher)) 1)))
                (require (distinct
? (list baker cooper fletcher miller smith)))
                (list (list 
'baker baker)
                      (list 'cooper cooper)
                      (list 'fletcher fletcher)
                      (list 'miller miller)
                      (list 'smith smith))))))))

profile一下,multiple-dwelling2的调用时间缩小到8毫秒,require和distinct?的调用次数分别降低到了404和129次。


4.42,说谎者谜题,
五个女生参加一个考试,她们的家长对考试结果过分关注。为此她们约定,在给家里写信谈到考试的时候,每个姑娘都要写一句真话和一句假话。下面是从她们的信里摘抄出来的句子:
Betty : kitty考第二,我只考了第三
Ethel : 你们应该很高兴听到我考了第一,joan第二
joan :   我考第三,可怜的Ethel垫底
kitty:  我第二,marry只考了第四
marry: 我是第四,Betty的成绩最高。
这五个姑娘的实际排名是什么?

将题目翻译成代码就OK了,说明性编程真是舒坦:
(define (liars-puzzle)
  (let ((betty (amb 
1 2 3 4 5))
        (ethel (amb 
1 2 3 4 5))
        (joan (amb 
1 2 3 4 5))
        (kitty (amb 
1 2 3 4 5))
        (marry (amb 
1 2 3 4 5)))
    (require
       (distinct
? (list betty ethel joan kitty marry)))
    (require (or (
= kitty 2) (= betty 3)))
    (require (not (and (
= kitty 2) (= betty 3))))
    (require (or (
= ethel 1) (= joan 2)))
    (require (not (and (
= ethel 1) (= joan 2))))
    (require (or (
= joan 3) (= ethel 5)))
    (require (not (and (
= joan 3) (= ethel 5))))
    (require (or (
= kitty 2) (= marry 4)))
    (require (not (and (
= kitty 2) (= marry 4))))
    (require (or (
= marry 4) (= betty 1)))
    (require (not (and (
= marry 4) (= betty 1))))
    (list (list 
'betty betty)
          (list 'ethel ethel)
          (list 'joan joan)
          (list 'kitty kitty)
          (list 'marry marry))))

答案是:
((betty 3) (ethel 5) (joan 2) (kitty 1) (marry 4))

4.43.也很有趣的题目,游艇迷题,
   Mary Ann Moore的父亲有一条游艇,他的四个朋友Colonel Dowing、Mr.Hall、Sir Barnacle Hood和Dr.Parker也各有一条。这五个人都有一个女儿,每个人都用另一个人的女儿的名字来为自己的游艇命名。Sir Barnacle的游艇叫Gabrielle,Mr.Moore拥有Lorna,Mr.Hall的游艇叫Rosalind,Melissa属于Colonel Downing(取自Sir Barnacle的女儿的名字),Garielle的父亲的游艇取的是Dr.Parker的女儿的名字。请问,谁是Lorna的父亲。

先说下结果,Lorna的父亲是Downing。
具体解答如下,先定义辅助过程:
(define (father yacht daughter)
     (cons yacht daughter))
(define (yacht father)
  (car father))
(define (daughter father)
  (cdr father))

然后翻译题目为代码即可,暂不考虑效率问题:
(define (yacht-puzzle)
  (let ((moore (father 
'lorna 'mary))  ;;Mr.Moore
        (downing (father 
'melissa (amb 'mary 'melissa 'gabrielle 'rosalind 'lorna))))  ;;Colonel Downing
    (require (not (equal
? (yacht downing) (daughter downing))))
    (let ((hall (father 
'rosalind (amb 'mary 'melissa 'gabrielle 'rosalind 'lorna))))  ;;Mr.Hall
       (require (not (equal
? (yacht hall) (daughter hall))))
       (let ((barnacle (father 
'gabrielle 'melissa))   ;;Sir Barnacle Hood
             (parker (father (amb 
'mary 'melissa 'gabrielle 'rosalind 'lorna) (amb 'mary 'melissa 'gabrielle 'rosalind 'lorna))))         ;;Dr.Parker
         (require (not (equal
? (yacht parker) (daughter parker))))
         (let ((gabrielle
-father (amb moore downing hall barnacle parker))) ;;Garielle's Father
           (require (equal? (daughter gabrielle-father) 'gabrielle))   
           (require (equal? (yacht gabrielle-father) (daughter parker)))
           (require (distinct
? (map daughter (list moore downing hall barnacle parker))))
           (require (distinct
? (map yacht (list moore downing hall barnacle parker))))
           (list 
              (list 
'moore (yacht moore) (daughter moore))
              (list 'downing (yacht downing) (daughter downing))
              (list 'hall (yacht hall) (daughter hall))
              (list 'barnacle (yacht barnacle) (daughter barnacle))
              (list 'parker (yacht parker) (daughter parker))))))))

运行(yacht-puzzle)的结果为:
((moore lorna mary) (downing melissa lorna) (hall rosalind gabrielle) (barnacle gabrielle melissa) (parker mary rosalind))

三元组:父亲名、游艇名、女儿名,因此lorna的父亲是Downing。Garielle的父亲是Mr.Hall,Mr.Hall的游艇名叫做Rosalind,正是Dr.Parker的女儿名字。

延伸题目,如果没有Mary Ann姓Moore这个条件,答案将有三个,分别是:
((moore lorna mary) (downing melissa lorna) (hall rosalind gabrielle) (barnacle gabrielle melissa) (parker mary rosalind))
((moore lorna gabrielle) (downing melissa rosalind) (hall rosalind mary) (barnacle gabrielle melissa) (parker mary lorna))
((moore lorna lorna) (downing melissa mary) (hall rosalind gabrielle) (barnacle gabrielle melissa) (parker mary rosalind))



posted @ 2008-11-15 00:02 dennis 阅读(1591) | 评论 (0)编辑 收藏

本节开始介绍神奇的amb函数,为引入逻辑程序设计做铺垫。关于amb,有清华王垠的一个文档:
http://cs2.swfc.edu.cn/~wanghuan/wangyin1/amb/amb.html

4.35,与an-element-of类似:
(define (an-integer-between low high)
  (require (not (
> low high)))
  (amb low (an
-integer-between (+ low 1) high)))

4.36,与练习3.69相关,貌似我没解过这道题,略过。

4.37,两点大大缩小了搜索范围:
1)通过限制i^2+j^2<= high^2,平方和大于上限平方的全部过滤掉
2)k的判断不再通过amb取值,而是求平方和的平方根是否为整数来判断,进一步缩小了搜索范围

posted @ 2008-11-04 01:20 dennis 阅读(1625) | 评论 (0)编辑 收藏


4.27,

;;; L-Eval input:
(define count 
0)

;;; L
-Eval value:
ok

;;; L
-Eval input:
(define (id x)
  (set
! count (+ 1 count))
  x)

;;; L
-Eval value:
ok

;;; L
-Eval input:
(define w (id (id 
10)))

;;; L
-Eval value:
ok

;;; L
-Eval input:
count

;;; L
-Eval value:
1

;;; L
-Eval input:
w

;;; L
-Eval value:
10

;;; L
-Eval input:
count

;;; L
-Eval value:
2

至于原因,w在没有强迫求值前,仅仅执行了一步(id 10),因此此时count为1,当要求打印w的时候force执行了第二步(id 10),因此count增加为2。

4.28,当参数也是函数的时候,例如:
(define square (lambda(x) (* x x)))
(define (test proc a)
  (proc a))
(test square 
3)

如果对operator不采用actual-value,那么square将延时求值,在执行(proc a)时无法辨认eval的过程类型。

4.29,俺第一个想到的就是树形递归的斐波那契数列:
(define (fib n)
  (cond ((
= 0 n) 0)
            ((
= 1 n) 1)
            (
else
              (
+ (fib (- n 1)) (fib (- n 2))))))
不带记忆功能和带记忆功能的force-it之间的性能差距非常明显。

第二问,有趣的地方在于square过程,注意到(define (square x) (* x x)),x在body出现了两次,那么如果是使用不带记忆功能的force-it, x将被求值两次,如果x本身带有副作用(例如例子里面的id过程),那么显然副作用也将被调用两次,因此答案不言自明。带记忆功能的force-it版本中,count将仍然是1,而在不带记忆功能的版本中count将增长到2。

4.30,第一问,我也谈不出所以然为什么ben的说法是正确的,关注下第二问的两个过程在不同eval-sequence下的表现,(p1 1)的结果没有改变都是(1 2),而(p2 1)在原始版本的eval-sequence中结果是1,而在Cy修改后的版本中(对中间步骤采用actual-value)结果是(1 2),也就是说在原始版本中的(set! x (cons x '(2)))的副作用根本没有实现,而在修改后的版本中实现了。俺觉的这个问题很迷惑,惰性求值与side effect相互作用很奇特,不过我更偏向原始版本,因为我觉的这样的实现更容易看清代码的意图,也就是说在透明性上更好,例如我分析p2过程就可以认为直接返回参数x;而实现副作用很容易让人掉入陷阱,并且很可能引进难以查找的bug。




posted @ 2008-11-02 01:18 dennis 阅读(1813) | 评论 (0)编辑 收藏


4.25,如果在scheme解释器的应用序求值下,unless定义为一个过程,那么
(* (factorial (- n 1))
将无穷递归下去。如果在正则序时,由于延时求值,仅当需要计算时才求值此表达式,不会造成无穷递归,在1的时候正常结束递归。

4.26,在上一节求值器的基础上定义unless的语法形式还是很简单的,
首先在analyze过程添加分析unless:
 ((unless? exp) (analyze (unless->if exp)))

然后定义unless?和unless->if

(define (unless? exp)
  (tagged
-list? exp 'unless))
(define (unless->if exp)
  (make
-if (cadr exp) (cadddr exp) (caddr exp)))

最后一问,构造一个unless与高阶函数联合使用的场景,在此场景下,unless不能定义成特殊形式,仅在定义成过程的情况下有效,我想像不出此场景。


posted @ 2008-10-31 23:12 dennis 阅读(443) | 评论 (0)编辑 收藏

    推荐一个项目:http://code.google.com/p/master-zhdoc/
    这个项目的目的是整理翻译一些大师的名篇。
    现在已经完成《Eric S. Raymond 五部曲》的翻译,包括《Hacker文化简史》、《大教堂和集市》、《如何成为一名Hacker》、《开拓智域》和《魔
法大锅炉》。有兴趣的可以在这里下载。


posted @ 2008-10-31 09:51 dennis 阅读(1362) | 评论 (0)编辑 收藏

update:俺确实够愚蠢了,竟然打包错了。半夜打包的,看来真有点头昏。非常抱歉,已经更正下载地址。
  
   swfheader是一个处理swf文件的工具脚本,可用于读取swf文件头信息、压缩和解压缩swf文件。很早以前发布过一个0.01版。最近复审了代码,发现了一个愚蠢的读二进制文件错误导致没办法正确的解压或者压缩swf文件。今天更正了此bug,重构了部分代码并做了更多测试,已经可以正常使用。

项目地址:
http://code.google.com/p/swf-util/
项目描述:
  一个轻量级的纯Ruby实现的swf文件处理脚本,可以读取swf文件头信息(大小、帧率、长宽、是否压缩、flash版本信息等)、压缩swf文件和解压缩swf文件。基于Apache License2协议发布。


示例
下载swfheader0.10.zip后,解压后有README文件和swfheader-0.10.gem,通过
gem install  swfheader-0.10.gem
命令安装swfheader即可使用。

1、读文件头信息:
require 'swfheader'
header
=SwfUtil::read_header("c:/test.swf"))
header.signature 
# 标志字符 CWS表示压缩的swf文件,FWS表示未压缩的
header.compression #compressed or uncompressed
header.size   #文件大小
header.nbits  #twips为单位的画面尺寸
header.xmax
header.ymax
header.width
header.height
header.version 
#flash版本
header.frame_date #帧率
header.frame_count #总帧数

header.inspect 
#信息描述字符串

header.inspect一个示例输出:
signature:   CWS
version:     
8
compression: compressed
size:        
5737111
nbits:       
14
xmax:        
7200
ymax:        
5760
width:       
360
height:      
288
frameRate:   
25
frameCount:  
10409


2、解压缩swf文件,如果源文件本身没有被压缩那么将抛出异常:
require 'swfheader'
SwfUtil::decompress_swf(
"c:/test.swf","c:/test_decompressed.swf")

3、压缩swf文件,如果源文件已经被压缩将抛出异常:
require 'swfheader'
SwfUtil::compress_swf(
"c:/test.swf","c:/test_compressed.swf")


posted @ 2008-10-11 23:38 dennis 阅读(1773) | 评论 (0)编辑 收藏

项目名称:Yanf4j(Yet another nio framework for java)
项目地址:http://code.google.com/p/yanf4j/,当前版本0.30-beta1
协议:Apache License, Version 2.0
简单描述:
    有这么多nio框架了,为什么要another?重复造轮子也罢,这框架脱胎于一个服务器项目的网络层代码,期间参考了cindy、grizzly等nio框架的实现,加上自己的一些心得体会实现的。特点是简单、小巧、超轻量级。项目没有多大野心,目标是高效、简单地实现非阻塞模式的Server(TCP、UDP)并且保证不错的性能要求,不提供客户端API 和阻塞模式。如果你的项目需要实现一个socket server并且不希望用太重量级的框架,yanf4j是个不错的选择。

    例子,在source archive中带有例子,这里描述下tcp和udp的echo server的实现。
 一、先看TCP的Echo Server
1、实现处理handler,继承HandlerAdapter类,实现相应的回调方法,这与其他nio框架没啥区别:
import com.google.code.yanf4j.nio.Dispatcher;
import com.google.code.yanf4j.nio.Session;
import com.google.code.yanf4j.nio.impl.HandlerAdapter;
import com.google.code.yanf4j.nio.util.DispatcherFactory;

public class EchoHandler extends HandlerAdapter<String> {

    Dispatcher dispatcher 
= DispatcherFactory.newDispatcher(4);

    @Override
    
public void onException(Session session, Throwable t) {
        t.printStackTrace();
    }

    @Override
    
public void onMessageSent(Session session, String t) {
        System.out.println("sent " + t + " to "
                    
+ session.getRemoteSocketAddress());
    }

    @Override
    
public void onSessionStarted(Session session) {
        System.out.println("session started");
        session.setUseBlockingRead(
true);
        session.setUseBlockingWrite(
false);
    }

    
public void onSessionCreated(Session session) {
        System.out.println(session.getRemoteSocketAddress().toString()
                    
+ " connected");
    }

    
public void onSessionClosed(Session session) {
        System.out.println(session.getRemoteSocketAddress().toString()
                    
+ " disconnected");

    }

    
public void onReceive(final Session session, final String msg) {
        System.out.println("recv:" + msg);
        
if (msg != null)
            dispatcher.dispatch(
new Runnable() {
                
public void run() {

                    
if (msg.equals("q"))
                        session.close();
                    session.send(msg);
                }
            });
    }

}


2、实现EchoServer,核心是TCPController类的使用:

        Configuration configuration = new Configuration();
        configuration.setStatisticsServer(
true);
        configuration.setTcpSessionReadBufferSize(
256 * 1024); // 设置读的缓冲区大小
        AbstractController controller = new TCPController(configuration,
                
new StringCodecFactory());
        controller.setPort(
8080); // 设置端口
        controller.setReadThreadCount(1); // 设置读线程数,通常为1
        controller.setReceiveBufferSize(16 * 1024); // 设置socket接收缓冲区大小
        controller.setReuseAddress(false); // 设置是否重用端口
        controller.setHandler(new EchoHandler()); // 设置handler
        controller.setHandleReadWriteConcurrently(true); // 设置是否允许读写并发处理
        controller.addStateListener(new ServerStateListener());
        controller.start();

Configuration 默认会在classpath查找yanf4j.properties属性文件,用于配置服务器属性,然而,你也看到,可以编码设置这些属性,具体参考wiki。

3、然后?没然后了,一个TCP的echo server已经搞定了,你可以telnet到8080端口试试了。

二、UDP的Echo server
1、handler,可以复用前面的EchoHandler
2、UDP的核心类是UDPController:

        Configuration configuration = new Configuration();
        configuration.setTcpPort(
8090);
        configuration.setTcpReuseAddress(
false);
        configuration.setStatisticsServer(
true);
        configuration.setTcpNoDelay(
true);
        configuration.setTcpReadThreadCount(
1);
        configuration.setTcpRecvBufferSize(
16 * 1024);
        UDPController controller 
= new UDPController(configuration);
        controller.setMaxDatagramPacketLength(
1024);
        controller.setHandler(
new EchoHandler());
        controller.start();

  更多细节,请参考项目主页上的wiki


posted @ 2008-10-11 14:25 dennis 阅读(2836) | 评论 (6)编辑 收藏

    Ruby的创造者为《代码之美》撰写的文章标题是《代码如散文》。程序和散文有一些共性,首先是两者都必须有清晰的意图,散文内容是什么,想表达什么,程序的功能是什么,能做什么;其次两者在意图的表达上(功能的实现上)都依赖于写作的具体风格,编程的隐喻之一就是写作。你想表达的思想是好的,但是如果表达得难以理解,那么要把这个思想传播给读者将非常困难。代码被读和修改的次数是相当多的,因此一个很重要的观点就是你写的代码是给人读的,你需要考虑可读性的问题,归结于写出漂亮的代码。
   判断代码是否漂亮似乎没有什么国家标准,更没有国家免检。代码是写给人读的,从这个角度上看,如果一段代码能让人很容易地读懂,让人感觉心情愉快,修改起来也不费什么力气,这似乎就是漂亮的代码咯。那么显然,漂亮的代码的真正含义是帮助程序员感到快乐和提高生产率。有了这个指导性的方向,你可以从这么几个方面去努力写出漂亮的代码:简洁性、保守性、简单性、灵活性和平衡。
   简洁性,文中以Ruby和Java版本的Hello World入手比较,在Ruby和其他动态语言中,你所做的就是你想表达的:打印Hello World
print "Hello World\n"
换成java,哦,你先要定义一个类,这个类有个入口main方法,在main方法中调用System.out对象的println方法打印:
class Sample{
   
public static void main(String []args){
     System.out.println(
"Hello World");
   }
}
我记的我初学java的时候就特别不理解为什么要定义一个类,为什么方法要static、args,而我仅仅想要的只是打印一个字符串,可语言硬塞给了我太多的概念:类、方法、入口、参数。这些额外的东西牵扯了太多的注意力,而往往却忘记了初衷是什么。因此在《unix编程艺术》一书中对OO的一个评价是:鼓励具有厚重的胶合和复杂层次的体系,大大降低了代码的简洁性和透明性,你无法一眼看出代码是想做什么的。OO的抽象能力很强大,因此在很多场景下是这种抽象能力的滥用,实现最简单的功能也是一定要有类,有类才有对象,有对象才有光:)而往往这些对象却非问题领域中的自然实体,而是某种胶合物,为了抽象而抽象。
   简洁同样意味着消除冗余。代码的重复是万恶之源,拷贝黏贴是滋生bug的温床,在重构概念如此深入人心的今天,这一点毋庸置疑。因此,谨记请DRY原则。语言级别的冗余可能是需要的,例如Ruby允许方法调用省略括号:
task :name=>:test
task({:name
=>:test})

这两行代码想表达的意思一样,显然第一种方式更简洁,这种语言级别的冗余显然是有利于程序员的,尽管将实现的难度推给了语言的设计和实现者。
   漂亮代码另一个有争议的方面就是它的熟悉性,人们对于新东西的接受程度远没有想象中的高,大家都喜欢自己熟悉的东西而非全新的思考方式(嗯,极客例外)。这其实是Ruby一直鼓吹的最小惊奇原则的另一种表达。Ruby看来就是这么个保守的语言,他有很强大的OO能力,但是没有全然照搬smalltalk,他有FP的能力但是却没有让你惊掉下巴,他仍然遵循着古老的顺序、循环、选择的程序结构。
   简单性强调是减轻程序员的工作负担,语言和类库API的优化应当有利于使用者,将困难留给实现者。前面提到的语言的冗余性就是一例。程序的复杂性来源有这么几个:商业上基于推销热点而非实际需求考虑出发带来的“特性清单”、业务领域本身的复杂度、程序员的自傲心理,最根本在于软件的开发的复杂性。如果能将复杂的功能,用人人理解的简单代码表达出来,当然漂亮!
   简单并不意味着简陋,保守也不意味着死板。灵活性同样是代码漂亮与否的判断标准,是否隔离了变化点,是否拥有一定的扩展能力,是否无需借助工具的增强而实现某些巧妙的调用。同样以Ruby为例,open class和元编程给了内置你在语言级别的“工具”,你无需借助antlr、cglib等等类库去做一些看似复杂的东西。你将感受到编程的快乐,而非为了工具而去做一些违背本意的事情。灵活性可能是把双刃剑,过分的强调灵活性、可扩展性也可能带来复杂的代码,注意你的“炫耀”心理。
   最后要强调的是平衡,在这些因素之间做出平衡,我觉的吧,没有更多实践的经验想平衡这些因素是相当困难的,如果了解了平衡的艺术,也许算是透出那么点“编程的艺术”的味道。Matz一直强调的一点是编程的乐趣,如果没有乐趣,我想我不会干这行,如果没有乐趣,我想我的工作效率将极度低下,从你认为是枯燥的工作中找乐子,存了这么个心理,你总能找出很多可以做的有趣事情,问题在于,你肯不肯做?

ps.加张图片,俺的blog国家免检

  

posted @ 2008-10-09 23:58 dennis 阅读(3060) | 评论 (4)编辑 收藏

 Ruby如何简洁地读整个文件,你可以这样做:
f=File.open("test.log","r")
result
=''
f.each_line do 
|line|
   result
+=line
end
puts result
但是,更简洁的方法是:
File.open("test.log","r"){ |f| f.collect.join}

利用了文件打开的IO对象混入了Enumerable模块这一特点,通过map或者collect将所有文件行放入一个数组,再join即可。

更正,其实更简介的方法是:
IO.read("test.log")
仅限于读文本文件。

这个tip的由来是我在读二进制文件的时候发现IO.read出来的大小与实际结果不符合,然后去尝试上文提到的这个方法,其实仍然是错误的。读二进制文件需要指定mode为b:
File.open("test.swf","rb")

仅作更正。

posted @ 2008-10-07 09:38 dennis 阅读(1299) | 评论 (3)编辑 收藏

    今天邮箱里收到的一封邮件,标题是《寻找好心人帮忙,不介意保养我》,人名就不列出来了,石化中。
你好,我叫XX,今年20岁,是XX的一名在校大学生,因为家里贫穷,妈妈又得了重病,家里再也没钱供我读书了,想寻找好心的人资助我读大学,(附件有我的照片)

如能供我读大学并出钱为妈妈治病,要我做任何事都可以,能包养我是最好的!

希望好心人尽快与我联系,资助多少都感谢你,我会尽量报答好心人的。

XX本地的可以约我见面详谈,

外地的能来XX最好,不能来的也可以网上视频

电话 XXXXX    X小姐(XX)

XXXXXXXXXX 可短信或电话联系  24小时为你等候

邮箱:XXXXXXXX

 

只要您一个电话,我的心就会来到您的身边,和您面对面的交流,心与心的沟通,
用我纯真率直与成熟交织的性格和丰富的知识底蕴为您服务

    我的gmail邮箱里每日的垃圾邮件成堆,不过gmail的过滤系统做的好,绝大部分垃圾邮件都直接进了垃圾箱,偶尔一两封漏网之鱼需要手工处理下。这封邮件俺不发表评论,俺只是要郑重声明:本人有老婆了,公布邮件地址仅为技术交流,并且穷人一个,老婆都快养不起了,何况N奶乎?

posted @ 2008-10-04 14:02 dennis 阅读(729) | 评论 (6)编辑 收藏

仅列出标题
共56页: First 上一页 21 22 23 24 25 26 27 28 29 下一页 Last