summaryrefslogtreecommitdiff
path: root/doc/syntax/layout.rdoc
blob: f07447587ba3330a47bf92380a45462d08017390 (plain)
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
= Code Layout

Expressions in Ruby are separated by line breaks:

    x = 1
    y = 2
    z = x + y

Line breaks also used as logical separators of the headers of some of control structures from their bodies:

    if z > 3       # line break ends the condition and starts the body
      puts "more"
    end

    while x < 3    # line break ends the condition and starts the body
      x += 1
    end

<tt>;</tt> can be used as an expressions separator instead of a line break:

    x = 1; y = 2; z = x + y
    if z > 3; puts "more"; end

Traditionally, expressions separated by <tt>;</tt> is used only in short scripts and experiments.

In some control structures, there is an optional keyword that can be used instead of a line break to separate their elements:

    # if, elsif, until and case ... when: 'then' is an optional separator:

    if z > 3 then puts "more" end

    case x
    when Numeric then "number"
    when String then "string"
    else "object"
    end

    # while and until: 'do' is an optional separator
    while x < 3 do x +=1 end

Also, line breaks can be skipped in some places where it doesn't create any ambiguity. Note in the example above: no line break needed before +end+, just as no line break needed after +else+.

== Breaking expressions in lines

One expression might be split into several lines when each line can be unambiguously identified as "incomplete" without the next one.

These works:

    x =         # incomplete without something after =
        1 +     # incomplete without something after +
        2

    File.read "test.txt",         # incomplete without something after ,
              enconding: "utf-8"

These would not:

    # unintended interpretation:
    x = 1     # already complete expression
        + 2   # interpreted as a separate +2

    # syntax error:
    File.read "test.txt"           # already complete expression
              , encoding: "utf-8"  # attempt to parse as a new expression, SyntaxError

The exceptions to the rule are lines starting with <tt>.</tt> ("leading dot" style of method calls) or logical operators <tt>&&</tt>/<tt>||</tt> and <tt>and</tt>/<tt>or</tt>:

    # OK, interpreted as a chain of calls
    File.read('test.txt')
        .strip("\n")
        .split("\t")
        .sort

    # OK, interpreted as a chain of logical operators:
    File.empty?('test.txt')
      || File.size('test.txt') < 10
      || File.read('test.txt').strip.empty?

If the expressions is broken into multiple lines in any of the ways described above, comments between separate lines are allowed:

    sum = base_salary +
          # see "yearly bonuses section"
          yearly_bonus(year) +
          # per-employee coefficient is described
          # in another module
          personal_coeff(employee)

    # We want to short-circuit on empty files
    File.empty?('test.txt')
      # Or almost empty ones
      || File.size('test.txt') < 10
      # Otherwise we check if it is full of spaces
      || File.read('test.txt').strip.empty?

Finally, the code can explicitly tell Ruby that the expression is continued on the next line with <tt>\\</tt>:

    # Unusual, but works
    File.read "test.txt" \
              , encoding: "utf-8"

    # More regular usage (joins the strings on parsing instead
    # of concatenating them in runtime, as + would do):
    TEXT = "One pretty long line" \
           "one more long line" \
           "one other line of the text"

The <tt>\\</tt> works as a parse time line break escape, so with it, comments can not be inserted between the lines:

    TEXT = "line 1" \
           # here would be line 2:
           "line 2"

    # This is interpreted as if there was no line break where \ is,
    # i.e. the same as
    TEXT = "line 1" # here would be line 2:
           "line 2"

    puts TEXT #=> "line 1"