`# =>`에서 `#p`로

때때로 문서를 작성하면 언어의 세부 사항을 발견할 수 있습니다!

나는 # => 를 사용하는 몇 가지 코드 예제와 함께 Generics 의 다양한 유형 인수가 있는 Crystal 에 대한 문서를 추가하는 PR을 열었습니다.

다음은 간단한 예입니다.

puts typeof("Hello!") # => String


그러나 나는 (광범위하게 말해서) 다음과 같은 제안을 받았습니다. 해당 표현식의 결과가 무엇인지 보여주기 위해 표현식 옆에 # =>를 사용하십시오.

즉, 40 + 2 표현식이 있으면 # =>를 사용하여 예상 결과를 표시하는 주석을 추가할 수 있습니다.

40 + 2 # => 42


#p 을 사용하여 예상 결과인지 확인합니다.

p 40 + 2


출력은 다음과 같습니다.

42


그렇다면 첫 번째 예의 문제점은 무엇이었습니까?




puts typeof("Hello!") # => String


제안은 계속되었습니다. [...] #putsnil 를 반환합니다.

😲 따라서 #putsnil를 반환하고 # =>가 식 평가 결과를 표시하면 올바른 주석은 다음과 같습니다.

puts typeof("Hello!") # => nil


음 ... 이것은 우리가 원하는 것이 아닙니다! 🥲

#으로 문서화 =>



제안의 마지막 부분은 다음과 같습니다. [...] 또한 #p#inspect를 사용하고 해당 인수를 반환합니다.

따라서 다음과 같이 작성할 수 있습니다.

p typeof("Hello!") # => String


기술적으로 말하면 이것은 #pString의 값인 typeof("Hello!")를 인쇄할 뿐만 아니라 해당 값을 반환하기 때문에 정확합니다.

맞지만 ... 우리는 #p 를 사용할 필요가 없습니다. 다음과 같이 예상 값을 표시하려면 # =>만 필요합니다.

typeof("Hello!") # => String


이제 코드가 잘 문서화되었습니다! 🤓🎉

또 다른 예



방금 배운 내용을 보강하기 위해 다른 예를 살펴보겠습니다. 이것은 documentation에서 바로 가져온 것입니다.

a = 1
b = 2
"sum: #{a} + #{b} = #{a + b}" # => "sum: 1 + 2 = 3"


이 예제에서는 보간법(표현식을 포함할 수 있음)을 사용하여 문자열 리터럴을 정의하므로 # =>를 사용하여 결과 문자열을 표시합니다.


지금까지 # => 가 포함된 주석을 사용하여 코드 줄을 문서화하는 방법을 배웠습니다. 엄청난!

그리고 이 모든 것이 우리로 하여금 #p#puts의 차이점을 보게 했습니다. 그렇다면 이 두 가지 방법의 구현을 살펴볼 수 있을까요? 🤔 ... 네! 그걸하자! 🤓🎉

하지만 그 전에 ...

📚 Did you know?
Methods #puts and #p also exist in Ruby.
They are implemented in module Kernel and with the same behaviour.
We can read the implementations for #puts and #p written in C in the documentation itself.



그리고 지금 ... 🥁

#puts vs #p under the hood 🔬



#풋



다음은 #puts에 대한 the source code입니다.

def puts(*objects) : Nil
  STDOUT.puts *objects
end


보시다시피 IO#puts 에 책임을 전달합니다. 보자 the implementation :

def puts(string : String) : Nil
  self << string
  puts unless string.ends_with?('\n')
  nil
end


엄청난! 메서드는 문자열을 작성하고 nil를 반환합니다(우리가 이미 예상한 대로).

#피



이제 #pthe implementation을 살펴보겠습니다.

def p(object)
  object.inspect(STDOUT)
  puts
  object
end


첫째, 메서드가 인수를 반환한다는 것을 알 수 있습니다.

그런 다음 "인쇄 책임"을 Object#inspect(io : IO)로 전달하는 것을 알 수 있습니다. 다음은 the source code입니다.

def inspect(io : IO) : Nil
  to_s io
end


코드 경로를 따라 Object#to_s(io : IO)the implementation을 계속 진행해 보겠습니다.

abstract def to_s(io : IO) : Nil


자, 방금 abstract 메서드를 찾았습니다.
Class를 "인쇄"하려고 하기 때문에 (p typeof("Hello!") # => String를 기억하십시오) Class#to_s(io : IO)implemented인지 살펴보겠습니다.

def to_s(io : IO) : Nil
  io << {{ @type.name.stringify }}
end

Class#to_sClass 문자열 표현을 출력하는 것을 볼 수 있습니다.

그리고 macros docs 🤓에서 {{ }}의 사용에 대해 읽을 수 있습니다.

🤯 Did you notice?
We've just learned how the methods #puts and #p are implemented, and all the time we were reading code in Crystal.
Yes! Crystal's stdlib is written in Crystal itself, making it a lot more natural to inspect and learn how the language works under the hood. 🤩



예시



다음은 #puts#p 사용의 차이점을 보여주는 또 다른 예입니다.

class A
  def initialize
    @foo = "Foo"
    @bar = "Bar"
  end
end

a = A.new
puts a
p a


출력은 다음과 같습니다.

#<A:0x7f25e8f28ea0>
#<A:0x7f25e8f28ea0 @foo="Foo", @bar="Bar">

#p (현재 우리가 알고 있는 #inspect 사용)가 더 많은 정보를 출력하는 것을 볼 수 있습니다.

작별 인사하고 나중에 보자



요약하자면:
  • # => 를 사용하여 코드 줄을 문서화하는 방법에 대해 배웠습니다.
  • 우리는 #puts#p 구현을 통해 이동했습니다.
  • 그리고 마지막으로 #puts#p 를 사용하는 것의 차이점에 대한 예를 보았습니다.

  • 당신이 그것을 즐겼기를 바랍니다! 😃

    좋은 웹페이지 즐겨찾기