解析 instiki 学习 Ruby

很久以前写的,没地方保存,不如扔到这里来,至少不枉费那么多字的组合。或许那天真的开始学 Ruby 的时候还能找到点熟悉的东西,呵呵。

Ruby 学习
解析 instiki 学习 Ruby

缘由
我是一个习惯用 Perl 写程序的人,最近的工作大多是基于 web 的应用。为了提高自己的效率,我构建了一个自己的应用框架。当时借鉴了 OpenInteract。后来又看到了 Maypole,一个极富技巧性的 web 应用框架。它起初的版本还不够完善,并没有实现严格意义上的 MVC 结构,在 Maypole 开发项目的 IRC 上我看到有人提到了 RubyOnRails 这个 Ruby 上的 MVC 框架。当时我粗看了一下,代码非常简洁。你知道我是个很懒的人,所以越是简单的东西对我的吸引力也越大。当初学习 Perl 也是因为它的简单。于是我第一次萌生学习 Ruby 的念头。

而最近配置 wiki.perlchina.org 的时候又机缘巧合的使用了 instiki ,这是个基于 RubyOnRails 的 wiki 程序。instiki 用起来非常爽,只要你的系统装好 ruby-1.8.1 以上版本,然后直接运行 ruby instiki.rb 就可以启动了。它不需要你安装数据库或者 web 服务器。

instiki 默认有三种标签语言,不过我想要一个 PerlPod 的标签库。开始的时候我想自己 hack 已有的代码,希望可以变通过来。与此同时,发送 Feature Request 到官方站点,结果开发人员非常爽快地说“自己写吧,接口非常简单的!”。哈,是很简单的,可是我不懂 Ruby 只晓得 Perl 怎么办?

不懂就学喽,况且看上去那套 MVC 似乎不错,要是自己用它也构建出可以直接运行的应用,那该多 cool 啊!至少不需要在客户的机器上配置那么多一整套的东西了。

准备工作
ok ,我们只需要三样东西,第一,Ruby 语言解释器,最新的版本在这里:

第二,instiki 程序,当前最新版本为 0.9.2 。

第三,一杯热茶。天冷了,需要暖暖手。

先让 instiki 跑起来
第一步,安装 Ruby 。在 Unix 上:

$ tar zxvf ruby-1.8.2.tar.gz
$ cd ruby-1.8.2
$ ./configure
$ make
$ make install

如果在 Windows 机器上,我上面给出的下载连接是单个 exe 文件,可以直接安装的,我就不罗嗦了。

第二步,解压缩 instiki 到运行目录。比如打算在 /www/wiki 下面运行的,那就

$ cd /www tar zxvf instiki-0.9.2.tgz mv instiki-0.9.2 wiki cd wiki

第三步,运行 instiki,就像文章开头说的:

$ ruby instiki.rb

然后屏幕上大约会显示:

[2005-01-18 23:47:01] INFO  WEBrick 1.3.1 [2005-01-18 23:47:01] INFO  ruby 1.8.2 (2004-12-25) [i386-mswin32] [2005-01-18 23:47:01] INFO  Your WEBrick server is now running on  http://localhost:2500 [2005-01-18 23:47:01] INFO  WEBrick::HTTPServer#start: pid=3148 port=2500

这说明服务都起来了。默认情况下,instiki 在 2500 端口上提供 http 服务,所以如果你在本地机器上安装运行的话,打开浏览器,输入:

http://localhost:2500/

好了,你应该看到它的界面了。当然我们也可以改用 80 端口,只要在启动的时候给出相关参数即可:

$ ruby instiki.rb --port=80

通常你的服务器已经在 80 端口提供其他的站点服务了,怎么办呢?Apache 的 mod_proxy 或者 mod_rewrite 都可以解决这个问题。这里不啰嗦了,下文为了简单,都改用 80 端口的访问地址。

第一次运行看到的界面,提示你输入 wiki 站点的名称(我输入的是 wiki.chunzi.org),站点的名称会在以后的页面中显示。然后是这个站点的 uri 名字空间,一般取用简短的即可(比如 main),这样以后这个站点内的所有资源的 URL 都是以“http://localhost/main/”开头的。以后你还可以设定其他的 wiki 站点,比如“ruby”,那么新的 wiki 站点的所有 URL 都以“http://localhost/ruby/”开头。

接下来设定 wiki 的管理密码。以后每次管理变更 wiki 站点配置信息,提交的时候都需要输入这个密码。提交后转到 HomePage 的编辑页面。HomePage 称为 WikiWord 。在 wiki 的世界里,每个页面都有一个唯一的 id ,这个 id 就是 WikiWord 。那么要访问某个 wiki 页面,URL 中只要包含指定的 WikiWord 即可。所以如果显示首页,也就是 WikiWord 为 HomePage 的页面,它的 URL 看起来就像是 “http://localhost/main/show/HomePage”。很简单,main 是我们设定的 uri 前缀,show 是告诉 wiki 要执行的动作,HomePage 就是要显示的页面了。

接着说,在编辑 HomePage 的文本输入框内随便写点东西,然后在最下面填上自己的名字“chunzi”,再点“Create”,这时候你会看到首页面,内容就是刚才编辑的。如果不满意,点页面左下方的 Edit 连接,再回到刚才的编辑页面。更新的话,点“Update”按钮,取消点右下方的 “Cancel”连接。

上面罗嗦了很多。基本上是 instiki wiki 的简单使用方法。其他的不啰嗦了,自己看看就明白的。我们关心的是 instiki 是如何用 Ruby 实现的,然后通过它的源代码来解析和学习。

看看幕后的文件组织结构
回到刚才的目录,我们看到 instiki 应用下面有一个主程序文件:instiki.rb ,一个说明文件 README ,另外还有三个目录:

  • app
  • libraries
  • storage

从字面意思来看,很简单,app 放的应该是 wiki 应用程序文件,libraries 放的是 ruby 的库文件,storage 就该是数据存储的地方了。

先看 storage ,它里面还有个目录,名称为 2500 ,和端口的名称一样?没错,什么端口上起来的,数据就保存在什么端口的名称的目录里面。在里面就是一个文件名很长的文件了,先不管它是什么格式的,怎么记录保存数据的。回头再看。

接下来看看 libraries 目录,hoho,里面很多 .rb 的文件,还有个 zip 文件夹和 diff 文件夹。我们知道,instiki 可以比对每次的页面更新情况,并能通过背景色和符号提示每次更新的变化之处。这个功能我们很熟悉,就是 diff ,比较内容差异用的。这里的 diff 目录也就是存放 diff 算法的通用模块的吧。这个和 Perl 里面差不多,不过 Perl 的模块都是 .pm 结尾的,而我们在这里看到的是 .rb 结尾的。那么 zip 目录就该是 zip 压缩算法的模块了。我们还看到了 web_controller_server.rb 文件,打开看看,第一二行为:

require 'webrick' include WEBrick

是不是有点眼熟?WEBrick 好像在哪儿见过?不错,启动 instiki 的时候,我们看到过的:

[2005-01-18 23:47:01] INFO  WEBrick 1.3.1 [2005-01-18 23:47:01] INFO  WEBrick::HTTPServer#start: pid=3148

instiki 没有要求你用 Apache 服务器,就是因为这里用了称之为 “WEBrick”的 web 服务器模块。而且还是带 controller 的,什么是 controller ?MVC 框架中的 C 就是这里的 Controller。呵呵。有点意思。

现在不再深入模块部分了,我们广度优先,且慢深度优先。再看 app 目录,yeah,看到什么了?三个目录,非常整齐划一:

  • controllers
  • models
  • views

这不就是 MVC 三大块东西么。controllers 里面只有一个 wiki.rb 文件。models 里面多了,什么 page.rb(管页面的);什么 revision.rb(管版本修订的);什么 wiki_words.rb(管理 Wiki Word 的)。views 里面也好多文件,不过不是 .rb 的了,改为 .rhtml ,模版文件?打开一个 top.rhtml 看看,哈,没错,就是模版文件,程序代码都用

<!--..-->

括起来的。

基本上 instiki 的文件组织结构就是如此了,它有存储数据的地方,它有通用的模块可以调用,它有符合 MVC 的三块东西组成:wiki 站点的控制器,若干业务处理模块,以及一堆模版文件。

顺藤摸瓜
instiki 非常简单,只需要运行 instiki.rb 文件就可以了,所以如果要分析它是如何运作的,就必须先来看看 instiki.rb 文件。好的,打开它,总共才 67 行,非常简短。先来看第一行,

#!/usr/local/bin/ruby

Unix 下面每一种 shell 下面运行的解释语言一般都要在第一行
写上这么一句,用来告诉 shell 用什么解释器来解释运行本文件的代码。Perl 也是如此,简单。

接着看:

if RUBY_VERSION < "1.8.1"
    puts "Instiki requires Ruby 1.8.1+"
    exit
end

就着字面意思一读,很明白了,如果 Ruby 的版本小于 1.8.1 那么输出一句提示,然后退出。这里我们看到这样一些东西:

  • if 语句块。和 Perl 不同,Ruby 不用小括号,也不用大括号,结束的地方用保留字 end 说明。
  • 表达式。RUBY_VERSION 应该是 Ruby 中的变量了,不过它没有 $ 开头,而且之前也没有申明过,说明应该是默认的变量,它和后面的 “1.8.1” 这个字符串比较大小,说明这个默认变量如其名,保存着当前 Ruby 解释器的版本号。
  • puts 方法。这个和 C++ 中的一样,该是往 STDOUT 输出数据用的,这里输出的是后面双引号圈起来的部分。
  • exit 方法。我想这个和 Perl 一样的,直接退出程序运行了。
  • 字符串。不用多说,上面的一看就知道。
  • 语句的结束不需要分号。这是优点还是缺点呢?缺点是语句分割不明确,优点是显而易见的:懒人不用多敲一个键了。

目前好像我们能知道的就这么多,最多加上字符串的数字的比较。这个什么语言都一样的。

继续看下面的代码:

require 'optparse' require 'fileutils'

Perl 里面也有 require ,用来包含外部的一个 perl 代码文件的;Perl 里面还有一个 use ,它和 require 不同,它是在运行前先载入一个模块文件,并作语法检查和编译操作,然后尝试运行其中的 import() 方法。这里 Ruby 的 require 到底对应到哪一种我们还不清楚,不过至少它是要表明载入一个外部文件用的。第一个被载入的是称为 optparse,这个和 Perl 里面的 GetOpt 模块有些类似,应该是用来对传入的参数作解析的,option parse 么,简单。第二个是 fileutils ,字面来说,文件处理中需要杂七杂八的函数功能都在里面了。那么在后面的代码中,我们应该能看到这两个模块(姑且先这么称呼)中的一些相关的方法调用的。

来,喝口茶。接着看:

cdir = File.expand_path(File.dirname(__FILE__)) %w( /libraries/ /app/models /app/controllers ).each { |dir| $:.unshift(cdir + dir) } %w( web_controller_server action_controller_servlet wiki_service wiki ).each { |lib| require lib }

这里有点意思了。一共三句话(三句语句)。第一个,我们注意到最后面的 FILE ,写法上和 Perl 一模一样,猜想应该就是当前程序代码文件的文件名(包含路径)了。(当然 Perl 里面还可以用 $0 来表示。)这里我们也看到了小括号,那么自然的按照通常的优先级,我们从里面往外看这句句子。刚才讲了 FILE ,围在外面的是

File.dirname(__FILE__)

我们看到了首字母大写的 File ,然后是个小数点,然后是个 dirname。直觉告诉我,小数点是 Ruby 中类调用类方法的运算符,虽然 Perl 里面用的是 → 不过好像 Perl6 也将要用点来做同样的事情。File 应该是类名,很可能这个类就来自刚才看到的 fileutiles 文件,接着 dirname 就是取目录名称的方法。ok,连起来看一遍,使用 File 类的 dirname 来解析当前文件名所对应的目录名称,也就是路径。

cdir = File.expand_path(...)

还是 File 类,这次是 expand_path 方法,故名思议,展开路径信息,并赋值给 cdir 这个变量。我们注意到:

  • 赋值操作和 Perl 没什么不同
  • 变量不需要申明,直接用就可以,也没有类型的讲法,该是什么就是什么,直接用就可以,连 $ 都省掉了,符合懒人的习惯,我喜欢。

第二句有点奥妙了。按照自然语言的解读特点,先把这句分段,一前一后一共两段,前段大致上是 %w( … ).each ;后段则是大括号括起来的部分,这部分又分为两段,前段 |dir| ,后段做了个什么操作。大体上给人的感觉就是要依次取出若干样东西,然后作 unshift 操作。第三句和这句结构上有点像。不同的是后面的操作不太一样。我们知道,Ruby 里面什么东西都是对象,所以 .each 的写法表示点之前的部分就是一个什么类。%w( … ) 的结构好比是 Perl 中的 qw( … ) 结构,该是把其中的单词作为元素放到一个数组中,不过这种写法允许你不用逗号和引号,这点上再次印证了 Ruby 和 Perl 都是为懒人创造的语言这一常识。each 应该是对数组对象的操作,依次取出其中的元素。取出来做什么呢,做后面的操作。第三句中,我们看到的后半段:

{ |lib| require lib }

熟悉的 require 指令又来了,这次他不是具体的外部文件的名称,而是 lib 。lib 是什么?看到前面的 |lib| 写法吗?应该就是它吧?联想到了什么?$_ ? 呵呵,两个竖线表示其中的变量为内参,接受传递进来的数据,以便代码块中应用。说到代码块,看来 Ruby 也不是像 Python 那样完全抛弃花括号的。读到这里,我有点不快,Perl 里面类似的写法: { require } 就可以了,简洁掉好几倍。Ruby 有时候也挺啰嗦的,就像我一样。概括起来,它要依次载入名为 web_controller_server、action_controller_servlet、 wiki_service、wiki 四个外部模块。

有了对第三句的理解,再回过来看第二句德后半段:

{ |dir| $:.unshift(cdir + dir) }

这里我们很容易就可以理解 |dir| 和 dir 的意义了,前半段列出了三个 dir ,现在依次传入,然后,cdir + dir ,cdir 在前面已经讲过了,是当前运行的 ruby 程序所在的路径,加上传入的 dir ,变为新的目录。这里我们看到:

  • + 可以用于字符串的连接操作

$:.unshift 看起来很怪,按照上面的经验分析一下,它要执行 unshift 方法,Perl 里面也有 unshift ,目的是把一个元素从数组的头部(也就是左边或者上边)压入(好比子弹上膛),那么推论点号之前的 $: 应该是个数组。第二句就是要把各个分目录压到一个数组里面去。我们纵览一下后面的代码,好像没有再次用到数组变量 $: 的地方,而压入的三个目录都是些 lib 目录,这次你又联想到了什么?@INC ? hoho,好像这样的联想非常合理哦,Ruby 的作者以前是不是 Perl 程序员阿?这里我们推测:

  • $: 是系统默认的特殊变量,雷同 @INC ,以便代码通过它来搜索定位要调用的外部模块。Ruby 中还是用到了 $ 符号的,也用了一个其他非字母符号跟在后面,意图表达一个特殊的变量。推想:
  • 是不是 Ruby 中的数组用 $ 开头来表示呢?

继续往下看,很简单的赋值语句:

fork_available = true

这里有些像 Java ,推想:

  • Ruby 里面的布尔值通过关键字 true 和 false 来表示。

后面代码中马上出现了 false 关键字,初步证实了上面的推想。

begin
   exit unless fork rescue NotImplementedError
   fork_available = false
end

开始有些复杂了。这里我们看到了一个 begin … rescue … end 结构。fork 需要介绍吗?fork 就是要复制当前进程,于是 fork 后就有两个相同的进程在内存里面运行。记得我们启动 instiki 的时候是什么样的吗?如果你是个细心的人,并同时试验过 Unix 和 Windows 环境,那你可以说,它们是不一样的。我们知道,Windows 下面不支持 fork(至少在 Perl 里面是这样,这里也应当如此),所以 Windows 下面运行后,Command 窗口中 ruby 程序没有结束,光标在闪,有请求到来的时候会显示若干信息,如果关掉这个窗口,wiki 的 http 服务也就停掉了。而 Unix 下面,fork 天生的环境里,你运行完 ruby instiki.rb 它输出几行信息就又回到了 shell 提示符状态。这时候你 ps 一下就会看到有个 ruby 进程在那边跑。不用多说了,这里的 fork 就是这回事情。那么好,

exit unless fork

我们知道,通常 fork 函数在完成复制一个相同进程后,返回一个进程 id 。在原来的进程,也就是父进程里面,fork 返回 0 ;而在新复制出来的进程,也就是子进程里面,fork 返回子进程的进程 id (也就是 pid,一个操作系统内不重复的数字编号)。exit unless fork 的意思就是父进程退出,子进程继续。这和在 Unix 下面看到的实际运行情况一致。

可是在 Windows 平台是不支持 fork ,那它又是如何继续执行的呢?后面一句:

rescue NotImplementedError

又让你联想到了什么?不好意思,我是用 UltraEdit 打开的 .rb 文件,同时我也下载了 Ruby 语言的语法高亮显示定义文件并加载到 UltraEdit 的 wordfile 中,所以我看到的这句话,resuce 是蓝色的,NotImplementedError 是红色的。

说到这里,我补充一下,根据颜色,其实可以判断出很多东西的。比如上面提到的变量 RUBY_VERSION 和 “Instiki requires Ruby 1.8.1+” 字符串都显示绿色,说明 RUBY_VERSION 是特殊变量,类似 Perl 中的标量类型。我看到 if begin end rescue unless 什么的都是蓝色,所以这些都是 Ruby 语言的保留字。puts exit require each unshift 都是棕色,说明它们都是系统内置的方法。

回过来看,NotImplementedError 显示红色,应该是 Ruby 语言内置的错误类型的表示。字面意思是:拯救 – 不可操作错误。还是之前的问题,联想到了什么?

eval { ... }; die $@ if $@;

是这个么?或者 Java 里面的:

try { ... } catch { ... }

rescue 是不是用来捕获一些异常或者错误的呢?如果 fork 不能执行(Windows 上就是如此),那就捕获这种名为 NotImplementedError 的错误,并为了拯救或者挽回,执行 rescue 到 end 之间的代码。这段代码没什么花头,一个赋值语句,标注了 fork 不可用的状态。

接着看:

begin
   pdflatex_available = system "pdflatex -version"  rescue Errno::ENOENT
   pdflatex_available = false
end

刚才见过的结构又来了,这次看起来容易得多。system 应该和 Perl 的一样,将后面的字符串作为 shell 命令来执行,并返回执行结果。很明显,程序想知道 pdflatex 执行文件的版本。这里有个疑问,system 返回的是版本号呢还是进程退出码?做个实验吧,到此为止我们都是靠猜想和推论,还没有实际动过手,毕竟这不是严谨的治学态度。在我的 Windows 上的 Command 窗口执行:

$ ruby -e "puts system 'ls'"

呵呵,我猜想和 Perl 一样的 -e 用法居然也是可以用的。同时也可以用单引号定义字符串。结果输出:

-e:1: warning: parenthesize argument(s) for future version false

Windows 上面当然没有 ls 命令,所以有个 warning,然后输出了 false 字符串。所以结论有了,system 返回的是布尔值。为了验证这个推想,把上面的 ls 改为 dir ,再运行,目录清单列出来了,最后还附加了一个 true 。实验成功!看来老毛说的不错,理论和实践相结合,呵呵。

回过头来再看,instiki 要知道是否 pdflatex 可用。那如果捕获 Errno::ENOENT 错误呢,就改变相应的变量值为 false 。那么 Errno::ENOENT 又是什么呢?Perl 里面也是有的,Perl 有个 Errno 模块,它引用了 POSIX 中的 ERRNO 相关的错误常量,ENOENT 是其中之一。那么 ENOENT 表示什么意思呢?既然是 POSIX 里面来的,也就是说这是符合 POSIX 规范的操作系统上底层的相关错误状态定义。你以前写程序,打开一个文件的时候,是不是要检查一下文件是否存在?如果不存在,代码又不能继续的话,通常都会输出一段错误信息,这时候 $! 包含的内容就是 “No Such File or directory”,不过这是段表述错误类型的字符串,在文件系统底层,它的代号就是 ENOENT 。呵呵,说得有点远了,不过我想提一下还是有必要的。老实说,我也就知道这一个错误代号,你问我别的,我就要去问 Google 了。

这里我们看到了双冒号的写法。于是我又猜想:

  • Ruby 使用 :: 表示或者引用类中的相关事物(变量,常量等)

继续,不要停:

OPTIONS = {
   :server_type => fork_available ? Daemon : SimpleServer,
   :port        => 2500,
   :storage     => "#{File.expand_path(FileUtils.pwd)}/storage",
   :pdflatex    => pdflatex_available 
}

哈希变量赋值?权当这么理解吧。关键字用冒号开头,然后用 => 连接键值对。这里我们又看到了一些眼熟的东西:

  • 条件 ? 为真运行这里的表达式 : 为假运行这里的表达式 这种结构的简单条件判断语句。
  • #{…} 的写法,类似 Perl 的 ${ … } 的写法,那句话的意思就是,通过 FileUtils 类的 pwd 方法取得当前路径,并通过 File 类的 expand_path 方法展开路径,然后通过 #{…} 运算将结果反引用为字符串,并在双引号中引用该值,与 /storage 合起来成为新的路径信息,用于确定存储信息的目录。

Revised on January 19, 2005 02:44 by chunzi

Read More

Leave a Reply

GitHub 中文版

应 Scott 之邀,负责翻译 GitHub 站点为中文版。700+ 词条,没有上下文,靠推猜去尝试翻译,所以一定会有地方看起来古怪或者不对,如果各位发现了,烦请及时告诉我,我去修正。当然,如果有更好的译法也请告诉我。期间 Henry 帮助 review 和修订了几条,谢谢 Henry。GitHub 目前提供可翻译的词条只是常见的大部分,所以看到有整句英文的不用奇怪。以后应该会陆续开放新的词条供译者翻译。

从我个人的角度来讲,中文版没什么太大意义。一般写代码用到 GitHub 的人,英文一定也没问题。但对于 GitHub 站点本身来讲,这次的全球语言本地化则是另一种意义,表明的是一种态度,一种亲和力。

救人一命(已实施血浆置换)

更新:昨天下午,病人已经开始血浆置换手术。情况稍有好转,但仍然非常虚弱。谢谢各位。

更新:目前病人几度昏迷,连转院都属危险。置换疗法可到苏州,南通做,但目前无法转移,而且昏迷的话是否必要也成问题。另外谢谢热心的许先生提供的信息。希望会有奇迹。谢谢所有转发消息的善良的人们。

前些天我老婆的朋友(我们都叫她茶叶姐姐)突然晕倒,当时初步检查说是血液病。经过这几天细致检查,虽然还未最终定论,但基本确定是“血栓性血小板减少性紫癜(TTP, Thrombotic Thrombocytopenia Purpura)”。这种病极为罕见,疗法目前叫停。我不是很懂,但至少,有机会救人一命,就应该抓住机会,不能错失。我希望所有认识我的朋友,都能帮助广泛传播这条消息,尽可能找到相关专业人士,以及有效疗法,最终目的只有一个,救人一命。我和茶叶姐姐有过几面之交,我担保此信息真实。任何需要联系我的人,可以直接发邮件到 chunzi@gmail.com 或者直接打我手机 18602198918,我会负责转告当事人。

茶叶姐姐的老公在天涯发文求助,以下全文转载。另外在开心网也有转贴。对于政府叫停疗法,我觉得我们的对策不是和政府拉锯,而是撇开所有繁文缛节,快速直接找到切实有效的治疗办法,救人一命的办法。谢谢大家。

天涯上的原始帖子:http://www.tianya.cn/publicforum/content/help/1/278626.shtml

我和我老婆已经结婚三年了,虽然各方面物质条件一般,但是一直生活的开心快乐,直到大概十天前。

7月2号我老婆突然觉得身体不适,身 上发出针尖大小的出血点,而且有按着不疼的乌青块,身体很疲惫,没有力气。我们感觉不对,马上到瑞金医院看病。看了瑞金医院的血液内科,在这一周做了很多 项检查之后,我们通过对医生的询问越来越感到事情的严重性,大部分医生初诊的结果都指向了一种叫TTP的病症,这是一个原来从未听说过非常少见也非常危险 的病症,每年约1∶100万,直到这周一做好骨髓穿刺,虽然骨髓穿刺的结果还没有完全出来,但基本排除了白血病的可能,越来越多的指向,指向了 TTP(TTP(thrombotic thrombocytopenia purpura) 血栓性血小板减少性紫癜 是一种急性有潜在致死性的疾病,其特点为:(1)严重血小板减少,(2)血涂片中见碎裂的红细胞(头盔状细胞,三角形红细胞,形状扭曲的红细胞)伴溶血的 证据(Hb水平降低,幼红细胞增多,网织细胞数增高,血清乳酸脱氢酶水平增高),(3)急性肾功能衰竭,(4)发热,(5)多脏器有表现不一的局部缺血性 损伤.临床表现包括中枢神经系统症状(神志模糊和昏迷);)这个消息对我和家人简直就是晴天霹雳。

在和医生和众多朋友询问过之后,知道TTP 首选的治疗方法为“血浆置换”疗法。1976年开始采用本法治疗TTP后疗效迅速提高,可达67%~84%,使TTP预后大为改观。认为它能去除体内促血 小板聚集物、补充正常抗聚集物,应及早进行。一般用量为每天40~80ml/kg的新鲜冷冻血浆,至少5~7天。治疗有效(一般在1~2周内) 则血清LDH浓度下降,血小板增高 神经系统的症状恢复。通常在血清LDH浓度下降至400U/L时,即可停止血浆置换。血浆置换疗法中不宜用冷沉淀物,以免大量ⅤW因子触发血管内血小板聚 集,输注血小板应列为禁忌。但是在和医生沟通之后让我几乎绝望,医生说就在前段时间,医院的上级部门以要重新审核“血浆置换”疗法的价格体系合理定价了为 由,全面停止了上海医院“血浆置换”疗法的操作,这无意于把我们逼到了绝路,我想政府部门重新审核肯定有种种理由,但是我想政府部门制定这种决定,也应该 多为病人着想,想的更加周全一点,尤其是对这种危险而又罕见的病例是不是在这段重新审查的阶段有什么变通的办法。可以重起“血浆置换”疗法救救我老婆的 命。
我也是实在没有办法了,只好希望通过众多的好朋友,众多的有同情心的网友帮我一起呼吁一下,希望可以可以重起“血浆置换”疗法救救我老婆 的命。万分的感谢大家!!!!

Google Ads

《我的奋斗》

早年还在枫林路混的时候,就花过小半天时间听老罗语录,一个人望着窗外痴笑不停;后来也看过他们新东方的人四处演讲的视频,以及老罗自己的一次演讲。所以看这本《我的奋斗》完全属于复习心态。这次没有花钱买,直接网上找 epub 的到 iphone 上看。看完了觉得还行,主要讲他小时候的想法和遭遇。谈不上奋斗。不过老罗本身的成功就是很好的奋斗昭示。因为最可贵的不是他的粗旷和愤青,而是他的细腻和坚持。坚持原则和坚持目标。

epub 看书还是有很多问题的。排版上肯定无法重现纸本。最要命的是内容质量无法保证。缺个章少个段的,都没法确认。我后来去书城翻了下,两个版本的 epub 都不完整。但要是看过 epub 电子书,谁还有心思再去翻一遍原版图书呢。像《我的奋斗》这种随便翻翻的闲书没什么问题。要是村上春树的《1Q84》我就无法接受。内容固然重要,形式也不可或缺。所以我买了两本,前两天在家翻地津津有味。所以我觉得,电子书并非要取代纸书,也无法取代。读这两种书的群体根本就是两个群体,互为补充罢了。特别在中国,更有一大群人整天拿着山寨手机看  txt 垃圾小说,还乐此不彼。

Zuill Bailey

NPR: Tiny Desk Concerts Podcast 6 月 6 日那期的 Zuill Bailey: Tiny Desk Concert 看得我莫名兴奋。看之前并不知道 Zuill Bailey 和那把大提琴的背景,只是被厚重而富有层次的乐音所震撼。Zuill Bailey 平实风趣的演说,极其投入卖力的演奏,加上 Bose 耳机的忠实回现,几乎可以感受到现场每丝每毫的空气震颤,听得我气血倒流。然后我才了解到他是中生代重量级大提琴演奏家,那把琴也是古董琴,所以音色特别浑厚凝重,甚至让人觉得它有气息有灵魂。之前我从未仔细聆听过大提琴演奏,以及 Bach 的乐章,这一次却让我犹如新生。好像那些暴风骤雨般的音色能透出来无限种颜色和感情来,又好像穿梭在无垠空彻的山川河谷之间。百听不厌,又每每感受不同。反正我是听了不下几十遍。

iOS 4.0

第一时间升级到了 iOS 4.0。感觉上确实要比原来要快些。所有打开过的应用都出现在任务栏里,让我有点不适应,很有强迫症要去关掉。删除应用时也不需要 vote 了,爽快很多。iBooks 在 iPhone 上显得小巧精致,就像捧着真的小书在看一样,很有好感。中文字体也比 iPad 上好很多,而且都是左对齐,不像 iPad 上只能两边靠齐,中间兀自多出来的空白丑死。不过发现 iPhone 上的 iBooks 查字典,会报告“Not available for this language.” 我用的可是全英文。Photos 里面看图片多了按地理分组,很直观很酷。本来超出屏幕的应用必须重启才会再显示到空白区域,现在会自动出来。原来双击 home 我设置的启动 camera 现在默认呼叫多任务,但我找不到重新设置的地方,倒是发现多了个 triple home 设置 VoiceOver/Zoom/Large Text/White on Black。

日志

无法回到过去,因而有志。志和博客不同,一个是历史记录,一个是个人出版。志和 twitter 相近,但如今 twitter 多为社交,包含但不限于志。自己的志,或琐碎,或隐私,没必要也不该公布。曾记过一纸本日志,猎猎回翻,仿佛穿梭时空观望过去的自己。很有意思。纸上涂画很有快意,但终归有所不便,无法想到就记,不免疏漏,也无索引。

现在,我决定按照这样的方式继续。mac 上用 tweeite 写志到另外的 twitter 帐号。因为 tweetie 实在是太方便了,cmd+i 调出窗口写,完了 cmd+enter 发布。完全不用鼠标。没有 mac 就用 iphone,官方的 twitter for iphone 最顺手,设好 api 无需翻墙,直接发推。数据都在云端,剩下的无非重构显示形式,这个不着急。

这个 timeline 才是最干净,最符合其意义的 timeline。所谓日志。

空手哲学

年岁越是上去,越是觉得身边的附属品太多太杂。每每在家整理东整理西的时候,都因为“舍不得”,“或许将来还有用”,“这可是一段回忆啊”等等,重新放回箱子。可是,真的需要么?未必。

看过《Up in the Air》的一定对 George Clooney 在演讲台上的一番话记忆犹新,那是关于 backpack 的一段说辞。看过《Fight Club》的一定对火烧 IKEA 家居变得一无所有而感到兴奋,却始终没有那样的勇气和非理智。人们总是倾向于拥有,不愿舍弃。在原始社会,这是值得嘉奖的,因为那时候物资匮乏。而我们生活的时代,物资充裕,拥有的多过所需的。不愿舍弃拥有的,这种进化而来的本能,使得生活在当今的我们,变得愈发烦躁和浮夸。同人于野有篇文章《坏比好重要》解释了为什么人们害怕损失(不愿舍弃)。

舍弃,开始变为一种哲学,一种生活态度。gugod 在以前的一篇“减法上等”的文章中说:

我也很愛這句安東·德·聖艾修伯(《小王子》的作者)所說過的話:

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.

私譯為:

完美,並非能再加入些什麼,而是無法再減去些什麼。

为求完美,必先舍弃。《Rework》中也提到“Say no by default”,在大家热衷于堆砌各种功能的时候,dhh 清醒并明白舍弃的积极意义。Apple  的产品也到处体现着舍弃哲学。

人们不愿尝试做些改变,多半只是因为没有尝到改变以后的甜头。虽然道理上明白,但未实践,就无从体会,也就没有动力改变。舍弃之后,带来的利弊究竟各有多少?何不亲身实践一下,然后理智分析。

就像 Gmail 里的邮件,删除还是存档?电脑里的文件,commit 还是 delete?purge-me。抽屉里的杂物,数月没用过的有几样?如果在可预见的未来并不需要,那就直接舍弃。如果是孤本,做好索引;如果是副本,需要时再去找好了。绝大多数我们看似用得着的东西,实际上几乎没有再用到的可能。

空手哲学,是一种境界。如同两袖清风,一身淡泊的出家修行者,虽然两手空空,但内心殷实。作为第一实践,我刚刚删除了无数 Google Reader 里的订阅(终于有了 unsubscribe from all 的功能,等了多少年了。)当然,除了实在的东西需要舍弃,还有许多情感也需要舍弃。此谓之放得下。

Getting thing done

公司每两周要开一次例会,小头目的例会。实际上也没多少事情,但为了告诉大老板“你看,我们一直在努力前进呢!”这样的信息,所以形式上还是要的。光是 GM 一个人唱戏,没那么多剧本。所以轮流下来大家讲,讲什么都可以,关于工作的关于管理的都行。这个礼拜挨到我,东西是早准备好了的,但会议意外取消,也没什么通知,估计要顺延。要讲的东西是 Getting things done, 第一次使 keynote,用得还比较浅白。早就上传到了 slideshare,这里顺便也放下:

WordPress Tweeter

新发 blog 用 FriendFeed 订阅再推送到 Twitter 有两个缺点:时延和墙。既然我的主机在墙外,为什么不直接用插件发呢?试试看 WordPress Tweeter,走 Twitter API,很好很强大。此文顺做测试。

流阅读

怎样阅读一堆内容最有效?看看现今的报纸杂志好了。字体大小,图片位置,颜色深浅,无不影响着阅读体验。并且更为重要的是,它们实际上是在引导阅读。

iPad 上就有个叫做 Early Edition 的应用,我很喜欢,本质上它是个 RSS 阅读软件,和 Google Reader 一样。但不同的是它按报纸风格排版:大标题,分纵览,有大块文字和图片,也有小块摘要消息。就单单是这么简单的创意,却足以令其鹤立鸡群。

昨天 Safari 5  发布的 reader 功能与此类似,用最简洁朴素的方法将内容呈现出来,效果非同一般。这也是为什么在 iBooks 上看书很赞,感觉很棒,但在 Kindle for mac/iphone 上看起来味同嚼蜡一般。顺提,Stanza for mac 也不怎样,BookReader 就很不错,非常接近 iBooks 了,另外一个 mac 上的软件 Tofu 也是类似的理念,流阅读。

像杂志还是像网页?流阅读还是点阅读?体验完全不同。

本来是想拿掉 Google 广告,再简化下 blog 页面,找新的 WordPress 主题,但始终没有满意的。要么太啰嗦,要么太花哨,要么毫无美感。我倒是很喜欢 http://daringfireball.net 的风格,干练、智慧,但仍然看起来像网页。

在几乎想要放弃时,突然看到 tanzaku,我这才恍然意识到,流阅读才是王道。