月度归档:2014年06月

『牛津通识读本:天文学简史』

history-of-astronomy本来就没指望过能通过通识读本来了解天文学,入门也算不上,但有三点感受。

一、关于一个学科的历史

霍斯金在序言中所说:

天文学的历史非常丰富,但是在传统观念支配下撰写的天文学史,则总是倾向于“过滤”掉许多历史事件、人物和观念“过滤”掉人们探索的过程,“过滤”掉人们在探索过程中所走的弯路,“过滤”掉失败,“过滤”掉科学家之间的钩心斗角……最终只留下一张“成就清单”。通常越是篇幅较小的通史著作,这种“过滤”就越严重,留下的“成就清单”也越简要。

不单天文学,弯路和试错实际上是任何一个学科发展过程中的必经之路。所以,我们看见的历史都是经过过滤和“打扮”的历史,光以对错成败论英雄对先驱者显得不公。对待自己所从事专业的领域,熟知正确的发展史固然重要,但是若能了解那些成功背后的故事,也能更好拓展思路和研究方法。

二、印刷术的作用

霍金斯在介绍中世纪的天文学时说到:

15世纪印刷术的发明有许多影响,最重要的是促进了数学学科的发展。所有抄写员都是人,在准备一个原稿的副本时都会犯偶然的错误。这些错误常常会传递给副本的副本。但若著作是文字作品,后来的抄写员注意到了文本的意义,他们就有可能识别和改正他们的同行新引入的许多差错。但是那些需要复制含有大量数学符号文本的抄写员难得运用这样的控制手段。结果,撰写数学或天文学论文的中世纪学生会面临巨大的挑战,因为他只有一个手稿的副本可用,而该副本不可避免地在传抄中会有讹误。

以前所理解的印刷术的作用是大大提升了效率,加快传播速度,而没有在更深层次认识到印刷术对数学类科学研究带来的影响。大家在学生时代肯定都经历过参考答案错误的情况下,让人怎么都觉得捉摸不透,继而把人带到坑里去了。类比到参考某天文大家的观测数据,因为制作副本人员不经意的一个笔误,可能会导致后来人在错误的道路上越走越远。

三、天文学发展的艰辛

从柏拉图、亚里士多德开始,人类逐渐对天空产生了幻想。没有前人的理论证明,没有先进的测量方法,只有丰富的个人阅历和少量不知可靠与否的前人观测数据,托勒密们慢慢形成自己的世界观和宇宙观。从托勒密、哥白尼、第谷、开普勒、伽利略、牛顿……一系列学说的提出、证伪、修正和完善由不得让人感叹和钦佩:

古代天文观测者的牛逼之处在于: 凭着一双肉眼,年复一年,竟然能逐渐得一个个接近事实的结论。这得经过多少种模型假设和试错才能做到呀!

如今的科技发展水平只能说对宇宙有了一个很初步的认识,人类活动还只能局限在太阳系,发射了几十年的旅行者1号也才刚刚飞出太阳系。整个宇宙,比人类所想象的还要大太多太多……乐观地想,也许五百年后,新人类看待我们这个时代所达到的天文学成就,就像我们看待托勒密地心说一样。

不想了,一想这些,就会令人感到虚无。

附录:『牛津通识读本:天文学简史』读书笔记

--EOF--

nginx location匹配规则

nginx location块的语法为:

1
location [ = | ~ | ~* | ^~ | @ ] uri { ... }

此处不考虑@,仅列出=,~,~*,^~和无前缀这五类前缀的匹配规则。

五类前缀的可分成两大类。
1. 普通匹配(literal string): =(精确匹配), ^~和无前缀(最长匹配)。
2. 正则匹配: ~(大小写敏感), ~*(大小写不敏感)。

匹配顺序为:
1. 精确匹配=前缀。如果匹配上,则停止。
2. 进行最长文本字符串匹配。如果最长匹配指令是以^~前缀开头,则停止;如果是无前缀,则继续。
3. 按定义顺序进行正则表达式匹配,如果匹配上,则停止;否则,用步骤2中的无前缀指令。

借用nginx官网上的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
location  = / {
  # matches the query / only.
  [ configuration A ] 
}
location  / {
  # matches any query, since all queries begin with /, but regular
  # expressions and any longer conventional blocks will be
  # matched first.
  [ configuration B ] 
}
location /documents/ {
  # matches any query beginning with /documents/ and continues searching,
  # so regular expressions will be checked. This will be matched only if
  # regular expressions don't find a match.
  [ configuration C ] 
}
location ^~ /images/ {
  # matches any query beginning with /images/ and halts searching,
  # so regular expressions will not be checked.
  [ configuration D ] 
}
location ~* \.(gif|jpg|jpeg)$ {
  # matches any request ending in gif, jpg, or jpeg. However, all
  # requests to the /images/ directory will be handled by
  # Configuration D.   
  [ configuration E ] 
}

/ -> configuration A
/index.html -> configuration B
/documents/document.html -> configuration C
/images/1.gif -> configuration D
/documents/1.jpg -> configuration E

--EOF--

erlang concurrent primitive exercise

1. Write a function my_spawn(Mod, Func, Args) that behaves like spawn(Mod, Func, Args) but with one difference. If the spawned process dies, a message should be printed saying why the process died and how long the process lived for before it died.

1
2
3
4
5
6
7
8
9
10
11
12
13
my_spawn(Mod, Func, Args) ->
  Pid = spawn(Mod, Func, Args),
  spawn(fun() ->
    {StartMegaSecs, StartSecs, _} = erlang:now(),
    Ref = monitor(process, Pid),
    receive
      {'DOWN', Ref, process, Pid, Why} ->
        {EndMegaSecs, EndSecs, _} = erlang:now(),
        io:format("~p exit, reason: ~p, time: ~p~n",
          [Pid, Why, (EndMegaSecs-StartMegaSecs)*1000000+EndSecs-StartSecs])
    end
  end),
  Pid.

Keypoint: spawn/3, monitor/2, now/0.

2. Write a function my_spawn(Mod, Func, Args, Time) that behaves like spawn(Mod, Func, Args) but with one difference. If the spawned process lives for more than Time seconds, it should be killed.

1
2
3
4
5
6
7
8
9
my_spawn2(Mod, Func, Args, Time) ->
  Pid = spawn(Mod, Func, Args),
  spawn(fun() ->
    monitor(process, Pid),
    receive
    after Time * 1000 -> exit(Pid, timeout)
    end
  end),
  Pid.

Keypoint: spawn/1, monitor/2, receive after end, exit/2.

3. Write a function that creates a registered process that writes out "running" every five seconds. Write a function that monitors this process and restarts it if it dies.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
-export([monitor_process/0]).
 
monitor_process() ->
  Pid = register_process(),
  loop_monitor(Pid).
 
start() ->
  io:format("~p running~n", [self()]),
  timer:sleep(5000),
  start().
 
register_process() ->
  spawn(fun start/0).
 
loop_monitor(Pid) ->
  Ref = monitor(process, Pid),
  receive
    {'DOWN', Ref, process, Pid, Why} ->
      io:format("~p shutdown due to ~p, restart it.~n", [Pid, Why]),
      loop_monitor(register_process())
  end.

Keypoint: timer:sleep/1, monitor/2, tail recursion.

4. Write a function that starts and monitors several worker processes. If any of the worker processes die, restart it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
-export([restart_one_for_one/0]).
restart_one_for_one() ->
  [start_and_monitor() || _ <- lists:seq(1, 10)],
  loop().
 
start() ->
  io:format("~p running~n", [self()]),
  timer:sleep(5000),
  start().
 
start_and_monitor() ->
  Pid = spawn(fun start/0),
  monitor(process, Pid).
 
loop() ->
  receive
    {'DOWN', _, process, Pid, Why} ->
      io:format("~p shutdown due to ~p, restart it.~n", [Pid, Why]),
      start_and_monitor()
  end,
  loop().

Keypoint: monitor/2, tail recursion, list comprehension.

5. Write a function that starts and monitors several worker processes. If any of the worker processes die, kill all the worker processes and restart them all.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-export([restart_one_for_all/0]).
 
restart_one_for_all() ->
  CenterPid = spawn(fun() -> [spawn_link(fun start/0) || _ <- lists:seq(1, 10)],
    receive after infinity -> true end end),
  io:format("Monitor Pid ~p~n", [CenterPid]),
  monitor(process, CenterPid),
  restart_handler().
 
start() ->
  io:format("~p running~n", [self()]),
  timer:sleep(5000),
  start().
 
restart_handler() ->
  receive
    {'DOWN', _, process, Pid, Why} ->
      io:format("~p shutdown due to ~p, restart it.~n", [Pid, Why]),
      restart_one_for_all()
  end.

Keypoint: monitor/2, spawn_link/1, list comprehension, receive after infinity end.

--EOF--