深入 Ruby 07:闭包与非局部控制流
一段带 return 的 block 在方法内部调用时可以正常返回,保存后等方法结束再调用,却可能抛 LocalJumpError。原因不是代码内容改变,而是退出目标已经不在当前执行路径里。闭包同时保存环境,控制语句还携带特定的退出语义,两者必须分开分析。 文章卡 项目 内容 先修 第 06 篇的 Proc、lambda 和 yield 实验 bundle exec ruby labs/07/run.rb 核心问题 return、break、next 分别终止哪次执行? 验收 有效与失效的 return/break、lambda 局部返回、共享闭包绑定 工程边界 长期保存回调优先使用明确的 call 返回契约 闭包捕获绑定,不是输入快照 两个闭包可以访问同一个外层局部变量: 123456count = 0increment = -> { count += 1 }observe = -> { count }increment.callincrement.callraise unless obse...
深入 Ruby 06:block、Proc 与 lambda
Ruby 的 block 可以让遍历方法把每项任务交给调用者处理。保存这段代码时常用 Proc,要求严格参数数量时可以用 lambda。它们并不是三个可随意替换的名称;执行位置、参数处理和退出行为都需要保持清楚。 文章卡 项目 内容 先修 第 05 篇的位置、关键字与 block 通道 实验 bundle exec ruby labs/06/run.rb 核心问题 谁调用 block,Proc 怎样接收参数,lambda 严格到哪里? 验收 yield 轨迹、无 block 返回枚举器、数量错误与数组解构 边界 参数行为在本篇;非局部 return 与 break 在第 07 篇 yield 调用当前方法收到的 block 实验方法把两个值交给调用者,并且有一个与 block 结果无关的最终返回值: 1234567891011def twice(value) return enum_for(__method__, value) unless block_given? yield value yield value + 1 :finish...
深入 Ruby 05:方法与参数绑定
filter(tasks, min_priority: 4) 与 filter(tasks, { min_priority: 4 }) 看起来接近,却可以产生不同结果。调用不能只看参数内容,还要看参数通过哪条语法通道传入、接收方法如何声明。本篇用一个最小筛选接口检查绑定过程。 文章卡 项目 内容 先修 第 01、04 篇;Array、Hash 与基本方法 实验 bundle exec ruby labs/05/run.rb 核心问题 哪些实参进入位置、关键字与 block,默认值何时求值? 验收 正确关键字、位置 Hash 失败、未知参数失败、转发与默认对象 版本边界 Ruby 3.4.11;不采用 Ruby 2 的隐式关键字迁移经验 方法签名先定义调用形状 累计工具用一个清楚的签名: Taskbook.filter(tasks, min_priority: 1, tag: nil, status: nil) 接收一个位置参数和三个可选关键字。完整实现见随文工程 lib/taskbook.rb。 tasks 是必须提供的位置参数,后面三项是具有...
深入 Ruby 04:Array、Hash 与 Range
清单、索引和范围判断分别适合 Array、Hash 与 Range,但容器名称还不足以预测行为。数组里的对象可能共享,Hash 的默认值可能根本没有写进容器,Range 的 cover? 与 include? 也可能得到不同答案。本篇从这些差异解释集合契约。 文章卡 项目 内容 先修 第 02–03 篇;引用、字符串与数值相等 实验 bundle exec ruby labs/04/run.rb 核心问题 谁共享对象,键怎样相等,范围如何包含? 验收 Array 构造、Hash 默认值、数字键、字符串键与区间反例 工程应用 任务顺序用 Array,唯一 ID 用 Hash,优先级用数值 Range 数组保存引用,不隐含复制 Array.new(2, []) 只求值一次作为默认项的数组,然后把同一个对象放进两个位置。本篇验证: 1234567shared = Array.new(2, [])shared[0] << :changedraise unless shared == [[:changed], [:changed]]separ...
深入 Ruby 03:String、Symbol 与编码
任务标题 '任务' 包含两个字符,在 UTF-8 中占六个字节。给任意字节贴上 UTF-8 编码标记不会自动修复它。Ruby 的 String 同时涉及内容字节、编码与可变性,输入验收必须分别检查这些条件。 文章卡 项目 内容 先修 第 01–02 篇;字节与字符的概念 实验 bundle exec ruby labs/03/run.rb 核心问题 字节是否有效、转码是否发生、修改影响哪个引用? 验收 字节数、字符数、非法输入、转码往返、别名与正则锚点 工程边界 标题与标签保持文本,固定状态使用 Symbol;外部数据在入口转换 内容与编码是两种信息 实验从一个可核对的短字符串开始: 123text = '任务'raise unless text.bytesize == 6raise unless text.length == 2 bytesize 适合限制读取或传输的字节量,length 按字符串编码计算字符数量。用户感知的字符还可能由多个码点组成,例如组合音标或某些 emoji;界面截断需要研究字素簇,不能把任意 byt...
深入 Ruby 02:数字与转换
7 / 3 得到 2,-7 / 3 得到 -3;0.1 + 0.2 不等于 0.3;'oops'.to_i 得到 0。这些行为各有用途,但放进同一输入管道,就可能把错误数据变成合法业务值。本篇分别检查表示、运算、舍入与转换。 文章卡 项目 内容 先修 第 01 篇;除法、字符串与错误处理的概念 实验 bundle exec ruby labs/02/run.rb 核心问题 精度在哪里丢失,输入何时必须失败? 验收 负整数除法、浮点反例、两种精确表示、舍入与非法转换 边界 CRuby 3.4.11;BigDecimal 的加载版本由实验输出记录 整数不只是更小的浮点数 Ruby 的 Integer 表示整数。大整数仍保持整数计算,不因为超过常见机器字大小就自动变成 Float。lab 检查 (10**100 + 1) - 10**100 == 1,这项断言关注保留低位,并不承诺任意大的数字没有内存和计算成本。Integer 两个整数相除得到向下取整的商。负数最能区分向下取整与朝零截断: 123raise unless 7 / 3 == 2rais...
深入 Ruby 01:表达式与控制流
if 0 在 Ruby 中进入真分支,空字符串和空数组也是如此。用其他语言的“空值”经验判断 Ruby 条件,会把合法输入误当作缺失,也会把需要拒绝的数据放行。本篇从真实条件值开始,再观察控制结构产生的结果。 文章卡 项目 内容 先修 第 00 篇;赋值、方法与数组的基础概念 核心问题 条件如何判真,控制结构返回什么,短路跳过了什么? 实验 bundle exec ruby labs/01/run.rb 验收 六种值、短路轨迹、赋值优先级、case 接收者和循环结果 边界 CRuby 3.4.11;不把 Rails 的 blank? 当成语言规则 真值不等于有效输入 本篇 lab 将六个值放进相同的条件表达式: 123values = [nil, false, 0, '', [], {}]truth = values.map { |value| value ? true : false }raise unless truth == [false, false, true, true, ...
深入 Ruby 00:导读与可重复运行
一个 Ruby 文件可以只有三行,但运行它需要的不只是这三行。解释器版本、加载的 gem、输入字节、当前目录和环境变量都可能改变结果。学习语言时,先把这些条件固定,后面的对象模型和并发结论才有可复核的依据。 本系列使用 Ruby 3.4.11 和 CRuby。这个版本是教学基线,不代表 Ruby 的最新版。官方发布包的 SHA256 是 5c22be44524312b3d433d68739bcc530633b1da5ef8ba0afa0a37680da17d3de;本文工程实际从该包构建。版本冻结、依赖锁和源码 revision 分别记录在工程与研究资料里。Ruby 3.4.11 发布说明 文章卡 项目 内容 先修 一种通用编程语言;能运行终端命令 核心问题 怎样证明命令使用了所选解释器,并且结果满足约定? 累计工程 examples/ruby/lib/taskbook.rb,内存任务校验、筛选和统计 实验入口 工程根目录执行 ruby labs/00/check.rb 验收 正确筛选、统计、输入拒绝和复制隔离都有可失败断言 版本边界 CRuby...
计算机图形学 E08:三页缓存怎样显示八页纹理
一组纹理有八页,画面每次只用其中一页,GPU 是否需要始终保存全部八页?可以只留三个槽,缺哪页就上传哪页。但省下的容量要用上传和调度来交换;相机不断回来访问刚被淘汰的页时,这种交换可能很差。 本篇只研究纹理页流送。沿用第 25、26 篇的上传、绘制与读回方法,以及第 34、35 篇的固定输入、画质前置检查和重复测量,不扩建完整引擎。全部源页已在 CPU 内存中,因此实验不包括磁盘、网络、图片解码或压缩纹理转码。 先固定画面需要哪些字节 实验生成八张 64×64 的 RGBA8 页,每页 16,384 字节,透明度固定为 255。RGB 由页号与整数像素坐标生成,颜色只作为诊断码值,没有光照、过滤、mip、混合或额外的颜色转换。 把八页视为一条虚拟纹理带,相机每帧停在一个整数页中心,输出正好是这一页的 64×64 像素。这个“相机”只是确定页号的有界模型,没有透视变换或跨页过滤。两条轨迹都只访问前四页: 12局部性:0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3抖动: 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 两条路径的着色器...
计算机图形学 E07:用八个三维高斯拟合多视图图像
六张图能否约束同一个三维表示,使它在另外三个视角也接近目标?E06 只恢复固定场景的一个光强;这次同时调整八个高斯的世界中心、颜色和不透明度。每次渲染都从同一组世界参数重新投影,不能为每张图单独拟合二维椭圆。 实验采用 24×24 RGB 合成图、固定协方差和两组随机初始化。它复现三维高斯表示、投影、合成与多视图优化的受限子集,保留训练成本和全部持出结果。 数据与未知量怎样分开 每个高斯含三维中心 μ、线性 RGB 颜色 c 和不透明度 o,共 7 个待优化数,八个合计 56 个。世界协方差统一固定为 diag(0.045,0.025,0.035),单位是世界长度的平方;颜色没有视线方向依赖。这里没有神经网络权重,连续场由显式高斯参数表达。 生成器中的八个真实高斯只用于产生目标。训练器接收六幅 RGB、相机及公共约束,不接收真实中心和颜色。初始化种子固定为 701、702,中心各分量均匀取自 [−0.6,0.6],颜色来自 [0.2,0.8],不透明度为 0.5。更新后中心限制到 [−0.85,0.85],颜色和不透明度限制到 [0.02,0.98]。 相机绕原点布置,水平半径...



