Ruby Language
제어 흐름
수색…
if, elsif, else 및 end
루비는 end
키워드로 종료되는 브랜칭 로직에 대해 예상되는 if
및 else
표현식을 제공합니다.
# Simulate flipping a coin
result = [:heads, :tails].sample
if result == :heads
puts 'The coin-toss came up "heads"'
else
puts 'The coin-toss came up "tails"'
end
Ruby에서 if
문은 값으로 평가되는 표현식이며 그 결과를 변수에 할당 할 수 있습니다.
status = if age < 18
:minor
else
:adult
end
Ruby는 또한 다음과 같이 표현할 수있는 C 스타일의 삼항 연산자 ( 자세한 내용은 여기 참조 )를 제공합니다.
some_statement ? if_true : if_false
이것은 if-else를 사용하여 위의 예를 다음과 같이 작성할 수 있음을 의미합니다.
status = age < 18 ? :minor : :adult
또한 Ruby는 추가 브랜칭 논리를 가능하게하는 표현식을 허용하는 elsif
키워드를 제공합니다.
label = if shirt_size == :s
'small'
elsif shirt_size == :m
'medium'
elsif shirt_size == :l
'large'
else
'unknown size'
end
의 조건 중 어느 것도 경우 if
/ elsif
체인에 해당 없으며이없는 else
절은 다음 식을 전무로 평가합니다. 이것은 nil.to_s
가 빈 문자열이기 때문에 문자열 보간에서 유용 할 수 있습니다 :
"user#{'s' if @users.size != 1}"
진실과 거짓 가치
Ruby에는 "거짓"으로 간주되는 두 개의 값이 있으며 if
표현식의 조건으로 테스트 할 때 false를 반환합니다. 그들은:
-
nil
- 부울
false
다른 모든 값은 다음을 포함하여 "사실"로 간주됩니다.
-
0
- 숫자 0 (정수 또는 기타) -
""
- 빈 문자열 -
"\n"
- 공백 만 포함하는 문자열 -
[]
- 빈 배열 -
{}
- 빈 해시
다음 코드를 예로 들어 보겠습니다.
def check_truthy(var_name, var)
is_truthy = var ? "truthy" : "falsy"
puts "#{var_name} is #{is_truthy}"
end
check_truthy("false", false)
check_truthy("nil", nil)
check_truthy("0", 0)
check_truthy("empty string", "")
check_truthy("\\n", "\n")
check_truthy("empty array", [])
check_truthy("empty hash", {})
출력 :
false is falsy
nil is falsy
0 is truthy
empty string is truthy
\n is truthy
empty array is truthy
empty hash is truthy
동안,까지
while
루프는 주어진 조건이 충족되는 동안 블록을 실행합니다 :
i = 0
while i < 5
puts "Iteration ##{i}"
i +=1
end
until
루프는 조건부가 거짓 인 동안 블록을 실행합니다.
i = 0
until i == 5
puts "Iteration ##{i}"
i +=1
end
인라인 if / unless
일반적인 패턴은 인라인 또는 후행를 사용하는 것입니다, if
또는 unless
:
puts "x is less than 5" if x < 5
이는 조건부 수정 자로 알려져 있으며 간단한 가드 코드와 초기 리턴 값을 추가하는 편리한 방법입니다.
def save_to_file(data, filename)
raise "no filename given" if filename.empty?
return false unless data.valid?
File.write(filename, data)
end
이러한 변경자에 else
절을 추가 할 수 없습니다. 또한 일반적으로 주 논리 내부에서 조건부 수정자를 사용하지 않는 것이 좋습니다. 복잡한 코드의 if
일반 if
, elsif
, else
대신 사용해야합니다.
~ 않는 한
일반적인 진술은 if !(some condition)
입니다. Ruby는 unless
문 대신 사용할 수 있습니다.
조건이 음수 인 if
를 제외하고는 구조가 if
문과 완전히 동일합니다. 또한, unless
문은 elsif
지원하지 않지만 else
지원 else
.
# Prints not inclusive
unless 'hellow'.include?('all')
puts 'not inclusive'
end
사례 발표문
Ruby는 switch 문에 case
키워드를 사용합니다.
case 문은
case
의 인수 위치에있는 선택적 조건과 절이없는 0 개 이상의when
절로 구성됩니다. 조건과 일치하는 첫 번째when
절 (조건이 null 인 경우 Boolean 진리로 평가)이 "wins"되고 해당 코드 스탠자가 실행됩니다. case 문의 값은 성공적인when
절의 값이거나 해당 절이 없으면nil
입니다.case 문은
else
절로 끝날 수 있습니다. 명령문이 쉼표로 구분 된 여러 후보 값을 가질 수있는 각각의when
.
예:
case x
when 1,2,3
puts "1, 2, or 3"
when 10
puts "10"
else
puts "Some other number"
end
짧은 버전 :
case x
when 1,2,3 then puts "1, 2, or 3"
when 10 then puts "10"
else puts "Some other number"
end
case
절의 값은 ===
method ( ==
아닌)를 사용하여 각 when
절과 일치합니다. 따라서 다양한 유형의 객체와 함께 사용할 수 있습니다.
Ranges에서는 case
문을 사용할 수 있습니다.
case 17
when 13..19
puts "teenager"
end
case
문은 Regexp 와 함께 사용할 수 있습니다.
case "google"
when /oo/
puts "word contains oo"
end
case
문은 Proc 또는 lambda와 함께 사용할 수 있습니다.
case 44
when -> (n) { n.even? or n < 0 }
puts "even or less than zero"
end
case
문은 클래스 와 함께 사용할 수 있습니다.
case x
when Integer
puts "It's an integer"
when String
puts "It's a string"
end
===
메서드를 구현하면 자신 만의 일치 클래스를 만들 수 있습니다.
class Empty
def self.===(object)
!object or "" == object
end
end
case ""
when Empty
puts "name was empty"
else
puts "name is not empty"
end
case
문은 다음 값과 일치하는 값없이 사용할 수 있습니다.
case
when ENV['A'] == 'Y'
puts 'A'
when ENV['B'] == 'Y'
puts 'B'
else
puts 'Neither A nor B'
end
case
문에는 값이 있으므로 메서드 인수 또는 할당에 사용할 수 있습니다.
description = case 16
when 13..19 then "teenager"
else ""
end
break, next 및 redo로 루프 제어
Ruby 블록의 실행 흐름은 break
, next
및 redo
문을 사용하여 제어 할 수 있습니다.
break
break
문은 블록을 즉시 종료합니다. 블록의 나머지 명령은 건너 뛰고 반복이 종료됩니다.
actions = %w(run jump swim exit macarena)
index = 0
while index < actions.length
action = actions[index]
break if action == "exit"
index += 1
puts "Currently doing this action: #{action}"
end
# Currently doing this action: run
# Currently doing this action: jump
# Currently doing this action: swim
next
next
명령문은 블록의 맨 위로 즉시 돌아가고 다음 반복으로 진행됩니다. 블록의 나머지 명령은 건너 뜁니다.
actions = %w(run jump swim rest macarena)
index = 0
while index < actions.length
action = actions[index]
index += 1
next if action == "rest"
puts "Currently doing this action: #{action}"
end
# Currently doing this action: run
# Currently doing this action: jump
# Currently doing this action: swim
# Currently doing this action: macarena
redo
redo
문은 블록의 맨 위로 즉시 돌아가고 동일한 반복을 다시 시도합니다. 블록의 나머지 명령은 건너 뜁니다.
actions = %w(run jump swim sleep macarena)
index = 0
repeat_count = 0
while index < actions.length
action = actions[index]
puts "Currently doing this action: #{action}"
if action == "sleep"
repeat_count += 1
redo if repeat_count < 3
end
index += 1
end
# Currently doing this action: run
# Currently doing this action: jump
# Currently doing this action: swim
# Currently doing this action: sleep
# Currently doing this action: sleep
# Currently doing this action: sleep
# Currently doing this action: macarena
Enumerable
반복
루프 외에도 다음 문은 each
및 map
과 같은 Enumerable 반복 메서드와 함께 작동 map
.
[1, 2, 3].each do |item|
next if item.even?
puts "Item: #{item}"
end
# Item: 1
# Item: 3
결과 값 차단
break
와 next
문 모두에서 값이 제공 될 수 있으며 블록 결과 값으로 사용됩니다.
even_value = for value in [1, 2, 3]
break value if value.even?
end
puts "The first even value is: #{even_value}"
# The first even value is: 2
던지다, 잡다
다른 많은 프로그래밍 언어와 달리 throw
키워드와 catch
키워드는 Ruby의 예외 처리와 관련이 없습니다.
Ruby에서는 다른 언어의 레이블처럼 throw
와 catch
가 조금 다릅니다. 그것들은 제어 흐름을 변경하는 데 사용되지만 예외와 같은 "오류"개념과는 관련이 없습니다.
catch(:out) do
catch(:nested) do
puts "nested"
end
puts "before"
throw :out
puts "will not be executed"
end
puts "after"
# prints "nested", "before", "after"
논리 문장으로 제어 흐름
반 직관적 인 것처럼 보이지만 논리적 연산자를 사용하여 명령문 실행 여부를 결정할 수 있습니다. 예를 들면 :
File.exist?(filename) or STDERR.puts "#{filename} does not exist!"
그러면 파일이 있는지 확인하고 오류 메시지 만 인쇄합니다. or
문은 게으르다. 즉 값이 참인지 거짓인지를 한 번 확인하면 실행이 중지된다. 첫 번째 용어가 사실대로 발견되자 마자 다른 용어의 가치를 확인할 필요가 없습니다. 그러나 첫 번째 용어가 틀린 경우 두 번째 용어를 검사해야합니다.
일반적인 사용은 기본값을 설정하는 것입니다.
glass = glass or 'full' # Optimist!
glass
의 값을 아직 설정하지 않은 경우 'full'로 설정합니다. 보다 간결하게, or
의 상징적 인 버전을 사용할 수 있습니다 :
glass ||= 'empty' # Pessimist.
첫 번째 문이 false 인 경우에만 두 번째 문을 실행할 수도 있습니다.
File.exist?(filename) and puts "#{filename} found!"
또 다시, and
게으르다 그래서 필요하다면 값에 도달하는 두 번째 명령문 만 실행합니다.
or
연산자는 and
보다 낮은 우선 순위를가집니다. 마찬가지로, ||
&&
보다 우선 순위가 낮습니다. 기호 양식은 단어 양식보다 우선 순위가 높습니다. 이 기법을 언제 할당 할 것인지를 알기 편리합니다.
a = 1 and b = 2
#=> a==1
#=> b==2
a = 1 && b = 2; puts a, b
#=> a==2
#=> b==2
and
andor
키워드는 금지되어 있습니다. 최소한의 가독성은 미묘한 버그를 일으킬 가능성이 크지 않습니다. 부울 표현식의 경우 항상&&
및||
대신. 흐름 제어의if
및unless
사용if
.&&
및||
또한 수용 가능하지만 덜 명확하다.
시작, 끝내다
begin
블록은 여러 명령문을 그룹화하는 제어 구조입니다.
begin
a = 7
b = 6
a * b
end
begin
블록은 블록의 마지막 명령문 값을 반환합니다. 다음 예제에서는 3
을 반환합니다.
begin
1
2
3
end
begin
블록은 결과를 리턴하는 데 여러 개의 명령문이 필요할 수있는 ||=
연산자를 사용하는 조건부 지정에 유용합니다.
circumference ||=
begin
radius = 7
tau = Math::PI * 2
tau * radius
end
또한 같은 다른 블록 구조와 결합 될 수있는 rescue
, ensure
, while
, if
, unless
등의 프로그램 흐름의 큰 제어를 제공한다.
Begin
블록은 { ... }
또는 do ... end
와 같은 코드 블록이 아닙니다. 함수에 전달할 수 없습니다.
return vs. next : 블록 내 비 로컬 반환
이 깨진 스 니펫을 고려해보십시오.
def foo
bar = [1, 2, 3, 4].map do |x|
return 0 if x.even?
x
end
puts 'baz'
bar
end
foo # => 0
블록 결과의 map
배열에 대한 값을 return
하기 위해 return
을 기대할 수 있습니다. 따라서 foo
의 반환 값은 [1, 0, 3, 0]
됩니다. 대신, return
은 foo
메소드의 값을 return
합니다 . baz
가 인쇄되지 않았으므로 실행이 해당 행에 도달하지 않았다는 것을 의미합니다.
next
으로 가치있는 트릭을합니다. 블록 레벨 return
합니다.
def foo
bar = [1, 2, 3, 4].map do |x|
next 0 if x.even?
x
end
puts 'baz'
bar
end
foo # baz
# => [1, 0, 3, 0]
return
이 없으면 블록에 의해 반환 된 값은 마지막 표현식의 값입니다.
등가 / 조건부 대입 연산자 (|| =)
Ruby에는 변수가 nil
또는 false
평가되는 경우에만 변수에 값을 할당 할 수있는 등호 연산자가 있습니다.
||= # this is the operator that achieves this.
또는 값을 지정하는 등호 기호를 나타내는이 연산자. 다음과 같이 표현할 수 있습니다.
x = x || y
위의 예는 정확하지 않습니다. 등호 연산자는 실제로 이것을 나타냅니다.
x || x = y
경우 x
평가 nil
또는 false
후 x
값이 할당되는 y
, 그렇지 않으면 변경되지.
다음은 or-equals 연산자의 실제 사용 사례입니다. 사용자에게 전자 메일을 보낼 코드 부분이 있다고 가정 해보십시오. 어떤 이유로이 사용자에게 이메일이없는 경우 어떻게합니까? 다음과 같이 작성할 수 있습니다.
if user_email.nil?
user_email = "[email protected]"
end
or-equals 연산자를 사용하여이 코드 전체를 자르고 깨끗하고 명확한 제어 및 기능을 제공 할 수 있습니다.
user_email ||= "[email protected]"
false
가 유효한 값인 경우 실수로 무시하지 않도록주의해야합니다.
has_been_run = false
has_been_run ||= true
#=> true
has_been_run = false
has_been_run = true if has_been_run.nil?
#=> false
삼항 연산자
루비는 삼항 연산자 ( ?:
:)를 가지고 있는데, 조건이 진리로 평가되면 두 값 중 하나를 반환합니다.
conditional ? value_if_truthy : value_if_falsy
value = true
value ? "true" : "false"
#=> "true"
value = false
value ? "true" : "false"
#=> "false"
그것은 삼자가 선호 되더라도 if a then b else c end
쓰는 것과 같다.
예 :
puts (if 1 then 2 else 3 end) # => 2
puts 1 ? 2 : 3 # => 2
x = if 1 then 2 else 3 end
puts x # => 2
플립 플롭 연산자
플립 플롭 연산자 ..
는 조건문의 두 조건 사이에서 사용됩니다.
(1..5).select do |e|
e if (e == 2) .. (e == 4)
end
# => [2, 3, 4]
첫 번째 부분이 true
가 될 때까지 조건은 false
평가됩니다. 그런 다음 두 번째 부분이 true
가 될 때까지 true
평가 true
. 그 후 다시 false
전환됩니다.
이 예는 무엇이 선택되는지를 보여줍니다.
[1, 2, 2, 3, 4, 4, 5].select do |e|
e if (e == 2) .. (e == 4)
end
# => [2, 2, 3, 4]
플립 플롭 연산자는 (IFS 포함한 내부 작동 unless
)과 삼원 연산자. 그렇지 않으면 범위 연산자로 간주됩니다.
(1..5).select do |e|
(e == 2) .. (e == 4)
end
# => ArgumentError: bad value for range
false
에서 true
, 그리고 여러번 뒤로 바꿀 수 있습니다 :
((1..5).to_a * 2).select do |e|
e if (e == 2) .. (e == 4)
end
# => [2, 3, 4, 2, 3, 4]