常跟人说,今年是我编程第十年了,听起来很夸张,不过是真的。经过2010、15和17年,现在算有自己的编码习惯和风格;但是每次回头看前一阵的代码,都会有很多地方不满意,甚至确信不该那么写;或许是因为懈怠,或许是并未熟记本应坚持的好习惯。
360离职前交接代码,老大帮我把1、2、3、4、5、6、7
改成enum
结构体,用XXXX_BIT
代替;甚为惭愧,于是把一坨if-else
改成switch-case
,具体内容抽象成函数。写go parser
那段时间,扶摇教给我如何写规范的git commit log
,以及scala
如何优雅的关闭文件描述符。这些细节让我印象深刻,好看的代码是如此重要,列一些点提醒自己时刻牢记。
使用go开发快一个月了,之前只是写写demo,真正在线上使用,才发现诸多不便(go真的兼具简洁和强大,还轮不到说它的坏话),吐槽一些别扭的地方。
1、if + 表达式。
只能表达式开头,如果想在特定条件下执行 “计算表达式 + 判断表达式结果”,似乎只能在外层加if。而C和C++可以随意加条件,任何有返回值的表达式都可以放到if的判断条件,加上逗号表达式,功能很强大。而go的这点不足,在维护代码时非常不方便。
Erlang真的很像Prolog,阿姆斯特朗博士在他的著作《Programming Erlang》开头解释为何要学习Erlang时,提到了Erlang的五大特点:
求斐波纳契数列的递归函数,一般来说我们会这么写:
def fib_normal(n): return n <= 2 and 1 or fib_normal(n-1) + fib_normal(n-2) 这当然是典型的费力不讨好的写法,弱智的教科书上都会这么写,还常常表达斐波纳契数列不是O(N)的效率,这么多年坑了不少人。这里只是引出尾递归,写了这么没效率的函数。
执行这个函数的时候,解释器每调用一次fib_normal都会开辟新的堆栈,假如每个堆栈需要K字节的缓冲区,那么计算出结果需要O(NlogN)*K大小的栈空间,如果N很大,就可能会溢出。
现在考虑另一种思路:把计算结果传下去,然后废掉本层栈空间,总的下来只用K大小的缓冲。这就是尾递归的本质,看一看使用尾递归的斐波纳契数列:
def fib_endr(n, a, b): return n == 2 and b or fib_endr(n-1, b, a + b) 舒爽了不少。
最开始玩儿逆向的时候,就很想搞明白x86的机器码,想知道反汇编引擎的工作原理。后来又觉得这个东西没什么好玩儿的,就是一步一步匹配出来的。而且大部分的资料写的都很奇怪,看半天也不知道他的重点在哪里,难以看下去。清明放假意味着更没什么正事儿要做,又一次看了x86指令的组成,在这里总结一下,希望自己写的不要那么模棱两可。
Prolog是我最喜欢的语言之一。ruby给人的感觉是轻松灵巧,还会有点儿惊艳,写ruby程序就像是拥抱自由;和ruby不同,Prolog规规矩矩,编程模式和常见编程语言大相径庭,通过已知自动推断未知。提供一些事实,制定一些规则,Prolog就会自动给出某些判断是yes还是no。