From 7f62f512f983a4d992dd9a31bb5e2f7dc3195940 Mon Sep 17 00:00:00 2001 From: tannevaled Date: Wed, 4 Nov 2026 12:53:15 +0100 Subject: [PATCH] README: the ndarray axis keyword (#883) and what makes $/ a different setter (#886) Two sentences had fallen behind the code they describe. **NDArray.** The line read "(axis, keepdims: true)", so the only documented way to reduce along an axis was the positional one. #883 taught the reductions and cumsum NumPy's `axis:` spelling, and cumsum was not in the sentence at all. Verified against rbgo built at 6eb7e4ad: a.sum => 15.0 a.sum(axis: 0).to_a => [3.0, 5.0, 7.0] a.sum(0).to_a => [3.0, 5.0, 7.0] a.cumsum(axis: 1).to_a => [0.0, 1.0, 3.0, 3.0, 7.0, 12.0] a.argmax(axis: 1).to_a => [2.0, 2.0] a.sum(0, axis: 0) => ArgumentError: axis given both positionally and as a keyword **Predefined globals.** The list claims each global gets "the setter MRI's variable table gives it rather than one untyped slot", then groups `$;`, `$,` and `$/` as though one setter covered them. Init_IO wires `$,` and `$\` to rb_str_setter and `$/`/`$-0` to deprecated_rs_setter, and #886 made that split real: `$/` now stores a frozen plain String of the bytes it was given instead of the object itself. The README now says so, because that difference is exactly the claim the sentence makes. rubydiff against MRI 4.0.7, same program, five lines of output: AGREE exit 0 A rbgo-main ruby 4.0.9 [arm64-darwin] B ruby@4.0 ruby 4.0.7 (2026-09-15 revision 229531a6cf) +PRISM The same program under the system ruby 2.6.10 diverges on exactly the two `$/` lines and agrees on the two `$,`/`$\` lines, which is the control: the freezing is 4.0 behaviour, not something rbgo invented. Co-Authored-By: Claude Opus 5 --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 95723dbd..b7dd2c76 100644 --- a/README.md +++ b/README.md @@ -433,6 +433,11 @@ JRuby**): (`$LOAD_PATH = []` → `NameError`), the checked ones enforce their type (`$stdout = nil` → `TypeError: $stdout must have write method, NilClass given`), and **`trace_var`**/`untrace_var` hook assignment to a global. + The separators are not interchangeable: `$,` and `$\` take `rb_str_setter` + and store what they are handed, while `$/` and `$-0` take MRI's + `deprecated_rs_setter` and store a **frozen plain String** of the same bytes + — so `$/ = s` leaves `s` untouched, `$/.frozen?` is true, and `$/` is not + `s.equal?` unless `s` was already a frozen bare String. - **Strings:** mutable (reference semantics) with `<<`/concat/replace/prepend/ insert/`[]=`/slice!/the bang methods and `freeze`/`FrozenError`; interpolation, heredocs (`<<`/`<<-`/`<<~`), `%w`/`%i` and `%q`/`%Q`/`%W`/`%I` @@ -532,7 +537,10 @@ JRuby**): `+ - * / **` with broadcasting (a number on either side), `sqrt`/`exp`/`log`/`sin`/`cos`/`abs`/`square`/`clip`, `NDArray.maximum`/`minimum`; reductions `sum`/`mean`/`max`/`min`/`prod`/ - `argmax`/`argmin` (whole array, or `(axis, keepdims: true)`) and `cumsum`; + `argmax`/`argmin` (whole array, or along one axis with `keepdims: true`) and + `cumsum` (flattened, or along one axis). The axis may be given positionally + (`a.sum(0)`) or by keyword as NumPy spells it (`a.sum(axis: 0)`); both at + once raises `ArgumentError`; `matmul`/`dot`/`NDArray.outer`, `NDArray.concatenate`/`stack` (`axis:`); `shape`/`ndim`/`size`/`to_a` (flat), and `p a` prints NumPy's repr (`array([[0., 1.], ...])`). Every argument is checked: a wrong count or type