Nexus 6p的一些攻略

网络连通性设置

Android 5.0开始,会通过NetworkMonitorwww.google.com/generate_204(或client[N].google.com/generate_204,视系统而不同,但均为google域服务)发送请求,判断网络的连通性。然而GFW所致,国内无法直接访问google相关的站点,因此我们需要修改一下默认的服务URL:

adb shell settings put global captive_portal_https_url "https://httpbin.org/status/204"
  • 注意,不同的major版本下的命令不同,可以google/baidu一下;
  • 顺便记录一下httpbin.org,可以模拟http的各种method/status等,非常方便;
  • 当然国内各个厂商如小米以及一些社区如ve2x也提供了支持,可以作为备选。实在不行自己做一个也可以。

执法缺位下的民众自决

写这一小段文字主要是近期异烟肼及高铁霸座有感。真心短,纯粹抒发胸臆,可能还不如一些帖子长——我毕竟不是善于舞文弄墨的博主:)

例如那些遍撒异烟肼的 人肉无赖男的,招数虽然不是最佳的,可是都是被逼无奈的,虽非最佳,也算次佳了。
——引自网上的一篇帖子(考虑到隐私和安全,没有注明出处和作者,如认为被侵权请给我留言,即刻删除)

异烟肼在这个话题中,其本质是一种约束和惩罚措施(的结合体),正如杀人偿命、损财赔偿等法律规定。可是,难道我们的法律经过这么大量参考、严格制定和多年验证,仍然有这么大的空白需要异烟肼们去填补么?不排除个例的情况下,大抵不是。异烟肼作为一种约束和惩罚措施的出现,其最主要价值不在本身,而在执行——在执法缺位的情况下,人民只能通过有限的方式进行自我保护以至生存环境的维护。这种方法无奈、原始、低效、易于有失公平,但却是无奈的选择。

人们抨击或追捧异烟肼及其背后针尖对麦芒的两方势力,分析并尝试缓解相关行为带来的正负面影响,并呼吁立法者立法、执法者作为。然而,在这一自发生长的工具面前,这一呼吁恐怕和需要响应这一呼吁的“有关部门”一样苍白无力——如果不是相关方不作为,这种新生事物怎能得到其生长的土壤?一个完美的法治环境无法杜绝此类极端行为(毕竟林子大了什么鸟都有),但却可以通过自我的完善杜绝它成为一种“现象”。

“没有异烟肼的世界”会是什么样?这里就不得不提到前段时间的高铁霸座事件。它将执法缺位造成的另一种后果摆在我们眼前:在人们找到一种自发而可行的自治手段之前,监管的缺位带来的就是无序。这对应于事件的前半段。事件的后半段中,霸座的小哥们迫于舆论压力而发表录像道歉。事情看起来不像完美解决,但总算是有了个交代。“总算是有了个交代”,这不正是人们所追求的最低限解决方案么?而给出这份及格答卷的,正是另一种“异烟肼”:舆论监督。我也会想:异烟肼怎么能跟舆论监督相提并论?到底能不能这样类比?不过加上一些定语,给出一些假设之后,我认为是可以的:舆论监督——在民众自治的环境下——与异烟肼起到了相似的效果。所不同者,前者自诞生开始就经过了多方检验修正并得到成长。虽然它在我们的国家仍然非常羸弱,但却是人们面对强大对手时最为行之有效且性价比最高的武器(我猜它的前身应该就是街坊邻里间口口相传的“吐沫星子”吧)。

异烟肼,这是人民看不到希望的情况下给出的方案;而舆论监督正是成长后的异烟肼。在一个拥有足够体量的社会中,任何缺位都会有人、事、物快速而自然地填补。这些替代品从最初的粗制滥造、顾此失彼默默地发展,逐步壮大,并终将静静地替代缺位者。但愿正在被替代的人们有保存自身、发挥作用、确保不被替代的自觉。

Homebrew灵活自定义Formulae

Homebrew是Mac上经常使用的包管理工具,类似还有pkgsrc等。但前者的sudo-free解放了我对改动mac os这个闭源系统的恐惧,在安装喜爱的软件的同时不必再担心系统罢工。

然而相对于各个Linux/BSD发行版的包管理工具,homebrew在版本管理和依赖冲突管理上的支持还是比较的弱。根据他们社区的交流来看,这两点还在不断地优化中。在这之前,如果遇到版本冲突的问题,我们该怎么办呢?版本冲突一般是如下两种情况:
* 由于tensorflow不支持3.7版本的python,因此我希望将其对python的依赖改为3.6.5版本。无奈软件源已经更新为3.7,有什么办法对python降级?
* 我通过一些hack or offical的方法解决了上述问题,终于可以使用tensorflow。然而某个foo app依赖的是python 3.7,如何进行multi slot安装呢。

对于第一种问题,解决方法为:添加自己的软件源,迁移并修改希望改动其安装配置的软件包的rb文件。这里用到的命令是brew tap user/repo。以tensorflow为例,过程如下:
1. 将Homebrew-core的github repo fork一个,并从Formulae目录中删除除tensorflow和python之外的rb描述文件,注意其它目录也有些相关的描述/文件也最好清空;
1. 提交更改,并在本地执行brew tap my_git_username/my_repo,以便将其加入homebrew的软件源;
1. 通过vim /usr/local/Homebrew/Library/Taps/my_git_username/my_repobrew edit python修改python.rb,并将其sha256url两个字段修改为自己期望的版本的hash和url;
1. 同样修改自己源中tensorflow.rb的deppends_on字段,将其依赖的python改为my_git_username/my_repo
1. 提交更改。

上述操作后,即可通过brew install my_git_username/my_repo/tensorflow来自定义安装tensorflow了。

对于第二种问题,解决方法更简单一些。Foo app依赖的python是在默认源中的。在我们直接安装Foo之后,Cellar目录下即有了两个版本的python,分别是3.6和3.7。之后就是版本选择的问题了,采用如下命令:

brew switch python 3.7

即可在版本之间按需切换。

本文的重点是通过自定义软件源的方式绕过版本管理的问题。其实homebrew本来是有一个homebrew/versions源来支持多版本管理的,可惜无福使用;而且听说其对python的支持只是在major版本之间,minor是不支持的,还是比较弱。还是希望homebrew团队多多更新,天天向上,多多兼容,造福我等小白。

顺带mark版本级别的说明(以python 3.6.5为例)
* major 主版本
* minor 子版本
* patch 小迭代

C++的两段名称查找[two-phrase name lookup]

原理

C++在涉及模板的特化及模板类的实例化时,通过两段查找来确定其定义中的每个命名。顺序大致为:
1. 第一步是模板的特化。此时只需要进行名称替换,也即将模板的形参以实参代替。此时编译器查找所有non-dependent命名,也即非成员函数或变量,并替换其类型或参数类型;
1. 第二步是模板类的实例化。在这之前编译器会进行常规的基类查找,并将所有dependent命名进行解析,也即成员函数或变量的查找(要么在本类的定义中找到,要么在基类或虚表中找到)。

详细原理参见文章:The Dreaded Two-Phase Name Lookup

这种两端查找对带继承的模板类开发有很大影响。有时我们会发现如下代码的错误:

template <typename T>
class Base {
    void foo1();
    void foo2();
};

template <typename T>
class Derived : public Base<T> {
    virtual void foo1();
    void bar() {
        foo1();         // ok
        foo2();         // error
        this->foo1();   // ok
        this->foo2();   // ok
    }
};

int main(...) {
    Derived<int>().bar();   // error occurs here
}

直接调用foo2产生的错误如下:

foo2();

/path/to/def.cpp:427:55: note: declarations in dependent base ‘Derived<int>’ are not found by unqualified lookup
/path/to/def.cpp:427:55: note: use ‘this->foo2’ instead

上述的错误即源于这个two-phrase name lookup。编译器在编译main函数的唯一一行代码时,首先特化Derived的模板,此时未在其定义内部找到foo2函数,故抛出错误。好在编译器给了友好的提示,我们将其改为this-foo2()之后,即编译通过。这么做的主要变化是将foo2这个命名从non-dependent弱化为dependent,从而延后它的解析。

不使用while的循环(setjmp的用法)

setjmplongjmp是ANSI C程序支持/控制库中的一对函数,用于保存env与返回。setjmp将当前env保存在一个jmp_buf中;longjmp返回后的env则从中取出,完全相同。这是一些有栈协程实现的基础。

setjmp和longjmp有一些有趣的应用,如替代while实现循环。如下为示例代码,来自cppreference

#include <iostream>
#include <csetjmp>

std::jmp_buf jump_buffer;

[[noreturn]] void a(int count) 
{
    std::cout << "a(" << count << ") called\n";
    std::longjmp(jump_buffer, count+1);  // setjump() 将返回 count+1
}

int main()
{
    volatile int count = 0; // 在 setjmp 作用域中被修改的局部变量必须是 volatile
    if (setjmp(jump_buffer) != 9) { // 在一个 if 内不等于常量表达式
        a(++count);  // 这会导致 setjmp() 退出
    }
}

程序是经过验证可以执行的,执行结果与cppreference给出的一致。

a(1) called
a(2) called
a(3) called
a(4) called
a(5) called
a(6) called
a(7) called
a(8) called

后续再过协程的时候还要返回来看看,在此mark。

Python map方法真心好用

Python下有个map方法,结合一些单目操作符或单参数的函数对iterable实例进行操作真的非常好用。

  1. 如下代码将通过localtime获得的时间信息数组转换为字符串数组:
','.join(map(str, time.localtime()))
  1. 如下进一步控制了转换后字符串的格式,注意分隔符为空,仅转换前六位元素(年月日时分秒):
''.join(map('{0>2d}'.format, time.localtime()[0,6])) # 好吧我承认可以使用strftime
一些备注
  • 新版string format方法的确方便了很多,可以灵活地控制输出格式。如上{0>2d}表示对应位置的整型值至少显示两位,否则左侧补零;
  • 如果希望采用双目或多目运算符,抑或使用多参数的方法,猜测应该需要采用placeholder,或者传入元素为同维度元组的数组。这一点纯猜,没有验证;
  • map的实现应该很简单,但是大大地方便了用户。至于其实现,其实类似stl alogrithm里的函数了,如std::transform或std::for_each等,均可以实现这个效果。不过map这个字眼老实说让用户非常直观地猜到它的意图。能及时跟上概念的演进也是新语言(相对c/c++)的优势吧。

重开博客

自打百度空间关闭以来,大量的博客文章都被下掉。恢复博客这件事,老实说技术上还是可能的,但是繁琐的工作让我从来没有想起要做这件事。近两年每每觉得还是需要个博客来记录自己的所想所做,这次算是成行了。

之前就开过一次wp,但是后来不知出了点什么问题导致打不开。这次重开倒是快了很多(因为之前的经验形成了意识流?),不过还是记录一下期间发生的问题,以备后用。

  1. httpd相关:

1) 需要配置虚拟主机来确保多站区分。具体参见httpd/conf.d/下的配置文件。上着班就不写太详细了;

       2) 站点目录需要设置为httpd专用的用户名,以便httpd拥有写权限。这可以方便wordpress的配置和升级(否则还需要为它额外配置ftp,更麻烦)  。这其实是建站基本知识,知道是知道,只是不记得细节了。

  1. mysql相关:

1) 注意grant privilege和set password所带的indentified by ‘xxx’是等效的。不要在设置密码后的grant操作中将密码覆盖了;

2) 对用户授权时,需要注意grant操作是要指定主机的,同时localhost和%需要分别设定,具体可以参见user表,从中可以看出该表的主键user id与<user, host>其实是一一对应的;

3) 授权完成后记得flush privileges,否则授权无效。

  1. wordpress相关:

如果前面几步都做到了,那么wordpress的安装可以说太简单了。只需要注意两点以便使用方便:

1) 设置用户名时设置为自己喜欢的名字,因为建立之后不能在前台修改。如果后悔了只能跑到后台数据库去裸改,关联的表就多了。好在wordpress好像并没有给这些表建立约束,改起来也没那么麻烦:P

2) 在“设置->固定链接”这个选项中,按照日期+文章名称定位的链接风格为人所喜,但经常会设置失败。查证了一下,需要做的有这么三项:

a. 确认mod_rewrite开启,因为是通过链接重写实现的。这一点基本没有问题;

b. 让httpd的虚拟主机配置项支持两个Option:Includes和FollowSymLinks;

c. 注意你的链接本身,http://hostname/year/month/day/postname是可以做到的,但是http://hostname/index.php/year/month/day/postname却不行;

*d. 补充一点。官方主题总有一个页尾:Proudly powered by WordPress(中文翻译包中叫做“自豪地使用WordPress”)。作为中国人,我选择了中文翻译包,然后为了去掉这东西搜了半天(上面这几个)中文字——搜得到就见鬼了。。到站点目录搜上面的英文吧,搜到的footer直接删除即可。老实说,用人家东西这样做貌似不是很好,不过我实在不愿意作活广告,致谢不也得自愿么~

以上。第一篇文章写在什么工具都还没有的环境下,后面计划慢慢把工具插件之类慢慢建立起来,首先还是赶紧装个markdown插件吧~