Триггер / флоп (он же f / f) - это оператор с отслеживанием состояния, происходящий из Perl.
Оператор f / f подразумевается в условных операторах (if и ternary) в ruby вместо диапазона, поэтому (1..5) - это диапазон, но (1..5)? 1: 5 - это п / ф. f / f имеет внутреннее состояние (истина / ложь) и состоит из двух условий. Он настраивается на ON (состояние становится истинным), когда его первое условие оценивается как истинное, и OFF, когда его второе условие оценивается как истинное. Разница между версиями с двумя и тремя точками заключается в том, что с двумя точками оценивается второе условие сразу после того, как первое оценивается как истинное, а с тремя точками - нет.
версия с двумя точками работает так:
A..B |
A -> false | State -> false
A -> true, B -> false | State -> true # notice how it checks both conditions
B -> false | State -> true
B -> true | State -> false
A -> false | State -> false
A -> true, B -> true | State -> false
сравните это с версией с тремя точками
A...B
A -> false | State -> false
A -> true | State -> true # three dotted version doesn't check second condition immediately
B -> false | State -> true
B -> true | State -> false
A -> false | State -> false
A -> true | State -> true
Давайте проследим за замечательной статьей о Perl, но с примерами на ruby.
Пример с двумя точками:
DATA.each_line do |line|
print "\t" if (line =~ /^start/ .. line =~ /^end/)
print line
end
__END__
First line.
start
Indented line
end
Back to left margin
Это печатает:
First line.
start
Indented line
end
Back to left margin
как вы можете видеть - f / f включается в строке 2 и выключается в строке 4. Однако в этом есть тонкость. Проверь это:
DATA.each_line do |line|
print "\t" if (line =~ /start/ .. line =~ /end/)
print line
end
__END__
First line.
Indent lines between the start and the end markers
Back to left margin
Это печатает:
First line.
Indent lines between the start and the end markers
Back to left margin
Там он включается на линии 2 и сразу выключается.
Представим, что вы не хотите проверять второй оператор сразу после первого. Здесь пригодятся трехточечные f / f. Посмотрите следующий пример.
DATA.each_line do |line|
print "\t" if (line =~ /start/ ... line =~ /end/)
print line
end
__END__
First line.
Indent lines between the start and the end markers
So this is indented,
and this is the end of the indented block.
Back to left margin
Какие отпечатки:
First line.
Indent lines between the start and the end markers
So this is indented,
and this is the end of the indented block.
Back to left margin
как вы можете видеть, он включается в строке 2 и выключается в строке 4
Теперь применим это к вашим примерам.
Я написал небольшой скрипт, чтобы проиллюстрировать его поведение
def mod(n, i)
result = i % n == 0
puts "#{i} mod #{n} => #{result}"
result
end
(11..20).each { |i|
if (mod(4, i))...(mod(3, i)) # NOTE it's a three dotted version
# NOTE that those puts show previous state, not the current one!
puts true
else
puts false
end
}
результат с двумя точками:
11 mod 4 => false
false
12 mod 4 => true
12 mod 3 => true # Notice how it checks both conditions here
true
13 mod 4 => false
false
14 mod 4 => false
false
15 mod 4 => false
false
16 mod 4 => true
16 mod 3 => false
true
17 mod 3 => false
true
18 mod 3 => true
true
19 mod 4 => false
false
20 mod 4 => true
20 mod 3 => false
true
результат с тремя точками:
11 mod 4 => false
false
12 mod 4 => true
true
13 mod 3 => false
true
14 mod 3 => false
true
15 mod 3 => true # turns OFF here
true
16 mod 4 => true # and turns immediately ON here
true
17 mod 3 => false
true
18 mod 3 => true
true
19 mod 4 => false
false
20 mod 4 => true
true
=> 11..20
P.S. Диапазон и триггер - это два совершенно разных оператора, и вы не должны путать их.
person
stefkin
schedule
03.08.2018