Python-like docstrings in Ruby!

About six months ago, I watched Peter Cooper’s Ruby Trickshots and learnt that Ruby has an interesting syntax that allows you to concatenate strings by simply placing them after each other.

For example:

1
"foo" "bar" # => "foobar"

I quickly realised that that meant that this was valid syntax:

1
"""foo"""   # => "foo"

Which meant that Python-like docstrings were syntactically valid in Ruby!

I hacked up a bit of code that let you read out the docstring in this gist:

It was an interesting hack, but I thought that Ruby would have to evaluate the concatenation on every method invocation, hence adding a performance hit purely to add a docstring, and hence ditched the idea of taking it further, and then promptly forgot about it.

Six months later, I found it when I was going through my old gists. I brought it up with CRuby Master @charliesome, and he informed me that CRuby is pretty smart and actually won’t emit bytecode if it detects that the literals aren’t actually used, so there is actually no performance hit (apart from when it’s parsing).

Proof:

https://eval.in/36676 Link
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def no_docstring
  nil
end

def with_docstring
  """Foo"""
  nil
end

puts RubyVM::InstructionSequence.of(method(:no_docstring)).disasm
puts "---"
puts RubyVM::InstructionSequence.of(method(:with_docstring)).disasm

# Output:
# == disasm: <RubyVM::InstructionSequence:no_docstring@/tmp/execpad-ecb5745fbd46/source-ecb5745fbd46>
# 0000 trace            8                                               (   1)
# 0002 putnil
# 0003 trace            16                                              (   3)
# 0005 leave
# ---
# == disasm: <RubyVM::InstructionSequence:with_docstring@/tmp/execpad-ecb5745fbd46/source-ecb5745fbd46>
# 0000 trace            8                                               (   5)
# 0002 putnil
# 0003 trace            16                                              (   8)
# 0005 leave

I made a gem called docstrings that allows accessing docstrings via Method#docstring. I’m not entirely sure how useful this actually is, so let me know if you end up using it.

Comments