класс Object
frozen_string_literal: false
Object является корневым классом всех Ruby объектов. Object наследуется от BasicObject, что позволяет создавать альтернативные иерархии объектов. Методы класса Object доступны всем классам, если они явно не переопределены.
Object включает в себя модуль Kernel, делая встроенные функции ядра глобально доступными. Хотя методы экземпляров класса Object определяются модулем Kernel, мы решили документировать их здесь для ясности.
При обращении к константам в классах, наследующих от Object, вам не нужно использовать полное имя пространства имён. Например, обращение к File внутри YourClass найдёт верхнеуровневый класс File.
В описаниях методов класса Object параметр символ относится к символу, который может быть строкой в кавычках или объектом Symbol (например, :name).
Константы
- ARGF
-
ARGF — это поток, предназначенный для использования в скриптах, обрабатывающих файлы, переданные в качестве аргументов командной строки или через STDIN.
См. ARGF (класс) для получения дополнительной информации.
- ARGV
-
ARGV содержит аргументы командной строки, используемые для запуска Ruby.
Для обработки аргументов командной строки можно использовать библиотеку, например, OptionParser.
- DATA
-
DATA — это объект File, содержащий секцию данных исполняемого файла. Для создания секции данных используйте
__END__:$ cat t.rb puts DATA.gets __END__ hello world! $ ruby t.rb hello world!
- ENV
-
ENV — это объект, похожий на Hash, для доступа к переменным среды.
См. ENV (класс) для получения дополнительной информации.
- FALSE
-
Псевдоним для
false - NIL
-
Псевдоним для
nil - OptParse
-
OptionParser
Введение
OptionParser — это класс для анализа опций командной строки. Он намного более продвинутый, но и проще в использовании, чем GetoptLong, и является более ориентированным на Ruby решением.
Функции
-
Описание аргументов и код для их обработки записываются в одном месте.
-
Он может выводить сводку опций; вам не нужно отдельно поддерживать эту строку.
-
Необязательные и обязательные аргументы задаются очень удобно.
-
Аргументы могут быть автоматически преобразованы в указанный класс.
-
Аргументы могут быть ограничены определённым набором.
Все эти функции показаны в примерах ниже. Смотрите make_switch для полной документации.
Минимальный пример
require 'optparse' options = {} OptionParser.new do |opts| opts.banner = "Usage: example.rb [options]" opts.on("-v", "--[no-]verbose", "Run verbosely") do |v| options[:verbose] = v end end.parse! p options p ARGVГенерация справки
OptionParser может использоваться для автоматической генерации справки для ваших команд:
require 'optparse' Options = Struct.new(:name) class Parser def self.parse(options) args = Options.new("world") opt_parser = OptionParser.new do |opts| opts.banner = "Usage: example.rb [options]" opts.on("-nNAME", "--name=NAME", "Name to say hello to") do |n| args.name = n end opts.on("-h", "--help", "Prints this help") do puts opts 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Обязательные аргументы
Для опций, требующих аргумент, в строках описания опции может быть указано имя опции в верхнем регистре. Если опция используется без обязательного аргумента, будет возбуждено исключение.
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!Использование:
bash-3.2$ ruby optparse-test.rb -r optparse-test.rb:9:in `<main>': missing argument: -r (OptionParser::MissingArgument) bash-3.2$ ruby optparse-test.rb -r my-library You required my-library!
Преобразование типов
OptionParser поддерживает возможность преобразования аргументов командной строки в объекты для нас.
OptionParser поставляется с несколькими готовыми типами преобразования типов. Это:
-
Date – Всё, что принимается
Date.parse -
DateTime – Всё, что принимается
DateTime.parse -
Time – Всё, что принимается
Time.httpdateилиTime.parse -
URI – Всё, что принимается
URI.parse -
Shellwords – Всё, что принимается
Shellwords.shellwords -
Строка – Любая непустая строка
-
Целое число – Любое целое число. Будет преобразовано в восьмеричное. (например, 124, -3, 040)
-
Число с плавающей точкой – Любое число с плавающей точкой. (например, 10, 3.14, -100E+13)
-
Числовое значение – Любое целое число, число с плавающей точкой или рациональное число (1, 3.4, 1/3)
-
DecimalInteger – Как
Integer, но без восьмеричного формата. -
OctalInteger – Как
Integer, но без десятичного формата. -
DecimalNumeric – Десятичное целое число или число с плавающей точкой.
-
TrueClass – Принимает '+', 'yes', 'true', '-', 'no', 'false' и по умолчанию является
true -
FalseClass – То же, что и
TrueClass, но по умолчанию являетсяfalse -
Массив – Строки, разделённые запятыми (например, 1,2,3)
-
Regexp – Регулярные выражения. Также включает опции.
Мы также можем добавить наши собственные преобразования, о которых мы поговорим позже.
Использование встроенных преобразований
В качестве примера используется встроенное преобразование
Time. Другие встроенные преобразования работают аналогичным образом. OptionParser попытается разобрать аргумент какTime. Если это удастся, этот момент времени будет передан в обработчик блока. В противном случае будет возбуждено исключение.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!Использование:
bash-3.2$ ruby optparse-test.rb -t nonsense ... invalid argument: -t nonsense (OptionParser::InvalidArgument) from ... time.rb:5:in `block in <top (required)>' from optparse-test.rb:31:in `<main>' bash-3.2$ ruby optparse-test.rb -t 10-11-12 2010-11-12 00:00:00 -0500 bash-3.2$ ruby optparse-test.rb -t 9:30 2014-08-13 09:30:00 -0400
Создание пользовательских преобразований
Метод
acceptкласса OptionParser может использоваться для создания преобразователей. Он определяет, какой блок преобразования вызывать, когда указывается класс. В примере ниже используется этот метод для получения объектаUserперед тем, как обработчикonполучит его.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!Вывод:
bash-3.2$ ruby optparse-test.rb --user 1 #<struct User id=1, name="Sam"> bash-3.2$ ruby optparse-test.rb --user 2 #<struct User id=2, name="Gandalf"> bash-3.2$ ruby optparse-test.rb --user 3 optparse-test.rb:15:in `block in find_user': No User Found for id 3 (RuntimeError)
Полный пример
Следующий пример — полная программа Ruby. Вы можете запустить её и увидеть эффект задания различных опций. Это, вероятно, лучший способ узнать особенности
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 ARGVShell Автозаполнение
Для современных оболочек (например, bash, zsh и т. д.) вы можете использовать автозаполнение опций командной строки.
Дополнительная документация
Приведённых выше примеров должно быть достаточно, чтобы понять, как использовать этот класс. Если у вас есть вопросы, создайте тикет на bugs.ruby-lang.org.
-
- ParseError
- RUBY_COPYRIGHT
-
Строка авторских прав для Ruby
- RUBY_DESCRIPTION
-
Полная строка версии Ruby, как
ruby -vпечатает' - RUBY_ENGINE
-
Движок или интерпретатор, используемый этим Ruby.
- RUBY_ENGINE_VERSION
-
Версия движка или интерпретатора, используемого этим Ruby.
- RUBY_PATCHLEVEL
-
Версия исправления для данного Ruby. Если это тестовая сборка Ruby, номер исправления будет -1
- RUBY_PLATFORM
-
Платформа для данного Ruby
- RUBY_RELEASE_DATE
-
Дата выпуска этого Ruby
- RUBY_REVISION
-
Ревизия SVN для этого Ruby.
- RUBY_VERSION
-
Используемая версия Ruby
- SCRIPT_LINES__
-
Когда переменной
SCRIPT_LINES__присваивается объект Hash, содержимое загруженных после этого файлов будет добавлено как массив строк с именем файла в качестве ключа. - STDERR
-
Содержит исходный STDERR
- STDIN
-
Содержит исходный STDIN
- STDOUT
-
Содержит исходный STDOUT
- Synchronizer
-
Класс, предоставляющий двухфазную блокировку с счётчиком. Подробности см. в Sync_m.
- Synchronizer_m
-
Модуль, предоставляющий двухфазную блокировку с счётчиком.
- TOPLEVEL_BINDING
-
Объект Binding для верхнего уровня области видимости
- TRUE
-
Псевдоним для
true - ThWait
-
Этот класс отслеживает завершение нескольких потоков. Базовые функции (ожидание завершения указанных потоков) доступны через метод класса ThreadsWait.all_waits. Более точный контроль можно получить с помощью методов экземпляров.
Пример:
ThreadsWait.all_waits(thr1, thr2, ...) do |t| STDERR.puts "Thread #{t} has terminated." end th = ThreadsWait.new(thread1,...) th.next_wait # next one to be done - TimeoutError
-
Возбуждается методом Timeout#timeout, когда блок выходит за пределы времени.
Публичные методы класса
# File ext/psych/lib/psych/core_ext.rb, line 3 def self.yaml_tag url Psych.add_tag(url, self) end
Публичные методы экземпляра
static VALUE
rb_obj_not_match(VALUE obj1, VALUE obj2)
{
VALUE result = rb_funcall(obj1, id_match, 1, obj2);
return RTEST(result) ? Qfalse : Qtrue;
} Возвращает true, если два объекта не совпадают (используя метод =~), иначе false.
static VALUE
rb_obj_cmp(VALUE obj1, VALUE obj2)
{
if (obj1 == obj2 || rb_equal(obj1, obj2))
return INT2FIX(0);
return Qnil;
} Возвращает 0, если obj и other являются одним и тем же объектом или obj == other, иначе nil.
<=> используется различными методами для сравнения объектов, например Enumerable#sort, Enumerable#max и т.д.
Ваша реализация <=> должна возвращать одно из следующих значений: -1, 0, 1 или nil. -1 означает, что self меньше, чем other. 0 означает, что self равен other. 1 означает, что self больше, чем other. Nil означает, что два значения не могут быть сравнены.
При определении <=>, вы можете включить Comparable, чтобы получить методы <=, <, ==, >=, > и between?.
VALUE
rb_equal(VALUE obj1, VALUE obj2)
{
VALUE result;
if (obj1 == obj2) return Qtrue;
result = rb_funcall(obj1, id_eq, 1, obj2);
if (RTEST(result)) return Qtrue;
return Qfalse;
} Равенство по регистру – Для класса Object, фактически то же самое, что вызов #==, но обычно переопределяется потомками для обеспечения осмысленной семантики в case операторах.
static VALUE
rb_obj_match(VALUE obj1, VALUE obj2)
{
return Qnil;
} Сопоставление шаблонов—Переопределяется потомками (в частности, Regexp и String) для обеспечения осмысленной семантики сопоставления шаблонов.
# File lib/csv.rb, line 2327 def CSV(*args, &block) CSV.instance(*args, &block) end
Передает args в CSV.instance.
CSV("CSV,data").read
#=> [["CSV", "data"]]
Если задан блок, экземпляру передается блок, и возвращаемое значение становится возвращаемым значением блока.
CSV("CSV,data") { |c|
c.read.any? { |a| a.include?("data") }
} #=> true
CSV("CSV,data") { |c|
c.read.any? { |a| a.include?("zombies") }
} #=> false
# File lib/delegate.rb, line 378
def DelegateClass(superclass)
klass = Class.new(Delegator)
methods = superclass.instance_methods
methods -= ::Delegator.public_api
methods -= [:to_s,:inspect,:=~,:!~,:===]
klass.module_eval do
def __getobj__ # :nodoc:
unless defined?(@delegate_dc_obj)
return yield if block_given?
__raise__ ::ArgumentError, "not delegated"
end
@delegate_dc_obj
end
def __setobj__(obj) # :nodoc:
__raise__ ::ArgumentError, "cannot delegate to self" if self.equal?(obj)
@delegate_dc_obj = obj
end
methods.each do |method|
define_method(method, Delegator.delegating_block(method))
end
end
klass.define_singleton_method :public_instance_methods do |all=true|
super(all) - superclass.protected_instance_methods
end
klass.define_singleton_method :protected_instance_methods do |all=true|
super(all) | superclass.protected_instance_methods
end
return klass
end Основной интерфейс этой библиотеки. Используйте для настройки делегирования при определении вашего класса.
class MyClass < DelegateClass(ClassToDelegateTo) # Step 1
def initialize
super(obj_of_ClassToDelegateTo) # Step 2
end
end
Вот пример использования из Tempfile, который на самом деле является объектом File с несколькими специальными правилами относительно местоположения хранения и того, когда файл File должен быть удален. Это делает его почти идеальным примером того, как использовать делегирование.
class Tempfile < DelegateClass(File)
# constant and class member data initialization...
def initialize(basename, tmpdir=Dir::tmpdir)
# build up file path/name in var tmpname...
@tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600)
# ...
super(@tmpfile)
# below this point, all methods of File are supported...
end
# ...
end
# File ext/digest/lib/digest.rb, line 96
def Digest(name)
const = name.to_sym
Digest::REQUIRE_MUTEX.synchronize {
# Ignore autoload's because it is void when we have #const_missing
Digest.const_missing(const)
}
rescue LoadError
# Constants do not necessarily rely on digest/*.
if Digest.const_defined?(const)
Digest.const_get(const)
else
raise
end
end Возвращает подкласс Digest по name потокобезопасным способом, даже когда используется загрузка по запросу.
require 'digest'
Digest("MD5")
# => Digest::MD5
Digest(:SHA256)
# => Digest::SHA256
Digest(:Foo)
# => LoadError: library not found for class Digest::Foo -- digest/foo
VALUE
rb_obj_class(VALUE obj)
{
return rb_class_real(CLASS_OF(obj));
} Возвращает класс obj. Этот метод всегда должен вызываться с явным получателем, так как class также является зарезервированным словом в Ruby.
1.class #=> Fixnum self.class #=> Object
VALUE
rb_obj_clone(VALUE obj)
{
VALUE clone;
VALUE singleton;
if (rb_special_const_p(obj)) {
rb_raise(rb_eTypeError, "can't clone %s", rb_obj_classname(obj));
}
clone = rb_obj_alloc(rb_obj_class(obj));
RBASIC(clone)->flags &= (FL_TAINT|FL_PROMOTED0|FL_PROMOTED1);
RBASIC(clone)->flags |= RBASIC(obj)->flags & ~(FL_PROMOTED0|FL_PROMOTED1|FL_FREEZE|FL_FINALIZE);
singleton = rb_singleton_class_clone_and_attach(obj, clone);
RBASIC_SET_CLASS(clone, singleton);
if (FL_TEST(singleton, FL_SINGLETON)) {
rb_singleton_class_attached(singleton, clone);
}
init_copy(clone, obj);
rb_funcall(clone, id_init_clone, 1, obj);
RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
return clone;
} Создает неглубокую копию obj—переменные экземпляра obj копируются, но не объекты, на которые они ссылаются. clone копирует замороженное и испорченное состояние obj. См. также обсуждение в разделе Object#dup.
class Klass attr_accessor :str end s1 = Klass.new #=> #<Klass:0x401b3a38> s1.str = "Hello" #=> "Hello" s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello"> s2.str[1,4] = "i" #=> "i" s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">" s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">"
Этот метод может иметь специфичное для класса поведение. Если это так, то это поведение будет задокументировано в методе #initialize_copy класса.
# File lib/rexml/xpath_parser.rb, line 11 def dclone clone end
предоставляет унифицированную операцию clone, для REXML::XPathParser для использования в нескольких типах объектов Object
# File lib/irb/src_encoding.rb, line 3 def default_src_encoding return __ENCODING__ end
frozen_string_literal: false НЕ ПИШИТЕ НИКАКИХ МАГИЧЕСКИХ КОММЕНТАРИЕВ ЗДЕСЬ.
static VALUE
rb_obj_define_method(int argc, VALUE *argv, VALUE obj)
{
VALUE klass = rb_singleton_class(obj);
return rb_mod_define_method(argc, argv, klass);
} Определяет одиночный метод в получателе. Параметр method может быть Proc, Method или объектом UnboundMethod. Если указан блок, он используется в качестве тела метода.
class A
class << self
def class_name
to_s
end
end
end
A.define_singleton_method(:who_am_i) do
"I am: #{class_name}"
end
A.who_am_i # ==> "I am: A"
guy = "Bob"
guy.define_singleton_method(:hello) { "#{self}: Hello there!" }
guy.hello #=> "Bob: Hello there!"
static VALUE
rb_obj_display(int argc, VALUE *argv, VALUE self)
{
VALUE out;
if (argc == 0) {
out = rb_stdout;
}
else {
rb_scan_args(argc, argv, "01", &out);
}
rb_io_write(out, self);
return Qnil;
} Выводит obj в указанный порт (по умолчанию $>). Эквивалентно:
def display(port=$>) port.write self end
Например:
1.display "cat".display [ 4, 5, 6 ].display puts
выводит:
1cat456
VALUE
rb_obj_dup(VALUE obj)
{
VALUE dup;
if (rb_special_const_p(obj)) {
rb_raise(rb_eTypeError, "can't dup %s", rb_obj_classname(obj));
}
dup = rb_obj_alloc(rb_obj_class(obj));
init_copy(dup, obj);
rb_funcall(dup, id_init_dup, 1, obj);
return dup;
} Создает неглубокую копию obj—переменные экземпляра obj копируются, но не объекты, на которые они ссылаются. dup копирует испорченное состояние obj.
Этот метод может иметь специфичное для класса поведение. Если это так, то это поведение будет задокументировано в методе #initialize_copy класса.
on dup vs clone
В общем случае, clone и dup могут иметь различную семантику в дочерних классах. В то время как clone используется для дублирования объекта, включая его внутреннее состояние, dup обычно использует класс дочернего объекта для создания нового экземпляра.
При использовании dup, любые модули, с которыми был расширен объект, не будут скопированы.
class Klass attr_accessor :str end module Foo def foo; 'foo'; end end s1 = Klass.new #=> #<Klass:0x401b3a38> s1.extend(Foo) #=> #<Klass:0x401b3a38> s1.foo #=> "foo" s2 = s1.clone #=> #<Klass:0x401b3a38> s2.foo #=> "foo" s3 = s1.dup #=> #<Klass:0x401b3a38> s3.foo #=> NoMethodError: undefined method `foo' for #<Klass:0x401b3a38>
static VALUE
obj_to_enum(int argc, VALUE *argv, VALUE obj)
{
VALUE enumerator, meth = sym_each;
if (argc > 0) {
--argc;
meth = *argv++;
}
enumerator = rb_enumeratorize_with_size(obj, meth, argc, argv, 0);
if (rb_block_given_p()) {
enumerator_ptr(enumerator)->size = rb_block_proc();
}
return enumerator;
} Создает новый Enumerator, который будет перечислять, вызывая method на obj, передавая args, если таковые имеются.
Если задан блок, он будет использоваться для вычисления размера перечислителя без необходимости его итерации (см. Enumerator#size).
Примеры
str = "xyz"
enum = str.enum_for(:each_byte)
enum.each { |b| puts b }
# => 120
# => 121
# => 122
# protect an array from being modified by some_method
a = [1, 2, 3]
some_method(a.to_enum)
Обычно вызывается #to_enum при определении методов для общего Enumerable, если блок не передан.
Вот такой пример с передачей параметров и блоком определения размера:
module Enumerable
# a generic method to repeat the values of any enumerable
def repeat(n)
raise ArgumentError, "#{n} is negative!" if n < 0
unless block_given?
return to_enum(__method__, n) do # __method__ is :repeat here
sz = size # Call size and multiply by n...
sz * n if sz # but return nil if size itself is nil
end
end
each do |*val|
n.times { yield *val }
end
end
end
%[hello world].repeat(2) { |w| puts w }
# => Prints 'hello', 'hello', 'world', 'world'
enum = (1..14).repeat(3)
# => returns an Enumerator when called without a block
enum.first(4) # => [1, 1, 1, 2]
enum.size # => 42
VALUE
rb_obj_equal(VALUE obj1, VALUE obj2)
{
if (obj1 == obj2) return Qtrue;
return Qfalse;
} Равенство — На уровне Object, == возвращает true только если obj и other являются одним и тем же объектом. Как правило, этот метод переопределяется в дочерних классах для предоставления значения, специфичного для класса.
В отличие от ==, метод equal? никогда не должен переопределяться подклассами, поскольку он используется для определения идентичности объекта (то есть, a.equal?(b) если и только если a является тем же объектом, что и b):
obj = "a" other = obj.dup obj == other #=> true obj.equal? other #=> false obj.equal? obj #=> true
Метод eql? возвращает true, если obj и other ссылаются на один и тот же ключ хеша. Это используется классом Hash для проверки членов на равенство. Для объектов класса Object, eql? является синонимом ==. Подклассы обычно продолжают эту традицию, создавая псевдоним eql? для своего переопределенного метода ==, но есть исключения. Типы Numeric, например, выполняют преобразование типов через ==, но не через eql?, поэтому:
1 == 1.0 #=> true 1.eql? 1.0 #=> false
static VALUE
rb_obj_extend(int argc, VALUE *argv, VALUE obj)
{
int i;
ID id_extend_object, id_extended;
CONST_ID(id_extend_object, "extend_object");
CONST_ID(id_extended, "extended");
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
for (i = 0; i < argc; i++)
Check_Type(argv[i], T_MODULE);
while (argc--) {
rb_funcall(argv[argc], id_extend_object, 1, obj);
rb_funcall(argv[argc], id_extended, 1, obj);
}
return obj;
} Добавляет к obj методы экземпляра из каждого модуля, заданного в качестве параметра.
module Mod
def hello
"Hello from Mod.\n"
end
end
class Klass
def hello
"Hello from Klass.\n"
end
end
k = Klass.new
k.hello #=> "Hello from Klass.\n"
k.extend(Mod) #=> #<Klass:0x401b3bc8>
k.hello #=> "Hello from Mod.\n"
VALUE
rb_obj_freeze(VALUE obj)
{
if (!OBJ_FROZEN(obj)) {
OBJ_FREEZE(obj);
if (SPECIAL_CONST_P(obj)) {
rb_bug("special consts should be frozen.");
}
}
return obj;
} Предотвращает дальнейшие изменения obj. Будет возбуждено исключение RuntimeError, если будет предпринята попытка изменения. Разморозить замороженный объект невозможно. См. также Object#frozen?.
Этот метод возвращает self.
a = [ "a", "b", "c" ] a.freeze a << "z"
Результат:
prog.rb:3:in `<<': can't modify frozen Array (RuntimeError) from prog.rb:3
Объекты следующих классов всегда заморожены: Fixnum, Bignum, Float, Symbol.
VALUE
rb_obj_frozen_p(VALUE obj)
{
return OBJ_FROZEN(obj) ? Qtrue : Qfalse;
} Возвращает статус замораживания obj.
a = [ "a", "b", "c" ] a.freeze #=> ["a", "b", "c"] a.frozen? #=> true
VALUE
rb_obj_hash(VALUE obj)
{
VALUE oid = rb_obj_id(obj);
#if SIZEOF_LONG == SIZEOF_VOIDP
st_index_t index = NUM2LONG(oid);
#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
st_index_t index = NUM2LL(oid);
#else
# error not supported
#endif
return LONG2FIX(rb_objid_hash(index));
} Генерирует хеш-значение Fixnum для этого объекта. Эта функция должна обладать свойством, что a.eql?(b) подразумевает a.hash == b.hash.
Хеш-значение используется вместе с eql? классом Hash для определения того, ссылаются ли два объекта на один и тот же ключ хеша. Любое хеш-значение, превышающее емкость Fixnum, будет усечено перед использованием.
Хеш-значение объекта может не быть идентичным в разных вызовах или реализациях Ruby. Если вам нужен стабильный идентификатор в разных вызовах и реализациях Ruby, вам нужно будет сгенерировать его с помощью пользовательского метода.
static VALUE
rb_obj_inspect(VALUE obj)
{
if (rb_ivar_count(obj) > 0) {
VALUE str;
VALUE c = rb_class_name(CLASS_OF(obj));
str = rb_sprintf("-<%"PRIsVALUE":%p", c, (void*)obj);
return rb_exec_recursive(inspect_obj, obj, str);
}
else {
return rb_any_to_s(obj);
}
} Возвращает строку, содержащую читаемое человеком представление obj. Значение по умолчанию inspect показывает имя класса объекта, кодировку идентификатора объекта и список переменных экземпляра и их значений (вызывая inspect для каждой из них). Пользовательские классы должны переопределять этот метод, чтобы обеспечить лучшее представление obj. При переопределении этого метода он должен возвращать строку, кодировка которой совместима с кодировкой по умолчанию.
[ 1, 2, 3..4, 'five' ].inspect #=> "[1, 2, 3..4, \"five\"]"
Time.new.inspect #=> "2008-03-08 19:43:39 +0900"
class Foo
end
Foo.new.inspect #=> "#<Foo:0x0300c868>"
class Bar
def initialize
@bar = 1
end
end
Bar.new.inspect #=> "#<Bar:0x0300c868 @bar=1>"
VALUE
rb_obj_is_instance_of(VALUE obj, VALUE c)
{
c = class_or_module_required(c);
if (rb_obj_class(obj) == c) return Qtrue;
return Qfalse;
} Возвращает true, если obj является экземпляром данного класса. См. также Object#kind_of?.
class A; end class B < A; end class C < B; end b = B.new b.instance_of? A #=> false b.instance_of? B #=> true b.instance_of? C #=> false
static VALUE
rb_obj_ivar_defined(VALUE obj, VALUE iv)
{
ID id = id_for_var(obj, iv, an, instance);
if (!id) {
return Qfalse;
}
return rb_ivar_defined(obj, id);
} Возвращает true, если данная переменная экземпляра определена в obj. Строковые аргументы преобразуются в символы.
class Fred
def initialize(p1, p2)
@a, @b = p1, p2
end
end
fred = Fred.new('cat', 99)
fred.instance_variable_defined?(:@a) #=> true
fred.instance_variable_defined?("@b") #=> true
fred.instance_variable_defined?("@c") #=> false
static VALUE
rb_obj_ivar_get(VALUE obj, VALUE iv)
{
ID id = id_for_var(obj, iv, an, instance);
if (!id) {
return Qnil;
}
return rb_ivar_get(obj, id);
} Возвращает значение данной переменной экземпляра или nil, если переменная экземпляра не установлена. Часть @ имени переменной должна быть включена для обычных переменных экземпляра. Выбрасывает исключение NameError, если предоставленный символ не является допустимым именем переменной экземпляра. Строковые аргументы преобразуются в символы.
class Fred
def initialize(p1, p2)
@a, @b = p1, p2
end
end
fred = Fred.new('cat', 99)
fred.instance_variable_get(:@a) #=> "cat"
fred.instance_variable_get("@b") #=> 99
static VALUE
rb_obj_ivar_set(VALUE obj, VALUE iv, VALUE val)
{
ID id = id_for_var(obj, iv, an, instance);
if (!id) id = rb_intern_str(iv);
return rb_ivar_set(obj, id, val);
} Устанавливает переменную экземпляра с именем symbol для данного объекта, тем самым расстраивая усилия автора класса по попытке обеспечить надлежащую инкапсуляцию. Переменная не обязательно должна существовать до этого вызова. Если имя переменной экземпляра передается как строка, эта строка преобразуется в символ.
class Fred
def initialize(p1, p2)
@a, @b = p1, p2
end
end
fred = Fred.new('cat', 99)
fred.instance_variable_set(:@a, 'dog') #=> "dog"
fred.instance_variable_set(:@c, 'cat') #=> "cat"
fred.inspect #=> "#<Fred:0x401b3da8 @a=\"dog\", @b=99, @c=\"cat\">"
VALUE
rb_obj_instance_variables(VALUE obj)
{
VALUE ary;
ary = rb_ary_new();
rb_ivar_foreach(obj, ivar_i, ary);
return ary;
} Возвращает массив имен переменных экземпляра для получателя. Обратите внимание, что простое определение доступа не создает соответствующую переменную экземпляра.
class Fred
attr_accessor :a1
def initialize
@iv = 3
end
end
Fred.new.instance_variables #=> [:@iv]
VALUE
rb_obj_is_kind_of(VALUE obj, VALUE c)
{
VALUE cl = CLASS_OF(obj);
c = class_or_module_required(c);
return class_search_ancestor(cl, RCLASS_ORIGIN(c)) ? Qtrue : Qfalse;
} Возвращает true, если class является классом obj, или если class является одним из суперклассов obj или модулей, включенных в obj.
module M; end class A include M end class B < A; end class C < B; end b = B.new b.is_a? A #=> true b.is_a? B #=> true b.is_a? C #=> false b.is_a? M #=> true b.kind_of? A #=> true b.kind_of? B #=> true b.kind_of? C #=> false b.kind_of? M #=> true
static VALUE
rb_obj_itself(VALUE obj)
{
return obj;
} Возвращает obj.
string = 'my string' #=> "my string" string.itself.object_id == string.object_id #=> true
VALUE
rb_obj_is_kind_of(VALUE obj, VALUE c)
{
VALUE cl = CLASS_OF(obj);
c = class_or_module_required(c);
return class_search_ancestor(cl, RCLASS_ORIGIN(c)) ? Qtrue : Qfalse;
} Возвращает true, если class является классом obj, или если class является одним из суперклассов obj или модулей, включенных в obj.
module M; end class A include M end class B < A; end class C < B; end b = B.new b.is_a? A #=> true b.is_a? B #=> true b.is_a? C #=> false b.is_a? M #=> true b.kind_of? A #=> true b.kind_of? B #=> true b.kind_of? C #=> false b.kind_of? M #=> true
VALUE
rb_obj_method(VALUE obj, VALUE vid)
{
return obj_method(obj, vid, FALSE);
} Ищет именованный метод как получатель в obj, возвращая объект Method (или вызывая NameError). Объект Method действует как замыкание в экземпляре объекта obj, поэтому переменные экземпляра и значение self остаются доступными.
class Demo
def initialize(n)
@iv = n
end
def hello()
"Hello, @iv = #{@iv}"
end
end
k = Demo.new(99)
m = k.method(:hello)
m.call #=> "Hello, @iv = 99"
l = Demo.new('Fred')
m = l.method("hello")
m.call #=> "Hello, @iv = Fred"
VALUE
rb_obj_methods(int argc, const VALUE *argv, VALUE obj)
{
rb_check_arity(argc, 0, 1);
if (argc > 0 && !RTEST(argv[0])) {
return rb_obj_singleton_methods(argc, argv, obj);
}
return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_i);
} Возвращает список имен открытых и защищенных методов obj. Это будет включать все методы, доступные в предках obj. Если необязательный параметр равен false, он возвращает массив открытых и защищенных методов-одиночек obj, массив не будет включать методы в модулях, включенных в obj.
class Klass
def klass_method()
end
end
k = Klass.new
k.methods[0..9] #=> [:klass_method, :nil?, :===,
# :==~, :!, :eql?
# :hash, :<=>, :class, :singleton_class]
k.methods.length #=> 56
k.methods(false) #=> []
def k.singleton_method; end
k.methods(false) #=> [:singleton_method]
module M123; def m123; end end
k.extend M123
k.methods(false) #=> [:singleton_method]
static VALUE
rb_false(VALUE obj)
{
return Qfalse;
} Только объект nil отвечает true к nil?.
Object.new.nil? #=> false nil.nil? #=> true
VALUE
rb_obj_id(VALUE obj)
{
/*
* 32-bit VALUE space
* MSB ------------------------ LSB
* false 00000000000000000000000000000000
* true 00000000000000000000000000000010
* nil 00000000000000000000000000000100
* undef 00000000000000000000000000000110
* symbol ssssssssssssssssssssssss00001110
* object oooooooooooooooooooooooooooooo00 = 0 (mod sizeof(RVALUE))
* fixnum fffffffffffffffffffffffffffffff1
*
* object_id space
* LSB
* false 00000000000000000000000000000000
* true 00000000000000000000000000000010
* nil 00000000000000000000000000000100
* undef 00000000000000000000000000000110
* symbol 000SSSSSSSSSSSSSSSSSSSSSSSSSSS0 S...S % A = 4 (S...S = s...s * A + 4)
* object oooooooooooooooooooooooooooooo0 o...o % A = 0
* fixnum fffffffffffffffffffffffffffffff1 bignum if required
*
* where A = sizeof(RVALUE)/4
*
* sizeof(RVALUE) is
* 20 if 32-bit, double is 4-byte aligned
* 24 if 32-bit, double is 8-byte aligned
* 40 if 64-bit
*/
if (STATIC_SYM_P(obj)) {
return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG;
}
else if (FLONUM_P(obj)) {
#if SIZEOF_LONG == SIZEOF_VOIDP
return LONG2NUM((SIGNED_VALUE)obj);
#else
return LL2NUM((SIGNED_VALUE)obj);
#endif
}
else if (SPECIAL_CONST_P(obj)) {
return LONG2NUM((SIGNED_VALUE)obj);
}
return nonspecial_obj_id(obj);
} Возвращает целочисленный идентификатор для obj.
То же самое число будет возвращено при всех вызовах object_id для данного объекта, и никакие два активных объекта не будут разделять идентификатор.
Примечание: некоторые объекты встроенных классов повторно используются для оптимизации. Это относится к непосредственным значениям и замороженным строковым литералам.
Непосредственные значения не передаются по ссылке, а передаются по значению: nil, true, false, Fixnums, символы и некоторые числа с плавающей запятой.
Object.new.object_id == Object.new.object_id # => false (21 * 2).object_id == (21 * 2).object_id # => true "hello".object_id == "hello".object_id # => false "hi".freeze.object_id == "hi".freeze.object_id # => true
VALUE
rb_obj_private_methods(int argc, const VALUE *argv, VALUE obj)
{
return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_priv_i);
} Возвращает список закрытых методов, доступных для obj. Если параметр all установлен в false, будут перечислены только те методы, которые находятся в получателе.
VALUE
rb_obj_protected_methods(int argc, const VALUE *argv, VALUE obj)
{
return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_prot_i);
} Возвращает список защищенных методов, доступных для obj. Если параметр all установлен в false, будут перечислены только те методы, которые находятся в получателе.
# File ext/psych/lib/psych/core_ext.rb, line 14
def psych_to_yaml options = {}
Psych.dump self, options
end Преобразовать объект в YAML. См. Psych.dump для получения дополнительной информации о доступных options.
VALUE
rb_obj_public_method(VALUE obj, VALUE vid)
{
return obj_method(obj, vid, TRUE);
} Аналогично method, ищет только общедоступный метод.
VALUE
rb_obj_public_methods(int argc, const VALUE *argv, VALUE obj)
{
return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_pub_i);
} Возвращает список общедоступных методов, доступных для obj. Если параметр all установлен в false, будут перечислены только те методы, которые находятся в получателе.
VALUE
rb_f_public_send(int argc, VALUE *argv, VALUE recv)
{
return send_internal(argc, argv, recv, CALL_PUBLIC);
} Вызывает метод, идентифицированный символом символ, передавая ему любые указанные аргументы. В отличие от send, #public_send вызывает только общедоступные методы. Когда метод идентифицируется строкой, строка преобразуется в символ.
1.public_send(:puts, "hello") # causes NoMethodError
VALUE
rb_obj_remove_instance_variable(VALUE obj, VALUE name)
{
VALUE val = Qnil;
const ID id = id_for_var(obj, name, an, instance);
st_data_t n, v;
struct st_table *iv_index_tbl;
st_data_t index;
rb_check_frozen(obj);
if (!id) {
goto not_defined;
}
switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
if (!iv_index_tbl) break;
if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break;
if (ROBJECT_NUMIV(obj) <= (long)index) break;
val = ROBJECT_IVPTR(obj)[index];
if (val != Qundef) {
ROBJECT_IVPTR(obj)[index] = Qundef;
return val;
}
break;
case T_CLASS:
case T_MODULE:
n = id;
if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), &n, &v)) {
return (VALUE)v;
}
break;
default:
if (FL_TEST(obj, FL_EXIVAR)) {
if (generic_ivar_remove(obj, id, &val)) {
return val;
}
}
break;
}
not_defined:
rb_name_err_raise("instance variable %1$s not defined",
obj, name);
UNREACHABLE;
} Удаляет именованную переменную экземпляра из obj, возвращая значение этой переменной.
class Dummy
attr_reader :var
def initialize
@var = 99
end
def remove
remove_instance_variable(:@var)
end
end
d = Dummy.new
d.var #=> 99
d.remove #=> 99
d.var #=> nil
static VALUE
obj_respond_to(int argc, VALUE *argv, VALUE obj)
{
VALUE mid, priv;
ID id;
rb_thread_t *th = GET_THREAD();
rb_scan_args(argc, argv, "11", &mid, &priv);
if (!(id = rb_check_id(&mid))) {
VALUE ret = basic_obj_respond_to_missing(th, CLASS_OF(obj), obj,
rb_to_symbol(mid), priv);
if (ret == Qundef) ret = Qfalse;
return ret;
}
if (basic_obj_respond_to(th, obj, id, !RTEST(priv)))
return Qtrue;
return Qfalse;
} Возвращает true, если obj отвечает на заданный метод. Закрытые и защищенные методы включаются в поиск только в том случае, если необязательный второй параметр принимает значение true.
Если метод не реализован, как Process.fork в Windows, File.lchmod в GNU/Linux и т. д., возвращается false.
Если метод не определен, вызывается метод respond_to_missing? и возвращается результат.
Если имя метода задано в виде строки, строка преобразуется в символ.
static VALUE
obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv)
{
return Qfalse;
} НЕ ИСПОЛЬЗУЙТЕ ЭТО ПРЯМО.
Метод-обработчик для возвращения того, может ли obj ответить на метод id или нет.
См. respond_to? и пример BasicObject.
VALUE
rb_f_send(int argc, VALUE *argv, VALUE recv)
{
return send_internal(argc, argv, recv, CALL_FCALL);
} Вызывает метод, идентифицированный символом символ, передавая ему любые указанные аргументы. Вы можете использовать __send__ , если имя send конфликтует с существующим методом в obj. Когда метод идентифицируется строкой, строка преобразуется в символ.
class Klass
def hello(*args)
"Hello " + args.join(' ')
end
end
k = Klass.new
k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
static VALUE
rb_obj_singleton_class(VALUE obj)
{
return rb_singleton_class(obj);
} Возвращает одиночный класс obj. Этот метод создает новый одиночный класс, если у obj его нет.
Если obj это nil, true, или false, он возвращает NilClass, TrueClass или FalseClass соответственно. Если obj является Fixnum или Symbol, он вызывает TypeError.
Object.new.singleton_class #=> #<Class:#<Object:0xb7ce1e24>> String.singleton_class #=> #<Class:String> nil.singleton_class #=> NilClass
VALUE
rb_obj_singleton_method(VALUE obj, VALUE vid)
{
const rb_method_entry_t *me;
VALUE klass;
ID id = rb_check_id(&vid);
if (!id) {
if (!NIL_P(klass = rb_singleton_class_get(obj)) &&
respond_to_missing_p(klass, obj, vid, FALSE)) {
id = rb_intern_str(vid);
return mnew_missing(klass, obj, id, id, rb_cMethod);
}
undef:
rb_name_err_raise("undefined singleton method `%1$s' for `%2$s'",
obj, vid);
}
if (NIL_P(klass = rb_singleton_class_get(obj)) ||
UNDEFINED_METHOD_ENTRY_P(me = rb_method_entry_at(klass, id)) ||
UNDEFINED_REFINED_METHOD_P(me->def)) {
vid = ID2SYM(id);
goto undef;
}
return mnew_from_me(me, klass, obj, id, rb_cMethod, FALSE);
} Аналогично method, ищет только одиночный метод.
class Demo
def initialize(n)
@iv = n
end
def hello()
"Hello, @iv = #{@iv}"
end
end
k = Demo.new(99)
def k.hi
"Hi, @iv = #{@iv}"
end
m = k.singleton_method(:hi)
m.call #=> "Hi, @iv = 99"
m = k.singleton_method(:hello) #=> NameError
VALUE
rb_obj_singleton_methods(int argc, const VALUE *argv, VALUE obj)
{
VALUE recur, ary, klass, origin;
struct method_entry_arg me_arg;
struct rb_id_table *mtbl;
if (argc == 0) {
recur = Qtrue;
}
else {
rb_scan_args(argc, argv, "01", &recur);
}
klass = CLASS_OF(obj);
origin = RCLASS_ORIGIN(klass);
me_arg.list = st_init_numtable();
me_arg.recur = RTEST(recur);
if (klass && FL_TEST(klass, FL_SINGLETON)) {
if ((mtbl = RCLASS_M_TBL(origin)) != 0) rb_id_table_foreach(mtbl, method_entry_i, &me_arg);
klass = RCLASS_SUPER(klass);
}
if (RTEST(recur)) {
while (klass && (FL_TEST(klass, FL_SINGLETON) || RB_TYPE_P(klass, T_ICLASS))) {
if (klass != origin && (mtbl = RCLASS_M_TBL(klass)) != 0) rb_id_table_foreach(mtbl, method_entry_i, &me_arg);
klass = RCLASS_SUPER(klass);
}
}
ary = rb_ary_new();
st_foreach(me_arg.list, ins_methods_i, ary);
st_free_table(me_arg.list);
return ary;
} Возвращает массив имён одиночных методов для obj. Если необязательный параметр all имеет значение true, список будет включать методы в модулях, включённых в obj. Возвращаются только общедоступные и защищенные одиночные методы.
module Other def three() end end class Single def Single.four() end end a = Single.new def a.one() end class << a include Other def two() end end Single.singleton_methods #=> [:four] a.singleton_methods(false) #=> [:two, :one] a.singleton_methods #=> [:two, :one, :three]
# File lib/webrick/httpservlet/cgi_runner.rb, line 12
def sysread(io, size)
buf = ""
while size > 0
tmp = io.sysread(size)
buf << tmp
size -= tmp.bytesize
end
return buf
end frozen_string_literal: false
cgi_runner.rb – запуск CGI.
Автор: IPR – Программирование на Ruby в Интернете – авторы Авторские права © 2000 TAKAHASHI Masayoshi, GOTOU YUUZOU Авторские права © 2002 авторы Программирования на Ruby в Интернете. Все права защищены.
$IPR: cgi_runner.rb,v 1.9 2002/09/25 11:33:15 gotoyuzo Exp $
VALUE
rb_obj_taint(VALUE obj)
{
if (!OBJ_TAINTED(obj) && OBJ_TAINTABLE(obj)) {
rb_check_frozen(obj);
OBJ_TAINT(obj);
}
return obj;
} Пометить объект как изменённый.
Объекты, помеченные как изменённые, будут ограничены в использовании различных встроенных методов. Это делается для предотвращения нежелательного компрометации системы пользователя данными, ненадёжными данными, такими как аргументы командной строки или строки, считанные из Kernel#gets.
Чтобы проверить, является ли объект изменённым, используйте tainted?.
Вы должны разметку объекта как неизменённого, только если ваш код проинспектировал его и определил, что он безопасен. Для этого используйте untaint.
VALUE
rb_obj_tainted(VALUE obj)
{
if (OBJ_TAINTED(obj))
return Qtrue;
return Qfalse;
} Возвращает true, если объект помечен как изменённый.
См. taint для получения дополнительной информации.
VALUE
rb_obj_tap(VALUE obj)
{
rb_yield(obj);
return obj;
} Передаёт self в блок, а затем возвращает self. Основное назначение этого метода — «присоединиться» к цепочке методов, чтобы выполнить операции над промежуточными результатами в этой цепочке.
(1..10) .tap {|x| puts "original: #{x.inspect}"}
.to_a .tap {|x| puts "array: #{x.inspect}"}
.select {|x| x%2==0} .tap {|x| puts "evens: #{x.inspect}"}
.map {|x| x*x} .tap {|x| puts "squares: #{x.inspect}"}
# File lib/timeout.rb, line 118
def timeout(*args, &block)
warn "#{caller_locations(1, 1)[0]}: Object##{__method__} is deprecated, use Timeout.timeout instead."
Timeout.timeout(*args, &block)
end static VALUE
obj_to_enum(int argc, VALUE *argv, VALUE obj)
{
VALUE enumerator, meth = sym_each;
if (argc > 0) {
--argc;
meth = *argv++;
}
enumerator = rb_enumeratorize_with_size(obj, meth, argc, argv, 0);
if (rb_block_given_p()) {
enumerator_ptr(enumerator)->size = rb_block_proc();
}
return enumerator;
} Создаёт новый Enumerator, который будет перебирать, вызывая method для obj, передавая args (если таковые имеются).
Если задан блок, он будет использоваться для расчёта размера перечислителя без необходимости его перебора (см. Enumerator#size).
Примеры
str = "xyz"
enum = str.enum_for(:each_byte)
enum.each { |b| puts b }
# => 120
# => 121
# => 122
# protect an array from being modified by some_method
a = [1, 2, 3]
some_method(a.to_enum)
Обычно #to_enum вызывается при определении методов для универсального Enumerable, в случае отсутствия блока.
Вот такой пример с передачей параметров и блоком определения размера:
module Enumerable
# a generic method to repeat the values of any enumerable
def repeat(n)
raise ArgumentError, "#{n} is negative!" if n < 0
unless block_given?
return to_enum(__method__, n) do # __method__ is :repeat here
sz = size # Call size and multiply by n...
sz * n if sz # but return nil if size itself is nil
end
end
each do |*val|
n.times { yield *val }
end
end
end
%[hello world].repeat(2) { |w| puts w }
# => Prints 'hello', 'hello', 'world', 'world'
enum = (1..14).repeat(3)
# => returns an Enumerator when called without a block
enum.first(4) # => [1, 1, 1, 2]
enum.size # => 42
VALUE
rb_any_to_s(VALUE obj)
{
VALUE str;
VALUE cname = rb_class_name(CLASS_OF(obj));
str = rb_sprintf("#<%"PRIsVALUE":%p>", cname, (void*)obj);
OBJ_INFECT(str, obj);
return str;
} Возвращает строку, представляющую obj. По умолчанию to_s выводит класс объекта и кодировку идентификатора объекта. В качестве специального случая, верхнеуровневый объект, являющийся начальной средой выполнения программ Ruby, возвращает «main».
VALUE
rb_obj_trust(VALUE obj)
{
rb_warning("trust is deprecated and its behavior is same as untaint");
return rb_obj_untaint(obj);
} Устаревший метод, эквивалентный untaint.
# File lib/mathn.rb, line 41
warn('lib/mathn.rb is deprecated') if $VERBOSE
mathn
mathn служит для повышения точности математических операций в Ruby и интеграции других стандартных математических библиотек.
Без mathn:
3 / 2 => 1 # Integer
С mathn:
3 / 2 => 3/2 # Rational
mathn сохраняет значения в точном виде.
Без mathn:
20 / 9 * 3 * 14 / 7 * 3 / 2 # => 18
С mathn:
20 / 9 * 3 * 14 / 7 * 3 / 2 # => 20
При использовании 'mathn' также загружаются библиотеки для Prime, CMath, Matrix и Vector.
Авторские права
Автор: Keiju ISHITSUKA (SHL Japan Inc.)
VALUE
rb_obj_untaint(VALUE obj)
{
if (OBJ_TAINTED(obj)) {
rb_check_frozen(obj);
FL_UNSET(obj, FL_TAINT);
}
return obj;
} Удаляет отметку «изменённый» с объекта.
См. taint для получения дополнительной информации.
VALUE
rb_obj_untrust(VALUE obj)
{
rb_warning("untrust is deprecated and its behavior is same as taint");
return rb_obj_taint(obj);
} Устаревший метод, эквивалентный taint.
VALUE
rb_obj_untrusted(VALUE obj)
{
rb_warning("untrusted? is deprecated and its behavior is same as tainted?");
return rb_obj_tainted(obj);
} Устаревший метод, эквивалентный tainted?.
# File lib/irb/xmp.rb, line 165 def xmp(exps, bind = nil) bind = IRB::Frame.top(1) unless bind xmp = XMP.new(bind) xmp.puts exps xmp end
Удобный метод, доступный только при подключении стандартной библиотеки IRB::XMP.
Создаёт новый объект XMP, используя заданные выражения в качестве параметра exps, и необязательный binding как bind, или использует глобальный binding. Затем оценивает заданные выражения с помощью режима приглашения :XMP.
Например:
require 'irb/xmp' ctx = binding xmp 'foo = "bar"', ctx #=> foo = "bar" #==>"bar" ctx.eval 'foo' #=> "bar"
См. XMP.new для получения дополнительной информации.
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.