Skip to main content

变色龙代码

最近的新玩具: https://github.com/coolwanglu/quine-chameleon

受mame的100个语言的quine-relay的启发,我想可否做一个完全图,即多个语言互相转换。
这样的程序英文叫multiquines,Wikipedia上有介绍,程序运行时需要指定一个参数,比如输出语言,然后程序会输出自身代码的对应那种语言的版本。如果指定参数就是这个程序源代码所使用的语言,那就是quine了。

网上有一个5种语言的multiquines,我看了看,不是太优美。我一开始就是朝着multiquines的方向写。然而后来注意到,不指定任何参数的时候对multiquines来说是没定义的(或者什么都不应该输出),这个有点浪费,于是我做了ouroboros(就像quine-relay那样)和随机转换两种模式。

再后来我注意到反而是不指定参数这部分更有趣,而且为了同时支持带参数和不带参数,需要各种判断,造成代码臃肿。于是我就把这两部分拆开,目前在源码中分别叫chameleon.*和multiquines.*。分别进行优化。

写这个东西最大的乐趣当然是不断加入新的语言。我开始不久就把自己熟悉的语言放进去了,然后慢慢添加新语言,不会的就现学现卖。基本上需要的语言特性和函数有如下几个

- 支持双引号定义的字符串,支持反斜杠转义
- 将字符串按分隔符切成数组
- 生成随机数
- 支持命令行参数
- 数组查找
- 字符串转义,或者json输出,或者字符串/正则式替换
- 输出(不带换行)

按目前的设计,第一条决定了一个语言是否能很容易的加入。这里比quine-relay难的地方在于,任何两个语言都要互相输出,所以最好能有一个公共的转义和还原的标准。而quine-relay中每个语言只需要考虑下一个语言的转义就好了,更方便预处理,支持新语言(比如whitespace,brainfuck)以及其他特性(比如字符串压缩)

我在写这个玩具的过程中也很自然的学习了一些新语言。之前为了写dunnet.js而研究了emacs lisp,这里还加入了其他lisp系列比如clojure,racket,发现写写脚本也还挺顺手的。只可惜scheme由于标准库太小以及srfi实现不统一没能加入。另外就是接触了之前完全不想接触的perl和awk,发现不但没有想像中的可怕,反而挺好用的。

ruby出乎我的意料,一直是各个语言中最短的,尤其multiquines的原始代码(不包含数据)只有80个字节!然而一般python就够我用了,也没有太大动力学新的。coffeescirpt和javascript经过不断优化也冲到了前面,不错!

其他值得一提的是,即使是之前比较陌生的go,lua,vala,我都能很快上手,一方面说明了文档齐全,互联网时代获取知识非常容易,另一方面我也觉得现代编程语言比较类似,语言本身已经成为了工具,脑子里有一些大概念就可以畅行无阻了。当然具体细节还是要慢慢学习和熟悉。

至于C家族,你们就乖乖在最后好好歇着吧。。。

Comments

Popular posts from this blog

[转] UTF-8 and Unicode FAQ for Unix/Linux

这几天,这个东西把我搞得很头疼 而且这篇文章好像太大了,blogger自己的发布系统不能发 只好用mail了 //原文 http://www.cl.cam.ac.uk/~mgk25/unicode.html UTF-8 and Unicode FAQ for Unix/Linux by Markus Kuhn This text is a very comprehensive one-stop information resource on how you can use Unicode/UTF-8 on POSIX systems (Linux, Unix). You will find here both introductory information for every user, as well as detailed references for the experienced developer. Unicode has started to replace ASCII, ISO 8859 and EUC at all levels. It enables users to handle not only practically any script and language used on this planet, it also supports a comprehensive set of mathematical and technical symbols to simplify scientific information exchange. With the UTF-8 encoding, Unicode can be used in a convenient and backwards compatible way in environments that were designed entirely around ASCII, like Unix. UTF-8 is the way in which Unicode is used under Unix, Linux, and similar systems. It is now time to make sure that you are well familiar

Determine Perspective Lines With Off-page Vanishing Point

In perspective drawing, a vanishing point represents a group of parallel lines, in other words, a direction. For any point on the paper, if we want a line towards the same direction (in the 3d space), we simply draw a line through it and the vanishing point. But sometimes the vanishing point is too far away, such that it is outside the paper/canvas. In this example, we have a point P and two perspective lines L1 and L2. The vanishing point VP is naturally the intersection of L1 and L2. The task is to draw a line through P and VP, without having VP on the paper. I am aware of a few traditional solutions: 1. Use extra pieces of paper such that we can extend L1 and L2 until we see VP. 2. Draw everything in a smaller scale, such that we can see both P and VP on the paper. Draw the line and scale everything back. 3. Draw a perspective grid using the Brewer Method. #1 and #2 might be quite practical. #3 may not guarantee a solution, unless we can measure distances/p

Moving Items Along Bezier Curves with CSS Animation (Part 2: Time Warp)

This is a follow-up of my earlier article.  I realized that there is another way of achieving the same effect. This article has lots of nice examples and explanations, the basic idea is to make very simple @keyframe rules, usually just a linear movement, then use timing function to distort the time, such that the motion path becomes the desired curve. I'd like to call it the "time warp" hack. Demo See the Pen Interactive cubic Bezier curve + CSS animation by Lu Wang ( @coolwanglu ) on CodePen . How does it work? Recall that a cubic Bezier curve is defined by this formula : \[B(t) = (1-t)^3P_0+3(1-t)^2tP_1+3(1-t)t^2P_2+t^3P_3,\ 0 \le t \le 1.\] In the 2D case, \(B(t)\) has two coordinates, \(x(t)\) and \(y(t)\). Define \(x_i\) to the be x coordinate of \(P_i\), then we have: \[x(t) = (1-t)^3x_0+3(1-t)^2tx_1+3(1-t)t^2x_2+t^3x_3,\ 0 \le t \le 1.\] So, for our animated element, we want to make sure that the x coordiante (i.e. the "left" CSS property) is \(