V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  lxdlam  ›  全部回复第 1 页 / 共 5 页
回复总数  93
1  2  3  4  5  
1 天前
回复了 UncleCAT4 创建的主题 Linux 谈谈使用 Linux 三年以来的感受
本科阶段用了很久的 Manjaro ,现在主力开发两台机器还是 macOS + Fedora ,不太追求 Cutting Edge 的滚动更新,Fedora 用着正好。

之前用过一段时间 NixOS ,但是 NixOS 会有一些 dirty hack 的工作要做,会有一定量级的时间定期调配置文件,后面就放弃日常使用了,下一步打算在 CI 场景用一下。
7 天前
回复了 Yadomin 创建的主题 程序员 Redis 更换了开源协议
Redis 这次换其实是比较强盗逻辑的。

背景是 Redis 之前开发了很多附加组件,如时序数据扩展 Timeseries ,JSON 扩展 RedisJSON ,然后这一系列扩展统称为 Redis Stack ,所有 RedisStack 就是按 SSPL 分发的,同时保持原有的代码为 3-Clause BSD 。

> In fact, more than 50% of redis.io downloads – from Redis 6 and beyond – come from Redis Stack. We now believe that extending this licensing to Redis itself will enable us to continue to evolve the most holistic set of data models, processing engines, and developer capabilities for our users.

根据原文,他们觉得既然有超过 50% 的用户下载 Redis 都是从 Redis Stack 过来的,那为什么不把这俩合一呢?是否合理、怎么合并暂且不提,单纯因为这个原因把 core Redis 的 License 换成 RSAL+SSPL ,就纯粹是在绑架那一批完全用不到 Redis Stack 的用户了。而显然,这虽然看起来是 Redis 跟托管云的斗争,但是实际上这部分成本总会以各种形式转嫁到 end user 上。
我的桌面是 Windows ,用一对 PreSouns Eris 3.5 ,但是接了个外置声卡走的平衡输出。
9 天前
回复了 xinbaoCode 创建的主题 程序员 如何简单 100%安全存放自己的密码?
介绍一下另一种形式,并非由一个 committee 来决定的形式:[终身仁慈独裁者]( https://en.wikipedia.org/wiki/Benevolent_dictator_for_life),从 Python 之父开始的一个特定名称,被他毙掉的 PEP 不计其数。一个非常著名的提案是 PEP-572 ,就是 Python 3.8 引入的赋值(海象)操作符 `:=`,社区对这个提案一直比较两极化,但是 Guido 下场了,最终通过这个提案。

Disclaimer:我并没有说这个提案通过跟 Guido 下场有直接关系,现象如此,而且我也经常使用海象操作符。
将一个接口 wrap 进一个 db transaction 本身只保证了 db 操作的“原子性”,这还建立在本身 db 的 txn 处于正确的 isolation level 下。

所谓的接口原子性要考虑的问题远比这个复杂,如果使用了其他的后端服务,诸如 Redis 写入、第三方系统 API 调用,当非原子操作产生时,这些服务是否均支持回滚?是否保证回滚时的一致性?这样就需要从业务逻辑去考虑,然后落实到技术层面去解决,比如 Redis 是否需要 transaction 去配合?对于不支持原子的操作技术上如何取消?无法取消的事务如何在业务跟技术层面去做补偿?
我可能是极少数买了 Mathematica for Home&Hobby 的,今年他把 Cloud access 整合之后估计就继续按年续 Service plan 了
52 天前
回复了 stimw 创建的主题 Python pdm 还是 dev container?
目前主用 rye ,只能说非常舒服
@lxdlam 当然,进阶还有更多话题,比如备份经常还有可能备份错,所以多天 snapshot 之类做回滚也是常见需求;根据 321 原则,是否在合理价格内支持两地、多地同步 etc ,这些大部分也都会算在成本点里面
感觉很多东西楼主没考虑到:

- 流量费用如何计算? Ingress 跟 Egress 各自怎么计算?
- SLA 如何保证?数据取回是否会有延迟?全球上传和下载平均速度如何?
- 安全和合规如何保证?不是所有人、所有存储方案都适合用 borg ,如果直接使用 S3 跟 WebDAV etc ,平台怎么保证安全性?如果有监管部门审计需求会如何响应?

在加密备份领域业界最好的方案应该是 Tarsnap ,当然也不便宜;跟你这个方案类似的是 rsync.net ,他们提供的安全性和方式支持非常完善,供参考。
并没有找工作,只是很好奇一件事:你们对 Elixir 的态度如何?
57 天前
回复了 wyhaya 创建的主题 分享创造 Dataflare: 一款简单轻量的数据库管理器
非常好看,用了下也挺轻量级的,支持了一波。提一个功能建议,可以增加 intergrate db shell 的支持,类似于 mongo compass 和 redis insight 下面的 integrated shell
用 Windows 10 专业电竞战斗版 1.5 。

https://www.v2ex.com/i/z8Tz1085.jpeg

图源来自网络。
59 天前
回复了 darkbread 创建的主题 游戏 游戏玩到一半玩不下去需要坚持吗?
我一向觉得游戏的目的是找到快乐,如果找不到快乐了,就可以不玩。
一方面我同意 #3 ,更像是编译器的 bug ,另一方面我本地似乎复现不了这个差距如此巨大的结果,估计可以看下 1.21rc 到现在( go 1.21.6 ) 的差异。

而对于一定程度上的差异( 100000ns per op ),单纯从生成代码上来看,f 生成的函数直接对 r 做了修改,所以需要一次对 r 的 load ,而 g 是对一个临时变量做修改,虽然二者都是一次 load 跟一次 store ,但是 r 毕竟不好说分配在哪儿(也许在 heap 上,也许在 register ,看编译器优化),那么 r 确实可能比起临时变量( go 倾向于分配在 register 上)的读写要更慢。至于为什么会有如此差异,实际上应该是因为编译器识别出来了这个累加 pattern ,而在 f 里因为没有额外操作,所以直接对 r 进行操作,把加数这些都当 immediate value 优化成单次 INCQ 了;而在 g 中,由于又读到了 r + 0 ,编译器首先优化成了将其写入中间变量的操作,又在后续 pass 中发现其实对 r 基本无操作,去掉了这里面所有 r 的主动 reference ,将其完全优化到了完全只读写中间变量,所以生成了这个样子的代码。

以上仅抛砖引玉,我不是 plan9 和 go compiler 专家,只能看个大概,这里面同样可能会有很多说不清的其他因素影响。但是我仍然同意,这种 case 应该 report 给官方去修改,而不是当新时代的语言律师模拟考题,同样,如果在乎这个粒度的性能差距,可能我们会选择更精细的语言和优化方式了,而不是在这继续抄写茴字剩下的写法。
日区 Spotify 已经两年+。

从体验上来说,AM 跟 Spotify 的算法都很不错,冷启动到符合我的喜好学习速度很快,也不会跟 Youtube 一样,播放列表只会循环推完全特定的歌,基本零探索性(比如推一些可能会喜欢可能不喜欢的)。

但是 AM 缺了一些关键功能,比如必须苹果全家桶才能用上比较好的远程控制,但也仅限是手机/电脑 -> HomePod ,诸如 Spotify 的所有端都可以跨端控制有很大距离。同时,除了苹果之外,Android 上的体验也不尽如人意,最终放弃。

从音质上来说,流媒体我完全不在意音质,确实非常喜欢的歌我都会去 mora ,ototoy 买 Hi-Res 或者直接收实体 CD 抓一份,我对流媒体的核心要求还是方便+曲库+算法。

特别补一个,Apple 的 iTunes Match ,就是所谓的“云盘”,其实非常难用。iTunes 的标签修复有非常大的苹果延迟,就是你并不能完全知道到底这个 tag 修复有没有被正常推到音乐库里面,有可能在 mac 上看起来修了,换个设备发现压根没变化。同时,上传音乐的时候苹果会去自己的音乐库 match ,如果有就会用自己的替代,这样如果你抓了 44.1khz 16bit 的 flac ,但是苹果并没有这个音质的版权,他会给你 match 回 aac 版本,音质倒退。
@ShadowPower 上面 #67 老哥也提到了,其实这个范式在函数式社区很常见,我们重点不关注你是不是所谓的“错误”,而关注类型本身,考虑用类型做 matcher 去配合值做 transformation 。这些年一些工业界的看起来很新的方法都来源于此,比如经典的 parser combinator ,如果你把 `Result<T>` 这个二元类型异构容器思考成 `Pair<&str /* remain input */, Result<T /* Token type */>>`,其实这里面的函数组合跟我上面说的 error monad 是一致的。更进一步来说,函数式的底层数学抽象 lambda calculus ,其实就是一种 combinatory logic ,天生以组合为主。在这种背景下,函数式语言采用这种思考是非常直接的。
@lxdlam typo:这种双类型语言 => 这种支持双类型(甚至更多类型)组成异构容器的语言
单从两种范式上来说,值类型跟异常类型错误直接比较很难比较清楚:

- 值类型还是将错误当作值,本身没有控制流操作,所以当作值处理可以轻松当作比如 data 的一部分到处传递处理等等,缺点就是缺乏强制力,简单把值 ignore 掉就可以丢掉错误,而大家都倾向于懒一点;
- 异常类型可以打断并接管控制流,更加强大,guarantee 也更好,如果 runtime 实现得不错(比如 Java )那用起来其实还是很舒服的,缺点就是这个特性很容易被误用(相信大家都听说过或者见过用 exception 传值的业务代码)。

两种范式各有优劣,其实没有直接关系,语言风格而已。

而单纯讨论值类型错误,Go 的实现有自己的优势。错误这个东西本身就是很容易产生很多 concrete type 的,基于 duck typing 的 interface 化,其实大大简化很多操作,比如直接把已有 error wrap 起来,然后实现一下 `Error` 和一些 helper function ,就能快速搞一个新的错误出来,开发效率是很高的(没有 thiserror 和 anyhow 之前,Rust 搞个自定义错误有多痛苦,相信很多朋友深有体会)。
Go 最大的问题其实在于,他采用了值类型错误,但是类型系统支持非常 basic ,导致大家处理错误非常痛苦。比如在类型系统比较现代的语言中,这种双类型语言或多或少能实现一定程度的 monad ,这样我们就可以写出类似于:
```
let val = some_function().map(fun).map(foo).map(bar);

match val {
Ok(v) => println!("Value is: {}", v),
Error(e) => println!("Failed! error: {}", e),
}
```
在这里面,我们我们确实不关心中间错误,直接 chain 起来,处理最后错误就行,而如果我们关心比如到某一步的错误,我们单独接一下这一步的结果就可以拿到中间结果再做处理。无论是看起来还是读起来,其实都非常清晰明了。而可惜的是,Go 因为一开始设计压根没想这个问题,导致现在的打补丁的 generics ,很长线看起来都很难支持这种比较完备的 monad 特性。所以,我们只能一步步 if-else ,或者将这三个函数塞到一个 slice 里面,用 `reflect` 循环每个函数 apply 去每一步拿一下 type 信息做一些非常丑的补丁。
稍微补一句:为啥这里需要比较好的类型系统才能实现?在上面的流程中,实际上 `map` 接到的函数签名类型是各不一样的,有比较好类型系统的编译器在这里可以做非常好的静态推断;或者我们完全交给动态类型,损失一定 runtime 性能也能做到。而可惜的是,Go 既要选择尽量静态类型,又没把静态类型做很好,就卡在这了。
1  2  3  4  5  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5373 人在线   最高记录 6543   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 49ms · UTC 08:36 · PVG 16:36 · LAX 01:36 · JFK 04:36
Developed with CodeLauncher
♥ Do have faith in what you're doing.