Live Note

Remain optimistic

文件类型

  • 普通文件
  • 目录文件
  • 链接文件:类似 Windows 的快捷方式,分软链接和硬链接
  • 设备文件:一般在/dev 目录下,一种是块设备文件,一种是字符设备文件

文件属性

-rwxrwxrwx

  • r: read
  • w: write
  • x: execute

第一个字符:

  • - : 普通文件
  • d : 目录文件
  • l : 链接文件
  • c : 字符设备
  • b : 块设备
  • p : 命名管道,如 FIFO
  • f : 堆栈文件,如 LIFO
  • s : 套接字

之后的三个三位字符组:

  1. 第一组代表文件拥有者(u)对该文件的权限
  2. 第二组代表文件用户组(g)对该文件的权限
  3. 第三组代表系统其它用户(o)对该文件的权限

文件系统类型

  • ext2 & ext3:ext3 是 ext2 的升级版本
  • swap:交换分区使用
  • vfat:DOS 中的系统(FAT12、FAT16 和 FAT32 等)
  • NFS:网络文件系统
  • ISO9660:光盘文件系统
Read more »

在某个论坛有人问了下面的一段代码

1
2
3
4
5
6
7
8
9
10
11
12
function f() {
console.log("outside")
}
function a() {
f()
{
function f() {
console.log("inside")
}
}
}
a()

问的是为什么在浏览器中是f is not a function
这个问题其实很好回答,存在函数提升,但是仔细想想又不对,因为函数提升是把整个函数都提升到当前作用域,所以按理来说 f 并不会是undefined
如果按照函数提升的话,结果应该是像这样:

1
2
3
4
5
6
7
8
9
10
11
function f() {
console.log("outside")
}

function a() {
function f() {
console.log("inside")
}
f() { }
}
a()

所以结果应该是inside才对,用 IE7 可以发现结果确实是 inside。
那这里为什么是 undefined 呢?
后面那位兄弟说在阮一峰的《ES6 入门》中说道,ES6 规定块级作用域中的函数定义规定为函数表达式。如果是定义为函数表达式的话,那就会像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function f() {
console.log("outside")
}

function a() {
var f
f()
{
var f = function f() {
console.log("inside")
}
}
}
a()

这么一来这个undefined就可以解释了,因为只存在变量提升,而还未定义,所以就会出现undefined。但是那本书后还加了一句,浏览器并未遵循实现。
后面在 starkoverflow 上找到了一个老哥的回答,他的解释为这是因为strict & non-strict mode的不同。

  • let 和 const 在两种模式下行为一样
  • function 在两种模式下的行为就不是一样的,因为浏览器会扩展非严格模式,从而兼容老代码。

所以,在strict mode中,第一段代码输出的是outsidenon-strict mode中就会报错,因为会变成下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function f() {
console.log("outside")
}

function a() {
var f // function-scoped
f()
{
let f1 = function () {
console.log("inside")
} // block-scoped
f = f1
}
}
a()

MDN 中关于Block-level functions in non-strict code的也只有一句话: Don't.

又一次的见证历史。

卡西莫多失去了他心爱的姑娘,也失去了他心爱的钟楼。

大火照片1

大火照片2

大火照片3

废墟中的十字架依旧闪发着光芒

废墟

PS: 看到一条推,说你看大火都没有把十字架给损毁,难道你还不相信上帝吗?下面回:因为金的熔点比木高很多。XD

一篇文章

昨天晚上看了某乎的一篇文章,叫《比 996 更该死的那些人》,里面的开头:

这几年真的觉得这个世界真的已经变得不可救药了
勤劳和奋斗不仅不再被传颂和赞扬,竟然成了被鄙视,被视作愚蠢的品质。
而享乐,投机取巧成这些在过去难以启齿的行为,成了光明正大,人人争相炫耀的东西。

虽然这篇文章我开了开头就没看了,但是还是让我感触颇深,我不赞同第二句,但是第三句我是非常赞同的。在以前我是不会羡慕别人的,不知道从什么时候开始,我会越来越羡慕那些比我强、过的比我好、智商比我高的人。是欲望变了吗?我觉得是的。那个无欲无求的日子,我是不想去回忆的,因为对我来说,和坐牢一样。

从不会去鄙视那些勤劳和奋斗的人,因为他们不知道什么时候就已经追上你并且超过你了,学如逆水行舟,不进则退,但是我实在无法理解的是,投机取巧,为什么在某些人眼里成了政治正确。炫耀享乐,这个我还是可以理解的,毕竟大部分的人还是喜欢被别夸,被别人羡慕嫉妒,当然也有真正是为了分享快乐。

投机取巧的话,不知道是否是因为圈子不同,我觉得我周围认为投机取巧的人是正确的人还不少,甚至于在学校加大监管的情况下,组队进行“帮助”,并且在成绩还可以的时候,去蛊惑那些认真考试但成绩不佳的同学,试图拉他们下水。实在是不能理解那些人心里的想法,是为了让别人顺从自己从而获得心里的快感吗?我不太懂。似乎各大高校都有这种人的存在,这到底是为什么呢?

Read more »

自然数上的一般归纳原理

假设$P$是自然数上的一个性质,则如果

  1. $P(0)$成立 – base case
  2. 对所有的自然数$k$,$P(k)$蕴涵$P(k+1)$ – induction step

则$P(n)$对所有自然数$n$成立

$$
\ \ \ \ \ \ \ \ \ \ [P(k)]\
\frac{P(0)\ P(k+1)}{P(n)}
$$

$[P(k)]$为归纳假设,$k$不能出现在$P(k + 1)$的任何假设中

定理:每个自然是要么是偶数,要么是奇数。
用归纳法来证明:

  1. 0 是偶数 -> 0 是偶数或奇数
  2. 假设 k 是偶数或奇数,证明 k + 1 是奇数或偶数:
    1. k 是偶数,则 k + 1 是奇数
    2. k 是奇数,则 k + 1 是偶数
  3. 得证
Read more »

公式: $$P{Q}R\ ({P}Q{R})$$

P 和 R 都是一阶公式, 如果前提条件 P 在执行 Q 前成立, 则执行后得到满足条件 R 的状态
部分正确性断言: 如果 P 在 Q 执行前为真, 那么, 如果 Q 的执行终止,则终止在使 R 为真的某个状态
终止性断言:如果 P 在 Q 执行前为真, 那么 Q 将终止在使 R 为真的某个状态
赋值公理: $$\vdash P_0 {x:=f} P$$

推理规则的表示

$$\frac{premise -> f_0, f_1, …, f_n}{conclusion -> f_0}$$

推理规则

  • Rules of Consequence:
    $$\frac{P{Q}R,\ R\rightarrow S}{P{Q}S}\ \ \ \ \ \frac{P{Q}R,\ S\rightarrow P}{S{Q}R}$$
  • Rule of Composition:
    $$\frac{P{Q_1}R_1,\ R_1{Q_2}R}{P{Q_1, Q_2}R}$$
  • Rules of Iteration:
    $$\frac{P\ &\ B{S}P}{P\ {while\ B\ do\ S}\ \neg B \ &\ P}$$

等式公理

  • 代换: $[N/x]M$ 表示表示 M 中的自由变元 x 用 N 代换的结果, N 中的自由变元代换后不能成为约束变元
  • 约束变元改名: $\lambda x:\sigma .M = \lambda y:\sigma.[y/x]M$ 例如:$\lambda x:\sigma.x + y = \lambda z:\sigma .z+y$
  • 等价公理: 计算函数实际就是在函数中使用实在变元替换形式变元, $(\lambda x:\sigma.M)N = [N/x]M$
  • 同余性规则: 相等的函数作用于相等的变元产生相等的结果, $\frac{M_1=M_2,\ N_1=N_2}{M_1N_1=M_2N_2}$

一个简陋的 VDOM

希望以后会慢慢完善吧…

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
let data = {
tag: "div",
children: [
{
tag: "span",
children: [
{
tag: "#text",
content: "hello world",
},
],
},
{
tag: "p",
children: [
{
tag: "#text",
content: "This is a paragraph!",
},
{
tag: "h1",
children: [
{
tag: "#text",
content: "This is a H1 tag",
},
],
},
{
tag: "h6",
children: [
{
tag: "#text",
content: "and I'm h6",
},
],
},
],
},
],
}

class VDOM {
constructor(data) {
this.tag = data.tag
this.children = data.children
this.content = data.content
}
static render(data) {
let _this = new VDOM(data)
if (_this.tag === "#text") {
return document.createTextNode(_this.content)
}
let node = document.createElement(_this.tag)
_this.children.map((child) => node.appendChild(VDOM.render(child)))
return node
}
}

let diff = (root, oldV, newV, current = 0) => {
if (!oldV) root.appendChild(newV)
else if (!newV) root.removeChild(root.childNodes[current])
else if (newV.tag !== oldV.tag || newV.content !== oldV.content)
root.replaceChild(new VDOM(newV).render(), root.childNodes[current])
// 递归判断
else
for (let i = 0; i < newV.children.length || i < oldV.children.length; i++)
diff(root.childNodes[i], oldV.children[i], newV.children[i], i)
}
document.querySelector("#root").appendChild(VDOM.render(data))

结构为:

1
2
3
4
5
6
7
8
9
10
<div id="root">
<div>
<span>hello world</span>
<p>
This is a paragraph!
<h1>This is a H1 tag</h1>
<h6>and I'm h6</h6>
</p>
</div>
</div>

Container

Let’s create a normal container first.

1
2
3
4
5
6
7
8
9
10
11
class Container {
constructor(x) {
this._value = x
}
// use the of to create the container
static of(x) {
return new Container(x)
}
}
Container.of(2) // Container { _value: 2 }
Container.of({ name: "jack" }) // Container { _value: { name: 'jack' } }

But we should not directly manipulate the data in the container. We need a function to do this.

1
2
3
4
5
6
// Container.prototype.map :: (a -> b) -> Container a -> Container b
Container.prototype.map = function (f) {
return Container.of(f(this._value))
}
let six = Container.of(2).map((x) => x * 3) // Container { _value: 6 }
six.map((x) => x.toString()).map((x) => "number: " + x + "!") // Container { _value: 'number: 6!' }

After passing the values in the Container to the map function, we can let them manipulate it; after the operation is completed, in order to prevent accidents, put them back into the Container they belong to. The result is that we can call the map continuously, running any function we want to run.
And the Functor is a container type that implements the map function and adheres to certain rules.

Maybe

In Haskell, the Maybe type is defined as follow:

1
data Maybe a = Just a | Nothing

Maybe will check if its value is empty before calling the passed function. So let’s create a simple one.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Maybe {
constructor(x) {
this._value = x
}
static of(x) {
return new Maybe(x)
}
isNothing() {
return this._value === null || this._value === undefined
}
// map :: (a -> b) -> Maybe a -> Maybe b
map(f) {
return this.isNothing() ? Maybe.of(null) : Maybe.of(f(this._value))
}
}
Maybe.of("hello world").map(match(/o/gi)) // Maybe { _value: [ 'o', 'o' ] }
Maybe.of({ name: "jack" })
.map($.prop("age"))
.map((x) => x + 10) // Maybe { _value: null }
Read more »

Function Composition

In computer science, function composition is an act or mechanism to combine simple functions to build more complicated ones. Like the usual composition of functions in mathematics, the result of each function is passed as the argument of the next, and the result of the last one is the result of the whole. -- Wikipedia

Example:

1
2
3
4
5
6
var compose = (f, g) => (x) => f(g(x))
var head = (x) => x[0]
var reverse = reduce((a, x) => [x].concat(a), [])

var last = compose(head, reverse)
last(["first", "second", "last"]) // 'last'

In the definition of compose, g will be executed before f, thus creating a right-to-left data stream. This is much more readable than nesting a bunch of function calls.

Associativity

Like many other functional programming concepts, associativity is derived from math.It is an expression in which the order of evaluation does not affect the end result provided the sequence of the operands does not get changed. -- JOSEPH REX

Example:

1
2
2 + (3 + 4) === 2 + 3 + 4 // true
2 * (3 * 4) === 2 * 3 * 4 // true

Because of the grouping of calls to compose is not important, so the result is the same. This also gives us the ability to write a variadic compose.
Like this:

1
2
3
4
5
6
7
8
9
10
var last = compose(head, reverse)
last(["first", "second", "last"]) // 'last'

var upperLast = compose(head, reverse, toUppercase)
upperLast(["first", "second", "last"]) // 'LAST'

var mediaUrl = _.compose(_.prop("m"), _.prop("media"))
// var images = _.compose(_.map(img), _.map(mediaUrl), _.prop('items'));
// use the associativity
var images = _.compose(_.map(_.compose(img, mediaUrl)), _.prop("items"))

There is no standard answer on how to composition, just make it more reusable.

Read more »