модуль Kernel
Модуль 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: Выводит инспекцию заданных объектов в стандартный вывод. -
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`: Возвращает стандартный вывод выполнения
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 865
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, который может быть строкой URI или существующим объектом URI:
# Returns a new URI.
uri = URI('http://github.com/ruby/ruby')
# => #<URI::HTTP http://github.com/ruby/ruby>
# Returns the given URI.
URI(uri)
# => #<URI::HTTP http://github.com/ruby/ruby>
Исходный код
# File lib/pp.rb, line 692
def pp(*objs)
objs.each {|obj|
PP.pp(obj)
}
objs.size <= 1 ? objs.first : objs
end выводит аргументы в красивом формате.
pp возвращает аргумент(ы).
Публичные методы экземпляра
Исходный код
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;
StringValue(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);
rb_io_fptr_cleanup_all(fptr);
RB_GC_GUARD(port);
return result;
} Возвращает вывод $stdout от выполнения command в дочерней оболочке; устанавливает глобальную переменную $? в состояние процесса.
Этот метод может иметь потенциальные уязвимости в безопасности, если вызван с недоверенным вводом; см. Введение команд.
Примеры:
$ `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
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
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);
} Возвращает новый объект Complex, если аргументы допустимы; в противном случае генерирует исключение, если exception равно true; в противном случае возвращает nil.
С аргументами типа Numeric real и imag, возвращает Complex.rect(real, imag), если аргументы допустимы.
Со строковым аргументом s, возвращает новый объект Complex, если аргумент допустим; строка может содержать:
-
Одну или две числовые подстроки, каждая из которых задаёт значение
Complex,Float,Integer,NumericилиRational, задавая прямоугольные координаты:-
Числовые подстроки действительной и мнимой частей, разделённые знаком (с завершающим символом
'i'):Complex('1+2i') # => (1+2i) Complex('+1+2i') # => (1+2i) Complex('+1-2i') # => (1-2i) Complex('-1+2i') # => (-1+2i) Complex('-1-2i') # => (-1-2i) -
Только числовая строка действительной части (без завершающего символа
'i'):Complex('1') # => (1+0i) Complex('+1') # => (1+0i) Complex('-1') # => (-1+0i) -
Только числовая строка мнимой части (с завершающим символом
'i'):Complex('1i') # => (0+1i) Complex('+1i') # => (0+1i) Complex('-1i') # => (0-1i)
-
-
Действительная и мнимая рациональные подстроки, разделённые знаком «@», каждая из которых задаёт значение
Rational, задавая полярные координаты:Complex('1/2@3/4') # => (0.36584443443691045+0.34081938001166706i) Complex('+1/2@+3/4') # => (0.36584443443691045+0.34081938001166706i) Complex('+1/2@-3/4') # => (0.36584443443691045-0.34081938001166706i) Complex('-1/2@+3/4') # => (-0.36584443443691045-0.34081938001166706i) Complex('-1/2@-3/4') # => (-0.36584443443691045+0.34081938001166706i)
Исходный код
# File kernel.rb, line 193
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([]) # => {}
Исходный код
# File kernel.rb, line 286
def Integer(arg, base = 0, exception: true)
if Primitive.mandatory_only?
Primitive.rb_f_integer1(arg)
else
Primitive.rb_f_integer(arg, base, exception)
end
end Возвращает целое число, преобразованное из 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
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;
} Преобразует блок в объект 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);
} Регистрирует filename для загрузки (используя Kernel::require) в первый раз при обращении к const (которое может быть String или символом).
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" module C autoload(:D, "d") autoload?(:D) #=> "d" autoload?(:B) #=> nil end class E autoload(:F, "f") autoload?(:F) #=> "f" autoload?(:B) #=> "b" end
Исходный код
static VALUE
rb_f_binding(VALUE self)
{
return rb_binding_new();
} Возвращает объект Binding, описывающий привязки переменных и методов в точке вызова. Этот объект может быть использован при вызове Binding#eval для выполнения команды в этой среде или извлечения локальных переменных.
class User
def initialize(name, position)
@name = name
@position = position
end
def get_binding
binding
end
end
user = User.new('Joan', 'manager')
template = '{name: @name, position: @position}'
# evaluate template in context of the object
eval(template, user.get_binding)
#=> {:name=>"Joan", :position=>"manager"}
Binding#local_variable_get может быть использован для доступа к переменным, имена которых являются зарезервированными ключевыми словами Ruby:
# This is valid parameter declaration, but `if` parameter can't
# be accessed by name, because it is a reserved word.
def validate(field, validation, if: nil)
condition = binding.local_variable_get('if')
return unless condition
# ...Some implementation ...
end
validate(:name, :empty?, if: false) # skips validation
validate(:name, :empty?, if: true) # performs validation
Исходный код
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! :leaf 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);
StringValue(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_lineв оболочку. -
Вызывает исполняемый файл по адресу
exe_path.
Этот метод потенциально уязвим для атак типа «внедрение команд», если используется с ненадёжными данными; см. Внедрение команд.
Новый процесс создаётся с помощью системного вызова exec; он может унаследовать часть своей среды от вызывающей программы (включая, возможно, открытые дескрипторы файлов).
Аргумент env, если задан, представляет собой хеш, который влияет на ENV нового процесса; см. Среда выполнения.
Аргумент options — хеш с параметрами для нового процесса; см. Параметры выполнения.
Первый обязательный аргумент может быть одним из следующих:
-
command_lineесли это строка, начинающаяся с зарезервированного слова оболочки или специальной встроенной команды, или содержащая один или несколько метасимволов. -
exe_pathв противном случае.
Аргумент command_line
Строковый аргумент command_line представляет собой командную строку, которая передаётся оболочке; она должна начинаться с зарезервированного слова оболочки, специальной встроенной команды или содержать метасимволы:
exec('if true; then echo "Foo"; fi') # Shell reserved word.
exec('exit') # Built-in.
exec('date > date.tmp') # Contains meta character.
Командная строка также может содержать аргументы и параметры для команды:
exec('echo "Foo"')
Вывод:
Foo
Подробную информацию об оболочке см. в разделе Оболочка выполнения.
Выбрасывает исключение, если новый процесс не может быть запущен.
Аргумент exe_path
Аргумент exe_path может быть одним из следующих:
-
Путь к исполняемому файлу, который нужно вызвать.
-
Массив из двух элементов: путь к исполняемому файлу и строка, используемая в качестве имени выполняемого процесса.
Пример:
exec('/usr/bin/date')
Вывод:
Sat Aug 26 09:38:00 AM CDT 2023
Ruby вызывает исполняемый файл напрямую. Этот вариант не использует оболочку; см. Аргументы args для ограничений.
exec('doesnt_exist') # Raises Errno::ENOENT
Если задан один или несколько args, каждый из них — аргумент или параметр, передаваемый исполняемому файлу:
exec('echo', 'C*')
exec('echo', 'hello', 'world')
Вывод:
C* hello world
Выбрасывает исключение, если новый процесс не может быть запущен.
Исходный код
static VALUE
f_exit(int c, const VALUE *a, VALUE _)
{
rb_f_exit(c, a);
UNREACHABLE_RETURN(Qnil);
} Инициирует завершение скрипта Ruby, выбросив SystemExit; исключение может быть перехвачено. Возвращает код выхода status в операционную систему.
Значения 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 выполняет все процедуры при выходе (см. Kernel::at_exit) и все финализаторы объектов (см. ObjectSpace::define_finalizer).
Пример:
at_exit { puts 'In at_exit function.' }
ObjectSpace.define_finalizer('string', proc { puts 'In finalizer.' })
exit
Вывод:
In 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)
Значения true и false для аргумента status соответствуют, соответственно, успеху и ошибке; значения целочисленных кодов зависят от операционной системы.
Исходный код
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);
} Создаёт дочерний процесс.
Если задан блок, выполняет его в дочернем процессе; при выходе из блока дочерний процесс завершается с кодом 0:
puts "Before the fork: #{Process.pid}"
fork do
puts "In the child process: #{Process.pid}"
end # => 382141
puts "After the fork: #{Process.pid}"
Вывод:
Before the fork: 420496 After the fork: 420496 In the child process: 420520
Без блока вызов fork возвращается дважды:
-
В родительском процессе, возвращая идентификатор процесса дочернего процесса.
-
В дочернем процессе, возвращая
nil.
Пример:
puts "This is the first line before the fork (pid #{Process.pid})"
puts fork
puts "This is the second line after the fork (pid #{Process.pid})"
Вывод:
This is the first line before the fork (pid 420199) 420223 This is the second line after the fork (pid 420199) This is the second line after the fork (pid 420223)
В обоих случаях дочерний процесс может завершиться с помощью Kernel.exit!, чтобы избежать вызова Kernel#at_exit.
Для предотвращения процессов-зомби родительский процесс должен вызвать:
-
Process.wait, чтобы собрать коды завершения своих дочерних процессов. -
Process.detach, чтобы больше не интересоваться их статусом.
Поток, вызывающий fork, является единственным потоком в созданном дочернем процессе; fork не копирует другие потоки.
Обратите внимание, что метод fork доступен на некоторых платформах, но не на всех:
Process.respond_to?(:fork) # => true # Would be false on some.
В противном случае вы можете использовать ::spawn вместо fork.
Исходный код
# File kernel.rb, line 67 def frozen? Primitive.attr! :leaf Primitive.cexpr! 'rb_obj_frozen_p(self)' end
Возвращает статус замораживания объекта.
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();
} Возвращает массив имён глобальных переменных. Включает специальные глобальные переменные регулярных выражений, такие как $~ и $+, но не включает пронумерованные глобальные переменные регулярных выражений ($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? вместо этого.
Исходный код
Исходный код
static VALUE
rb_f_load(int argc, VALUE *argv, VALUE _)
{
VALUE fname, wrap, path, orig_fname;
rb_scan_args(argc, argv, "11", &fname, &wrap);
orig_fname = rb_get_path_check_to_string(fname);
fname = rb_str_encode_ospath(orig_fname);
RUBY_DTRACE_HOOK(LOAD_ENTRY, RSTRING_PTR(orig_fname));
path = rb_find_file(fname);
if (!path) {
if (!rb_file_load_ok(RSTRING_PTR(fname)))
load_failed(orig_fname);
path = fname;
}
rb_load_internal(path, wrap);
RUBY_DTRACE_HOOK(LOAD_RETURN, RSTRING_PTR(orig_fname));
return Qtrue;
} Загружает и выполняет 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]
Исходный код
# File kernel.rb, line 160
def loop
Primitive.attr! :inline_block
unless defined?(yield)
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_f_loop_size)'
end
begin
while true
yield
end
rescue StopIteration => e
e.result
end
end Повторно выполняет блок.
Если блок не указан, возвращается перечислитель.
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)) {
// TODO: when removed in 4.0, update command_injection.rdoc
rb_warn_deprecated_to_remove_at(4.0, "Calling Kernel#open with a leading '|'", "IO.popen");
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, подключённый к заданному файлу.
Этот метод может иметь уязвимости в области безопасности, если используется с ненадежным входом; см. Инъекция команд.
Без блока возвращается поток файла:
open('t.txt') # => #<File:t.txt>
С блоком, вызывается блок с открытым потоком файла, затем закрывается поток:
open('t.txt') {|f| p f } # => #<File:t.txt (closed)>
Вывод:
#<File:t.txt>
См. File.open для подробностей.
Исходный код
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]
Kernel#p предназначен для отладки. Реализации Ruby могут определить Kernel#p как не прерывимый целиком или частично. В CRuby, запись данных Kernel#p не прерывима.
Исходный код
# File lib/pp.rb, line 685 def pretty_inspect PP.pp(self, ''.dup) end
Возвращает красиво отформатированный объект в виде строки.
См. модуль PP для получения более подробной информации.
Исходный код
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);
} Эквивалентно 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);
} Вызывает исключение; см. Исключения.
Аргумент exception задаёт класс нового исключения; он должен быть классом Exception или одним из его подклассов (чаще всего, RuntimeError или StandardError), или экземпляром одного из этих классов:
begin raise(StandardError) rescue => x p x.class end # => StandardError
Аргумент message задаёт сохранённое сообщение в новом исключении, которое можно получить методом Exception#message; сообщение должно быть объектом, преобразуемым в строку string-convertible object или nil:
begin raise(StandardError, 'Boom') rescue => x p x.message end # => "Boom"
Если аргумент message не указан, сообщением является имя класса исключения.
См. Сообщения.
Аргумент backtrace может быть использован для изменения трассировки стека нового исключения, как сообщается Exception#backtrace и Exception#backtrace_locations; трассировка стека должна быть массивом Thread::Backtrace::Location, массивом строк, одиночной строкой или nil.
Использование массива Thread::Backtrace::Location экземпляров является наиболее согласованным вариантом и должно предпочтительно использоваться, когда это возможно. Необходимое значение можно получить из caller_locations или скопировать из Exception#backtrace_locations другой ошибки:
begin do_some_work() rescue ZeroDivisionError => ex raise(LogicalError, "You have an error in your math", ex.backtrace_locations) end
Способы, как Exception#backtrace и Exception#backtrace_locations поднятого исключения, устанавливаются в одну и ту же трассировку стека.
Когда желаемый стек расположений недоступен и должен быть построен заново, можно использовать массив строк или одиночную строку. В этом случае устанавливается только Exception#backtrace:
begin raise(StandardError, 'Boom', %w[dsl.rb:3 framework.rb:1]) rescue => ex p ex.backtrace # => ["dsl.rb:3", "framework.rb:1"] p ex.backtrace_locations # => nil end
Если аргумент backtrace не указан, трассировка стека устанавливается в соответствии с массивом Thread::Backtrace::Location объектов, полученных из стека вызовов.
См. Трассировки стека.
Ключевой аргумент cause устанавливает сохранённую причину в новом исключении, которую можно получить методом Exception#cause; причина должна быть объектом исключения (Exception или одним из его подклассов) или nil:
begin raise(StandardError, cause: RuntimeError.new) rescue => x p x.cause end # => #<RuntimeError: RuntimeError>
Если ключевой аргумент cause не указан, причина - это значение $!.
См. Причина.
В альтернативном порядке вызова, где аргумент exception не указан, поднимается новое исключение класса, заданного $!, или класса RuntimeError, если $! является nil:
begin raise rescue => x p x end # => RuntimeError
Если аргумент exception не указан, аргумент message и ключевой аргумент cause могут быть указаны, но аргумент backtrace не может быть указан.
Исходный код
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 задают параметры кодирования; см. Параметры кодирования.
Исходный код
VALUE
rb_f_require_relative(VALUE obj, VALUE fname)
{
VALUE base = rb_current_realfilepath();
if (NIL_P(base)) {
rb_loaderror("cannot infer basepath");
}
base = rb_file_dirname(base);
return rb_require_string_internal(rb_file_absolute_path(fname, base), false);
} Ruby пытается загрузить библиотеку с именем string относительно каталога, содержащего требуемый файл. Если файл не существует, генерируется исключение 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, pipe, сокет, когда несколько процессов считывают данные из потока.
Наконец, разработчики ядра 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;
} Устанавливает proc в качестве обработчика трассировки или отключает трассировку, если параметр равен nil.
Примечание: этот метод устарел, используйте TracePoint вместо него.
proc принимает до шести параметров:
-
строка с именем события
-
строка с именем файла
-
номер строки
-
символ с именем метода или nil
-
связка или nil
-
класс, модуль или nil
proc вызывается всякий раз, когда происходит событие.
События:
"c-call"-
вызов C-функции
"c-return"-
возвращение из C-функции
"call"-
вызов метода Ruby
"class"-
начало определения класса или модуля
"end"-
окончание определения класса или модуля
"line"-
выполнение кода в новой строке
"raise"-
вызов исключения
"return"-
возвращение из метода Ruby
Трассировка отключается в контексте proc.
class Test
def test
a = 1
b = 2
end
end
set_trace_func proc { |event, file, line, id, binding, class_or_module|
printf "%8s %s:%-2d %16p %14p\n", event, file, line, id, class_or_module
}
t = Test.new
t.test
Результат:
c-return prog.rb:8 :set_trace_func Kernel
line prog.rb:11 nil nil
c-call prog.rb:11 :new Class
c-call prog.rb:11 :initialize BasicObject
c-return prog.rb:11 :initialize BasicObject
c-return prog.rb:11 :new Class
line prog.rb:12 nil nil
call prog.rb:2 :test Test
line prog.rb:3 :test Test
line prog.rb:4 :test Test
return prog.rb:5 :test Test Исходный код
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 || (argc == 1 && NIL_P(argv[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);
} Приостанавливает выполнение текущей нити на количество секунд, указанное числовым аргументом secs, или навсегда, если secs равно nil; возвращает целое число приостановленных секунд (округлённое).
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
} Создаёт новый дочерний процесс, выполняя одно из следующих действий в этом процессе:
-
Передаёт строку
command_lineв оболочку. -
Вызывает исполняемый файл по пути
exe_path.
Этот метод имеет потенциальные уязвимости в области безопасности, если используется с ненадежным вводом; см. Внедрение команд.
Возвращает идентификатор процесса (pid) нового процесса, не ожидая его завершения.
Для предотвращения «зомби-процессов» родительский процесс должен вызвать либо:
-
Process.wait, чтобы собрать статусы завершения своих дочерних процессов. -
Process.detach, чтобы не интересоваться их статусом.
Новый процесс создаётся с помощью системного вызова exec; он может унаследовать часть своей среды из вызывающей программы (включая открытые дескрипторы файлов).
Аргумент env, если задан, — это хеш, который влияет на ENV для нового процесса; см. Среда выполнения.
Аргумент options — это хеш опций для нового процесса; см. Опции выполнения.
Первый обязательный аргумент — один из следующих:
-
command_lineесли это строка, и если она начинается с зарезервированного слова оболочки или специального встроенного, или если она содержит один или несколько метасимволов. -
exe_pathв противном случае.
Аргумент command_line
Строковый аргумент command_line — это командная строка, которая должна быть передана оболочке; она должна начинаться с зарезервированного слова оболочки, начинаться со специального встроенного или содержать метасимволы:
spawn('if true; then echo "Foo"; fi') # => 798847 # Shell reserved word.
Process.wait # => 798847
spawn('exit') # => 798848 # Built-in.
Process.wait # => 798848
spawn('date > /tmp/date.tmp') # => 798879 # Contains meta character.
Process.wait # => 798849
spawn('date > /nop/date.tmp') # => 798882 # Issues error message.
Process.wait # => 798882
Командная строка также может содержать аргументы и параметры для команды:
spawn('echo "Foo"') # => 799031
Process.wait # => 799031
Вывод:
Foo
См. Оболочка выполнения для получения подробной информации об оболочке.
Вызывает исключение, если новый процесс не смог выполнить задачу.
Аргумент exe_path
Аргумент exe_path — один из следующих:
-
Путь к исполняемому файлу, который нужно вызвать.
-
Массив из 2 элементов, содержащий путь к вызываемому исполняемому файлу и строку, которая будет использоваться как имя выполняемого процесса.
spawn('/usr/bin/date') # Path to date on Unix-style system. Process.waitВывод:
Mon Aug 28 11:43:10 AM CDT 2023
Ruby вызывает исполняемый файл напрямую. Этот вариант не использует оболочку; см. Аргументы args для замечаний.
Если задан один или несколько args, каждый из них — аргумент или опция, которые нужно передать исполняемому файлу:
spawn('echo', 'C*') # => 799392
Process.wait # => 799392
spawn('echo', 'hello', 'world') # => 799393
Process.wait # => 799393
Вывод:
C* hello world
Вызывает исключение, если новый процесс не смог выполнить задачу.
Исходный код
static VALUE
f_sprintf(int c, const VALUE *v, VALUE _)
{
return rb_f_sprintf(c, v);
} Возвращает строку, полученную в результате форматирования objects в format_string.
Для получения подробной информации о format_string, см. Спецификации формата.
Исходный код
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)) {
StringValue(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 _)
{
rb_thread_t *th = GET_THREAD();
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;
last_status_clear(th);
// 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 = rb_check_typeddata(status, &rb_process_status_type);
// Set the last status:
rb_obj_freeze(status);
th->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_lineв оболочку. -
Вызывает исполняемый файл по адресу
exe_path.
Этот метод имеет потенциальные уязвимости для безопасности, если вызывается с недоверенными данными; см. Внедрение команд.
Возвращает:
-
trueесли команда завершилась со статусом ноль. -
falseесли выходной статус — ненулевое целое число. -
nilесли команда не смогла выполниться.
Вызывает исключение (вместо возвращения false или nil) если ключевой аргумент exception установлен в true.
Присваивает код ошибки команды $?.
Новый процесс создается с помощью системного вызова system; он может унаследовать часть своей среды от вызывающей программы (возможно, включая открытые дескрипторы файлов).
Аргумент env, если задан, — это хеш, влияющий на ENV для нового процесса; см. Среда выполнения.
Аргумент options — это хеш параметров для нового процесса; см. Параметры выполнения.
Первый обязательный аргумент — это одно из следующего:
-
command_lineесли это строка, и если она начинается со служебного слова оболочки или специального встроенного кода, или если она содержит один или несколько метасимволов. -
exe_pathв противном случае.
Аргумент command_line
Строковый аргумент command_line — это командная строка, которая будет передана оболочке; она должна начинаться со служебного слова оболочки, начинаться со специального встроенного кода или содержать метасимволы:
system('if true; then echo "Foo"; fi') # => true # Shell reserved word.
system('exit') # => true # Built-in.
system('date > /tmp/date.tmp') # => true # Contains meta character.
system('date > /nop/date.tmp') # => false
system('date > /nop/date.tmp', exception: true) # Raises RuntimeError.
Присваивает код ошибки команды $?:
system('exit') # => true # Built-in.
$? # => #<Process::Status: pid 640610 exit 0>
system('date > /nop/date.tmp') # => false
$? # => #<Process::Status: pid 640742 exit 2>
Командная строка также может содержать аргументы и параметры для команды:
system('echo "Foo"') # => true
Вывод:
Foo
Подробности об оболочке см. в Оболочке выполнения.
Вызывает исключение, если новый процесс не смог выполниться.
Аргумент exe_path
Аргумент exe_path — это одно из следующего:
-
Путь к исполняемому файлу, который должен быть вызван.
-
Массив из 2 элементов, содержащий путь к исполняемому файлу и строку, которая будет использоваться в качестве имени исполняемого процесса.
Пример:
system('/usr/bin/date') # => true # Path to date on Unix-style system.
system('foo') # => nil # Command failed.
Вывод:
Mon Aug 28 11:43:10 AM CDT 2023
Присваивает код ошибки команды $?:
system('/usr/bin/date') # => true
$? # => #<Process::Status: pid 645605 exit 0>
system('foo') # => nil
$? # => #<Process::Status: pid 645608 exit 127>
Ruby вызывает исполняемый файл напрямую. Этот вариант не использует оболочку; см. Аргументы args для предостережений.
system('doesnt_exist') # => nil
Если задан один или несколько args, каждый из них — аргумент или параметр, передаваемый исполняемому файлу:
system('echo', 'C*') # => true
system('echo', 'hello', 'world') # => true
Вывод:
C* hello world
Вызывает исключение, если новый процесс не смог выполниться.
Исходный код
# File kernel.rb, line 89 def tap Primitive.attr! :inline_block 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);
} Выполняет тест для одного или обоих объектов файловой системы по указанным путям path0 и path1:
-
Каждый путь
path0илиpath1указывает на файл, каталог, устройство, канал и т. д. -
Символ
charвыбирает конкретный тест.
Тесты:
-
Каждый из этих тестов работает только с объектом по пути
path0, и возвращаетtrueилиfalse; для несуществующего объекта возвращаетfalse(не вызывает исключение):Символ Тест 'b'Является ли объект блочным устройством. 'c'Является ли объект символьным устройством. 'd'Является ли объект каталогом. 'e'Существует ли объект. 'f'Является ли объект существующим обычным файлом. 'g'Установлен ли бит setgid для объекта. 'G'Соответствует ли группа владельца объекта группе вызывающего. 'k'Установлен ли бит sticky для объекта. 'l'Является ли объект символической ссылкой. 'o'Принадлежит ли объект эффективному идентификатору пользователя вызывающего. 'O'Как 'o', но использует реальный идентификатор пользователя (а не эффективный).'p'Является ли объект FIFO-устройством (именованным каналом). 'r'Доступен ли объект для чтения эффективным идентификатором пользователя/группы вызывающего. 'R'Как 'r', но использует реальный идентификатор пользователя/группы (а не эффективный).'S'Является ли объект сокетом. 'u'Установлен ли бит setuid для объекта. 'w'Доступен ли объект для записи эффективным идентификатором пользователя/группы вызывающего. 'W'Как 'w', но использует реальный идентификатор пользователя/группы (а не эффективный).'x'Доступен ли объект для выполнения эффективным идентификатором пользователя/группы вызывающего. 'X'Как 'x', но использует реальный идентификатор пользователя/группы (а не эффективный).'z'Существует ли объект нулевой длины. -
Этот тест работает только с объектом по пути
path0, и возвращает целочисленный размер илиnil:Символ Тест 's'Возвращает положительный целочисленный размер, если объект существует и имеет ненулевую длину, nilв противном случае. -
Каждый из этих тестов работает только с объектом по пути
path0, и возвращает объектTime; вызывает исключение, если объекта не существует:Символ Тест 'A'Время последнего доступа к объекту. 'C'Время последнего изменения объекта. 'M'Время последней модификации объекта. -
Каждый из этих тестов работает со временем последней модификации (
mtime) каждого из объектов по путямpath0иpath1, и возвращаетtrueилиfalse; возвращаетfalseесли какой-либо из объектов не существует:Символ Тест '<'Является ли 'mtime` в `path0` меньше, чем в `path1`. '='Равны ли 'mtime` в `path0` и `path1`. '>'Является ли 'mtime` в `path0` больше, чем в `path1`. -
Этот тест работает с содержимым каждого из объектов по путям
path0иpath1, и возвращаетtrueилиfalse; возвращаетfalseесли какой-либо из объектов не существует:Символ Тест '-'Существуют ли объекты и идентичны ли они.
Исходный код
# File kernel.rb, line 121
def then
Primitive.attr! :inline_block
unless defined?(yield)
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, если нет catch блока для tag. Необязательный второй параметр предоставляет возвращаемое значение для 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 получает новое значение переменной в качестве параметра. См. также 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 52
def warn(*msgs, uplevel: nil, category: nil)
if Primitive.cexpr!("NIL_P(category)")
Primitive.rb_warn_m(msgs, uplevel, nil)
elsif Warning[category = Primitive.cexpr!("rb_to_symbol_type(category)")]
Primitive.rb_warn_m(msgs, uplevel, category)
end
end Если предупреждения отключены (например, с помощью флага -W0), ничего не делает. В противном случае преобразует каждое сообщение в строку, добавляет символ новой строки к строке, если она не заканчивается символом новой строки, и вызывает Warning.warn со строкой.
warn("warning 1", "warning 2")
выводит:
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
выводит:
baz.rb:6: warning: invalid call to foo
Если передан ключевой аргумент category, передаётся категория в Warning.warn. Переданная категория должна быть одной из следующих:
- :deprecated
-
Используется для предупреждения об устаревшей функциональности, которая может быть удалена в будущем.
- :experimental
-
Используется для экспериментальных функций, которые могут измениться в будущих выпусках.
- :performance
-
Используется для предупреждения об API или шаблонах, имеющих негативное влияние на производительность.
Приватные методы экземпляров
Исходный код
# File ext/json/lib/json/common.rb, line 873
def JSON(object, *args)
if object.is_a?(String)
return JSON.parse(object, args.first)
elsif object.respond_to?(:to_str)
str = object.to_str
if str.is_a?(String)
return JSON.parse(object.to_str, args.first)
end
end
JSON.generate(object, args.first)
end Если object является строкой, разобрать строку и вернуть результат разбора в виде структуры данных Ruby. В противном случае сгенерировать JSON текст из структуры данных Ruby и вернуть его.
Аргумент opts передаётся в функцию генерации/разбора соответственно. См. документацию по функциям generate и parse.
Исходный код
# File lib/uri/common.rb, line 865
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, который может быть строкой URI или существующим объектом URI:
# Returns a new URI.
uri = URI('http://github.com/ruby/ruby')
# => #<URI::HTTP http://github.com/ruby/ruby>
# Returns the given URI.
URI(uri)
# => #<URI::HTTP http://github.com/ruby/ruby>
Исходный код
# File lib/rubygems/core_ext/kernel_gem.rb, line 35
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.is_a? 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 — это список требований к версии, которым должен соответствовать указанный gem, чаще всего «= example.version.number». См. Gem::Requirement для того, как указать требование к версии.
Если вы будете активировать последнюю версию gem, нет необходимости вызывать Kernel#gem, Kernel#require сделает это за вас.
Kernel#gem возвращает true, если gem был активирован, в противном случае false. Если gem не был найден, не соответствовал требованиям к версии или уже была активирована другая версия, будет вызвано исключение.
Kernel#gem следует вызывать перед любыми операторами require (иначе RubyGems может загрузить конфликтную версию библиотеки).
Kernel#gem загружает предварительные версии только тогда, когда указаны предварительные requirements:
gem 'rake', '>= 1.1.a', '< 2'
В более старых версиях RubyGems переменная окружения GEM_SKIP могла использоваться для пропуска активации указанных gem, например, для тестирования изменений, которые ещё не были установлены. Теперь RubyGems делегирует это -I и переменной среды RUBYLIB для пропуска активации gem.
Пример:
GEM_SKIP=libA:libB ruby -I../libA -I../libB ./mycode.rb
Исходный код
# File ext/json/lib/json/common.rb, line 851
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 860
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 692
def pp(*objs)
objs.each {|obj|
PP.pp(obj)
}
objs.size <= 1 ? objs.first : objs
end Выводит аргументы в красивом формате.
pp возвращает аргумент(ы).
Исходный код
# File lib/rubygems/core_ext/kernel_require.rb, line 36
def require(path) # :doc:
return gem_original_require(path) unless Gem.discover_gems_on_require
RUBYGEMS_ACTIVATION_MONITOR.synchronize do
path = File.path(path)
# If +path+ belongs to a default gem, we activate it and then go straight
# to normal require
if spec = Gem.find_default_spec(path)
name = spec.name
next if Gem.loaded_specs[name]
# Ensure -I beats a default gem
resolved_path = begin
rp = nil
load_path_check_index = Gem.load_path_insert_index - Gem.activated_gem_paths
Gem.suffixes.find do |s|
$LOAD_PATH[0...load_path_check_index].find do |lp|
if File.symlink? lp # for backward compatibility
next
end
full_path = File.expand_path(File.join(lp, "#{path}#{s}"))
rp = full_path if File.file?(full_path)
end
end
rp
end
Kernel.send(:gem, name, Gem::Requirement.default_prerelease) unless
resolved_path
next
end
# If there are no unresolved deps, then we can use just try
# normal require handle loading a gem from the rescue below.
if Gem::Specification.unresolved_deps.empty?
next
end
# If +path+ is for a gem that has already been loaded, don't
# bother trying to find it in an unresolved gem, just go straight
# to normal require.
#--
# TODO request access to the C implementation of this to speed up RubyGems
if Gem::Specification.find_active_stub_by_path(path)
next
end
# Attempt to find +path+ in any unresolved gems...
found_specs = Gem::Specification.find_in_unresolved path
# If there are no directly unresolved gems, then try and find +path+
# in any gems that are available via the currently unresolved gems.
# For example, given:
#
# a => b => c => d
#
# If a and b are currently active with c being unresolved and d.rb is
# requested, then find_in_unresolved_tree will find d.rb in d because
# it's a dependency of c.
#
if found_specs.empty?
found_specs = Gem::Specification.find_in_unresolved_tree path
found_specs.each(&:activate)
# We found +path+ directly in an unresolved gem. Now we figure out, of
# the possible found specs, which one we should activate.
else
# Check that all the found specs are just different
# versions of the same gem
names = found_specs.map(&:name).uniq
if names.size > 1
raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ", "}"
end
# Ok, now find a gem that has no conflicts, starting
# at the highest version.
valid = found_specs.find {|s| !s.has_conflicts? }
unless valid
le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate"
le.name = names.first
raise le
end
valid.activate
end
end
begin
gem_original_require(path)
rescue LoadError => load_error
if load_error.path == path &&
RUBYGEMS_ACTIVATION_MONITOR.synchronize { Gem.try_activate(path) }
return gem_original_require(path)
end
raise load_error
end
end При использовании RubyGems, Kernel#require заменяется собственным методом, способным загружать gems по требованию.
Когда вы вызываете require 'x', происходит следующее:
-
Если файл можно загрузить из существующей загрузки Ruby, он загружается.
-
В противном случае ищутся установленные gems с файлом, который соответствует. Если он найден в gem ‘y’, этот gem активируется (добавляется в загрузку).
Сохраняется обычная функциональность require возвращать false, если этот файл уже был загружен.
Исходный код
# 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–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.