FrankHB 最近的时间轴更新
↓挽……
2022-04-15 12:27:47 +08:00
FrankHB

FrankHB

V2EX 第 34994 号会员,加入于 2013-02-28 10:06:28 +08:00
FrankHB 最近回复了
28 天前
回复了 yagamil 创建的主题 程序员 为啥 js 语言里面 那么喜欢嵌套,匿名
@yagamil 根本不是你理解的这样。就因为这种冗余的元数据的选取跟语义独立,所以才困难。因为这种东西就是给人看的,机器原则上不可能检查(除非是具有比你更强 NLP 能力的真·强 AI 到直接能把你淘汰的那种),你不可能预知别人看了会跟你想得一样,更不可能保证你的命名绝对是最优解,光是确保能满足需求的工作量就触及了“软件工程的本质困难”。一旦要添加能影响语义的特性(比如反射),又是一地鸡毛。
当然机器原则上不可能检查的东西多了,比如怎么让 GC 代替显式资源释放的位置。但是没有一个其它问题的普遍性能和命名困难相提并论。(如果有,那么最接近的是如何定义相等操作。)
29 天前
回复了 diagnostics 创建的主题 Android iOS 换成安卓,都是槽点
1.2.3. 没用过接近的机器,没遇到类似问题,无法评价。
4. 不 root 用安卓找啥不痛快啊。不过我的系统比较近原生本来也没内置广告,app 开屏的没几个,网页平时基本不用,也懒得动。
5. 也就这个是纯软件问题。然而平时基本用不到网页看视频,甚至没注意到……(有说 iOS 强的我也没法确认。)
29 天前
回复了 dayeye2006199 创建的主题 程序员 AI 热下被忽视的编程语言
@kiwi95 其它语言能不 crash 是有代价的,在 memory safety 问题上基本都依赖 GC (倒不需要 lint ),极少部分是 region-based 但基本没在工业界有显著性。依赖 GC 导致的 STW/latency 问题一直就没真正彻底解决过(总不能让用户都上 TB 级别的主存用 Azul C4 吧),就算现在可以不是主要问题了,RAM 利用率低下导致客户端开发从来都很糙,就不可能是正确的解决方向,只能是 workaround 。更要命的是依赖 GC 的代码在资源分配边界上缺乏不变量的混乱导致的质量问题,原则上是不可能解决的——你要非 GC 语言移植到依赖 GC 的语言直接干掉内存释放都行,反过来试试?实际上不依赖 GC 会迫使实现者分析清楚用 GC 不可能自动解决干净而本来就要人来决断的逻辑问题,设计的完善程度就是不一样的。一旦依赖 GC 就注定是半吊子实现,如果不能排除未来有更严格的质量需求,那基本得重写,提前背负这种风险相当不值。
所以实际上光是要避免这些实用问题,比较有存在感的语言也就 C 、C++、Rust 了。然后算上其它可维护性和管理成本选哪个?(这几个语言的 lint 也没多少用。) Rust 也就是矮子里拔高个,因为剩下的编译器做得更少,就算写起来简单点,review 成本更高。当然如果什么人都不缺可以直接 C++ ,不用跟 rustc 斗了(只要有本事兜得住 ICE 和依赖管理之类乱七八糟的破事就行)。
29 天前
回复了 dayeye2006199 创建的主题 程序员 AI 热下被忽视的编程语言
@chesha1 不,刚好相反,我首先不怎么有兴趣对连 prioritize spec 都搞不定的项目做贡献。Rust 能有显著性,只因在座的各位(在对付 memory safety 等问题上)更加辣鸡,所以显得 Rust 在对付不听话的 coder 节约 review 成本上有奇效。但是……我本来就不需要对付这些人。
另一方面,Rust 确保 safety 依赖具体 ad-hoc type system 的设计的欠缺灵活性是我直接不爽的——比如没法单独要 memory safety 而无视 concurrency safety (即便我甚至可以证明某段代码就是单线程下跑的),导致一些简单的写法不 unsafe 就表达不出来——如果时常考虑 unsafe 那我干嘛还要允许 rustc 浪费时间?所以我都不会拿 Rust 的设计过来抄,而是当作反面教材用。
至于没有兴趣折腾是很正常的,主要不是 Rust 的问题——而是因为一些基础设施不管用什么语言重新实现都很无聊,耗费资源又大,既然原来的东西不是烂到没法用,就没什么人有动机来推了。
比如这里很多东西依赖 CUDA 吧,但你也没法说老黄一直能嘚瑟,等写得差不多了,新一代跨设备的行业标准来了怎么办,岂不是 49 年入国军?关于 GPU 这方面软件栈长期选型问题都是传统艺能了,DX 还是 GL ,GL 还是 Vulkan ,要折腾迟早都要踩一遍坑。别人非得对付是因为有具体项目需求,我又没有,现在有了也可以用现成的凑数,又不是没法用。那么为什么不当等等党,拖着减少要踩的坑的绝对数量,等到有确定的具体项目需求发现不得不重新造了再说?
29 天前
回复了 yagamil 创建的主题 程序员 为啥 js 语言里面 那么喜欢嵌套,匿名
@FrankHB 还要做个语言限制的修正。
上文所述的 API ,不仅仅是环境中提供访问的函数名,明确包括形参名称这种 lambda calculus 中唯一提供的命名( bound variable )的方式。
实际情况是,具名函数的函数名被当作 API 的一部分,因为它指称的对象(函数)的内部结构是默认封装的,所以也就函数名以及类型这样的外部特征允许标识(identify) 一个 API 了。更何况还有基于具名函数的 ad-hoc polymorphism:重载。
然而函数以外的普通的对象的表示其实也是封装的,甚至某种意义上是更加封装的,内部结构同样不保证总是清楚唯一( ABI 的意义上例外)。那么为什么这些对象名不是 API 的一部分?因为两者的实现难度存在差别:实现的语义等价变换会重写函数体(或者 basic block 之类的变体),但是重写更一般的对象内部结构会依赖更困难和特设(ad-hoc)的方式来证明语义等价而不属于标准的优化技术(比如把整数和浮点数类型相互替换需要证明计算结果没有误差没有 fenv 副作用),所以一般不考虑。因此,把一个非函数的对象的结构暴露到 API 层次,容易混淆接口和实现的边界。所以就算全局对象作为 API 的一部分,一般也不会提供字段这样的内部表示,而是具体函数功能的一部分配置(典型例子是语言提供的标准流对象)。
但是,参数名在实现内部实际上还遵循一种更特殊普遍的 API:naming convention 。大多数情况下,只有一个函数形参命名成 x ,只要没其它嵌套作用域冲突,就已经够可读了。循环不变量的 i 、j 、k 同理。要强行提供更具体的命名反倒不一定更清晰,因为原始目的就没有这个意思。这种约定在大多数语言中不被视为 API ,因为大多数语言压根就没提供足够的反射机制来对变量名直接进行操作。但是,如果语言允许局部的完全反射并提供充分的操作(如 Lisp-like 的 symbol->string/string->symbol ),对代码对应的 AST 直接进行元编程,应该怎么命名变量名的 pattern 就是 API 的一部分。只不过这类 API 基本只会在自动化代码审查的元程序中用到,而且通常不像函数名和类型一样会被提前静态检查。
其它语言中这种情况相当少见,不过不是没有:例如 C 的宏允许做字符串拼接生成参数;例如 #pragma GCC poison 。无论如何,这些只能生成而无法反射的用法都相当恶心,所以缺少关注。
29 天前
回复了 yagamil 创建的主题 程序员 为啥 js 语言里面 那么喜欢嵌套,匿名
@FrankHB 严格来说,现在大多语言支持的 lambda 都是 applicative 的,也就是实际参数必须在调用前被严格求值,那么所有对应的形参和函数体默认都是封装的(编译器能够自由重写其内容而不管源代码里到底用了什么命名),除非有 MIT Scheme 那种 procedural-environment 这样的反射功能,或者另外严格约定基于源代码等价性的等于操作之类的奇葩设计。但如果函数不仅仅是 applicative 而可能是 operative 的(包括一般的过程宏或者 vau 这样的 FEXPR ctor 引入的匿名函数),实际参数可以非严格求值而直接把 AST 这样暴露源代码信息的东西扔进去计算(换种说法,默认就对源代码总是有完全反射),那么函数体封装和不封装之间区别就大了去了:不封装的函数会要求实现单独证明语义等价之后才允许变换,这一般是不可能的(除非预知实际参数是什么内容,做 partial evaluation )。

具名函数和匿名函数在这里的习惯性差别是,前者是否使用单独的语法形式(而非把匿名函数当初值进行变量定义的方式引入)的选择是未指定的。因此前者能够具有更严格的封装性要求,例如完全可以在语言规则中指定假定函数体就是封装的。ALGOL-like 的语言中函数声明和定义分离其实就依赖这种假设。
29 天前
回复了 yagamil 创建的主题 程序员 为啥 js 语言里面 那么喜欢嵌套,匿名
@yagamil 明明命名困难是两大计算机科学难题之一,你不在乎就无所谓了?
你这首先用复用不复用来判断命名的方式是病,得治。

使用符号命名是有明确的目的性的,就是塞入语义上无关紧要(操作语义上就是某种 alpha renaming ;虽然遇到反射会失效)但有确切含义的元数据来辅助人类阅读者改善推理,同时语言实现不影响语义等价翻译(比如编译优化)的可行性。后者可以在语义上约定自己的假设而同时能被机器改善推理(比如 devirtualization )。
其实这就是所谓的封装性(encapsulating)的确切内涵。因为教学质量的普遍垃圾,很少有人理解,不管是 access control 这样在 name resolution 上加 hook 还是 inclusion polymorphism 这样在 call 上加 hook ,都只是 encapsulation 的实现细节而已。

你若只是因为要让看得清楚,而不管这里的原始目的,这是胡搅蛮缠。因为只是为了看清楚,而不是区分“这个不是那个”这种依赖元数据内容的场合,完全可以用编辑器辅助的纯语法方式(例如高亮边界)解决。

一般地,在一个合理的设计中要求实体具名,充分必要条件是这个命名属于用户关心的 API 的一部分——只有这种场合人理解命名的冗余含义才能确保可能帮助准确地正确使用(当然前提是命名对了)而不是干扰人类读者的冗余噪声。否则,都是耍流氓。

有一种常见的误解是关于人为在源代码(而非实现内部变换)中引入“中间变量”的必要性。
实际上如果不考虑一等状态(比如 C++的那种 RAII ),任意的显式声明引入的中间变量在逻辑上是冗余的,只不过因为考虑读者的脑容量有限,避免发生 register spill 之类的问题,所以有的作者才试图这样做。
但是,这种中间变量完全可以 canonicalize 成 let form 。(学 ALGOL-like 语言学傻的不容易理解这一点,因为不知道 block 实际上是 lambda 的 derivation——用 JS 的话来说就是 IIFE 。)
这种情况下,到底什么变量才是真正有资格当中间变量的问题才会显著——只有能被复用时,才配被提升到 let 的变量名的位置上。
那么不被复用的复杂表达式可读性差怎么办?很简单,拆成具名函数的调用。引入的函数名就不是这种中间变量了,它可以是内部 API ,即便只被用到了一次。
之所以函数名和普通的变量名区别对待,是因为具名函数的实现默认是封装的(函数体不可见),因此它有资格单独占据名称。
当然,如果考虑一等状态,比如 lifetime 这种依赖对象自身存在的情况,那就有复杂多了的例外——因为存在隐含的资源释放,实际上有类似函数调用的作用。不过,遵循约定的代码反而会更清晰可读:如果严格遵循“不复用的对象不在 let form 中出现为变量名”,人很容易推理出为什么需要有孤零零(甚至一次都没用到)的对象;反之就麻烦多了,读者要自行验证这里到底复用了几次才放心。结果,在这个上下文中尽量排除没有复用的具名对象,反倒更合理了。

题外话,显式类型(explicit typing)和命名的必要性同等,也就是在 API 上才配用。所以 bb 什么 auto 啊 var 啊看不清楚类型的,那也是耍流氓。
29 天前
回复了 yagamil 创建的主题 程序员 为啥 js 语言里面 那么喜欢嵌套,匿名
@Al0rid4l 其实和为什么没多大关系,虽然允许遵循链式命名解析的变量(名)算是 lambda 演算的主要贡献,lambda 演算的命名就只有约束变量(函数参数)这个地方能用。而现代语言更常见的命名依赖的环境这种抽象是在 Lisp 用动态作用域实现 lambda 演算变体时提出的副产品(相比纯 lambda 演算依赖 capture 和 capture avoidance substitution ),并且环境的实现方式( alist )因为保存了状态恰好还同时更加兼容词法作用域和非纯函数式的用法( impure λv calculus ),能够直接平替没作用域的符号表而已。
所以也不是学 C 学傻,基本上不清楚一些历史的,默认只能当作都是傻的。
29 天前
回复了 dayeye2006199 创建的主题 程序员 AI 热下被忽视的编程语言
@user667788 要现代岂不是先得把 py 干掉?
没什么现代语言能抄个 1930 年就有的 lambda 还有脸限制一行的吧。

@L4Linux 什么叫不追求 memory safety ,你写的玩意儿有几个是可以随便 crash 无所谓的?
(就是挂在导弹上漏尿的都不算 Rust 所谓的 memory safety 。)
你要说用 Rust 是懒得 review 这种低端问题,让人跟 rustc 斗法节约时间,然而并不是所有项目都能节约出多少,这还差不多。

@chesha1 1. 市场是大但是分层且不互通,得看水平在什么程度上。
不限预算是无所谓的,反正什么语言都得会。
卡死预算也是无所谓的,反正这俩都不会。
中间层次就比较迷,得看从事的领域是不是恰好有很多已经造过的轮子。众所周知,C++和 Rust 用户造(烂)轮子的水平和品位半斤八两,如果一个领域流毒 C++烂轮子多、好轮子少,那么 C++就有超额成本;反过来就是 Rust 占便宜。但恰好这里 Rust 基本就没轮子……
至于跟 rustc 斗的更低层次的初级用户,比 CRUD boy 贵不了多少了。
2. 非技术问题。会折腾的没什么人有兴趣自己造更没资源推广。
3. “挺好的”,说明比较初级。

@uni spec ,请。

@talkischeap567 那坨前后一致性都有问题的 shit 伪码就见过写 cmodel 的翻译成 C/C++,没见过其他抖 M 来整活的。
106 天前
回复了 tracker647 创建的主题 C++ 这份简历大四春招投个中/小公司没问题吧?
@reallynyn 都 23 ?你给我在主流实现里找个 23 的 flat_map 给我抄抄?

(当然熟悉 C++11 特性嘛,要我来面的话……比如实现个 C++11 能用的 uses_allocator_construction_args 试试? https://github.com/FrankHB/YSLib/blob/master/YBase/include/ystdex/allocator.hpp#L203
关于   ·   帮助文档   ·   博客   ·   nftychat   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1802 人在线   最高记录 5634   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 21ms · UTC 16:25 · PVG 00:25 · LAX 09:25 · JFK 12:25
Developed with CodeLauncher
♥ Do have faith in what you're doing.