推荐一篇介绍函数式编程(functional programming)的文章

说实话,对于函数式编程(functional programming),我一直云里雾里,不大明白。今天读到一篇文章:An introduction to functional programming,感觉写的不错,读完之后,至少觉得自己入门了。我把其中最核心的一段话摘录出来,并做了翻译:

When people talk about functional programming, they mention a dizzying number of “functional” characteristics. They mention immutable data, first class functions and tail call optimisation. These are language features that aid functional programming. They mention mapping, reducing, pipelining, recursing, currying and the use of higher order functions. These are programming techniques used to write functional code. They mention parallelization, lazy evaluation and determinism. These are advantageous properties of functional programs.  

Ignore all that. Functional code is characterised by one thing: the absence of side effects. It doesn’t rely on data outside the current function, and it doesn’t change data that exists outside the current function. Every other “functional” thing can be derived from this property. Use it as a guide rope as you learn.

译文:

当人们谈论起函数式编程,他们总会提到一堆令人眼花缭乱的“函数式”特性。他们提到“不可变数据”,“`first class functions`”和“尾调用优化”。这些是辅助函数式编程的语言特性。他们提到“`map/reduce`”,“流水线”,“递归”,“`currying`”和“高阶函数”。这些是写函数式代码的编程技术。他们提到“并行”,“惰性求值”和“确定性”。这些是函数式程序的优良特性。  

忽略上面提到的这些,函数式代码被一个特性所决定:没有副作用,即它不依赖于也不会改变当前函数以外的数据状态。其它所有“函数式特性”均由此特性衍生出来。  

使用screen命令产生并管理多个工作窗口

Unix/Linux下的screen命令一个很重要的功能就是可以在一个物理连接(SSH/telnet)终端(terminal)上创建并管理多个工作窗口(也称之为“virtual terminal”)。达到此目的可以有以下两种方式:

(1)启动screen命令进入一个工作窗口,进行一番操作后,使用ctrl-a d命令离开这个窗口,回到真实的终端。然后在真实终端再次启动screen命令,就可以启动下一个工作窗口。如下例所示:

[root@localhost ~]# screen
[detached from 5362.pts-0.localhost]
[root@localhost ~]# screen
[detached from 5378.pts-0.localhost]
[root@localhost ~]#
[root@localhost ~]# ps -ef | grep -i SCREEN
root      5362     1  0 06:19 ?        00:00:00 SCREEN
root      5378     1  0 06:20 ?        00:00:00 SCREEN
root      5394  5334  0 06:20 pts/0    00:00:00 grep --color=auto -i SCREEN
[root@localhost ~]# screen -ls
There are screens on:
        5378.pts-0.localhost    (Detached)
        5362.pts-0.localhost    (Detached)
2 Sockets in /var/run/screen/S-root.
[root@localhost ~]# ps -ef | grep 5378
root      5378     1  0 06:20 ?        00:00:00 SCREEN
root      5379  5378  0 06:20 pts/2    00:00:00 /bin/bash
root      5745  5722  0 21:45 pts/0    00:00:00 grep --color=auto 5378
[root@localhost ~]# ps -ef | grep 5362
root      5362     1  0 06:19 ?        00:00:00 SCREEN
root      5363  5362  0 06:19 pts/1    00:00:00 /bin/bash
root      5749  5722  0 21:50 pts/0    00:00:00 grep --color=auto 5362

可以看到会有两个SCREEN进程(进程号分别为53625378),同时每个进程都有一个/bin/bash的子进程,而这个/bin/bash子进程就是工作窗口(“virtual terminal”)。

(2)利用嵌套screen命令,也就是启动screen命令进入一个工作窗口以后,不会返回真正的终端,而是不断在当前的工作窗口中递归地调用screen命令。如下例所示:

[root@localhost ~]# screen
[detached from 5756.pts-0.localhost]
[root@localhost ~]# ps -ef | grep -i SCREEN
root      5756     1  0 21:52 ?        00:00:00 SCREEN
root      5817  5722  0 21:52 pts/0    00:00:00 grep --color=auto -i SCREEN
[root@localhost ~]# ps -ef | grep 5756
root      5756     1  0 21:52 ?        00:00:00 SCREEN
root      5757  5756  0 21:52 pts/1    00:00:00 /bin/bash
root      5772  5756  0 21:52 pts/2    00:00:00 /bin/bash
root      5787  5756  0 21:52 pts/3    00:00:00 /bin/bash
root      5802  5756  0 21:52 pts/4    00:00:00 /bin/bash
root      5819  5722  0 21:53 pts/0    00:00:00 grep --color=auto 5756

可以看到这种方式只会有一个SCREEN进程,所有的工作窗口(“virtual terminal”)都是由这一个进程产生的。

参考资料:
(1)Why is there only one SCREEN process in nested screen session?
(2)10 Screen Command Examples to Manage Linux Terminals

cd命令小技巧

(1)从任一目录回到用户的home目录:“cd”或“cd ~”。举例如下:

[root@localhost ~]# cd /home/iso/
[root@localhost iso]# pwd
/home/iso
[root@localhost iso]# cd
[root@localhost ~]# pwd
/root
[root@localhost ~]# cd /home/iso/
[root@localhost iso]# pwd
/home/iso
[root@localhost iso]# cd ~
[root@localhost ~]# pwd
/root

(2)回到之前的工作目录:“cd -”。举例如下:

[root@localhost ~]# pwd
/root
[root@localhost ~]# cd -
/home/iso
[root@localhost iso]# pwd
/home/iso

闲侃CPU(二)

时钟(clock)是驱动所有CPU处理器逻辑的数字信号。

CPU的速率可以用时钟周期(clock cycle)来衡量。举个例子,5 GHz CPU每秒可以产生50亿的时钟周期。每条CPU指令的执行都会占用一个或多个时钟周期。

CPU的速率是衡量CPU性能的一个重要参数。但是更快的CPU速率并不一定能带来性能的改善,而是要看这些CPU时钟周期都用在做什么。举个例子,如果都用在等待访问内存的结果,那么提高CPU的速率就不会带来真正性能的提升。

Bash shell内置wait命令简介

Bash shell内置了wait命令,官方文档对wait解释如下:

wait

     wait [-n] [jobspec or pid …]

Wait until the child process specified by each process ID pid or job specification jobspec exits and return the exit status of the last command waited for. If a job spec is given, all processes in the job are waited for. If no arguments are given, all currently active child processes are waited for, and the return status is zero. If the -n option is supplied, wait waits for any job to terminate and returns its exit status. If neither jobspec nor pid specifies an active child process of the shell, the return status is 127.

wait命令可以使当前shell进程挂起,等待所指定的由当前shell产生的子进程退出后,wait命令才返回。wait命令的参数可以是进程ID或是job specification。举例如下:

root# sleep 10 &
[3] 876
root# wait 876
[3]+  Done                    sleep 10
root# sleep 20 &
[1] 877
root# wait %1
[1]+  Done                    sleep 20 

wait命令一个很重要用途就是在Bash shell的并行编程中,可以在Bash shell脚本中启动多个后台进程(使用&),然后调用wait命令,等待所有后台进程都运行完毕,Bash shell脚本再继续向下执行。像下面这样:

command1 &
command2 &
wait

Bash shell还有一个内置变量:$!,用来记录最后一个被创建的后台进程。

root# sleep 20 &
[1] 874
root# sleep 10 &
[2] 875
root# echo $!
875

echo $!输出结果是875,是第二个执行的sleep命令。

参考资料:
Does bash script wait for one process to finish before executing another?

什么是big data?

Big data”(大数据)的称呼已经火了很长一段时间了。今天我查阅了一些资料,记录一下自己的理解。“Big data”应该包含以下两个方面的含义:

(1)数据量本身很庞大。现在一款几亿人使用的社交软件可以聊天,上传图片,推送文章,发语音信息,等等。一个人可能一天就要产生几M到几十M的信息,那么几亿人一年会产生多少?真是一个非常大数量级的数据。

(2)伴随处理这些大数量级的数据所产生的技术。我们传统处理数据的方法已不再适合处理这些大规模数据了,所以要不断探索和解决这些技术难题。例如:如何存储这些数据,如何寻找特定的数据,如何从这些数据中挖掘出一些有用的信息,等等。

但是,每个问题都有两面性,“Big data”也不例外。一个显著的问题就是用户的隐私。你的社交软件知道了你的太多信息:你的手机号码,你的联系人,你喜欢看什么,等等。也许它比你还了解你。。。

参考资料:
(1)big data
(2)A (very) short history of big data
(3)Big Data

什么是sandbox?

stackoverflow上的一个帖子很好地解释了在计算机领域出现频率较高的“sandbox”的含义:

Sandbox的来源:国外的家庭在自家院子里圈出个地方,堆上沙子,让孩子在里面玩。由于这个小圈子和外界环境隔离开来,所以小孩子不会受到外界环境干扰,比较安全。这个环境就被称之为“sandbox”或“sandpit”。

在计算机领域,sandbox也是同样的含义。可以把sandbox看做计算机内部运行的一个独立环境,sandbox会对在其内部运行的程序(可以看做小孩子)做一个限制,这样即使程序会对计算机系统有破坏,它也跑不出sandbox这个环境。

docker笔记(2)——“docker daemon”,“image”和“container”

使用“service docker start”命令实际上是启动docker daemon程序,可以用“ps”命令查看一下:

[root@localhost ~]# ps -ef | grep docker
root     24791     1  0 Mar18 ?        00:00:03 /usr/bin/docker -d --selinux-enabled
root     24969 24950  0 03:25 pts/0    00:00:00 grep --color=auto docker

-d”选项表明开启daemon模式。

Docker中最重要的概念是imagescontainersimages可以比做虚拟机软件(VirtualBox或者VMware)的虚拟磁盘镜像文件(VirtualBox的格式是*.vdiVMware*.vmdk)。从images可以创建一个或多个containers进程,这个可以比做从虚拟磁盘镜像文件创建出虚拟机程序。

使用docker run命令可以创建一个containers,并且在containers中运行命令,如下所示:

[root@localhost ~]# docker run --rm -ti ubuntu /bin/bash
root@88129ebf9b61:/# ls

新的containers运行的是一个ubuntu镜像,并且进入bash交互模式。

docker笔记(1)—— RHEL 7.0安装docker

官方RHEL 7.0安装docker的文档在这里。由于这个需要用户注册,所以在这里我介绍另一种方法:使用CentOSdocker rpm包。

(1)CentOS的软件包在这里:http://cbs.centos.org/repos/virt7-testing/x86_64/os/,你可以配置到yum源(软件仓库)的配置文件里,类似这样:

[centos-extra]
name=centos extra
baseurl=http://cbs.centos.org/repos/virt7-testing/x86_64/os/
enabled=1
gpgcheck=0

(2)运行“yum install docker”命令。

(3)安装成功后,运行“docker version”命令:

[root@localhost yum.repos.d]# docker version
Client version: 1.5.0
Client API version: 1.17
Go version (client): go1.3.3
Git commit (client): a8a31ef/1.5.0
OS/Arch (client): linux/amd64
FATA[0000] Get http:///var/run/docker.sock/v1.17/version: dial unix /var/run/docker.sock: no such file or directory. Are you trying to connect to a TLS-enabled daemon without TLS?

可以看到有“FATA[0000]......”提示,原因是没有启动docker daemon程序,使用“service docker start”可以启动docker程序。再次执行“docker version”命令:

[root@localhost bin]# docker version
Client version: 1.5.0
Client API version: 1.17
Go version (client): go1.3.3
Git commit (client): a8a31ef/1.5.0
OS/Arch (client): linux/amd64
Server version: 1.5.0
Server API version: 1.17
Go version (server): go1.3.3
Git commit (server): a8a31ef/1.5.0

可以看到“FATA[0000]......”提示没有了。

(4)接下来的步骤可参考这里