You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# Ruby 3.3: in `pack': unknown pack directive 'r' in 'r*' (ArgumentError)
33
+
```
29
34
***Notes:**
30
35
31
36
### `Dir.for_fd` and `Dir.fchdir`
32
37
33
-
***Reason:**
38
+
Two methods to accept an integer file descriptor as an argument: `for_fd` creates a `Dir` object from it; `fchdir` changes the current directory to one specified by a descriptor.
39
+
40
+
***Reason:** New methods allow to use UNIX file descriptors if they are returned from a C-level code or obtained from OS.
# It was performed in the Ruby's core folder, and lists the doc/ contents
54
+
55
+
# Attempt to use a bogus fileno will result in error:
56
+
Dir.for_fd(0)
57
+
# `for_fd': Not a directory - fdopendir (Errno::ENOTDIR)
58
+
59
+
# Same with fileno that doesn't designate a directory:
60
+
Dir.for_fd(Dir.new('README.md').fileno)
61
+
# in `initialize': Not a directory @ dir_initialize - README.md (Errno::ENOTDIR)
62
+
63
+
# Same logic works for .fchdir
64
+
Dir.fchdir(fileno) #=> 0
65
+
Dir.pwd
66
+
# "/home/zverok/projects/ruby/doc" -- the current path have changed successfully
67
+
```
37
68
***Notes:**
69
+
* The functionality is only supported on POSIX platforms;
70
+
* The initial [ticket](https://bugs.ruby-lang.org/issues/19347) only proposed to find a way to be able to change a current directory to one specified by a descriptor (i.e., what eventually became `.fchdir`), but during the discussion a need were discovered for a generic instantiation of a `Dir` instance from the descriptor (what became `from_fd`), as well as a generic way to change the current directory to one specified by `Dir` instance ([`#chdir`](TODO), which is not related to descriptors but is generically useful).
38
71
39
72
### `Dir#chdir`
40
73
41
-
***Reason:**
74
+
An instance method version of [Dir.chdir](https://docs.ruby-lang.org/en/master/Dir.html#method-c-chdir): changes the current working directory to one specified by the `Dir` instance.
***Notes:** Unlike [Dir.chdir](https://docs.ruby-lang.org/en/master/Dir.html#method-c-chdir), the new method doesn't have a block form (the form that restores previous working directory after the block is finished).
m ="2023-12-25".match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/)
94
+
m.named_captures
95
+
#=> {"year"=>"2023", "month"=>"12", "day"=>"25"}
96
+
m.named_captures(symbolize_names:true)
97
+
#=> {:year=>"2023", :month=>"12", :day=>"25"}
98
+
```
99
+
***Notes:** While `symbolize_names:` might looks somewhat strange (usually we talk about hash _keys_), it is done for consistency with Ruby standard library's [`JSON.parse`](https://docs.ruby-lang.org/en/master/JSON.html#module-JSON-label-Output+Options) signature, which inherited the terminology from the JSON specification.
54
100
55
101
### `Module#set_temporary_name`
56
102
@@ -60,7 +106,80 @@ Allows to assign a string to be rendered as class/module's `#name`, without assi
# `set_temporary_name': the temporary name must not be a constant path to avoid confusion (ArgumentError)
143
+
144
+
# When the module with a temporary name is put into a constant,
145
+
# it receives a permanent name, which can't be changed anymore
146
+
C= dynamic_class
147
+
148
+
# It affects all associated values (including modules)
149
+
150
+
dynamic_class #=> C
151
+
instance #=> #<C:0x0...>
152
+
instance.method(:foo) #=> #<Method: C#foo() ...>
153
+
dynamic_class::Nested#=> C::Nested
154
+
dynamic_class::OtherNested#=> C::OtherNested
155
+
156
+
dynamic_class.set_temporary_name("Can I have it back?")
157
+
# `set_temporary_name': can't change permanent name (RuntimeError)
158
+
159
+
# `nil` can be used to cleanup a temporary name:
160
+
other_class =Class.new
161
+
other_class.set_temporary_name("another one")
162
+
other_class #=> another one
163
+
other_class.set_temporary_name(nil)
164
+
other_class #=> #<Class:0x0...>
165
+
```
166
+
***Notes:** Any phrase that used as a temporary name would be used verbatim; this might create very confusing `#inspect` results and error messages; so it is advised to use strings somehow implying that the name belong to a module. Imagine we wrap into classes with temporary names RSpec-style examples, and then there is a typo in such example:
167
+
```ruby
168
+
it "works as a calculator"do
169
+
expec(2+2).to eq 4
170
+
end
171
+
# If we assign just the example description as a temp.name, the
172
+
# error would look like this:
173
+
#
174
+
# undefined method `expec' for an instance of works as a calculator
175
+
# ^^^^^^^^^^^^^^^^^^^^^
176
+
#
177
+
# ...which is confusing. So it is probably better to construct a
178
+
# module-like temporary name, to have:
179
+
#
180
+
# undefined method `expec' for an instance of MyFramework::Example("works as a calculator")
181
+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
182
+
```
64
183
65
184
### `ObjectSpace::WeakKeyMap`
66
185
@@ -100,13 +219,37 @@ A new "weak map" concept implementation. Unlike `ObjectSpace::WeakMap`, it compa
100
219
```
101
220
***Notes:**
102
221
103
-
### `Proc#dup` and `#clone` call `#initialize_dup` and `#initialize_clone`
222
+
### `Proc#dup` and `#clone` call `#initialize_dup` and `#initialize_copy`
104
223
105
-
***Reason:**
224
+
***Reason:** A fix for an old inconsistency: `Object`'s `#dup` and `#clone` methods docs
106
225
***Discussion:**[Feature #19362]
107
226
***Documentation:** — (Adheres to the behavior described for [Object#dup](https://docs.ruby-lang.org/en/master/Object.html#method-i-dup) and [#clone](https://docs.ruby-lang.org/en/master/Kernel.html#method-i-clone))
108
227
***Code:**
109
-
***Notes:**
228
+
```ruby
229
+
# The examples would work the same with
230
+
# #dup/#initialize_dup and #clone/#initialize_copy
231
+
classTaggedProc < Proc
232
+
attr_reader:tag
233
+
234
+
definitialize(tag)
235
+
super()
236
+
@tag= tag
237
+
end
238
+
239
+
definitialize_dup(other)
240
+
@tag= other.tag
241
+
super
242
+
end
243
+
end
244
+
245
+
proc=TaggedProc.new('admin') { }
246
+
247
+
proc.tag #=> 'admin'
248
+
proc.dup.tag
249
+
# Ruby 3.2 => nil, the duplication didn't went through initialize_dup
250
+
# Ruby 3.3 => "admin"
251
+
```
252
+
***Notes:** Inheriting from core classes is an advanced technique, and most of the times there are simple ways to achieve same goals (like wrapper objects containing a `Proc` and an additional info).
110
253
111
254
### `Process.warmup`
112
255
@@ -118,27 +261,45 @@ A new "weak map" concept implementation. Unlike `ObjectSpace::WeakMap`, it compa
118
261
119
262
### `Process::Status#&` and `#>>` are deprecated
120
263
121
-
***Reason:**
264
+
***Reason:** These methods have been treating `Process::Status` as a very thin wrapper around an integer value of the return status of the process; which is unreasonable for supporting Ruby in more varying environments.
### `Thread::Queue#freeze` and `SizedQueue#freeze` raise `TypeError`
128
270
129
-
***Reason:**
271
+
***Reason:** The discussion was started with a bug report about `Queue` not respecting `#freeze` in any way (`#push` and `#pop` were still working after `#freeze` call). It was then decided that allowing to freeze a queue like any other collection (leaving it immutable) would have questionable semantics: as `Queue` is meant to be an inter-thread communication utility, freezing a queue while some thread waits for it would either leave this thread hanging, or would require `#freeze`'s functionality to extend for communication with dependent threads. Neither is a good option, so the behavior of the method was changed to communicate that queue freezing doesn't make sense.
130
272
***Discussion:**[Bug #17146]
131
273
***Documentation:**[Thread::Queue#freeze](https://docs.ruby-lang.org/en/master/Thread/Queue.html#method-i-freeze) and [Thread::SizedQueue#freeze](https://docs.ruby-lang.org/en/master/Thread/SizedQueue.html#method-i-freeze)
132
-
***Code:**
133
-
***Notes:**
134
274
135
-
### `Range#reverse_each` behavior change with semi-open ranges
Specialized `Range#reverse_each` method is implemented.
278
+
279
+
***Reason:** Previously, `Range` didn't have a specialized `#reverse_each` method, so calling it would invoke a generic `Enumerable#reverse_each`. The latter works by converting the object to array, and then enumerating this array. In case of a `Range` this can be inefficient (producing large arrays) or impossible (when only upper bound of the range is defined)
# Ruby 3.2: can't iterate from NilClass (TypeError)
291
+
# Ruby 3.3: #=> [5, 4, 3]
292
+
293
+
(1...).reverse_each
294
+
# Ruby 3.2: hangs forever, trying to produce an array
295
+
# Ruby 3.3: `reverse_each': can't iterate from NilClass (TypeError)
296
+
297
+
# The latter change affects any type of range beginning:
298
+
('a'...).reverse_each
299
+
# Ruby 3.2: hangs forever, trying to produce an array
300
+
# Ruby 3.3: `reverse_each': can't iterate from NilClass (TypeError)
301
+
```
302
+
***Notes:** Other than raising `TypeError` for endless ranges (which works with any type of range beginning), the specialized behavior is only implemented for `Integer`. A possibility of a generalization was [discussed](https://bugs.ruby-lang.org/issues/18515#note-4) by using object's `#pred` method (opposite to `#succ`, which the range uses to iterate forward), but the scope of this change would be bigger, as currently only `Integer` implements such method. It is possible that the adjustments would be made in the future versions.
142
303
143
304
### `Refinement#target` as an alternative of `Refinement#refined_class`
0 commit comments