модуль Kernel
RubyGems добавляет метод gem, чтобы разрешить активацию определённых версий gem и переопределяет метод require в Kernel, чтобы сделать gems, как будто они находятся в $LOAD_PATH. Смотрите документацию этих методов для более подробной информации.
Модификация ядра для обеспечения того, что все вызовы `require` вызывают тот же самый метод
Модуль Kernel включён классом Object, поэтому его методы доступны в каждом объекте Ruby.
Методы экземпляра Kernel задокументированы в классе Object, в то время как методы модуля задокументированы здесь. Эти методы вызываются без получателя и, следовательно, могут быть вызваны в функциональной форме:
sprintf "%.1f", 1.234 #=> "1.2"
Что здесь
Модуль Kernel предоставляет методы, которые полезны для:
Преобразования
Запросы
-
__callee__: Возвращает имя вызываемого метода в качестве символа. -
__dir__: Возвращает путь к каталогу, из которого был вызван текущий метод. -
__method__: Возвращает имя текущего метода в качестве символа. -
autoload?: Возвращает файл, который будет загружен при ссылке на данный модуль. -
block_given?: Возвращаетtrue, если блоку был передан в вызывающий метод. -
caller: Возвращает текущую стек вызовов в виде массива строк. -
caller_locations: Возвращает текущую стек вызовов в виде массива объектовThread::Backtrace::Location. -
class: Возвращает классself. -
frozen?: Возвращает, заморожен лиself. -
global_variables: Возвращает массив глобальных переменных в виде символов. -
local_variables: Возвращает массив локальных переменных в виде символов. -
test: Выполняет указанные тесты для заданного единственного файла или пары файлов.
Выход
-
abort: Выходит из текущего процесса после вывода заданных аргументов. -
at_exit: Выполняет заданный блок при завершении процесса. -
exit: Выходит из текущего процесса после вызова всех зарегистрированныхat_exitобработчиков. -
exit!: Выходит из текущего процесса без вызова зарегистрированныхat_exitобработчиков.
Исключения
-
catch: Выполняет заданный блок, возможно перехватывая брошенный объект. -
raise(алиасfail): Возбуждает исключение на основе заданных аргументов. -
throw: Возвращается из активного блока catch, ожидая заданного тега.
IO
-
::pp: Выводит заданные объекты в красивом формате. -
gets: Возвращает и присваивает$_следующую строку из текущего входного потока. -
open: Создаёт объектIO, подключённый к заданному потоку, файлу или подпроцессу. -
p: Выводит вывод inspect заданных объектов в стандартный вывод. -
print: Выводит заданные объекты в стандартный вывод без новой строки. -
printf: Выводит строку, полученную при применении заданной строки формата к любым дополнительным аргументам. -
putc: Эквивалентно <tt.$stdout.putc(object)</tt> для заданного объекта. -
puts: Эквивалентно$stdout.puts(*objects)для заданных объектов. -
readline: Аналогичноgets, но возбуждает исключение в конце файла. -
readlines: Возвращает массив оставшихся строк из текущего входного потока.
Программы
-
lambda: Возвращает лямбда-программу для заданного блока.
Отслеживание
-
set_trace_func: Устанавливает заданную программу как обработчик отслеживания или отключает отслеживание, если заданоnil. -
trace_var: Начинает отслеживание присваиваний заданной глобальной переменной. -
untrace_var: Отключает отслеживание присваиваний заданной глобальной переменной.
Подпроцессы
-
`команда`: Возвращает стандартный вывод выполнения
commandв подоболочке. -
exec: Заменяет текущий процесс новым процессом. -
fork: Разделяет текущий процесс на два процесса. -
spawn: Выполняет заданную команду и возвращает её pid без ожидания завершения. -
system: Выполняет заданную команду в подоболочке.
Загрузка
-
autoload: Регистрирует заданный файл для загрузки, когда данный констант впервые ссылается. -
load: Загружает заданный Ruby-файл. -
require: Загружает указанный Ruby-файл, если он ещё не загружен. -
require_relative: Загружает путь к Ruby-файлу относительно вызывающего файла, если он ещё не загружен.
Возвращения
-
tap: Возвращаетselfв данный блок; возвращаетself. -
then(алиасyield_self): Возвращаетselfв блок и возвращает результат блока.
Случайные значения
-
rand: Возвращает псевдослучайное дробное число строго между 0,0 и 1,0. -
srand: Инициализирует генератор псевдослучайных чисел заданным числом.
Другое
-
eval: Вычисляет заданную строку как код Ruby. -
loop: Повторяет выполнение заданного блока. -
sleep: Приостанавливает текущую нить на заданное количество секунд. -
sprintf(алиасformat): Возвращает строку, полученную в результате применения заданной строки форматирования к дополнительным аргументам. -
syscall: Выполняет системный вызов операционной системы. -
trap: Указывает обработку системных сигналов. -
warn: Выводит предупреждение на основе заданных сообщений и параметров.
Общедоступные методы класса
# File lib/uri/common.rb, line 718
def URI(uri)
if uri.is_a?(URI::Generic)
uri
elsif uri = String.try_convert(uri)
URI.parse(uri)
else
raise ArgumentError,
"bad argument (expected URI object or URI string)"
end
end Возвращает uri, преобразованный в объект URI.
# File lib/pp.rb, line 644
def pp(*objs)
objs.each {|obj|
PP.pp(obj)
}
objs.size <= 1 ? objs.first : objs
end выводит аргументы в красивом формате.
pp возвращает аргумент(ы).
Общедоступные методы экземпляров
static VALUE
rb_f_array(VALUE obj, VALUE arg)
{
return rb_Array(arg);
} Возвращает массив, преобразованный из object.
Попытка преобразовать object в массив с использованием to_ary в первую очередь и to_a во вторую:
Array([0, 1, 2]) # => [0, 1, 2]
Array({foo: 0, bar: 1}) # => [[:foo, 0], [:bar, 1]]
Array(0..4) # => [0, 1, 2, 3, 4]
Возвращает object в массиве, [object], если object невозможно преобразовать:
Array(:foo) # => [:foo]
static VALUE
f_BigDecimal(int argc, VALUE *argv, VALUE self)
{
VALUE val, digs_v, opts = Qnil;
argc = rb_scan_args(argc, argv, "11:", &val, &digs_v, &opts);
int exception = opts_exception_p(opts);
size_t digs = SIZE_MAX; /* this means digs is omitted */
if (argc > 1) {
digs_v = rb_to_int(digs_v);
if (FIXNUM_P(digs_v)) {
long n = FIX2LONG(digs_v);
if (n < 0)
goto negative_digs;
digs = (size_t)n;
}
else {
if (RBIGNUM_NEGATIVE_P(digs_v)) {
negative_digs:
if (!exception)
return Qnil;
rb_raise(rb_eArgError, "negative precision");
}
digs = NUM2SIZET(digs_v);
}
}
return rb_convert_to_BigDecimal(val, digs, exception);
} Возвращает BigDecimal, преобразованный из value с точностью ndigits десятичных знаков.
Когда ndigits меньше, чем количество значащих цифр в значении, результат округляется до этого числа знаков в соответствии с текущим режимом округления; см. BigDecimal.mode.
Когда ndigits равно 0, количество цифр для корректного представления числа с плавающей точкой определяется автоматически.
Возвращает value, преобразованный в BigDecimal, в зависимости от типа value:
-
Integer,Float,Rational,Complexили BigDecimal: преобразуется напрямую:# Integer, Complex, or BigDecimal value does not require ndigits; ignored if given. BigDecimal(2) # => 0.2e1 BigDecimal(Complex(2, 0)) # => 0.2e1 BigDecimal(BigDecimal(2)) # => 0.2e1 # Float or Rational value requires ndigits. BigDecimal(2.0, 0) # => 0.2e1 BigDecimal(Rational(2, 1), 0) # => 0.2e1
-
Строка: преобразуется путем разбора, если она содержит целое или дробное число; начальные и конечные пробелы игнорируются:
# String does not require ndigits; ignored if given. BigDecimal('2') # => 0.2e1 BigDecimal('2.0') # => 0.2e1 BigDecimal('0.2e1') # => 0.2e1 BigDecimal(' 2.0 ') # => 0.2e1 -
Другой тип, который отвечает на метод
:to_str: сначала преобразуется в строку, затем преобразуется в BigDecimal, как указано выше. -
Другой тип:
-
Вызывает исключение, если ключевой аргумент
exceptionравенtrue. -
Возвращает
nilесли ключевой аргументexceptionравенtrue.
-
Вызывает исключение, если value оценивается как Float и digits больше, чем Float::DIG + 1.
static VALUE
nucomp_f_complex(int argc, VALUE *argv, VALUE klass)
{
VALUE a1, a2, opts = Qnil;
int raise = TRUE;
if (rb_scan_args(argc, argv, "11:", &a1, &a2, &opts) == 1) {
a2 = Qundef;
}
if (!NIL_P(opts)) {
raise = rb_opts_exception_p(opts, raise);
}
if (argc > 0 && CLASS_OF(a1) == rb_cComplex && UNDEF_P(a2)) {
return a1;
}
return nucomp_convert(rb_cComplex, a1, a2, raise);
} Возвращает x+i*y;
Complex(1, 2) #=> (1+2i)
Complex('1+2i') #=> (1+2i)
Complex(nil) #=> TypeError
Complex(1, nil) #=> TypeError
Complex(1, nil, exception: false) #=> nil
Complex('1+2', exception: false) #=> nil
Синтаксис строковой формы:
string form = extra spaces , complex , extra spaces ;
complex = real part | [ sign ] , imaginary part
| real part , sign , imaginary part
| rational , "@" , rational ;
real part = rational ;
imaginary part = imaginary unit | unsigned rational , imaginary unit ;
rational = [ sign ] , unsigned rational ;
unsigned rational = numerator | numerator , "/" , denominator ;
numerator = integer part | fractional part | integer part , fractional part ;
denominator = digits ;
integer part = digits ;
fractional part = "." , digits , [ ( "e" | "E" ) , [ sign ] , digits ] ;
imaginary unit = "i" | "I" | "j" | "J" ;
sign = "-" | "+" ;
digits = digit , { digit | "_" , digit };
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
extra spaces = ? \s* ? ; См. String#to_c.
# File kernel.rb, line 171
def Float(arg, exception: true)
if Primitive.mandatory_only?
Primitive.rb_f_float1(arg)
else
Primitive.rb_f_float(arg, exception)
end
end Возвращает arg, преобразованный в число с плавающей точкой. Типы Numeric преобразуются напрямую, а со строкой String и nil остальное преобразуется с помощью arg.to_f. Преобразование строки String с недопустимыми символами приведет к ArgumentError. Преобразование nil генерирует TypeError. Исключения можно подавить, передав exception: false.
Float(1) #=> 1.0
Float("123.456") #=> 123.456
Float("123.0_badstring") #=> ArgumentError: invalid value for Float(): "123.0_badstring"
Float(nil) #=> TypeError: can't convert nil into Float
Float("123.0_badstring", exception: false) #=> nil
static VALUE
rb_f_hash(VALUE obj, VALUE arg)
{
return rb_Hash(arg);
} Возвращает хэш, преобразованный из object.
-
Если
object:-
Хэш, возвращает
object. -
Пустой массив или
nil, возвращает пустой хэш.
-
-
В противном случае, если
object.to_hashвозвращает хэш, возвращает этот хэш. -
В противном случае, возвращает
TypeError.
Примеры:
Hash({foo: 0, bar: 1}) # => {:foo=>0, :bar=>1}
Hash(nil) # => {}
Hash([]) # => {}
static VALUE
rb_f_integer(int argc, VALUE *argv, VALUE obj)
{
VALUE arg = Qnil, opts = Qnil;
int base = 0;
if (argc > 1) {
int narg = 1;
VALUE vbase = rb_check_to_int(argv[1]);
if (!NIL_P(vbase)) {
base = NUM2INT(vbase);
narg = 2;
}
if (argc > narg) {
VALUE hash = rb_check_hash_type(argv[argc-1]);
if (!NIL_P(hash)) {
opts = rb_extract_keywords(&hash);
if (!hash) --argc;
}
}
}
rb_check_arity(argc, 1, 2);
arg = argv[0];
return rb_convert_to_integer(arg, base, opts_exception_p(opts));
} Возвращает целое число, преобразованное из object.
Попытка преобразовать object в целое число с использованием to_int в первую очередь и to_i во вторую; см. ниже сведения об исключениях.
При ненулевом base, object должно быть строкой или преобразуемым в строку.
Числовые объекты
С целочисленным аргументом object возвращается object:
Integer(1) # => 1 Integer(-1) # => -1
С плавающим аргументом object возвращается object, усеченное до целого числа:
Integer(1.9) # => 1 # Rounds toward zero. Integer(-1.9) # => -1 # Rounds toward zero.
Строковые объекты
Со строковым аргументом object и нулевым base возвращается object, преобразованное в целое число в системе счисления 10:
Integer('100') # => 100
Integer('-100') # => -100
При base ноль, строка object может содержать начальные символы для указания фактической системы счисления (индикатор основания):
Integer('0100') # => 64 # Leading '0' specifies base 8.
Integer('0b100') # => 4 # Leading '0b', specifies base 2.
Integer('0x100') # => 256 # Leading '0x' specifies base 16.
При положительном base (в диапазоне от 2 до 36) возвращается object, преобразованное в целое число в заданной системе счисления:
Integer('100', 2) # => 4
Integer('100', 8) # => 64
Integer('-100', 16) # => -256
С отрицательным base (в диапазоне от -36 до -2) возвращается object преобразованное в целое число в индикаторе основания, если он есть, или -base:
Integer('0x100', -2) # => 256
Integer('100', -2) # => 4
Integer('0b100', -8) # => 4
Integer('100', -8) # => 64
Integer('0o100', -10) # => 64
Integer('100', -10) # => 100
base -1 равно -10 случаю.
При преобразовании строк допускаются и игнорируются окружающие пробелы и вложенные подчеркивания:
Integer(' 100 ') # => 100
Integer('-1_0_0', 16) # => -256
Другие классы
Примеры с object различных других классов:
Integer(Rational(9, 10)) # => 0 # Rounds toward zero. Integer(Complex(2, 0)) # => 2 # Imaginary part must be zero. Integer(Time.now) # => 1650974042
Ключевые слова
При заданном необязательном ключевом аргументе exception как true (по умолчанию):
-
Вызывает
TypeError, еслиobjectне отвечает наto_intилиto_i. -
Вызывает
TypeError, еслиobjectравноnil. -
Вызывает
ArgumentError, еслиobject- недопустимая строка.
При заданном exception как false, любое исключение подавляется, и возвращается nil.
static VALUE
path_f_pathname(VALUE self, VALUE str)
{
if (CLASS_OF(str) == rb_cPathname)
return str;
return rb_class_new_instance(1, &str, rb_cPathname);
} Создает новый объект Pathname из заданной строки, path, и возвращает объект пути.
Для использования этого конструктора необходимо сначала подключить расширение стандартной библиотеки Pathname.
require 'pathname'
Pathname("/home/zzak")
#=> #<Pathname:/home/zzak>
См. также Pathname::new для получения дополнительной информации.
static VALUE
nurat_f_rational(int argc, VALUE *argv, VALUE klass)
{
VALUE a1, a2, opts = Qnil;
int raise = TRUE;
if (rb_scan_args(argc, argv, "11:", &a1, &a2, &opts) == 1) {
a2 = Qundef;
}
if (!NIL_P(opts)) {
raise = rb_opts_exception_p(opts, raise);
}
return nurat_convert(rb_cRational, a1, a2, raise);
} Возвращает x/y или arg в виде Rational.
Rational(2, 3) #=> (2/3)
Rational(5) #=> (5/1)
Rational(0.5) #=> (1/2)
Rational(0.3) #=> (5404319552844595/18014398509481984)
Rational("2/3") #=> (2/3)
Rational("0.3") #=> (3/10)
Rational("10 cents") #=> ArgumentError
Rational(nil) #=> TypeError
Rational(1, nil) #=> TypeError
Rational("10 cents", exception: false) #=> nil
Синтаксис строковой формы:
string form = extra spaces , rational , extra spaces ;
rational = [ sign ] , unsigned rational ;
unsigned rational = numerator | numerator , "/" , denominator ;
numerator = integer part | fractional part | integer part , fractional part ;
denominator = digits ;
integer part = digits ;
fractional part = "." , digits , [ ( "e" | "E" ) , [ sign ] , digits ] ;
sign = "-" | "+" ;
digits = digit , { digit | "_" , digit } ;
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
extra spaces = ? \s* ? ; См. также String#to_r.
static VALUE
rb_f_string(VALUE obj, VALUE arg)
{
return rb_String(arg);
} Возвращает строку, преобразованную из object.
Попытка преобразовать object в строку с использованием to_str в первую очередь и to_s во вторую:
String([0, 1, 2]) # => "[0, 1, 2]"
String(0..5) # => "0..5"
String({foo: 0, bar: 1}) # => "{:foo=>0, :bar=>1}"
Вызывает TypeError если object невозможно преобразовать в строку.
static VALUE
rb_f_callee_name(VALUE _)
{
ID fname = prev_frame_callee(); /* need *callee* ID */
if (fname) {
return ID2SYM(fname);
}
else {
return Qnil;
}
} Возвращает имя вызываемого метода в виде Symbol. Если вызов произошел вне метода, возвращает nil.
static VALUE
f_current_dirname(VALUE _)
{
VALUE base = rb_current_realfilepath();
if (NIL_P(base)) {
return Qnil;
}
base = rb_file_dirname(base);
return base;
} Возвращает канонизированный абсолютный путь к каталогу файла, из которого вызывается этот метод. Это означает, что символические ссылки в пути разрешены. Если __FILE__ равен nil, он возвращает nil. Возвращаемое значение равно File.dirname(File.realpath(__FILE__)).
static VALUE
rb_f_method_name(VALUE _)
{
ID fname = prev_frame_func(); /* need *method* ID */
if (fname) {
return ID2SYM(fname);
}
else {
return Qnil;
}
} Возвращает имя в определении текущего метода как Symbol. Если вызывается за пределами метода, возвращает nil.
static VALUE
rb_f_backquote(VALUE obj, VALUE str)
{
VALUE port;
VALUE result;
rb_io_t *fptr;
SafeStringValue(str);
rb_last_status_clear();
port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
if (NIL_P(port)) return rb_str_new(0,0);
GetOpenFile(port, fptr);
result = read_all(fptr, remain_size(fptr), Qnil);
rb_io_close(port);
RFILE(port)->fptr = NULL;
rb_io_fptr_finalize(fptr);
RB_GC_GUARD(port);
return result;
} Возвращает $stdout вывод от запуска command во вспомогательном процессе; устанавливает глобальную переменную $? в состояние процесса.
Этот метод имеет потенциальные уязвимости безопасности, если вызывается с недоверенными входными данными; см. Command Injection.
Примеры:
$ `date` # => "Wed Apr 9 08:56:30 CDT 2003\n" $ `echo oops && exit 99` # => "oops\n" $ $? # => #<Process::Status: pid 17088 exit 99> $ $?.status # => 99>
Встроенный синтаксис %x{...} использует этот метод.
static VALUE
f_abort(int c, const VALUE *a, VALUE _)
{
rb_f_abort(c, a);
UNREACHABLE_RETURN(Qnil);
} Немедленно завершает выполнение, фактически вызывая Kernel.exit(false). Если задано msg, оно записывается в STDERR перед завершением.
static VALUE
rb_f_at_exit(VALUE _)
{
VALUE proc;
if (!rb_block_given_p()) {
rb_raise(rb_eArgError, "called without a block");
}
proc = rb_block_proc();
rb_set_end_proc(rb_call_end_proc, proc);
return proc;
} Преобразует block в объект Proc (и, следовательно, связывает его в точке вызова) и регистрирует его для выполнения при выходе программы. Если зарегистрировано несколько обработчиков, они выполняются в обратном порядке регистрации.
def do_at_exit(str1)
at_exit { print str1 }
end
at_exit { puts "cruel world" }
do_at_exit("goodbye ")
exit
производит:
goodbye cruel world
static VALUE
rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
{
VALUE klass = rb_class_real(rb_vm_cbase());
if (!klass) {
rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
}
return rb_mod_autoload(klass, sym, file);
} Registers _filename_ to be loaded (using Kernel::require) the first time that _const_ (which may be a String or a symbol) is accessed. autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
Если const определен как autoload, имя файла для загрузки заменяется на filename. Если const определен, но не как autoload, ничего не делает.
static VALUE
rb_f_autoload_p(int argc, VALUE *argv, VALUE obj)
{
/* use rb_vm_cbase() as same as rb_f_autoload. */
VALUE klass = rb_vm_cbase();
if (NIL_P(klass)) {
return Qnil;
}
return rb_mod_autoload_p(argc, argv, klass);
} Возвращает filename для загрузки, если name зарегистрирован как autoload.
autoload(:B, "b") autoload?(:B) #=> "b"
static VALUE
rb_f_binding(VALUE self)
{
return rb_binding_new();
} Возвращает объект Binding, описывающий привязки переменных и методов в точке вызова. Этот объект может использоваться при вызове eval для выполнения вычисленной команды в этой среде. См. также описание класса Binding.
def get_binding(param)
binding
end
b = get_binding("hello")
eval("param", b) #=> "hello"
static VALUE
rb_f_block_given_p(VALUE _)
{
rb_execution_context_t *ec = GET_EC();
rb_control_frame_t *cfp = ec->cfp;
cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
return RBOOL(cfp != NULL && VM_CF_BLOCK_HANDLER(cfp) != VM_BLOCK_HANDLER_NONE);
} Возвращает true, если yield будет выполнять блок в текущем контексте. Форма iterator? слегка устарела.
def try
if block_given?
yield
else
"no block"
end
end
try #=> "no block"
try { "hello" } #=> "hello"
try do "hello" end #=> "hello"
static VALUE
rb_callcc(VALUE self)
{
volatile int called;
volatile VALUE val = cont_capture(&called);
if (called) {
return val;
}
else {
return rb_yield(val);
}
} Генерирует объект Continuation, который он передает связанному блоку. Вам нужно require 'continuation' перед использованием этого метода. Выполнение cont.call приведет к возврату callcc (как и пропуск конца блока). Значение, возвращаемое callcc, — это значение блока или значение, переданное cont.call. См. класс Continuation для получения более подробной информации. См. также Kernel#throw для альтернативного механизма разворачивания стека вызовов.
static VALUE
rb_f_caller(int argc, VALUE *argv, VALUE _)
{
return ec_backtrace_to_ary(GET_EC(), argc, argv, 1, 1, 1);
} Возвращает текущий стек выполнения — массив, содержащий строки в форме file:line или file:line: in `method'.
Необязательный параметр start определяет количество начальных записей стека, которые нужно опустить с вершины стека.
Второй необязательный параметр length может использоваться для ограничения количества записей, возвращаемых из стека.
Возвращает nil, если start больше размера текущего стека выполнения.
Необязательно можно передать диапазон, который вернет массив, содержащий записи в указанном диапазоне.
def a(skip) caller(skip) end def b(skip) a(skip) end def c(skip) b(skip) end c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10:in `<main>'"] c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11:in `<main>'"] c(2) #=> ["prog:8:in `c'", "prog:12:in `<main>'"] c(3) #=> ["prog:13:in `<main>'"] c(4) #=> [] c(5) #=> nil
static VALUE
rb_f_caller_locations(int argc, VALUE *argv, VALUE _)
{
return ec_backtrace_to_ary(GET_EC(), argc, argv, 1, 1, 0);
} Возвращает текущий стек выполнения — массив, содержащий объекты местоположения трассировки стека.
См. Thread::Backtrace::Location для получения дополнительной информации.
Необязательный параметр start определяет количество начальных записей стека, которые нужно опустить с вершины стека.
Второй необязательный параметр length может использоваться для ограничения количества записей, возвращаемых из стека.
Возвращает nil, если start больше размера текущего стека выполнения.
Необязательно можно передать диапазон, который вернет массив, содержащий записи в указанном диапазоне.
static VALUE
rb_f_catch(int argc, VALUE *argv, VALUE self)
{
VALUE tag = rb_check_arity(argc, 0, 1) ? argv[0] : rb_obj_alloc(rb_cObject);
return rb_catch_obj(tag, catch_i, 0);
} catch выполняет свой блок. Если throw не вызывается, блок выполняется нормально, и catch возвращает значение последнего вычисленного выражения.
catch(1) { 123 } # => 123
Если вызывается throw(tag2, val), Ruby ищет в своем стеке блок catch, метка которого tag совпадает с object_id tag2. Когда он найден, выполнение блока прекращается, и возвращается val (или nil, если второй аргумент не был передан throw).
catch(1) { throw(1, 456) } # => 456
catch(1) { throw(1) } # => nil
Когда в качестве первого аргумента передается tag, catch передает его в качестве параметра блока.
catch(1) {|x| x + 2 } # => 3
Когда метка tag не задана, catch передает новый уникальный объект (как из Object.new) в качестве параметра блока. Этот объект затем может использоваться в качестве аргумента для throw, и будет соответствовать правильному блоку catch.
catch do |obj_A|
catch do |obj_B|
throw(obj_B, 123)
puts "This puts is not reached"
end
puts "This puts is displayed"
456
end
# => 456
catch do |obj_A|
catch do |obj_B|
throw(obj_A, 123)
puts "This puts is still not reached"
end
puts "Now this puts is also not reached"
456
end
# => 123
static VALUE
rb_f_chomp(int argc, VALUE *argv, VALUE _)
{
VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("chomp"), argc, argv);
rb_lastline_set(str);
return str;
} Эквивалентно $_ = $_.chomp(string). См. String#chomp. Доступно только при указании параметра командной строки -p/-n.
static VALUE
rb_f_chop(VALUE _)
{
VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("chop"), 0, 0);
rb_lastline_set(str);
return str;
} Эквивалентно ($_.dup).chop!, за исключением того, что nil никогда не возвращается. См. String#chop!. Доступно только при указании командной строки опций -p/-n.
# File kernel.rb, line 18 def class Primitive.attr! 'inline' Primitive.cexpr! 'rb_obj_class(self)' end
Возвращает класс obj. Этот метод всегда должен вызываться с явным получателем, так как class также является зарезервированным словом в Ruby.
1.class #=> Integer self.class #=> Object
# File kernel.rb, line 47 def clone(freeze: nil) Primitive.rb_obj_clone2(freeze) end
Создаёт неглубокую копию obj — переменные экземпляра obj копируются, но не объекты, на которые они ссылаются. clone копирует состояние замороженного значения obj, если ключевой аргумент :freeze не задан или имеет значение false или true. См. также обсуждение в 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 класса.
VALUE
rb_f_eval(int argc, const VALUE *argv, VALUE self)
{
VALUE src, scope, vfile, vline;
VALUE file = Qundef;
int line = 1;
rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
SafeStringValue(src);
if (argc >= 3) {
StringValue(vfile);
}
if (argc >= 4) {
line = NUM2INT(vline);
}
if (!NIL_P(vfile))
file = vfile;
if (NIL_P(scope))
return eval_string_with_cref(self, src, NULL, file, line);
else
return eval_string_with_scope(scope, src, file, line);
} Вычисляет выражение(я) Ruby в string. Если указано binding, которое должно быть объектом Binding, вычисление выполняется в его контексте. Если присутствуют необязательные параметры filename и lineno, они будут использоваться при сообщении об ошибках синтаксиса.
def get_binding(str)
return binding
end
str = "hello"
eval "str + ' Fred'" #=> "hello Fred"
eval "str + ' Fred'", get_binding("bye") #=> "bye Fred"
static VALUE
f_exec(int c, const VALUE *a, VALUE _)
{
rb_f_exec(c, a);
UNREACHABLE_RETURN(Qnil);
} Заменяет текущий процесс, выполняя указанную внешнюю команду command, которая может иметь один из следующих видов:
-
exec(commandline) -
строка командной строки, которая передаётся стандартной оболочке
-
exec(cmdname, arg1, ...) -
имя команды и один или несколько аргументов (без оболочки)
-
exec([cmdname, argv0], arg1, ...) -
имя команды,
argv[0]и ноль или более аргументов (без оболочки)
В первом виде строка воспринимается как командная строка, которая подвергается расширению оболочки перед выполнением.
Стандартная оболочка всегда означает "/bin/sh" на системах Unix-подобных, в противном случае, ENV["RUBYSHELL"] или ENV["COMSPEC"] на Windows и подобных. Команда передается в качестве аргумента переключателю "-c" оболочки, за исключением случая COMSPEC.
Если строка первого вида (exec("command")) следует этим простым правилам:
-
нет метасимволов,
-
не начинается с зарезервированного слова оболочки или специального встроенного,
Ruby вызывает команду непосредственно без оболочки.
Вы можете принудительно вызвать оболочку, добавив «;» в строку (потому что «;» — это метасимвол).
Обратите внимание, что это поведение наблюдается с помощью полученного pid (возвращаемое значение spawn() и IO#pid для IO.popen) является pid вызванной команды, а не оболочки.
Во втором виде (exec("command1", "arg1", ...)) первый элемент воспринимается как имя команды, а остальные передаются как параметры команде без расширения оболочки.
В третьем виде (exec(["command", "argv0"], "arg1", ...)) — начиная массив из двух элементов в начале команды, первый элемент — это команда для выполнения, а второй аргумент используется в качестве значения argv[0], которое может отобразиться в списках процессов.
Для выполнения команды используются одна из exec(2) системных вызовов, поэтому выполняемая команда может унаследовать часть среды исходной программы (включая открытые дескрипторы файлов).
Это поведение изменяется заданными env и options параметрами. См. ::spawn для деталей.
Если выполнение команды не удаётся (обычно Errno::ENOENT, когда её не найдено), возбуждается исключение SystemCallError.
Этот метод изменяет атрибуты процесса в соответствии с заданными options перед exec(2) системным вызовом. См. ::spawn для более подробной информации о заданных options.
Изменённые атрибуты могут сохраняться, когда exec(2) системный вызов завершается неудачей.
Например, жёсткие ограничения ресурсов не восстанавливаются.
Рассмотрите возможность создания дочернего процесса с помощью ::spawn или Kernel#system, если это неприемлемо.
exec "echo *" # echoes list of files in current directory # never get here exec "echo", "*" # echoes an asterisk # never get here
static VALUE
f_exit(int c, const VALUE *a, VALUE _)
{
rb_f_exit(c, a);
UNREACHABLE_RETURN(Qnil);
} Инициирует завершение скрипта Ruby, возбудив исключение SystemExit. Это исключение может быть перехвачено. Необязательный параметр используется для возвращения кода состояния вызывающей среде. true и FALSE значения status означают успех и неудачу соответственно. Интерпретация других целочисленных значений зависит от системы.
begin exit puts "never get here" rescue SystemExit puts "rescued a SystemExit exception" end puts "after begin block"
выводит:
rescued a SystemExit exception after begin block
Непосредственно перед завершением Ruby выполняет любые at_exit функции (см. Kernel::at_exit) и выполняет любые финализаторы объектов (см. ObjectSpace::define_finalizer).
at_exit { puts "at_exit function" }
ObjectSpace.define_finalizer("string", proc { puts "in finalizer" })
exit
выводит:
at_exit function in finalizer
static VALUE
rb_f_exit_bang(int argc, VALUE *argv, VALUE obj)
{
int istatus;
if (rb_check_arity(argc, 0, 1) == 1) {
istatus = exit_status_code(argv[0]);
}
else {
istatus = EXIT_FAILURE;
}
_exit(istatus);
UNREACHABLE_RETURN(Qnil);
} Немедленно завершает процесс. Обработчики выхода не запускаются. status возвращается в базовую систему в качестве кода завершения.
Process.exit!(true)
Без аргументов возбуждает исключение в $! или возбуждает RuntimeError, если $! равно nil. С одним строковым аргументом возбуждает RuntimeError с данной строкой в качестве сообщения. В противном случае первый параметр должен быть классом исключения (или другим объектом, возвращающим объект исключения при отправке сообщения exception). Необязательный второй параметр устанавливает сообщение, связанное с исключением (доступно через Exception#message), а третий параметр — массив информации обратного вызова (доступен через Exception#backtrace). Причина сгенерированного исключения (доступна через Exception#cause) автоматически устанавливается на «текущее» исключение ($!), если таковое имеется. Альтернативное значение, либо объект Exception, либо nil, может быть указано через аргумент :cause.
Исключения перехватываются оператором rescue в блоках begin...end.
raise "Failed to create socket" raise ArgumentError, "No parameters", caller
static VALUE
rb_f_fork(VALUE obj)
{
rb_pid_t pid;
pid = rb_call_proc__fork();
if (pid == 0) {
if (rb_block_given_p()) {
int status;
rb_protect(rb_yield, Qundef, &status);
ruby_stop(status);
}
return Qnil;
}
return PIDT2NUM(pid);
} Создаёт дочерний процесс. Если указан блок, этот блок выполняется в дочернем процессе, и дочерний процесс завершается со статусом ноль. В противном случае вызов fork возвращается дважды: один раз в родительском процессе, возвращая идентификатор процесса дочернего процесса, и один раз в дочернем процессе, возвращая nil. Дочерний процесс может завершиться с помощью Kernel.exit! для избежания запуска любых at_exit функций. Родительский процесс должен использовать Process.wait для сбора статусов завершения своих дочерних процессов или использовать Process.detach для регистрации отсутствия интереса к их статусу; в противном случае операционная система может накапливать процессы-зомби.
Поток, вызывающий fork, является единственным потоком в созданном дочернем процессе. fork не копирует другие потоки.
Если fork недоступен, Process.respond_to?(:fork) возвращает false.
Обратите внимание, что fork(2) недоступен на некоторых платформах, таких как Windows и NetBSD 4. Поэтому вместо fork() следует использовать spawn().
Возвращает строку, полученную в результате форматирования objects в format_string.
Подробности по format_string, см. в Спецификации форматирования.
Kernel#format является псевдонимом для Kernel#sprintf.
# File kernel.rb, line 67 def frozen? Primitive.attr! 'inline' Primitive.cexpr! 'rb_obj_frozen_p(self)' end
Возвращает статус замораживания объекта obj.
a = [ "a", "b", "c" ] a.freeze #=> ["a", "b", "c"] a.frozen? #=> true
static VALUE
rb_f_gets(int argc, VALUE *argv, VALUE recv)
{
if (recv == argf) {
return argf_gets(argc, argv, argf);
}
return forward(argf, idGets, argc, argv);
} Возвращает (и присваивает $_) следующую строку из списка файлов в ARGV (или $*), или со стандартного ввода, если файлы не указаны в командной строке. Возвращает nil в конце файла. Необязательный аргумент указывает разделитель записей. Разделитель включается в содержимое каждой записи. Разделитель nil считывает всё содержимое, а разделитель нулевой длины считывает ввод по абзацам, где абзацы разделяются двумя последовательными переводами строк. Если первый аргумент — целое число или задан необязательный второй аргумент, возвращаемая строка не будет длиннее указанного значения в байтах. Если в ARGV присутствуют несколько имён файлов, gets(nil) будет считывать содержимое по одному файлу за раз.
ARGV << "testfile" print while gets
выводит:
This is line one This is line two This is line three And so on...
Стиль программирования, использующий $_ в качестве неявного параметра, постепенно теряет свою популярность в сообществе Ruby.
static VALUE
f_global_variables(VALUE _)
{
return rb_f_global_variables();
} Возвращает массив имён глобальных переменных. Это включает специальные глобальные переменные regexp, такие как $~ и $+, но не включает пронумерованные глобальные переменные regexp ($1, $2, и т. д.).
global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr]
static VALUE
rb_f_gsub(int argc, VALUE *argv, VALUE _)
{
VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("gsub"), argc, argv);
rb_lastline_set(str);
return str;
} Эквивалентно $_.gsub..., за исключением того, что $_ будет обновлён, если замена произойдёт. Доступно только при использовании опций командной строки -p/-n.
static VALUE
rb_f_iterator_p(VALUE self)
{
rb_warn_deprecated("iterator?", "block_given?");
return rb_f_block_given_p(self);
} Устарело. Используйте block_given? вместо этого.
# File lib/syntax_suggest/core_ext.rb, line 78 def load(file, wrap = false) syntax_suggest_original_load(file) rescue SyntaxError => e require "syntax_suggest/api" unless defined?(SyntaxSuggest::DEFAULT_VALUE) SyntaxSuggest.handle_error(e) end
Загружает и выполняет программу Ruby из файла filename.
Если имя файла — абсолютный путь (например, начинается с ‘/’), файл будет загружен непосредственно с помощью абсолютного пути.
Если имя файла — явный относительный путь (например, начинается с ‘./’ или ‘../’), файл будет загружен с помощью относительного пути от текущей директории.
В противном случае файл будет искаться в каталогах библиотек, указанных в $LOAD_PATH ($:). Если файл найден в каталоге, будет предпринята попытка загрузить файл относительно этого каталога. Если файл не найден ни в одном из каталогов в $LOAD_PATH, файл будет загружен с помощью относительного пути от текущей директории.
Если файла не существует при попытке его загрузки, будет возбуждено исключение LoadError.
Если необязательный параметр wrap равен true, загруженный скрипт будет выполнен внутри анонимного модуля, защищая глобальное пространство имён вызывающей программы. Если необязательный параметр wrap — модуль, загруженный скрипт будет выполнен внутри данного модуля. В любом случае локальные переменные загруженного файла не будут переданы в среду загрузки.
static VALUE
rb_f_local_variables(VALUE _)
{
struct local_var_list vars;
rb_execution_context_t *ec = GET_EC();
rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp));
unsigned int i;
local_var_list_init(&vars);
while (cfp) {
if (cfp->iseq) {
for (i = 0; i < ISEQ_BODY(cfp->iseq)->local_table_size; i++) {
local_var_list_add(&vars, ISEQ_BODY(cfp->iseq)->local_table[i]);
}
}
if (!VM_ENV_LOCAL_P(cfp->ep)) {
/* block */
const VALUE *ep = VM_CF_PREV_EP(cfp);
if (vm_collect_local_variables_in_heap(ep, &vars)) {
break;
}
else {
while (cfp->ep != ep) {
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
}
}
}
else {
break;
}
}
return local_var_list_finish(&vars);
} Возвращает имена текущих локальных переменных.
fred = 1 for i in 1..10 # ... end local_variables #=> [:fred, :i]
static VALUE
rb_f_loop(VALUE self)
{
RETURN_SIZED_ENUMERATOR(self, 0, 0, rb_f_loop_size);
return rb_rescue2(loop_i, (VALUE)0, loop_stop, (VALUE)0, rb_eStopIteration, (VALUE)0);
} Повторяет выполнение блока.
Если блок не задан, возвращается итератор.
loop do print "Input: " line = gets break if !line or line =~ /^q/i # ... end
Исключение StopIteration, поднятое в блоке, прерывает цикл. В этом случае loop возвращает значение «результат», хранящееся в исключении.
enum = Enumerator.new { |y|
y << "one"
y << "two"
:ok
}
result = loop {
puts enum.next
} #=> :ok
static VALUE
rb_f_open(int argc, VALUE *argv, VALUE _)
{
ID to_open = 0;
int redirect = FALSE;
if (argc >= 1) {
CONST_ID(to_open, "to_open");
if (rb_respond_to(argv[0], to_open)) {
redirect = TRUE;
}
else {
VALUE tmp = argv[0];
FilePathValue(tmp);
if (NIL_P(tmp)) {
redirect = TRUE;
}
else {
VALUE cmd = check_pipe_command(tmp);
if (!NIL_P(cmd)) {
argv[0] = cmd;
return rb_io_s_popen(argc, argv, rb_cIO);
}
}
}
}
if (redirect) {
VALUE io = rb_funcallv_kw(argv[0], to_open, argc-1, argv+1, RB_PASS_CALLED_KEYWORDS);
if (rb_block_given_p()) {
return rb_ensure(rb_yield, io, io_close, io);
}
return io;
}
return rb_io_s_open(argc, argv, rb_cFile);
} Создаёт объект IO, подключённый к указанному потоку, файлу или подпроцессу.
Требуемый строковый аргумент path определяет, что произойдёт:
-
Открывается файл по указанному
path. -
Процесс разделяется.
-
Создаётся подпроцесс.
Каждый из этих случаев описан ниже.
Открытие файла
Если path не начинается с символа трубы ('|'), открывается поток файла с File.open(path, mode, perm, **opts).
Без блока возвращается поток файла:
open('t.txt') # => #<File:t.txt>
С блоком выполняется блок с открытым потоком файла, а затем закрывается поток:
open('t.txt') {|f| p f } # => #<File:t.txt (closed)>
Вывод:
#<File:t.txt>
См. File.open для получения подробной информации.
Разделение процесса
Если path — это двухсимвольная строка '|-', процесс разделяется, а дочерний процесс подключается к родительскому.
Без блока:
io = open('|-')
if io
$stderr.puts "In parent, child pid is #{io.pid}."
else
$stderr.puts "In child, pid is #{$$}."
end
Вывод:
In parent, child pid is 27903. In child, pid is 27903.
С блоком:
open('|-') do |io|
if io
$stderr.puts "In parent, child pid is #{io.pid}."
else
$stderr.puts "In child, pid is #{$$}."
end
end
Вывод:
In parent, child pid is 28427. In child, pid is 28427.
Создание подпроцесса
Если path это '|command' ('command' != '-'), новый подпроцесс выполняет команду; его открытый поток возвращается. Обратите внимание, что команда может быть обработана оболочкой, если она содержит метасимволы оболочки.
Без блока:
io = open('|echo "Hi!"') # => #<IO:fd 12>
print io.gets
io.close
Вывод:
"Hi!"
С блоком выполняется блок с потоком, а затем поток закрывается:
open('|echo "Hi!"') do |io|
print io.gets
end
Вывод:
"Hi!"
static VALUE
rb_f_p(int argc, VALUE *argv, VALUE self)
{
int i;
for (i=0; i<argc; i++) {
VALUE inspected = rb_obj_as_string(rb_inspect(argv[i]));
rb_uninterruptible(rb_p_write, inspected);
}
return rb_p_result(argc, argv);
} Для каждого объекта obj, выполняется:
$stdout.write(obj.inspect, "\n")
При передаче одного объекта, возвращается этот объект; при передаче нескольких объектов, возвращается массив, содержащий эти объекты; при отсутствии объекта, возвращается nil.
Примеры:
r = Range.new(0, 4) p r # => 0..4 p [r, r, r] # => [0..4, 0..4, 0..4] p # => nil
Вывод:
0..4 [0..4, 0..4, 0..4]
static VALUE
rb_f_print(int argc, const VALUE *argv, VALUE _)
{
rb_io_print(argc, argv, rb_ractor_stdout());
return Qnil;
} Эквивалентно $stdout.print(*objects), этот метод — простой способ записи в $stdout.
Записывает заданные объекты в $stdout; возвращает nil. Добавляет разделитель записей вывода $OUTPUT_RECORD_SEPARATOR $\), если он не nil.
При указании аргумента objects для каждого объекта:
-
Преобразуется с помощью метода
to_s, если это не строка. -
Записывается в
stdout. -
Если это не последний объект, записывается разделитель полей вывода
$OUTPUT_FIELD_SEPARATOR($,если он неnil).
С использованием стандартных разделителей:
objects = [0, 0.0, Rational(0, 1), Complex(0, 0), :zero, 'zero'] $OUTPUT_RECORD_SEPARATOR $OUTPUT_FIELD_SEPARATOR print(*objects)
Вывод:
nil nil 00.00/10+0izerozero
С указанными разделителями:
$OUTPUT_RECORD_SEPARATOR = "\n" $OUTPUT_FIELD_SEPARATOR = ',' print(*objects)
Вывод:
0,0.0,0/1,0+0i,zero,zero
Без аргументов записывает содержимое $_ (обычно это последнее введённое пользователем значение):
gets # Sets $_ to the most recent user input. print # Prints $_.
static VALUE
rb_f_printf(int argc, VALUE *argv, VALUE _)
{
VALUE out;
if (argc == 0) return Qnil;
if (RB_TYPE_P(argv[0], T_STRING)) {
out = rb_ractor_stdout();
}
else {
out = argv[0];
argv++;
argc--;
}
rb_io_write(out, rb_f_sprintf(argc, argv));
return Qnil;
} Эквивалентно:
io.write(sprintf(format_string, *objects))
Для получения дополнительной информации о format_string, см. Спецификации формата.
С единственным аргументом format_string, форматирует objects в строку, затем записывает отформатированную строку в $stdout:
printf('%4.4d %10s %2.2f', 24, 24, 24.0)
Вывод (в $stdout):
0024 24 24.00#
С аргументами io и format_string, форматирует objects в строку, затем записывает отформатированную строку в io:
printf($stderr, '%4.4d %10s %2.2f', 24, 24, 24.0)
Вывод (в $stderr):
0024 24 24.00# => nil
Без аргументов ничего не делает.
static VALUE
f_proc(VALUE _)
{
return proc_new(rb_cProc, FALSE, TRUE);
} Эквивалентно Proc.new.
static VALUE
rb_f_putc(VALUE recv, VALUE ch)
{
VALUE r_stdout = rb_ractor_stdout();
if (recv == r_stdout) {
return rb_io_putc(recv, ch);
}
return forward(r_stdout, rb_intern("putc"), 1, &ch);
} Эквивалентно:
$stdout.putc(int)
См. IO#putc для важной информации о многобайтовых символах.
static VALUE
rb_f_puts(int argc, VALUE *argv, VALUE recv)
{
VALUE r_stdout = rb_ractor_stdout();
if (recv == r_stdout) {
return rb_io_puts(argc, argv, recv);
}
return forward(r_stdout, rb_intern("puts"), argc, argv);
} Эквивалентно
$stdout.puts(objects)
static VALUE
f_raise(int c, VALUE *v, VALUE _)
{
return rb_f_raise(c, v);
} Без аргументов, вызывает исключение в $! или вызывает RuntimeError, если $! имеет значение nil. С одним аргументом String, вызывает исключение RuntimeError с заданной строкой в качестве сообщения. В противном случае, первый параметр должен быть классом исключения (или другим объектом, возвращающим объект исключения при отправке сообщения exception). Необязательный второй параметр устанавливает сообщение, связанное с исключением (доступно через Exception#message), а третий параметр — массив данных для отслеживания стека вызовов (доступно через Exception#backtrace). Причина созданного исключения (доступно через Exception#cause) автоматически устанавливается на «текущее» исключение ($!), если оно есть. Альтернативное значение, либо объект Exception, или nil, может быть задано через аргумент :cause.
Исключения обрабатываются блоком rescue в блоках begin...end.
raise "Failed to create socket" raise ArgumentError, "No parameters", caller
static VALUE
rb_f_rand(int argc, VALUE *argv, VALUE obj)
{
VALUE vmax;
rb_random_t *rnd = rand_start(default_rand());
if (rb_check_arity(argc, 0, 1) && !NIL_P(vmax = argv[0])) {
VALUE v = rand_range(obj, rnd, vmax);
if (v != Qfalse) return v;
vmax = rb_to_int(vmax);
if (vmax != INT2FIX(0)) {
v = rand_int(obj, rnd, vmax, 0);
if (!NIL_P(v)) return v;
}
}
return DBL2NUM(random_real(obj, rnd, TRUE));
} Если вызывается без аргумента или если max.to_i.abs == 0, rand возвращает псевдослучайное число с плавающей точкой от 0.0 до 1.0 включительно для 0.0 и исключая 1.0.
rand #=> 0.2725926052826416
Когда max.abs больше или равно 1, rand возвращает псевдослучайное целое число, большее или равное 0 и меньшее чем max.to_i.abs.
rand(100) #=> 12
Когда max является Range, rand возвращает случайное число, где range.member?(number) == true.
Отрицательные или числа с плавающей точкой для max допускаются, но могут давать неожиданные результаты.
rand(-100) # => 87 rand(-0.5) # => 0.8130921818028143 rand(1.9) # equivalent to rand(1), which is always 0
Kernel.srand может использоваться для обеспечения воспроизводимости последовательностей случайных чисел при разных запусках программы.
См. также Random.rand.
static VALUE
rb_f_readline(int argc, VALUE *argv, VALUE recv)
{
if (recv == argf) {
return argf_readline(argc, argv, argf);
}
return forward(argf, rb_intern("readline"), argc, argv);
} Эквивалентно методу Kernel#gets, за исключением того, что он вызывает исключение при вызове в конце потока:
$ cat t.txt | ruby -e "p readlines; readline" ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"] in `readline': end of file reached (EOFError)
Необязательный ключевой аргумент chomp указывает, нужно ли опускать разделители строк.
static VALUE
rb_f_readlines(int argc, VALUE *argv, VALUE recv)
{
if (recv == argf) {
return argf_readlines(argc, argv, argf);
}
return forward(argf, rb_intern("readlines"), argc, argv);
} Возвращает массив, содержащий строки, полученные при вызове Kernel#gets, до достижения конца потока; (см. Line IO).
При использовании только строкового аргумента sep возвращает оставшиеся строки, определяемые разделителем строк sep, или nil при отсутствии; см. Разделитель строк:
# Default separator. $ cat t.txt | ruby -e "p readlines" ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"] # Specified separator. $ cat t.txt | ruby -e "p readlines 'li'" ["First li", "ne\nSecond li", "ne\n\nFourth li", "ne\nFifth li", "ne\n"] # Get-all separator. $ cat t.txt | ruby -e "p readlines nil" ["First line\nSecond line\n\nFourth line\nFifth line\n"] # Get-paragraph separator. $ cat t.txt | ruby -e "p readlines ''" ["First line\nSecond line\n\n", "Fourth line\nFifth line\n"]
При использовании только целочисленного аргумента limit ограничивает количество байтов в строке; см. Предел строки:
$cat t.txt | ruby -e "p readlines 10" ["First line", "\n", "Second lin", "e\n", "\n", "Fourth lin", "e\n", "Fifth line", "\n"] $cat t.txt | ruby -e "p readlines 11" ["First line\n", "Second line", "\n", "\n", "Fourth line", "\n", "Fifth line\n"] $cat t.txt | ruby -e "p readlines 12" ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
При использовании аргументов sep и limit объединяет оба поведения; см. Разделитель и предел строк.
Необязательный ключевой аргумент chomp указывает, следует ли пропускать разделители строк:
$ cat t.txt | ruby -e "p readlines(chomp: true)" ["First line", "Second line", "", "Fourth line", "Fifth line"]
Необязательные ключевые аргументы enc_opts задают параметры кодирования; см. Параметры кодирования.
# File lib/syntax_suggest/core_ext.rb, line 86 def require(file) syntax_suggest_original_require(file) rescue SyntaxError => e require "syntax_suggest/api" unless defined?(SyntaxSuggest::DEFAULT_VALUE) SyntaxSuggest.handle_error(e) end
Загружает указанный name, возвращая true при успехе и false если функция уже загружена.
Если имя файла не разрешается в абсолютный путь и не начинается с ‘./’ или ‘../’, файл будет искаться в каталогах библиотек, перечисленных в $LOAD_PATH ($:). Если имя файла начинается с ‘./’ или ‘../’, разрешение основано на Dir.pwd.
Если имя файла имеет расширение “.rb”, оно загружается как исходный файл; если расширение — “.so”, “.o” или “.dll”, или стандартное расширение динамической библиотеки в текущей платформе, Ruby загружает динамическую библиотеку как расширение Ruby. В противном случае Ruby пытается добавить “.rb”, “.so” и так далее к имени, пока не найдет. Если файл с указанным именем не найден, будет поднято исключение LoadError.
Для расширений Ruby имя файла может использовать любое расширение динамической библиотеки. Например, в Linux расширение сокета — “socket.so” и require 'socket.dll' загрузит расширение сокета.
Абсолютный путь загруженного файла добавляется в $LOADED_FEATURES ($"). Файл не будет загружен повторно, если его путь уже присутствует в $". Например, require 'a'; require './a' не загрузит a.rb повторно.
require "my-library.rb" require "db-driver"
Любые константы или глобальные переменные в загруженном исходном файле будут доступны в глобальном пространстве имен вызывающей программы. Однако локальные переменные не будут переданы в среду загрузки.
# File lib/syntax_suggest/core_ext.rb, line 94
def require_relative(file)
if Pathname.new(file).absolute?
syntax_suggest_original_require file
else
relative_from = caller_locations(1..1).first
relative_from_path = relative_from.absolute_path || relative_from.path
syntax_suggest_original_require File.expand_path("../#{file}", relative_from_path)
end
rescue SyntaxError => e
require "syntax_suggest/api" unless defined?(SyntaxSuggest::DEFAULT_VALUE)
SyntaxSuggest.handle_error(e)
end Ruby пытается загрузить библиотеку с именем строка относительно каталога, содержащего требуемый файл. Если файл не существует, будет поднято исключение LoadError. Возвращает true если файл был загружен и false если файл был загружен ранее.
static VALUE
rb_f_select(int argc, VALUE *argv, VALUE obj)
{
VALUE scheduler = rb_fiber_scheduler_current();
if (scheduler != Qnil) {
// It's optionally supported.
VALUE result = rb_fiber_scheduler_io_selectv(scheduler, argc, argv);
if (!UNDEF_P(result)) return result;
}
VALUE timeout;
struct select_args args;
struct timeval timerec;
int i;
rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
if (NIL_P(timeout)) {
args.timeout = 0;
}
else {
timerec = rb_time_interval(timeout);
args.timeout = &timerec;
}
for (i = 0; i < numberof(args.fdsets); ++i)
rb_fd_init(&args.fdsets[i]);
return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
} Вызывает системный вызов select(2), который отслеживает несколько дескрипторов файлов, ожидая, пока один или несколько дескрипторов файлов не станут доступными для операций ввода-вывода.
Не реализовано на всех платформах.
Каждый из аргументов read_ios, write_ios, и error_ios является массивом объектов IO.
Аргумент timeout — это целочисленный интервал времени ожидания в секундах.
Метод отслеживает объекты ввода-вывода, указанные во всех трех массивах, ожидая, пока некоторые из них не станут доступными; возвращает массив из 3 элементов:
-
Массив объектов из
read_iosготовых к чтению. -
Массив объектов из
write_iosготовых к записи. -
Массив объектов из
error_iosс ожидаемыми исключениями.
Если ни один объект не становится доступным в течение заданного timeout, возвращается nil.
IO.select просматривает буфер объектов ввода-вывода для проверки возможности чтения. Если буфер ввода-вывода не пуст, IO.select немедленно сообщает о возможности чтения. Этот «просмотр» происходит только для объектов ввода-вывода. Он не происходит для объектов, подобных вводу-выводу, таких как OpenSSL::SSL::SSLSocket.
Лучший способ использования IO.select — вызывать его после выполнения асинхронных методов, таких как read_nonblock, write_nonblock и т. д. Методы генерируют исключения, которые расширяются IO::WaitReadable или IO::WaitWritable. Модули сообщают, как вызывающей программе следует ожидать с помощью IO.select. Если IO::WaitReadable генерируется, вызывающая программа должна ждать чтения. Если IO::WaitWritable генерируется, вызывающая программа должна ждать записи.
Таким образом, блокирующее чтение (readpartial) можно эмулировать с помощью read_nonblock и IO.select следующим образом:
begin result = io_like.read_nonblock(maxlen) rescue IO::WaitReadable IO.select([io_like]) retry rescue IO::WaitWritable IO.select(nil, [io_like]) retry end
В частности, сочетание асинхронных методов и IO.select предпочтительнее для объектов ввода-вывода, таких как OpenSSL::SSL::SSLSocket. У него есть метод to_io для возвращения базового объекта IO. IO.select вызывает to_io для получения дескриптора файла для ожидания.
Это означает, что возможность чтения, уведомленная IO.select, не означает возможность чтения из объекта OpenSSL::SSL::SSLSocket.
Наиболее вероятный случай — OpenSSL::SSL::SSLSocket буферизует некоторые данные. IO.select не видит буфер. Поэтому IO.select может заблокироваться, когда OpenSSL::SSL::SSLSocket#readpartial не блокируется.
Однако существуют и более сложные ситуации.
SSL — это протокол, который представляет собой последовательность записей. Запись состоит из нескольких байтов. Таким образом, удаленный конец SSL отправляет частичную запись, IO.select сообщает о возможности чтения, но OpenSSL::SSL::SSLSocket не может декодировать байт, и OpenSSL::SSL::SSLSocket#readpartial будет заблокирован.
Также удаленный конец может запросить переподключение SSL, что заставляет локальный движок SSL написать некоторые данные. Это означает, что OpenSSL::SSL::SSLSocket#readpartial может вызвать системный вызов записи, и он может заблокироваться. В такой ситуации OpenSSL::SSL::SSLSocket#read_nonblock генерирует IO::WaitWritable, а не блокируется. Таким образом, вызывающая программа должна ждать готовности к записи, как в примере выше.
Сочетание асинхронных методов и IO.select также полезно для потоков, таких как tty, сокеты каналов, сокеты, когда несколько процессов читают из потока.
Наконец, разработчики ядра Linux не гарантируют, что возможность чтения select(2) означает возможность чтения последующего read(2) даже для одного процесса; см. select(2)
Вызов IO.select до IO#readpartial работает как обычно. Однако это не лучший способ использования IO.select.
Возможность записи, уведомленная select(2), не показывает, сколько байтов доступно для записи. Метод IO#write блокируется, пока вся строка не будет записана. Таким образом, IO#write(two or more bytes) может заблокироваться после уведомления о возможности записи IO.select. Необходимо использовать IO#write_nonblock, чтобы избежать блокировки.
Блокирующую запись (write) можно эмулировать с помощью write_nonblock и IO.select следующим образом: IO::WaitReadable также необходимо перехватывать для переподключения SSL в OpenSSL::SSL::SSLSocket.
while 0 < string.bytesize
begin
written = io_like.write_nonblock(string)
rescue IO::WaitReadable
IO.select([io_like])
retry
rescue IO::WaitWritable
IO.select(nil, [io_like])
retry
end
string = string.byteslice(written..-1)
end
Пример:
rp, wp = IO.pipe
mesg = "ping "
100.times {
# IO.select follows IO#read. Not the best way to use IO.select.
rs, ws, = IO.select([rp], [wp])
if r = rs[0]
ret = r.read(5)
print ret
case ret
when /ping/
mesg = "pong\n"
when /pong/
mesg = "ping "
end
end
if w = ws[0]
w.write(mesg)
end
}
Вывод:
ping pong ping pong ping pong (snipped) ping
static VALUE
set_trace_func(VALUE obj, VALUE trace)
{
rb_remove_event_hook(call_trace_func);
if (NIL_P(trace)) {
return Qnil;
}
if (!rb_obj_is_proc(trace)) {
rb_raise(rb_eTypeError, "trace_func needs to be Proc");
}
rb_add_event_hook(call_trace_func, RUBY_EVENT_ALL, trace);
return trace;
} Establishes _proc_ as the handler for tracing, or disables
tracing if the parameter is +nil+.
*Note:* this method is obsolete, please use TracePoint instead.
_proc_ takes up to six parameters:
* an event name
* a filename
* a line number
* an object id
* a binding
* the name of a class
_proc_ is invoked whenever an event occurs.
Events are:
+c-call+:: call a C-language routine
+c-return+:: return from a C-language routine
+call+:: call a Ruby method
+class+:: start a class or module definition
+end+:: finish a class or module definition
+line+:: execute code on a new line
+raise+:: raise an exception
+return+:: return from a Ruby method
Tracing is disabled within the context of _proc_.
class Test
def test
a = 1
b = 2
end
end
set_trace_func proc { |event, file, line, id, binding, classname|
printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
}
t = Test.new
t.test
line prog.rb:11 false
c-call prog.rb:11 new Class
c-call prog.rb:11 initialize Object
c-return prog.rb:11 initialize Object
c-return prog.rb:11 new Class
line prog.rb:12 false
call prog.rb:2 test Test
line prog.rb:3 test Test
line prog.rb:4 test Test
return prog.rb:4 test Test Обратите внимание, что для c-call и c-return событий возвращаемая привязка — это привязка ближайшего Ruby-метода, вызывающего C-метод, так как сами C-методы не имеют привязок.
static VALUE
rb_f_sleep(int argc, VALUE *argv, VALUE _)
{
time_t beg = time(0);
VALUE scheduler = rb_fiber_scheduler_current();
if (scheduler != Qnil) {
rb_fiber_scheduler_kernel_sleepv(scheduler, argc, argv);
}
else {
if (argc == 0) {
rb_thread_sleep_forever();
}
else {
rb_check_arity(argc, 0, 1);
rb_thread_wait_for(rb_time_interval(argv[0]));
}
}
time_t end = time(0) - beg;
return TIMET2NUM(end);
} Приостанавливает выполнение текущей нити на duration секунд (любое число, включая Float с дробной частью). Возвращает фактическое количество проспанных секунд (округленное), которое может быть меньше запрошенного, если другая нить вызывает Thread#run. Если вызвано без аргумента, sleep() будет приостанавливаться навсегда.
Time.new #=> 2008-03-08 19:56:19 +0900 sleep 1.2 #=> 1 Time.new #=> 2008-03-08 19:56:20 +0900 sleep 1.9 #=> 2 Time.new #=> 2008-03-08 19:56:22 +0900
static VALUE
rb_f_spawn(int argc, VALUE *argv, VALUE _)
{
rb_pid_t pid;
char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
VALUE execarg_obj, fail_str;
struct rb_execarg *eargp;
execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
eargp = rb_execarg_get(execarg_obj);
fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
pid = rb_execarg_spawn(execarg_obj, errmsg, sizeof(errmsg));
if (pid == -1) {
int err = errno;
rb_exec_fail(eargp, err, errmsg);
RB_GC_GUARD(execarg_obj);
rb_syserr_fail_str(err, fail_str);
}
#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
return PIDT2NUM(pid);
#else
return Qnil;
#endif
} spawn выполняет указанную команду и возвращает её pid.
pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
Process.wait pid
pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
Process.wait pid
Этот метод похож на Kernel#system, но не ожидает завершения команды.
Родительский процесс должен использовать Process.wait для получения кода завершения своего дочернего процесса или использовать Process.detach для отключения интереса к его статусу; в противном случае операционная система может накапливать процессы-зомби.
spawn имеет множество опций для задания атрибутов процесса:
env: hash
name => val : set the environment variable
name => nil : unset the environment variable
the keys and the values except for +nil+ must be strings.
command...:
commandline : command line string which is passed to the standard shell
cmdname, arg1, ... : command name and one or more arguments (This form does not use the shell. See below for caveats.)
[cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
options: hash
clearing environment variables:
:unsetenv_others => true : clear environment variables except specified by env
:unsetenv_others => false : don't clear (default)
process group:
:pgroup => true or 0 : make a new process group
:pgroup => pgid : join the specified process group
:pgroup => nil : don't change the process group (default)
create new process group: Windows only
:new_pgroup => true : the new process is the root process of a new process group
:new_pgroup => false : don't create a new process group (default)
resource limit: resourcename is core, cpu, data, etc. See Process.setrlimit.
:rlimit_resourcename => limit
:rlimit_resourcename => [cur_limit, max_limit]
umask:
:umask => int
redirection:
key:
FD : single file descriptor in child process
[FD, FD, ...] : multiple file descriptor in child process
value:
FD : redirect to the file descriptor in parent process
string : redirect to file with open(string, "r" or "w")
[string] : redirect to file with open(string, File::RDONLY)
[string, open_mode] : redirect to file with open(string, open_mode, 0644)
[string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
[:child, FD] : redirect to the redirected file descriptor
:close : close the file descriptor in child process
FD is one of follows
:in : the file descriptor 0 which is the standard input
:out : the file descriptor 1 which is the standard output
:err : the file descriptor 2 which is the standard error
integer : the file descriptor of specified the integer
io : the file descriptor specified as io.fileno
file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
:close_others => false : inherit
current directory:
:chdir => str Форма cmdname, arg1, ... не использует оболочку. Однако на разных ОС встроенными командами могут быть разные вещи. Пример — «echo», которое является встроенной командой в Windows, но обычной программой в Linux и Mac OS X. Это означает, что Process.spawn 'echo', '%Path%' выведет содержимое переменной среды %Path% в Windows, а Process.spawn 'echo', '$PATH' выведет буквально $PATH.
Если в качестве env задан хэш, среда обновляется env перед exec(2) в дочернем процессе. Если в паре в env значение равно nil, переменная удаляется.
# set FOO as BAR and unset BAZ.
pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command)
Если в качестве options задан хэш, он задаёт группу процессов, создание новой группы процессов, лимиты ресурсов, текущую директорию, umask и перенаправления для дочернего процесса. Также можно указать очистку переменных окружения.
Ключ :unsetenv_others в options указывает на очистку переменных окружения, кроме тех, которые указаны env.
pid = spawn(command, :unsetenv_others=>true) # no environment variable
pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true) # FOO only
Ключ :pgroup в options задаёт группу процессов. Соответствующее значение должно быть true, нулём, положительным целым числом или nil. true и ноль заставляют процесс стать лидером новой группы процессов. Положительное целое число заставляет процесс присоединиться к указанной группе процессов. Значение по умолчанию, nil, заставляет процесс остаться в той же группе процессов.
pid = spawn(command, :pgroup=>true) # process leader pid = spawn(command, :pgroup=>10) # belongs to the process group 10
Ключ :new_pgroup в options указывает на передачу флага CREATE_NEW_PROCESS_GROUP в CreateProcessW(), что является API Windows. Эта опция только для Windows. true означает, что новый процесс является корневым процессом новой группы процессов. У нового процесса отключено CTRL+C. Этот флаг необходим для Process.kill(:SIGINT, pid) в дочернем процессе. По умолчанию :new_pgroup равен false.
pid = spawn(command, :new_pgroup=>true) # new process group pid = spawn(command, :new_pgroup=>false) # same process group
Ключ :rlimit_foo задаёт ограничение ресурсов. foo должен быть одним из типов ресурсов, таких как core. Соответствующее значение должно быть целым числом или массивом, содержащим одно или два целых числа: аналогично аргументам cur_limit и max_limit для Process.setrlimit.
cur, max = Process.getrlimit(:CORE) pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary. pid = spawn(command, :rlimit_core=>max) # enable core dump pid = spawn(command, :rlimit_core=>0) # never dump core.
Ключ :umask в options задаёт umask.
pid = spawn(command, :umask=>077)
Ключи :in, :out, :err, целое число, IO и массив задают перенаправление. Перенаправление отображает дескриптор файла в дочернем процессе.
Например, stderr можно объединить с stdout следующим образом:
pid = spawn(command, :err=>:out) pid = spawn(command, 2=>1) pid = spawn(command, STDERR=>:out) pid = spawn(command, STDERR=>STDOUT)
Ключи хэша задают дескриптор файла в дочернем процессе, запущенном с помощью spawn. :err, 2 и STDERR задают поток стандартной ошибки (stderr).
Значения хэша задают дескриптор файла в родительском процессе, вызывающем spawn. :out, 1 и STDOUT задают поток стандартного вывода (stdout).
В приведенном выше примере стандартный вывод в дочернем процессе не указан. Поэтому он унаследован от родительского процесса.
Поток стандартного ввода (stdin) можно указать с помощью :in, 0 и STDIN.
Можно указать имя файла в качестве значения хэша.
pid = spawn(command, :in=>"/dev/null") # read mode pid = spawn(command, :out=>"/dev/null") # write mode pid = spawn(command, :err=>"log") # write mode pid = spawn(command, [:out, :err]=>"/dev/null") # write mode pid = spawn(command, 3=>"/dev/null") # read mode
Для stdout и stderr (и их комбинации) используется режим записи. В противном случае используется режим чтения.
Для явного задания флагов и разрешений для создания файла используется массив.
pid = spawn(command, :in=>["file"]) # read mode is assumed pid = spawn(command, :in=>["file", "r"]) pid = spawn(command, :out=>["log", "w"]) # 0644 assumed pid = spawn(command, :out=>["log", "w", 0600]) pid = spawn(command, :out=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600])
Массив задаёт имя файла, флаги и разрешения. Флаги могут быть строкой или целым числом. Если флаги опущены или nil, предполагается File::RDONLY. Разрешения должны быть целым числом. Если разрешения опущены или nil, предполагается 0644.
Если в качестве ключа хэша указан массив IOs и целых чисел, все элементы будут перенаправлены.
# stdout and stderr is redirected to log file. # The file "log" is opened just once. pid = spawn(command, [:out, :err]=>["log", "w"])
Ещё один способ объединить несколько дескрипторов файлов — [:child, fd]. [:child, fd] означает дескриптор файла в дочернем процессе. Это отличается от fd. Например, :err=>:out означает перенаправление child stderr в parent stdout. Но :err=>[:child, :out] означает перенаправление child stderr в child stdout. Они отличаются, если stdout перенаправлен в дочернем процессе следующим образом.
# stdout and stderr is redirected to log file. # The file "log" is opened just once. pid = spawn(command, :out=>["log", "w"], :err=>[:child, :out])
[:child, :out] можно использовать для объединения stderr с stdout в IO.popen. В этом случае IO.popen перенаправляет stdout в канал в дочернем процессе, а [:child, :out] относится к перенаправленному stdout.
io = IO.popen(["sh", "-c", "echo out; echo err >&2", :err=>[:child, :out]]) p io.read #=> "out\nerr\n"
Ключ :chdir в options задаёт текущую директорию.
pid = spawn(command, :chdir=>"/var/tmp")
По умолчанию spawn закрывает все нестандартные неуказанные дескрипторы. «Стандартные» дескрипторы — 0, 1 и 2. Это поведение задаётся опцией :close_others. :close_others не влияет на стандартные дескрипторы, которые закрываются только если :close указан явно.
pid = spawn(command, :close_others=>true) # close 3,4,5,... (default) pid = spawn(command, :close_others=>false) # don't close 3,4,5,...
:close_others по умолчанию false для spawn и IO.popen.
Обратите внимание, что дескрипторы, для которых уже установлен флаг close-on-exec, закрываются независимо от опции :close_others.
Поэтому IO.pipe и spawn могут использоваться как IO.popen.
# similar to r = IO.popen(command) r, w = IO.pipe pid = spawn(command, :out=>w) # r, w is closed in the child process. w.close
:close указывается как значение хэша для индивидуального закрытия дескриптора.
f = open(foo) system(command, f=>:close) # don't inherit f.
Если дескриптор файла нужно унаследовать, можно использовать io=>io.
# valgrind has --log-fd option for log destination.
# log_w=>log_w indicates log_w.fileno inherits to child process.
log_r, log_w = IO.pipe
pid = spawn("valgrind", "--log-fd=#{log_w.fileno}", "echo", "a", log_w=>log_w)
log_w.close
p log_r.read
Также возможно обмен дескрипторами файлов.
pid = spawn(command, :out=>:err, :err=>:out)
Ключи хэша задают дескрипторы файлов в дочернем процессе. Значения хэша задают дескрипторы файлов в родительском процессе. Таким образом, вышеуказанное перенаправляет stdout и stderr. Внутренне spawn использует дополнительный дескриптор для решения таких циклических сопоставлений дескрипторов файлов.
См. Kernel.exec для стандартной оболочки.
static VALUE
f_sprintf(int c, const VALUE *v, VALUE _)
{
return rb_f_sprintf(c, v);
} Возвращает строку, полученную в результате форматирования objects в format_string.
Подробности о format_string, см. Спецификации форматирования.
Kernel#format является псевдонимом для Kernel#sprintf.
static VALUE
rb_f_srand(int argc, VALUE *argv, VALUE obj)
{
VALUE seed, old;
rb_random_mt_t *r = rand_mt_start(default_rand());
if (rb_check_arity(argc, 0, 1) == 0) {
seed = random_seed(obj);
}
else {
seed = rb_to_int(argv[0]);
}
old = r->base.seed;
rand_init(&random_mt_if, &r->base, seed);
r->base.seed = seed;
return old;
} Инициализирует генератор псевдослучайных чисел системы с помощью number. Возвращает предыдущее значение seed.
Если number опущено, инициализирует генератор, используя источник энтропии, предоставляемый операционной системой (если доступно /dev/urandom в системах Unix или криптографический провайдер RSA в Windows), который затем объединяется со временем, идентификатором процесса и номером последовательности.
srand можно использовать для обеспечения повторяемости последовательностей псевдослучайных чисел между разными запусками программы. Установив seed в известное значение, программы могут быть детерминированными во время тестирования.
srand 1234 # => 268519324636777531569100071560086917274 [ rand, rand ] # => [0.1915194503788923, 0.6221087710398319] [ rand(10), rand(1000) ] # => [4, 664] srand 1234 # => 1234 [ rand, rand ] # => [0.1915194503788923, 0.6221087710398319]
static VALUE
rb_f_sub(int argc, VALUE *argv, VALUE _)
{
VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("sub"), argc, argv);
rb_lastline_set(str);
return str;
} Эквивалентно $_.sub(args), за исключением того, что $_ будет обновлён, если произойдёт подстановка. Доступно только при заданных командной строкой опциях -p/-n.
static VALUE
rb_f_syscall(int argc, VALUE *argv, VALUE _)
{
VALUE arg[8];
#if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
# define SYSCALL __syscall
# define NUM2SYSCALLID(x) NUM2LONG(x)
# define RETVAL2NUM(x) LONG2NUM(x)
# if SIZEOF_LONG == 8
long num, retval = -1;
# elif SIZEOF_LONG_LONG == 8
long long num, retval = -1;
# else
# error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
# endif
#elif defined(__linux__)
# define SYSCALL syscall
# define NUM2SYSCALLID(x) NUM2LONG(x)
# define RETVAL2NUM(x) LONG2NUM(x)
/*
* Linux man page says, syscall(2) function prototype is below.
*
* int syscall(int number, ...);
*
* But, it's incorrect. Actual one takes and returned long. (see unistd.h)
*/
long num, retval = -1;
#else
# define SYSCALL syscall
# define NUM2SYSCALLID(x) NUM2INT(x)
# define RETVAL2NUM(x) INT2NUM(x)
int num, retval = -1;
#endif
int i;
if (RTEST(ruby_verbose)) {
rb_category_warning(RB_WARN_CATEGORY_DEPRECATED,
"We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
}
if (argc == 0)
rb_raise(rb_eArgError, "too few arguments for syscall");
if (argc > numberof(arg))
rb_raise(rb_eArgError, "too many arguments for syscall");
num = NUM2SYSCALLID(argv[0]); ++argv;
for (i = argc - 1; i--; ) {
VALUE v = rb_check_string_type(argv[i]);
if (!NIL_P(v)) {
SafeStringValue(v);
rb_str_modify(v);
arg[i] = (VALUE)StringValueCStr(v);
}
else {
arg[i] = (VALUE)NUM2LONG(argv[i]);
}
}
switch (argc) {
case 1:
retval = SYSCALL(num);
break;
case 2:
retval = SYSCALL(num, arg[0]);
break;
case 3:
retval = SYSCALL(num, arg[0],arg[1]);
break;
case 4:
retval = SYSCALL(num, arg[0],arg[1],arg[2]);
break;
case 5:
retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
break;
case 6:
retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
break;
case 7:
retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
break;
case 8:
retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
break;
}
if (retval == -1)
rb_sys_fail(0);
return RETVAL2NUM(retval);
#undef SYSCALL
#undef NUM2SYSCALLID
#undef RETVAL2NUM
} Вызывает системный вызов Posix syscall(2), который вызывает указанную функцию.
Вызывает функцию операционной системы, идентифицируемую integer_callno; возвращает результат функции или вызывает исключение SystemCallError, если произошла ошибка. Эффект вызова зависит от платформы. Аргументы и возвращаемое значение зависят от платформы.
Для каждого из arguments: если это целое число, оно передается напрямую; если это строка, она интерпретируется как двоичная последовательность байтов. Может быть до девяти таких аргументов.
Аргументы integer_callno и argument, а также возвращаемое значение, зависят от платформы.
Примечание: Method syscall по своей сути небезопасен и не переносим. Для более безопасного и немного более переносимого программирования предпочтительна библиотека DL (Fiddle).
Не реализовано на всех платформах.
static VALUE
rb_f_system(int argc, VALUE *argv, VALUE _)
{
VALUE execarg_obj = rb_execarg_new(argc, argv, TRUE, TRUE);
struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
struct rb_process_status status = {0};
eargp->status = &status;
rb_last_status_clear();
// This function can set the thread's last status.
// May be different from waitpid_state.pid on exec failure.
rb_pid_t pid = rb_execarg_spawn(execarg_obj, 0, 0);
if (pid > 0) {
VALUE status = rb_process_status_wait(pid, 0);
struct rb_process_status *data = RTYPEDDATA_DATA(status);
// Set the last status:
rb_obj_freeze(status);
GET_THREAD()->last_status = status;
if (data->status == EXIT_SUCCESS) {
return Qtrue;
}
if (data->error != 0) {
if (eargp->exception) {
VALUE command = eargp->invoke.sh.shell_script;
RB_GC_GUARD(execarg_obj);
rb_syserr_fail_str(data->error, command);
}
else {
return Qnil;
}
}
else if (eargp->exception) {
VALUE command = eargp->invoke.sh.shell_script;
VALUE str = rb_str_new_cstr("Command failed with");
rb_str_cat_cstr(pst_message_status(str, data->status), ": ");
rb_str_append(str, command);
RB_GC_GUARD(execarg_obj);
rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, str));
}
else {
return Qfalse;
}
RB_GC_GUARD(status);
}
if (eargp->exception) {
VALUE command = eargp->invoke.sh.shell_script;
RB_GC_GUARD(execarg_obj);
rb_syserr_fail_str(errno, command);
}
else {
return Qnil;
}
} Выполняет command… в дочерней оболочке. command… имеет один из следующих форматов.
Этот метод может иметь потенциальные уязвимости в случае вызова с недоверенными данными; см. Инъекция команд.
-
commandline -
Строка командной строки, передаваемая в стандартную оболочку
-
cmdname, arg1, ... -
Имя команды и один или несколько аргументов (без оболочки)
-
[cmdname, argv0], arg1, ... -
Имя команды,
argv[0]и ноль или более аргументов (без оболочки)
system возвращает true если команда завершилась с нулевым кодом, false для ненулевого кода завершения. Возвращает nil если выполнение команды завершилось ошибкой. Статус ошибки доступен в $?.
Если передан аргумент exception: true, метод вызывает исключение вместо возвращения false или nil.
Аргументы обрабатываются так же, как и в Kernel#spawn.
Аргументы в виде хэша, env и options, такие же, как в exec и spawn. Подробности см. в Kernel#spawn.
system("echo *")
system("echo", "*")
выводит:
config.h main.rb *
Обработка ошибок:
system("cat nonexistent.txt")
# => false
system("catt nonexistent.txt")
# => nil
system("cat nonexistent.txt", exception: true)
# RuntimeError (Command failed with exit 1: cat)
system("catt nonexistent.txt", exception: true)
# Errno::ENOENT (No such file or directory - catt)
См. Kernel#exec для стандартной оболочки.
# File kernel.rb, line 89 def tap yield(self) self end
Передает self в блок и затем возвращает self. Основное назначение этого метода — «присоединиться» к цепочке методов, чтобы выполнять операции над промежуточными результатами в цепочке.
(1..10) .tap {|x| puts "original: #{x}" }
.to_a .tap {|x| puts "array: #{x}" }
.select {|x| x.even? } .tap {|x| puts "evens: #{x}" }
.map {|x| x*x } .tap {|x| puts "squares: #{x}" }
static VALUE
rb_f_test(int argc, VALUE *argv, VALUE _)
{
int cmd;
if (argc == 0) rb_check_arity(argc, 2, 3);
cmd = NUM2CHR(argv[0]);
if (cmd == 0) {
goto unknown;
}
if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) {
CHECK(1);
switch (cmd) {
case 'b':
return rb_file_blockdev_p(0, argv[1]);
case 'c':
return rb_file_chardev_p(0, argv[1]);
case 'd':
return rb_file_directory_p(0, argv[1]);
case 'e':
return rb_file_exist_p(0, argv[1]);
case 'f':
return rb_file_file_p(0, argv[1]);
case 'g':
return rb_file_sgid_p(0, argv[1]);
case 'G':
return rb_file_grpowned_p(0, argv[1]);
case 'k':
return rb_file_sticky_p(0, argv[1]);
case 'l':
return rb_file_symlink_p(0, argv[1]);
case 'o':
return rb_file_owned_p(0, argv[1]);
case 'O':
return rb_file_rowned_p(0, argv[1]);
case 'p':
return rb_file_pipe_p(0, argv[1]);
case 'r':
return rb_file_readable_p(0, argv[1]);
case 'R':
return rb_file_readable_real_p(0, argv[1]);
case 's':
return rb_file_size_p(0, argv[1]);
case 'S':
return rb_file_socket_p(0, argv[1]);
case 'u':
return rb_file_suid_p(0, argv[1]);
case 'w':
return rb_file_writable_p(0, argv[1]);
case 'W':
return rb_file_writable_real_p(0, argv[1]);
case 'x':
return rb_file_executable_p(0, argv[1]);
case 'X':
return rb_file_executable_real_p(0, argv[1]);
case 'z':
return rb_file_zero_p(0, argv[1]);
}
}
if (strchr("MAC", cmd)) {
struct stat st;
VALUE fname = argv[1];
CHECK(1);
if (rb_stat(fname, &st) == -1) {
int e = errno;
FilePathValue(fname);
rb_syserr_fail_path(e, fname);
}
switch (cmd) {
case 'A':
return stat_atime(&st);
case 'M':
return stat_mtime(&st);
case 'C':
return stat_ctime(&st);
}
}
if (cmd == '-') {
CHECK(2);
return rb_file_identical_p(0, argv[1], argv[2]);
}
if (strchr("=<>", cmd)) {
struct stat st1, st2;
struct timespec t1, t2;
CHECK(2);
if (rb_stat(argv[1], &st1) < 0) return Qfalse;
if (rb_stat(argv[2], &st2) < 0) return Qfalse;
t1 = stat_mtimespec(&st1);
t2 = stat_mtimespec(&st2);
switch (cmd) {
case '=':
if (t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec) return Qtrue;
return Qfalse;
case '>':
if (t1.tv_sec > t2.tv_sec) return Qtrue;
if (t1.tv_sec == t2.tv_sec && t1.tv_nsec > t2.tv_nsec) return Qtrue;
return Qfalse;
case '<':
if (t1.tv_sec < t2.tv_sec) return Qtrue;
if (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec) return Qtrue;
return Qfalse;
}
}
unknown:
/* unknown command */
if (ISPRINT(cmd)) {
rb_raise(rb_eArgError, "unknown command '%s%c'", cmd == '\'' || cmd == '\\' ? "\\" : "", cmd);
}
else {
rb_raise(rb_eArgError, "unknown command \"\\x%02X\"", cmd);
}
UNREACHABLE_RETURN(Qundef);
} Использует символ cmd для выполнения различных проверок на file1 (первая таблица ниже) или на file1 и file2 (вторая таблица).
Проверки на один файл:
Cmd Returns Meaning
"A" | Time | Last access time for file1
"b" | boolean | True if file1 is a block device
"c" | boolean | True if file1 is a character device
"C" | Time | Last change time for file1
"d" | boolean | True if file1 exists and is a directory
"e" | boolean | True if file1 exists
"f" | boolean | True if file1 exists and is a regular file
"g" | boolean | True if file1 has the setgid bit set
"G" | boolean | True if file1 exists and has a group
| | ownership equal to the caller's group
"k" | boolean | True if file1 exists and has the sticky bit set
"l" | boolean | True if file1 exists and is a symbolic link
"M" | Time | Last modification time for file1
"o" | boolean | True if file1 exists and is owned by
| | the caller's effective uid
"O" | boolean | True if file1 exists and is owned by
| | the caller's real uid
"p" | boolean | True if file1 exists and is a fifo
"r" | boolean | True if file1 is readable by the effective
| | uid/gid of the caller
"R" | boolean | True if file is readable by the real
| | uid/gid of the caller
"s" | int/nil | If file1 has nonzero size, return the size,
| | otherwise return nil
"S" | boolean | True if file1 exists and is a socket
"u" | boolean | True if file1 has the setuid bit set
"w" | boolean | True if file1 exists and is writable by
| | the effective uid/gid
"W" | boolean | True if file1 exists and is writable by
| | the real uid/gid
"x" | boolean | True if file1 exists and is executable by
| | the effective uid/gid
"X" | boolean | True if file1 exists and is executable by
| | the real uid/gid
"z" | boolean | True if file1 exists and has a zero length Проверки, требующие два файла:
"-" | boolean | True if file1 and file2 are identical
"=" | boolean | True if the modification times of file1
| | and file2 are equal
"<" | boolean | True if the modification time of file1
| | is prior to that of file2
">" | boolean | True if the modification time of file1
| | is after that of file2 # File kernel.rb, line 120
def then
unless Primitive.block_given_p
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_obj_size)'
end
yield(self)
end Передает self в блок и возвращает результат блока.
3.next.then {|x| x**x }.to_s #=> "256"
Хорошее использование then — это передача значений в цепочках методов:
require 'open-uri'
require 'json'
construct_url(arguments).
then {|url| URI(url).read }.
then {|response| JSON.parse(response) }
При вызове без блока метод возвращает Enumerator, что можно использовать, например, для условного прерывания цепочки:
# meets condition, no-op 1.then.detect(&:odd?) # => 1 # does not meet condition, drop value 2.then.detect(&:odd?) # => nil
static VALUE
rb_f_throw(int argc, VALUE *argv, VALUE _)
{
VALUE tag, value;
rb_scan_args(argc, argv, "11", &tag, &value);
rb_throw_obj(tag, value);
UNREACHABLE_RETURN(Qnil);
} Передает управление в конец активного блока catch в ожидании tag. Вызывает UncaughtThrowError если для tag нет блока catch. Дополнительный второй параметр предоставляет возвращаемое значение для блока catch, которое по умолчанию равно nil. Примеры см. в Kernel::catch.
static VALUE
f_trace_var(int c, const VALUE *a, VALUE _)
{
return rb_f_trace_var(c, a);
} Управляет отслеживанием присваивания глобальным переменным. Параметр symbol идентифицирует переменную (как имя строки или идентификатор символа). cmd (который может быть строкой или объектом Proc) или блок выполняется всякий раз, когда переменной присваивается новое значение. Блок или объект Proc получает новое значение переменной в качестве параметра. См. также Kernel::untrace_var.
trace_var :$_, proc {|v| puts "$_ is now '#{v}'" }
$_ = "hello"
$_ = ' there'
выводит:
$_ is now 'hello' $_ is now ' there'
static VALUE
sig_trap(int argc, VALUE *argv, VALUE _)
{
int sig;
sighandler_t func;
VALUE cmd;
rb_check_arity(argc, 1, 2);
sig = trap_signm(argv[0]);
if (reserved_signal_p(sig)) {
const char *name = signo2signm(sig);
if (name)
rb_raise(rb_eArgError, "can't trap reserved signal: SIG%s", name);
else
rb_raise(rb_eArgError, "can't trap reserved signal: %d", sig);
}
if (argc == 1) {
cmd = rb_block_proc();
func = sighandler;
}
else {
cmd = argv[1];
func = trap_handler(&cmd, sig);
}
if (rb_obj_is_proc(cmd) &&
!rb_ractor_main_p() && !rb_ractor_shareable_p(cmd)) {
cmd = rb_proc_isolate(cmd);
}
return trap(sig, func, cmd);
} Определяет обработку сигналов. Первый параметр — имя сигнала (строка, например, «SIGALRM», «SIGUSR1» и т. д.) или номер сигнала. Символы «SIG» могут быть опущены из имени сигнала. Команда или блок определяют код, который будет выполнен при возникновении сигнала. Если команда — строка «IGNORE» или «SIG_IGN», сигнал будет проигнорирован. Если команда — «DEFAULT» или «SIG_DFL», будет вызван обработчик по умолчанию Ruby. Если команда — «EXIT», скрипт будет завершен сигналом. Если команда — «SYSTEM_DEFAULT», будет вызван обработчик по умолчанию операционной системы. В противном случае будет выполнена заданная команда или блок. Специальное имя сигнала «EXIT» или номер сигнала ноль будет вызвано непосредственно перед завершением программы. trap возвращает предыдущий обработчик для данного сигнала.
Signal.trap(0, proc { puts "Terminating: #{$$}" })
Signal.trap("CLD") { puts "Child died" }
fork && Process.wait
выводит:
Terminating: 27461 Child died Terminating: 27460
static VALUE
f_untrace_var(int c, const VALUE *a, VALUE _)
{
return rb_f_untrace_var(c, a);
} Удаляет отслеживание для указанной команды по заданной глобальной переменной и возвращает nil. Если команда не указана, удаляются все отслеживания для этой переменной, и возвращается массив, содержащий удаленные команды.
# File warning.rb, line 50 def warn(*msgs, uplevel: nil, category: nil) Primitive.rb_warn_m(msgs, uplevel, category) end
Если предупреждения отключены (например, с флагом -W0), ничего не делает. В противном случае преобразует каждое сообщение в строку, добавляет символ новой строки в конец строки, если она на нем не заканчивается, и вызывает Warning.warn со строкой.
warn("warning 1", "warning 2")
<em>produces:</em>
warning 1
warning 2 Если передан ключевой аргумент uplevel, к строке будет добавлена информация о вызвавшем фрейме в том же формате, который используется функцией rb_warn C.
# In baz.rb
def foo
warn("invalid call to foo", uplevel: 1)
end
def bar
foo
end
bar
<em>produces:</em>
baz.rb:6: warning: invalid call to foo Если передан ключевой аргумент category, передает категорию в Warning.warn. Переданная категория должна быть одной из следующих:
- :deprecated
-
Используется для предупреждений о устаревшей функциональности, которая может быть удалена в будущем.
- :experimental
-
Используется для экспериментальных функций, которые могут измениться в будущих выпусках.
# File kernel.rb, line 144
def yield_self
unless Primitive.block_given_p
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_obj_size)'
end
yield(self)
end Передает self в блок и возвращает результат блока.
"my string".yield_self {|s| s.upcase } #=> "MY STRING"
Хорошее использование then — это передача значений в цепочках методов:
require 'open-uri'
require 'json'
construct_url(arguments).
then {|url| URI(url).read }.
then {|response| JSON.parse(response) }
Методы частного экземпляра
# File ext/json/lib/json/common.rb, line 685
def JSON(object, *args)
if object.respond_to? :to_str
JSON.parse(object.to_str, args.first)
else
JSON.generate(object, args.first)
end
end Если object является строкой, разобрать строку и вернуть результат разбора в виде структуры данных Ruby. В противном случае, сгенерировать JSON текст из объекта структуры данных Ruby и вернуть его.
Аргумент opts передаётся для генерации/разбора соответственно. См. документацию по generate и parse.
# File lib/uri/common.rb, line 718
def URI(uri)
if uri.is_a?(URI::Generic)
uri
elsif uri = String.try_convert(uri)
URI.parse(uri)
else
raise ArgumentError,
"bad argument (expected URI object or URI string)"
end
end Возвращает uri, преобразованный в объект URI.
# File lib/rubygems/core_ext/kernel_gem.rb, line 41
def gem(gem_name, *requirements) # :doc:
skip_list = (ENV["GEM_SKIP"] || "").split(/:/)
raise Gem::LoadError, "skipping #{gem_name}" if skip_list.include? gem_name
if gem_name.kind_of? Gem::Dependency
unless Gem::Deprecate.skip
warn "#{Gem.location_of_caller.join ':'}:Warning: Kernel.gem no longer "\
"accepts a Gem::Dependency object, please pass the name "\
"and requirements directly"
end
requirements = gem_name.requirement
gem_name = gem_name.name
end
dep = Gem::Dependency.new(gem_name, *requirements)
loaded = Gem.loaded_specs[gem_name]
return false if loaded && dep.matches_spec?(loaded)
spec = dep.to_spec
if spec
if Gem::LOADED_SPECS_MUTEX.owned?
spec.activate
else
Gem::LOADED_SPECS_MUTEX.synchronize { spec.activate }
end
end
end Используйте Kernel#gem, чтобы активировать определённую версию gem_name.
requirements — это список требований к версии, которому должна соответствовать указанная драгоценность, чаще всего «= example.version.number». См. Gem::Requirement для того, как указать требование к версии.
Если вы будете активировать последнюю версию драгоценности, вам не нужно вызывать Kernel#gem, Kernel#require сделает всё правильно за вас.
Kernel#gem возвращает true, если драгоценность была активирована, иначе false. Если драгоценность не была найдена, не соответствует требованиям к версии или уже активирована другая версия, будет поднято исключение.
Kernel#gem следует вызывать до любых инструкций require (иначе RubyGems может загрузить конфликтную версию библиотеки).
Kernel#gem загружает предварительные версии только тогда, когда указаны предварительные requirements:
gem 'rake', '>= 1.1.a', '< 2'
В более старых версиях RubyGems переменная среды GEM_SKIP могла использоваться для пропуска активации указанных драгоценностей, например, для тестирования изменений, которые ещё не были установлены. Теперь RubyGems использует -I и переменную среды RUBYLIB для пропуска активации драгоценности.
Пример:
GEM_SKIP=libA:libB ruby -I../libA -I../libB ./mycode.rb
# File ext/json/lib/json/common.rb, line 663
def j(*objs)
objs.each do |obj|
puts JSON::generate(obj, :allow_nan => true, :max_nesting => false)
end
nil
end Выводит objs в стандартный вывод (STDOUT) как строки JSON в самой краткой форме, то есть в одной строке.
# File ext/json/lib/json/common.rb, line 672
def jj(*objs)
objs.each do |obj|
puts JSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false)
end
nil
end Выводит objs в стандартный вывод (STDOUT) как строки JSON в красивом формате с отступами и на нескольких строках.
# File lib/pp.rb, line 644
def pp(*objs)
objs.each {|obj|
PP.pp(obj)
}
objs.size <= 1 ? objs.first : objs
end выводит аргументы в красивом виде.
pp возвращает аргумент(ы).
# File ext/psych/lib/psych/y.rb, line 5 def y *objects puts Psych.dump_stream(*objects) end
Псевдоним для Psych.dump_stream, предназначенный для использования с IRB.
Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.