Skip to content

Commit ce29ec5

Browse files
authored
deprecate (;) (#30115) (#34039)
1 parent 3382125 commit ce29ec5

File tree

7 files changed

+25
-14
lines changed

7 files changed

+25
-14
lines changed

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ Language changes
1818

1919
* Calling `show` or `repr` on a 0-dimensional `AbstractArray` now shows valid code for creating an equivalent 0-dimensional array, instead of only showing the contained value. ([#33206])
2020

21+
* The syntax `(;)`, which used to parse as an empty block expression, is deprecated.
22+
In the future it will indicate an empty named tuple ([#30115]).
23+
2124
Multi-threading changes
2225
-----------------------
2326

doc/src/base/punctuation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Extended documentation for mathematical symbols & functions is [here](@ref math-
2626
| `()` | parentheses with no arguments constructs an empty [`Tuple`](@ref) |
2727
| `(a,...)` | parentheses with comma-separated arguments constructs a tuple containing its arguments |
2828
| `(a=1,...)` | parentheses with comma-separated assignments constructs a [`NamedTuple`](@ref) |
29-
| `(;)` | parentheses can also be used to group one or more semicolon separated expressions |
29+
| `(x;y)` | parentheses can also be used to group one or more semicolon separated expressions |
3030
| `a[]` | [array indexing](@ref man-array-indexing) (calling [`getindex`](@ref) or [`setindex!`](@ref)) |
3131
| `[,]` | [vector literal constructor](@ref man-array-literals) (calling [`vect`](@ref Base.vect)) |
3232
| `[;]` | [vertical concatenation](@ref man-array-concatenation) (calling [`vcat`](@ref) or [`hvcat`](@ref)) |

doc/src/manual/control-flow.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Julia provides a variety of control flow constructs:
44

5-
* [Compound Expressions](@ref man-compound-expressions): `begin` and `(;)`.
5+
* [Compound Expressions](@ref man-compound-expressions): `begin` and `;`.
66
* [Conditional Evaluation](@ref man-conditional-evaluation): `if`-`elseif`-`else` and `?:` (ternary operator).
77
* [Short-Circuit Evaluation](@ref): `&&`, `||` and chained comparisons.
88
* [Repeated Evaluation: Loops](@ref man-loops): `while` and `for`.
@@ -19,7 +19,7 @@ direct usage of tasks, but certain problems can be solved much more easily by us
1919

2020
Sometimes it is convenient to have a single expression which evaluates several subexpressions
2121
in order, returning the value of the last subexpression as its value. There are two Julia constructs
22-
that accomplish this: `begin` blocks and `(;)` chains. The value of both compound expression constructs
22+
that accomplish this: `begin` blocks and `;` chains. The value of both compound expression constructs
2323
is that of the last subexpression. Here's an example of a `begin` block:
2424

2525
```jldoctest
@@ -32,7 +32,7 @@ julia> z = begin
3232
```
3333

3434
Since these are fairly small, simple expressions, they could easily be placed onto a single line,
35-
which is where the `(;)` chain syntax comes in handy:
35+
which is where the `;` chain syntax comes in handy:
3636

3737
```jldoctest
3838
julia> z = (x = 1; y = 2; x + y)
@@ -41,7 +41,7 @@ julia> z = (x = 1; y = 2; x + y)
4141

4242
This syntax is particularly useful with the terse single-line function definition form introduced
4343
in [Functions](@ref). Although it is typical, there is no requirement that `begin` blocks be multiline
44-
or that `(;)` chains be single-line:
44+
or that `;` chains be single-line:
4545

4646
```jldoctest
4747
julia> begin x = 1; y = 2; x + y end

src/julia-parser.scm

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,17 +1910,22 @@
19101910
;; convert an arglist to a tuple or block expr
19111911
;; leading-semi? means we saw (; ...)
19121912
;; comma? means there was a comma after the first expression
1913-
(define (arglist-to-tuple leading-semi? comma? args . first)
1913+
(define (arglist-to-tuple s leading-semi? comma? args . first)
19141914
(if (and (pair? first) (null? args) (not leading-semi?) (not comma?))
19151915
`(block ,@first) ;; this case is (x;)
19161916
(or (and (not comma?) (length= args 1) (pair? (car args)) (eq? (caar args) 'parameters)
19171917
(let ((blk (parameters-to-block (car args))))
19181918
(and blk (or (and (not leading-semi?)
19191919
`(block ,@first ,@blk))
19201920
(and (null? first) (null? blk)
1921-
`(block)))))) ;; all semicolons inside ()
1921+
;; all semicolons inside ()
1922+
(if (length= (car args) 1)
1923+
(begin (parser-depwarn s "(;)" "begin end")
1924+
;; should eventually be (tuple (parameters))
1925+
`(block))
1926+
`(block)))))))
19221927
(and (null? first) (null? args) (not comma?)
1923-
`(block)) ;; this case is (;)
1928+
(error "unreachable"))
19241929
(rm-linenums
19251930
(if (and (pair? args) (pair? (car args)) (eq? (caar args) 'parameters))
19261931
`(tuple ,(car args) ,@first ,@(map kw-to-= (cdr args)))
@@ -1974,7 +1979,7 @@
19741979
(take-token s) ;; take #\)
19751980
'(|::| . #f))
19761981
((eqv? nxt #\;)
1977-
(let ((ex (arglist-to-tuple #t #f (parse-arglist s #\) ))))
1982+
(let ((ex (arglist-to-tuple s #t #f (parse-arglist s #\) ))))
19781983
(cons ex (eq? (car ex) 'tuple))))
19791984
(else
19801985
;; here we parse the first subexpression separately, so
@@ -1991,10 +1996,11 @@
19911996
((eqv? t #\,)
19921997
;; tuple (x,) (x,y) etc.
19931998
(take-token s)
1994-
(cons (arglist-to-tuple #f #t (parse-arglist s #\) ) ex)
1999+
(cons (arglist-to-tuple s #f #t (parse-arglist s #\) ) ex)
19952000
#t))
19962001
((eqv? t #\;)
19972002
(cons (arglist-to-tuple
2003+
s
19982004
#f
19992005
;; consider `(x...; ` the start of an arglist, since it's not useful as a block
20002006
(vararg? ex)

src/julia-syntax.scm

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1768,7 +1768,9 @@
17681768
(current-vals '())
17691769
(expr #f))
17701770
(if (null? L)
1771-
(merge expr (to-nt current-names current-vals))
1771+
(or (merge expr (to-nt current-names current-vals))
1772+
;; if that result is #f the named tuple is empty
1773+
'(call (core NamedTuple)))
17721774
(let ((el (car L)))
17731775
(cond ((or (assignment? el) (kwarg? el))
17741776
(if (not (symbol? (cadr el)))

test/namedtuple.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ end
133133
@test Meta.lower(Main, Meta.parse("(; f(x))")) == Expr(:error, "invalid named tuple element \"f(x)\"")
134134
@test Meta.lower(Main, Meta.parse("(;1=0)")) == Expr(:error, "invalid named tuple field name \"1\"")
135135

136-
@test Meta.parse("(;)") == quote end
136+
@test eval(Expr(:tuple, Expr(:parameters))) === NamedTuple()
137137
@test Meta.lower(Main, Meta.parse("(1,;2)")) == Expr(:error, "unexpected semicolon in tuple")
138138

139139
# splatting

test/syntax.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ macro test999_str(args...); args; end
171171

172172
# blocks vs. tuples
173173
@test Meta.parse("()") == Expr(:tuple)
174-
@test Meta.parse("(;)") == Expr(:block)
174+
@test_skip Meta.parse("(;)") == Expr(:tuple, Expr(:parameters))
175175
@test Meta.parse("(;;;;)") == Expr(:block)
176176
@test_throws ParseError Meta.parse("(,)")
177177
@test_throws ParseError Meta.parse("(;,)")
@@ -1322,7 +1322,7 @@ end
13221322
@test Meta.parse("-(x)^2") == Expr(:call, :-, Expr(:call, :^, :x, 2))
13231323
@test Meta.parse("-(a=1)^2") == Expr(:call, :-, Expr(:call, :^, Expr(:(=), :a, 1), 2))
13241324
@test Meta.parse("-(x;y)^2") == Expr(:call, :-, Expr(:call, :^, Expr(:block, :x, LineNumberNode(1,:none), :y), 2))
1325-
@test Meta.parse("-(;)^2") == Expr(:call, :-, Expr(:call, :^, Expr(:block), 2))
1325+
@test_skip Meta.parse("-(;)^2") == Expr(:call, :-, Expr(:call, :^, Expr(:tuple, Expr(:parameters)), 2))
13261326
@test Meta.parse("-(;;;;)^2") == Expr(:call, :-, Expr(:call, :^, Expr(:block), 2))
13271327
@test Meta.parse("-(x;;;)^2") == Expr(:call, :-, Expr(:call, :^, Expr(:block, :x), 2))
13281328
@test Meta.parse("+((1,2))") == Expr(:call, :+, Expr(:tuple, 1, 2))

0 commit comments

Comments
 (0)