модуль 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в подоболочке. -
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 842
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 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равенfalse.
-
Вызывает исключение, если 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);
} Возвращает новый объект 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 212
def Float(arg, exception: true)
if Primitive.mandatory_only?
Primitive.rb_f_float1(arg)
else
Primitive.rb_f_float(arg, exception)
end
end Возвращает arg, преобразованный в float. Типы 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 305
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.
Для использования этого конструктора необходимо сначала загрузить расширение стандартной библиотеки 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);
} Возвращает рациональное число или 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);
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
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, описывающий связи переменных и методов в момент вызова. Этот объект может использоваться при вызове 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);
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_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('echo') # 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 вызывает исполняемый файл напрямую, без оболочки и без расширения оболочки:
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 указывают на успех и неудачу соответственно; значения целых чисел зависят от системы.
Без аргументов, вызывает исключение в $! или возбуждает RuntimeError, если $! равно nil. С одним аргументом, вызывает RuntimeError с указанной строкой в качестве сообщения. В противном случае, первый параметр должен быть классом Exception (или другим объектом, возвращающим объект Exception при отправке сообщения 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);
} Создаёт дочерний процесс.
При передаче блока, выполняет его в дочернем процессе; при выходе из блока дочерний процесс завершается со статусом ноль:
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 вызывается дважды:
-
Один раз в родительском процессе, возвращая pid дочернего процесса.
-
Один раз в дочернем процессе, возвращая
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
Возвращает статус замораживания 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();
} Возвращает массив имён глобальных переменных. Включает специальные глобальные переменные регулярных выражений, такие как $~ и $+, но не включает пронумерованные глобальные переменные регулярных выражений ($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 180
def loop
unless block_given?
return enum_for(:loop) { Float::INFINITY }
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 637 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);
} Без аргументов, вызывает исключение в $! или вызывает RuntimeError, если $! является nil. С одним аргументом String, вызывает RuntimeError с строкой в качестве сообщения. В противном случае, первый параметр должен быть классом Exception (или другим объектом, который возвращает объект Exception при отправке сообщения 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 задают параметры кодирования; см. Параметры кодирования.
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 представляет собой целочисленный интервал времени ожидания в секундах.
Метод отслеживает объекты IO, указанные во всех трех массивах, ожидая, пока некоторые из них не станут доступными; возвращает массив из 3 элементов, элементы которого:
-
Массив объектов в
read_ios, готовых для чтения. -
Массив объектов в
write_ios, готовых для записи. -
Массив объектов в
error_ios, у которых есть ожидаемые исключения.
Если ни один объект не станет доступным в течение заданного timeout, возвращается nil.
IO.select проверяет буфер объектов IO для проверки возможности чтения. Если буфер IO не пустой, IO.select немедленно сообщает о возможности чтения. Эта «проверка» происходит только для объектов IO. Она не происходит для объектов, подобных IO, таких как 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 предпочтительно для объектов типа IO, таких как 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('echo') # => 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 — это одно из следующих:
-
Путь к исполняемому файлу, который необходимо вызвать:
spawn('/usr/bin/date') # Path to date on Unix-style system. Process.waitВывод:
Thu Aug 31 10:06:48 AM CDT 2023
-
Массив из двух элементов, содержащий путь к исполняемому файлу и строку, используемую в качестве имени исполняемого процесса:
pid = spawn(['sleep', 'Hello!'], '1') # 2-element array. p `ps -p #{pid} -o command=`Вывод:
"Hello! 1\n"
Ruby вызывает исполняемый файл напрямую без оболочки и без расширения оболочки.
Если указан один или несколько 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. Возвращает предыдущее значение начального значения.
Если number опущено, задает начальное значение генератора, используя источник энтропии, предоставленный операционной системой (если доступен /dev/urandom в системах Unix или криптографический поставщик RSA в Windows), который затем комбинируется с временем, идентификатором процесса и порядковым номером.
srand может использоваться для обеспечения повторяемости последовательностей псевдослучайных чисел в разных запусках программы. Установкой начального значения в известное значение программы могут быть детерминированными во время тестирования.
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 _)
{
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('echo') # => 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('echo') # => 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 — это одно из следующих:
-
Путь к исполняемому файлу, который необходимо вызвать.
-
Массив из двух элементов, содержащий путь к исполняемому файлу и строку, используемую в качестве имени исполняемого процесса.
Пример:
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 вызывает исполняемый файл напрямую без оболочки и без расширения оболочки:
system('doesnt_exist') # => nil
Если указан один или несколько args, каждый из них является аргументом или опцией, передаваемыми исполняемому файлу:
system('echo', 'C*') # => true
system('echo', 'hello', 'world') # => true
Вывод:
C* hello world
Вызывает исключение, если новый процесс не смог выполнить команду.
# 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 (вторая таблица).
File тесты на одном файле:
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 129
def then
unless block_given?
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
Хороший пример использования then — передача значений в цепочках методов:
require 'open-uri'
require 'json'
construct_url(arguments).
then {|url| URI(url).read }.
then {|response| JSON.parse(response) }
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, ожидающего метки метка. Вызывает UncaughtThrowError , если для метки метка нет блока 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")
Результат:
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
-
Используется для экспериментальных функций, которые могут измениться в будущих выпусках.
# File kernel.rb, line 144
def yield_self
unless block_given?
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"
Приватные методы экземпляра
# File ext/json/lib/json/common.rb, line 679
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 842
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 — это список требований к версии, которым должна соответствовать указанная жемчужина, чаще всего «= 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 657
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 666
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 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 spec = Gem.find_unresolved_default_spec(path)
# 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, spec.name, Gem::Requirement.default_prerelease) unless
resolved_path
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 заменяется на собственную версию, которая способна загружать жемчужины по требованию.
Когда вы вызываете require 'x', происходит следующее:
-
Если файл можно загрузить из существующей Ruby-пути загрузки, он загружается.
-
В противном случае, ищутся установленные жемчужины, содержащие соответствующий файл. Если он найден в жемчужине ‘y’, эта жемчужина активируется (добавляется в путь загрузки).
Сохранена обычная 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–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.