起因: 我去问莎莎这个问题
me: 然后最近有了点奇怪的想法(书里肯定写过,但是我不知道是哪些书)
说起来以前一直不懂为啥比如看书时要从一堆显然的东西开始定义
比如说 a,b 是能比大小的。令 a>b 这种表达
后来发现这是 impl Ord
因为 复数/向量/矩阵/etc 不能比大小
这是 scale 的特征
也就是说利用 trait 去表达特性来证明,可以脱离具体的对象
比如具有特征 A 的可以比大小,那就 impl A 的都可以做某些行为
用编程语言的话大概是对类指定约束就能无视具体的对象,进行操作
比如给定了大小比较方法就能取 max min
莎莎 是的
generic pogramming 等下 http://elementsofprogramming.com/
me: 艹,里面有些地方我隐隐有过感觉,但是基本找不到相关资料 唯一一本比较接近的只有 sicp(在这之前
下面是读书感想, 不算笔记.

P11 的 concept 在 cpp20 终于引入了.
而 rust 早有了.
翻了下书里提供的源码, 原来
P251 也提到了这个
新版 clang 需要 --std=c++11 or 14 or 17 来避免问题.

这个 ValueType 没太 get 意义.
P251 提到了
notion image
notion image
为了使 T 和 T* 都能得到类型 T, 所以用 value_type 包了一下. 加了一个中间层进行”转发”

P13
P18
P21
链表判断环的算法.
while slow and fast and fast.next

2.5 的动作
notion image
一个是 C style 的 &mut self
一个是 fp-style 的 self → Self

P37
严格尾调用可以变换为一个迭代过程, 方法是把每个递归调用变成一个到开始的 goto
从汇编角度非常自然. 函数调用时, 先把寄存器压栈存了, 再一个 jmp. 对应 goto

Item 3.1:
试着写了个测试, 发现精度区别有点难判断.
3.6 讲了矩阵快速幂 + 线性递归, 然后是经典 fib
细节
项目 3.2 的解答:
 

P53
4.3 实现 max / min 以及 n 个变量的 max / min

P72

P77
欧几里得部分主要是展现了怎么用约束(各种代数结构)来对输入的变量进行必要的约束,从而写出不面向具体类型, 而是用代数的性质指导泛型的编写. 这样就不需要针对所有数字类型全实现一遍 i8 i16 …. i128 u8 …. u128.
一个偷懒写法是先只写泛型, 等报错后看 ra 的提示补全必要的 trait

在书里提到了函数的签名分很多种. 但是主要提到这两种.
类似类型形状的改变(?)
前者是类型变换, 后者是元组映射到
在写基于变换的泛型时, 要从函数签名的形状出发.
比如 Add 是一个 (T1,T2)->V , 那写的时候 lhs 是
T1: Add<Rhs=T2, Output=V>
如果再抽象出一个 Fn, 那签名写成 Fn(T1, T2) → V (这里 Fn, FnMut, FnOnce) 由于仅 Copy 就不深入了.
再比如 SubAssign 是一个 &mut self, T -> void, 那么只需要指定 rhs, 而一般又默认推到 Self, 可以省略不写.

第 6 章介绍了迭代器, 对, 就是 cpp 标准库里那个很难用的迭代器.
下面是黑的环节
迭代器失效
迭代器失效.
还有经典 macro #define all(x) x.begin(), x.end()

关于高阶泛型

思考这样一个场景:
变化的只有 next( tmp ) 和 val( tmp )
抽象一下, 就是这种泛型. T<V>
T 是容器类型, V 是元素类型.
T 的约束就是 next, end, val
把满足相关的叫做 type T<V> = Iterator<Item=V>
我们就把链表和 vec 的遍历统一起来了, 这难道不酷吗, 后面忘了.

里面提到的 for_each 可参照
Self: Sized, 就是书里提到的有界约束.
rust 在这里使用了 Option 而不是书里的”范围的极限”, 避免了不经检查直接 take value 的操作.

这里其实是设计模式的迭代器模式, 把迭代过程抽象了出来, 从而可以把 f 传进去实现高阶过程.(SICP)

P100 提到了经典但不著名语言 APL

引理 6.8 本质就是 P.all(pred) ⇒ sub P . all(pred)

P118 written in return style:

7.2 章其实讲的是生成器。。类似一个 tree 上的 map 不过 cpp 没有“生成器”,所以书里写得不太 clear 不然
就直接求树高了(书上原例子 map 可以看作不停 yield 值的一种对象(好处是可以写成 chain 如果要不取可以 yield None,后面接 filter

P130
判断二叉树同构,其实类似的思路可以用于判断镜像。力扣原题。
左 == 右的镜像。所以要打开来传。

原书 P129
里面提到的增强是这么理解:
对两棵树 impl Iterator ,然后就变成一个 Sequence,然后 Sequence 可以按字典序比较大小。
然后有 Ord 就能 impl Sort(基于比较的 sort),Sort 完后就能用二分找相等的树。(这里 impl Hash 不合算,需要把序列化)
所以本质还是 sort(Vec<Tree>,key=dfs 序)
找相等的还可以考虑用 hash 比较, 但是对树求 hash 成本太高了(需要序列化 + 存储)

p140 开始的 mut iter 看不懂,算了。
8.5 的结论提到的用 goto 实现状态机可以理解成一个 match case 分发操作到不同的函数。
临时违反再复原在 cpp 里很常用,比如递归回溯。

P160 迭代器拷贝
有点想到 c 的
基于范围的 copy 在 rust 里大概是
链起来非常优美。

P171 开始的代码很有 sicp 的味道了。用泛型近似 Any,requires 本质就是个文档宏。所有判断都用 Fn 引入。代码里除了 if while 控制流外全是函数调用,非常 sicp

P181
开始引入群论。置换,轨道。
第 10 章的置换后面缓缓再看,目前没咂摸出啥味道。不过里面提到了计算次数。可能是重点。
那堆 template + typename + requires 的咒语看起来噪音太大了。

第 11 章开始可能需要对着 ide + 代码理解了(在车上看的,完全没进脑子)
notion image
rust 也有对应的问题, 比如 struct 的 Partial Move
就是讨论了一下数组的操作

12.1 实现 pair
sicp 的 cons
tuple 可以 cons 套 cons
造了一遍 stl 的 std::array<size, T>
类似 rust 的 [T; N]

P224 的 bounded_range 可以对应 rust 的 a..=b
对 range 取 index 的目前需要 slice_index_methods

我们不应该去限制基础机器和语言的表达能力, 而应该为每种可用结构确定适当的用法. 好的软件产品出自各种组件的正确组织, 而不是出自一套语法的或者语义的约束.

指针的意义
拷贝可以从 rust 的 Copy vs Clone 去理解.
销毁可以从 Drop 去理解

P239 最后一段在讲 RAII
 
Loading...
Steven Lynn
Steven Lynn
喂马、劈柴、周游世界
最新发布
我与 Dify 的半年
2025-3-9
我的2022年终小结
2024-11-9
记录雅思考试经历与一点学习心得
2024-11-9
Hackergame 2024 思路小结
2024-11-9
黑客松、日本、入职:我的2024下半年的总结
2024-11-9
NotionNext:基于Notion和NextJS的开源博客
2024-11-9