四月 15, 2008

视频

  1. YouTube :YouTube(你的视频)是一个可以让用户免费上传、观赏、分享视频短片的热门视频共享网站
  2. Meta Cafe: Metacafe (麦塔咖啡厅)-得到最好的网上视频-搞笑录象,惊奇短片,罕见电影
  3. Vimeo视频媒体):分享你自己剪辑的短片。上传你用自己的数码相机,手机,或摄象机拍摄后剪辑的短片,并通过Vimeo与大家分享。
  4. Daily
    Motion
    (每日行动):发布,标签,整和并分享你的视频剪辑短片。
  5. Imeem(亿门): imeem
    是一个社会媒体服务性质的网站。用户互相观看,传送,分享各种各样的媒体类型,包括包括博客、图片、音频、视频.在某中意义上说,imeem

    是以媒体为中心的社会服务网络,在另一层意义上来说,为用户提供了线上内容分享服务。
  6. ClipShack(剪辑室): ClipShack
    是录象爱好者的社区,用户可以将自己制作的视频上传给人们观赏,讨论,可以与朋友,家人共享短片,可以将这里的视频放入你的博客。
  7. vSocial视频社区): 用最快,最方便的方法上传、观看、分享视频短片。
  8. Jumpcut(跳跃剪刀):
    最好的在线制作、整和、分享电影和幻灯片的网站。这是别无仅有的一个网站。Jumpcut
    为您提供便利。
  9. Video
    Bomb
    (视频炸弹): Video Bomb
    为您过滤出网上最热门的视频短片:您只要点击‘Incoming!’就能找到您最想要的东西。多个类似视频会按照点击率排序。
  10. eyeSpot(关注点):
    拍摄,整和,分享你的视频。在线使用eyespot混合器来编辑并整和你的录象,音乐和图片。免费与世界共享你的视频。
  11. revver
    (回转者): 上传,共享视频。
  12. Avidbeauty(渴望美好): Avid Beauty
    是提供给
    IPOD用户的娱乐社区。我们提供可以下载到IPOD上的博客. 同时为会员提供 Flickr 图片, YouTube 视频和 LiveJournal integration 。

音乐

  1. last.fm: Last.fm是通过搜索和添加你最喜欢的歌手来形成风格的流动音乐网站 。创建你自己的音乐库并通过搜索来寻找和你拥有相似音乐库的同好们。
  2. Musicovery:
    根据心情来发现新的歌曲,通过免费的网络收音机来浏览不同风格和时代的
    音乐
  3. read.io :Read.io将RSS
    feeds转换成播客,由TextToSpeech转播.
    多语言支持.
  4. MusicStrands:
    使用MusicStrands搜索新音乐。听取片段,然后标出你不想购买的歌曲,或者在指定地点标出你想要购买的歌曲。接着从不同的卖主那里购买你想要的音乐。
  5. PODZINGER:
    PODZINGER - 世界上第一个音频,视频搜索引擎。
  6. Upto11:Upto11使用标签和队列向您推介新音乐。你可以创建个人工作页面,分享你的推荐,标签,播放列表。
  7. Pandora: Pandora可以通过你以前和现在的喜好来帮助你寻找并发现新的音乐

通信工具

  1. Meebo:
    meebo, 可以让您收到任何地方的来短信.
    支持 msn,
    yahoo, aol/aim, google talk (gtalk),jabber和icq。
  2. Joopz:
    允许用户从网上向个人及团体发送短信,同时可以直接从网上收到来自收件人来自个人电脑或
    Mac 的回复。Joopz web
    短信可以从世界上所有可以上网的设备上发给任何美国或加拿大的手机用户。
  3. campfire:提供简易的网上商务洽谈室。Campfire允许实时共享,编辑,协作,为用户提供一个安全的,密码保护的洽谈室。
  4. Goowy: 提供免费网页和flash电子邮件服务。用户可以即时通信,发送电子邮件,聊天,更多。
  5. Gizmo: Gizmo
    Project使用你的电脑连接(宽带或拨号),来与其他电脑用户打电话。只要点击鼠标,你就可以和在地球任何地方的朋友,家人,同事通话,就是这么简单。你们可以清楚的聊天,聊多久都可以,免费!
  6. eBuddy:
    为所有人,所有地区提供网上短信服务。
  7. e-messenger: e-Messenger 是一种方便用户在不用安装任何插件或 Java
    程序就可以同MSN, AOL
    和Yahoo用户聊天的应用软件。当你的学校或公司阻断你使用
    IM,即使隔着防火墙,你也可以用Web版的激活了JavaScript的标准ebuddy浏览器。
  8. ILOVEIM: eBuddy是在线提供 MSN, Yahoo 和 AIM
    (AOL)短信网站.当你的学校或公司阻断你使用
    IM,即使隔着防火墙,你也可以用Web版的激活了JavaScript的标准ebuddy浏览器。

图片


  1. Flickr
    :最好的储存、搜索、整理和分享您的图片的地方

  2. Zooomr
    :举世最好的在线分享,搜索,储存,整理照片的网站。

  3. Slide


  4. zoto
    zoto

  5. 23HQ

    :你的图片不是和你喜欢的人分享,而是储存在电脑硬盘上吗?

  6. Mybloop
    : MyBloop-
    免费共享图片,音频,视频。储存量无限制,无须安装软件。

博客

  1. Blogger: 傻瓜网站,可以快速发表你的想法,与人们交流,更多。
  2. Weblogs, Inc: 通过产业环境,创造使用者可以分享的产品。
  3. BlogCode:
    BlogCode.com是一个以StoryCode.com为模板,以快速、简易、直观的方式推荐博客的网站。用它,你可以以你最喜欢的日志(甚至你自己的日志)为基点,来找到
    …..
  4. blo.gs: 通过这个网页和电子邮件,你可以密切关注你最喜欢的日志你甚至可以在旁边制作一个博客名单列表,这样你就可以知道哪些你喜欢的博客更新了.
  5. BlogLines: 免费网搜索,订阅,制作,分享新闻和博客以及丰富的网站内容的网站。

书签

  1. Digg: Digg 主要靠用户自行填充内容。所有的内容都会被提交到本网站。分享,发现,加书签,支持你所喜欢的文章。
  2. del.icio.us: 社区性书签管理器。使用书签本,你可以将书签加入你的列表并将其加以分类。
  3. Reddit: Reddit可以搜索网络上最新,最流行的书籍。输入你正在看的书籍的连接,reddit
    就能知道你喜欢什么类型的书。
  4. StumbleUpon:
    StumbleUpon通过点击频率分析群众对书的质量的评价。当你犹豫的时候,可以看看和你爱好相似的朋友们喜欢的书。
  5. Blinklist:
    真正的人们共享兴趣的的网页名单。为人们喜欢的,或准备稍后收藏的网站写出了
    评价
  6. Blummy:
    一个通过你的书签工具栏,快速连接你喜欢的网页的免费工具。在Blummy
    上添加或制作几个小插件后,你几乎可以做任何事:添加图片到Flickr, 添加站点到del.icio.us,
    在WIkipedia.看文章,从上百个”blummlets”书签中选择你喜欢的,或者制作你自己的书签。

  7. Techcrunch: TechCrunch是关于Web
    2.0的产品及公司的博客,大部分(技术分析)文章都是Michael Arrington所写.
    这个博客第一次开始发表文章是在
    2.05611日。
  8. Furl:用Furl的简易书签,可以从所有网站连接你最喜欢的网页书签。通过Furl可以方便的储存、做笔记、分享你储存的连接、或浏览最热门的书签,来找到最新的或有意思的内容。

  9. Spurl:
    使用Spurl的免费线上书签服务和搜索引擎,你决不会再次无故丢失网页连接。只需点击书签本,Spurl就能快速储存网址,同时通过您的喜好来推荐新文章。
  10. Trailfire: 用于写作,分享的软件。

VOIP(网络电话

  1. Jajah: jah是网络电话提供商,由澳大利亚人Roman Scharf和Daniel
    Mattes制作于
    2.0501月.Jajah 的总部位于美国加洲的Mountain
    View,和卢森堡。Jajah还有一个位于以色列的显影中心。
  2. skype:Skype可以免费下载,免费致电他人.Skype是IP语音软件界的老大。
  3. Private Phone:
    拥有一个免费的当地语音电话号码和信息,你就可以在线查询任何电话。

游戏

1.Trendio: Trendio.com是一个在线的市场预测网站.用户不是真正的钱从公司购买股票,而是用虚拟货币购买有可靠新闻的项目的股票.可用到的词包括时世政治,体育和娱乐新闻中这些词出现的越多,股票的价值就越高.现在这个网站使用大约三千个搜索,来测量这些词的价值.


2.
GameSnips:digg风格的在线游戏列表.可以选择最近更新的游戏列表,或按点击率排列的列表。


3.
Pictaps: Roxik Pictaps -
画一个小人,然后看(控制)他在
3D界面中跳舞。


4.
Broadcast
Game
:
这个广播游戏的目的是:通过用户所在的方位,把所有的电缆和网络终端,连接到通往网络中心的网络上。而你需要做的仅仅是点击或轮流点击电缆,终端,或网络中心。

5.Pikipimp.com : 想过要把图片添加到你的相册中去吗?
使用Pikpimp程序可以方便的将网上任何图片添加到相册中。储存相册后就可以自由的将其加入你自己的网页了。

6.Mainada: 喜欢画漫画和素描吗?(感谢 Tiago)

wiki(维基百科)

  1. Wikipedia: 最大的免费网络多语言支持百科全书。超过2.0万个词条解释,并且数量持续增加中。
  2. LittleWiki:
    你可以在LittleWiki网站上创建公众的或私人的维基网页。Wiki是所有人都可以登入并编辑内容的网站,也就是说你可以编入和编辑所有你想添加的信息,任意阅读其他人编入的信息。

  3. Wetpaint:
    Wetpaint动力网站集合众人的智慧。Wetpaint的主要优势在于允许所有人
    特别是没有技术能力的人和有兴趣,有激情的人一起,来创造并建设网站.
    为了让任何人都可以登入并编辑这个网站,Wetpaint连接了同种类型中最好的万维,博客,论坛,及社区网络。
  4. JotSpot: 用户可以WYSIWYG编辑器来连接Jotspot的安全维基综合网站,建设并分享这个网站。通过安装各种各样的应用软件-项目管理器,公司目录,博客,论坛投票,日历等-来完善你的维基内容,然后邀请他人来投稿。
  5. PBWiki:
    制作一个免费的,密码保护的万维网站就跟做一个花生酱三文治一样容易。轻松上传
    HTML,将文档连接入你的网页,合并RSS,等等。

办公工具

  1. Zoho Office
    Suite
    : 在线Word Processor(文字处理器)。
  2. Google
    Docs & Spreadsheets: 使用Google Docs
    & Spreadsheets,您可以:

* 使用我们的在线编辑器来编排文档,检查拼写,等等

*上传Word,OpenOffice,RTF, HTML或text.文档

*下载…

  1. Num Sum: 简易的网络共享电子制表软件。
  2. Dictinary
    :在线字典。
  3. notifyr.org:使用notifyr.org让您走在前沿.
    Notifyr是一个任何人都可以轻松使用的工具,使用它,您可以每天在世界范围内,轻松快速的接收所有网站的最新更新的文件。网络蚂蚁出了新股票?或新产品上市信息
    ?–永远为您提供最好的,免费的信息。
  4. ThinkFree
    Office
    :
    你是否希望过可以在Linux系统上编辑Excel电子制表软件?你是否希望过可以给同事看一份在电脑上的陈述,而不是用Powerpoint制作的?你是否希望过可以…
  5. Numly: Numly是一个web 2.0的启动,提供web
    2.0下一代的版权和
    DRM数字许可证书。
  6. gOffice:免费的线上文字处理软件,可输出pdfhtml格式的信件,允许个性化信纸模板。

RSS服务

  1. FeedBurner:
    FeedBurner
    博客,播客,商业出版社拥有的内容创造更高的价值。我们将以高级feed管理技术,和熟练的期刊订阅的投递技巧,忠实的为您服务。
  2. Feed Digest: Feed Digest支持RSS和Atom
    feeds的剖析,再生及重新结构。你可以使用它将RSS或Atom feeds的内容转移到你的网站
  3. Attensa: Attensa, Inc.是一个制造RSS阅读器,提供在线RSS聚合器,企业RSS服务和RSS软件自动智能投递的软件公司。
  4. Tiny Tiny RSS: Tiny Tiny RSS是基于网络的新闻feed网站。通过它你可以阅读任何地区的新闻,并且它给人的感觉就像桌面的一个应用程序一样。
  5. Feed43:免费在线(在不影响您工作的状态下)转换网页为RSS
    feed。
  6. Feed
    Mailer
    : 直接向您发送电子邮件。(感谢
    John
    )

电邮

  1. Gmail:
    Gmail是一种实验性质的网络电子邮件,创建它的目的在于可以让你永远没有必要删除邮件,并且总是可以找到你想找到的邮件。

  2. 30 Gigs: 30Gigs.com是只有接到邀请才能注册的网络电子邮件。想想看,足足30G的空间。
  3. Zookoda:
    专门提供给用电子邮件来行销的博客
    。Zookoda以发送电子邮件的方法,为您博客的访客提供您的博客的每日,每周或每月摘要。
  4. Sprout: 为您管理电子邮件销售和服务业务。不需要IT部门,邮件屋可以帮您整理邮件并提供回复建议,节约您的时间,并让您与您的客户保持紧密的联系。不需要做任何设置,只需几分钟就可以迅速启动。
  5. Gawab:提供有特色的电子邮件服务,支持POP/SMTP.

新闻

  1. NewsGator: 在同一个地方就可以阅读所有你喜欢的新闻,网页和博客。
  2. newsvine.com: 用Newsvine追踪突发新闻:先在”The
    Wire”上阅读AP和ESPN上的一连串相关新闻,然后在”The
    Vine”上阅读用户发表的内容和专栏。接着通过评论或投票与其他读者交流,最后在Newsvine上写或者改进自己的专栏。
  3. Gabbr :Gabbr是一个社区新闻和博客网络。用户可以保存和共享他们喜欢的新闻摘要和博客日志。
  4. wired: 新闻网站和期刊,涵盖了技术,文化,商务,政治等方面的新闻。
  5. Clipmarks:
    在线新闻焦点集锦.

文件共享

  1. Box.Net:
    免费在线储存、分享文档的网站。您可以在我们的网络硬盘上储存,浏览,分享文档,也可以检索文档,图片,文档
  2. AllPeers:无限制的私人网络硬盘。任意分享私人图片。不需要记忆密码,没有公用登入通道。不需要上传就可以分享你的视频-节省主机内存,节约时间。私有并且安全。没有间谍插件,没有广告插件,没有讨厌的广告。
  3. MailBigFile 提供可以共享文件的网络硬盘。

其他

  1. Live:
    微软网2.0入口
  2. LinkedIn:类似Facebook,为商务业务人员提供。用它为自己建立一个商务网,来增加寻找工作和被雇佣的可能性,或使用它来与重要商务客户保持联系。
  3. BaseCamp:
    简单的项目管理,黑名单,记数器,时间线,文件共享,日历,等等。Basecamp适用于为大小项目的负责人,提供解决关于交流,合作,组织的方法。
  4. Side Job Track:为独立承包商提供工作跟踪服务。Sidejobtrack为商品,服务,钟点服务提供并管理发票,并汇报付款和进帐的资金流动路线。
  5. Kayak.com 搜索上百个旅行网站为您的飞机旅行和价位提供更多选择。搜索和预定机票是完全免费的,因为我们不是旅行社。
  6. TravBuddy 探险者的网站使用这个网站你不需要周游世界。可能你只是想分享一下一个当地你喜欢的饭馆,或者是上星期在附近发现的一个适合观看落日的地方。不管你是在家还是在国外寻找,发现的乐趣是相同的。对你来说司空见惯的东西,对旅行者来说可能是个惊喜呢。
  7. Wayfaring 是一个可以在谷歌地图上创建自己的路线,地址,标签的有趣的地方。
  8. Omnidrive:
    和世界上第一个网络硬盘一样,你可以把你硬盘中所有的文件上传到这个网站,支持所有平台。
  9. ma.gnolia: 在网络上创建自己的网站及社区.
  10. Ajaxian: Ajax相关博客
  11. Web 2.0 Sites:2.0网站目录,所有2.0网站的相关服务.
十一月 7, 2007

为什么使用Lighttpd,从性能方面来说,首先考虑单进程与多进程问题,这也是我为什么不想使用Apache的原因,多进程服务器的惊群问题,简单来说
多进程服务(例如Apache)在一个请求发送时候会唤醒所有sleep的进程,但是最终服务的只有一个,在进程数目很多,请求频繁的时候这会造成一个大
困扰,系统会忙于切换进程,如果看Top会发现CPU使用在system的比例很高,至于Lighttpd则使用单进程来响应quest,使用
libevent,poll()作为event handler,如果在linux2.4下,还可以选择rtsig作为event
handler。如果不使用大文件(>4G)支持,lighttpd使用sendfile()来发送文件,完全的zero-copy,在这方面性能
表现是占优的。同时Lighttpd使用FastCGI来做动态脚本处理,经过实测,在性能表现上也可以接受。

另外就是原先使用Apache的用户迁移成本会比较少,Lighttpd语法与Apache接近,并且核心功能基本实现,我关注的就是
url_rewrite,PHP(这是当然的),alias,custom_log这几个模块,语法接近,并且也同样支持跟cronolog的管道配合日
志,所以迁移之后功能都可以实现。另外我比较了Apache和Lighttpd的Suexec方案,虽然目前Lighttpd并没有官方模块来支持这一特
性,但是就实现的难度来看,跟Apache1.3乃至Apache2+MPM差不多……(如果希望安全的使用Apache2+MPM+PHP,一样需要
FastCGI模式)

如此,我们就可以开始尝试了,首先是Lighttpd的下载,然后把PHP安装为cgi模式,你可能需要安装Libevent,如果需要url_rewrite支持,还需要pcre,安装基础安装可以看TutorialLighttpdAndPHP

安装PHP

./configure \
–prefix=/usr/local/php-cgi \
–enable-fastcgi \
–enable-discard-path \
–enable-force-redirect \
&&make \
&&make install

在php.ini里边修改你的设置

cgi.fix_pathinfo = 1

安装Lighttpd

./configure \
–prefix=/usr/local/lighttpd \
&& make \
&& make install

设定文件范例 PHP部分

fastcgi.server = ( “.php” =>
(( “socket” => “/tmp/php-fastcgi.socket”,
“bin-path” => “/usr/local/php-cgi/bin/php”,
“idle-timeout” => 30,
“min-procs” => 1,
“max-procs” => 1,
“bin-environment” => (
“PHP_FCGI_CHILDREN” => “1″,
“PHP_FCGI_MAX_REQUESTS” => “10000″ ),
“bin-copy-environment” => (
“PATH”, “SHELL”, “USER” ),
“broken-scriptfilename” => “enable”
))
)

一个简单的启动/停止脚本

#!/bin/shLIGHTTPD_CONFIG=/usr/local/apache04/conf/httpd.conf
LIGHTTPD_BIN=/usr/local/apache04/sbin/lighttpd
LIGHTTPD_PID=/usr/local/apache04/lighttpd.pid
test -r $LIGHTTPD_CONFIG || exit 6

case “$1″ in
start )
echo -n “Starting lighttpd”
$LIGHTTPD_BIN -f $LIGHTTPD_CONFIG
;;
stop )
echo -n “Shutting down lighttpd”
killall lighttpd
rm $LIGHTTPD_PID
;;
esac
exit 0

这样就可以跑起来了:)

Lighttpd

libevent

PCRE

Powered by ScribeFire.

十月 30, 2007

在suse10下安装ruby on rails 遇到一些问题记录下来。

1、安装mysql-rub出错。

gem install mysql 报错,原因为没有安装mysql-devel.

2、安装rmagick出错
checking for Magick-config… no
checking for GraphicsMagick-config… no

未安装imagemagick-devel包。

 首先在 Windows 上面安裝 Ruby on Rails ,有两种方式

  1. 直接使用 Instant Rails一次全部安裝好
  2. 使用Ruby oneclick Installer分批安裝

我們來看看第一個方法,也應該是最快的方式,使用 Instant Rails 來一次全部弄好,Instant Rails 網頁上簡介是

Instant Rails is a one-stop Rails runtime solution containing Ruby, Rails, Apache, and MySQL, all preconfigured and ready to run. No installer, you simply drop it into the directory of your choice and run it. It does not modify your system environment.

所以安裝他一次就可以將所有 Ruby on Rails ,Apache ,MySQL 都裝好,有種 Appserv 的感覺。並且你還可以額外安裝 Typo, SCGI, Mongrel, 和 HighLine ,最近他連 Rad Rails 都有附,真是太簡便了。這裡有一個 Tutorial 有關於 Instant Rails ,可以看看。

其次的安裝方式是先裝 Ruby ,再用 gem 安裝其他東西。要在 Windows 上面安裝 Ruby 就使用Ruby oneclick Installer 來安裝即可,聽他的名字就知道他只需要 one click 即可安裝。等到安裝完 Ruby ,Ruby oneclick Installer 會順便裝好 gem ,再利用

gem i rails -y

安裝 Ruby on Rails 就好啦。不過安裝 apache ,mysql…..東西,就可能要你自己好好的 survey 一下。ONLamp 有一篇 Rolling with Ruby on Rails 是一篇不錯的 Tutorial ,可以試試看,這裡也有一篇在winxp中手工安装Ruby on Rails 笔记可以試試看,這裡也有 Robbin 寫的
在Windows平台使用Apache2.2和Mongrel运行Ruby on Rails

至於大家關心的 IDE 部份,我推薦 RadRails ,這是從 Eclipse 改的 Ruby on Rails IDE,可能是 TextMate 以外最好的 IDE,Instant Rails 已經有附,直接拿來用即可。

下面是我用One-Click Ruby Install 安装的详细步骤

一、安装Ruby、rails、mongrel和lighttpd

从rubyforge网站下载One-Click Ruby Install,运行安装程序,就安装好了ruby和rubygems。

运行命令:

gem update –system #这步是用来升级rubygems的。

gem install rails –-include-dependences

gem install mongrel –y

gem install mongrel_service -y

安装好了rails和mongrel

二、把Mongrel作为Services启动

mongrel_rails service::install -N depot -c d:\Rubyproject\depot -p 3000 –e production

-N指明服务名称,-d指明rails应用的目录,-p是mongrel监听的tcp端口,-e是启动模式为生产模式

这样打开控制面版|管理工具|服务,就可以发现增加了一项名为“depot”的服务,就可以通过控制面版来管理服务了。如果需要命令行启动和关闭该服务,那么:

mongrel_rails service::start -N depot

mongrel_rails service::stop -N depot

如果需要从服务中注销该项服务,那么:

mongrel_rails service::remove -N depot

如果需要安装多个mongrel实例,那么可以这样:

mongrel_rails service::install -N depot0 -c d:\Rubyproject\depot -p 3000 –e production

mongrel_rails service::install -N depot1 -c d:\Rubyproject\depot -p 3001 –e production

诸如此类。

三、安装配置lighttpd

安装Windows版本的Lighttpd
下载地址是:http://www.kevinworthington.com:8181/?p=116,windows版本的lighttpd默认被安装在c:/lighttpd,这个安装位置是不能修改的。

配置Lighttpd,配置port:

打开c:\lighttpd\etc\lighttpd.conf

取消 server.port = 81 前的注释,你也可以使用port:80

开启模块,其他模块不要乱开,会出问题

server.modules = (”mod_proxy”,
“mod_rewrite”,
“mod_accesslog”,
“mod_alias” )

另外在这个配置文件末位加上:

proxy.debug = 0
proxy.balance = “fair”
proxy.server = ( “/” =>
(
( “host” => “127.0.0.1″, “port” => 3000 ),
( “host” => “127.0.0.1″, “port” => 3001 )
)
)

这里的port就是Mongrel server的port,启动Lighttpd使用命令:

c:\lighttpd\sbin\lighttpd.exe -D -f c:\lighttpd\etc\lighttpd.conf

通过http://localhost:81/ 就可以成功访问了哈。

四、安装rmagick

在windows环境下,旧版本的Rmagick安装完gem后,需要运行一个postinstall.rb来设置windows字体等。新版本的Rmagick没有这个步骤,代替是安装ImageMagick。我按照README安装成功后,在rails中使用还是出现无法读取字体的错误,忍无可忍又换了旧版本的Rmagick,没想到跟ruby的解释器版本不一致,render templage的时候出现parse error类型的错误。认真比对了下新老版本的差别,原来旧版本的Rmagick在Config目录下多了个type-windows.xml来设置windows字体,在此记录下正确的安装方法:

1.到http://rubyforge.org/frs/?group_id=12&release_id=8170,下载RMagick-1.15.9_IM-6.3.5-8-Q8_prod.zip

2.解压后在目录执行gem install rmagick-1.15.9-win32.gem

3.最后,双击ImageMagick-6.3.5-8-Q8-windows-dll.exe安装ImageMagick(切忌不要安装imagemagick主页上最新的ImageMagick-6.3.6-8-Q8-windows-dll.exe 文件,使用时会和rmagick不兼容)

4.将ImageMagick的安装目录加进环境变量path,如果有的话就不用了

5.最后一步,将附件中的type-windows.xml拷贝进ImageMagick安装目录下的config目录,比如E:\ImageMagick-6.3.0-Q8\config,修改type.xml,原来是:

代码

  1. <typemap>  
  2.   <include file=“type-ghostscript.xml” />  
  3. </typemap>  

render_code();修改为:

代码

  1. <typemap>  
  2. <include file=“type-windows.xml” />  
  3.   <!– <include file=”type-ghostscript.xml” /> –>  
  4. </typemap>  

render_code();安装完成,测试下网上那个流传的RMagick的验证码例子,终于正常了。

十月 20, 2007

将下载到的文件解压缩,找到、/libs/dbconnect.php.default, 重命名为dbconnect.php
settings.php.default 重命名为settings.php

上传到空间上去,打开http://yoursite/install/

按照提示输入数据库连接的信息,基本就可以了。

按照提示,/libs/dbconnect.php 权限设为655
将/install文件夹删除

好了,现在可以用 god (12345)登录了。
PIGG下载
http://www.pligg.com/forum/downloads.php?do=file&id=22&act=down
中文语言包(老鬼):
http://bbs2.chinahtml.com/attachment.php?attachmentid=4218&d=1173669288

Powered by ScribeFire.

九月 24, 2007

前一阵在一个project中使用了ReaderWriterLock,发现了两个问题:

  Performance非常差

 
 UpgradeToWriterLock并不是atomic的从ReaderLock转换到WriterLock,而是等同于
“lock.ReleaseReaderLock();
lock.AcquireWriterLock();”.这样的semantics有一定的迷惑性,我开始的时候也认为这个operation是
atomic的,等出现bug并debug了很久才发现原来如此。不过经过认真的思考,发现这其实不是。NET
designer的错,根本没办法把这个operation设计成atomic的。原因如下:

  很多个thread同时acquire到了ReaderLock,

  他们都call UpgradeToWriterLock,如果这个operation是atomic的,那么没有哪个thread能upgrade成功。

  后来我干脆不用ReaderWriterLock了,直接换成了LockFree的方法。这个得益于ibm的一些paper.(http://www.research.ibm.com/people/m/michael/pubs.htm

  在C#中实现LockFree其实是很简单的,因为有了Garbage Collection,

  code:

1 class LockFreeDictionary
2 {
3 private Dictionary m_dict = new Dictionary();
4
5 public Value Lookup(Key key)
6 {
7 return m_dict[key];
8 }
9
10 public void Update(Key key, Value value)
11 {
12 Dictionary newDict = null;
13 Dictionary oldDict = null;
14 do
15 {
16 oldDict = m_dict;
17 newDict = new Dictionary(oldDict);
18 newDict[key] = value;
19 } while (Interlocked.CompareExchange>(ref m_dict, newDict, oldDict) != oldDict);
20 }
21 }
22

  解释如下:

  line 16, keep a reference to the original Dictionary object,

  line 17, construct a new Dictionary object base on original object. For oldDict, this step is readonly, and doesn’t need lock,

  line 18, perform the update operation upon the new constructed object,

 
 line 19, try to swap the new object into the original one. If the
return value of Interlocked.CompareExchange operation is NOT equal to
oldDict, it means during this do-while block executation, there is
another thread changed m_dict. In this scenario, we need to do the
update again.

  the swapped out object (oldDict) can be collected by Garbage Collection.

 
 if we want to use LockFree data structure in C++, there is another
technique called Hazard Pointer. it’s in the ibm research papers.

  不过不是什么情况都可以使用这种LockFreeDictionary的,,不然你会得到相反的效果(performance很差),这里的scenario是read非常多,write非常少。 不过这种情况也挺常见的。

  这种方法的好处是在Lookup的时候没有任何lock,从而极大的提高了performance.(我的project里面比ReaderWriterLock提高了2000倍,)

  对LockFree有研究的或者有兴趣的可以留言大家讨论讨论,:)

Powered by ScribeFire.

九月 23, 2007

Lua语言简介

1993
年在巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro in
Brazil)诞生了一门编程语言,发明者是该校的三位研究人员,他们给这门语言取了个浪漫的名字——Lua,在葡萄牙语里代表美丽的月亮。事实证明她没
有糟蹋这个优美的单词,Lua语言正如它名字所预示的那样成长为一门简洁、优雅且富有乐趣的语言。

Lua从一开始就是作为一门方便嵌入
(其它应用程序)并可扩展的轻量级脚本语言来设计的,因此她一直遵从着简单、小巧、可移植、快速的原则,官方实现完全采用ANSI
C编写,能以C程序库的形式嵌入到宿主程序中。Lua的每个版本都保持着开放源码的传统,不过各版采用的许可协议并不相同,自5.0版(最新版是5.1)
开始她采用的是著名的MIT许可协议。正由于上述特点,所以Lua在游戏开发、机器人控制、分布式应用、图像处理、生物信息学等各种各样的领域中得到了越
来越广泛的应用。其中尤以游戏开发为最,许多著名的游戏,比如Escape from Monkey Island、World of
Warcraft、大话西游,都采用了Lua来配合引擎完成数据描述、配置管理和逻辑控制等任务。

作为一门过程型动态语言,Lua有着如
下的特性:1、变量名没有类型,值才有类型,变量名在运行时可与任何类型的值绑定;2、语言只提供唯一一种数据结构,称为表(table),它类似key
-value关联数组,可以用任何类型的值作为key和value。提供了一致且富有表达力的表构造语法,使得Lua很适合描述复杂的数据;3、函数是一
等类型,支持匿名函数和正则尾递归(proper tail recursion);4、支持词法定界(lexical
scoping)和闭包(closure);5、提供thread类型和结构化的协程(coroutine)机制,在此基础上可方便实现协作式多任务;
6、运行期能编译字符串形式的程序文本并载入虚拟机执行;7、通过元表(metatable)和元方法(metamethod)提供动态元机制
(dynamic
meta-mechanism),从而允许程序运行时根据需要改变或扩充语法设施的内定语义;8、能方便地利用表和动态元机制实现基于原型
(prototype-based)的面向对象模型;9、从5.1版开始提供了完善的模块机制,从而更好地支持开发大型的应用程序;

Lua
的语法类似PASCAL和Modula但更加简洁,所有的语法产生式规则(EBNF)不过才60几个。熟悉C和PASCAL的程序员一般只需半个小时便可
将其完全掌握。而在语义上Lua则与Scheme极为相似,她们完全共享上述的1、3、4、6点特性,
Scheme的continuation与协程也基本相同只是自由度更高。最引人注目的是,两种语言都只提供唯一一种数据结构:Lua的表和Scheme
的列表(list)。正因为如此,有人甚至称Lua为“只用表的Scheme”。

库和工具

相比Java、Python、Perl,Lua的开源工具和库可能并不算多,但其中不乏优秀之作。以下介绍的资源均可在http://lua-users.org/wiki/LuaAddons上找到,而且绝大多数都遵循着与Lua相同的许可协议。

一、Kepler

Kepler
是一个简单且轻量的Web开发平台(但这并不意味着只能用它来开发简单的应用),支持用Lua撰写Web程序,因此相当易学易用,并且能较方便地应用在一
些资源受限的系统中。由于使用ANSI C和Lua进行开发,所以它能移植到任何支持ANSI C的平台上。

Kepler由多个Lua扩
展库组成,包括CGILua、LuaSocket、LuaFileSystem、Copas、LuaSQL、LuaLDAP、LuaExpat、
LuaXMLRPC、LuaSOAP、LuaZip、Xavante等,它们可大致分为核心库和功能支撑库两部分。其中核心是CGILua和
LuaSocket,后者负责TCP/UDP
sockets的操作,前者则可以创建动态页面并处理web表单上的输入数据。Kepler通过CGILua起动器(launcher)使得Web服务器
能执行CGILua和Web程序并与之通信。目前的版本已经包括适合CGI、FastCGI、Apache、IIS、Tomcat、Zope的
CGILua起动器,因此用Lua开发的Web程序可以在这些种类的服务器中自由迁移,只要同时安装上对应的CGILua起动器。

LuaFileSystem
是对标准Lua库中文件读写功能的补充,它提供了一种可移植的方法来访问系统的目录结构和文件属性。Copas则是一个基于协程的服务调度器。
Xavante是一个用Lua开发的支持HTTP 1.1的Web服务器,它直接支持CGILua而无需起动器。

其它的组件提供了SQL数据库访问、XML解析、LDAP、SOAP、XMLRPC、ZIP文件操作等功能,用户如果只需要其中的某些功能,可以抽出相关组件(及其所依赖的组件)来使用。

二、wxLua

GUI
是开发人员花费气力比较大的一个领域,因此简化GUI程序的编写一直是广大程序员的努力方向。随着脚本语言的兴起,将动态、灵活、易用的脚本语言引入到
GUI开发中是一种非常有价值的尝试。由于复杂的GUI布局需要大量的描述信息,所以比起其它脚本来,既适合编程又适合描述数据的Lua语言在构建GUI
上就具有独特的优势。

wxWidgets是一个著名的跨平台C++
GUI库,wxLua在Lua与wxWidgets之间架起了一座桥梁,通过它Lua代码几乎可以调用wxWidgets的所有功能。wxLua基本将
wxWidgets的类体系映射到了Lua(基于原型)的对象模型中,这使得程序员能以基于对象或面向对象的风格来开发wxLua程序。一个Lua脚本的
撰写、运行、测试和修改可以非常快速,这无疑大大提高了GUI程序的开发效率,因此wxLua非常适合快速原型的构造。另外,Lua本身以及
wxWidgets良好的可移植性使得相应的Lua GUI程序在许多平台上都能顺畅地运行。

三、Pluto

虽然Lua
中的表能通过表构造器以Lua代码的形式保存到文件中从而实现持久化,但当数据之间有着复杂的引用关系,并且存在循环引用、共享引用等特殊情况时,这个任
务就变得相当困难与繁琐了。Pluto持久化库能够为用户解决这个难题。在它的帮助下程序员可以将任意复杂的表数据保存到特殊格式的二进制文件中以待将来
恢复,库会自动处理循环引用之类的情况。

除表之外,Pluto还支持函数(确切地说是闭包)、thread的持久化,这种能力非常有意
义。大家都知道程序调试中的一个基本动作就是复现bug,但很多时候bug产生的条件是非常复杂的,依赖很多因素,开发者很难精确地构建出完全一致的运行
环境。而利用Pluto对函数和thread的持久化能力,我们可以把bug发生时程序的完整运行环境保存下来,今后就可凭此方便地复现bug。另外一个
重要应用是游戏进度的保存。实现游戏逻辑的Lua脚本的运行状态能随时写入到文件中留待将来恢复,这使得在任何时间点保存游戏成了一件非常容易的事情。

四、LuaCOM

LuaCOM
是一个支持Lua与符合COM规范的组件对象(确切一点说是自动化对象)进行交互的扩展库。所谓交互包括了两个方面,首先是允许Lua程序使用COM对
象。LuaCOM支持注册在系统注册表中的COM对象的动态实例化,也支持动态访问运行中的对象。在LuaCOM的帮助下,调用COM对象方法就象调用普
通Lua函数一样,存取属性也与存取表的字段类似,同时它还负责Automation数据类型与Lua数据类型的自动转换。有了这些特性,Lua程序操作
COM对象就变得容易多了,再加上Lua天生的动态性,这无疑使其成了一门非常灵活的组件装配语言。

交互的另外一个方面就是支持用Lua
来实现(自动化)组件对象并提供给外部客户使用。LuaCOM同时支持进程内和进程外组件,它提供了一些辅助函数来处理注册、对象实例化这类事情,从而简
化了相关工作。由于LuaCOM实际上是根据Lua的表来构造一个COM对象,所以我们可以做一些非常有趣的事情:在userdata数据类型(代表不属
于Lua世界的数据结构)和动态元机制的支持下,Lua能通过表访问各种各样的外部数据,包括C++对象、C结构或者CORBA对象等等;LuaCOM可
以很方便地将代表这些数据的表包装成一个COM对象给外部使用,从而使得那些老迈的应用程序和库无需太多的努力便能跻身于COM世界。

五、tolua


接用C实现某些功能,然后将相应的函数导入到Lua中是很常见的做法。不过尽管Lua提供了与C语言交互的API,但用户必需手工进行繁琐的Lua栈(用
于与C交换数据)操作,而且还需注意两种语言数据类型的正确转换。难怪有人说使用Lua的C
API就象在使用汇编语言一样。为了减轻程序员的负担,一些C/C++ Wrapper应运而生。

tolua本身不是一个
Wrapper,但它是一个Wrapper代码自动生成器。它使用一种称为包(package)的文件来描述要导入到Lua环境中的常量、变量、函数、类
和方法,这种文件按照简化了的C++头文件格式编写。使用时首先让tolua解析包文件以生成含有相应胶水代码的C/C++源文件。然后将生成的源文件编
译并与那些具体实现功能的目标模块链接起来。

tolua虽然自动产生胶水代码,但需另外撰写描述文件,所以仍然不够方便。其它一些Wrapper库则利用C++模板元编程技术来自动生成合适的连接代码,从而避免了额外的描述文件,比如使用boost库的luabind。

六、LuaJIT

Lua
非常高效,它运行得比许多其它脚本(如Perl、Python、Ruby)都快,这点在第三方的独立测评中得到了证实。尽管如此,仍然会有人不满足,他们
总觉得“嗯,还不够快!”。LuaJIT就是一个为了再榨出一点速度的尝试,它利用JIT编译技术把Lua代码编译成本地机器码后交由CPU直接执行。
LuaJIT测评报告表明,在浮点运算、循环和协程的切换等方面它的加速效果比较显著,但如果程序大量依赖C编写的函数,那么运行速度便不会有什么改进。
目前LuaJIT只支持X86 CPU。

LuaJIT中包括一个名为Coco的库,用户可以单独使用它。Coco为C函数提供了真正的协
程能力,用户能在C函数内部的任何一点将协程挂起,然后在将来用协程恢复操作返回到那一点。在标准Lua中,协程的挂起与恢复是不允许跨越C函数调用边界
的。Coco使用了一些依赖于特定系统的特性,因此在移植程序时要特别注意。

七、ChunkSpy

Lua的虚拟机字节码指令集并非语言定义的一部分,因此官方没有提供相应的文档。用户当然可以通过查看相关源代码来获取信息,但这毕竟不方便。

ChunkSpy
是一个Lua虚拟机字节码反汇编器,可以将一个二进制Lua代码块输出为非常易读的各种格式(详细或简略,带或不带源程序)的字节码汇编文件。而且它还支
持交互式的反汇编,用户在敲入一行代码后立刻就能看到对应的字节码指令。ChunkSpy的作者写过一篇详细的介绍Lua5虚拟机指令的文章,名为《A
No-Frills Introduction to Lua 5 VM
Instructions》,你在项目主页上能找到它。这篇文章现在已经针对最新的Lua5.1做了更正。另外,他还是Yueliang项目的开发者,这
个项目采用Lua语言本身来实现Lua。从项目名来看,作者应该是个华人。

八、其它

另外一些库与工具还包括
LuaEDIT、LuaEclipse、VS’05LuaLangPack(它们都是IDE或IDE插件),LuaWrapper、CaLua、CPB、
CppLua(Wrapper库),LuaProfiler(性能测量工具)等,读者可以在lua-user.org与luaforge.net网站上找
到它们以及其它有用资源。

Powered by ScribeFire.

九月 22, 2007
EXIF,是英文Exchangeable Image
File(可交换图像文件)的缩写,最初由日本电子工业发展协会(JEIDA –Japan Electronic Industry Development
Association) 制订,目前的版本是修改发表于1998年6月的2.1版。国际标准化组织(ISO)正在制订的相机文件设计标准(DCF — Design
role for Camera File
system)就是以EXIF2.1格式为基础而设定的。记住,EXIF是一种图像文件格式,只是文件的后缀名还是沿用大家熟悉的jpg而已。实际上,EXIF信息就是由数码相机在拍摄过程中采集一系列的信息,然后把信息放置在我们熟知的jpg文件的头部,也就是说EXIF信息是镶嵌在JPEG图像文件格式内的一组拍摄参数,主要包括摄影时的光圈、快门、ISO、日期时间等各种与当时摄影条件相关的讯息,相机品牌型号,色彩编码,拍摄时录制的声音以及全球定位系统(GPS)等信息。简单的说,它就好像是傻瓜相机的日期打印功能一样,只不过EXIF信息所记录的资讯更为详尽和完备。不过,具有EXIF信息的JPEG图像文件要比普通的JPEG文件略大一点。就目前市场而言,新一代的数码相机都具有附加EXIF信息功能,大多数的数码相机厂商也都会随数码相机发售时附赠能够读取EXIF信息的软件,例如
Nikon 系列的数码相机就附赠 NikonView 软件,Agfa系列的相机则附赠 Photowize V1.8版,而富士相机附送的EXIF
viewer软件更是这方面的领军人物(目前已在很多网站提供免费下载。还有一部分的数码相机会自动将EXIF信息转存成文档文件,例如:NIKON CoolPix
990和SONY
FD系列。除了硬件厂商随数码相机附带的EXIF信息查看软件,很多专业的图像软件厂商在这方面也不甘示弱,相继推出自己公司看图软件的最新版来支持这种近乎完美的JPEG-EXIF图像信息附加技术,如最近刚推出的ACDSee
4.0版本,就对现在流行的各种数码相机有相当好的支持,在EXIF图像信息附加方面较之其3.0版本也有很大的进步。不管是硬件厂商的配套软件还是专业名门的看图工具,所有这些软件都是为了方便数码摄影者能更方便地保存查看摄影图像的重要信息。我们将这些读取EXIF信息的软件归纳后分为四类:专业EXIF信息查看工具(以富士的EXIF
viewer为例) 、具有查看EXIF信息的强大通用看图工具(以ACDSee为例)、支持EXIF信息查看的操作系统(微软的Windows
XP)以及可以修改EXIF信息的另类工具(EXIF
Editer),而我们这里要讲的是通过C#在WEB上读取一个图片的EXIF信息。

二、相关类(GetEXIFMetaData):

因为代码比较长,有五百多行,我只能将关键代码的片段拿出来讲讲,需要源码的请发邮件到 yubo@x263.net 索取,或者直接加到MSN上在MSN提供你的邮箱。

这个类中构造了两个结构MetadataDetail 和 Metadata  ,前者是为了存储EXIF中某元素信息的三种格式,起到中间转化的作用,一个是十六进制的索引信息,一个是没用处理过的信息代码,一个是显示信息。后面的那个结构就是存储一张图片所有EXIF信息元素的。 有两个方法LookupEXIFValue 和 GetEXIFMetaData ,前一个方法是处理特殊元素的对应显示的,后者从图片中读取相关信息然后填充到MetaData结构中。

using
System;
using System.Drawing;
using System.Drawing.Imaging;
using
System.Collections;
using System.ComponentModel;

namespace
Test.Com
{
/// <summary>
/// 功能:获得图片EXIF信息
/// 作者:Rexsp
///
创建日期:2004-03-20
/// </summary>
public class
EXIFMetaData
{
  #region 构造函数
  /// <summary>
  ///
构造函数
  /// </summary>
  public
EXIFMetaData()
  {
  }
  #endregion

  #region 数据转换结构
  ///
<summary>
  /// 转换数据结构
  /// </summary>
  public struct
MetadataDetail
  {
   public string Hex;//十六进制字符串
   public string
RawValueAsString;//原始值串
   public string
DisplayValue;//显示值串
  }
  #endregion

  #region EXIF元素结构
  ///
<summary>
  /// 结构:存储EXIF元素信息
  /// </summary>
  public
struct Metadata
  {
   public MetadataDetail EquipmentMake;
   public
MetadataDetail CameraModel;
   public MetadataDetail
ExposureTime;//曝光时间
   public MetadataDetail Fstop;
   public
MetadataDetail DatePictureTaken;
   public MetadataDetail ShutterSpeed;//
快门速度
   public MetadataDetail MeteringMode;//曝光模式
   public MetadataDetail
Flash;//闪光灯
   public MetadataDetail XResolution;
   public MetadataDetail
YResolution;
   public MetadataDetail ImageWidth;//照片宽度
   public
MetadataDetail ImageHeight;//照片高度

   public MetadataDetail
FNumber;//  f值,光圈数
   public MetadataDetail ExposureProg;//  曝光程序
  
public MetadataDetail SpectralSense;//  
   public MetadataDetail
ISOSpeed;//  ISO感光度
   public MetadataDetail OECF;//  
   public
MetadataDetail Ver;//  EXIF版本
   public MetadataDetail
CompConfig;//  色彩设置
   public MetadataDetail CompBPP;//  压缩比率
   public
MetadataDetail Aperture;//  光圈值
   public MetadataDetail
Brightness;//  亮度值Ev
   public MetadataDetail ExposureBias;//  曝光补偿
  
public MetadataDetail MaxAperture;//  最大光圈值

   public MetadataDetail
SubjectDist;// 主体距离
   public MetadataDetail LightSource;//  白平衡
   public
MetadataDetail FocalLength;//  焦距
   public MetadataDetail
FPXVer;//  FlashPix版本
   public MetadataDetail ColorSpace;//  色彩空间
  
public MetadataDetail Interop;//  
   public MetadataDetail
FlashEnergy;//  
   public MetadataDetail SpatialFR;//  
   public
MetadataDetail FocalXRes;//  
   public MetadataDetail FocalYRes;//  
  
public MetadataDetail FocalResUnit;//  
   public MetadataDetail
ExposureIndex;//  曝光指数
   public MetadataDetail SensingMethod;//  感应方式
  
public MetadataDetail SceneType;//  
   public MetadataDetail
CfaPattern;//  
  }
  #endregion

  #region 查找EXIF元素值
  public
string LookupEXIFValue(string Description, string Value)
  {
   string
DescriptionValue = null;

   switch(Description)
   {
    case
“MeteringMode”:

     #region  MeteringMode
    {
    
switch(Value)
     {
      case “0″:
       DescriptionValue =
“Unknown”;break;
      case “1″:
       DescriptionValue =
“Average”;break;
      case “2″:
       DescriptionValue = “Center
Weighted Average”;break;
      case “3″:
       DescriptionValue =
“Spot”;break;
      case “4″:
       DescriptionValue =
“Multi-spot”;break;
      case “5″:
       DescriptionValue =
“Multi-segment”;break;
      case “6″:
       DescriptionValue =
“Partial”;break;
      case “255″:
       DescriptionValue =
“Other”;break;
     }
    }
     #endregion
    
    
break;
    case “ResolutionUnit”:

     #region
ResolutionUnit
    {
     switch(Value)
     {
      case
“1″:
       DescriptionValue = “No Units”;break;
      case “2″:
      
DescriptionValue = “Inch”;break;
      case “3″:
       DescriptionValue =
“Centimeter”;break;
     }
    }

     #endregion

    
break;
    //省略N行相似代码

   }
   return
DescriptionValue;
  }
  #endregion

  #region
取得图片的EXIF信息
  public Metadata GetEXIFMetaData(string PhotoName)
  {
  
// 创建一个图片的实例
   System.Drawing.Image MyImage =
System.Drawing.Image.FromFile(PhotoName);
   // 创建一个整型数组来存储图像中属性数组的ID
  
int[] MyPropertyIdList = MyImage.PropertyIdList;
   //创建一个封闭图像属性数组的实例
  
PropertyItem[] MyPropertyItemList = new
PropertyItem[MyPropertyIdList.Length];
  
//创建一个图像EXIT信息的实例结构对象,并且赋初值

   #region 创建一个图像EXIT信息的实例结构对象,并且赋初值
  
Metadata MyMetadata = new Metadata();
   MyMetadata.EquipmentMake.Hex =
“10f”;
   MyMetadata.CameraModel.Hex = “110″;
  
MyMetadata.DatePictureTaken.Hex = “9003″;
   MyMetadata.ExposureTime.Hex =
“829a”;
   MyMetadata.Fstop.Hex = “829d”;
   MyMetadata.ShutterSpeed.Hex =
“9201″;
   MyMetadata.MeteringMode.Hex = “9207″;
   MyMetadata.Flash.Hex =
“9209″;
   MyMetadata.FNumber.Hex = “829d”; //
  
MyMetadata.ExposureProg.Hex = “”; //
   MyMetadata.SpectralSense.Hex =
“8824″; //
   MyMetadata.ISOSpeed.Hex = “8827″; //
  
MyMetadata.OECF.Hex = “8828″; //
   MyMetadata.Ver.Hex = “9000″; //
  
MyMetadata.CompConfig.Hex = “9101″; //
   MyMetadata.CompBPP.Hex = “9102″;
//
   MyMetadata.Aperture.Hex = “9202″; //
   MyMetadata.Brightness.Hex
= “9203″; //
   MyMetadata.ExposureBias.Hex = “9204″; //
  
MyMetadata.MaxAperture.Hex = “9205″; //
   MyMetadata.SubjectDist.Hex =
“9206″; //
   MyMetadata.LightSource.Hex = “9208″; //
  
MyMetadata.FocalLength.Hex = “920a”; //
   MyMetadata.FPXVer.Hex = “a000″;
//
   MyMetadata.ColorSpace.Hex = “a001″; //
   MyMetadata.FocalXRes.Hex
= “a20e”; //
   MyMetadata.FocalYRes.Hex = “a20f”; //
  
MyMetadata.FocalResUnit.Hex = “a210″; //
   MyMetadata.ExposureIndex.Hex =
“a215″; //
   MyMetadata.SensingMethod.Hex = “a217″; //
  
MyMetadata.SceneType.Hex = “a301″;
   MyMetadata.CfaPattern.Hex =
“a302″;
   #endregion

   // ASCII编码
   System.Text.ASCIIEncoding
Value = new System.Text.ASCIIEncoding();
            
   int index =
0;
   int MyPropertyIdListCount=MyPropertyIdList.Length;
  
if(MyPropertyIdListCount!=0)
   {
    foreach (int MyPropertyId in
MyPropertyIdList)
    {
     string hexVal = “”;
    
MyPropertyItemList[index] = MyImage.GetPropertyItem(MyPropertyId);

    
#region 初始化各属性值
     string
myPropertyIdString=MyImage.GetPropertyItem(MyPropertyId).Id.ToString(”x”);
    
switch(myPropertyIdString)
     {
      case “10f”:
      {
      
MyMetadata.EquipmentMake.RawValueAsString
=BitConverter.ToString(MyImage.GetPropertyItem (MyPropertyId).Value);
      
MyMetadata.EquipmentMake.DisplayValue =
Value.GetString(MyPropertyItemList[index].Value);
      
break;
      }

      case “110″:
      {
      
MyMetadata.CameraModel.RawValueAsString
=BitConverter.ToString(MyImage.GetPropertyItem(MyPropertyId).Value);
      
MyMetadata.CameraModel.DisplayValue
=Value.GetString(MyPropertyItemList[index].Value);
      
break;

      }

      case “9003″:
      {
      
MyMetadata.DatePictureTaken.RawValueAsString
=BitConverter.ToString(MyImage.GetPropertyItem(MyPropertyId).Value);
      
MyMetadata.DatePictureTaken.DisplayValue
=Value.GetString(MyPropertyItemList[index].Value);
      
break;
      }
    //省略N行相似代码
     }
     #endregion
    

     index++;
    }
   }

   MyMetadata.XResolution.DisplayValue
= MyImage.HorizontalResolution.ToString();
  
MyMetadata.YResolution.DisplayValue =
MyImage.VerticalResolution.ToString();
   MyMetadata.ImageHeight.DisplayValue
= MyImage.Height.ToString();
   MyMetadata.ImageWidth.DisplayValue =
MyImage.Width.ToString();
   MyImage.Dispose();
   return
MyMetadata;
  }
  #endregion
}
}

然后就是个调用的问题,有了这个类,我如何读取图片的EXIF信息呢?代码如下:
  
EXIFMetaData em = new EXIFMetaData();
   string
filePath=Server.MapPath(”Test.jpg”);//这里可以动态传递图片路径的
   EXIFMetaData.Metadata
m = em.GetEXIFMetaData(filePath);//这里就是调用,传图片绝对路径
   string exif =
m.Ver.DisplayValue;
   string camera = m.CameraModel.DisplayValue;
  
string model = m.CameraModel.DisplayValue;
   string aperture =
m.Aperture.DisplayValue;
   string shutter =
m.ShutterSpeed.DisplayValue;
   string sensitive =
m.ExposureIndex.DisplayValue;

有什么不明白的,欢迎提出来,此代码经过测试,功能正常。

Powered by ScribeFire.

九月 15, 2007

在参与了几个大型PHP项目,写了很多PHP代码以后,我发现很多工具可以提高代码质量,简化发布,使得做为PHP开发人员的生涯变得轻松许多。许多这样
的工具可能已经为大家所用。但是,由于一些人甚至没有注意到这些工具的存在,我会从此开始,好了,不说废话,下面是我认为所有PHP程序员应该知道的工具
列表。

Phing - 一个项目构建系统

Phing LogoPhing 是一个基于Apache ANT 的项目构建系统。它的名字是一个拗口的语句首字母缩写 - PHing Is Not GNU make 。Phing可以做传统构建系统比如 GNU make 能做的任何事情,同时没有陡峭的学习曲线。

在phing(以及其他的构建系统)背后的思想是评估一系列相关性,然后执行一系列PHP类去正确的安装和配置一个应用系统。构建过程用一个简单的
XML配置文件控制。Out of the box,
phing内置可以执行一系列替换(比如:在你的开发版本和产品版本间改变include路径)、执行SQL语句、移动和复制文件、运行外部脚本等等。通
过扩展包含在发行包中的“task”类,你也可以创造自己的定制任务。

对任何需要在超过一台服务器上部署大型PHP应用的人来世,Phing是一个无价之宝。同时我发现它对简单的PHP脚本也是很有用的。

Xdebug - 调试和分析工具

Xdebug LogoXdebug 是帮助你调试和分析脚本的一个PHP扩展。Xdebug中最有用的特性是在激活后显示的新注意信息、警告信息和错误信息。如果一个脚本不能正常运行,Xdebug将会输出关于错误信息的完整堆跟踪 ,会附带函数名称、参数值、源文件和行号。这对于厌倦了PHP默认只带的可怜的错误报告功能的程序员是一个值得欢迎的特性。

这个扩展有很多更先进的功能,允许开发人员进行代码覆盖率分析,收集分析信息以及交互式地调试脚本。profiling functionality 功能尤其有用。分析器使用一个普通的输出文件格式,允许你使用象 KCacheGrind 这样的工具快速发现你代码中的瓶颈。对任何严肃的开发人员而言,一个好的分析器是基本工具,它使得你妥善优化你的代码,同时避免过早优化带来的危害

PHPUnit - 单元测试框架

PHPUnit logoPHPUnit 是一个轻量级的PHP测试框架。它是在PHP5下面的 JUnit 3.8.1 完整移植,是xUnit 测试框架家族的一员(它们基于软件模式 先锋 Kent Beck 的设计)。

单元测试是几个现代敏捷开发方法的基础,使得PHPUnit成为许多大型PHP项目的关键工具。这个工具也可以被前面讨论的Xdebug扩展用来生成代码覆盖率报告 ,并且可以与phing集成来自动测试。

Propel - ORM(对象关系映射)框架

Propel LogoPropel是一个PHP5下面的对象关系映射(ORM)框架,它起源于Apache Torque项目。它提供了一个复杂但是易用的数据库抽象层,使得你可以在PHP中象使用普通类和对象一样得使用数据库实体。Propel允许你使用一种简单的XML格式定义你的数据库,这个XML文件被用来映射数据库,生成应用中使用的静态类。 

Propel被内嵌于流行的Symfony PHP框架 (还有其他的),它使得代码更灵活、模块化以及可移植。这个项目有The project has 出色的文档,以及很棒的支持社区。

phpMyAdmin / phpPgAdmin - 基于web的数据库管理系统

phpMyAdmin Logo历史有点长可是还是很有用,phpMyAdmin是对于任何数据库(对应PostgreSQL和SQLite是phpPgAdmin 和 phpSQLiteAdmin)最有用的管理工具之一。它有助于做每一件事情 - 从为了调试应用去创建和删除数据库到做备份。安装它通常是我在一个LAMP服务器上面安装完 Apache, PHP和MySQL后做的第一件事情。如果你使用MySQL,不知何故还没听说过它,那么现在就安装 。

其他工具

还有很多优秀的工具用以符合各种需要,帮助PHP开发者创建一个丰富的开发环境 — 我希望我可以说到所有这些工具。我发现对自己有用的工具有PHP Beautifier, Spyc, CreoleSmarty。我确信还有很多我忘记或者没听说过的有用工具。因此,如果你知道某个我遗漏的PHP开发伟大工具,请留言让我(以及所有人)知道!

Powered by ScribeFire.

九月 12, 2007

原文链接:Functional Programming For The Rest of Us
原文作者:Vyacheslav Akhmechet

程序员拖沓成性,每天到了办公室后,泡咖啡,检查邮箱,阅读 RSS
feed,到技术站点查阅最新的文章,在编程论坛的相关版面浏览公共讨论,并一次次地刷新以免漏掉一条信息。然后是午饭,回来后盯了IDE没几分钟,就再
次检查邮箱,倒咖啡。最后在不知不觉中,结束了一天。

不平凡的事是每隔一段时间会跳出一些很有挑战性的文章。如果没错,这些天你至少发现了一篇这类文章——很难快速通读它们,于是就将之束之高阁,直到
突然你发现自己已经有了一个长长的链接列表和一个装满了PDF文件的目录,然后你梦想着到一个人迹罕至的森林里的小木屋苦读一年以期赶上,要是每天清晨你
沿着那里的林中小溪散步时会有人带来食物和带走垃圾就更好了。

虽然我对你的列表一无所知,但我的列表却是一大堆关于函数式编程的文章。而这些基本上是最难阅读的了。它们用枯燥的学院派语言写成,即使“在华尔街
行业浸淫十年的专家(veterans)”也不能理解函数式编程(也写作FP)都在探讨些什么。如果你去问花旗集团(Citi
Group)或德意志银行(Deutsche Bank)的项目经理[1],为什么选择了 JMS 而不 Erlang,他们可能回答不能在产业级的应用中使用学院派语言。问题是,一些最为复杂的,有着最严格需求的系统却是用函数式编程元素写成。有些说法不能让人信服。

的确,关于函数式编程的文章和论文难于理解,但他们本来不必这么晦涩。这一知识隔阂的形成完全是历史原因。函数式编程的概念本身并不困难。这篇文章
可以作为“简易的函数式编程导引”。是一座从我们命令式(imperative)的思维模式到函数式编程的桥梁。去取杯咖啡回来继续读下去吧。可能你的同
事很快就会开始取笑你对函数式编程发表的观点了。

那么什么是函数式编程呢?它怎么产生?它可以被掌握吗(Is it
edible)?如果它真如其倡导者所言,为什么没有在行业中得到更广泛的使用?为什么好像只有那些拿着博士学位的人才使用它?最要紧的是,为什么它就
TMD 这么难学?这些 closure, continuation,
currying,惰性求值和无副作用等等究竟是些什么东西?没有大学参与的项目怎么使用它?为什么它看上去这么诡异于和我们命令式思想友好,圣洁和亲近
的一切的一切?我们将于不久扫清这些疑问。首先让我来解释形成实际生活和学界文章之间巨大隔阂的缘起,简单得像一次公园的散步。

信步游园

启动时间机器,我们散步在两千多年以前的一个被遗忘了太久的春季明媚的日子,那是公元前380年。雅典城墙外的橄榄树树荫里,柏拉图和一个英俊的奴隶小男孩朝着学院走去。“天气真好”,“饮食不错”,然后话题开始转向哲思。

“瞧那两个学生,”为了使问题更容易理解,柏拉图仔细地挑选着用词,“你认为谁更高呢?”
小男孩看着那两个人站着的水漕说,“他们差不多一样高”。
柏拉图说:“你的差不多一样是什么意思?”。“我在这里看他们是一样高的,不过我肯定如果走近些就会看出他们高度的差别。”
柏拉图笑了,他正把这个孩子带到正确的方向。“那么你是说,我们这个世界没有完全的等同了?”
小男孩想了一会儿回答,“对,我不这样认为,任何事物总有一些区别,即使我们看不到它。”
这句话非常到位!“那么如果这世上没有完全的相等,你又是如何理解‘完全’相等这个概念的呢?”
小男孩迷惑得说:“我不知道。”最初尝试着理解数学的本源(nature)时也会产生这种疑惑。

柏拉图暗示这个世上的万物都只是一个对完美的近似。他还认识到我们即使没有接触到完美但依然可以理解这一概念。所以他得出结论,完美的数学形式只能
存在于另一个世界,我们通过和那个世界的某种联系在一定程度上知晓他们。很明显我们不能看到完美的圆,但我们可以理解什么是完美的圆并用数学公式将它表达
出来。那么,什么是数学?为什么宇宙可以用数学定理描述?数学可以描述宇宙中的所有现象吗?[2]

数学哲学是一个很复杂的课题。像大多数哲学学科一样它更倾向于提出问题而不是给出解答。这些意见中很多都循回绕转于一个事实,即数学实际上是一个谜
语:我们设置了一系列基本的不冲突的原理和一些可以施加于这些原理的操作规则,然后我们就能堆砌这些规则以形成更复杂的规则。数学家把这种方法叫做“形式
系统”或“演算”。如果愿意,我们可以很快写出一个关于 Tetris(译者注:一种通常被称为俄罗斯方块的游戏)的形式系统。实际上,工作中的
Tetris 实现就是一个形式系统,只是被指定使用了个不常见的表现形式。

人马座的那个生物文明也许不能理解我们的 Tetris 和圆的范式,因为可能他们唯一的感知输入是气味香橙的橘子。他们也许永远不会发现
Tetris
范式,但很可能会有一个圆的范式。我们也可能将无法阅读它,因为我们的嗅觉没有那么复杂,可是一旦我们理解(pass)了那一范式的表示形式(通过这种传
感器和标准解码技术来理解这种语言),其底层的概念就可被任何智能文明所理解。

有趣的是如果从来没有智能文明存在,Tetris
和圆的范式仍然严密合理,只是没有人注定将会发现他们。如果产生了一种智能文明,他就会发现一些形式系统来帮助描述宇宙的规律。但他还是不大可能发现
Tetris 因为宇宙中再没有和它相似的事物。在现实世界中这类无用的形式系统或迷题的例子数不胜数,Tetris
只是其中的一个典型。我们甚至不能确定自然数是否是对客观世界的完整近似,至少我们可以简单的想像一个很大的数它不能用宇宙中任何东西描述,因为它以近乎
无穷。

历史一瞥[3]

再次启动时间机器,这一次的旅行近了很多,我们回到 1930 年代。大萧条正在蹂躏着那个或新或就的时代。空前的经济下挫影响着几乎所有阶层的家庭生活,只有少数人还能够保持着饥谨危机前的安逸。一些人就如此幸运地位列其中,我们关心的是普林斯顿大学的数学家们。

采用了歌特式风格设计建造的新办公室给普林斯顿罩上天堂般的幸福光环,来自世界各地的逻辑学家被邀请到普林斯顿建设一个新的学部。虽然彼时的美国民
众已难能弄到一餐的面包,普林斯顿的条件则是可以在高高的穹顶下,精致雕凿的木质墙饰边上整日的品茶讨论或款款慢步于楼外的林荫之中。

阿隆左·丘奇就是一个在这种近于奢侈的环境中生活着的数学家。他在普林斯顿获得本科学位后被邀留在研究生院继续攻读。阿隆左认为那里的建筑实属浮
华,所以他很少一边喝茶一边与人讨论数学,他也不喜欢到林中散步。阿隆左是一个孤独者:因为只有一个人时他才能以最高的效率工作。虽然如此,他仍与一些普
林斯顿人保持的定期的联系,其中包括阿兰·图灵,约翰·冯·诺依曼,和 kurt Grodel。

这四个人都对形式系统很感兴趣,而不太留意现实世界,以便致力于解决抽象的数学难题。他们的难题有些共同之处:都是探索关于计算的问题。如果我们有
了无限计算能力的机器,哪些问题可以被解决?我们可以使他们自动地得以解决吗?是否还是有些问题无法解决,为什么?不同设计的各种机器是否具有相同的计算
能力?

通过和其它人的合作,阿隆左·丘奇提出了一个被称为 lambda 演算的形式系统。这个系统本质上是一种虚拟的机器的编程语言,他的基础是一些以函数为参数和返回值的函数。函数用希腊字母 lambda 标识,这个形式系统因此得名[4]。利用这一形式系统,阿隆左就可以对上述诸多问题推理并给出结论性的答案。

独立于阿隆左,阿兰·图灵也在进行着相似的工作,他提出了一个不同的形式系统(现在被称为图灵机),并使用这一系统独立得给出了和阿隆左相似的结论。后来被证明图灵机和 lambda 演算能力等同。

我们的故事本可以到此结束,我会就此歇笔,而你也将浏览到下一个页面,如果第二次世界大战没有在那时打响。整个世界笼罩在战争的火光和硝烟之中,美
国陆军和海军前所未有的大量使用炮弹,为了改进炮弹的精确度,部队组织了大批的科学家持续地计算微分方程以解出弹道发射轨迹。渐渐意识到这个任务用人力手
工完成太耗精力后,人们开始着手开发各种设备来攻克这个难关。第一个解出了弹道轨迹的机器是 IBM 制造的 Mark I ——
它重达5吨,有75万个组件,每秒可以完成三次操作。

竞争当然没有就此结束,1949年,EDVAC(Electronic Discrete Variable Automatic
Computer,爱达瓦克)被推出并获得了极大的成功。这是对冯·诺依曼架构的第一个实践实例,实际上也是图灵机的第一个现实实现。那一年好运与阿隆左
·丘奇无缘。

直到1950年代将尽,一位 MIT 的教授John
McCarthy(也是普林斯顿毕业生)对阿隆左·丘奇的工作产生了兴趣。1958年,他公开了表处理语言 Lisp。Lisp 是对阿隆左·丘奇的
lambda 演算的实现但同时它工作在冯·诺依曼计算机上!很多计算机科学家认识到了 Lisp
的表达能力。1973年,MIT人工智能实验室的一组程序员开发了被称为Lisp机器的硬件-阿隆左 lambda 演算的硬件实现!

函数式编程

函数式编程是对阿隆左·丘奇理论的实践应用。但也并非全部 lambda 演算都被应用到了实践中,因为 lambda
演算不是被设计为在物理局限下工作的。因此,象面向对象的编程一样,函数式编程是一系列理念,而不是严格的教条。现在有很多种函数式编程语言,他们中的大
多数以不同方式完成不同任务。在本文中我将就最广泛使用的源自函数式编程的思想作一解释,并将用Java语言举例。(的确,你可以用Java写出函数式的
程序如果你有显著的受虐倾向)。在下面的小节中,我将会把Java作为一种函数式语言,并对其稍加修改使它成为一种可用的函数式语言。现在开始吧。

lambda
演算被设计用来探询关于计算的问题,所以函数式编程主要处理计算,并惊人地用函数来完成这一过程。函数是函数式编程的基本单位,函数几乎被用于一切,包括
最简单的计算,甚至变量都由计算取代。在函数式编程中,变量只是表达式的别名(这样我们就不必把所有东西打在一行里)。变量是不能更改的,所有变量只能被
赋值一次。用 Java 的术语来说,这意味着所有单一变量都被声明为 final(或 C++ 的 const)。在函数式编程中没有非 final
的变量。

final int i = 5;
final int j = i + 3;

因为函数式编程中所有变量都是 final 的,所以可以提出这样两个有趣的表述:没有必要总是写出关键字
final,没有必要把变量再称为变量。那么现在我们对Java作出两个修改:在我们的函数式 Java 中所有变量默认都是
final的,我们将变量(variable)称为符号(symbol)。

就此你也许会质疑,用我们新创造的语言还能写出有些复杂度的程序吗?如果每个符号都是不可变更(non-mutalbe)的,那么就无法改变任何状
态!其实事实并非完全如此。在阿隆左研究其 lambda
演算时,他并不想将某个状态维护一段时间以期未来对其进行修改。他关注的是对数据的操作(也通常被称为”演算体 caculating
stuff”)。既然已被证明lambda演算与图灵机等价,它可以完成所有命令式编程语言能够完成的任务。那么,我们怎么才能做到呢?

答案是函数式程序能保存状态,只是它并非通过变量而是使用函数来保存状态。状态保存在函数的参数中,保存在堆栈上。如果你要保存某个状态一段时间并
时不时地对其进行一些修改,可以写个递归函数。举个例子,我们写个函数来翻转 Java 的字符串。记住,我们声明的每个变量默认都是 final
的。[5]

String reverse(String arg) {
if(arg.length == 0) {
return arg;
}
else {
return reverse(arg.substring(1, arg.length)) + arg.substring(0,1);
}}

这个函数很慢因为它不断地调用自己[6],它还也是个嗜内存魔因为要持续分配对象。不过它的确是在用函数式风格。你可能会问,怎么有人会这样写程序?好的,我这就慢慢讲来:

函数式编程的优点

你可能会认为我根本无法对上面那个畸形的函数给出个合理的解释。我开始学习函数式编程时就是这么认为的。不过我是错了。有很好的理由使用这种风格,
当然其中一些属主观因素。例如,函数式程序被认为更容易阅读。因为每个街区的孩子都知道,是否容易理解在旁观者的眼中,所以我将略去这些主观方面的理由。
幸运的是,还有很多的客观理由。

单元测试

因为函数式编程的每一个符号都是 final 的,没有函数产生过副作用。因为从未在某个地方修改过值,也没有函数修改过在其作用域之外的量并被其他函数使用(如类成员或全局变量)。这意味着函数求值的结果只是其返回值,而惟一影响其返回值的就是函数的参数。

这是单元测试者的梦中仙境(wet
dream)。对被测试程序中的每个函数,你只需在意其参数,而不必考虑函数调用顺序,不用谨慎地设置外部状态。所有要做的就是传递代表了边际情况的参
数。如果程序中的每个函数都通过了单元测试,你就对这个软件的质量有了相当的自信。而命令式编程就不能这样乐观了,在 Java 或 C++
中只检查函数的返回值还不够——我们还必须验证这个函数可能修改了的外部状态。

调试

如果一个函数式程序不如你期望地运行,调试也是轻而易举。因为函数式程序的 bug
不依赖于执行前与其无关的代码路径,你遇到的问题就总是可以再现。在命令式程序中,bug
时隐时现,因为在那里函数的功能依赖与其他函数的副作用,你可能会在和 bug
的产生无关的方向探寻很久,毫无收获。函数式程序就不是这样——如果一个函数的结果是错误的,那么无论之前你还执行过什么,这个函数总是返回相同的错误结
果。

一旦你将那个问题再现出来,寻其根源将毫不费力,甚至会让你开心。中断那个程序的执行然后检查堆栈,和命令式编程一样,栈里每一次函数调用的参数都
呈现在你眼前。但是在命令式程序中只有这些参数还不够,函数还依赖于成员变量,全局变量和类的状态(这反过来也依赖着这许多情况)。函数式程序里函数只依
赖于它的参数,而那些信息就在你注视的目光下!还有,在命令式程序里,只检查一个函数的返回值不能够让你确信这个函数已经正常工作了,你还要去查看那个函
数作用域外数十个对象的状态来确认。对函数式程序,你要做的所有事就是查看其返回值!

沿着堆栈检查函数的参数和返回值,只要发现一个不尽合理的结果就进入那个函数然后一步步跟踪下去,重复这一个过程,直到它让你发现了 bug 的生成点。

并行

函数式程序无需任何修改即可并行执行。不用担心死锁和临界区,因为你从未用锁!函数式程序里没有任何数据被同一线程修改两次,更不用说两个不同的线程了。这意味着可以不假思索地简单增加线程而不会引发折磨着并行应用程序的传统问题。

事实既然如此,为什么并不是所有人都在需要高度并行作业的应用中采用函数式程序?嗯,他们正在这样做。爱立信公司设计了一种叫作 Erlang
的函数式语言并将它使用在需要极高抗错性和可扩展性的电信交换机上。还有很多人也发现了 Erlang
的优势并开始使用它。我们谈论的是电信通信控制系统,这与设计华尔街的典型系统相比对可靠性和可升级性要求高了得多。实际上,Erlang
系统并不可靠和易扩展,Java 才是。Erlang 系统只是坚如磐石。

关于并行的故事还没有就此停止,即使你的程序本身就是单线程的,那么函数式程序的编译器仍然可以优化它使其运行于多个CPU上。请看下面这段代码:

String s1 = somewhatLongOperation1();
String s2 = somewhatLongOperation2();
String s3 = concatenate(s1, s2);

在函数编程语言中,编译器会分析代码,辨认出潜在耗时的创建字符串s1和s2的函数,然后并行地运行它们。这在命令式语言中是不可能的,因为在那
里,每个函数都有可能修改了函数作用域以外的状态并且其后续的函数又会依赖这些修改。在函数式语言里,自动分析函数并找出适合并行执行的候选函数简单的像
自动进行的函数内联化!在这个意义上,函数式风格的程序是“不会过时的技术(future
proof)”(即使不喜欢用行业术语,但这回要破例一次)。硬件厂商已经无法让CPU运行得更快了,于是他们增加了处理器核心的速度并因并行而获得了四
倍的速度提升。当然他们也顺便忘记提及我们的多花的钱只是用在了解决平行问题的软件上了。一小部分的命令式软件和 100%
的函数式软件都可以直接并行运行于这些机器上。

代码热部署

过去要在 Windows上安装更新,重启计算机是难免的,而且还不只一次,即使是安装了一个新版的媒体播放器。Windows XP
大大改进了这一状态,但仍不理想(我今天工作时运行了Windows
Update,现在一个烦人的图标总是显示在托盘里除非我重启一次机器)。Unix系统一直以来以更好的模式运行,安装更新时只需停止系统相关的组件,而
不是整个操作系统。即使如此,对一个大规模的服务器应用这还是不能令人满意的。电信系统必须100%的时间运行,因为如果在系统更新时紧急拨号失效,就可
能造成生命的损失。华尔街的公司也没有理由必须在周末停止服务以安装更新。

理想的情况是完全不停止系统任何组件来更新相关的代码。在命令式的世界里这是不可能的。考虑运行时上载一个Java类并重载一个新的定义,那么所有
这个类的实例都将不可用,因为它们被保存的状态丢失了。我们可以着手写些繁琐的版本控制代码来解决这个问题,然后将这个类的所有实例序列化,再销毁这些实
例,继而用这个类新的定义来重新创建这些实例,然后载入先前被序列化的数据并希望载入代码可以恰到地将这些数据移植到新的实例。在此之上,每次更新都要重
新手动编写这些用来移植的代码,而且要相当谨慎地防止破坏对象间的相互关系。理论简单,但实践可不容易。

对函数式的程序,所有的状态即传递给函数的参数都被保存在了堆栈上,这使的热部署轻而易举!实际上,所有我们需要做的就是对工作中的代码和新版本的
代码做一个差异比较,然后部署新代码。其他的工作将由一个语言工具自动完成!如果你认为这是个科幻故事,请再思考一下。多年来
Erlang工程师一直更新着他们的运转着的系统,而无需中断它。

机器辅助的推理和优化

函数式语言的一个有趣的属性就是他们可以用数学方式推理。因为一种函数式语言只是一个形式系统的实现,所有在纸上完成的运算都可以应用于用这种语言书写的程序。编译器可以用数学理论将转换一段代码转换为等价的但却更高效的代码[7]。多年来关系数据库一直在进行着这类优化。没有理由不能把这一技术应用到常规软件上。

另外,还能使用这些技术来证明部分程序的正确,甚至可能创建工具来分析代码并为单元测试自动生成边界用例!对稳固的系统这种功能没有价值,但如果你
要设计心房脉冲产生器 (pace
maker)或空中交通控制系统,这种工具就不可或缺。如果你编写的应用程序不是产业的核心任务,这类工具也是你强于竞争对手的杀手锏。

高阶函数

我记得自己在了解了上面列出的种种优点后曾想:“那都是非常好的特性,可是如果我不得不用天生就不健全的语言编程,把一切变量声明为
final 产生的代码将是垃圾一堆。” 这其实是误解。在如Java 这般的命令式语言环境里,将所有变量声明为 final 没有用,但是在函数式语言里不是这样。函数式语言提供了不同的抽象工具它会使你忘记你曾经习惯于修改变量。高阶函数就是这样一种工具。

函数式语言中的函数不同于 Java 或 C 中的函数,而是一个超集——它有着 Java 函数拥有的所有功能,但还有更多。创建函数的方式和 C 中相似:

int add(int i, int j) {
return i + j;
}

这意味着有些东西和同样的 C 代码有区别。现在扩展我们的 Java 编译器使其支持这种记法。当我们输入上述代码后编译器会把它转换成下面的Java代码(别忘了,所有东西都是 final 的):

class add_function_t {
int add(int i, int j) {
return i + j;
}
}

add_function_t add = new add_function_t();

这里的符号 add 并不是一个函数。这是一个有一个成员函数的很小的类。我们现在可以把 add
作为函数参数放入我们的代码中。还可以把它赋给另一个符号。我们在运行时创建的 add_function_t
的实例如果不再被使用就将会被垃圾回收掉。这些使得函数成为第一级的对象无异于整数或字符串。(作为参数)操作函数的函数被称为高阶函数。别让这个术语吓
着你,这和 Java 的 class 操作其它
class(把它们作为参数)没有什么区别。我们本可以把它们称为“高阶类”但没有人注意到这个,因为 Java 背后没有一个强大的学术社区。

那么怎样,何时应该使用高阶函数呢?我很高兴你这样问。如果你不曾考虑类的层次,就可能写出了一整团堆砌的代码块。当你发现其中一些行的代码重复出
现,就把他们提取成函数(幸运的是这些依然可以在学校里学到)。如果你发现在那个函数里一些逻辑动作根据情况有变,就把他提取成高阶函数。糊涂了?下面是
一个来自我工作的实例:假如我的一些 Java 代码接受一条信息,用多种方式处理它然后转发到其他服务器。

class MessageHandler {
void handleMessage(Message msg) {
// …
msg.setClientCode(”ABCD_123″);
// …

sendMessage(msg);
}

// …

}

现在假设要更改这个系统,现在我们要把信息转发到两个服务器而不是一个。除了客户端的代码一切都像刚才一样——第二个服务器希望这是另一种格式。怎