隨手扎
【心得筆記】Emacs、Rust、Kotlin成就取得
除了Golang,上週也把Emacs相關的、Rust、Kotlin等給看完取得成就~
就來簡短紀錄一下。
學習GNU Emacs
推薦指數:★☆☆☆☆
讀完日期:2020/02/12
想要學習Gnu Emacs,看一下內建的教程就好。這本我只是略讀,感覺對我幫助不大。總之如果你想學Gnu Emacs,不用讀這本,應該這樣做:
- 下載Gnu Emacs
- M-x help-with-tutorial-spec-language
- 選擇繁體中文
- 然後閱讀它
※ 如果你有開上方的menu-bar,也可以直接選擇help->Emacs Tutorial(C-h t)。
GNU Emacs Lisp編程入門
推薦指數:★☆☆☆☆
讀完日期:2020/02/13
如果你有寫elisp的需求,這本書可以略過,但有的話,可以看下。Emacs Lisp API文檔並不那麼好入門,這個可以帶你入一點點門(幫助有限就是)。
上面兩本書我看的都是比較舊的了,也都是略讀。這本裡面提到的技術手冊我沒找著。
Kotlin語言文檔(v1.3)
推薦指數:★★★☆☆
讀完日期:2020/02/13
语言的设计是石头铸造的(译注:原文为“cast in stone”,意为“最终定论,板上钉钉”,此处双關
但这块石头相当柔软,经过一番努力,我们可以后期重塑它。
– Kotlin 设计团队Kotlin 旨在成为程序员的实用工具。
在语言演进方面,它的实用主义本质遵循以下原则:— 一直保持语言的现代性。
— 与用戶保持持续的反馈循环。
— 使版本更新对用戶来说是舒适的。由于这是理解 Kotlin 如何向前发展的关键。
Page 502
官方文檔的中文翻譯,很棒!Kotlin設計的我還算喜歡。想學的話,這可以看看。
不過有部份沒有翻譯。(意外我幾乎還是看完了,說明我英文有進步?)
最主要的目標是JVM,勢必得了解兩者差異。
与 Java 语言比较
Kotlin 解决了一些 Java 中的问题
Kotlin 通过以下措施修复了 Java 中一系列⻓期困扰我们的问题:— 空引用由类型系统控制。
— 无原始类型
— KOTLIN 中数组是不型变的
— 相对于 JAVA 的 SAM-转换, KOTLIN 有更合适的 函数类型
— 没有通配符的使用处型变
— KOTLIN 没有受检异常JAVA 有而 KOTLIN 没有的东西
— 受检异常
— 不是类的原生类型
— 静态成员
— 非私有化字段
— 通配符类型
— 三目操作符 A ? B : CKOTLIN 有而 JAVA 没有的东西
— LAMBDA 表达式 + 内联函数 = 高性能自定义控制结构
— 扩展函数
— 空安全
— 智能类型转换
— 字符串模板
— 属性
— 主构造函数
— 一等公⺠的委托
— 变量与属性类型的类型推断
— 单例
— 声明处型变 & 类型投影
— 区间表达式
— 操作符重载
— 伴生对象
— 数据类
— 分离用于只读与可变集合的接口
— 协程
Page.526
Rust程式設計從頭開始
推薦指數:★★★☆☆
讀完日期:2020/02/21
相比下面那本,這本好入門很多。不過畢竟下面是正式文檔,我還是看了下。
Rust Book 中文翻譯
推薦指數:★★☆☆☆
讀完日期:2020/02/21
很深,有些東西還需要再理解下。
記憶體管理
这里有两个术语是关于内存管理的。栈和堆是帮助你决定何时分配和释放内存的抽象(概念)。
这是一个高层次的比较: 栈非常快速,并且是Rust默认分配内存的地方。不过这个分配位于函数调用的本地,并有大小限制。堆,在另一方面,更慢,并且需要被你的程序显式分配。不过它无事实上的大小限制,并且是全局可访问的。大部分语言有一个默认堆分配的垃圾回收器。这意味着每个值都是装箱的。有很多原因为什么要这么做,不过这超出了这个教程的范畴。这也有一些优化会使得这些规则不是100%的时间为真。与其依赖栈和Drop来清理内存,垃圾回收器用处理堆来代替。
那么如果栈是更快并更易于管理的,那么我们为啥还需要堆呢?一个大的原因是只有栈分配的话意味着你只有先进后出语义的获取存储的方法。堆分配严格的说更通用,允许以任意顺序从池中取出和返回存储,不过有复杂度开销。
一般来说,你应该倾向于栈分配,因此,Rust默认栈分配。栈的先进后出模型在基础层面上更简单。这有两个重大的影响:运行时效率和语义影响。…
……非先进后出语义的灵活性(也就是说:表现力)意味着大体上讲编译器不能在编译时自动推断出哪些内存应该被释放;它不得不依赖动态协议,可能来自于语言之外,来驱动释放(引用计数,就像是用Rc和Arc,是这个的一个例子)。
当考虑到极端情况,堆分配的增加的表现力带来了要么是显著的运行时支持
錯誤處理
在try!中封装一个表达式会返回一个未封装的正确(Ok)值,除非结果是Err,在这种情况下Err会从当前函数提早返回。
值得注意的是你只能在一个返回Result的函数中使用try!,这意味着你不能在main()中使用try!,因为main()不返回任何东西。
多型
当涉及到多态的代码时,我们需要一个机制来决定哪个具体的版本应该得到执行。这叫做“分发”(dispatch)。大体上有两种形式的分发:静态分发和动态分发。虽然Rust喜欢静态分发,不过它也提供了一个叫做“trait对象”的机制来支持动态分发。
宣告覆蓋(重複宣告)
Rust允許覆蓋已經宣告的變數。
fn main() {
let message = "Hello, World";
println!("{}", message); // => "Hello, World"
let message = "Hello, Daniel";
println!("{}", message); // => "Hello, Daniel"
}
哲學家問題的解決方法
use std::thread;
use std::sync::{Mutex, Arc};
struct Philosopher {
name: String,
left: usize,
right: usize,
}
impl Philosopher {
fn new(name: &str, left: usize, right: usize) -> Philosopher {
Philosopher {
name: name.to_string(),
left: left,
right: right,
}
}
fn eat(&self, table: &Table) {
let _left = table.forks[self.left].lock().unwrap();
let _right = table.forks[self.right].lock().unwrap();
println!("{} is eating.", self.name);
thread::sleep_ms(1000);
println!("{} is done eating.", self.name);
}
}
struct Table {
forks: Vec<Mutex<()>>,
}
fn main() {
let table = Arc::new(Table { forks: vec![
Mutex::new(()),
Mutex::new(()),
Mutex::new(()),
Mutex::new(()),
Mutex::new(()),
]});
let philosophers = vec![
Philosopher::new("Baruch Spinoza", 0, 1),
Philosopher::new("Gilles Deleuze", 1, 2),
Philosopher::new("Karl Marx", 2, 3),
Philosopher::new("Friedrich Nietzsche", 3, 4),
Philosopher::new("Michel Foucault", 0, 4),
];
let handles: Vec<_> = philosophers.into_iter().map(|p| {
let table = table.clone();
thread::spawn(move || {
p.eat(&table);
})
}).collect();
for h in handles {
h.join().unwrap();
}
}
米歇尔·福柯应该使用4,0作为参数,不过我们用了0,4。这事实上是为了避免死锁:我们的哲学家中有一个左撇子!这是解决这个问题的一个方法,并且在我看来,是最简单的方法。
其他
- [2020/02/22] 為你自己學 Ruby on Rails