Ruby 메소드에 느낌표가 사용되는 이유는 무엇입니까?


540

루비에서 일부 메소드에는 해당 객체가 포함되어 있는지 묻는 ?질문과 같은 물음표 ( ) include?가 있습니다. 그러면 참 / 거짓을 반환합니다.

그러나 왜 어떤 방법에는 다른 방법이없는 느낌표 ( !)가 있습니까?

무슨 뜻이에요?


21
동의어 : bang, 느낌표
prusswan

17
수락 된 답변은 stackoverflow.com/a/612653/109618 로 변경되어야합니다 . wobblini.net/bang.txtruby-forum.com/topic/176830#773946 참조 - "뱅뱅 (bang) 표시는"뱅뱅이 비 뱅크 버전보다 더 위험합니다. 주의해서 다루십시오 ""-Matz
David J.

2
경우 쾅 방법은 좋은 디자인 선택이 될 것입니다 단지모든 강타 방법은 위험했다. 슬프게도 그들은 아니기 때문에 변경 가능하지 않은 것이 무엇인지 암기하는 데 좌절스러운 운동이됩니다.
Damien Roche

답변:


617

일반적으로 끝나는 !메소드는 메소드가 호출 된 객체수정할 것임을 나타냅니다 . 루비는 다른 사람들이 참조 할 수있는 상태를 변경하기 때문에이를 " 위험한 메소드 " 라고 부릅니다 . 다음은 문자열에 대한 간단한 예입니다.

foo = "A STRING"  # a string called foo
foo.downcase!     # modifies foo itself
puts foo          # prints modified foo

출력됩니다 :

a string

표준 라이브러리에는 비슷한 이름의 메서드 쌍이 !있고없는 방법이 많이 있습니다. 없는 것들은 "안전한 방법 (safe methods)"으로 불리며 , 수신자 에 대한 변경 사항이 없이 사본에 적용된 변경 사항이있는 원본의 사본을 반환합니다 . 다음은없는 동일한 예입니다 !.

foo = "A STRING"    # a string called foo
bar = foo.downcase  # doesn't modify foo; returns a modified string
puts foo            # prints unchanged foo
puts bar            # prints newly created bar

출력 :

A STRING
a string

이것은 컨벤션 일 뿐이지 만 많은 루비 클래스가이를 따릅니다. 또한 코드에서 수정 된 내용을 추적하는 데 도움이됩니다.


2
종료 대 종료와 같은 경우도 있습니다! 그리고 (레일에서) 저장 대 저장!
Andrew Grimm

24
많은 작은 라이브러리는이 규칙을 따르지 않습니다. 이상한 일이 발생하면 종종 obj.what을 대체하십시오! obj = obj.whatever! 그것을 고치십시오. 매우 실망 스럽습니다.
Sarah Mei

101
플레이는 예외를 발생 방법에 사용되는 경우에있어서, 사용하지 않을 때되지 예 : savesave!ActiveRecord
ecoologic

3
@AbhilashAK 저장! 저장할 수 없으면 오류가 발생합니다. 이것은 true / false를 리턴하는 정기적 저장과 반대입니다.
BookOfGreg

31
@tgamblin Ruby에는 강타없이 변경되는 많은 메소드가 있습니다. 뱅으로 변경하지는 않지만 오류 발생 또는 건너 뛰기 오류와 같은 놀라운 작업을 수행하는 드문 방법이 있습니다. 앞머리는 이것이 더 특이한 버전의 방법이라고 말하는데 사용되며 이것이 올바른 것으로 표시되어 답변에 반영되어야한다고 생각합니다.
BookOfGreg

143

느낌표는 많은 것을 의미하며 때로는 "이것은 위험합니다. 조심하세요"이외의 많은 것을 말할 수 없습니다.

다른 사람들이 말했듯이 표준 방법에서는 종종 객체를 돌연변이시키는 방법을 나타내는 데 사용되지만 항상 그런 것은 아닙니다. 많은 표준 방법은 자신의 수신기를 변경 느낌표 (필요는 없습니다 pop, shift, clear), 느낌표 몇 가지 방법이 자신의 수신기를 변경하지 마십시오 ( exit!). 예를 들어이 기사 를 참조하십시오 .

다른 라이브러리에서는 다르게 사용할 수 있습니다. Rails에서 느낌표는 종종 자동으로 실패하지 않고 실패시 예외가 발생 함을 의미합니다.

명명 규칙이지만 많은 사람들이 미묘하게 다른 방식으로 사용합니다. 자신의 코드에서 엄지 손가락의 좋은 규칙은 메서드가 "위험한"작업을 수행 할 때마다, 특히 같은 이름을 가진 두 개의 메서드가 존재하고 그 중 하나가 다른 메서드보다 "위험한"경우이를 사용하는 것입니다. "위험한"은 거의 모든 것을 의미 할 수 있습니다.


75

이 명명 규칙은 Scheme 에서 해제되었습니다 .

1.3.5 명명 규칙

일반적으로 부울 값을 항상 반환하는 프로 시저 이름은 일반적으로``? ''로 끝납니다. 이러한 절차를 술어라고합니다.

일반적으로 값을 이전에 할당 된 위치 (섹션 3.4 참조)에 저장하는 프로 시저 이름은 일반적으로``! ''로 끝납니다. 이러한 절차를 돌연변이 절차라고합니다. 관례 적으로, 돌연변이 절차에 의해 반환 된 값은 명시되지 않았다.


2
이 답변에 +1하기 때문에! 용법. 정말 좋은 답변 Steven
DavidSilveira

감사합니다 @DavidSilveira!
Steven Huwig

24

! 일반적으로 메서드가 결과를 반환하는 대신 개체에 작용 함을 의미합니다. 책 프로그래밍 Ruby에서 :

"위험한"또는 수신자를 수정하는 메소드는 뒤에 "!"로 이름이 지정 될 수 있습니다.


18

Bang을 사용한 메소드를 말하는 것이 가장 정확합니다! 더 위험 하거나 놀라운 버전입니다. Bang을 사용하지 않고 변경하는 많은 메소드가 .destroy있으며 일반적으로 메소드는 코어 라이브러리에 더 안전한 대안이 존재 하는 Bang 만 있습니다.

예를 들어, Array에는 .compactand가 .compact!있으며 두 메소드 모두 배열을 변경하지만 배열에 .compact!nil이 없으면 self 대신 nil을 반환하므로 self를 반환하는 것보다 더 놀랍습니다.

내가 쾅 발견 한 유일한 비 돌연변이 방법은 Kernel.exit!보다 더 놀라운 .exit당신이 잡을 수 없기 때문에 SystemExit프로세스가 종료된다.

Rails와 ActiveRecord는 .create!실패에 대한 오류를 유발하는 것과 같은보다 '놀라운'효과를 위해 강타를 사용한다는 점에서 이러한 추세를 계속합니다 .


16

themomorohoax.com에서 :

뱅은 내 개인적인 취향에 따라 아래 방법으로 사용할 수 있습니다.

1) 활성 레코드 방법은 원하는대로 수행하지 않으면 오류를 발생시킵니다.

2) 활성 레코드 방법으로 레코드를 저장하거나 방법으로 개체를 저장합니다 (예 : 스트립!)

3) 방법은 장소에 대한 게시물과 같은 "추가"작업을 수행하거나 작업을 수행합니다.

요점은 실제로 필요한지 여부를 생각했을 때만 강타를 사용하는 이유는 다른 개발자에게 강타를 사용하는 이유를 확인해야하는 번거 로움을 덜기 위해서입니다.

뱅은 다른 개발자에게 두 가지 신호를 제공합니다.

1) 메소드를 호출 한 후 객체를 저장할 필요가 없습니다.

2) 메소드를 호출하면 db가 변경됩니다.

http://www.themomorohoax.com/2009/02/11/when-to-use-a-bang-exclamation-point-after-rails-methods


6

간단한 설명 :

foo = "BEST DAY EVER" #assign a string to variable foo.

=> foo.downcase #call method downcase, this is without any exclamation.

"best day ever"  #returns the result in downcase, but no change in value of foo.

=> foo #call the variable foo now.

"BEST DAY EVER" #variable is unchanged.

=> foo.downcase! #call destructive version.

=> foo #call the variable foo now.

"best day ever" #variable has been mutated in place.

그러나 downcase!위의 설명에서 메소드 를 호출 한 경우 foo영구적으로 소문자로 변경됩니다. downcase!새 문자열 객체를 반환하지 않지만 문자열을 제자리로 바꾸고 완전히 foo소문자로 바꿉니다. downcase!꼭 필요한 경우가 아니면 사용 하지 않는 것이 좋습니다 .


1
!

나는 이것을 이전의 모든 것을 파괴하는 폭발적인 변화로 생각하고 싶다. 쾅 또는 느낌표는 코드를 영구적으로 저장하고 있음을 의미합니다.

예를 들어 루비의 전역 대체 방법을 사용 gsub!하면 대체는 영구적입니다.

상상할 수있는 또 다른 방법은 텍스트 파일을 열고 찾기 및 바꾸기를 수행 한 다음 저장하는 것입니다. !코드에서도 마찬가지입니다.

bash 세계에서 온 또 다른 유용한 알림은 sed -i영구적으로 저장된 변경을 수행하는 것과 비슷한 효과가 있습니다.


1

"파괴적 방법"이라고 부르는 이들은 당신이 언급 한 대상의 원본을 바꾸는 경향이 있습니다.

numbers=[1,0,10,5,8]
numbers.collect{|n| puts n*2} # would multiply each number by two
numbers #returns the same original copy
numbers.collect!{|n| puts n*2} # would multiply each number by two and destructs the original copy from the array
numbers   # returns [nil,nil,nil,nil,nil]

0

결론 : !메소드는 호출 된 객체의 값을 변경하는 반면 메소드가없는 !메소드는 메소드가 호출 된 객체를 덮어 쓰지 않고 조작 된 값을 반환합니다.

!메소드를 호출 한 변수에 저장된 원래 값이 필요하지 않은 경우 에만 사용 하십시오.

나는 다음과 같은 것을 선호합니다 :

foo = "word"
bar = foo.capitalize
puts bar

또는

foo = "word"
puts foo.capitalize

대신에

foo = "word"
foo.capitalize!
puts foo

원래 값에 다시 액세스하려는 경우를 대비하여.


1
답변이 도움이되지 않았기 때문입니다. "맨 아래 줄 :! 메소드는 호출 된 객체의 값만 변경합니다"는 사실이 아닙니다.
Darwin

@Darwin는 않습니다 개체의 값을 변경합니다. !수정 된 사본을 반환하지 않고 객체를 변경합니다.
Charles

그래서 이것이 무엇이라고 생각합니까? User.create!
다윈

어떤 맥락에서 @Darwin? 액티브 레코드?
찰스

예, ActiveRecord.
다윈
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.