WTF They(Google) kills my project before I do it by myself!

May 31, 2011

Spring cleaning for some of our APIs

I’ve found and maintained Google APIs for .NET project since 2009.

Although I’m busy in another scala project and nearly forgot Mirosoft Windows, I think I should update the project often.

Now Google gonna kill their APIs and kill my project too.

I will continue to maintain this project until all those APIs inaccessible.

Thank you all!

IL

 

社交网络的流行密码

May 31, 2011

from 商业价值

作者:王伟 成远 | 发表时间:五月 – 31 – 2011 | 分类:变量

当社交网络让传播信息的成本急剧降低,我们该如何把握流行?

在最新一集热门美剧《生活大爆炸》中,谢耳朵和艾米发现模因(即Meme,指八卦和其他社交信息)像传染性生物一样繁殖自己,并将人类作为宿主。他们使用了“模因流行病学”的理论在朋友中进行实验,同时用带有刺激、恶性和世俗信息的八卦勾引朋友,以检验前者是否传播得更快。

 

4月20日,开心网以这集《生活大爆炸》的故事做开场,发布了独立于开心网的群组产品“海贝”。开心网品牌战略总监孙璐说:“八卦在小圈子、小群体里传播,传来传去不出几个人。而放大到现实世界,还会有‘好事者’(连接不同圈子的结点用户)将小圈子八卦传播到另一个圈子,甚至有些变成社会流行新闻。模拟这些特点,海贝具有严格邀请注册和一键跨群分享等功能。

显然,这种对于信息传播的深入思考,今后必然还会引发更多的功能和应用。

在《商业价值》对社交网络的系列思考里,我们曾在上一篇报道中描述了一个社交新世界的到来——这是最好的时代,也是最坏的时代。好处在于,如果你想成为主角,社交网络能够帮助你迅速成为焦点;坏处在于,所有人都像孤单的游鱼,瞬间就被淹没在信息的海洋中。在这个时代,每个人自觉或不自觉地成为了数字移民,迁移着过去的关系,也构建着新的自己。

那么,社交新世界让信息传递的成本前所未有地降低,我们该如何在这个新世界中把握流行的密码?

被免疫的病毒传播

技术哲学大师凯文·凯利曾经提出过“传真机效应”的理论:第一台传真机的研发费用高达上千万美元,零售价格也要超过2000美元,但是这台传真机却毫无价值,因为世界上还没有其他传真机可以同它联系。第二台传真机的出现使得第一台传真机具备了价值,第三台传真机让前两台更有价值,以此类推。因此凯文·凯利得出结论:用户买下传真机,实则是买下整个传真网络——这个网络远比传真机本身更加值钱。

凯文·凯利的理论为市场营销专家带来了直接的启发:在社会网络中要想创造流行,就要尽可能地扩展这个网络的宽度和广度,加入网络的人数越多,流行影响的范围就会越广。然而遗憾的是,急剧扩大的网络固然增强了产品所能影响的范围,但对网络的过度迷信者却为自己掘下了坟墓。

在社交网络出现初期,由于信息传递的成本极度降低,于是就出现了一发不可收拾的病毒营销和疯狂的粉丝买卖。广告商兴奋地看着自己的广告传达到的人群与日俱增;然而不久,他们就发现这些铺天盖地的信息轰炸,不仅没有带来更多忠实的客户,反倒是每年巨额的广告费用大都打了水漂。买卖粉丝的人看着一夜骤增的粉丝数目,除了满足虚荣并未有更好的感觉,因为这些粉丝中的大多数根本无法与之形成有效的交流。

事实上,病毒传播的最大克星恰恰是用户的免疫。例如,每一次流行感冒发生时,感冒病毒都会创造了一个巨大的网络。在这个网络中,感染病毒的人越多,流行病就越有威力;然而,流行感冒大都不久之后就中止了,原因在于通过接种流感疫苗,大多数人对感冒病毒具有免疫力之后,这流行也就结束了。足够大的、能够被影响的网络固然是流行的先决条件,但过度的病毒传播引发出受众免疫力,则会最终葬送这场流行。

20世纪70年代末期,电话的普及使得商家意识到这是一个经济高效的推销方式,从此针对目标客户家庭的电话推销增加了10倍。但是真相却是,在那之后的20多年里,电话推销的有效性却降低了50%。网络越大固然威力就越大,但是在网络规模扩大的同时,网络成员遭遇的骚扰也就越多,他们的免疫力也就越发提高。

人们关于流行的社会学认识,也因为社交新世界的诞生出现了许多进步。斯坦福大学计算机科学系的助教朱·莱斯科夫(Jure Leskovec)曾经做过一个在社交网络上进行产品推荐的实验。结果显示,在通常情况下,病毒式的推广并不能有效地推动用户的实际购买行为,同时病毒式推广的传播范围和实际影响亦有限,过度推广反而造成负面结果。对于用户确实不需要的产品,即使是社交关系中的强关系做出的推荐,也往往达不到预期效果。唯一让病毒推广的支持者欣慰的是,相对于其他产品,宗教类和科技类的产品更适合进行病毒推广。

莱斯科夫还和斯坦福大学在读博士生Jaewon Yang在新著的两篇研究论文中揭示了新闻在线共享的模式,从而提供了一种提早预测新闻流行度上升还是下降的方法。他们研发出一种工具,可以画出信息在网上传播的流量图。这个可视化的效果显示了博客与新闻网站之间的联系。

他们分析了1年内的1.7亿篇新闻文章和博客,以及8个月内的Twitter微博。他们跟踪每篇作品在其他博客、新闻和微博中提到的次数,以测量其受到的关注度。他们不看链接,而是跟踪博客和文章中有特色的词组——如“做无用功”(lipstick on a pig)——的出现频度。他们利用这些数据创建了一个揭示6种不同模式的图表。例如,一些新闻快速传播达到顶峰后消失,图上形成一个尖峰形状。其他的则更有持久力,上升和下降都比较平缓。

“通过观察特定类型的媒体在什么时间节点上参与到转播中来,你能看到不同模式的出现。”莱斯科夫说。例如,如果某事件由一篇博客爆料,其传播模式会与传统新闻媒体爆料不同。莱斯科夫说,“博客在哪一点上介入报道,是决定新闻持久性的一个主要因素。比如,即便传统媒体只短暂集中在一篇报道上,而博客的讨论却能让该新闻更长时间地停留在公众的视野中。

莱斯科夫认为,预测一则新闻或任何其它消息在网络流行的广度,可以帮助网站更有效地安排其内容和广告。这种方法也能显示出作者或博客是如何被共享的,并以此来判断其影响力。通过研究新出现的新闻的早期反响,研究者能够预测较长一段时间里某个内容的流行程度图,准确度达75%。

莱斯科夫说:“这些结果与预测工具结合使用时将更加有力。这些工具能预测一个新闻获得的关注量,而不是只预测其传播的模式。为预测关注量,研究者要看新闻的发布地点、主题以及其他因素。”

莱斯科夫的研究是建立在大规模实时数据的基础上,实验条件的改变让该领域的研究者们相信,流行是可控、也可以制造的,虽然模因本身具有突变性和不稳定性。

制造模因的四个法则

前不久,社会化问答网站知乎里,一个豆瓣面试产品经理的问题在11个小时内成为当时知乎最热门的帖子。与知乎里其他问题和回答不太一样的地方是,这个问题的提出者是参加豆瓣产品经理的压力测试被“刺激”到的应聘者,回答者则是他的面试官。提问者的叙述口吻还有时下网络流行的“吐槽”特点。

同样是知乎上的一则公司八卦——“腾讯员工朱小草关于马化腾的评价”,在新浪微博上被转发(截止发稿时间)近3000次之多。

从很多流行案例中,我们发现其实传播起来的八卦或者模因具有一些共同特征:比如内部人、简短易懂、社会或小群体环境、短时间爆发、具有故事性等。我们可以粗略总结为“模因制造”的四法则:

一、内部人法则

流行制造的第一步是信息源可信任。解决可信问题,内部人是一个很好的组成元素。这方面的商业案例已经很多。

1990年,雷克萨斯轿车在美国刚刚建立其豪华车生产线不久,技术人员发现LS400车生产线上的两个小问题,产品需要被召回。这让本想围绕质量和做工占领市场的雷克萨斯无比尴尬——进入美国市场才一年,就要承认自己旗舰产品的质量问题,实在让人难堪。

相对于以往在媒体道歉、发布公告的传统做法,这一次雷克萨斯独辟蹊径:在产品召回的当日,分别给每一位用户打电话。用户从经销商那里检修完车之后,每一辆车都被认真清洗,并且免费把油加满。如果用户住处距离经销商超过100英里,专门的技工会登门拜访。

雷克萨斯的做法一时被圈内人士认为过于紧张。事实上,雷克萨斯清楚的知道愿意冒险购买一辆新上线的豪华车的顾客是什么样的人群。当时的用户数量虽然只有几千人,但这些人都是汽车内行,热衷于谈论汽车,是朋友圈中汽车方面的权威,人群虽少但却决定了这个汽车品牌在新市场的口碑。事情的结果印证了雷克萨斯管理层的判断,一场本会成为灾难的汽车质量问题却为公司赢得了客户服务的美誉。

雷克萨斯的案例中,企业的高明之处在于牢牢抓住了品牌形象传播中最核心的一群人——内行,借助这些人的意见权威引爆了一个品牌的流行。这也就不难理解为什么国外的一些香皂品牌会在产品说明书中留下客服电话——几乎没有人会为如何使用香皂咨询客服的,然而厂家却了解:哪怕只有一个人打来电话,那个人一定是对香皂产品充满热情的人。他或者是香皂内行,或者是设计专家,他们的建议对于产品的改进意义重大。通过一个客服电话,香皂厂商就能轻松地找到对于他们意义重大的“内行”。

这些“内行”在品牌传播的网络中或许只占微不足道的比例,但是他们却对于流行的引爆意义重大。在社交网络上,他们可能就是那些超级链接者,或者是能够影响细分人群的意见领袖。如何准确的找到并影响他们,很大程度上能够助推产品的流行。

二、环境法则

人类归根结底是社会动物,尽管大多数人自认为意志坚定,但是没有人能够做到完全不受环境的影响。

上世纪70年代,斯坦福大学社会学教授菲利·普津巴多曾做过一个著名的“囚徒实验”。他和他的助手们在斯坦福大学心理系大楼的地下室建立了一座模拟监狱,通过当地报纸招募了75名身心健康的志愿者。他将这些社会志愿者连同一些教师志愿者分成两组,一组作为守卫,一组作为囚犯。津巴多让当地警察局协助,以一个假罪名逮捕了这些囚犯并将他们关进了监狱,由另外一批志愿者看守,模拟监狱的情形。

实验结果让人大吃一惊,那些原来以为自己是反对暴力、品行优秀的看守们,很快变成了冷酷的训导者。第一天晚上,他们在凌晨把囚犯弄醒,强迫他们做俯卧撑。第二天,囚犯们造反了,他们开始拿着灭火器和看守对喷。随着实验的进展,看守们变得越来越残忍,个个施虐成性,不少囚犯已经变得极度精神抑郁。以至于到后来,身处其中的人已经忘记了那只是一个模拟的监狱而已。

津巴多的结论是,在某些具体的情况下,人类内在的癖性会屈服于强大的情境,我们的亲人,身边的朋友都会对我们的行为产生影响。尤其是在社交网络中,我们的行为总是潜移默化中被他人影响,哪怕是一个自认为意志坚定的人。

哈佛大学的尼古拉斯·克里斯塔吉斯教授通过研究进一步证明了环境对个体的影响。他在TED做过一场演讲。他介绍了“寡妇效应(Widower Effect)” ——即夫妻当中的一个人过世后的那一年里,在世的另一人的死亡概率会翻倍。“寡妇效应”和其他一些相似的现象引发了克里斯塔吉斯的思考。他意识到,类似的现象不只是发生在成对的人当中,而是存在于整体社会中。社会中的众多独立个体组成了巨大的社会网络,人与人直接或者间接地相互影响。当一个陌生人朝你微笑的时候,你也会用笑脸来回应,这就是社会网络中人与人之间相互影响的一个例子。

更令人印象深刻的例子是,克里斯塔吉斯分析了肥胖“传染”的方式。这种“传染”更复杂,更神秘。它不像SARS病毒那样从一个中心点向外传播开去,而是包含了多个方向的相互影响。研究显示,在这30年里,超重的人越来越多,并且与肥胖者关系越近的人,发胖的机率越高。另一个研究结论更让克里斯塔吉斯震惊:即使一个肥胖者死了之后,他的影响依然存在,社会网络会自发地试图恢复到从前的状态,就像有记忆力的生命体一样。

三、简约法则

奇普·希思《让创意更有黏性》一书中,提出的创意让人们记住的第一法则就是简约。在该书中他例举了不少商业案例:

壳牌是一家拥有百年历史并且始终居于《财富》500强前10位的明星企业。在其推行的新的企业文化中包含了四大部分:简化、快速、业绩导向、关注外部,其中最核心的部分便是“简化”。这从一个侧面说明了越来越多的企业不再以自己复杂的流程为傲,而是希望用简单来应对当前混沌的商业环境。

当我们把网站做得无所不包之时,Google的首页却只放置了一个搜索框,但又有谁能够否认Google是全世界最实用的网站之一呢?

当以亚马逊为首的B2C网站将品类打造得无比丰富之时,Groupon却反其道而行,简化到每天只出售一种商品,并且价格极低,天天替换。这种让消费者始终处于期待与惊喜中的崭新电子商务模式成为了当下的一大热点,模仿者众多。

在乔布斯近乎偏执的坚持下,iPhone最终只在机身上留下了一个按钮。但就是这种简化到极致的设计,使得一部复杂的智能手机几乎不需要使用说明书,小孩都能够轻易的把玩。

我们的设计人员都太喜欢做“加法”了,不断添加更多的功能,但真正能“黏住”客户的始终是遵循简单理念的产品和服务,从Google到iPhone无不如此。设计领域有一条至关重要的原则:“Don’t make me think”。理解这点你就会明白,客户是不会花时间揣摩各个按钮的功能的,对于他们来说更简单的选择便是放弃,然后选择你竞争对手的产品——更友好、更简单的东西。

回到传播理念上,如果你想让对方完全理解你,就必须将内容设计得精简,核心观点必须让别人一目了然。正如硅谷的一些商业计划书能够写在餐巾纸的背面,而往往就是这样简单的商业理念最容易受到投资者的青睐。关于这方面的内容,还有另一本优秀的书籍《餐巾纸的背面》(The Back of the Napkin)可以提供更详尽的指导。

最后借用飞利浦的品牌承诺来为这段内容做一个简短的总结,那就是:精于心,简于型(Sense and Simplicity)。

四、时机法则

如果说在传统社会结构中,人们更多的还是关心环境影响这一空间因素的话,那么在信息爆发转瞬消亡的社交网络时代,对于时间因素的把握就显得至关重要。某种程度上来说,社交网络时代流行的把握更需要追求“时机的艺术”。

研究复杂网络领域的权威艾伯特-拉斯络·巴拉巴希(Albert-Laszlo Barabasi)在研究社交网络时代的信息传播后,得出结论称:由于信息传递速度的加快,如今的信息传播越来越从原来的长尾演变到“粗头重尾”,即现在的信息会在发布之时起,迅速爆发并迅速衰减。一篇文章,一条新闻能够风靡并流传数年越来越成为了历史。

对于希望在社交时代把握流行的人,或许更应该注意到“时机”的价值。在社交网络中,一条信息在什么时候开始推送,让它在什么时候影响到特定人群,越来越成为一种艺术而不单单是技术层面的实现。

值得注意的是,“模因理论”并不是为了制造流行而产生的理论,它是基于社会学、流行病学等研究基础上提出的大胆假设。“模因理论”的社会意义远大于它为商业制造流行带来的价值。在适当的时机,利用聪明的方法,模因甚至会推动社会变革,改变历史。

身为著名心理学家弗洛伊德的外甥,爱德华·伯尼斯试图把心理学理论和营销技巧相结合。一战爆发后,伯尼斯的构想找到了实践的机会。他参与美国公共资讯委员会(CPI),利用大众媒体、好莱坞电影等工具,成为推动美国参战的“说服工程”的幕后策划者,是“山姆大叔”形象的制造者。

更具社会学意义的是,模因中的一些不经意间会沉淀为一些习俗,这也是一个众多模因竞争的结果。最后,有助维持母体不死和低成本维系的模因被上升为习俗,成为社会文化和制度的组成部分。习俗会造成群体认同,个体不遵守会被视为异类,因此好的模因制造出来可以相互约束,维持社会秩序。

(Frost&Sullivan首席顾问王煜全先生激发了本文的诞生,并对文章内容有重要贡献。)

 

评:

关于“被免疫的病毒传播”

归根到底还是要看人们的需求。这就像喝咖啡,怎么喝,你还是需要睡觉的。

因此,应该关注如何给用户带来实际价值。

关于“简约法则”

简单固然很容易吸引人,大而全也是必要的。两者能有机结合,或许更是威力无穷。

如amazon与groupon结合。用户能看到所有分类商品。或是首页只有不到十个的推荐商品。

如facebook与twitter结合。用户可以看到自己的一堆应用,或者只有好友亲自传播的消息。

我们给用户切换的按钮。大多数时候让他们只使用特定最常用功能。如果需要,他们随时可以使用更多复杂功能来满足他们特定需求。

例如写blog时只有title和content。除非他们需要,才会让他们看到添加tag,隐私权限,是否允许回复等功能的按钮。

 

 

 

 

“Social Network” the movie

March 22, 2011

After I watched that, I finished my “Watch social network” task on my own site.

It feels good using my own site to do the job. For this feeling, I will make this site better, you guys will see that one day.

What’s I learned from this movie: I need move faster.

I have a good idea, no matter it’s good enough or not. Implement it quickly. Don’t make it too long. Or the idea will be rotten.

All your skill and your gift is just to implement your dream faster.

Don’t waste time. Work hard. Speed UP…

 

IL

Re: [scala] The right tool — by Martin Odersky

May 19, 2010

http://scala-programming-language.1934581.n4.nabble.com/The-right-tool-td2220305.html#a2222101

In reply to this post by Erik Engbrecht
On Mon, May 17, 2010 at 10:49 PM, Erik Engbrecht <[hidden email]> wrote:

I think Scala is very large compared to languages like Python or Java, but smaller than C++.
By “large” I mean there are a lot of concepts in the language.  Just to list a few that aren’t in Java…
… I am always a bit uneasy when reading a list like this and arguing with it. Yes, Scala has a lot of features but it tries very hard to make them facets of a uniform core which is not that large. I realize that for a newcomer, in particular someone brought up in the C/Java tradition, Scala might look large. For instance, objects/companion objects which you mention. If you do an in-depth study of language specs, these are actually significantly simpler then Java’s static class members. But static class members are known whereas companion objects are less well known, so they look more complex for most people.

Here’s a discussion of the other features you mention, in comparison to Java.

  • Higher kinded types

Yes, that’s definitely beyond Java. This is the one feature where for a long time I was not sure whether it is worth the weight. I have been leaning recently more towards believing that it will probably turn out to be quite useful.

  • by-name method parameters
vs special treatment of ||, &&, assert.
  • companion objects
vs statics (see above).
  • case classes
vs enums (arguably at least as complicated in both syntax and type checking).
  • structural types
Yes.
  • closures / first-class functions
Yes, until Java gets them, in which case Java’s will be more complex, due to throws clauses.
  • for comprehensions
vs extended for-loops, looks like pretty much the same thing to me.
  • mixin composition / multiple inheritence
vs extends/implements. Again, you might argure that traits simply drop some restrictions in interfaces.
  • self types
yes, sort of. Again we simply drop a restriction in Java on the type of `this’.
  • type inference
Not sure that adds complexity per se. Java does it as well, but more clumsily. Have you looked at the
<> notation in Java 7? How is that simpler?
  • currying
You might say, we just drop a restriction that functions have only one parameter list…
OK I concede, it’s a yes.
  • pattern matching (and associated unapply etc support machinery)
vs switches, which are getting more complex, and I always forget to put a break at the end of a case.
  • loose syntax for some language constructs, e.g. dropping parenthesis
Yes, but Java programmers have to learn that it’s array.length, but string.length(). Not sure what is better.
  • specialization
That’s an annotation-driven optimization. I don’t think we should count that
  • operator overloading
Compared to the large number of synactically defined operators in Java I think that’s a net win.
  • multiple parameter lists for methods
That’s a duplicate of currying.
  • parameter lists that come before the method name (colon prefixed operators)
You mean colon-suffixed, right? yes.
  • implicits (parameters, conversions, values)
Yes, but they let us avoid a lot of special cases.
  • stable ids vs non-stable ids
Linked to abstract types, yes.
  • default arguments
Yes.
  • lazy values
Vs special static member initialization, which also has lazy semantics.
  • added access qualifiers (e.g. private[this])
Vs dropping package level visibility.
  • XML as-a-language construct
Yes. That’s the second extension where in retrospect I am not sure it was a good thing overall. When we started out with Scala, XML was the showcase where functional programming could be clearly shown to be useful. At the time most people thought you could do everything with pure OOP. So we added XML.. Today, the case for FP is much stronger, and the case for XML has gotten weaker. So maybe the inclusion of XML in Scala was a historical accident. But anyway, it’s in, and will stay in.
  • …and I’m probably forgeting some…
So what does it drop from Java:
  • static members
  • field / method dichotomy
  • object / primitive dichotomy
I think you seriously underestimate the complexities in Java. Just some points, it’s far from an exhaustive list

- 4 namespaces (methods/fields/types/packages) instead of two.
- different name resolution rules for each namespace.
- enums
- annotations (yes Scala has them as well but they are much, much simpler than Java’s)
- some tricky syntactic corner cases to disambiguate between casts and expressions.
- nasty explicit parameterization. Does anyone even know how to pass a type parameter to a method in Java?
- over-reliance on wildcards, leading to very hard to diagnose type errors.
- restrictions on arrays with generics.
- raw types(!)
- restrictions that inner classes can only acces final members.
- super constructors.
- dataflow analyses for definite assigment and termination (these are actually useful, but burn about 20 pages in the spec).
- throws clauses and the rules governing them
- auto-boxing
- complicated rules what kind of casts are allowed where

A lot of these points look simple, but start to read up on their precise rules, they are anything but.

I don’t want to get into a feature to feature comparison between languages. My main point is, that, if you draw up a list of bullet points you can make any language look forbiddingly complex.

I certainly agree that if Java is your point of departure, then there is a lot of new stuff to learn in Scala. My argument is that there is also a lot of stuff in Java that people take more or less for granted but that is pretty complicated under the covers (and I argue from quite intimate experience here).

Some measures: The grammar of Scala is actually smaller than the grammar of Java. The typechecker of Scala is about the same length in lines of code as the type checker for Java, or the type checker for Haskell. Of course, every type checker is written in its own language, so you can draw an infinite number of conclusions form that, all of the form:

Scala’s type system is X-times more complicated than Java’s or Haskell’s, but code written in the language
is X-times more compact

where X ranges from 0 to infinity.

Cheers

– Martin

NUnit Framework for .NET Compact Framework and Silverlight

February 26, 2010

Unofficial NUnit Framework port for .NET Compact Edition and Silverlight.

Only nunit.framework project.

Now Add NUnit-2.5.3.9345 for .NET CF 3.5 and Silverlight 3.0. Please checkout and build via Visual Studio 2008 yourself.

Visit the project site here.

NUnit_Framework_for_CF_2.5.3.9345.zip

NUnit_Framework_for_Silverlight_2.5.3.9345.zip

Single Letter Programming Langage A-Z

December 16, 2009

Nearly every IT workers heard C language, because it is widely used, because its name is so simple — one single letter “C”.

If you think it is cool, you still have chance name your own language with single letter.

All unused letters in show below (O and X are my favorite :-):

H I N O P U V W X Y

A Programming Language

B Programming Language

C Programming Language

D Programming Language

E Programming Language

F Programming Language

G Programming Language

H Programming Language

I Programming Language

J Programming Language

K Programming Language

L Programming Language

M Programming Language

N Programming Language

O Programming Language

P Programming Language

Q Programming Language

R Programming Language

S Programming Language

T Programming Language

U Programming Language

V Programming Language

W Programming Language

X Programming Language

Y Programming Language

Z Programming Language

Memory leak in erlang.

September 15, 2009

Let’s talk about memory leak in java or .net first.

Maybe you think with auto Garbage Collection, there will no memory leak at all.

Suggest you write your own ArrayList. You pre-allocate a space when you create one. When you add more elements than your space, you allocate a new space twice as the old space, copy your data to the new space, and add new elements. It’s OK so far.

Now, we delete most of the elements, and, unlucky, you forgot free your space…

This is what we called memory leak in java or .NET. when you implement a ThreadPool, ObjectPool, HashTable, etc. be careful memory leak.

In  erlang, it’s nearly no cost to spawn a new process. And erlang encourage you create more processes. It’s erlang-style! We all like it!

All right.

Now I just port a java project to erlang. I make most of abject a gen_server. It’s natural. And It’s dangerous.

GC won’t free your gen_server, you need terminate it BY YOURSELF!! Every actors are everlasting, you need KILL them with your hands!

Any best practice for this kinda memory leak? Do not tell me “Supervisor + start_link”.

Object-Oriented on Erlang VM

September 6, 2009

Erlang is a *super* concurrent-oriented functional language.

Here, I listed some way to write object-oriented code for erlang. (Not just some shapes trick)

1. mudole as value.

ModuleName = math,
X = ModuleName:sqrt(16.0).

Ok, it’s not OO enough.

2. build-in parameter module and extends module.

-module(super).
-export([f1/0]).
f1() -&gt; super_f1.
%%%%%%%%%%%%%%%%%%%%%%
-module(sub).
-extends(super).

Try to call sub:f1().

-module(pmodule, [X]).
-export([x/0]).
x() -&gt; X.

And you can do this:

Obj = pmodule:new(cool),
Obj:x().

It’s true. You can do it right now! Although these features are experimented. see Inheritance in Erlang.

3. other object-oriented languages run on erlang vm.

Reia

ruby-style, every object is a gen_server.

Now, it’s compiler just compile the reia code into the erlang code.

See slide.

ECT(Erlang Class Transformation)

add object-oriented programming to Erlang.

see Object-oriented extension to Erlang.

WOOPER(Wrapper for Object-Oriented Programming in Erlang)

eXAT(erlang eXperimental Agent Tool)

Too old.

Enumeration class for string parameter

September 4, 2009

When I write the Google API for .NET, there are a lot of string parameters, like imageColor and safeLevel etc.

So I create an enum for every kind of parameter.

public enum SafeLevel
{
    off,
    moderate = 0,
    active,
}

I even set the moderate of SafeLevel as default value. And I can use the ToString method to get the string value most of the time.

Not every string parameter are so readable. They use “r” for relevance and “d” for date for instance.

At this time, I use extension method + switch.

public string GetString(this SortType value)
{
    switch (value)
    {
        case SortType.relevance:
            return "r";
        case SortType.date:
            return "d";
        default:
            return null;
    }
}

Or I use some helper class like LanguageUtility.

Everything is OK until Google add more choices of parameters.

Someone complained Google now can translate XXX language. Then I have to release a new version to follow the pace of Google!

The bad day has gone. Now I use string parameter directly. One can translate any language Google supported without complain and waiting.

But without enum and the helper class, API user need to check every parameter code from Google (like me).

For keeping life easy for all of you, I create the simple Enumeration class

public enum SafeLevel
    /// <summary>
    /// The enumeration. For parameters of Google APIs.
    /// </summary>
    public abstract class Enumeration
    {
        private readonly string name;

        private readonly string value;

        private readonly bool isDefault;

        /// <summary>
        /// Initializes a new instance of the <see cref="Enumeration"/> class.
        /// </summary>
        /// <param name="value">The value.</param>
        protected Enumeration(string value)
            : this(value, value)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Enumeration"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="value">The value.</param>
        protected Enumeration(string name, string value)
            : this(name, value, false)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Enumeration"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="value">The value.</param>
        /// <param name="isDefault">if set to <c>true</c> it is default value.</param>
        protected Enumeration(string name, string value, bool isDefault)
        {
            this.name = name;
            this.isDefault = isDefault;
            this.value = value;
        }

        /// <summary>
        /// Gets a value indicating whether this instance is default.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance is default; otherwise, <c>false</c>.
        /// </value>
        public bool IsDefault
        {
            get
            {
                return this.isDefault;
            }
        }

        /// <summary>
        /// Gets the value.
        /// </summary>
        /// <value>The value.</value>
        public string Value
        {
            get
            {
                return this.value;
            }
        }

        /// <summary>
        /// Gets the name.
        /// </summary>
        /// <value>The name.</value>
        public string Name
        {
            get
            {
                return this.name;
            }
        }

        /// <summary>
        /// Performs an implicit conversion from <see cref="Google.API.Enumeration"/> to <see cref="System.String"/>.
        /// </summary>
        /// <param name="enumeration">The enumeration.</param>
        /// <returns>The result of the conversion.</returns>
        public static implicit operator string(Enumeration enumeration)
        {
            if (enumeration.IsDefault)
            {
                return null;
            }

            return enumeration.Value;
        }

        /// <summary>
        /// Returns a <see cref="System.String"/> that represents this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/> that represents this instance.
        /// </returns>
        public override string ToString()
        {
            return this.Name;
        }

        /// <summary>
        /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
        /// <returns>
        ///     <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        /// <exception cref="T:System.NullReferenceException">
        /// The <paramref name="obj"/> parameter is null.
        /// </exception>
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(this, obj))
            {
                return true;
            }

            if (obj == null)
            {
                return false;
            }

            if (!this.GetType().IsInstanceOfType(obj))
            {
                return false;
            }

            return this.Value == ((Enumeration)obj).Value;
        }

        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public override int GetHashCode()
        {
            Debug.Assert(this.Value != null, "Value cannot be null.");

            return this.Value.GetHashCode();
        }
    }
}

It has three readonly properties: Name, Value and IsDefault.

It can also convert to string implicitly. Then you can use it as string. Or you can make it looks like the type of parameter is Enumeration but not string.

TranslateClient client = new TranslateClient();
string translated = client.Translate(text, Language.ChineseSimplified, Language.English);

It looks the same of the old enum parameter version. But the Language is not a enum but a subclass of Enumeration and the English is a public static readonly field.

public static readonly Language English = new Language("English", "en");

Here I want add two more static method and a implicit convert method.

public static Language GetDefault();

public static ICollection<Language> GetEnums();

public static implicit operator Language(string value)

It’s not hard using reflection. But I need repeat them in every subclasses of Enumeration.

Although code template tool can help me a lot, but I do not think it’s a good I idea. Don’t repeat yourself!

So I create a generic Enumeration class:

public abstract class Enumeration<T> : Enumeration, IEquatable<T> where T : Enumeration<T>

This class has a very interesting constrain. We can only create a subclass like this:

public sealed class SortType : Enumeration<SortType>

The subclass must pass itself as the generic parameter. (Tell me if I’m wrong.) In other words, the T in Enumeration is must be the type of subclass.

Here I marked SortType as sealed, because the Enumeration can only know it subclass but not sub-subclass.

Here is the whole code of Enumeration:

    /// <summary>
    /// The enumeration. Provide more static methods and properties for every concrete enumeration.
    /// </summary>
    /// <typeparam name="T">The type of concrete enumeration.</typeparam>
    public abstract class Enumeration<T> : Enumeration, IEquatable<T>
        where T : Enumeration<T>
    {
        private static T @default;

        private static IDictionary<string, T> dictionary;

        /// <summary>
        /// Initializes a new instance of the <see cref="Enumeration&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="value">The value.</param>
        protected Enumeration(string value)
            : base(value)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Enumeration&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="value">The value.</param>
        protected Enumeration(string name, string value)
            : base(name, value)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Enumeration&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="value">The value.</param>
        /// <param name="isDefault">if set to <c>true</c> it is default value.</param>
        protected Enumeration(string name, string value, bool isDefault)
            : base(name, value, isDefault)
        {
        }

        /// <summary>
        /// Gets the dictionary of value and enumeration.
        /// </summary>
        /// <value>The dictionary.</value>
        protected static IDictionary<string, T> Dictionary
        {
            get
            {
                Initialize();
                return dictionary;
            }
        }

        /// <summary>
        /// Gets the default enumeration.
        /// </summary>
        /// <returns>The default enumeration</returns>
        public static T GetDefault()
        {
            Initialize();
            return @default;
        }

        /// <summary>
        /// Gets all enumerations.
        /// </summary>
        /// <returns>All enumerations</returns>
        public static ICollection<T> GetEnums()
        {
            return Dictionary.Values;
        }

        /// <summary>
        /// Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <param name="other">An object to compare with this object.</param>
        /// <returns>
        /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
        /// </returns>
        public bool Equals(T other)
        {
            if (other == null)
            {
                return false;
            }

            return this.Value == other.Value;
        }

        /// <summary>
        /// Initializes this instance.
        /// </summary>
        protected static void Initialize()
        {
            if (dictionary == null)
            {
                dictionary = new Dictionary<string, T>();

                var type = typeof(T);

                ////var enums =
                ////    from propertyInfo in
                ////        type.GetProperties(
                ////        BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.GetProperty)
                ////    where
                ////        propertyInfo.PropertyType.IsAssignableFrom(typeof(T)) &&
                ////        propertyInfo.GetIndexParameters().Length == 0
                ////    select propertyInfo.GetValue(null, null) as T;

                var enums =
                    from fieldInfo in
                        type.GetFields(
                        BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.GetField)
                    where fieldInfo.FieldType.IsAssignableFrom(type)
                    select fieldInfo.GetValue(null) as T;

                foreach (var @enum in enums)
                {
                    Debug.Assert(@enum != null, "enum cannot be null.");

                    dictionary[@enum.Value] = @enum;

                    if (@default == null && @enum.IsDefault)
                    {
                        @default = @enum;
                    }
                }
            }
        }

        /// <summary>
        /// Converts the specified value to this enumeration.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="construct">The constructor function.</param>
        /// <returns>The enumeration.</returns>
        protected static T Convert(string value, Func<string, T> construct)
        {
            if (value == null)
            {
                return GetDefault();
            }

            T @enum;

            if (!Dictionary.TryGetValue(value, out @enum))
            {
                @enum = construct(value);
            }

            return @enum;
        }
    }

Here I use the lazy load trick but not initialize in the static constructor, because the static constructor will run before than the static fields in subclass have been assigned.

And the implement convert operation can only defined in the subclass. So I put most of the logic into the Convert method.

Here is what a subclass looks like:

    /// <summary>
    /// The search safety level.
    /// </summary>
    public sealed class SafeLevel : Enumeration<SafeLevel>
    {
        /// <summary>
        /// Disables safe search filtering.
        /// </summary>
        public static readonly SafeLevel Off = new SafeLevel("Off", "off");

        /// <summary>
        /// Enables moderate safe search filtering. Default value.
        /// </summary>
        public static readonly SafeLevel Moderate = new SafeLevel("Moderate", "moderate", true);

        /// <summary>
        /// Enables the highest level of safe search filtering.
        /// </summary>
        public static readonly SafeLevel Active = new SafeLevel("Active", "active");

        private SafeLevel(string value)
            : base(value)
        {
        }

        private SafeLevel(string name, string value)
            : base(name, value)
        {
        }

        private SafeLevel(string name, string value, bool isDefault)
            : base(name, value, isDefault)
        {
        }

        /// <summary>
        /// Performs an implicit conversion from <see cref="System.String"/> to <see cref="SafeLevel"/>.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The result of the conversion.</returns>
        public static implicit operator SafeLevel(string value)
        {
            return Convert(value, s => new SafeLevel(s));
        }
    }

Although the solution has some smell, like visit static method in superclass and static protected method.

I hope it can solve my problem well.

Thanks for reading.

Good! F# (May 2009) support tail recursion very well!

July 23, 2009

What’s the tail recursion?

In computer science, tail recursion (or tail-end recursion) is a special case of recursion in which the last operation of the function, the tail call, is a recursive call. Such recursions can be easily transformed to iterations. Replacing recursion with iteration, manually or automatically, can drastically decrease the amount of stack space used and improve efficiency. This technique is commonly used with functional programming languages, where the declarative approach and explicit handling of state promote the use of recursive functions that would otherwise rapidly fill the call stack. (from Wikipedia)

Still don’t understand? OK, let me show you the code.

int f(int n) {
    return f(n + 1);    // it's the last operation.
}

If you run f(0), you will get a StackOverFlowException.

How about F#?

let rec f n = f (n + 1)

The keyword "rec" tell compiler it's a recursive function.

We use Reflector to see how it looks like as a C# code:

public static a f&lt;a&gt;(int n)
{
    while (true)
    {
        n++;
    }
}

The magic the compiler done is called Tail Call Optimization. (see Adventures in F#--Tail Recursion in Three Languages)

Another case of tail recursion:

type t() =
member x.f1 n = x.f2 (n + 1)
member x.f2 n = x.f1 (n + 1)

This time, when you run t().f1 0, you will get the StackOverFlowException too.

Don't worry. Just open the F# project properties dialog and the Build tab. Check the "Generate tail calls" on. Then the exception disappeared.

See what's different of the IL code:

"Generate tail calls" unchecked

.method public instance !!a f1(int32 n) cil managed
{
.maxstack 5
L_0000: nop
L_0001: ldc.i4.s 0x2e
L_0003: call void [mscorlib]System.Console::Write(char)
L_0008: ldarg.0
L_0009: ldarg.1
L_000a: ldc.i4.1
L_000b: add
L_000c: call instance !!0 Program/t::f2(int32)
L_0011: ret
}

"Generate tail calls" checked


.method public instance !!a f1
(int32 n) cil managed
{
.maxstack 5
L_0000: nop
L_0001: ldc.i4.s 0x2e
L_0003: call void [mscorlib]System.Console::Write(char)
L_0008: ldarg.0
L_0009: ldarg.1
L_000a: ldc.i4.1
L_000b: add
L_000c: tail
L_000e: call instance !!0 Program/t::f2(int32)
L_0013: ret
}

One more case:

type t() =
member x.f3 n = x.f3 (n + 1)

No matter you check the "Generate tail calls" or not, the compiler will do the Tail Call Optimization.

The reflector will render it like this:

public a f3&amp;amp;lt;a&amp;amp;gt;(int n)
{
    while (true)
    {
        n++;
        this = this;
    }
}

Scala compile will do the Tail Call Optimization too, but there's no "tail" in JVM until now. So we need to wait for the Java 7.


Follow

Get every new post delivered to your Inbox.