루비: 전화해 (늙은 개가 새로운 재주를 배운다)

1752 단어
몇 년 전 저는 수석 개발자가 우리가 SRP를 준수하고 call라는 단일 인터페이스를 통해 클래스와 인스턴스를 노출하기를 원하는 곳에서 일했습니다. 예:

def Foo
  def self.call = new.call
  def call = "hello"
end


해시를 반환할 때 to_h, 문자열 등을 위해 to_s와 같은 더 명백한 규칙을 무시했지만 결국 이것은 특정 측면에서 꽤 깨끗한 코드베이스를 만들었습니다. 엄격하게 적용됩니다.

그 외에도 놓친 기회 중 하나는 이와 같은 클래스/인스턴스가 유용한 이유에 대한 폭 넓은 이해를 생성하는 것이었고 최근에 질문을 다시 검토할 기회가 있었습니다.

모르는 경우 calllambdaproc 에 이미 응답하는 두 개의 루비 개체가 있습니다.

l = lambda { |x| x * x }
puts l.call(2) # 4

p = proc { |x| x + x }
puts p.call(3) # 6

method 또는 (바람직하게는) public_method를 사용하여 메서드를 proc으로 변환할 수도 있습니다.

def foo(x) = x - x
m = method(:foo)
puts m.call(10) # 0 


이를 염두에 두고 모두 동일한 인터페이스로 실행되는 람다, 프로시저, 메서드, 클래스 또는 클래스의 인스턴스를 전달할 수 있습니다. 이것은 콜백과 다른 실행에 매우 유용합니다.

속임수에 관해서는 ... 실제로 call를 호출하는 방법에는 여러 가지가 있습니다. l.call(2)는 당연하지만 l.(2)도 할 수 있습니다.

procs, lambdas 및 method의 경우 l[2]l.yield(2)도 있지만 (이것을 몰랐습니다!) 클래스 또는 인스턴스의 경우 지원을 추가해야 합니다(예: alias_method :[], :call ). 그러면 수업이 약간 지저분해지기 시작하므로 .() 를 고수하는 경향이 있습니다.

하지만 더 있습니다. Elixir 파이프의 팬이라면:

l = lambda { |x| x * x }
p = proc { |x| x + x }
output = proc { |x| puts "*** #{x} ***" }

(l >> p >> output).call(2) # *** 8 ***
(output << p << l).call(2) # *** 8 ***


정말 합당한 이유가 없는 한 PR에서 이와 같은 코드를 승인할지 모르겠지만 이것이 가능한지 전혀 몰랐습니다. 새로운 트릭!

좋은 웹페이지 즐겨찾기