Hoes of Tech

Conceptualization of Technology

  • Back to Mac

    在过去的一段时间里,我一直在用ZTE的安卓手机Axon 7,我并不讨厌Android,也没有感觉到网上所说的卡顿或者内存不足等问题,不过系统更新太慢&弹窗还是让人觉得用起来并不舒服。实际上,日本版的Axon7直到去年的7月才更新了Android7.1.1,并且似乎并没有后续更新的计划,我并不期待新版本的功能,但缺乏Security Patch还是让人颇有些不安的。于是,趁着iPhone发布新版本,我换了iPhone8。

    实际上,在iPhone之前,我已经买了iPad,因为它给了我很大的惊喜。在ヨドバシカメラ的店头随手试了一下iPad Pro + Apple Pencil之后,流畅的书写感觉给我留下了很深的印象,以至于我当时就买了下来。后来半年的时间里iPad也没有让我失望,配合GoodNotes4,不论是读论文还是会议笔记,iPad都没有出现任何问题。由于在iPad上书写几乎对环境没有要求(不需要光源,不需要桌子或垫板),在睡觉之前甚至可以趴在床上写日记。毫无疑问这是我这些年里买的最不会后悔的产品了。

    在换了iPhone之后,我把很久之前买的Mac mini mid2012翻了出来,自从把环境全部转移到了ArchLinux+i3之后Mac mini就一直没有开过机。跟Linux比起来macOS的优势并不明显,尤其是低配版的Mac mini并没有SSD …

    Read more...

  • Writing A Threadpool in Rust

    多线程一直是我相当不相碰的东西,总觉得看起来很棒,用起来却一点都不放心——尤其是过去用Delphi体验了多线程之后。实际上到了多线程里根本就没法定位那里出了错误,因此大部分时间压根不是在“调试”,而是告诉用户怎么用才能避免这个错误。在给OOC写MultiTheard Generating的时候我也紧紧用了最简单的ThreadPool,并且因为互斥锁多线程还没有单线程快。总之,这么多年我一直有意的躲避多线程的问题。

    而Rust一直在宣传它在多线程上的优势——所有权如何的好,在Servo里面他们如何用Rust写了个漂亮的Parallel Parser。加上最近一年一直再用Rust写游戏的服务器,于是我决定回头看看Rust下的多线程体验到底如何。

    ThreadPool

    相比简单的用多线程算个加法,或者写个The Computer Language Benchmarks Game的测试程序来说,ThreadPool可能更适合练手。在这里,我会实现下面这个结构的ThreadPool:

    ThreadPool

    简单来说,主线程通过Channel向ThreadPool发送Job,然后Threadpool里的每一个子线程在空闲时都会尝从Channel里获取Job,然后执行它。执行完毕之后,Job的返回结果会通过另一个Channel传送给主线程。实际上,在C或Delphi里,实现这么一个东西似乎并不是很困难,然而,Rust因为独特的所有权制度,代码比思路要复杂一些,下面,让我们来看看怎么实现这个ThreadPool。

    Jobs for the Job

    首先 …

    Read more...

  • Formal Concept Analysis with Rust (1) - Introduction

    Introduction

    不知不觉,从开始使用Rust到现在已经有接近一年了,Rust也渐渐成为了目前用起来感觉最舒服的语言。虽然Rust号称因为有确定性析构,所以不会在内存释放上有效率损失,不过在实际使用中,总是能够感觉到再有大量小内存分配和释放的时候运行效率和内存效率都比C要稍微低一些。这次,让我们用Rust通过实现一套形式概念分析的算法,来看看Rust在全列举程序上的表现到底如何。

    Formal Concept Lattice

    这次我们将把重心放在实现上,对与Formal Concept的我们只介绍在程序中需要使用的特征,如果打算了解更详细的理论内容,可以参考Lattice Theory的综述性论文,比如:

    Wille, Rudolf.

    "Restructuring lattice theory: an approach based on hierarchies of concepts."

    Ordered sets. Springer Netherlands, 1982. 445-470.

    简单来说,对于一组文章\(D={d_1, d_2, \dots, d_n}\),和一些事先提取出来的文字\(W …

    Read more...

  • Description of LZ77

    Basic Definitions

    In this article, \(D\) is used to represent an i-elements data array. \(d_0, d_1, ... , d_i\) are the elements of \(D\). Any continuous subset of \(D\) is called slices, represented by \(S(i, j)\), where \(i\) and \(j\) is the start and end position. For two slices \(S_1\) and …

    Read more...

  • Dive into Rust(1) - Iterator

    大概三个月之前,这三个月,我一直在使用Rust。回想起来,在离开Object Pascal家族之后,过去五六年里也已经尝试了很多的新语言,不管是D,还是因为谷歌的名头而开始用的Go,又或者是Nim,Crystal或者Zimbu,都没能让我真正的满意,而OOC虽然在语法上让人十分舒服,但它使用了libGC,并且对多线程和Closure的支持并不到位。其实,在改进OOC的过程中,有人提出过给OOC加入RAII,并且尝试把一部分内容分配在了栈上,不过很可惜,OOC的编译器在设计当初并没有考虑这些事情,不到几个小时这种改进就遇到了问题。

    在刚刚接触Rust的时候曾经写过一篇关于Rust的文章,里面阐述了我对Rust的第一印象——省心。把代码写出来,编译器就会指出所有的错误,在这几十天里,我明显感觉到在调试程序时莫名其妙的错误少多了——我还清楚的记得之前在OOC里因为一个Generics的bug导致ArrayList<T>里的元素过早被回收,结果就是程序有时候正常,有时候乱码,有时候Segmentation Fault,而这种问题在Rust里几乎不会出现。

    当然,Rust这么做的代价就是语法上的繁杂。Rust的语法并不算复杂,大部分关键词的意义都很明确,也没有存在歧义的设计,然而说它繁杂却不为过,一个简单的例子就是在声明一个用到了Borrow的Struct时,编译器要求必须指明所有Borrow的Lifetime,因此定义和声明中就出现了大量的Lifetime标识符 …

    Read more...

  • A First Look at Rust

    过去的一年半多,我一直沉迷与OOC,原因倒是很简单,OOC是目前为止我所能见到的最容易理解和最容易书写的语言。并且另外一个极其重要的地方是,它可以编译成C代码。编译成C代码,也就意味着优化可以交给高度发展的C语言编译器来做,听起来似乎适合十分高效的方法。

    最近几年类似的语言越来越多,从很久很久之前就存在却一直没出名的Haxe,还有最近的Nim-lang,以及采用了类似ruby语法的Crystal,甚至包括编译成C++的felix。这些语言都号称自己考虑了速度(运行速度),至少从编译成C/C++的层面上。

    可惜的是,在改进OOC编译器rock的过程中,我遇到了越来越多的问题,这些问题让喜欢速度的人泄气。一个最明显的事情是,这些语言几乎都用了GC,不论是libGC还是自己写的,并且更重要的是,很多语言特性是基于GC设计的——比如闭包,比如iterator的unwrap,在有没GC的情况下,这些东西的设计要复杂的多。在OOC里,由于Generics不是Template,更多的东西开始依存GC,在用了它一年后,当我真正开始在工作里使用的时候,这些问题开始出现,我开始打算关闭GC,但很显然这是不可能的。编译器会把一切搞不清楚的事情踢给GC。

    在这个时候 …

    Read more...

  • Closures in OOC

    上一篇Complexity Behind Closure,这次来专注于Rock是如何在C里实现Closure的。

    Block as Blocks

    首先,需要指出的是,在C里面并不是完全没有办法使用Closure。Apple的GCC Fork里就给C添加了Block,用于实现Closure:

    (Steal from the Wiki)

    #include <stdio.h>
    #include <Block.h>
    typedef int (^IntBlock)();
    
    IntBlock MakeCounter(int start, int increment) {
        __block int i = start;
    
        return Block_copy( ^ {
            int ret = i;
            i += increment;
            return ret;
        });
    
    }
    
    int main(void) {
        IntBlock …
    Read more...

  • Complexity Behind Closure

    Introduction

    今天,我在ooc-kean上看到了一个注释:

    minimum: static func ~multiple(value: This, values: ...) -> This {
        // FIXME: This creates a closure that causes a leak every time this function is called.
        values each(|v|
            if ((v as This) < value)
                value = v
        )
        value
    }
    

    minimum是Float类型的一个扩展,这里用了闭包来实现对每个值的比较。如果这些发生在GC之下,那么一切都没有问题,因为任何内存(包括闭包的)都会被GC默默的回收。但OOC-Kean并没有打开GC,这里就出现了问题 …

    Read more...

  • Introduction to The OOC Programming Language

    我想试一门新语言……但:

    • 我希望这门语言能简洁易懂 —— 排除了Perl/Rust...
    • 我不想自己管理内存 —— 排除了C/C++/Object Pascal...
    • 最好它能跟C差不多快 —— 排除了Python/Ruby...
    • 并且最好能在任何地方编译&运行 —— 排除了D
    • 我不想带着一个数百兆的运行库 —— 排除了Java
    • 我不怕Bug —— 欢迎来到OOC的世界

    Why OOC?

    • Compile to C,所有的代码都会首先编译成C,然后由clang或者gcc编译成二进制代码 这意味着,只要你有一台能运行ooc编译器的电脑,那么你的代码就可以在几乎任何有C编译器的平台上运行。

    • Class,Function overloading,Extend,Operator Overloading.... OOC拥有绝大部分你所期待的高级语言的功能。 ooc借鉴了很多语言,尝试这把这些语言里优秀(并且有趣)的元素融合到一起。

    • Easy interface to c. OOC可以直接使用C的头文件,也可以在C里简单的使用ooc的函数。

    OOC的官方网站里有更多介绍和参考资料 …

    Read more...

  • OOC, Generics and Flawed Design

    昨天在github上讨论OOC的一些特性,随后这个语言的设计者写了这篇文章。 虽然大部分都在谈ooc的编译器设计,但更多的内容在于程序设计的思想,复杂度,维护上面。我希望这篇文章能对读者有哪怕一丁点的帮助。

    原文地址:http://fasterthanlime.com/blog/2015/ooc-generics-and-flawed-designs

    ooc可能是我(注:原作者)最得意的成果,但同时,对我来说它也是让我头疼不已的“刺头”。

    一个重要的原因就是它的设计(构架)并不让人满意,并且在当下,很多东西没法简单的解决。但不要误解: 在某种意义上,所有的设计都是“糟糕”的,不论是由一个人掌管,或者有社区驱动。没有任何一个设计能被称为完美。尽管我们并没有关于“完美”的定义和度量。

    现在回到ooc上来,一些话题反复的被提起,比如interface(接口)和cover(覆盖)。这个问题的原因一部分来自与人们会简单的认为这些概念应该跟其他语言里的一样,因为它们的名字完全相同。但事实并不是这样,纵使拥有相同的名字,它们的意义也不尽相同。如果这些概念跟其他语言里的概念完全一样,那么ooc会是一个简单的C …

    Read more...