EncodingError
is the base class for encoding errors.
SystemCallError
is the base class for all low-level platform-dependent errors.
The errors available on the current platform are subclasses of SystemCallError
and are defined in the Errno
module.
File.open("does/not/exist")
raises the exception:
Errno::ENOENT: No such file or directory - does/not/exist
A rational number can be represented as a pair of integer numbers: a/b (b>0), where a is the numerator and b is the denominator. Integer
a equals rational a/1 mathematically.
You can create a Rational object explicitly with:
A rational literal.
You can convert certain objects to Rationals with:
Method Rational
.
Examples
Rational(1) #=> (1/1) Rational(2, 3) #=> (2/3) Rational(4, -6) #=> (-2/3) # Reduced. 3.to_r #=> (3/1) 2/3r #=> (2/3)
You can also create rational objects from floating-point numbers or strings.
Rational(0.3) #=> (5404319552844595/18014398509481984) Rational('0.3') #=> (3/10) Rational('2/3') #=> (2/3) 0.3.to_r #=> (5404319552844595/18014398509481984) '0.3'.to_r #=> (3/10) '2/3'.to_r #=> (2/3) 0.3.rationalize #=> (3/10)
A rational object is an exact number, which helps you to write programs without any rounding errors.
10.times.inject(0) {|t| t + 0.1 } #=> 0.9999999999999999 10.times.inject(0) {|t| t + Rational('0.1') } #=> (1/1)
However, when an expression includes an inexact component (numerical value or operation), it will produce an inexact result.
Rational(10) / 3 #=> (10/3) Rational(10) / 3.0 #=> 3.3333333333333335 Rational(-8) ** Rational(1, 3) #=> (1.0000000000000002+1.7320508075688772i)
A Range object represents a collection of values that are between given begin and end values.
You can create an Range object explicitly with:
A range literal:
# Ranges that use '..' to include the given end value. (1..4).to_a # => [1, 2, 3, 4] ('a'..'d').to_a # => ["a", "b", "c", "d"] # Ranges that use '...' to exclude the given end value. (1...4).to_a # => [1, 2, 3] ('a'...'d').to_a # => ["a", "b", "c"]
A range may be created using method Range.new
:
# Ranges that by default include the given end value. Range.new(1, 4).to_a # => [1, 2, 3, 4] Range.new('a', 'd').to_a # => ["a", "b", "c", "d"] # Ranges that use third argument +exclude_end+ to exclude the given end value. Range.new(1, 4, true).to_a # => [1, 2, 3] Range.new('a', 'd', true).to_a # => ["a", "b", "c"]
A beginless range has a definite end value, but a nil
begin value. Such a range includes all values up to the end value.
r = (..4) # => nil..4 r.begin # => nil r.include?(-50) # => true r.include?(4) # => true r = (...4) # => nil...4 r.include?(4) # => false Range.new(nil, 4) # => nil..4 Range.new(nil, 4, true) # => nil...4
A beginless range may be used to slice an array:
a = [1, 2, 3, 4] r = (..2) # => nil...2 a[r] # => [1, 2]
Method each
for a beginless range raises an exception.
An endless range has a definite begin value, but a nil
end value. Such a range includes all values from the begin value.
r = (1..) # => 1.. r.end # => nil r.include?(50) # => true Range.new(1, nil) # => 1..
The literal for an endless range may be written with either two dots or three. The range has the same elements, either way. But note that the two are not equal:
r0 = (1..) # => 1.. r1 = (1...) # => 1... r0.begin == r1.begin # => true r0.end == r1.end # => true r0 == r1 # => false
An endless range may be used to slice an array:
a = [1, 2, 3, 4] r = (2..) # => 2.. a[r] # => [3, 4]
Method each
for an endless range calls the given block indefinitely:
a = [] r = (1..) r.each do |i| a.push(i) if i.even? break if i > 10 end a # => [2, 4, 6, 8, 10]
A range can be both beginless and endless. For literal beginless, endless ranges, at least the beginning or end of the range must be given as an explicit nil value. It is recommended to use an explicit nil beginning and implicit nil end, since that is what Ruby uses for Range#inspect
:
(nil..) # => (nil..) (..nil) # => (nil..) (nil..nil) # => (nil..)
An object may be put into a range if its class implements instance method <=>
. Ruby core classes that do so include Array
, Complex
, File::Stat
, Float
, Integer
, Kernel
, Module
, Numeric
, Rational
, String
, Symbol
, and Time
.
Example:
t0 = Time.now # => 2021-09-19 09:22:48.4854986 -0500 t1 = Time.now # => 2021-09-19 09:22:56.0365079 -0500 t2 = Time.now # => 2021-09-19 09:23:08.5263283 -0500 (t0..t2).include?(t1) # => true (t0..t1).include?(t2) # => false
A range can be iterated over only if its elements implement instance method succ
. Ruby core classes that do so include Integer
, String
, and Symbol
(but not the other classes mentioned above).
Iterator methods include:
Included from module Enumerable: each_entry
, each_with_index
, each_with_object
, each_slice
, each_cons
, and reverse_each
.
Example:
a = [] (1..4).each {|i| a.push(i) } a # => [1, 2, 3, 4]
A user-defined class that is to be used in a range must implement instance <=>
; see Integer#<=>
. To make iteration available, it must also implement instance method succ
; see Integer#succ
.
The class below implements both <=>
and succ
, and so can be used both to construct ranges and to iterate over them. Note that the Comparable
module is included so the ==
method is defined in terms of <=>
.
# Represent a string of 'X' characters. class Xs include Comparable attr_accessor :length def initialize(n) @length = n end def succ Xs.new(@length + 1) end def <=>(other) @length <=> other.length end def to_s sprintf "%2d #{inspect}", @length end def inspect 'X' * @length end end r = Xs.new(3)..Xs.new(6) #=> XXX..XXXXXX r.to_a #=> [XXX, XXXX, XXXXX, XXXXXX] r.include?(Xs.new(5)) #=> true r.include?(Xs.new(7)) #=> false
First, what’s elsewhere. Class Range:
Inherits from class Object.
Includes module Enumerable, which provides dozens of additional methods.
Here, class Range provides methods that are useful for:
::new
: Returns a new range.
begin
: Returns the begin value given for self
.
bsearch
: Returns an element from self
selected by a binary search.
count
: Returns a count of elements in self
.
end
: Returns the end value given for self
.
exclude_end?
: Returns whether the end object is excluded.
first
: Returns the first elements of self
.
hash
: Returns the integer hash code.
last
: Returns the last elements of self
.
max
: Returns the maximum values in self
.
min
: Returns the minimum values in self
.
minmax
: Returns the minimum and maximum values in self
.
size
: Returns the count of elements in self
.
==
: Returns whether a given object is equal to self
(uses ==
).
===
: Returns whether the given object is between the begin and end values.
cover?
: Returns whether a given object is within self
.
eql?
: Returns whether a given object is equal to self
(uses eql?
).
include?
(aliased as member?
): Returns whether a given object is an element of self
.
%
: Requires argument n
; calls the block with each n
-th element of self
.
each
: Calls the block with each element of self
.
step
: Takes optional argument n
(defaults to 1); calls the block with each n
-th element of self
.
inspect
: Returns a string representation of self
(uses inspect
).
to_a
(aliased as entries
): Returns elements of self
in an array.
::json_create
: Returns a new Range object constructed from the given object.
as_json
: Returns a 2-element hash representing self
.
to_json
: Returns a JSON string representing self
.
To make these methods available:
require 'json/add/range'
SocketError
is the error class for socket.
StringScanner
provides for lexical scanning operations on a String
. Here is an example of its usage:
require 'strscan' s = StringScanner.new('This is an example string') s.eos? # -> false p s.scan(/\w+/) # -> "This" p s.scan(/\w+/) # -> nil p s.scan(/\s+/) # -> " " p s.scan(/\s+/) # -> nil p s.scan(/\w+/) # -> "is" s.eos? # -> false p s.scan(/\s+/) # -> " " p s.scan(/\w+/) # -> "an" p s.scan(/\s+/) # -> " " p s.scan(/\w+/) # -> "example" p s.scan(/\s+/) # -> " " p s.scan(/\w+/) # -> "string" s.eos? # -> true p s.scan(/\s+/) # -> nil p s.scan(/\w+/) # -> nil
Scanning a string means remembering the position of a scan pointer, which is just an index. The point of scanning is to move forward a bit at a time, so matches are sought after the scan pointer; usually immediately after it.
Given the string “test string”, here are the pertinent scan pointer positions:
t e s t s t r i n g 0 1 2 ... 1 0
When you scan
for a pattern (a regular expression), the match must occur at the character after the scan pointer. If you use scan_until
, then the match can occur anywhere after the scan pointer. In both cases, the scan pointer moves just beyond the last character of the match, ready to scan again from the next character onwards. This is demonstrated by the example above.
Method
Categories There are other methods besides the plain scanners. You can look ahead in the string without actually scanning. You can access the most recent match. You can modify the string being scanned, reset or terminate the scanner, find out or change the position of the scan pointer, skip ahead, and so on.
beginning_of_line?
(bol?)
Data
There are aliases to several of the methods.
Raised when OLE processing failed.
EX:
obj = WIN32OLE.new("NonExistProgID")
raises the exception:
WIN32OLERuntimeError: unknown OLE server: `NonExistProgID' HRESULT error code:0x800401f3 Invalid class string
Raised when an IO
operation fails.
File.open("/etc/hosts") {|f| f << "example"} #=> IOError: not opened for writing File.open("/etc/hosts") {|f| f.close; f.read } #=> IOError: closed stream
Note that some IO
failures raise SystemCallError
s and these are not subclasses of IOError:
File.open("does/not/exist") #=> Errno::ENOENT: No such file or directory - does/not/exist
Raised by some IO
operations when reaching the end of file. Many IO
methods exist in two forms,
one that returns nil
when the end of file is reached, the other raises EOFError
.
EOFError
is a subclass of IOError
.
file = File.open("/etc/hosts") file.read file.gets #=> nil file.readline #=> EOFError: end of file reached file.close
ARGF
is a stream designed for use in scripts that process files given as command-line arguments or passed in via STDIN.
The arguments passed to your script are stored in the ARGV
Array
, one argument per element. ARGF
assumes that any arguments that aren’t filenames have been removed from ARGV
. For example:
$ ruby argf.rb --verbose file1 file2 ARGV #=> ["--verbose", "file1", "file2"] option = ARGV.shift #=> "--verbose" ARGV #=> ["file1", "file2"]
You can now use ARGF
to work with a concatenation of each of these named files. For instance, ARGF.read
will return the contents of file1 followed by the contents of file2.
After a file in ARGV
has been read ARGF
removes it from the Array
. Thus, after all files have been read ARGV
will be empty.
You can manipulate ARGV
yourself to control what ARGF
operates on. If you remove a file from ARGV
, it is ignored by ARGF
; if you add files to ARGV
, they are treated as if they were named on the command line. For example:
ARGV.replace ["file1"] ARGF.readlines # Returns the contents of file1 as an Array ARGV #=> [] ARGV.replace ["file2", "file3"] ARGF.read # Returns the contents of file2 and file3
If ARGV
is empty, ARGF
acts as if it contained "-"
that makes ARGF
read from STDIN, i.e. the data piped or typed to your script. For example:
$ echo "glark" | ruby -e 'p ARGF.read' "glark\n" $ echo Glark > file1 $ echo "glark" | ruby -e 'p ARGF.read' -- - file1 "glark\nGlark\n"
OptionParser
OptionParser
? See the Tutorial.
OptionParser
is a class for command-line option analysis. It is much more advanced, yet also easier to use, than GetoptLong
, and is a more Ruby-oriented solution.
The argument specification and the code to handle it are written in the same place.
It can output an option summary; you don’t need to maintain this string separately.
Optional and mandatory arguments are specified very gracefully.
Arguments can be automatically converted to a specified class.
Arguments can be restricted to a certain set.
All of these features are demonstrated in the examples below. See make_switch
for full documentation.
require 'optparse' options = {} OptionParser.new do |parser| parser.banner = "Usage: example.rb [options]" parser.on("-v", "--[no-]verbose", "Run verbosely") do |v| options[:verbose] = v end end.parse! p options p ARGV
OptionParser
can be used to automatically generate help for the commands you write:
require 'optparse' Options = Struct.new(:name) class Parser def self.parse(options) args = Options.new("world") opt_parser = OptionParser.new do |parser| parser.banner = "Usage: example.rb [options]" parser.on("-nNAME", "--name=NAME", "Name to say hello to") do |n| args.name = n end parser.on("-h", "--help", "Prints this help") do puts parser exit end end opt_parser.parse!(options) return args end end options = Parser.parse %w[--help] #=> # Usage: example.rb [options] # -n, --name=NAME Name to say hello to # -h, --help Prints this help
For options that require an argument, option specification strings may include an option name in all caps. If an option is used without the required argument, an exception will be raised.
require 'optparse' options = {} OptionParser.new do |parser| parser.on("-r", "--require LIBRARY", "Require the LIBRARY before executing your script") do |lib| puts "You required #{lib}!" end end.parse!
Used:
$ ruby optparse-test.rb -r optparse-test.rb:9:in `<main>': missing argument: -r (OptionParser::MissingArgument) $ ruby optparse-test.rb -r my-library You required my-library!
OptionParser
supports the ability to coerce command line arguments into objects for us.
OptionParser
comes with a few ready-to-use kinds of type coercion. They are:
Date
– Anything accepted by Date.parse
(need to require optparse/date
)
DateTime
– Anything accepted by DateTime.parse
(need to require optparse/date
)
Time
– Anything accepted by Time.httpdate
or Time.parse
(need to require optparse/time
)
URI
– Anything accepted by URI.parse
(need to require optparse/uri
)
Shellwords
– Anything accepted by Shellwords.shellwords
(need to require optparse/shellwords
)
String
– Any non-empty string
Integer
– Any integer. Will convert octal. (e.g. 124, -3, 040)
Float
– Any float. (e.g. 10, 3.14, -100E+13)
Numeric
– Any integer, float, or rational (1, 3.4, 1/3)
DecimalInteger
– Like Integer
, but no octal format.
OctalInteger
– Like Integer
, but no decimal format.
DecimalNumeric
– Decimal integer or float.
TrueClass
– Accepts ‘+, yes, true, -, no, false’ and defaults as true
FalseClass
– Same as TrueClass
, but defaults to false
Array
– Strings separated by ‘,’ (e.g. 1,2,3)
Regexp
– Regular expressions. Also includes options.
We can also add our own coercions, which we will cover below.
As an example, the built-in Time
conversion is used. The other built-in conversions behave in the same way. OptionParser
will attempt to parse the argument as a Time
. If it succeeds, that time will be passed to the handler block. Otherwise, an exception will be raised.
require 'optparse' require 'optparse/time' OptionParser.new do |parser| parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time| p time end end.parse!
Used:
$ ruby optparse-test.rb -t nonsense ... invalid argument: -t nonsense (OptionParser::InvalidArgument) $ ruby optparse-test.rb -t 10-11-12 2010-11-12 00:00:00 -0500 $ ruby optparse-test.rb -t 9:30 2014-08-13 09:30:00 -0400
The accept
method on OptionParser
may be used to create converters. It specifies which conversion block to call whenever a class is specified. The example below uses it to fetch a User
object before the on
handler receives it.
require 'optparse' User = Struct.new(:id, :name) def find_user id not_found = ->{ raise "No User Found for id #{id}" } [ User.new(1, "Sam"), User.new(2, "Gandalf") ].find(not_found) do |u| u.id == id end end op = OptionParser.new op.accept(User) do |user_id| find_user user_id.to_i end op.on("--user ID", User) do |user| puts user end op.parse!
Used:
$ ruby optparse-test.rb --user 1 #<struct User id=1, name="Sam"> $ ruby optparse-test.rb --user 2 #<struct User id=2, name="Gandalf"> $ ruby optparse-test.rb --user 3 optparse-test.rb:15:in `block in find_user': No User Found for id 3 (RuntimeError)
Hash
The into
option of order
, parse
and so on methods stores command line options into a Hash
.
require 'optparse' options = {} OptionParser.new do |parser| parser.on('-a') parser.on('-b NUM', Integer) parser.on('-v', '--verbose') end.parse!(into: options) p options
Used:
$ ruby optparse-test.rb -a {:a=>true} $ ruby optparse-test.rb -a -v {:a=>true, :verbose=>true} $ ruby optparse-test.rb -a -b 100 {:a=>true, :b=>100}
The following example is a complete Ruby program. You can run it and see the effect of specifying various options. This is probably the best way to learn the features of optparse
.
require 'optparse' require 'optparse/time' require 'ostruct' require 'pp' class OptparseExample Version = '1.0.0' CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary] CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" } class ScriptOptions attr_accessor :library, :inplace, :encoding, :transfer_type, :verbose, :extension, :delay, :time, :record_separator, :list def initialize self.library = [] self.inplace = false self.encoding = "utf8" self.transfer_type = :auto self.verbose = false end def define_options(parser) parser.banner = "Usage: example.rb [options]" parser.separator "" parser.separator "Specific options:" # add additional options perform_inplace_option(parser) delay_execution_option(parser) execute_at_time_option(parser) specify_record_separator_option(parser) list_example_option(parser) specify_encoding_option(parser) optional_option_argument_with_keyword_completion_option(parser) boolean_verbose_option(parser) parser.separator "" parser.separator "Common options:" # No argument, shows at tail. This will print an options summary. # Try it and see! parser.on_tail("-h", "--help", "Show this message") do puts parser exit end # Another typical switch to print the version. parser.on_tail("--version", "Show version") do puts Version exit end end def perform_inplace_option(parser) # Specifies an optional option argument parser.on("-i", "--inplace [EXTENSION]", "Edit ARGV files in place", "(make backup if EXTENSION supplied)") do |ext| self.inplace = true self.extension = ext || '' self.extension.sub!(/\A\.?(?=.)/, ".") # Ensure extension begins with dot. end end def delay_execution_option(parser) # Cast 'delay' argument to a Float. parser.on("--delay N", Float, "Delay N seconds before executing") do |n| self.delay = n end end def execute_at_time_option(parser) # Cast 'time' argument to a Time object. parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time| self.time = time end end def specify_record_separator_option(parser) # Cast to octal integer. parser.on("-F", "--irs [OCTAL]", OptionParser::OctalInteger, "Specify record separator (default \\0)") do |rs| self.record_separator = rs end end def list_example_option(parser) # List of arguments. parser.on("--list x,y,z", Array, "Example 'list' of arguments") do |list| self.list = list end end def specify_encoding_option(parser) # Keyword completion. We are specifying a specific set of arguments (CODES # and CODE_ALIASES - notice the latter is a Hash), and the user may provide # the shortest unambiguous text. code_list = (CODE_ALIASES.keys + CODES).join(', ') parser.on("--code CODE", CODES, CODE_ALIASES, "Select encoding", "(#{code_list})") do |encoding| self.encoding = encoding end end def optional_option_argument_with_keyword_completion_option(parser) # Optional '--type' option argument with keyword completion. parser.on("--type [TYPE]", [:text, :binary, :auto], "Select transfer type (text, binary, auto)") do |t| self.transfer_type = t end end def boolean_verbose_option(parser) # Boolean switch. parser.on("-v", "--[no-]verbose", "Run verbosely") do |v| self.verbose = v end end end # # Return a structure describing the options. # def parse(args) # The options specified on the command line will be collected in # *options*. @options = ScriptOptions.new @args = OptionParser.new do |parser| @options.define_options(parser) parser.parse!(args) end @options end attr_reader :parser, :options end # class OptparseExample example = OptparseExample.new options = example.parse(ARGV) pp options # example.options pp ARGV
Completion
For modern shells (e.g. bash, zsh, etc.), you can use shell completion for command line options.
The above examples, along with the accompanying Tutorial, should be enough to learn how to use this class. If you have any questions, file a ticket at bugs.ruby-lang.org.
Raised when Ruby can’t yield as requested.
A typical scenario is attempting to yield when no block is given:
def call_block yield 42 end call_block
raises the exception:
LocalJumpError: no block given (yield)
A more subtle example:
def get_me_a_return Proc.new { return 42 } end get_me_a_return.call
raises the exception:
LocalJumpError: unexpected return
Raised in case of a stack overflow.
def me_myself_and_i me_myself_and_i end me_myself_and_i
raises the exception:
SystemStackError: stack level too deep
Ractor is an Actor-model abstraction for Ruby that provides thread-safe parallel execution.
Ractor.new
makes a new Ractor, which can run in parallel.
# The simplest ractor r = Ractor.new {puts "I am in Ractor!"} r.take # wait for it to finish # Here, "I am in Ractor!" is printed
Ractors do not share all objects with each other. There are two main benefits to this: across ractors, thread-safety concerns such as data-races and race-conditions are not possible. The other benefit is parallelism.
To achieve this, object sharing is limited across ractors. For example, unlike in threads, ractors can’t access all the objects available in other ractors. Even objects normally available through variables in the outer scope are prohibited from being used across ractors.
a = 1 r = Ractor.new {puts "I am in Ractor! a=#{a}"} # fails immediately with # ArgumentError (can not isolate a Proc because it accesses outer variables (a).)
The object must be explicitly shared:
a = 1 r = Ractor.new(a) { |a1| puts "I am in Ractor! a=#{a1}"}
On CRuby (the default implementation), Global Virtual Machine Lock (GVL) is held per ractor, so ractors can perform in parallel without locking each other. This is unlike the situation with threads on CRuby.
Instead of accessing shared state, objects should be passed to and from ractors by sending and receiving them as messages.
a = 1 r = Ractor.new do a_in_ractor = receive # receive blocks until somebody passes a message puts "I am in Ractor! a=#{a_in_ractor}" end r.send(a) # pass it r.take # Here, "I am in Ractor! a=1" is printed
There are two pairs of methods for sending/receiving messages:
Ractor#send
and Ractor.receive
for when the sender knows the receiver (push);
Ractor.yield
and Ractor#take
for when the receiver knows the sender (pull);
In addition to that, any arguments passed to Ractor.new
are passed to the block and available there as if received by Ractor.receive
, and the last block value is sent outside of the ractor as if sent by Ractor.yield
.
A little demonstration of a classic ping-pong:
server = Ractor.new(name: "server") do puts "Server starts: #{self.inspect}" puts "Server sends: ping" Ractor.yield 'ping' # The server doesn't know the receiver and sends to whoever interested received = Ractor.receive # The server doesn't know the sender and receives from whoever sent puts "Server received: #{received}" end client = Ractor.new(server) do |srv| # The server is sent to the client, and available as srv puts "Client starts: #{self.inspect}" received = srv.take # The client takes a message from the server puts "Client received from " \ "#{srv.inspect}: #{received}" puts "Client sends to " \ "#{srv.inspect}: pong" srv.send 'pong' # The client sends a message to the server end [client, server].each(&:take) # Wait until they both finish
This will output something like:
Server starts: #<Ractor:#2 server test.rb:1 running> Server sends: ping Client starts: #<Ractor:#3 test.rb:8 running> Client received from #<Ractor:#2 server test.rb:1 blocking>: ping Client sends to #<Ractor:#2 server test.rb:1 blocking>: pong Server received: pong
Ractors receive their messages via the incoming port, and send them to the outgoing port. Either one can be disabled with Ractor#close_incoming
and Ractor#close_outgoing
, respectively. When a ractor terminates, its ports are closed automatically.
When an object is sent to and from a ractor, it’s important to understand whether the object is shareable or unshareable. Most Ruby objects are unshareable objects. Even frozen objects can be unshareable if they contain (through their instance variables) unfrozen objects.
Shareable objects are those which can be used by several threads without compromising thread-safety, for example numbers, true
and false
. Ractor.shareable?
allows you to check this, and Ractor.make_shareable
tries to make the object shareable if it’s not already, and gives an error if it can’t do it.
Ractor.shareable?(1) #=> true -- numbers and other immutable basic values are shareable Ractor.shareable?('foo') #=> false, unless the string is frozen due to # frozen_string_literal: true Ractor.shareable?('foo'.freeze) #=> true Ractor.shareable?([Object.new].freeze) #=> false, inner object is unfrozen ary = ['hello', 'world'] ary.frozen? #=> false ary[0].frozen? #=> false Ractor.make_shareable(ary) ary.frozen? #=> true ary[0].frozen? #=> true ary[1].frozen? #=> true
When a shareable object is sent (via send
or Ractor.yield
), no additional processing occurs on it. It just becomes usable by both ractors. When an unshareable object is sent, it can be either copied or moved. The first is the default, and it copies the object fully by deep cloning (Object#clone
) the non-shareable parts of its structure.
data = ['foo', 'bar'.freeze] r = Ractor.new do data2 = Ractor.receive puts "In ractor: #{data2.object_id}, #{data2[0].object_id}, #{data2[1].object_id}" end r.send(data) r.take puts "Outside : #{data.object_id}, #{data[0].object_id}, #{data[1].object_id}"
This will output something like:
In ractor: 340, 360, 320 Outside : 380, 400, 320
Note that the object ids of the array and the non-frozen string inside the array have changed in the ractor because they are different objects. The second array’s element, which is a shareable frozen string, is the same object.
Deep cloning of objects may be slow, and sometimes impossible. Alternatively, move: true
may be used during sending. This will move the unshareable object to the receiving ractor, making it inaccessible to the sending ractor.
data = ['foo', 'bar'] r = Ractor.new do data_in_ractor = Ractor.receive puts "In ractor: #{data_in_ractor.object_id}, #{data_in_ractor[0].object_id}" end r.send(data, move: true) r.take puts "Outside: moved? #{Ractor::MovedObject === data}" puts "Outside: #{data.inspect}"
This will output:
In ractor: 100, 120 Outside: moved? true test.rb:9:in `method_missing': can not send any methods to a moved object (Ractor::MovedError)
Notice that even inspect
(and more basic methods like __id__
) is inaccessible on a moved object.
Class
and Module
objects are shareable so the class/module definitions are shared between ractors. Ractor objects are also shareable. All operations on shareable objects are thread-safe, so the thread-safety property will be kept. We can not define mutable shareable objects in Ruby, but C extensions can introduce them.
It is prohibited to access (get) instance variables of shareable objects in other ractors if the values of the variables aren’t shareable. This can occur because modules/classes are shareable, but they can have instance variables whose values are not. In non-main ractors, it’s also prohibited to set instance variables on classes/modules (even if the value is shareable).
class C class << self attr_accessor :tricky end end C.tricky = "unshareable".dup r = Ractor.new(C) do |cls| puts "I see #{cls}" puts "I can't see #{cls.tricky}" cls.tricky = true # doesn't get here, but this would also raise an error end r.take # I see C # can not access instance variables of classes/modules from non-main Ractors (RuntimeError)
Ractors can access constants if they are shareable. The main Ractor is the only one that can access non-shareable constants.
GOOD = 'good'.freeze BAD = 'bad'.dup r = Ractor.new do puts "GOOD=#{GOOD}" puts "BAD=#{BAD}" end r.take # GOOD=good # can not access non-shareable objects in constant Object::BAD by non-main Ractor. (NameError) # Consider the same C class from above r = Ractor.new do puts "I see #{C}" puts "I can't see #{C.tricky}" end r.take # I see C # can not access instance variables of classes/modules from non-main Ractors (RuntimeError)
See also the description of shareable_constant_value pragma in Comments syntax explanation.
Each ractor has its own main Thread
. New threads can be created from inside ractors (and, on CRuby, they share the GVL with other threads of this ractor).
r = Ractor.new do a = 1 Thread.new {puts "Thread in ractor: a=#{a}"}.join end r.take # Here "Thread in ractor: a=1" will be printed
In the examples below, sometimes we use the following method to wait for ractors that are not currently blocked to finish (or to make progress).
def wait sleep(0.1) end
It is **only for demonstration purposes** and shouldn’t be used in a real code. Most of the time, take
is used to wait for ractors to finish.
See Ractor design doc for more details.
Random
provides an interface to Ruby’s pseudo-random number generator, or PRNG. The PRNG produces a deterministic sequence of bits which approximate true randomness. The sequence may be represented by integers, floats, or binary strings.
The generator may be initialized with either a system-generated or user-supplied seed value by using Random.srand
.
The class method Random.rand
provides the base functionality of Kernel.rand
along with better handling of floating point values. These are both interfaces to the Ruby system PRNG.
Random.new
will create a new PRNG with a state independent of the Ruby system PRNG, allowing multiple generators with different seed values or sequence positions to exist simultaneously. Random
objects can be marshaled, allowing sequences to be saved and resumed.
PRNGs are currently implemented as a modified Mersenne Twister with a period of 2**19937-1. As this algorithm is not for cryptographical use, you must use SecureRandom
for security purpose, instead of this PRNG.
See also Random::Formatter
module that adds convenience methods to generate various forms of random data.
Raised when given an invalid regexp expression.
Regexp.new("?")
raises the exception:
RegexpError: target of repeat operator is not specified: /?/
Raised when an invalid operation is attempted on a thread.
For example, when no other thread has been started:
Thread.stop
This will raises the following exception:
ThreadError: stopping only thread note: use sleep to stop forever
The exception class which will be raised when pushing into a closed Queue. See Thread::Queue#close
and Thread::SizedQueue#close
.
A class that provides the functionality of Kernel#set_trace_func
in a nice Object-Oriented API.
We can use TracePoint
to gather information specifically for exceptions:
trace = TracePoint.new(:raise) do |tp| p [tp.lineno, tp.event, tp.raised_exception] end #=> #<TracePoint:disabled> trace.enable #=> false 0 / 0 #=> [5, :raise, #<ZeroDivisionError: divided by 0>]
If you don’t specify the type of events you want to listen for, TracePoint
will include all available events.
Note do not depend on current event set, as this list is subject to change. Instead, it is recommended you specify the type of events you want to use.
To filter what is traced, you can pass any of the following as events
:
:line
execute an expression or statement on a new line
:class
start a class or module definition
:end
finish a class or module definition
:call
call a Ruby method
:return
return from a Ruby method
:c_call
call a C-language routine
:c_return
return from a C-language routine
:raise
raise an exception
:rescue
rescue an exception
:b_call
event hook at block entry
:b_return
event hook at block ending
:a_call
event hook at all calls (call
, b_call
, and c_call
)
:a_return
event hook at all returns (return
, b_return
, and c_return
)
:thread_begin
event hook at thread beginning
:thread_end
event hook at thread ending
:fiber_switch
event hook at fiber switch
:script_compiled
new Ruby code compiled (with eval
, load
or require
)
Raised when throw
is called with a tag which does not have corresponding catch
block.
throw "foo", "bar"
raises the exception:
UncaughtThrowError: uncaught throw "foo"
The Kernel
module is included by class Object
, so its methods are available in every Ruby object.
The Kernel
instance methods are documented in class Object
while the module methods are documented here. These methods are called without a receiver and thus can be called in functional form:
sprintf "%.1f", 1.234 #=> "1.2"
Module Kernel provides methods that are useful for:
__callee__
: Returns the called name of the current method as a symbol.
__dir__
: Returns the path to the directory from which the current method is called.
__method__
: Returns the name of the current method as a symbol.
autoload?
: Returns the file to be loaded when the given module is referenced.
binding
: Returns a Binding
for the context at the point of call.
block_given?
: Returns true
if a block was passed to the calling method.
caller
: Returns the current execution stack as an array of strings.
caller_locations
: Returns the current execution stack as an array of Thread::Backtrace::Location
objects.
class
: Returns the class of self
.
frozen?
: Returns whether self
is frozen.
global_variables
: Returns an array of global variables as symbols.
local_variables
: Returns an array of local variables as symbols.
test
: Performs specified tests on the given single file or pair of files.
abort
: Exits the current process after printing the given arguments.
at_exit
: Executes the given block when the process exits.
exit
: Exits the current process after calling any registered at_exit
handlers.
exit!
: Exits the current process without calling any registered at_exit
handlers.
catch
: Executes the given block, possibly catching a thrown object.
raise
(aliased as fail
): Raises an exception based on the given arguments.
throw
: Returns from the active catch block waiting for the given tag.
::pp
: Prints the given objects in pretty form.
gets
: Returns and assigns to $_
the next line from the current input.
open
: Creates an IO
object connected to the given stream, file, or subprocess.
p
: Prints the given objects’ inspect output to the standard output.
print
: Prints the given objects to standard output without a newline.
printf
: Prints the string resulting from applying the given format string to any additional arguments.
putc
: Equivalent to <tt.$stdout.putc(object)</tt> for the given object.
puts
: Equivalent to $stdout.puts(*objects)
for the given objects.
readline
: Similar to gets
, but raises an exception at the end of file.
readlines
: Returns an array of the remaining lines from the current input.
lambda
: Returns a lambda proc for the given block.
set_trace_func
: Sets the given proc as the handler for tracing, or disables tracing if given nil
.
trace_var
: Starts tracing assignments to the given global variable.
untrace_var
: Disables tracing of assignments to the given global variable.
`command`: Returns the standard output of running command
in a subshell.
exec
: Replaces current process with a new process.
fork
: Forks the current process into two processes.
spawn
: Executes the given command and returns its pid without waiting for completion.
system
: Executes the given command in a subshell.
autoload
: Registers the given file to be loaded when the given constant is first referenced.
load
: Loads the given Ruby file.
require
: Loads the given Ruby file unless it has already been loaded.
require_relative
: Loads the Ruby file path relative to the calling file, unless it has already been loaded.
tap
: Yields self
to the given block; returns self
.
then
(aliased as yield_self
): Yields self
to the block and returns the result of the block.
rand
: Returns a pseudo-random floating point number strictly between 0.0 and 1.0.
srand
: Seeds the pseudo-random number generator with the given number.
eval
: Evaluates the given string as Ruby code.
loop
: Repeatedly executes the given block.
sleep
: Suspends the current thread for the given number of seconds.
sprintf
(aliased as format
): Returns the string resulting from applying the given format string to any additional arguments.
syscall
: Runs an operating system call.
trap
: Specifies the handling of system signals.
warn
: Issue a warning based on the given messages and options.
Module Enumerable provides methods that are useful to a collection class for:
These methods return information about the Enumerable other than the elements themselves:
include?
, member?
: Returns true
if self == object
, false
otherwise.
all?
: Returns true
if all elements meet a specified criterion; false
otherwise.
any?
: Returns true
if any element meets a specified criterion; false
otherwise.
none?
: Returns true
if no element meets a specified criterion; false
otherwise.
one?
: Returns true
if exactly one element meets a specified criterion; false
otherwise.
count
: Returns the count of elements, based on an argument or block criterion, if given.
tally
: Returns a new Hash
containing the counts of occurrences of each element.
These methods return entries from the Enumerable, without modifying it:
Leading, trailing, or all elements:
first
: Returns the first element or leading elements.
take
: Returns a specified number of leading elements.
drop
: Returns a specified number of trailing elements.
take_while
: Returns leading elements as specified by the given block.
drop_while
: Returns trailing elements as specified by the given block.
Minimum and maximum value elements:
min
: Returns the elements whose values are smallest among the elements, as determined by <=>
or a given block.
max
: Returns the elements whose values are largest among the elements, as determined by <=>
or a given block.
minmax
: Returns a 2-element Array
containing the smallest and largest elements.
min_by
: Returns the smallest element, as determined by the given block.
max_by
: Returns the largest element, as determined by the given block.
minmax_by
: Returns the smallest and largest elements, as determined by the given block.
Groups, slices, and partitions:
group_by
: Returns a Hash
that partitions the elements into groups.
partition
: Returns elements partitioned into two new Arrays, as determined by the given block.
slice_after
: Returns a new Enumerator
whose entries are a partition of self
, based either on a given object
or a given block.
slice_before
: Returns a new Enumerator
whose entries are a partition of self
, based either on a given object
or a given block.
slice_when
: Returns a new Enumerator
whose entries are a partition of self
based on the given block.
chunk
: Returns elements organized into chunks as specified by the given block.
chunk_while
: Returns elements organized into chunks as specified by the given block.
These methods return elements that meet a specified criterion:
find_all
, filter
, select
: Returns elements selected by the block.
find_index
: Returns the index of an element selected by a given object or block.
reject
: Returns elements not rejected by the block.
uniq
: Returns elements that are not duplicates.
These methods return elements in sorted order:
sort
: Returns the elements, sorted by <=>
or the given block.
sort_by
: Returns the elements, sorted by the given block.
each_entry
: Calls the block with each successive element (slightly different from each).
each_with_index
: Calls the block with each successive element and its index.
each_with_object
: Calls the block with each successive element and a given object.
each_slice
: Calls the block with successive non-overlapping slices.
each_cons
: Calls the block with successive overlapping slices. (different from each_slice
).
reverse_each
: Calls the block with each successive element, in reverse order.
filter_map
: Returns truthy objects returned by the block.
flat_map
, collect_concat
: Returns flattened objects returned by the block.
grep
: Returns elements selected by a given object or objects returned by a given block.
grep_v
: Returns elements selected by a given object or objects returned by a given block.
reduce
, inject
: Returns the object formed by combining all elements.
sum
: Returns the sum of the elements, using method +
.
zip
: Combines each element with elements from other enumerables; returns the n-tuples or calls the block with each.
cycle
: Calls the block with each element, cycling repeatedly.
To use module Enumerable in a collection class:
Include it:
include Enumerable
Implement method each which must yield successive elements of the collection. The method will be called by almost any Enumerable method.
Example:
class Foo include Enumerable def each yield 1 yield 1, 2 yield end end Foo.new.each_entry{ |element| p element }
Output:
1 [1, 2] nil
These Ruby core classes include (or extend) Enumerable:
These Ruby standard library classes include Enumerable:
Virtually all methods in Enumerable call method each in the including class:
Hash#each
yields the next key-value pair as a 2-element Array
.
Struct#each
yields the next name-value pair as a 2-element Array
.
For the other classes above, each yields the next object from the collection.
The example code snippets for the Enumerable methods:
Ruby exception objects are subclasses of Exception
. However, operating systems typically report errors using plain integers. Module
Errno
is created dynamically to map these operating system errors to Ruby classes, with each error number generating its own subclass of SystemCallError
. As the subclass is created in module Errno
, its name will start Errno::
.
The names of the Errno::
classes depend on the environment in which Ruby runs. On a typical Unix or Windows platform, there are Errno
classes such as Errno::EACCES, Errno::EAGAIN, Errno::EINTR, and so on.
The integer operating system error number corresponding to a particular error is available as the class constant Errno::
error::Errno
.
Errno::EACCES::Errno #=> 13 Errno::EAGAIN::Errno #=> 11 Errno::EINTR::Errno #=> 4
The full list of operating system errors on your particular platform are available as the constants of Errno
.
Errno.constants #=> :E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, ...