Live Note

Remain optimistic

又一次的见证历史。

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

大火照片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 »

What is currying

Currying is the technique of translating the evaluation of a function that takes multiple arguments into evaluating a sequence of functions, each with a single argument. -- Wikipedia
It mean this:

1
2
3
4
5
let add = (x) => (y) => x + y
let addOne = add(1)
let addTwo = add(2)
addOne(11) // 12
addTwo(11) // 13

In order to define functions more easily, we need the loadsh, it will help us to currying the function.

make some using thing

1
2
3
4
5
6
7
8
9
10
11
12
13
var _ = require("loadsh").curry

var match = _((regex, str) => str.match(regex))
var replace = _((regex, replacement, str) => str.replace(regex, replacement))
var filter = _((f, array) => array.filter(f))
match(/\s+/g, "test Message") // [' ']
match(/\s+/g)("test Message") // [' ']

var hasSpace = match(/\s+/g)
hasSpace("testMessage") // null
filter(hasSpace, ["testMessage1", "test Message2", "test Message 3"]) // ['test Message2', 'test Message 3']
var noA = replace(/[Aa]+/g, "*")
noA("aaaabbbAAAc") // '*bbb*c'
Read more »

Function

function has special rules:

  1. It must work for every possible input value
  2. And it has only one relationship for each input value

Although each input will only have one output, but for different inputs may have the same output.

Pure function

Given all these, pure functions have a big set of advantages. They are easier to read and understand, as they do one thing. There is no need to look outside the function code and check for variables. There is no need to think how changing the value of the variable will affect other functions. No mutations in other functions will affect the result of the pure function for a specific input.
Pure functions are easier to test, as all dependencies are in the function definition and they do one thing.
For Example:

1
2
3
4
5
6
7
8
9
10
var arr = [1, 2, 3]

// Pure
arr.slice(0, 2) // [1, 2]
arr.slice(0, 2) // [1, 2]
arr.slice(2, 3) // [3]

// Impure
arr.splice(0, 2) // [1, 2]
arr.splice(0, 2) // [3]

Another Example:

1
2
3
4
5
6
7
8
9
10
11
// Impure
var sign = 3

// The return value depends on the system status
var isBigger = (num) => num > 3

// Pure
var isBigger = (num) => {
var sign = 3
return num > sign
}