Linux无线折腾记- Endless Wireless

感谢阿稳的鼓励,让我把邪恶的独家秘籍公开于世。其实也算不上什么狗屁,只不过北京的这个夜晚太热,让人非常焦躁。

去你妈的无线

暗夜
赤膊的Mars因为一时的脑残
挥舞着iwconfig
怒视着恶龙

地狱
散发着死寂的热气
豆大的汗珠布满了勇士的躯体
一声狂吼
“干你丫的,无线!今天老子就把你做了!”

恶龙没有听见
它根本就是聋子
摇头摆尾
不肯就范
它向往自由
不愿给勇士继续当拉车的驴

勇士将宝剑抛远
脱下内裤
使出终极奥意
“wicd……”

“啊!”
脚下一滑
衰 到地面
嘴里啃了好多怪里怪气的泥巴

好多坑
怎么原来没看到
不想了
继续使出绝招吧

“wicd!”
此波能量巨大
将nm顿时化为无形
恶龙顿时傻逼了
乖乖把勇士的战车套在身上

天边
微微泛起了白光
勇士乘着呼啸的战车
消失在天与地的界限
是走向了黑暗
还是投奔了光明
只有无尽的夜才知道

下面列出演员表
ndiswrapper 乐队
madwifi 乐队
lspci & lshw 组合
iwconfig & iwlist 组合
lsmod & modprobe 组合
network manager 乐队
wicd 乐队

** 引子
所有的事情都源于一个叫做awesome的漂亮姑娘…… Mars看上了这个awesome,想把她带回家,可是发现awesome不能与原有的在gnome配好的无线和谐相处。Mars去远方求一种药水,能够使得二者可以和谐相处。

** 发现的问题

*** ndiswrapper与madwifi之争
我一直用的nidswrapper驱动,这次有点怀疑是不是驱动出了问题。不过借助于lsmod看貌似驱动都加载正常。但是也是心理犯嘀咕,所以还是折腾了好久madwifi。madwifi的stable版本不支持我的内核,最后搞了一个snapshot才可以编译,这其中耽误了不少功夫。
最大的弯路在于一值不晓得iwconfig与network manager有冲突。手工配置iwconfig一直不成功。还乱搞一气。胡乱装了wicd,肯定是于事无补啊。最后在awesome中启动nm-applet网络就能配置了。当然这个还需要仔细研究一下了。因为有这些烂问题在所以也不知道madwifi配置是否成功,反正编译安装都正常,模块加载也都正常。

*** wicd与network manager有冲突
虽然这已经不是什么新闻了(不过我才知道,shy~),但是wicd既然与network manager有冲突,理所当然应该在安装一个包的时候反安装另外一个。也要在运行时检查是否有另一个运行。X的窗口管理器这点就做的比较好,同时只能有一个在跑。
wicd与nm水火不容的程度真是难于形容,就算有一个nm-applet的僵尸在,wicd也不能正常工作。

*** wicd本身启动就有问题
wicd针对于ubuntu的安装包,在安装完成的时候要启动自身的守护进程。问题是启动守护进程需要root权限,这点做的还不够细致,所以导致启动一定失败。需要手工启动。

UNO牌Ruby源码实在是写得太烂了

最近研究UNO牌,想自己写一个,于是google一下,准备参考。还真的发现有人用Ruby写了一个,真不错啊。
http://www.merkisoft.ch/projects/uno/

由于估计是瑞士人写的,所以文档和程序的命名都是用的德语,看着好吃力,幸亏有google在线翻译,我把大部分文字都翻译成了英文。这是我第一次近距离接触德语,感觉怕怕的,语法甚是我辈所不能理解。

看着看着,我就惊讶了。这是什么烂程序啊。我一向以为欧洲程序员有严谨的作风,受过良好教育,守规矩,有各种好的习惯。看来并不是所有人都像DHH一样啦。我把一些心得体会记下来,警醒自己和同路中人今后不要走弯路。由于源代码只能看不能摸,哦,是不能发布,所以这里我不能贴出源码片段。

1. 有一个函数将近100行,它的名字叫做run。我在豆瓣上说我看见了一个100行的ruby函数,众人立刻对我表示深深的同情。有人说20行就已经很多了。看来今天我确实遇到极品了。那么这么重的坏味道究竟来自于哪里呢,哦原来作者用if实现了一个有限状态机(FSM),多么极品的想法啊。长的函数是代码坏味道之首,一定要重写。有限状态机的相关部分可以参考state_machine不要重复发明轮子DRY,更不要用Ruby重复发明轮子,我真的很在意。另外说一句state_machine的作者也算呕心沥血,花了多年时间才到这个程度的,大家应该能感觉到其功力深厚。

2. 没有大胆使用class。换句话说没有有效的封装。最典型的例子就是“牌”,UNO牌是一种桌面游戏,其基本元素就是一张张的牌。作者似乎定义了一些类,但是却没有一个是关于“牌”的。这就导致了在其他类的内部出现了大量的不相关的代码。没有关于“牌”的类,自然关于牌的函数也是凤毛麟角,这样对系统的主要逻辑产生了很大冲击。不易于看到程序清晰的主干。建议做一个Card类,将牌本身的一些动作封装进去。

3. 使用魔法数。靠数字辨别颜色,靠数字表明牌的类型。这个坏处就不用多讲了。别让大家需要猜谜语,于人于己都不是好主意。应该更多的使用常量和符号,杜绝使用魔法数。

4. 将一个功能分散到多个文件中实现。我承认的确有些复杂的功能需要把功能实现分散开。但是这里的情况完全不是这样的。本身一些定义很清晰应该在模型一层。其中有一个类的实例方法在三个不同的地方实现。问题是文件之间应该确保调用顺序,要在文件当中写明require。但事实上这项工作交给了调用者,也就是说调用者得到功能与其require加载的顺序有关,一旦加载顺序不对,程序就完蛋了。这样的东西纯属人祸,我相信有很多不明不白的程序就是这么完蛋的。建议在一个文件中实现相关功能,文件头部必须显式调用所依赖的库或文件。

5. 莫名其妙的命名,比如ok。

6. 自己发明的单元测试,美其名曰单元测试。建议使用标准的单元测试框架,或者使用Rspec这样的奇妙工具。测试的力度还应该加大一些,目前来看还远不到单元的级别。

其他一些想法

1. 设计上通讯应该和模型逻辑等分离。模型接口应该和通讯高度解耦,这样就可以用任意通讯程序替换,这也是提高可测性的考虑。

2. 命名要遵守一般原则。比如用UNO的标准用语来命名牌或者动作,而不要使用同义词。最好使用英语,其他语言的命名还是不提倡。

3. 使用reek这样的工具,保持警惕性,保持对坏味道敏感性。看看结果

mars@mars-laptop:~/uno-ruby/src$ reek . | grep "LongMethod"
  AdvancedSpieler#karteWaehlen has approx 15 statements (LongMethod)
  Mensch#karteWaehlen has approx 21 statements (LongMethod)
  Mensch#zeigeKarten has approx 9 statements (LongMethod)
  busy has approx 6 statements (LongMethod)
  Spiel#add has approx 7 statements (LongMethod)
  Spiel#run has approx 37 statements (LongMethod)

要想保持完美体型就得经常锻炼,而且得科学锻炼,写程序也是一样,要讲求科学,要不断反省自己,另外要经常写,保持肌肉健壮。

New Challenge

今日入职新工作,工作机是一台WinXP,来得时候没带其他OS的安装介质,只好挂着代理下Python的安装包。

想起老大吩咐准备Python培训时说:实在不行就每天一道Python Challenge

于是等待下载的时候就捡起了Python Challenge(http://www.pythonchallenge.com/)。话说上次(四年前?)被第五关那个伪装成”Pack Hell”的”pickle”给恶心到了,当时心中隐隐懊恼自己的E文水平,顺便也认为在计算机编程题中以谐音作为难点很无趣,于是就木有继续做下去。
没想到会又一次面对这站。

因为安装包还在下载中,所以解题时自然无法使用本机的Python。

于是突发奇想,反正从前也用Python切过这站,今次何不换门语言?

把Python Challenge 玩成New Challenge好了 : P

第一关,直接在地址栏里敲入

?View Code JAVASCRIPT
javascript: alert(Math.pow(2, 38));

……貌似算得还挺快?

第二关, 移位密码……脑子里立刻浮现出一堆 map 和 lambda ……
这就不麻烦 js 了吧~
打开 TryHaskell(http://www.tryhaskell.org),敲了几句代码,正确性没问题,不过 tryhaskell 的shell不能粘贴代码,整段密文好长……
只好老老实实的在vps的terminal里启一个hugs,幸好tryhaskell里头输入的代码还是可以拷贝下来的。

?View Code HASKELL
let s="……lmu ynnjw ml rfc spj. " 
in map (\w -> inter­sperse "" $ map (\c -> [chr $ 97 + mod (ord c - 97 + 2) 26]) w) $ words­ s

写得很快,读着有点恶心的一坨代码 : P

此处的 intersperse 在 Data.List 中定义(tryhaskell 很体贴,默认就导入了这个函数,而且在tryHaskell中使用ord和chr等函数也无需import Data.Char, 很方便吧?……不过话说tryhaskell里头貌似无法导入任何模块,所以提供的函数全一些也是为了大家玩得开心。),用途和 Python 中的字符串方法 join 近似,只不过 intersperse 定义在泛型的列表上,可用的范围更广罢了。另外intersperse返回值类型仍然一个列表,如果在处理字符串的时候希望达到和Python中join函数相同的效果,需要对结果 concat 一下 : )

Python中的

?View Code PYTHON
",".join(["hello", "world"])

在Haskell中可以写为

?View Code HASKELL
concat $ intersperse  ","  ["hello", "world"]

其实 concat 和 intersperse 的组合与 Data.List 中的 intercalate 函数是等价的。
写成这样就行了:

?View Code HASKELL
intercalate  ","  ["hello", "world"]

好吧,既然Haskell里头实现Python的join函数很容易,那么split函数呢?
……这个,貌似除了Hackage中的那个正则split,并没有特别简单的方法。
前些天山寨了一个,简单用用,性能没测,不知在特别大的字符串上效率如何。
正确性是没问题的 : P

?View Code HASKELL
> module MySplit (split) where
 
> split :: String -> String -> [String]
 
> split s tkn | l == 0 = [s]
>             | otherwise = _split s
 
>     where
>         l = length tkn
>         _split x | tkn == take l x =
>                         "": (_split $ drop l x)
 
>                  | null x =
>                         "":[]
 
>                  | otherwise =
>                         (head x : head sp) : tail sp
>                             where
>                                 sp = _split $ tail x

这个实现采取逐位匹配的方法搜寻作为分割符的串,好处是清晰易懂,坏处是会做许多无用功,如果使用BM算法的跳转匹配,效率会提升许多。

呃,貌似跑题了……

本帖主题是New Challenge来着……嗯

虽说学习新语言时,应该避免”用Pascal语法写出BASIC风格的程序”(《十年学会编程》http://daiyuwen.freeshell.org/gb/misc/21-days-cn.html),

但是,使用新语言尝试过去已经完成的任务,确实是一个学习语言的好方法。
著名的编程语言联系练习项目PLEAC(http://pleac.sourceforge.net/),就是如此。

PLEAC中使用接近30种不同的语言来重复完成Perl CookBook中的练习。其中既包括Python,Ruby,C++等热门语言,也包括Haskell,OCaml,Guile,R等小众语言,甚至还有汇编语言。

看来学习就是一个”重复”的过程,
不断挑战自己,用旧瓶酿出新酒来吧~!
: D

定义 0 的阶乘

如果 projecteuler 的 problem 34 的官方答案是正确的,那么 0 的阶乘就是 1。否则,官方的答案就是错误的。

0 的阶乘为什么是 1 呢?
……为了将就 阶乘的 “递推定义“

“n!=n*(n-1)!,那么必然有一个初值需要人为规定。我们知道1!=1,根据1!=1*0!,所以0!=1而不是0。 “

狗屁splint,折腾死我了

偶尔看到一个下载管理工具uget觉得挺好玩的,就弄了一个svn版本的准备玩玩。突发奇想想实践一下静态检查,索性祭出splint。惨痛的经历就这样开始了。

1.

mars@mars-laptop:~/memoryleaktest/urlget/trunk/src$ splint ug_plugin_curl.c 
Splint 3.1.2 --- 03 May 2009
 
ug_plugin_curl.c:38: Include file  matches the name of a POSIX
    library, but the POSIX library is not being used.  Consider using +posixlib
    or +posixstrictlib to select the POSIX library, or -warnposix to suppress
    this message.
  Header name matches a POSIX header, but the POSIX library is not selected.
  (Use -warnposixheaders to inhibit warning)
ug_plugin_curl.c:43:26: Cannot find include file glib/gstdio.h on search path:
                           /usr/include;/usr/include
  Preprocessing error. (Use -preproc to inhibit warning)
ug_plugin_curl.c:44:29: Cannot find include file ug_plugin_curl.h on search
                           path: /usr/include;/usr/include
ug_plugin_curl.c:45:31: Cannot find include file ug_data_download.h on search
                           path: /usr/include;/usr/include
ug_plugin_curl.c:46:23: Cannot find include file ug_stdio.h on search path:
                           /usr/include;/usr/include
ug_plugin_curl.c:47:23: Cannot find include file ug_utils.h on search path:
                           /usr/include;/usr/include
ug_plugin_curl.c:48:21: Cannot find include file ug_uri.h on search path:
                           /usr/include;/usr/include
Preprocessing error for file: /home/mars/memoryleaktest/urlget/trunk/src/ug_plug
                           in_curl.c
*** Cannot continue.

看来是没有加载必要的头文件,翻看了一下源码文件夹应该在include 中,添加上

2.

mars@mars-laptop:~/memoryleaktest/urlget/trunk/src$ splint -I../include \
 ug_plugin_curl.c
Splint 3.1.2 --- 03 May 2009
 
ug_plugin_curl.c:38: Include file  matches the name of a POSIX
    library, but the POSIX library is not being used.  Consider using +posixlib
    or +posixstrictlib to select the POSIX library, or -warnposix to suppress
    this message.
  Header name matches a POSIX header, but the POSIX library is not selected.
  (Use -warnposixheaders to inhibit warning)
ug_plugin_curl.c:43:26: Cannot find include file glib/gstdio.h on search path:
                           ../include;/usr/include;/usr/include
  Preprocessing error. (Use -preproc to inhibit warning)
../include/ug_plugin.h:43:19: Cannot find include file glib.h on search path:
                                 ../include;/usr/include;/usr/include
   In file included from ../include/ug_plugin_curl.h:51,
                 from ug_plugin_curl.c:44
../include/ug_dataset.h:47:19: Cannot find include file glib.h on search path:
                                  ../include;/usr/include;/usr/include
   In file included from ../include/ug_plugin.h:44,
                 from ../include/ug_plugin_curl.h:51,
                 from ug_plugin_curl.c:44
../include/ug_data.h:45:19: Cannot find include file glib.h on search path:
                               ../include;/usr/include;/usr/include
   In file included from ../include/ug_dataset.h:48,
                 from ../include/ug_plugin.h:44,
                 from ../include/ug_plugin_curl.h:51,
                 from ug_plugin_curl.c:44
../include/ug_markup.h:43:19: Cannot find include file glib.h on search path:
                                 ../include;/usr/include;/usr/include
   In file included from ../include/ug_data.h:46,
                 from ../include/ug_dataset.h:48,
                 from ../include/ug_plugin.h:44,
                 from ../include/ug_plugin_curl.h:51,
                 from ug_plugin_curl.c:44
../include/ug_data_download.h:61:19: Cannot find include file glib.h on search
    path: ../include;/usr/include;/usr/include
   In file included from ../include/ug_plugin_curl.h:52,
                 from ug_plugin_curl.c:44
../include/ug_stdio.h:50: Include file  matches the name of a POSIX
    library, but the POSIX library is not being used.  Consider using +posixlib
    or +posixstrictlib to select the POSIX library, or -warnposix to suppress
    this message.
../include/ug_stdio.h:53: Include file  matches the name of a POSIX
    library, but the POSIX library is not being used.  Consider using +posixlib
    or +posixstrictlib to select the POSIX library, or -warnposix to suppress
    this message.
../include/ug_stdio.h:55: Include file  matches the name of a POSIX
    library, but the POSIX library is not being used.  Consider using +posixlib
    or +posixstrictlib to select the POSIX library, or -warnposix to suppress
    this message.
../include/ug_stdio.h:58:19: Cannot find include file glib.h on search path:
                                ../include;/usr/include;/usr/include
   In file included from ug_plugin_curl.c:46
../include/ug_stdio.h:59:26: Cannot find include file glib/gstdio.h on search
                                path: ../include;/usr/include;/usr/include
../include/ug_utils.h:40:19: Cannot find include file glib.h on search path:
                                ../include;/usr/include;/usr/include
   In file included from ug_plugin_curl.c:47
../include/ug_utils.h:41:26: Cannot find include file glib/gstdio.h on search
                                path: ../include;/usr/include;/usr/include
../include/ug_uri.h:40:19: Cannot find include file glib.h on search path:
                              ../include;/usr/include;/usr/include
   In file included from ug_plugin_curl.c:48
Preprocessing error for file: /home/mars/memoryleaktest/urlget/trunk/src/ug_plug
                              in_curl.c
*** Cannot continue.

哦,原来找不到glib头文件。靠,还没装glib的库和头文件,安装一下,对了把curl的库也一同装上。为了避免太多低质量的提示使用 +posixlib参数。

3.

mars@mars-laptop:~/memoryleaktest/urlget/trunk/src$ splint -I../include \
 ug_plugin_curl.c +posixlib
Splint 3.1.2 --- 03 May 2009
 
ug_plugin_curl.c:43:26: Cannot find include file glib/gstdio.h on search path:
                           ../include;/usr/include;/usr/include
  Preprocessing error. (Use -preproc to inhibit warning)
../include/ug_plugin.h:43:19: Cannot find include file glib.h on search path:
                                 ../include;/usr/include;/usr/include
   In file included from ../include/ug_plugin_curl.h:51,
                 from ug_plugin_curl.c:44
../include/ug_dataset.h:47:19: Cannot find include file glib.h on search path:
                                  ../include;/usr/include;/usr/include
   In file included from ../include/ug_plugin.h:44,
                 from ../include/ug_plugin_curl.h:51,
                 from ug_plugin_curl.c:44
../include/ug_data.h:45:19: Cannot find include file glib.h on search path:
                               ../include;/usr/include;/usr/include
   In file included from ../include/ug_dataset.h:48,
                 from ../include/ug_plugin.h:44,
                 from ../include/ug_plugin_curl.h:51,
                 from ug_plugin_curl.c:44
../include/ug_markup.h:43:19: Cannot find include file glib.h on search path:
                                 ../include;/usr/include;/usr/include
   In file included from ../include/ug_data.h:46,
                 from ../include/ug_dataset.h:48,
                 from ../include/ug_plugin.h:44,
                 from ../include/ug_plugin_curl.h:51,
                 from ug_plugin_curl.c:44
../include/ug_data_download.h:61:19: Cannot find include file glib.h on search
    path: ../include;/usr/include;/usr/include
   In file included from ../include/ug_plugin_curl.h:52,
                 from ug_plugin_curl.c:44
../include/ug_stdio.h:58:19: Cannot find include file glib.h on search path:
                                ../include;/usr/include;/usr/include
   In file included from ug_plugin_curl.c:46
../include/ug_stdio.h:59:26: Cannot find include file glib/gstdio.h on search
                                path: ../include;/usr/include;/usr/include
../include/ug_utils.h:40:19: Cannot find include file glib.h on search path:
                                ../include;/usr/include;/usr/include
   In file included from ug_plugin_curl.c:47
../include/ug_utils.h:41:26: Cannot find include file glib/gstdio.h on search
                                path: ../include;/usr/include;/usr/include
../include/ug_uri.h:40:19: Cannot find include file glib.h on search path:
                              ../include;/usr/include;/usr/include
   In file included from ug_plugin_curl.c:48
Preprocessing error for file: /home/mars/memoryleaktest/urlget/trunk/src/ug_plug
                              in_curl.c
*** Cannot continue.

啊,这是为什么阿,为什么?!看看/usr/include下面有没有 glib.h,果然没有。原来glib头文件在/usr/include/glib-2.0里面。于是乎添加一个目录啊。
4.

mars@mars-laptop:~/memoryleaktest/urlget/trunk/src$ splint -I../include \
 -I/usr/include/glib-2.0 ug_plugin_curl.c +posixlib
Splint 3.1.2 --- 03 May 2009
 
/usr/include/glib-2.0/glib/garray.h:50:9:
Parse Error. (For help on parse errors, see splint -help parseerrors.)
*** Cannot continue.

不是吧,这么牛逼的头文件居然无法解析。简直就是开玩笑嘛。google一下关键词“splint glib parse error”得到非常多不靠谱的答案,不过在这个网址http://www.cs.virginia.edu/pipermail/splint- discuss/2008-February/001110.html
有这样一段话

I compile a more elaborate, but very similar file perfectly using the make command in my working directory, so I went to check what I might be forgetting, only to find `pkg-config –cflags glib-2.0` hidden in my make file’s CFLAGS variable. Splint passes -I to the preprocessor, and the above backtick expression evaluates to “-I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include” on my system.

貌似添加一个地址是不对的。那就添加两个好了。

5.

mars@mars-laptop:~/memoryleaktest/urlget/trunk/src$ splint -I../include \
 `pkg-config --cflags glib-2.0`  ug_plugin_curl.c +posixlib
Splint 3.1.2 --- 03 May 2009
 
ug_plugin_curl.c:91:75: Static supported_schemes[4] initialized to null value:
                           supported_schemes[4] = NULL
  A reference with no null annotation is assigned or initialized to NULL.  Use
  /*@null@*/ to declare the reference as a possibly null pointer. (Use
  -nullassign to inhibit warning)
ug_plugin_curl.c:96:2: Static plugin_class_curl.reserve initialized to null
                          value: plugin_class_curl.reserve = NULL
ug_plugin_curl.c:97:24: Initial value of plugin_class_curl.instance_size is
                           type size_t, expects guint: sizeof(UgPluginCurl)
  Types are incompatible. (Use -type to inhibit warning)
ug_plugin_curl.c:99:2: Static plugin_class_curl.file_types initialized to null
                          value: plugin_class_curl.file_types = NULL
ug_plugin_curl.c:113:42: Storage plugin_class_curl reachable from initial value
                            is unqualified static (should be unqualified)
  Storage derivable from a parameter does not match the alias kind expected for
  the formal parameter. (Use -compmempass to inhibit warning)
 
.....
.....
.....
 
ug_plugin_curl.c:756:58: Null storage passed as non-null param:
                            g_filename_from_utf8 (..., NULL)
ug_plugin_curl.c:760:16: Fresh storage file not released before return
   ug_plugin_curl.c:756:2: Fresh storage file created
/usr/include/bits/confname.h:31:27: *** Internal Bug at cscannerHelp.c:2428:
    Unexpanded macro not function or constant: int _PC_MAX_CANON [errno: 25]
     *** Please report bug to submit@bugs.debian.org (via reportbug) ***
       (attempting to continue, results may be incorrect)
/usr/include/bits/confname.h:32:1: Parse Error: Non-function declaration:
    _PC_MAX_CANON : int. (For help on parse errors, see splint -help
    parseerrors.)
*** Cannot continue.

问题是发现了不少,可是怎么又在系统文件上出了问题啊。google一下,找到答案http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=473595
原来这的确是一个bug,由于splint在07年以后就没有更新过,所以应该是所有版本都会受到影响的吧。只要去掉 +posixlib就能正常工作了。
6.

mars@mars-laptop:~/memoryleaktest/urlget/trunk/src$ splint -I../include \
 `pkg-config --cflags glib-2.0`  ug_plugin_curl.c
Splint 3.1.2 --- 03 May 2009
 
ug_plugin_curl.c:38: Include file  matches the name of a POSIX
    library, but the POSIX library is not being used.  Consider using +posixlib
    or +posixstrictlib to select the POSIX library, or -warnposix to suppress
    this message.
  Header name matches a POSIX header, but the POSIX library is not selected.
  (Use -warnposixheaders to inhibit warning)
 
.....
.....
.....
 
ug_plugin_curl.c:760:16: Fresh storage file not released before return
   ug_plugin_curl.c:756:2: Fresh storage file created
 
Finished checking --- 179 code warnings

终于成功了。总结一下,想当然以为添加了/usr/include/glib-2.0就能行。结果差点把自己搞死,本来用splint的人就少,像我这样乱用的人就更少了。

一点流水帐

1. emacs 23 与 ibus 冲突,ubuntu 910切换到中文问题解决。 感谢crazycode的指点。
2. 标签云 acts-as-taggable-on 插件,canvas explorercanvas感谢blade提供的信息
3. 读Rework,但是没有找到完全版。

新玩具

1.Try Haskell
http://tryhaskell.org
想用Haskell验证一下想法,可惜手头的机器上面没有装解释器?
现在有了这个在线Haskell解释器可以随时随地享受FP的乐趣了~

2.Try Ruby
http://tryruby.org
在线的Ruby解释器,看了TryHaskell的介绍就知道它的思路来自于这个。

3.NodeJs
http://nodejs.org/
好心人为Javascript的V8引擎编写的IO接口,包括文件和网络。
作者的例子中包括了一个小型的聊天室的服务器。

不多说了吧,祝大家玩得开心,用着舒心~~

MongoDB 东扯西

话说,传统的关系型数据库已经不那么吃香了。近来其他类型的数据库如雨后的春笋一般层出不穷,令人目不暇接,但也肯能非常令人恼火。究其原因,大多是觉得关系型数据库的性能不行,很多情况下也不适合互联网的应用。有针对性的,各路神侠构造了各种兵器,其中很大一类是基于key/value机制的数据库,典型的代表呢,就是Tokyo Cabinetmemcachedb。Tony Bain的一篇文章Is the Relational Database Doomed?对一些数据库发展的现状做了一个客观的评说。另外,还有ibm提出的xml的东西,不知道是个啥,半死不活的样子。很多年以前还有人搞了面向对象的数据库,后来也不怎么着,算是无疾而终(这么说很对不起还活着的兄弟,那能怎么样呢,不过是行尸走肉)。

无疑,数据库战场上的波澜会将每一个互联网开发者卷入其中。一波又一波的“去SQL化”浪潮(详见这里)在改变我们观念的同时,也在改变互联网的构建方式。

Document-Oriented database应运而生,典型代表

CouchDB 有篇不错的英文介绍

不过今天的主角是MongoDB注意啊不是MangoDB,让我们开开心心的开始吧。

Ruby的编码真愁人

我说这么好的语言在国内流行不起来呢。编码是个大问题。不管怎么说Java在这一点上做的还是很有先见之明的。而且做得也算最好了。编码的问题直接影响了我举的例子,本来是想拿blade的豆瓣开涮的,无奈编码问题没有解决。

不过今天还是比较有成绩的,第一,我的RadRails终于能加载nokogiri,究其原因多半是从前先装了RadRails后装的ruby1.8。反复重装几次也不能解决问题,后来把用户数据全部删除,重新关联解释器就好了。真是折腾死我了。

另外大家一定要用nokogiri,暂时不要去想别的解析器了,如果你看到别的教程说Hpricot好,多半儿这个文章是一年以前写的没啥价值了。不要走回头路。

补充一个非常好的学习地址

Railscasts

看演示,学ruby,让ruby在你眼前闪亮!

当然还有相应的文字版本,供那些喜欢安静,或者带宽较小的朋友。

home

Web Scraping in Ruby 直捣黄龙

今天我们来看看怎么获取我们关心的信息,直击要害。

Web给了我们太多不想要的信息,比如说你去新浪看新闻,竟是些不着边际的花边新闻,只不过是些惹眼的词汇罢了,并没有什么真实的内容。我经常有这种感受,为了看网页中的一点点儿东西,要忍受整个网页里面的垃圾信息对我的轰炸,各种广告,弹出对话框,有的还有脚本漏洞真实令人防不胜防,烦不胜烦。

比如我就想知道当下微软的股票价格,我怎么办呢?

http://finance.yahoo.com/q?d=t&s=MSFT

就是一个能提供这种信息的地方,哦那里有股票的价格。

image

我们用一个小工具SelectorGadget,这是个什么东西呢?简单来说,这个工具告诉我们关于某种信息的精确定位坐标。比如说我要找百度大厦,在地图上告诉你“这儿”就是不精确的,但是要是告诉你在“上地九街”就很精确了。这个工具就提供精确制导坐标,你只要点击你想要的区域,它就能自动生成css选择表达式或者xpath表达式,非常高效。有了它,几乎能把90%以上的网页都搞定。

闲言少叙见代码

require 'rubygems'
require 'nokogiri'
require 'open-uri'
 
msft_stock_url = "http://finance.yahoo.com/q?d=t&s=MSFT"
doc = Nokogiri::HTML(open(msft_stock_url))
 
doc.xpath("//*[(@id = \"table1\")]//*[(@id = \"yfs_l10_msft\")]").each do |item|
  puts item.text   
end