每次修改代码一般只会涉及一部分文件,大部分代码都是不必重复编译的。而且编译明显是分步骤也有依赖关系,比如要测试程序就得先链接出一个可执行文件,要链接就得先编译成.o。。。所以就有了make,自动分析任务的依赖关系,只对有变更的文件执行编译,省心省时间。
不过make的语法晦涩啊…就有了rake
rake提供了file函数可以指明文件的依赖关系,比如:
file 'fdict.o' => ['src/fdict.c', 'src/fdict.h'] do
sh 'gcc -Wall -c src/fdict.c'
end
file 'test.o' => ['src/test.c'] do
sh 'gcc -Wall -c src/test.c'
end
file就是个ruby的函数调用,把重复的东西去掉很简单
CFlags = '-Wall'
[
['src/fdict.c', 'src/fdict.h'],
['src/test.c']
].each do |fn_c, *_|
fn_o = File.basename(fn_c).ext('o')
file fn_o => [fn_c, *_] do
sh "gcc #{CFlags} -c #{fn_c}"
end
end
再就是链接和执行
OFiles = %w{fdict.o test.o}
task :run => [:link] do
sh "./test"
end
task :link => OFiles do
sh "gcc #{CFlags} #{OFiles.join(' ')} -o test"
end
每修改两行C程序到控制台下边一个rake run就可以立即执行,这一来写c就有点像写脚本了。
Posted on 五月 18th, 2010 in 笔记 | 2 Comments »
无论何时,只要单个资源需要在多个用户间共享,就必须处理一致性的问题。
回头想下“函数式语言无副作用适合写并发程序”之类的说法,只是在计算上的并发,对存储上的并发照样得上锁上钥匙。
win32的窗体使用handle而不是指针
一个窗体可能会被多个进程处理,也可以隐藏窗体对象的内部实现。
真空管和三极管的共性
都可以将信号放大,这一来就可以用电信号来控制开关了。就有了逻辑电路…
lua从堆栈机转到寄存器机
因为lua实现里表示值的那个结构体Tvalue是个tagged union,个头太大了(两个指针这么长)。在堆栈上push/pop一来一回吃资源,搞成寄存器机可以省些搬运。
为什么要有链接器
可以把程序分成模块。
C中结构体不可比较
因为结构体里数据对齐的空隙里面的东西可能随机的。
C++为什么不用printf
类型不安全。像cout好像是对每个内置类型都重载了一个<<操作符
x86实模式的逻辑地址
x86实模式的逻辑地址是段寄存器(如cs)里存一个基地址(16位),左移四位再加上一个16位的偏移。
为什么要这么蛋疼,因为当时的主线有20位(可寻址1mb),但是intel的寄存器只有16位。
自动机
就是根据输入自动切换状态的计算模型。不过状态有限,识别的语言(语言就是字符串的集合)是最少的。自动机可以识别的语言就叫正则语言。
给自动机加一个堆栈就是下推自动机,这样状态就可以无限了,可以识别的语言就叫上下文无关语言。
给自动机加一个随机存储,就是图灵机了。可以识别的语言就叫可判定语言。
有可能是imageMagick没装利索。找不到imagemagick,显示错误信息的时候试图把上传的文件对象序列化,就505了。
sudo apt-get install imagemagick --fix-missing
使用三方库就得做好不可预料事件的准备哇
关于paperclip的使用,这两篇简介好像不错:
http://jimneath.org/2008/04/17/paperclip-attaching-files-in-rails/
http://thewebfellas.com/blog/2008/11/2/goodbye-attachment_fu-hello-paperclip
ps: 又遇到了个没预料的问题,上传validates_attachment_content_type指定的类型之外的文件时候同样会遇到个500 internal server error,未解中。
Posted on 五月 8th, 2010 in 备忘 | 5 Comments »
发觉算法太弱了 =”=
当年在ACM那里呆了两天就隐身了,可惜那个老师非常非常非常好的(实验室里还有空调 >_<)。总觉得这玩意水太深,掉进去就出不来了....“不成熟的优化乃万恶之源”这话又正好应了惰性心理,心安理得地“出了性能问题再说之前先弄出来再说管算法干嘛”...可现实往往是,不会算法你压根就弄不出来...
先从一棵二叉查找树开始好了。挖坑慢慢填,时间有的是(?)
module BTree where
data BTree a b = Empty
| BNode {
kv :: (a, b),
left :: BTree a b,
right :: BTree a b
}
deriving(Show, Eq)
insert :: (Ord a) => (a, b) -> BTree a b -> BTree a b
insert (k,v) Empty = BNode (k, v) Empty Empty
insert (k,v) pnode@(BNode (pk, _) lnode rnode)
| k == pk = pnode { kv = (k,v) }
| k < pk = pnode { left = insert (k,v) lnode }
| k > pk = pnode { right = insert (k,v) rnode }
find :: (Ord a) => a -> BTree a b -> Maybe b
find k Empty = Nothing
find k (BNode (pk,pv) lnode rnode)
| k == pk = Just pv
| k <= pk = find k lnode
| k > pk = find k rnode
find _ _ = Nothing
remove :: (Ord a) => a -> BTree a b -> BTree a b
remove k Empty = Empty
remove k pnode@(BNode (pk,pv) lnode rnode)
| k == pk = merge lnode rnode
| k <= pk = pnode { left = remove k lnode }
| k > pk = pnode { right = remove k rnode }
merge :: (Ord a) => BTree a b -> BTree a b -> BTree a b
merge lnode rnode = fromList $ (toList lnode) ++ (toList rnode)
--helper
isEmpty Empty = True
isEmpty _ = False
fromList :: (Ord a) => [(a,b)] -> BTree a b
fromList = foldl (flip insert) Empty
toList :: BTree a b -> [(a,b)]
toList Empty = []
toList (BNode (k,v) lnode rnode) =
(toList lnode) ++ [(k,v)] ++ (toList rnode)
-- for test
root = fromList $ [
(4, "fleurer"),
(10, "ssword"),
(100, "ssword"),
(2, "xx")]
haskell做数据结构好像别扭的很…不用ST Monad或者IO的话什么都是值还不能引用,像二叉树的旋转什么的就没想出常数时间的办法。像上面那个remove就直接简单粗暴了orz
(邪恶音:用ST Monad不就好了嘛)
(ST Monad都用了还用haskell干嘛 TvT)
Posted on 五月 7th, 2010 in 杂碎 | 4 Comments »
“好久没更新了”~orz又这么开头了。
昨天下午给新人讲东西时候差点着起急来,耐心什么的实在是差了些。同理,这个blog也快不会写了。笔记什么的都有记在在本子上,怨念什么的也都在twi上发泄了个精光。想翻译点东西可是怎么都觉得驴唇不对马嘴,就全部作罢。
完整的橇课,上午看书下午敲代码。再同各种善意的小朋友交流下,要说充实倒确实非比寻常。不过总觉得倦的厉害,简单一个“中午不睡下午崩溃”似乎还说不过去。代码就够傲骄了,人自然更难伺候。写这句话的时候当年推销饮水机的两位童鞋又敲门进来推销凉席,都不容易。
还是说代码吧。敏捷编程什么都领悟不了还扯淡什么人生。一天几十行,我起草一份《蜗牛宣言》好了~
想用rails换掉学校网站正在用的这个aspx系统。都说rails不好维护,可是当前的这aspx系统我已经完全维护无力了,瞅着bug在那里只能对着那两万行的一个类发呆。用rails重写最起码我能维护,能用不能用写出来再说。(敏捷什么的就当笑话听吧)
闲着把寒假时候烂掉的那个堆栈机完善了下,随后发懒两个星期没碰代码,回头想下应该差不多能用了(当然是想当然)。代码改的相当蛋疼,用上了ruby那VALUE式的tagged pointer,没打算oo的也在c里把类型搞成了对象,再就是大量少于十行的小函数。以前只是听说lua的upvalue实现很简洁,看了下发现用在这里不合适,lua的临时变量和求值栈都在同一个栈帧里连续着,只要不是闭包的变量在函数执行完立即回收。而这个堆栈机里的堆栈只是求值栈,临时变量都在一个动态分配的结构体里。这里让栈帧在函数执行完后统统保留,等着GC回收就是。
从淘宝上打印了本《莱昂氏unix源码剖析》,作者好个惜字如金,读起来也很吃力。 前半部分是unix v6的全部源码,仅9000行出头。随便翻下就被雷了,内存管理的malloc和mfree不到百行,而枚举一个进程的子进程什么的就都这样:
for(p = &proc[0]; p < &proc[NPROC]; p++)
if (a->p_pid == p->p_ppid) {
p->p_ppid = 1;
if (p->p_stat == SSTOP)
setrun(p);
}
swtch();
简单粗暴,多好。