2010-04-26

屠龙术

典出《庄子·列御寇》:“朱泙漫学屠龙于支离益,殚千金之家。三年技成,而无所用其巧。”

另附,陆游《冬夜读书示子聿》:
古人学问无遗力, 少壮工夫老始成。纸上得来终觉浅, 绝知此事要躬行。

标签:

I like AUR!

AUR(Arch User Repository) 是个社区驱动的仓库。Arch用户可以提交 PKGBUILD 文件供其他用户分享,而 PKGBUILD 文件就像菜谱一样,告诉 makepkg 怎样生成一个可以用 pacman 安装的程序包。类似Debian中的apt-src。

yaourt 是个前端脚本,除了查找标准的仓库如 core, community 以及 testing (默认不搜索)之外,还会搜索 AUR,这样用户可选的安装包种类可以算是五花八门,包罗万象了。安装了一个llvm-py,不过发现导入llvm.core的时候会失败,在Debian中安装 python-llvm 也是如此。最后发现是生成 so 文件的时候没有链接到 libffi,用 yaourt 安装 llvm-py, 过程中可以修改一下 PKGBUILD 文件,如下:

[sourcecode language="diff"]
--- a/PKGBUILD  Mon Apr 26 10:25:34 2010 -0700
+++ b/PKGBUILD  Mon Apr 26 10:25:56 2010 -0700
@@ -18,6 +18,7 @@
build() {
cd $startdir/src
svn co http://llvm-py.googlecode.com/svn/trunk/ llvm-py-${pkgver}
+  export LDFLAGS=`pkg-config libffi --libs`
cd llvm-py-${pkgver}
python setup.py install \
--prefix=/usr \
[/sourcecode]

这回果然OK了。

标签:

2010-04-25

杂记


上周因为McAfee的问题,差点想把机器重装了。不过后来成功修复,于是就沿用着WinXP + VMware的方式。VMware里跑了个ArchLinux,就算以后换电脑也只需要把虚拟机拷贝过去即可,方便。


周末玩了把LP组里的macbook小白,很喜欢它的键盘。如果Apple卖裸机就好了,出于习惯我更喜欢用Linux。最低配置的13macbookpro京东卖8688,而万达专卖店现在也只卖8800,据称已经卖得只剩最后一台。我理想中的笔记本:macbookpro那样的造型,没有光驱,运行Linux


今天在万达似乎看见两位名人,因为没有打招呼所以不能确定。第一个是凤姐,在第一食品,相似度90%。第二个是冯正虎,正和他妻子从公司楼下的桥上往百联方向走,相似度95%。插肩而过后,左右看了看,似乎没有便衣,有点后悔没有握个手。正心神不定的时候还看见一个很像谢晋的,汗。


没想到现在坐海盗船都有点心虚了,想当年我可是在嘉年华玩过高空弹球的,以至于后来玩过山车和超级进化都感觉乏味。廉颇老矣!

标签:

2010-04-22

人品爆发

标签:

2010-04-12

感谢信

往blog上贴代码算是比较痛苦的问题,因为需要人肉语法高亮。平时我基本是用vim的TOhtml,或者在emacs里选中一块区域后 M-x htmlize-region,虽然不算很麻烦,不过贴到blog里后配色或者排版都不太如意。

感谢我们伟大光荣正确的老鄢同学,为我装了个syntaxhighlighter-plus,一举解决了这个烦恼的问题。同时感谢老鄢一直维护着这个wpmu,在网管岗位上尽职尽责,并让我免于网事在天朝的各种繁琐 -- 比如:网站备案。

标签:

Case Classes

Scala 里有个叫做 "case classes" 的东西,这个应该是从 ML 家族的语言特性启发而来,习惯于 C/C++ 的程序员可能较少看到这个名词。比如,我们要写一个算术表达式解析器,比如下面就是一些合法的表达式:

  • 5

  • -5

  • 2+3

  • foo

  • 4 + foo


这在ML家族语言比如Haskell中非常容易表达。如下,这也是迄今为止我看到的最简洁的表达方式(看起来直接就是EBNF的描述方法):

> data Expr =
>     Number Int
>   | Var String
>   | UnOp String Expr
>   | BinOp String Expr Expr
> deriving (Show)


Scala 中用 "case classes" 来描述,如下:

abstract class Expr
case class Var(name: String) extends Expr
case class Number(num: Double) extends Expr
case class UnOp(operator: String, arg: Expr) extends Expr
case class BinOp(operator: String, left: Expr, right: Expr) extends Expr


看起来没有 Haskell 那么简单直接,但远远聊胜于无了:

scala> val op = BinOp("+", Number(1), Var("x"))
op: BinOp = BinOp(+,Number(1.0),Var(x))


Haskell中类似,

ghci> let op = BinOp "+" (Number 1) (Var "x")
ghci> op

BinOp "+" (Number 1) (Var "x")

标签: ,

2010-04-09

Why I love Arch

$ sudo python bin/ps_mem.py  | sed 's/^/> /'
>  Private  +   Shared  =  RAM used     Program
>
>  76.0 KiB +  59.0 KiB = 135.0 KiB     agetty
>  92.0 KiB +  62.0 KiB = 154.0 KiB     init
> 112.0 KiB +  66.5 KiB = 178.5 KiB     crond
> 152.0 KiB +  68.5 KiB = 220.5 KiB     sed
> 196.0 KiB +  44.5 KiB = 240.5 KiB     dhcpcd
> 212.0 KiB + 513.5 KiB = 725.5 KiB     udevd (3)
> 832.0 KiB + 443.5 KiB =   1.2 MiB     syslog-ng (2)
>   1.2 MiB +  79.5 KiB =   1.3 MiB     bash
>   1.6 MiB +   1.1 MiB =   2.7 MiB     sshd (3)
> ---------------------------------
>                           6.9 MiB


# wget -c http://www.pixelbeat.org/scripts/ps_mem.py

标签:

2010-04-08

call by name vs. call by value

假设现在需要在Scala实现一个断言函数,我们该怎么做呢?可能第一反应是下面的代码:
> val assertionEnabled = true
>
> def myAssert(predicate: Boolean) =
>   if (assertionEnabled && !predicate)
>     throw new AssertionError

简单来说,就是我们期望传入一个bool值,然后检查它,比如:myAssert(5 > 3)。看起来很完美,至少一眼看下去简单得无法挑剔。但是,有一个重大问题是:无论断言是否被打开,predicate都会被计算一次。如果写成myAssert(foo(x,y)),则foo(x,y)会被执行一次 -- 虽然接下来因为&&是个短路操作符,myAssert()并不检查该函数的执行结果。这叫call-by-value[1],就是说参数传递给函数之前会先计算出其结果。

Scala除了支持C家族中的call-by-value外还支持call-by-name,代码改动很简单:

-- def myAssert(predicate: Boolean) =
++ def myAssert(predicate: => Boolean) =

我这样,predicate将会在myAssert中求值,而非传入时求值。C程序员会认为 "x = 1"是个赋值语句,而对习惯于FP思维的程序员来说,他们可能倾向另一种解释:x只是个name(label),但它绑定了一个类型为整型的数值1(或者x是个返回整数1的函数)。

参考:
[1]  Evaluation Strategy,http://en.wikipedia.org/wiki/Evaluation_strategy

标签:

2010-04-07

archlinux技巧一则

因为在家访问大部分USA的archlinux的镜像都比较慢,后来就改成了Japan的,不过还是比较慢,在LP用PPS的时候一般下载速度只有3KiB/s左右。于是就找了几个国内的,sync了一下后居然提示没啥好更新的(本来有30MB以上的文件需要下载),想来可能是国内这几个镜像未必是同步更新的缘故。

切换了回去以后发现已然如故,还是提示没有更新。今天sync的时候发现community有更新,然后便诡异的报告某些依赖无法解决,而在切换镜像之前这些都是好好的。可能是某些记录没有更新。

$ sudo find /var/lib/pacman/sync/ -type f \
-name .lastupdate -exec rm -f {} \;


重新 sudo pacman -Syu 即可。

标签:

Stackable Modifications

Scala里面支持trait,可以提供类似Ruby mixin以及Java interface的功能,还有一个有趣的功能是 "stackable modification",感觉很像Ruby中常提到的 monkey patch。摘录 "Programming in Scala" 中的一个小例子,假设有个整型数构成的队列,提供两个基本操作:put和get,分别用于存、取一个数。接下来,我们对存入数据分别做三种操作:

  1. 倍乘 - 对输入数据n,存入n * 2;

  2. 增一 - 对输入数据n,存入n + 1;

  3. 过滤 - 对输入数据n,当且仅当 n 不为负数时才存入。


这在Scala里面实现起来相当舒服:

> abstract class IntQueue {
>   def get(): Int
>   def put(x: Int)
> }
>
> import scala.collection.mutable.ArrayBuffer
>
> class BasicIntQueue extends IntQueue {
>   private val buf = new ArrayBuffer[Int]
>   def get() = buf.remove(0)
>   def put(x: Int) { buf += x }
> }
>
> trait Doubling extends IntQueue {
>   abstract override def put(x: Int) {super.put(2 * x)}
> }
>
> trait Incrementing extends IntQueue {
>   abstract override def put(x: Int) {super.put(1 + x)}
> }
>
> trait Filtering extends IntQueue {
>   abstract override def put(x: Int) {
>     if (x >= 0) super.put(x)
>   }
> }


val q = new BasicIntQueue with Doubling
这样在q中存入10,则会取回20。

val q = new BasicIntQueue with Incrementing with Doubling
这样在q中存入14,则会取回29(double一次再增一)。

标签: