programing

루비의 블록에 대한 do..end vs curly brace

starjava 2023. 6. 11. 10:14
반응형

루비의 블록에 대한 do..end vs curly brace

제 동료 중에는 do를 사용해서는 안 된다고 적극적으로 설득하는 사람이 있습니다.Ruby에서 여러 줄 블록을 정의하기 위해 curly brace를 사용합니다.

저는 짧은 한 줄에만 곱슬곱슬한 교정기를 사용하는 것에 대해 확고하게 생각하고 있습니다.다른 모든 것을 위해 끝.하지만 저는 좀 더 큰 공동체에 연락해서 해결책을 얻으려고 생각했습니다.

그렇다면 어떤 것이 그것이고, 왜 그럴까요? (일부 코드의 예)

context do
  setup { do_some_setup() }
  should "do somthing" do
    # some more code...
  end
end

또는

context {
  setup { do_some_setup() }
  should("do somthing") {
    # some more code...
  }
}

개인적으로, 위의 것들을 보는 것만으로도 저는 그 질문에 답할 수 있습니다. 하지만 저는 이것을 더 큰 공동체에 개방하고 싶었습니다.

일반적인 관례는 do를 사용하는 것입니다.다중 선 블록의 경우 끝이고 단일 선 블록의 경우에는 물결 괄호가 있지만 다음 예에서 설명할 수 있는 두 가지 차이점도 있습니다.

puts [1,2,3].map{ |k| k+1 }
2
3
4
=> nil
puts [1,2,3].map do |k| k+1; end
#<Enumerator:0x0000010a06d140>
=> nil

이는 {}이(가) 실행보다 우선 순위가 높다는 것을 의미합니다.마지막으로, 사용할 항목을 결정할 때 이 점을 명심하십시오.

선호도를 개발하는 동안 명심해야 할 예가 하나 더 있습니다.

다음 코드:

task :rake => pre_rake_task do
  something
end

진정한 의미:

task(:rake => pre_rake_task){ something }

그리고 이 코드는:

task :rake => pre_rake_task {
  something
}

진정한 의미:

task :rake => (pre_rake_task { something })

따라서 곱슬곱슬한 중괄호를 사용하여 원하는 실제 정의를 얻으려면 다음 작업을 수행해야 합니다.

task(:rake => pre_rake_task) {
  something
}

매개 변수에 브레이스를 사용하는 것이 좋습니다. 하지만 그렇게 하지 않을 경우에는 사용하는 것이 가장 좋습니다.이러한 혼란을 피하기 위해 이러한 경우에 끝납니다.

Ruby 프로그래밍에서:

중괄호는 우선 순위가 높고, do는 우선 순위가 낮습니다.메서드 호출에 괄호로 묶이지 않은 매개 변수가 있는 경우 블록의 브레이스 형식이 전체 호출이 아닌 마지막 매개 변수에 바인딩됩니다.문서가 호출에 바인딩됩니다.

그래서 코드는

f param {do_something()}

을 록을에 합니다딩바에 .param 은 code 수변 코입니다.

f param do do_something() end

을 록을함수바인니다합딩에 .f.

그러나 함수 인수를 괄호로 묶으면 문제가 되지 않습니다.

이것에 대한 몇 가지 관점이 있습니다. 이것은 정말로 개인적인 선호의 문제입니다.많은 루비스트들이 당신의 방식을 취합니다.그러나, 두 가지 다른 일반적인 스타일은 항상 하나 또는 다른 하나를 사용하는 것입니다.{}, 값을반블의경우럭는하환▁that경▁for.do ... end부작용으로 실행되는 블록의 경우.

내가 본 가장 일반적인 규칙(가장 최근에 언플러그드 루비에서)은 다음과 같습니다.

  • 다중 줄 블록인 경우 실행/종료 사용
  • 단일 줄 블록인 경우 {} 사용

저는 do/end에 투표합니다.


는 컨션은입니다.do .. end 및 다중 및선회▁multil의 경우{ ... }한 줄짜리의

하지만 난 좋아요do .. end더 좋아요, 그래서 라이너 하나가 있을 때, 저는 사용합니다.do .. end하지만 세 줄로 된 실행/종료에 대해 평소와 같이 형식을 지정합니다.이것은 모두를 행복하게 만듭니다.

  10.times do 
    puts ...
  end

의 한 가지 .{ } 전체가 마지막 변수에 함좋아 않을 뿐입니다. 그리고 제가 보기에는 그렇게 좋아 보이지 않습니다.이들은 문 그룹이 아니며 읽기 쉽도록 해시 상수와 충돌합니다.

게다가, 나는 충분히 봐왔습니다.{ }C 프로그램에서.루비의 방식은, 평소와 마찬가지로, 더 좋습니다.정확히 한 가지 유형이 있습니다.if다시 돌아가서 진술서를 복합 진술서로 변환할 필요가 없습니다.

곱슬곱슬한 중괄호에는 한 가지 주요 이점이 있습니다. 대부분의 편집자는 이를 일치시키는 시간이 훨씬 쉬워 특정 유형의 디버깅을 훨씬 쉽게 할 수 있습니다.한편, 키워드 "do...end"는 특히 "end"가 "if"와 일치하기 때문에 일치하기가 상당히 어렵습니다.

몇몇 영향력 있는 루비스트들은 반환 값을 사용할 때는 중괄호를 사용하고, 사용하지 않을 때는 실행/종료를 제안합니다.

http://talklikeaduck.denhaven2.com/2007/10/02/ruby-blocks-do-or-brace (archive.org 에서)

http://onestepback.org/index.cgi/Tech/Ruby/BraceVsDoEnd.rdoc (archive.org 에서)

이것은 일반적으로 좋은 관행인 것 같습니다.

이 원칙을 조금 수정해서 한 줄에 do/end를 사용하는 것은 읽기 어렵기 때문에 피해야 한다고 말씀드리고 싶습니다.

중괄호는 전체 메서드 호출 대신 메서드의 최종 매개 변수에 바인딩되므로 중괄호 사용에 더욱 주의해야 합니다.괄호만 추가하면 됩니다.

사실 그것은 개인적인 선호이지만, 지난 3년 동안 저의 루비 경험에서 제가 배운 것은 루비가 그 스타일을 가지고 있다는 것입니다.

예를 들어 JAVA 배경에서 온 경우 사용할 수 있는 부울 메서드가 있습니다.

def isExpired
  #some code
end 

낙타 대소문자를 주목하고 대부분 'is' 접두사를 사용하여 부울 방법으로 식별합니다.

하지만 루비의 세계에서, 같은 방법은

def expired?
  #code
end

그래서 저는 개인적으로 '루비웨이'로 가는 것이 더 낫다고 생각합니다(하지만 이해하는 데 시간이 좀 걸린다는 것을 압니다(약 1년이 걸렸습니다:D).

마지막으로, 저는 찬성합니다.

do 
  #code
end

블록들

차이(순차/구속력)가 이미 지적되었고, 그것이 문제를 찾기 어려울 수 있음에도 불구하고 나는 또 다른 답을 넣었습니다(틴맨 등이 지적했습니다).제 예는 경험이 많은 프로그램 담당자들도 일요일 시간대처럼 읽지 않는, 그다지 일반적이지 않은 코드 조각의 문제를 보여준다고 생각합니다.

module I18n
    extend Module.new {
        old_translate=I18n.method(:translate)
        define_method(:translate) do |*args|
            InplaceTrans.translate(old_translate, *args)
        end
        alias :t :translate
    }
end

module InplaceTrans
    extend Module.new {
        def translate(old_translate, *args)
            Translator.new.translate(old_translate, *args)
        end
    }
end

그 다음 코드를 작성했습니다.

#this code is wrong!
#just made it 'better looking'
module I18n
    extend Module.new do
        old_translate=I18n.method(:translate)
        define_method(:translate) do |*args|
            InplaceTrans.translate(old_translate, *args)
        end
        alias :t :translate
    end
end

만약 당신이 그것을 바꾼다면.{}여기까지do/end가 발생할 수 .translate존재하지 않음...

왜 이런 일이 발생하는지는 여기서 한 가지 이상의 우선 순위로 지적됩니다.하지만 여기서 교정기를 어디에 둘까요?(@양철맨: 나는 항상 너처럼 교정기를 사용하지만, 여기서는...감독)

그래서 모든 대답은.

If it's a multi-line block, use do/end
If it's a single line block, use {}

"하지만 교정기/우선순위를 주시하라!"를 사용하지 않으면 잘못된 것입니다.

다시:

extend Module.new {} evolves to extend(Module.new {})

그리고.

extend Module.new do/end evolves to extend(Module.new) do/end

(확장의 결과가 블록에 어떤 영향을 미치든...)

따라서 실행/종료를 사용하려면 다음을 사용합니다.

#this code is ok!
#just made it 'better looking'?
module I18n
    extend(Module.new do 
        old_translate=I18n.method(:translate)
        define_method(:translate) do |*args|
            InplaceTrans.translate(old_translate, *args)
        end
        alias :t :translate
    end)
end

개인적인 편견으로 말하자면, 저는 도/엔드 블록보다는 곱슬곱슬한 중괄호를 선호합니다. 왜냐하면 대부분의 배경 언어로 인해 도/엔드 규칙보다 더 많은 수의 개발자가 사용하기 때문입니다.따라서 진정한 열쇠는 상점 내에서 합의에 도달하는 것입니다. 만약 Do/End가 모든 개발자가 사용해야 하는 것보다 6/10 개발자가 사용해야 하는 것이라면, 6/10이 곱슬곱슬한 중괄호를 사용한다면, 그 패러다임을 고수하십시오.

팀 전체가 코드 구조를 더 빨리 식별할 수 있도록 패턴을 만드는 것이 전부입니다.

이 둘 사이에는 미묘한 차이가 있지만 {}이(가) 실행/종료보다 더 엄격하게 바인딩됩니다.

저의 개인적인 스타일은 엄격한 규칙보다 가독성을 강조하는 것입니다.{...}do...end선택, 그러한 선택이 가능할 때.가독성에 대한 저의 생각은 다음과 같습니다.

[ 1, 2, 3 ].map { |e| e + 1 }      # preferred
[ 1, 2, 3 ].map do |e| e + 1 end   # acceptable

[ 1, 2, 3 ].each_with_object [] do |e, o| o << e + 1 end # preferred, reads like a sentence
[ 1, 2, 3 ].each_with_object( [] ) { |e, o| o << e + 1 } # parens make it less readable

Foo = Module.new do     # preferred for a multiline block, other things being equal
  include Comparable
end

Foo = Module.new {      # less preferred
  include Comparable
}

Foo = Module.new { include Comparable }      # preferred for a oneliner
Foo = module.new do include Comparable end   # imo less readable for a oneliner

[ [ 1 ], [ 1, 2 ] ].map { |e| e.map do |e| e + 1 end }  # slightly better
[ [ 1 ], [ 1, 2 ] ].map { |e| e.map { |e| e + 1 } }     # slightly worse

다중선 중첩 블록과 같은 더 복잡한 구문에서, 나는 인터스패싱을 시도합니다.{...}그리고.do...end가장 자연스러운 결과를 위한 구분자.

Foo = Module.new { 
  if true then
    Bar = Module.new {                          # I intersperse {} and keyword delimiters
      def quux
        "quux".tap do |string|                  # I choose not to intersperse here, because
          puts "(#{string.size} characters)"    # for multiline tap, do ... end in this
        end                                     # case still loks more readable to me.
      end
    }
  end
}

엄격한 규칙이 없기 때문에 프로그래머마다 조금씩 다른 선택을 할 수 있지만, 주관적이긴 하지만 가독성을 위한 사례별 최적화는 엄격한 규칙을 준수하는 것보다 순익이라고 생각합니다.

저는 여기서 가장 많이 투표된 답변의 예를 들었습니다.말합니다,

[1,2,3].map do 
  something 
end

array.rb의 내부 구현을 확인하면 map 메서드의 헤더에 다음과 같이 표시됩니다.

Invokes the given block once for each element of self.

def map(*several_variants)
    (yield to_enum.next).to_enum.to_a
end

즉, 코드 블록을 수락합니다. 실행과 종료 사이에 있는 모든 것이 수율로 실행됩니다.그러면 결과가 다시 배열로 수집되어 완전히 새로운 개체가 반환됩니다.

따라서 Do-end 블록이나 {}을(를) 만날 때마다 내부적으로 실행될 코드 블록이 매개 변수로 전달된다는 마인드 맵을 사용하십시오.

세 번째 옵션이 있습니다.들여쓰기에서 자체 라인의 "끝"을 추론하기 위해 전처리기를 작성합니다.간결한 코드를 선호하는 깊은 사상가들은 우연히 옳습니다.

루비를 해킹하는 것이 더 낫습니다. 그래서 이것은 깃발입니다.

물론, "싸움을 골라라"는 가장 간단한 해결책은 일련의 끝이 모두 동일한 선에 나타나는 스타일 관습을 채택하고 구문 색상을 가르쳐 그것들을 음소거하는 것입니다.편집의 용이성을 위해 편집기 스크립트를 사용하여 이러한 시퀀스를 확장/축소할 수 있습니다.

루비 코드 라인의 20%에서 25%는 자체 라인에서 "끝"이며, 모두 들여쓰기 규칙에 의해 사소한 추론이 가능합니다.루비는 가장 큰 성공을 거둔 혀 같은 언어입니다.사람들이 이것에 이의를 제기할 때, 모든 끔찍한 괄호가 어디에 있는지 묻는다면, 저는 그들에게 불필요한 "끝"의 일곱 줄로 끝나는 루비 함수를 보여줍니다.

저는 대부분의 괄호를 유추하기 위해 리스프 전처리기를 사용하여 수년 동안 코드를 작성했습니다. 막대 '|'은 줄 끝에서 자동으로 닫는 그룹을 열었고, 달러 기호 '$'는 그룹화를 추론하는 데 도움이 되는 기호가 없는 빈 자리 표시자 역할을 했습니다.물론 이곳은 종교적인 전쟁 지역입니다.괄호가 없는 리스프/스킴은 모든 언어 중에서 가장 시적입니다.그러나 구문 색상을 사용하여 괄호를 쉽게 음소거할 수 있습니다.

저는 여전히 Haskell을 위한 전처리기로 코딩하고, 여기에 문서를 추가하고, 모든 플러시 라인을 주석으로 기본 설정하고, 모든 것을 코드로 들여씁니다.저는 언어가 어떻든 간에 댓글 캐릭터를 싫어해요.

언급URL : https://stackoverflow.com/questions/5587264/do-end-vs-curly-braces-for-blocks-in-ruby

반응형