江湖医生一样的程序员

2010年2月25日星期四

Blog 搬家到 Github Pages

** 这里今后将不会更新. 新博客地址是 http://mrluanma.github.com/ **
** 我烧制的两个 Feeds 已经定向到新地址了: **
** http://feeds.feedburner.com/mrluanma **
** http://feed.feedsky.com/mrluanma **

从 [Github Pages][1] 出生那天起我就觉得这家伙很酷, 今天终于从[Scott Chacon's blog][2]那里
git clone 了一套模板过来, 开始正式用 Github Pages 写博客了.

我喜欢 Github Pages. 我觉得它最大的好处就是你只要祭起你最爱的编辑器(¡sɔɐɯǝ ¡sɔɐɯǝ
¡sɔɐɯǝ)就可以写博了, 从此忘掉浏览器的文本框吧. 当然, 你还得有 git, 不过这也绝对是优点,
我总觉得敲键盘的人应该都是版本控才对, 有 git 记录下每个更改不是很好吗?

Github Pages 的背后是[Jekyll][3], Jekyll 生成纯静态的 HTML, 你基本可以部署到任何 Hosting
环境, 比如[Heroku][4].

[1]: http://pages.github.com/
[2]: http://jointheconversation.org/
[3]: http://github.com/mojombo/jekyll/
[4]: http://roylez.github.com/2010/02/04/jekyll-on-heroku.html

2010年2月14日星期日

用 PXE 引导方式安装 Ubuntu 8.04 LTS 服务器流水账

File: install-ubuntu-8.04-server-with-pxe.txt -*- Encoding: utf-8 -*-
Time-stamp: <luanma 02/14/2010 00:56:02>

用 PXE 引导方式安装 Ubuntu 8.04 LTS 服务器流水账

过春节了, 弄了个古董 PC 回家鼓捣鼓捣(我觉得吧什么
BT 机啊, 路由器啊, 还是 PC 最好玩). 那先得整个
Linux 系统装上啊, 但机器没有软驱, 没 CD-ROM, 弄个
DVD-RW 接上 BIOS 不认, 不支持 USB 引导, 硬盘上也没
个可以引导的系统, 折腾了半天反正系统是没装上去, 正
愁着呢, 后来发现主板支持 PXE[1] 引导, 一试, 挺顺利,
现在把过程记录一下.

首先下载 Ubuntu 8.04 LTS server 版的 ISO 文件
ubuntu-8.04.4-server-i386.iso, 选择这个版本是因为
它是 LTS 版本, 可以有更久的官方更新维护支持.

然后因为我家里另外一台电脑是 Windows XP 系统笔记本,
所以得整个 Windows 下的 TFTP 服务器, 这个
tftpd32[2] 真是简单又好用, 下载
http://tftpd32.jounin.net/download/tftpd32.335.zip
解压运行 tftpd32.exe 即可.

运行之后设置 tftpd32.exe 的 Current Directory 为
C:\TFTPD\(可按自己喜好设置), 然后切换到 "DHCP
server" 标签, 设置如下(这是我路由器的 IP, 可能需要
根据你的实际情况作相应的更改):

IP pool starting address: 192.168.1.100
Size of pool: 10
Boot file: /pxelinux.0
WINS/DNS server: 8.8.8.8
Default router: 192.168.1.1
Mask: 255.255.255.0
其它的设置项不用修改, 然后按"save"按钮. 我还准备
了截图一张.

如果你的路由器开了 DHCP, 那么您需要关闭它, 我用的
是 TP-Link 的 WR-150G+, 用 Web 界面关掉 DHCP 之后,
需要重启路由器才能生效, 本本上运行着 tftpd32 的
DHCP 服务器, 无线能正常连接, 刚开始提示连接受限制,
但是很快就可以从 tftpd32 的 DHCP 服务器上拿到分配
到的 IP, 192.168.1.100.

准备做的差不多了, 剩下最后一步, 解压
ubuntu-8.04.4-server-i386.iso 里的
install\netboot\ubuntu-installer\i386\ 目录到
C:\TFTPD\ 文件夹下, 用你喜欢的编辑器打开
C:\TFTPD\pxelinux.cfg\default 文件, 删除所有的
"ubuntu-installer/i386/"(引号内内容), 保存退出.

把古董机开机, 按 F12 选择 Network boot, 很顺利地进
入安装程序, 因为所有的东西都是从因特网上下载, 所以
想顺利安装还得有因特网连接, 并且速度不要太慢, 否则
有得等了. 建议就用英文安装, 并且引导的时候输入
"cli"只安装基本命令行系统, 这样可以少下点东西.

整个过程其实挺简单, 不过是我第一次弄, 所以可能有点
想的复杂了. 半个春晚的功夫, 我的机器顺利装上了,
取名叫做 ma10t.

1. http://en.wikipedia.org/wiki/Preboot_Execution_Environment
2. http://tftpd32.jounin.net/

2010年2月12日星期五

random bits

File: hello.txt -*- Encoding: utf-8 -*-
Time-stamp: <luanma 02/12/2010 09:23:40>

Feb 4, 2010 Being youthful at the time I figured I could design and
implement a language --Guido van Rossum
Feb 4, 2010 Converting an algorythm from recursion to different kind
of stack is pretty easy and I suggest you try that. Here is how you
can do it.

def recursive(params)
if some_conditions(params)
recursive(update_params(params))
end
end

recursive(starting_params)
will transform into

stack = [starting_params]
while !stack.empty?
current_params = stack.delete_at(0)
if some_conditions(current_params)
stack << update_params(current_params)
end
end
Feb 4, 2010 RT @jesusai 和一政法学弟聊天,我说"在司法不独立的社会你学
法律有什么用?",他说"以后你不也还就是个局域网从业者"
Feb 4, 2010
function f() return f() end f() --tail recursion
function c() c() end c() --stack overflow
Feb 4, 2010
# stack overflow in Ruby
irb(main):001:0> def s;s;end;s
SystemStackError: stack level too deep
Feb 4, 2010 Read this line, and do what it says twice. --recursion
Feb 4, 2010
template <int i>
class Overflow {
typedef typename Overflow<i + 1>::type type;
};

typedef Overflow<0>::type Kaboom;
Feb 4, 2010
Python:

so=lambda:so();so()

Alternatively:

def so():so()
so()

And if Python optimized tail calls...:

o=lambda:map(o,o());o()
Feb 4, 2010
bash in 10 chars (the space in the function is important):

i(){ i;};i
Feb 4, 2010
(defun x () (1+ (x))) (x)
(error "Lisp nesting exceeds `max-lisp-eval-depth'")
Debugger entered--Lisp error: (error "Lisp nesting exceeds
`max-lisp-eval-depth'")
Feb 4, 2010
In Scheme, this will cause the interpreter to run out of memory:

(define (x)
((x)))

(x)
Feb 4, 2010
Haskell:

let x = x
print x
Feb 4, 2010
a{return a*a;};
Compile with:

gcc -D"a=main()" so.c
Expands to:

main() {
return main()*main();
}
Feb 4, 2010
(a=lambda{a.call}).call
Feb 4, 2010
(new function() { arguments.callee();});
Feb 4, 2010
Perl in 10 chars

sub x{&x}x
Eventually uses up all available memory.
Feb 4, 2010
MS-DOS batch:

copy CON so.bat
so.bat
^Z
so.bat
Feb 4, 2010
class Overflow
def initialize
Overflow.new
end
end

Overflow.new
Feb 12, 2010
For example, to rename all the "v2_*.rb" files to "v3_*.rb" I would type:

for file in *; do mv "$file" "v3_${file#v2_}"; done

2010年2月5日星期五

Quidway AR28-11 路由器内网PC通过公网IP访问映射的内网SERVER案例

File: QuidwayAR28-11-router-nat-configuration-demo.txt -*- Encoding: utf-8 -*-
Time-stamp: <luanma 02/05/2010 17:08:42>

Quidway AR28-11 路由器内网PC通过公网IP访问映射的内网SERVER案例

问题描述
=======

拓朴如上图,内网PC与内网所在的SERVER在同一个网段,
现在内网SERVER对公网用户提供WWW和FTP服务,在公网上
有相应的域名。现在要求内网PC可以同时通过公网域名、
公网IP和私网IP来访问内网的这台SERVER。

过程分析
=======

内网主机通过公网域名来访问映射的SERVER在AR路由器上
都是通过NAT DNS-MAP来实现的,但不能同时通过公网IP
和私网IP来访问SERVER。如果在设备内网口配置NAT
SERVER则可以把访问公网地址转换成私网地址,然后向
SERVER发起连接,但源地址还是内网主机的地址,此时
SERVER给PC回应报文时就不会走路由器,直接发到了内网
PC上,内网PC认为不是自己要访问的地址,会把这个报文
丢弃,因此会导致连接中断。如果让SERVER把报文回给路
由器,路由器再根据NAT SESSION就可以正确转发给PC了。

解决方法
=======

在内网接口配置一个NAT OUTBOUND 3000就可以了。具体
配置如下:

[H3C]dis cu
#
sysname H3C
#
clock timezone gmt+08:004 add 08:00:00
#
cpu-usage cycle 1min
#
connection-limit disable
connection-limit default action deny
connection-limit default amount upper-limit 50 lower-limit 20
#
web set-package force flash:/http.zip
#
radius scheme system
#
domain system
#
local-user admin
password cipher .]@USE=B,53Q=^Q`MAF4<1!!
service-type telnet terminal
level 3
service-type ftp
#
acl number 2000
rule 0 permit source 192.168.1.0 0.0.0.255
rule 1 deny
#
acl number 3000
rule 0 permit ip source 192.168.1.0 0.0.0.255 destination 192.168.1.2 0
#
interface Aux0
async mode flow
#
interface Ethernet1/0
ip address 192.168.1.1 255.255.255.0
nat outbound 3000
nat server protocol tcp global 200.0.0.2 ftp inside 192.168.1.2 ftp
#
interface Ethernet1/1
#
interface Ethernet1/2
#
interface Ethernet1/3
#
interface Ethernet1/4
#
interface Ethernet1/5
#
interface Ethernet1/6
#
interface Ethernet1/7
#
interface Ethernet1/8
#
interface Ethernet2/0
ip address 200.0.0.2 255.255.255.0
nat outbound 2000
nat server protocol tcp global 200.0.0.2 ftp inside 192.168.1.2 ftp
#
interface Ethernet3/0
#
interface NULL0
#
FTP server enable
#
ip route-static 0.0.0.0 0.0.0.0 200.0.0.1 preference 60
#
user-interface con 0
user-interface aux 0
user-interface vty 0 4
authentication-mode scheme
#
return
[H3C]

说明
===

1. 本案例适用于R系列、AR系列、MSR系列路由器,secpath防
火墙。
2. R系列路由器在使用此案例时内网口需要undo ip
fast-forwarding,并且在使用FTP映射时,客户端只能使
用主动模式去访问。

TL-WR340G+ 和 TL-WR841N 无线桥接的配置

File: TP-LINK-TL-WR340G+-TL-WR841N-wireless-bridge.txt -*- Encoding: utf-8 -*-
Time-stamp: <luanma 02/05/2010 16:48:12>

TL-WR340G+ 和 TL-WR841N 无线桥接的配置

我住同一个小区的亲戚家安装了宽带, 我买了个
TL-WR841N(180RMB) 放他家, 想蹭宽带用用. 配置好了
之后发现信号不够强, 只有靠窗户的位置才能有两个信号,
时不时的还掉个线啥的, 真是不舒服, 我就准备再买个无
线路由器放我家窗口的位置, 做一个无线桥接, 这样就在
我家任何一个角落都能舒服地蹭网了. 出于价格考虑,
这次买了便宜一点的 TL-WR340G+(120RMB), 折腾了一段
时间, 最后把两个路由器的位置调换(也就是 TL-WR841N
放我家窗户的位置, 然后 TL-WR340G+ 放亲戚家), 先在
亲戚家的 TL-WR340G+ 上设置好宽带上网, 启用无线, 设
置好无线密码(注意: 请设置高安全等级加密方
法:WPA-PSK/WPA2-PSK安全类型,AES加密算法,有效防
止蹭网。详细请看:
http://www.tp-link.com.cn/pages/article-detail.asp?result=faq&d=33)
然后修改"无线网络基本设置"--"信道"为2(注意: 信道要
和桥接的另外一个路由器一致), 然后我们的第一个路由
器就设置完了. 然后设置 TL-WR841N, 首先关闭 DHCP
服务, 然后修改 LAN 口地址为 192.168.0.2, 然后就可
以设置无线桥接了, 在 TL-WR841N 的 Web 管理界面"无
线设置"--"基本设置", 开启 WDS, 扫描到 TL-WR340G+
的 SSID 号及 MAC 地址, 选择 TL-WR340G+ 上设置的无
线密码类型并输入密码, 注意两个无线路由器的信道需要
保持一致, 保存并重启路由器即可.

我的技术有用论观以及对 Web 架构的浅显认识

File: web-architecture.txt -*- Encoding: utf-8 -*-
Time-stamp: <luanma 02/05/2010 15:16:40>

在一个封闭的小圈子里讨论 Web 架构的时候, 我"突发奇
想"将一小段内容发到 twitter 上:

> 并且大部分的网站都不需要 Google 级别的负载, 所以
对于大部分开发者, 创业者来说, "架构"都是最最不重
要的事情, 做出好产品, 伺候好用户, 赚到钱才是真的.

然后 @xmpp 认为我这是"技术无用论", 我也做了一些解
释. 现稍作整理, 权充博文一篇.

可能我的表达的确存在一些让人误解的地方. 以下是我
说那句话的上下文.

> 昨天上网不小心看到了一些关于网站架构的讨论:有人
说将WEB站点用独立的方式,也就是静态页面放到一服
务器,动态页面放一服务器,图片放另一服务器,用它
们组起来作为一个站点,这样会加快浏览速度。

> 请问这样的原理是怎样的??我真的不解!

一般静态页面和图片可以当做一种东西处理, 和动态页面
比起来肯定少耗费 CPU, 动态页面的话肯定会比较费
CPU, memcache 专耗内存, DB 基本上整体负载都很高,
所以如果你有一堆机器要"架构"的话, 肯定需要在 CPU,
内存, IO 这三方面来均衡着排布. 比如 memcache 耗内
存不耗 CPU, 那就可以把动态页面放 memcache 的机器上
一起跑, DB 啥都耗就自己占整个机器跑, 静态文件这些
就直接让反向代理的 web 服务器来跑.

以上讲的是物理机器上的分隔, 其实为了提高访问速度,
一般在 URL 上也要做文章. 因为浏览器 HTTP 协议同时
只对一个域名的机器发起最多两个连接, 比如我打开一个
动态页面, 这个动态页面里用到 20 个静态文件, 那如果
这些文件都是用两个水管来放的话, 是不是没有我同时用
N*2 根水管来放快? 所以一般网站就算只有一台机器提
供全部内容, 也会把静动态内容放到不同的二级域名下来
提供, 比如说一般的内容用 website.com 来提供, 静态
文件就就用 static.website.com 来提供, 这样浏览器就
可以向 website.com 发起两个连接要东西, 同时也可以
static.website.com 发起两个连接要静态文件.

> 没懂,啥叫水管?

其实我说的时候我就感觉没说清楚, 我这里一个水管的意
思就是一个 TCP 连接.

我找找别人解释的更清楚的:

http://blog.joycode.com/musicland/archive/2005/04/16/48690.aspx
相关的引用如下:

"在HTTP 1.1 Spec 中针对 Persistent Connections 提
出了这样的 Practical considerations:Clients that
use persistent connections SHOULD limit the number
of simultaneous connections that they maintain to
a given server. A single-user client SHOULD NOT
maintain more than 2 connections with any server
or proxy. A proxy SHOULD use up to 2*N connections
to another server or proxy, where N is the number
of simultaneously active users. These guidelines
are intended to improve HTTP response times and
avoid congestion.

以上内容表明,为了提高HTTP响应时间以及避免产生网络
堵塞,HTTP连接中的客户端不应该与服务器端建立超过2
个的HTTP连接。如果有更多的请求需要,那么这些请求将
被pipeline到这两个HTTP连接之中,并以异步的方式传送
给服务器端。举个例子:有上百辆汽车(requests)想从
天津开往北京,但是天津与北京之间最多只允许修建两条
公路(HTTP connection),因此这些汽车要想从天津驶
往北京的话,就只能走这两条公路。"

http://lvmlvy.javaeye.com/blog/581447
这篇很详细, 内容都挺好, 我就不摘录了, 建议都看看

忘了说一句, 我是山寨的, 只是看了一堆各个网站的架构,
并没有大型 Web 运营经验, 并且我估计很长时间内也不
会有这样的事情做. *并且大部分的网站都不需要 Google
级别的负载, 所以对于大部分开发者, 创业者来说, "架
构"都是最最不重要的事情, 做出好产品, 伺候好用户,
赚到钱才是真的.*

以下是 twitter 上的讨论:

@xmpp

RT: @mrluanma: 大部分的网站都不需要 Google 级别的
负载, 所以对于大部分开发者, 创业者来说, "架构"都是
最最不重要的事情, 做出好产品,伺候好用户, 赚到钱才
是真的 // 技术无用论。看你站的角度,如站在孔子学院
网站角度,"做出好产品"也是很不重要的

@mrluanma(我自己)

RT: @xmpp RT: @mrluanma: 大部分的网站都不需要
Google 级别的负载... // 技术无用论。看你站的角度,
如站在孔子学院网站角度,"做出好产品"也是很不重要
的 //我绝对不认为技术无用, 我说的是大部分网站不需
要担心架构问题, 至少在早期不用.

@xiaoxiaolu

非技术无用论,是产品导向,等有负载再解决是务实做
法,换个角度也可以说为啥你丫不进大公司?我已见过不
止一家公司做完技术就准备倒闭 RT @xmpp: RT:
@mrluanma: 对于大部分开发者, 创业者, 架构是最最不
重要的事情, 做出好产品,伺候好用户// 技术无用论。

@nepalon

@mrluanma 市场导向的话对处于生存期的公司比较合适,
只要迎合市场,功能不算太烂,一般都可以有市场。但要
进一步发展就要提高技术了,有了更好的技术,才能提高
性能、提高用户体验、提高自己的行业中的地位。我们的
做法是通过销售来发掘市场,从而根据市场来开发产品、
做技术储备。

@mrluanma

RT @nepalon: 因为我本身就是做开发的, 我觉得把市场
看的比架构重是我的一个突破, 当然, 要长远发展, 如果
有技术负债, 也肯定是要还的. 这两天用到的产品体验中,
360buy, 邮政的EMS查询, 移动的号薄管家这些的技术负
债我觉得都比较严重.

2010年2月4日星期四

random bits

Jul 30, 2009 在此 GNU Emacs 23 正式发布之良辰吉日, 把 Windows 机器上的
Emacs 从 ntemacs 23 更换成 GNU Emacs 23.1.1. 希望 Aquamacs 早日升级.
Jul 30, 2009 有人说 Emacs 版本号大, 关键是年纪在那里摆着呢, 单说 GNU
Emacs 都比我.
Jul 30, 2009 Natter: XMPP library, Computer to computer via XMPP, IQ
Only.
Aug 3, 2009 wikipedia备份数据下载
http://download.wikimedia.org/backup-index.html
Aug 12, 2009 Beta Reduction is a transformation of the Lambda
Calculus(LC). LC is the mathematical foundation of all LISPy
language.
Aug 14, 2009 在安装 php-5.3.0-Win32-VC9-x86 时发现, VC 2008 编译出来的
程序需要安装相应的 Microsoft Visual C++ 2008 Redistributable Package,
否则会报"由于应用程序配置不正确, 应用程序未能启动"的错误.
Aug 14, 2009 Github Pages 简直是最帅的 BSP 了吧.
Aug 16, 2009 Reviewed SilverStripe, Joomla, Exponent, Jaws, ImpressCMS
CMS written in PHP.
Aug 16, 2009 Microsoft Web Platform Installer is pretty cool!
http://www.microsoft.com/web/
Aug 16, 2009 Plone 有非常优秀的 UI, 不过基于 PHP 的 CMS 有非常好的
hosting 环境.
Aug 16, 2009 SilverStripe rewrite rule for nginx:
if (!-f $request_filename) {
rewrite ^/(.*?)(\?|$)(.*)$ /sapphire/main.php?url=$1&$3 last;
}
Aug 17, 2009 SilverStripe 有最 AJAX 的 UI, Drupal 有最可扩展的架构.
Aug 17, 2009 It is bound to M-m. (back-to-indentation) Move point to
the first non-whitespace character on this line.
Aug 17, 2009 taskkill /f /im nginx.exe
Aug 17, 2009 Reviewed pivotx blog engine, looks good!
Aug 18, 2009 Drupal rewrite rule for nginx:
if (!-f $request_filename) {
rewrite ^/(.*)$ /index.php?q=$1 last;
}
Sep 3, 2009 Java Platform 里除了 Java 语言外还真不错, JRuby 让 Rails
有了更广阔的部署空间和一大堆的库可以用, 刚看一个演示在 JBoss 应用服务
器上部署 Rails App, 真是简单到不能再简单了. 该演示提到 Drools 规则引
擎, Ruby 里据我所知是没有这么成熟度的规则引擎库的. 这两天对 JVM 上的
语言 Clojure 也蛮来电.
Jan 22, 2010 On the other hand, the CS curriculum really is
critical. Learning it would save you from inventing PHP, which would
be a huge benefit to mankind. --David Chapman
Jan 22, 2010 First of all, he really was looking at the Symbolics
code; we caught him doing it several times. But secondly, even if he
hadn't, it's a whole lot easier to copy what someone else has
already designed than to design it yourself. --Dan Weinreb
Jan 22, 2010 By following a proprietary model, symbolics (and lmi)
doomed lisp machines. Doomed in much the same way, though a different
market, as Amiga and BeOS. The only surviving lisp machine is RMS'
emacs VM. --Paddy Murphy
Jan 22, 2010 In fact there is plenty of evidence that supports
Mr. Chapman's point that most of the influential programs are
produced by amateurs.

Take Altair Basic, MS-DOS, and Windows. Neither Gates nor Allen had
formal education in computer science when they released these
products. They wouldn't probably worked on them if they had.

Another evidence is Linux. Linus Torvalds started university in 1988,
first released Linux in 1991 and got his degree in 1996. He originally
developed the Linux kernel as a hobby OS.

Richard Gabriel has a good analysis on that. --Kamen Tomov
Jan 25, 2010 The third principle is that web.py should, by default, do
the right thing by the Web. This means distinguishing between GET and
POST properly. It means simple, canonical URLs which synonyms redirect
to. It means readable HTML with the proper HTTP headers. --Aaron Swartz
Jan 26, 2010 昨晚看法制频道在给贵州黎平县的法院执行人员歌功颂德, 但是
他妈的他们执行的是个什么案件啊, 一个喝了酒的小年青用打火机点燃了加油站
漏出流到水沟里的汽油, 烧了十户人家的房子, 结果这个小青年承担 70% 的责
任, 判刑 10 年, 赔款 15 万, 加油站一方承担 30% 责任, 这他妈这是法律吗?
Jan 27, 2010
# echo {a..t}
a b c d e f g h i j k l m n o p q r s t

for in in `echo {a..t}`; do wget http://host/file${i}.zip; done
Jan 29, 2010 Since coroutines can have more points of entry and exit
than subroutines, it is possible to implement any subroutine as a
coroutine. "Subroutines are special cases of ... coroutines." —Donald
Knuth
Jan 29, 2010 An example of a generator returning the Fibonacci numbers
using Python's yield statement can be seen below.

def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a+b

for number in fibonacci(): # Use the generator as an iterator
print number
Jan 29, 2010
A lock can be built using an atomic test-and-set instruction as follows:
function Lock(boolean *lock) {
while (test_and_set (lock) == 1)
;
}
Jan 29, 2010
In mathematics, a multiset (or bag) is a generalization of a set.
Jan 29, 2010
Perhaps the simplest persistent data structure is the singly-linked
list or cons-based list, a simple list of objects formed by each
carrying a reference to the next in the list.
Jan 29, 2010
preorder(node)
print node.value
if node.left ≠ null then preorder(node.left)
if node.right ≠ null then preorder(node.right)
inorder(node)
if node.left ≠ null then inorder(node.left)
print node.value
if node.right ≠ null then inorder(node.right)
postorder(node)
if node.left ≠ null then postorder(node.left)
if node.right ≠ null then
print node.value
Jan 29, 2010
levelorder(root)
q = empty queue
q.enqueue(root)
while not q.empty do
node := q.dequeue()
visit(node)
if node.left ≠ null
q.enqueue(node.left)
if node.right ≠ null
q.enqueue(node.right)
Feb 2, 2010
RT @vvchn: 生于八零年代,承蒙时代错爱.屡遇砖家教改,深受思想渎害.苦读十
年八载,举家艰难负债.文凭贬值太快,大学亏本买卖.应聘人山人海,创业缺乏人
脉.都市雨淋日晒,无处安营扎寨.郊县觅得住宅,辛苦打工还贷.理想就地掩埋,现
实金钱崇拜.人生犹如竞赛,不敢丝毫懈怠.偶尔自怨自艾,感叹青春不再.
Feb 2, 2010
Features of a programming language, whether syntactic or semantic, are
all part of the language's user interface. And a user interface can
handle only so much complexity or it becomes unusable. This is also
the reason why Python will never have continuations, and even why I'm
uninterested in optimizing tail recursion. --Guido
Feb 2, 2010
http://stackoverflow.com/questions/429995/how-do-c-and-c-store-large-objects-on-the-stack
Feb 2, 2010
http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap
Feb 2, 2010
http://stackoverflow.com/questions/1294756/queue-that-uses-a-stack

Take two stacks, in and out.

To enqueue an element, push it on stack in.
To dequeue an element, pop an element from stack out if out is not
empty; otherwise, pop and push all elements from in to out, then serve
the top element of out.

It is important that you perform step 2 only if necessary. Note that
enqueue has complexity O(1), and dequeue has amortized complexity
O(1), provided your implementations of pop and push are O(1).
Feb 2, 2010
stacks for threads are often smaller. You can change the default at
link time, or change at run time also. For reference some defaults
are:

glibc i386, x86_64 7.4 MB
Tru64 5.1 5.2 MB
Cygwin 1.8 MB
Solaris 7..10 1 MB
MacOS X 10.5 460 KB
AIX 5 98 KB
OpenBSD 4.0 64 KB
HP-UX 11 16 KB
Feb 3, 2010
The code from __future__ import braces raises the exception
SyntaxError: not a chance.
Feb 3, 2010
In computer science, manifest typing is when the software programmer
explicitly identifies the type of each variable being declared. For
example: if variable X is going to store integers then its type must
be declared as integer.

In contrast, some programming languages use implicit typing (aka. type
inference) where the type is deduced from context or allow for dynamic
typing in which the variable is just declared and may be assigned a
value of any type at runtime.
Feb 3, 2010
HipHop for PHP: Move Fast --Haiping Zhao
Feb 4, 2010
这年头——

到处都是错别字:植树造零,白收起家,勤捞致富,选霸干部,任人为闲,择油
录取,得财兼币,检查宴收,大力支吃,为民储害,提钱释放,攻官小姐。

2010年2月3日星期三

random bits

Dec 31, 2007
(let* ((yin ((lambda (foo) (newline) foo)
(call-with-current-continuation (lambda (bar) bar))))
(yang ((lambda (foo) (write-char #\*) foo)
(call-with-current-continuation (lambda (bar) bar)))))
(yin yang))
Dec 31, 2007
dc -e 9534175522489273769672731388983542309678957P
Jan 15, 2008
ASDF is to Lisp what Make is to C.
Jan 16, 2008
Common Lisp's FORMAT function is--along with the extended LOOP
macro--one of the two Common Lisp features that inspires a strong
emotional response in a lot of Common Lisp users. Some love it; others
hate it.^1
Jan 16, 2008
CL-USER> (format nil "~:d" 100000000)
"100,000,000"
CL-USER> (format nil "~,,'.,4:d" 100000000)
"1.0000.0000"
Jan 16, 2008
CL-USER> (format nil "~R file~:P" 1)
"one file"
CL-USER> (format nil "~R file~:P" 11)
"eleven files"
Jan 16, 2008
(format nil "~{~a~^, ~}" (list 1 2 3))
CL-USER> "1, 2, 3"
Jan 16, 2008
CL-USER> (format nil "~{~s~*~^ ~}" '(:a 10 :b 20))
":A :B"
Jan 16, 2008
(tagbody
a (print 'a) (if (zerop (random 2)) (go c))
b (print 'b) (if (zerop (random 2)) (go a))
c (print 'c) (if (zerop (random 2)) (go b)))
Jan 16, 2008
CL-USER> '(((((((((((((((((((((((((((())))))))))))))))))))))))))))
(((((((((((((((((((((((((((NIL)))))))))))))))))))))))))))
Jan 16, 2008
CL-USER> (setf (values *x* *y*) (floor (/ 57 34)))
1
23/34
Jan 16, 2008
CL-USER> (cl:defparameter *passwd* (sb-posix:getpwuid
(sb-posix:getuid)) "REPL generated global variable.")
*PASSWD*
CL-USER> (loop for s in '("dir" "gecos" "gid" "name" "passwd" "shell"
"uid") collect
(let* ((symbol-name (string-upcase (concatenate 'string "passwd-" s)))
(func (find-symbol symbol-name (find-package :sb-posix))))
(when func
(funcall func *passwd*))))
("/home/luanma" "Xiaohong Zhao,,," 1000 "luanma" "x" "/bin/bash" 1000)
Jan 17, 2008
CL-USER> (cl:defparameter *random* (loop repeat 1000 collect (random
1000)) "REPL generated global variable.")
*RANDOM*
CL-USER> (loop for r in *random*
counting (oddp r) into odds
counting (evenp r) into evens
summing r into sum
maximizing r into max
minimizing r into min
finally (return (list odds evens sum max min)))
(494 506 516910 998 0)
Jan 17, 2008
CL-USER> (loop 'hello)
Jan 17, 2008
The function LDB,
whose name stands for load byte, can be used to extract and set (with
SETF) any number of contiguous bits from
an integer.
Jan 18, 2008
If your program gets this function name 'from outside', you'd
better make very sure that you're not funcalling the function
FORMAT-MY-HARD-DRIVE-AND-SEND-SOME-MISSILES-TO-CHINA...
Feb 11, 2008
Lighty & nginx
Feb 11, 2008
static long binary_decode(const char *s) {
long x=0;

while(*s!=0 && (*s=='1' || *s=='0')) {
x<<=1;
x+=*s-'0';
s++;
}

return x;
}
Feb 15, 2008
_, space_count = string.gsum(s, " ", " ")
Feb 15, 2008
s = "Deadline is 30/05/1999, firm"
date = "%d%d/%d%d/%d%d%d%d"
print(string.sub(s, string.find(s, date)))
Feb 15, 2008
pair = "name = value"
_, _, key, value = string.find(pair, "(%a+)%s*=%s*(%a+)")
print(key, value)
Feb 15, 2008
date = '17/7/1999'
_, _, d, m, y = string.find(date, "(%d+)/(%d+)/(%d+)")
print(d, m, y)
Feb 15, 2008
s = [[then he said: "that's all right!"]]
_, _, c, quotedPart = string.find(s, "([\"'])(.-)%1")
print(quotedPart)
print(c)
Feb 15, 2008
print(string.gsub("hello, lua!", "(%a)", "%1-%1"))
Feb 15, 2008
print(string.gsub("hello, lua!", "(.)(.)", "%2%1"))
Feb 15, 2008
function trim (s)
return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end
Feb 16, 2008
-- typical usage: lua -e N=1000 sieve.lua | column
Feb 17, 2008
Check: A unit test framework for C programs.
Feb 17, 2008
NAME
tree - list contents of directories in a tree-like format.
Feb 17, 2008
$ autoreconf --install
$ ./configure
$ make

(`autoreconf' determines which commands are needed in order for
`configure' to be created or brought up to date. Previously one would
use a script called `autogen.sh' or `bootstrap', but that practice is
unnecessary now.)
Feb 21, 2008
plugin_LTLIBRARIES = guile.la
guile_la_SOURCES = guile.c
guile_la_CFLAGS = $(GUILE_CFLAGS) $(GLIB2_CFLAGS)
guile_la_LDFLAGS = -avoid-version -module
guile_la_LIBADD = $(GUILE_LDFLAGS) $(GLIB2_LIBS)
Feb 21, 2008
dnl Check for guile
GUILE_FLAGS
GUILE_SITE_DIR
Feb 21, 2008
dnl Check for glib2
PKG_CHECK_MODULES(GLIB2,glib-2.0 >= 2.4
gthread-2.0,HAVE_GLIB2=yes,HAVE_GLIB2=no)
AC_SUBST(GLIB2_LIBS)
AC_SUBST(GLIB2_CFLAGS)

if test "x$HAVE_GLIB2" = "xno"; then
AC_MSG_ERROR([XChat Guile requires GLib2 to compile.])
fi
Feb 21, 2008
AUTOMAKE_OPTIONS = dist-bzip2 dist-zip
Feb 21, 2008
What is SunUO?
--------------

SunUO is a free Ultima Online server, based on RunUO.


Getting SunUO
-------------

You can download SunUO on the home page:

http://www.sunuo.org/
Feb 21, 2008
To generate the project files you must download premake 3.1 from:
http://sourceforge.net/project/showfiles.php?group_id=71616
and place the executable (premake.exe) in this directory.

First you should edit config.lua to make sure you get what you need.

After this is done you should run the .bat files corresponding to your version
of 'Microsoft Visual C++' (MSVC). This will generate a solution in
this directory.

You can run clean.bat to clean up the project files in case you want to switch
to another version of MSVC.
Feb 21, 2008
# Checks for libraries.
AC_CHECK_LIB([dl], [main])
AC_CHECK_LIB([pthread], [main],, AC_MSG_ERROR([cannot find pthread library]))

PKG_CHECK_MODULES(freetype2, freetype2 >= 0.15.0)
AC_SUBST(freetype2_CFLAGS)
AC_SUBST(freetype2_LIBS)

PKG_CHECK_MODULES(pcre, libpcre >= 5.0)
AC_SUBST(pcre_CFLAGS)
AC_SUBST(pcre_LIBS)
Feb 21, 2008
AM_INIT_AUTOMAKE([1.9 no-dist-gzip dist-bzip2])
Feb 22, 2008
AC_CANONICAL_HOST
Feb 22, 2008
gettextize
Feb 22, 2008
make tags
Feb 24, 2008
latex-cjk-chinese-arphic-bkai00mp
latex-cjk-chinese-arphic-bsmi00lp
latex-cjk-chinese-arphic-gbsn00lp
latex-cjk-chinese-arphic-gkai00mp
Feb 25, 2008
fibs :: [Int]
fibs = 0 : 1 : [ a + b | (a, b) <- zip fibs (tail fibs)]
Feb 25, 2008
For OCaml, use tuareg-mode
Feb 26, 2008
iota count [start step]
This procedure takes its name from the APL primitive.
Feb 26, 2008
(let loop () (loop))
Feb 26, 2008
(let loop () (begin (sleep 2) (loop)))
Feb 26, 2008
(pp
(map (lambda (n)
(let* ((str (make-string n #\g))
(url (string-append str ".com")))
(cons url (host url)))) (iota 38 2)))

(("gg.com" . "80.93.161.15")
("ggg.com" . "66.98.154.24")
("gggg.com" . "67.18.104.18")
("ggggg.com" . "82.98.86.161")
("gggggg.com" . "216.102.246.27")
("ggggggg.com" . "209.85.84.167")
("gggggggg.com" . "72.51.27.51")
("ggggggggg.com" . "72.51.27.51")
("gggggggggg.com" . "208.73.212.12")
("ggggggggggg.com" . "72.30.33.102")
("gggggggggggg.com" . "72.30.33.102")
("ggggggggggggg.com" . "72.30.33.102")
("gggggggggggggg.com" . "72.30.33.102")
("ggggggggggggggg.com" . "72.30.33.102")
("gggggggggggggggg.com" . "69.46.228.45")
("ggggggggggggggggg.com" . "72.51.27.51")
("gggggggggggggggggg.com" . "72.51.27.51")
("ggggggggggggggggggg.com" . "66.45.254.245")
("gggggggggggggggggggg.com" . "72.51.27.51")
("ggggggggggggggggggggg.com" . "72.51.27.51")
("gggggggggggggggggggggg.com" . "66.45.254.244")
("ggggggggggggggggggggggg.com" . "72.51.27.51")
("gggggggggggggggggggggggg.com"
.
"208.73.212.12")
("ggggggggggggggggggggggggg.com"
.
"69.46.228.41")
("gggggggggggggggggggggggggg.com"
.
"8.15.231.215")
("ggggggggggggggggggggggggggg.com"
.
"72.51.27.51")
("gggggggggggggggggggggggggggg.com"
.
"208.73.212.12")
("ggggggggggggggggggggggggggggg.com"
.
"72.51.27.51")
("gggggggggggggggggggggggggggggg.com"
.
"8.15.231.215")
("ggggggggggggggggggggggggggggggg.com"
.
"216.188.26.235")
("gggggggggggggggggggggggggggggggg.com"
.
"8.15.231.214")
("ggggggggggggggggggggggggggggggggg.com"
.
"8.15.231.219")
("gggggggggggggggggggggggggggggggggg.com"
.
"216.188.26.235")
("ggggggggggggggggggggggggggggggggggg.com"
.
"38.97.225.135")
("gggggggggggggggggggggggggggggggggggg.com"
.
"66.45.254.245")
("ggggggggggggggggggggggggggggggggggggg.com"
.
"216.188.26.235")
("gggggggggggggggggggggggggggggggggggggg.com"
.
"69.46.228.56")
("ggggggggggggggggggggggggggggggggggggggg.com"
.
"8.15.231.213"))
#unspecified
Feb 27, 2008
"Class precedence list" is often abbreviated, in documentation and
Scheme variable names, to "cpl".
Feb 27, 2008
Description: Enhanced Implementation of Emacs Interpreted Objects
EIEIO is an Emacs lisp program which implements a controlled
object-oriented programming methodology following the CLOS
standard. EIEIO also has object browsing functions, and custom widget
types. It has a fairly complete manual describing how to use it.
.
EIEIO is now a part of CEDET (Collection of Emacs Development
Environment Tools).
Feb 27, 2008
EIEIO is a CLOS (Common Lisp Object System) compatibility layer.
Feb 28, 2008
(define-class <complex> (<number>)
(r #:init-value 0 #:getter get-r #:setter set-r! #:init-keyword #:r)
(i #:init-value 0 #:getter get-i #:setter set-i! #:init-keyword #:i))
Feb 28, 2008
(define-class <complex> (<number>)
(r #:init-value 0 #:accessor real-part #:init-keyword #:r)
(i #:init-value 0 #:accessor imag-part #:init-keyword #:i))
Feb 28, 2008
(define-class <complex> (<number>)
;; True slots use rectangular coordinates
(r #:init-value 0 #:accessor real-part #:init-keyword #:r)
(i #:init-value 0 #:accessor imag-part #:init-keyword #:i)
;; Virtual slots access do the conversion
(m #:accessor magnitude #:init-keyword #:magn
#:allocation #:virtual
#:slot-ref (lambda (o)
(let ((r (slot-ref o 'r)) (i (slot-ref o 'i)))
(sqrt (+ (* r r) (* i i)))))
#:slot-set! (lambda (o m)
(let ((a (slot-ref o 'a)))
(slot-set! o 'r (* m (cos a)))
(slot-set! o 'i (* m (sin a))))))
(a #:accessor angle #:init-keyword #:angle
#:allocation #:virtual
#:slot-ref (lambda (o)
(atan (slot-ref o 'i) (slot-ref o 'r)))
#:slot-set! (lambda(o a)
(let ((m (slot-ref o 'm)))
(slot-set! o 'r (* m (cos a)))
(slot-set! o 'i (* m (sin a)))))))
Feb 28, 2008
Class precedence list (CPL)
Rule 1: Each class is more specific than its superclasses.
Rule 2: For a given class, superclasses listed earlier are more
specific than those listed later.
Feb 28, 2008
(use-modules (logging logger)
(logging rotating-log)
(logging port-log)
(oop goops))
Feb 28, 2008
sudo apt-get source bnetd armagetronad-dedicated bzflag-server
conquest-server crossfire-server cyphesis-cpp fceu-server
freeciv-server ggz-game-servers ggz-txt-client ggzd imazesrv koalamud
libatlas-cpp-0.6-1 libgrapple-dev liquidwar-server monopd mordor
nexuiz-server openarena-server pennmush-mysql pvpgn pybridge-server
python-2play python-poker-network python-poker2d python-tofu
tetrinet-server tetrinetx xtux-server alien-arena-server
sauerbraten-server teamspeak-server tremulous-server warsow-server
Feb 28, 2008
Coroutines are a very simple cooperative multitasking environment
where the switch from one task to another is done explicitly by a
function call. Coroutines are a lot faster than processes or threads
switch, since there is no OS kernel involvement for the operation.
Feb 28, 2008
PCL(3) Portable Coroutine Library
PCL(3)

NAME
co_create, co_call, co_resume, co_delete, co_exit_to, co_exit,
co_current - C coroutine management

SYNOPSIS
#include <pcl.h>

coroutine_t co_create(void *func, void *data, void *stack, int
stacksize);
void co_delete(coroutine_t co);
void co_call(coroutine_t co);
void co_resume(void);
void co_exit_to(coroutine_t co);
void co_exit(void);
coroutine_t co_current(void);
Feb 28, 2008
static long tvcmp(struct timeval *a, struct timeval *b) {

if (a->tv_sec - b->tv_sec)
return a->tv_sec - b->tv_sec;
return a->tv_usec - b->tv_usec;
}
Feb 28, 2008
static int co_ctx_sdir(unsigned long psp) {
int nav = 0;
unsigned long csp = (unsigned long) &nav;

return psp > csp ? -1: +1;
}

static int co_ctx_stackdir(void) {
int cav = 0;

return co_ctx_sdir((unsigned long) &cav);
}
Feb 29, 2008
Atlas-C++

Welcome to Atlas-C++, the C++ reference implementation of the Atlas protocol.

This library implements the Atlas protocol, for use in client-server
game applications. This library is suitable for linking to either
clients or servers.
Feb 29, 2008
Grapple supports simple development of networked applications using both
TCP/IP and UDP/IP. Grapple keeps track of connections to a server, relays
messages from client to client, all without the need to understand any
complicated network code. Grapples feature list is as follows

Simple client-server networking
Keeps all clients aware of all other clients
Network messenging by either a push or a pull model, or a mixture of both
Unlimited connections to multiple servers.
Multiple methods of querying users
Data transfer via TCP, UDP, or reliable UDP
Passworded servers
User Groups for client bandwidth saving
Server security - server can disconnect any client
Network load reacting data transmission and retransmission
Background pinging to monitor network states
A fuly functional lobby system (see README.lobby)
Feb 29, 2008
poker-network includes a poker server, a client library, an abstract
user interface library and a client based on it.

The server deals the cards and checks the user actions using a poker
game engine (poker-engine). It listens on a TCP/IP port and
understands a poker-network specific protocol. The persistent
informations (accounts, hand history etc.) are stored in a MySQL
database. The server was designed and tested to gracefully handle 1000
simultaneous players on a single machine also running the MySQL
server.
Feb 29, 2008
p + k is defined to be &p[k]
Feb 29, 2008
static double identityMatrix[3][3] = {
{ 1.0, 0.0, 0.0 },
{ 0.0, 1.0, 0.0 },
{ 0.0, 0.0, 1.0 }
};
Feb 29, 2008
Almost every wise saying has an oppsite one, no less wise, to banance it.
-- Goerge Santayana
Feb 29, 2008
The world is concurrent.
Things in the world don't share data.
Things communicate with messages.
Things fail.
Feb 29, 2008
Erlang is characterized by the following features:

* Concurrency - Erlang has extremely lightweight processes whose memory
requirements can vary dynamically. Processes have no shared memory and
communicate by asynchronous message passing. Erlang supports
applications with very large numbers of concurrent processes. No
requirements for concurrency are placed on the host operating system.

* Distribution - Erlang is designed to be run in a distributed
environment. An Erlang virtual machine is called an Erlang node. A
distributed Erlang system is a network of Erlang nodes (typically one
per processor). An Erlang node can create parallel processes running
on other nodes, which perhaps use other operating systems. Processes
residing on different nodes communicate in exactly the same was as
processes residing on the same node.

* Robustness - Erlang has various error detection primitives which can
be used to structure fault-tolerant systems. For example, processes
can monitor the status and activities of other processes, even if
these processes are executing on other nodes. Processes in a
distributed system can be configured to fail-over to other nodes in
case of failures and automatically migrate back to recovered nodes.

* Soft real-time - Erlang supports programming "soft" real-time systems,
which require response times in the order of milliseconds. Long
garbage collection delays in such systems are unacceptable, so Erlang
uses incremental garbage collection techniques.

* Hot code upgrade - Many systems cannot be stopped for software
maintenance. Erlang allows program code to be changed in a running
system. Old code can be phased out and replaced by new code. During
the transition, both old code and new code can coexist. It is thus
possible to install bug fixes and upgrades in a running system without
disturbing its operation.

* Incremental code loading - Users can control in detail how code is
loaded. In embedded systems, all code is usually loaded at boot time.
In development systems, code is loaded when it is needed, even when
the system is running. If testing uncovers bugs, only the buggy code
need be replaced.

* External interfaces - Erlang processes communicate with the outside
world using the same message passing mechanism as used between Erlang
processes. This mechanism is used for communication with the host
operating system and for interaction with programs written in other
languages. If required for reasons of efficiency, a special version of
this concept allows e.g. C programs to be directly linked into the
Erlang runtim
Feb 29, 2008
average(X) -> sum(X) / len(X).

sum([H|T]) -> H + sum(T);
sum([]) -> 0.

len([_|T]) -> 1 + len(T);
len([]) -> 0.
Feb 29, 2008
double([H|T]) -> [2*H|double(T)];
double([]) -> [].

member(H, [H|_]) -> true;
member(H, [_|T]) -> member(H, T);
member(_, []) -> false.
Feb 29, 2008
average(X) -> average(X, 0, 0).

average([H|T], Length, Sum) ->
average(T, Length + 1, Sum + H);
average([], Length, Sum) ->
Sum / Length.
Feb 29, 2008
Tail recursive = the last thing the function does is to call itself.
Feb 29, 2008
luanma@yueliang:~$ gcc -Os -S hello.c -o -
.file "hello.c"
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "Hello, world!"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $16, %esp
pushl $.LC0
call puts
movl -4(%ebp), %ecx
xorl %eax, %eax
leave
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (GNU) 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)"
.section .note.GNU-stack,"",@progbits
Feb 29, 2008
luanma@yueliang:~$ strace hello
execve("./hello", ["hello"], [/* 36 vars */]) = 0
uname({sys="Linux", node="yueliang", ...}) = 0
brk(0) = 0x80be000
brk(0x80becb0) = 0x80becb0
set_thread_area({entry_number:-1 -> 6, base_addr:0x80be830,
limit:1048575, seg_32bit:1, contents:0, read_exec_only:0,
limit_in_pages:1, seg_not_present:0, useable:1}) = 0
brk(0x80dfcb0) = 0x80dfcb0
brk(0x80e0000) = 0x80e0000
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 5), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0xb7fa6000
write(1, "Hello, world!\n", 14Hello, world!
) = 14
exit_group(0) = ?
Process 15734 detached
Mar 1, 2008
loop(W, Bit, State) ->
receive
{gs,quit,_,_,_} -> true;
{gs,W,keypress,[],[b|_]} -> move(left, W, Bit, State);
{gs,W,keypress,[],[n|_]} -> move(rot, W, Bit, State);
{gs,W,keypress,[],[m|_]} -> move(right, W, Bit, State);
drop_block -> move(down, W, Bit, State);
{gs,W,keypress,[],[space|_]} -> move(drop, W, Bit, State);
{gs,W,keypress,[],[d|_]} -> move(down, W, Bit, State);
{gs,W,keypress,[],[question|_]} ->
io:format("b -- left\nn -- rotate\nm -- right\nspace -- drop\n"),
loop(W, Bit, State);
Any ->
io:format("? for help\n"),
loop(W, Bit, State)
end.
Mar 14, 2008
CS is not C and Java.
Mar 14, 2008
F#
Mar 14, 2008
Functional programming is based on a simple computation model with
three constructions: variables, function
definitions, and applications of a function to an argument. This model
is called the l-calculus and it was
introduced by Alonzo Church in 1932, thus before the first computer.
It was created to offer a general
theoretical model of the notion of computability. In the l-calculus,
all functions are values which can be
manipulated. They can be used as arguments to other functions, or
returned as the result of a call to another
function. The theory of l-calculus asserts that everything which is
computable (i.e., programmable) can be
written in this formalism. Its syntax is too limited to make its use
as a programming language practical, so
primitive values (such as integers or character strings), operations
on these primitive values, control
structures, and declarations which allow the naming of values or
functions and, in particular, recursive
functions, have all been added to the l-calculus to make it more palatable.
Mar 14, 2008
Unit

The unit type describes a set which possesses only a single element,
denoted: ().

# () ;;
- : unit = ()
Mar 14, 2008
# 1 :: 2 :: 3 :: [] ;;
- : int list = [1; 2; 3]
Mar 14, 2008
# [ 1 ] @ [ 2 ; 3 ] ;;
- : int list = [1; 2; 3]
Mar 14, 2008
# if 3=4 then 0 else "4";;
Characters 20-23:
This expression has type string but is here used with type int
Mar 14, 2008
A local declaration is an expression and can thus be used to construct
other expressions:

# (let x = 3 in x * x) + 1 ;;
- : int = 10
Mar 14, 2008
The number of arguments of a function is called its arity.
Mar 14, 2008
Closure

Objective CAML treats a function expression like any other expression
and is able to compute its value. The
value returned by the computation is a function expression and is
called a closure. Every Objective CAML
expression is evaluated in an environment consisting of name-value
bindings coming from the declarations
preceding the expression being computed. A closure can be described as
a triplet consisting of the name of the
formal parameter, the body of the function, and the environment of the
expression. This environment needs to be
preserved because the body of a function expression may use, in
addition to the formal parameters, every other
variable declared previously. These variables are said to be ``free''
in the function expression. Their values
will be needed when the function expression is applied.
Mar 14, 2008
# let g = function x -> function y -> 2*x + 3*y ;;
val g : int -> int -> int = <fun>
# let g = function x y -> 2*x + 3*y ;;
val g : int -> int -> int = <fun>
Mar 14, 2008
# ( + ) ;;
- : int -> int -> int = <fun>
# let succ = ( + ) 1 ;;
val succ : int -> int = <fun>
# succ 3 ;;
- : int = 4
Mar 14, 2008
# let ( ++ ) c1 c2 = (fst c1)+(fst c2), (snd c1)+(snd c2) ;;
val ++ : int * int -> int * int -> int * int = <fun>
# let c = (2,3) ;;
val c : int * int = 2, 3
# c ++ c ;;
- : int * int = 4, 6
Mar 14, 2008
There is an important limitation on the possible operators. They must
contain only symbols (such as *, +, @,
etc. ) and not letters or digits. Certain functions predefined as
infixes are exceptions to the rule. They are
listed as follows: or mod land lor lxor lsl lsr asr.
Mar 14, 2008
In Objective CAML, variables are statically bound. The environment
used to execute the application of a closure
is the one in effect at the moment of its declaration (static scope)
and not the one in effect at the moment of
application (dynamic scope).
Mar 14, 2008
Objective CAML generates parameterized types for every function which
doesn't use the form of its arguments.
This polymorphism is called parametric polymorphism.
Mar 14, 2008
# let mk_mult_fun_list n =
let rec mmfl_aux p =
if p = n then [ ( * ) n ]
else (( * ) p) :: (mmfl_aux (p+1))
in (mmfl_aux 1) ;;
val mk_mult_fun_list : int -> (int -> int) list = <fun>
Mar 14, 2008
# let rec fold_left f a l =
if null l then a
else fold_left f ( f a (List.hd l)) (List.tl l) ;;
val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>

# let sum_list = fold_left (+) 0 ;;
val sum_list : int list -> int = <fun>
# sum_list [2;4;7] ;;
- : int = 13

# let concat_list = fold_left (^) "" ;;
val concat_list : string list -> string = <fun>
# concat_list ["Hello "; "world" ; "!"] ;;
- : string = "Hello world!"
Mar 14, 2008
# let is_a_vowel c = match c with
'a' | 'e' | 'i' | 'o' | 'u' | 'y' -> true
| _ -> false ;;
val is_a_vowel : char -> bool = <fun>
Mar 14, 2008
# let eq_rat cr = match cr with
((_,0),(_,0)) -> true
| ((_,0),_) -> false
| (_,(_,0)) -> false
| ((n1,1), (n2,1)) when n1 = n2 -> true
| ((n1,d1), (n2,d2)) when ((n1 * d2) = (n2 * d1)) -> true
| _ -> false;;
val eq_rat : (int * int) * (int * int) -> bool = <fun>
Mar 16, 2008
/* Now for the BIG LOOP. */
Mar 21, 2008
Install PostgreSQL on Ubuntu 7.10

This quick walk-through are my notes for installing the PostgreSQL
database server and the PgAdmin administration application on Ubuntu
Linux, and also set up the server so it allows access to other PC's on
your network.

Before we move on, this guide was tested on the current release of
Ubuntu Linux, (7.10 - Gutsy Gibbon) and PostgreSQL 8.2, but it should
also be applicable to older versions (of Ubuntu and PostgreSQL) and
other Debian based distros.

Right for the basic installation, at the command-line, enter the
following commands (or search for the listed packages in synaptic if
you prefer that way of working):

$ sudo apt-get install postgresql postgresql-client postgresql-contrib
$ sudo apt-get install pgadmin3

This installs the database server/client, some extra utility scripts
and the pgAdmin GUI application for working with the database.

Now we need to reset the password for the 'postgres' admin account for
the server, so we can use this for all of the system administration
tasks. Type the following at the command-line (substitute in the
password you want to use for your administrator account):

$ sudo su postgres -c psql template1
template1=# ALTER USER postgres WITH PASSWORD 'password';
template1=# \q

That alters the password for within the database, now we need to do
the same for the unix user 'postgres':

$ sudo passwd -d postgres
$ sudo su postgres -c passwd

Now enter the same password that you used previously.

Then, from here on in we can use both pgAdmin and command-line access
(as the postgres user) to run the database server. But before you jump
into pgAdmin we should set-up the PostgreSQL admin pack that enables
better logging and monitoring within pgAdmin. Run the following at the
command-line:

$ sudo su postgres -c psql < /usr/share/postgresql/8.2/contrib/adminpack.sql

Finally, we need to open up the server so that we can access and use
it remotely - unless you only want to access the database on the local
machine. To do this, first, we need to edit the postgresql.conf file:

$ sudo gedit /etc/postgresql/8.2/main/postgresql.conf

Now, to edit a couple of lines in the 'Connections and Authentication' section…

Change the line:

#listen_addresses = 'localhost'

to

listen_addresses = '*'

and also change the line:

#password_encryption = on

to

password_encryption = on

Then save the file and close gedit.

Now for the final step, we must define who can access the server. This
is all done using the pg_hba.conf file.

$ sudo gedit /etc/postgresql/8.2/main/pg_hba.conf

Comment out, or delete the current contents of the file, then add this
text to the bottom of the file:

1 # DO NOT DISABLE!
2 # If you change this first entry you will need to make sure that the
3 # database
4 # super user can access the database using some other method.
5 # Noninteractive
6 # access to all databases is required during automatic maintenance
7 # (autovacuum, daily cronjob, replication, and similar tasks).
8 #
9 # Database administrative login by UNIX sockets
10 local all postgres ident sameuser
11 # TYPE DATABASE USER CIDR-ADDRESS METHOD
12
13 # "local" is for Unix domain socket connections only
14 local all all md5
15 # IPv4 local connections:
16 host all all 127.0.0.1/32 md5
17 # IPv6 local connections:
18 host all all ::1/128 md5
19
20 # Connections for all PCs on the subnet
21 #
22 # TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD
23 host all all [ip address] [subnet mask] md5

and in the last line, add in your subnet mask (i.e. 255.255.255.0) and
the IP address of the machine that you would like to access your
server (i.e. 138.250.192.115). However, if you would like to enable
access to a range of IP addresses, just substitute the last number for
a zero and all machines within that range will be allowed access
(i.e. 138.250.192.0 would allow all machines with an IP address
138.250.192.x to use the database server).

That's it, now all you have to do is restart the server:

$ sudo /etc/init.d/postgresql-8.2 restart

And all should be working.