Archive for 五月, 2009

gvim使用笔记

Posted on 五月 26th, 2009 in 备忘 | 17 Comments »

使用gvim也有一段时间了,还不敢说得心应手,不过倒也不会再碰editplus之类的编辑器了。它真的很好用,熟悉起来也真的需要很长时间。前辈们说的话里还是很多实话的。

使用gvim是个有趣的过程,按下一个i,鼠标 + 箭头 它就跟普通的编辑器没有两样,初学之时不至于像在vi中完全无从下手。诚然,在键盘上的手移动到鼠标处是相当累人的,按着箭头等着光标挪到那地方也很磨耐性!这就是gvim的好处,一个命令就可以将光标移动到你想要的地方。一般而言,学会了一个命令之后要再忘记就很难了,找到了近路,谁还会绕远呢?另外,个人觉得也不用总是纠结“这是vi!要按vi的法子来!”,我就觉得ctrl+s比esc+:w省力,ctrl+a比ggvG方便,反正用着舒服就好。

note几个命令:

o 在当前行下新建一行;
! 运行一个控制台的命令,例如 ! ruby % 解释执行当前文件,其中%代表当前的文件名;
) 移动光标到下一个自然段,在程序里可以跳到下个函数;
x 删除当前字符;
r 替换当前字符;
= 自动缩进当前行;
gg=G 自动缩进整个文本;
=a{ 自动缩进{}内的文本;
va” 选择”"内的文本;
. 重复上一条命令;

如果光标目前在一个字符串的第一个引号上,”blah blah blah”,要删除引号中的内容,就d/”+enter,对删除括号中的内容同理;(update:感谢reus同学, 使用di”命令更简单 ^^ )(update:貌似da”也可以 ^_^)

另外发现vi的很多命令都是有参数的:
>3> 可以让光标下的三行右移一个缩进;
tabn 2 可以切换到第二个tab;
17gg 跳到第17行;
12| 跳到当前行的第12个字符;
8l 右移8个字符,结合gg可以快速定位错误的位置;

update: 感谢ginkgo同学,有时vim在处理中文标点时会发生错位,解决方法就是在~/.vimrc里加上set ambiwidth=double

update: 刚从editplus,notepad++过来的同学有一点可能不大能接受的是,vim不会自动记住配置,重启一下vim又完全复原。而配置.vimrc对新人的门槛又太高。其实有个命令:mkv!,即可自动保存当前的所有配置到.vimrc。不过使用前最好备份一下原先的.vimrc。

Ps:动物园出版社貌似有本《学习vi编辑器》,眼镜猴的封面,感觉不是很全,不过作为入门还是不错的。

haskell中的指针

Posted on 五月 23rd, 2009 in 备忘 | 8 Comments »

标题党了,阿门。其实更像C++,java之类语言中的引用。这就是Data.IORef中的IORef,使用它可以创建真正mutable的变量。

在do-notation中可以写这样的代码:

do {
	…
	x< - return x+1;
}

很像变量,但其实不是真正的mutable,因为它本质上就是(\x -> ..) x+1 ,两个x不在同一个scope,内存中没有值发生改变。

而Data.IORef则是在内存中搞一块地方,提供对这一块内存中输入输出的函数,并通过IO monad将它隔离开,这样就有点真正的变量的意思啦。大致就这几个函数:

newIORef :: a -> IO (IORef a) --创建一个新的IORef(废话~,不过有时也觉得haskell挺”面向对象”的…)
 
readIORef :: IORef a -> IO a
writeIORef :: IORef a -> a -> IO ()

太直白了,一个读一个写,都是IO操作,只不过操作的对象不是标准输入输出,而是内存里的一个值。值得一提的是,haskell的惰性求值让它只有在必要的时候才会读取,这样一来在传递参数的时候就不会访问值所在的内存,就像C中传递一个指针那样节约。唉,发明haskell的那个委员会真是一群天才。

Ps:学习haskell到熟悉基本的语法之后,强烈推荐那个《make yourselves a scheme in 48 hours》的教程!通过用haskell实现一个完整的scheme,对于monad,类型系统的理解绝对会大有好处!

关于副作用

Posted on 五月 9th, 2009 in 笔记 | 7 Comments »

所谓三人成虎,monad就是了。

先烈告诉我们,玩haskell,不用学monad;玩monad,不用学范畴论。当年不懂事啊,正被functor态射范畴这堆鬼东西折磨的半死的时候,突然就骂了出来:“妈的,这还是编程么?数学的拉去见学院派大胡子去!”

嗯,咱是程序员。学院派大胡子去死。嗯。

12Dec06
16:20:11 [Botje] monads have to be the singly most tutorialized feature _EVER_

好吧,这里只谈副作用(不过貌似monad还真避不开)。只是我自己的理解,不保证正确。大牛和小白请直接略过。

纵然大牛们反复重申monad不是为副作用而生,但相信大部分人一定是从IO那里才认识的monad。那么什么才是副作用呢?有个装逼(装纯?)的概念,那就是“引用透明”(reference transparency)。如果拿固定的参数调用一个函数,得到的结果一定是相同的。如果拿相同的参数调用同一个函数两次而得到的结果不一样,那么这个函数就是有副作用的。

如ruby的gets函数,它没有参数,返回一个string。每次执行(参数都是为空)返回的结果不一定一样(决定权在你的输入了),所以说它就没有引用透明。

看下Haskell中getLine函数的类型:

getLine :: IO String

和gets不一样,它返回的类型是IO String而非直接的String。先想一下,如果它的返回类型是String会怎样?你就可以把getLine函数塞到四处都是,可以让每个函数的结果都与输入有关。好吧,引用透明呢?见大胡子去了。

IO是个类型构造子,仅仅是把后面的String包起来。如果你输入“Alpaca”,它就返回IO “Alpaca”。怎样从中取出”Alpaca”来呢?像List,Maybe之类就直接上模式匹配就可以了,而所谓模式匹配就是匹配类型构造子。你可以let (x:xs)=alist\,但不可以let (IO str)=getLine。因为IO类型构造子在模块中没有被导出,换句话说,它是“私有”的,就像OO中把构造函数私有一样,只有那个模块里面的函数才可以访问它。这样一来在外面的你就不能从getLine中取值了。那该怎么办?里面有>>=。它可以把你的操作塞到里面去,可就是不让你从把里面的值带到别处。

getLine >>= (\str -> {-- your operation here--})

在这里>>=的实现大致就是这样(假设>>=只为IO存在):

>>= :: IO a -> (a -> IO b) -> IO b
IO a >>= f = f a

它可以把函数串成一条链,并限制函数f的返回类型必须还得是IO。这样,与外界交互的一切代码就都被迫标上了个IO的标记。不是从外面取值,而是往外面传操作,操作完了再把它包好原样扔回去。而在haskell的纯洁世界中,外面的值是完全无法访问的。