Skip to content


拜拜2013

唉,2013就这么溜走了,一年又过去了,工作之后的时间真是走得飞快。今年一共写了三篇博客,额,三篇……我好懒…不过,今年完成了几件大事。
慢慢说吧:

1月

  • 坐班车的时候,MBP从货架上摔下来,磕凹进去了一块儿,硬盘坏了。于是换了个SSD,大爽,一年的心情在转忧为喜中开始了。
  • 找个周末专程去城西给@zongyuanwu 和@要做一个可爱的人 分享Clojure,从此拉开一年的价值观输出的序幕。
  • 因为12306抢票插件,github被天朝人民DDOS,并且短暂墙掉几天。

2月

  • 部门内部分享Clojure,继续价值观输出。
  • 回家,开始吃吃喝喝过大年,火锅啊火锅啊!豆花啊豆花啊!各种好吃的!各种上山下乡好耍惨了!
  • 折腾jekyll,试图把blog迁移到github上去,还自己写了个脚本神马的,但是最后发现自己做的页面太挫,实在进行不下去了。

3月

  • 脾气变得暴躁,讨厌别人向我问低级的问题,没有耐心,多次吐槽。
  • 领证了,学雷锋纪念日那天,她向雷锋同志学习,热情地帮我解决了人生问题。我会到处说那是因为我们在一起的1314+1314天么?
  • 把房子买了,欠下一屁股债。

4月

  • 键盘帽坏了,苹果死活不给俺单换键盘帽,折腾来折腾去,最后万能的淘宝20块钱解决。
  • TT4开始步入紧张的开发的节奏。
  • @大毛蛋 结婚,去了趟太原,会了会多年不见的大学同学,陪老婆在汾河边走走。不知道下次再聚是何时了,唉…
  • 我会说我低调地发布了一个Clojure写的工具放到线上使用至今而且零八阿哥么~

5月

  • 不断Fix bug,离上线越来越近,系统模块好多,好难hold住的感觉。
  • 在公交站的电杆洞洞里捡回一只黄色狸花猫,取名贱贱,从此微博微信都是它。
  • 老婆去海南outing,带回来好多大芒果,原来芒果这么好吃。

6月

  • ACUG(Alibaba Clojure User Group)首次聚会,很开心的。
  • 用imparsonate写了个用类似SQL的语法去TT数据的工具,被Clojure的表达能力震惊了。
  • 某天,带贱贱看狗夜叉呢,突然地震了。与是我给贱贱放上吃的,下楼了。
  • 天气开始变热了,今年持续一夏的40多度的高温不知不觉开始了,吃午饭都是煎熬。
  • 拍婚纱照,结婚各项事宜提上日程。
  • TT4上线。

7月

  • 开始TT3向TT4的切换,小心翼翼,如履薄冰,学到了好多东西。
  • Clojure出了core.async,哥再次折服了。
  • 买了对戒,这辈子带上就取不下来了!

8月

  • 奶奶七十大寿,回老家待了三天,好久没有在夏天回去过了,稻田、稻穗还有清凉的早晨,仿佛一下子回到童年。
  • 偶尔会去游泳什么的。
  • 晚上起来的有些频繁,一到值班的星期就有些神经敏感。
  • 领到入职三年的纪念品,再次感受到时间是多么锋利,突然就三年了,我特么的还记得来杭州时带的什么行李呢!

9月

  • 公司搬家到西溪园区,对我而言是从此暴跌的幸福感,更长时间的班车意味着更早起床,更晚回家。
  • 部门outing去了坑爹的温州,坑爹的南麂岛,一路无聊的感觉。
  • 贱贱送人寄养了,突然屋子里没有什么闹腾的了,很是想念这货。
  • 生产系统逐渐稳定了些,但是还是不少问题在fix。业务基本切到TT4.

10月

  • 回家结婚,把这件大事情给办了!累了好几天,胡吃海喝了好几天,以至于后来肠炎了,挂吊瓶……
  • 回杭州后没几天,贱贱就接回来了,这货肥了好大一圈,看来在别人家也过得挺不错嘛。月底就带她去咔嚓了…猫生残缺了…
  • 突然发现了Cursive Clojure这个玩意儿,目前最好的Clojure IDE了,一直用到现在,说不完的爽。
  • 为mac没有Onenote郁闷,为python没有partition-all郁闷。

11月

  • 双11,忙。
  • 微博活跃度开始下降,微信使用频率增加。
  • 生日,收到老婆精心准备的一连串礼物,很开心。

12月

  • 双12,狗忙。
  • 在团队内部讲《Clojure是门好语言》结束年度价值观输出。
  • 学车进度死慢死慢,今年不会有什么阶段性的成果了。

总的来说,今年,

  • 工作比较累,你说这是所谓成长么?也许吧,我就是感觉有点累而已。
  • 人生大事,今年总算是办掉一件,其实生活还是这样子,没有特别明显的变化。

对于2014,

  • 希望工作更加游刃有余,别像今年这么狗忙狗忙了。
  • 房子要装修,是件麻烦事儿,希望能够应付得过来。
  • 还是希望自己多写写博客吧,虽然2013年做的不是很好。

爱你一生,爱你一世!

Posted in 阳光洒满了这个世界.

Tagged with , .


core.async学习笔记(1)——简介与使用

近期Rich等clojure的开发者发布了core.async这个库,很有意思clojure终于打算为并发提供更好用的基础设施了。于是决定学习一下core.async,从用法到实现,写一个系列。先挖个坑,慢慢填,打理一下很久没有更新的博客。

core.async为clojure提供了基于channel的并发编程模型的支持,即所谓的Communicating Sequential Processes (CSP)。如果你熟悉go语言,go里头的goroutine和channel就是CSP的典型代表。再往简单的说,就是不同的并发处理单元(线程、进程、协程等等)之间通过消息传递的方式(比如channel)进行通讯和和协作。

这里简单介绍几个重要的API。

所有接口都在clojure.core.async这个namespace下

(require ‘[clojure.core.async :refer :all])

从channel说起,创建channel:

(chan)
(chan 10)
(chan (buffer 10)) ;; 还有dropping-buffer和sliding-buffer

channel的读写:

(let [ch (chan 1)]
  (go (>! ch 1))
  (>!! ch :a)
  (println (<!! ch))
  (go (println (<! ch)))
  nil)

需要注意的是,< !和<!!是从channel读一个值,>!和>!!是往channel写一个值。区别在于:

  • 带’!'的必须用在(go …)表达式里,
  • 带’!!’的必须用在原生线程里,比如main线程,或者(thread …)表达式里以及其他原生线程。

说道这里,就要说说(go …)表达式和原生线程的区别了,一个是IOC(inversion of control) Thread,一个是Native Thread。后者就不多说了,也就是操作系统提供的Thread。IOC Thread必须通过(go …)来创建。这一点跟golang的goroutine太像了,甚至都是用了”go”这个单词。IOC Thread的好处是不会一一映射到Native Thread上,当IOC Thread遇到阻塞操作的适合,就会让出当前执行的线程资源,系统再调度别的IOC Thread来执行。阻塞操作包括对channel的读和写,还包括网络IO操作等(不过当前core.async还不支持网络IO)。这样,我们就可以创建大量的IOC Thread,而不必担心Native Thread带来的消耗。同时,代码用同步的方式书写,避免了各种事件机制、回调函数带来的复杂度。

既然golang是很典型的CSP,那么golang里头重要的select当然也不能少了,core.async提供了alts!/alts!!两个接口。

(let [ch1 (chan)
      ch2 (chan)]
  (go (dotimes [i 2]
        (prn (str "CH1" (<! ch1)))))
  (go (dotimes [i 2]
        (prn (str "CH2" (<! ch2)))))   (go (dotimes [i 4]         (alts! [[ch1 i] [ch2 i]])))) 

这里启动了两个IOC线程从各自的channel里读数据,然后打印,重复两次。另外一个IOC线程同时往两个channel写 alts!/alts!!有两种用法,一种是写,一种是读。读的时候,参数是一个channel的向量,每次返回从某一个channel读到的结果。结果是一个包含两个元素的向量,第一个元素是读到的值,第二个元素是读到这个值的channel。

 (let [ch1 (chan)       ch2 (chan)]   (go (dotimes [i 4]         (>! ch1 [:ch1 i])))
  (go (dotimes [i 4]
        (>! ch2 [:ch2 i])))
  (go (dotimes [i 4]
        (println (alts! [ch1 ch2])))))
;; 标准输出
;; [[:ch2 0] #]
;; [[:ch1 0] #]
;; [[:ch1 1] #]
;; [[:ch1 2] #]

写的时候参数依然是一个向量,向量每一个元素也是向量,第一个元素是要写入的channel,第二个元素是要写入的值。

(let [ch1 (chan)
      ch2 (chan)]
  (go (dotimes [i 4]
        (println (str "CH1-" (<! ch1)))))
  (go (dotimes [i 4]
        (println (str "CH2-" (<! ch2)))))
  (go (dotimes [i 4]
        (alts! [[ch1 i] [ch2 i]]))))
;; 标准输出,多试几次,结果不一样的~
;; CH1-0
;; CH2-1
;; CH1-2
;; CH2-3

alts!/alts!!默认优先级是按照参数向量的顺序,否则是随机顺序。当有一个操作成功之后,就不会进行其他操作了。所以,写的时候0~3只会被写入一次。

timeout是一种特殊的channel,超时时间到了之后会自动关闭,读操作会得到nil。比如这样:

(let [ch (chan)]
  (go (println (alts! [ch (timeout 1000)] :default :time-out))))

优点:

just a library, not syntax。试想,一个原来没有此功能的语言要活生生加入这样的功能,还得保持整原有代码的兼容性,只有lisp才能作得如此优雅!

缺点:

才刚刚开始…暂时还没有IO操作的支持,没有IO的异步都是耍流氓哇。

其他资源:

  • http://clojure.com/blog/2013/06/28/clojure-core-async-channels.html
  • http://clojure.github.io/core.async/
  • https://github.com/clojure/core.async/tree/master/examples

p.s. 欢迎访问纯爷们的小生活

p.s.s 原文地址:http://chunyemen.org/archives/862

Posted in 未分类.


略记clojure中Java交互的两个坑

好久没写东西了…从春节回来之后就没有西闲下来过,搞定了一些重要的事情~^_^。现在项目进入紧张的开发过程中,自己也开始尝试再非核心的项目中引入clojure。记一下最近遇到的两个坑吧,关于clojure的java interop的。

repeat与java对象

我其实需要一组java对象的seq,把他们new出来就好。于是我写了这样的代码…

(repeat (SomeClass. ))

后来代码行为很奇特,于是…于是…我发现我不是在操作一组java对象,而是同一个对象。后来一想,同一个对象才是符合clojure的行为的。因为clojure自身的对象都是不可变的,那么repeat返回同一个对象是理所当然的了!来看看repeat的源代码:

(defn repeat
  "Returns a lazy (infinite!, or length n if supplied) sequence of xs."
  {:added "1.0"
   :static true}
  ([x] (lazy-seq (cons x (repeat x))))
  ([n x] (take n (repeat x))))

已经很明显了,果断返回同一个对象啊…看来是自己想当然了,经过clojure-cn邮件组的同学的提示,正确的写法应该是:

(repeatedly cnt #(SomeClass. ))

java异常

我只是想说,java interop的时候,一定别忘了catch 异常,一定记得把java调用的代码用try包起来,不然线程推出了都不知道是为啥!

 

p.s. 原文地址:http://chunyemen.org/archives/852
p.s.s. 欢迎访问纯爷们的小生活

Posted in 我和小老婆之间的事.

Tagged with , .


在Mac OSX上通过SSH代理实现github访问

前提,你需要一个ssh代理。

创建如下两个文件,并加上可执行权限。
~/.socks5proxyssh:

#!/bin/sh
ssh -o ProxyCommand="/Users/xiafei/.socks5proxywrapper %h %p" "$@"

~/.socks5proxywrapper

#!/bin/sh
connect -S 127.0.0.1:7086 "$@"  
# 我的ssh代理监听在本地的7086端口,可以实用ssh name@ssh.server.com -D port监听

修改~/.gitconfig,增加如下内容:

[http]
    proxy = socks5://127.0.0.1:7086
    # http协议直接走ssh代理
[core]
    gitproxy = /Users/xiafei/.socks5proxywrapper
    # git协议通过wrapper走代理

导出环境变量

# ssh协议代理wrapper
export GIT_SSH="/Users/xiafei/.socks5proxyssh"

这里获得connect的源文件,注释掉1765行,编译后放到$PATH上:

gcc connect.c -o connect
cp connect /usr/local/bin

现在你就应该可以实用git了,实测clone,push都没问题。

下面开始说正事儿:
gfw这帮傻逼,github这种站点都封,真不怕遭报应啊,真不怕生娃没菊花啊,真不怕被钉在耻辱柱上啊。好歹你们丫的还是技术人员,不能有diang性就没人性了啊!草泥马。

p.s. 原文地址:http://chunyemen.org/archives/813
p.s.s. 欢迎访问纯爷们的小生活

Posted in 我和小老婆之间的事.

Tagged with , .


拜拜2012

转眼一年就过去了,工作之后的日子真是比在学校快多了,现在的杭州温度已经降到了零下,不过今天阳光明媚,吃过早饭,坐在窗户边的椅子上,泡上一杯龙井茶,开始回顾2012这一年。

去年写过6个愿望:

  1. 家人平安快乐,包括某猪
  2. 工作上能够承担更大的事情,把现在的事情做好,做大
  3. 努力学习电吉他,要脱离当前弱到爆的水平
  4. 回趟天津,而且得是上半年,不然真就见不到人了
  5. 最后的,也是最难的,希望年底地时候能够毫不犹豫地说出”what can make me CRAZY?”这个问题的答案

现在来一一回顾:

  1. 家人都身体健康,平平安安。谢谢老天的眷顾。
  2. 当时指的是实时流计算的项目,现在由于组织架构的原因,已经废弃。这里头有太多需要总结的了,后面会说。
  3. 年中的时候报了个吉他班,现在电吉他算是入门了吧,不过因为很少练习,水平一直很低。
  4. 没回去,失败了,没兑现。
  5. clojure,连我老婆都知道怎么念这单词了。

2012剩下不到12个小时了,不算这一篇,这一年我一共写了21篇博客,出去吐槽和絮叨的部分,剩下14篇都是技术相关,其中10篇是写clojure。算下来平均一个月一篇吧,有点懒了,明年应该是两周一篇才对得起自己。开始回顾!

1月

  1. 那个时候还有搜索平台部,年会很high,记得最后喝了好多酒,记得被提名了,可是没有得奖,记得搞了个吉他+口琴+太极版本的《大海》,很囧,是吧?
  2. 买了《三体》1和2,加上家里的3,已经凑齐了,很满足,可惜过年没有好好通读一遍。要不今年?
  3. 跟别人拼车回家,杭州到重庆一千多多公里,虽然一路上很顺利,但是最后弄得有点卓急,以后再也不拼车了。
  4. 带着活儿回家,放假还要抽时间写代码,每天汇报线上情况,怎么说呢…
  5. 过年回家最快乐的两件事情,一是见亲人朋友,二是各种好吃的。

2月

  1. 新一年的工作开始,来到DW的项目室,这段经历给了我很大的成长,当然,成长多半是痛苦的。不过,我很感谢。在不合适的时间点,每个人(包括我)又代表不同的部门,各自怀揣目的,不可能把一件事情做好。相互的不信任,没有一致的目标,是团队失败的根本原因。从自身来看,我们的系统概念复杂而且含糊,组件太多,可操作性太差,不必要的性能损耗过高,坑又太多,是我们自己失败的原因。或许,痛过才能证明爱过,这些痛也代表这我们对系统倾注的心血,也是我们成长路上必须要过去的坎儿。
  2. 开始学习clojure,全是中文资料几乎没有,真庆幸自己能够有耐心一点点看下去。

3月

  1. 合租的同事要离职,准备搬家,找房子真的是很麻烦的事情,很纠结,好在最后找到了现在的住处,价廉物美~
  2. 加班挺多,老婆经常在晚上等我一起回去,对你说声谢谢!
  3. 春天逐渐来临,跟悟时夫妇(人家现在是合法的了)以及侯一起到处逛逛,晒太阳。躺在草地上看风筝,看风筝背后湛蓝的天空,真是惬意。
  4. 黑皮的女儿出生了,拉开了今年周围的人生女不生男的序幕,预约了干爹的位置。

4月

  1. 开始做4clojure,有种当年坐acm题才学会cpp的感觉。其实学语言没有什么窍门,唯有coding!coding!coding!
  2. 团队的技术分享再度搞起来,当然零食少不了的,这种氛围很自在,很惬意,至今难忘。
  3. 老婆回学校做毕设了,留下我在杭州瞬间变成屌丝,各种煮面、泡面。偶尔做几个菜,却突然没有食欲。一个人去看电影,感觉跟周围格格不入。一个人,真是不舒服。
  4. 团队outing去泰国,5天6夜的旅行果然很赞,赞的不仅仅是资本主义特色的东西,跟多的是放松的心情和预约的旅程!

5月

  1. 开始捧着ipad读《Programming Clojure》和《Clojure in Action》,每天晚上基本上是2点睡,不是看书就是4clojure刷题,深深记得半夜写了个层层嵌套的代码被别人40个字符秒杀….以上这一切是因为…因为..没人管我…
  2. 跟悟时一起做系统的新版本,实践这自己幼稚的开发理念。
  3. 问老婆“今天想我几次?”,答:“一直在想啊,不是离散变量,是连续的。”
  4. 春天越发放荡起来,某易边上的草坪已经很茂盛了!年度的集体婚礼又来了,可惜那天晚上我在加班,不过最后跑过去看到了齐秦~
  5. 老婆顺利通过答辩。

6月

  1. 变化来临,团队被拆,吃完最后的午餐,拿着乔毅送的零食,照完最后的大合影,吃玩毛妹的宴请,送走长帅去北京,大家成为首批去一淘的人,在b2b最后的日子显得这么的不舍。
  2. 在一淘躁动了几个星期,最终还是暂时安定下来。回首这段时光,自己的想法和行动都是那么的幼稚,幼稚,幼稚,不过我庆幸最终我做出的选择是正确的。

7月

  1. 慢慢习惯每天俩小时在班车上的生活,偶尔还能在班车上睡上一觉,基友们都渐渐搬到城里去住了,最后剩下我一个人每天在滨江和城西之间来回。
  2. 在一淘的日子显得特别的清闲(也许就我是这样的吧),每天到公司要看一个小时微博,中午伙同以前的团队的基友们四出觅食,晚上打两个小时桌上足球,故障报警都跟我没关系,我只要每天写写文档,搞搞daemon。
  3. 继续学吉他,老师华了2/3的课程来教我古典吉他,但是我倒觉得挺好,至少哥会看五线谱了~
  4. 老婆入职~

8月

  1. 台风袭来,在家soho了一天~其实啥也没干。
  2. 每周五下班都觉得特别开心,因为回家刚好可以看《中国好声音》,至于奥运,就看了看林丹的决赛。
  3. 老妹来杭州实习,在这里呆了一个星期,很遗憾没怎么一起到处去耍,只是吃了顿火锅。
  4. 最终还是离开一淘,去了集团TimeTunnel团队,一去就开始学习维护线上系统,学习处理各种警告,比一淘的时候真是压力山大。
  5. 老婆上了茶艺课,俺送了一套茶具给她~这套茶具使用频率还是很高的。
  6. 今天给老婆讲了间谍偷lisp程序,偷到三页括号的笑话,她笑了,还说后三页肯定都是右括号。你太让我骄傲了!

9月

  1. 秋日将至,树叶渐黄,班车外是欣赏不完的风景,一年四季,每天都不重样。城里有个5A级景区,这一点是杭州最爽的地方,我就不说还一个很破很乱的火车站了。
  2. 在集团的工作逐步步上正轨,了解老系统,开发新版本,维护线上,这一切对我的成长来说是很宝贵的,我至少看见了一个线上实际运行的系统应该是什么样子的。
  3. 买了本《Go语言编程》两天看完了,之后我再也没碰过那本书,不过Go却是是个好东西,有机会我会考虑使用的,不过哥当然更喜欢Clojure,哈哈。
  4. 受不了各种断网了,果断买了个ssh账户,现在世界清净多了。可是前不久新闻说不能使用“非法代理”,我就查查技术资料,应该没事儿吧。。。。
  5. 好声音押宝梁博夺冠,InfoQ送了张QConf的门票,可惜那天哥有事情,没去成,浪费了。

10月

  1. 十一长假,跟老婆大吵一架,然后分别离家出走。好在后来和好了,才能够去参加毛妹的婚礼。
  2. 利用业余时间,开始做第一个自己的clojure项目——zk-web,完完整整做下来,感觉收获很大,在github上得了好些星星,很开心啊~

11月

  1. 继续给zk-web添加功能,clojure这东西玩起来真的很high,你会发现很多以前ugly and dirty的事情都会变得simple and elegant。
  2. 毛妹要离职了,哎,真心不舍啊,一起入职的几个同事,慢慢的,慢慢的,都在不同的地方,那种遗憾的感觉,是因为我们之间真不是同事那么浅薄的关系。祝福~
  3. 经历了淘宝的11.11,系统经受住了考验。凡是经历过11.11的码农,经验值肯定暴涨,自信心也会提高!
  4. 开始看《Joy of Clojure》,这本书果断买纸质版了。英文比前两本书要难一些,不过边查边看,会了解更多。clojure不仅仅是简单的jvm+lisp,背后关于状态、简单等问题的思考才是吸引我的根本原因。

12月

  1. 学会做鱼香肉丝了,应该可以拿到业余厨师的毕业证了吧~
  2. 在微博上弄了一个clojure的微刊,本来想把相关资料搜集起来跟大家分享,结果这个屎一样的产品搞的哥毫无兴趣。
  3. 我跟她求婚了,只是戒指买大了2号……法律流程什么的都是浮云了。

然后,是2013年的愿望,或者要达成的事情:

  1. 家人都身体健康,平安是福。
  2. 两周一篇博客。
  3. 工作上能够有更大的提升,在实战经验上能有质的飞跃。
  4. 苦心钻研clojure,向社区大牛们看齐。
  5. 学习中式面点~俗称包子馒头花卷儿什么的。

That’s all!

Posted in 这是一个无名的小站.

Tagged with , .


zk-web——简单的zookeeper web UI

先说废话

最近工作挺忙,上一篇博客俨然已经一个月以前了。不过忙起来,觉得充实了很多,人的精神状态也比之前一阵好了不少。总之,现在状态还挺好,空余时间还能看看书,写写东西。

再说起因

为啥要做一个zookeeper的web ui呢?命令行的东西一般来说还是很强大的,可是zk的client却有点弱。工作的时候,我一般都习惯在web上查看zk的数据,并做一些简单的操作——删除,新增,写数据之类的。之前我一直使用killme2008大牛的node-zk-browser。可是这玩意儿是node.js写的,而我对node.js一窍不通,也没想过要通,安装部署就废了老大的劲儿。再加上有时候想改点东西,就无从入手了。于是,程序员造轮子的贱毛病就犯了。想想,用clojure写吧,正好练练手。于是就开始了。

再说过程

简单思考一下,一个zookeeper的web ui无非包含以下三个部分:zk连接,web框架,css框架。下面说说三个部分的选型:

zk连接

我认为没有比curator更好用的zk客户端了,真庆幸悟时很早就把他介绍给我。curator虽然好用,api却略显啰嗦。不过用把curator wrap到clojure中,只留出最简洁的api,却是十分容易的,clojure很擅长这个。这部分代码在zk.clj中,目前只有区区57行。

web框架

clojure的web框架有很多,compojure, ring, noir等等,这些东西之间是什么关系我还有点傻傻分不清楚。noir定义了丰富的宏,把compojure和ring封装起来,api简洁优雅,深深吸引了我。无论是定义页面(defpage)、页面元素(defpartial)、生成html(使用hiccup)、post/get处理、session管理、cookie管理,都以简单得不能再简单的方式呈现出来,深得clojure的至简之道。感谢noir,感谢clojure,这部分代码只有100行多一点。

css框架

我是web白痴,我需要一个白痴级别的框架。经同事介绍,twitter的boostrap符合条件,再加上我们的TimeTunnel的管理系统也使用了boostrap,页面大方美观,于是css就使用boostrap了。使用boostrap后,基本不用写css了,只需要给你的页面元素写上各种class就好。

再说现状

zk-web现在read-only的部分基本完工了,如果你只是查看zk的数据的话,用zk-web基本能够满足你的需求了。简单贴点图:

首页上会记录最近访问的三个zeekeeper地址,直接点击即可访问,数据记录在cookie中。也可以输入新的地址。

节点的详情页面顶端是每一级祖先节点的链接,左边是孩子节点的链接,中间是节点的信息,右边是数据。

最后说将来

以后计划增加节点增删改的功能,以及针对xml,json的pretty-print。现在想到的就这么多,代码在https://github.com/qiuxiafei/zk-web,欢迎关注。

p.s. 欢迎访问纯爷们的小生活

p.s.s. 原文地址:http://chunyemen.org/archives/789

Posted in 我和小老婆之间的事.

Tagged with , , , .


Mac Mountain Lion下配置Safari局部代理

首先问候一下方校长的祖上…让我没法欢度国庆!
于是昨天买了个ssh,倒腾了一下,现在上网畅快了。现在把配置方法纪录一下。

需要交代的:

  • 系统环境Mac OSX 10.8.2
  • 需要使Safari能够对部分网站使用代理(别跟我提chrome+swity!, 权限好烦)
  • 你需要有一个ssh帐户

第一步,启动本地代理转发

使用如下命令:

ssh -D 7086 ssh-user-name@ssh-host-name.domain

7086是ssh转发时监听的本地端口,我们只需要把请求转发到localhost:7086,就可以实现通过ssh代理访问目标网站。

第二步,配置.pac文件

.pac实际上就是js,需要定义一个FindProxyForURL(url, host)的函数。浏览器根据函数的返回值选择直连或者使用代理。我的.pac如下:

function FindProxyForURL(url, host)
{
    url = url.toLowerCase();
    host = host.toLowerCase();
    if(dnsDomainIs(host, "twitter.com")
        || dnsDomainIs(host, "blogspot.com")
        // and more
            )
        return "SOCKS localhost:7086";
}

第三步,制定.pac文件

将写好的.pac文件放到/Applications/Safari.app/Contents/Resources/下
你需要在系统偏好设置-网络-高级-代理中选择自动代理配置,单击选取文件,选择刚才的.pac文件。如果你找不到上述路径,command + shift + G,输入路径即可。

好了,打开Safari,浏览某些网站吧。
如果更改了.pac文件,需要重启Safari才能生效。

p.s. 欢迎访问纯爷们的小生活
p.s. 原文地址:http://chunyemen.org/archives/782

Posted in 我和小老婆之间的事.

Tagged with , , , , .


Challenge Python Challenge in Clojure

玩python的同学,肯定都知道PythonChallenge这个游戏,既学习了python,又锻炼了智商。今天,我试试用clojure来解决里面的题目。具体的解题思路就省略了,主要谈谈怎么使用clojure。

Level 0:   2的38次方

卧槽,clojure.core里头怎么找不到求乘方的函数!?一开始就这么不顺。那就取个巧吧,谁让这个底数是2呢…

user=> (bit-shift-left 2 38)
549755813888

于是得到下一题的url。

Level 1:  一个简单的解码。

图片已经提示了,是ansic码加2,具体实现需要处理一下非字母表字符和一点边界情况。用map来得最直观:

(def data ".........")
(defn decodec 1
    (cond
        (not (Character/isLowerCase c)) c
        (= c \y) \a
        (= c \z) \b
        :else (char (+ 2 (int c)))))
(apply str (map decodec data))

Level 2: 找字母

页面源代码中给出了一大坨乱码,并且提示说找出其中的字母,很简单,上filter:

(def data "………")
(apply str (filter #(Character/isLetter %) data))

得到”equality”,进入下一题

Level 3: 找特定字母组合

页面中同样给出一大坨字母,提示很明显了,找出左右被3个大写字母包围的小写字母。这种情况正则处理比较合适,比如re-seq

(def data "………")
    (->> (re-seq #"[a-z][A-Z][A-Z][A-Z][a-z][A-Z][A-Z][A-Z][a-z]" data)
         (map #(nth % 4))
         (apply str))

re-seq返回所有匹配的串,详见clojuredocs: re-seq。
我们得到下一题的链接:linkedlist

Level 4: Follow Web Link

很有意思,大意是要根据页面的提示,跳转到另外一个页面,一直follow到最终的页面。我们需要做两件事情

  • 通过url获取页面
  • 解析页面,获取新的url

获取页面推荐使用reader + line-seq的组合。reader函数返回一个java.io.BufferedReader,支持从文件名,String,URL,InputStream,Socket,byte array等方式构造,相当的帅啊!line-seq则是从java.io.BufferedReader返回一个按照换行符切分的字符串lazy sequence。这俩基本上算绝配。剩下的事情就是写个循环了….

(defn get-list [start]
    (loop [n start]
        (let [url (str "http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=" n)
              data (first (line-seq (clojure.java.io/reader url)))
              target (re-seq #"\d+" data)]
            (println url data target)
            (recur (first target)))))

从”12345″开始,

(get-list "12345")

按照中间的提示:

; 16044 divided by 2
(get-list "8022")

最后进入下一关:peak

Level 5:python反序列化

这个有点坑爹了….完全python的语言特性,你让哥怎么搞!你让哥怎么搞!!
怎么搞?当然用python搞了!
这里使用一个小trick,通过shell调用python,然后….不说了,太猥琐了,上代码吧

(require '1)

(def stdin "import urllib,pickle
obj=pickle.load(urllib.urlopen(\"http://www.pythonchallenge.com/pc/def/banner.p\"))
for line in obj:
    print \"\".join(map(lambda pair: pair[0]*pair[1], line))")

(println (:out (sh "python" :in stdin)))

你能在终端上看到答案的….
啥时候试试clojure-py…应该能有不那么猥琐的解决方法..

p.s. 欢迎访问纯爷们的小生活
p.s.s. 原文地址:http://chunyemen.org/archives/769

Posted in 我和小老婆之间的事.

Tagged with , , .


三荣三耻以自省

以静心学习为荣,以无聊吐槽为耻。
以看书阅读为荣,以沉迷微博为耻。
以勤奋抠腚为荣,以胡言乱语为耻。

Posted in 脑子里什么在转悠.

Tagged with .


都是反射惹的祸

最近哥很郁闷…不过不想谈郁闷的事情…

哥一直觉得clojure的map肯定没有java原生的map快,为了验证想法,前一阵子哥做了一个实验:

user=> (import java.util.HashMap)
java.util.HashMap
user=> (def mp (HashMap.))
#'user/mp
user=>  (time (dotimes [n 10000000] (.put mp 1 1)))
"Elapsed time: 10024.797 msecs"
nil

可以看到,把HashMap的put操作做一千万次,耗时约10秒。再看看clojure的版本:

user=> (def mp {})     
#'user/mp
user=>  (time (dotimes [n 10000000] (assoc mp 1 1)))
"Elapsed time: 328.825 msecs"
nil

好吧,clojure原生的map竟然只要300多毫秒,话说那个时候哥还不知道clojure里头的反射原理,只觉得此事严重违背了知觉,相当坑爹。
反射的地方在这里:

(.put mp 1 1)

为什么呢?
clojure不知道mp的类型是啥,即使你之前把mp定义成了HashMap对象,可是在别的时候,你也可能改变绑定的关系,所以,clojure还是不知道mp的类型是啥。既然不知道类型是啥,那只有通过反射来找出mp对象名字叫”put”的方法。
clojure有一个打开反射警告的开关:

user=> (set! *warn-on-reflection* true)
true

打开之后,在发生反射的地方会打印警告:

user=>  (time (dotimes [n 10000000] (.put mp 1 1)))
Reflection warning, NO_SOURCE_PATH:5 - call to put can't be resolved.
"Elapsed time: 9853.678 msecs"
nil

通过type hint,我们可以告诉clojure某个对象是什么类型,就能避免反射:

user=>  (time (dotimes [n 10000000] (.put ^HashMap mp 1 1)))
"Elapsed time: 100.548 msecs"
nil

于是,没有警告了,速度也快了。

不过,个人觉得,太多的type hint让clojure原本融洽的代码变得有点恶心…唉…

p.s. 欢迎访问纯爷们的小生活

p.s.s 原文地址:http://chunyemen.org/archives/761

Posted in 我和小老婆之间的事.

Tagged with , , .