Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ Language changes

* 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])

* The syntax `(;)`, which used to parse as an empty block expression, is deprecated.
In the future it will indicate an empty named tuple ([#30115]).

Multi-threading changes
-----------------------

Expand Down
2 changes: 1 addition & 1 deletion doc/src/base/punctuation.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Extended documentation for mathematical symbols & functions is [here](@ref math-
| `()` | parentheses with no arguments constructs an empty [`Tuple`](@ref) |
| `(a,...)` | parentheses with comma-separated arguments constructs a tuple containing its arguments |
| `(a=1,...)` | parentheses with comma-separated assignments constructs a [`NamedTuple`](@ref) |
| `(;)` | parentheses can also be used to group one or more semicolon separated expressions |
| `(x;y)` | parentheses can also be used to group one or more semicolon separated expressions |
| `a[]` | [array indexing](@ref man-array-indexing) (calling [`getindex`](@ref) or [`setindex!`](@ref)) |
| `[,]` | [vector literal constructor](@ref man-array-literals) (calling [`vect`](@ref Base.vect)) |
| `[;]` | [vertical concatenation](@ref man-array-concatenation) (calling [`vcat`](@ref) or [`hvcat`](@ref)) |
Expand Down
8 changes: 4 additions & 4 deletions doc/src/manual/control-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Julia provides a variety of control flow constructs:

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

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

```jldoctest
Expand All @@ -32,7 +32,7 @@ julia> z = begin
```

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

```jldoctest
julia> z = (x = 1; y = 2; x + y)
Expand All @@ -41,7 +41,7 @@ julia> z = (x = 1; y = 2; x + y)

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

```jldoctest
julia> begin x = 1; y = 2; x + y end
Expand Down
16 changes: 11 additions & 5 deletions src/julia-parser.scm
Original file line number Diff line number Diff line change
Expand Up @@ -1911,17 +1911,22 @@
;; convert an arglist to a tuple or block expr
;; leading-semi? means we saw (; ...)
;; comma? means there was a comma after the first expression
(define (arglist-to-tuple leading-semi? comma? args . first)
(define (arglist-to-tuple s leading-semi? comma? args . first)
(if (and (pair? first) (null? args) (not leading-semi?) (not comma?))
`(block ,@first) ;; this case is (x;)
(or (and (not comma?) (length= args 1) (pair? (car args)) (eq? (caar args) 'parameters)
(let ((blk (parameters-to-block (car args))))
(and blk (or (and (not leading-semi?)
`(block ,@first ,@blk))
(and (null? first) (null? blk)
`(block)))))) ;; all semicolons inside ()
;; all semicolons inside ()
(if (length= (car args) 1)
(begin (parser-depwarn s "(;)" "begin end")
;; should eventually be (tuple (parameters))
`(block))
`(block)))))))
(and (null? first) (null? args) (not comma?)
`(block)) ;; this case is (;)
(error "unreachable"))
(rm-linenums
(if (and (pair? args) (pair? (car args)) (eq? (caar args) 'parameters))
`(tuple ,(car args) ,@first ,@(map kw-to-= (cdr args)))
Expand Down Expand Up @@ -1975,7 +1980,7 @@
(take-token s) ;; take #\)
'(|::| . #f))
((eqv? nxt #\;)
(let ((ex (arglist-to-tuple #t #f (parse-arglist s #\) ))))
(let ((ex (arglist-to-tuple s #t #f (parse-arglist s #\) ))))
(cons ex (eq? (car ex) 'tuple))))
(else
;; here we parse the first subexpression separately, so
Expand All @@ -1992,10 +1997,11 @@
((eqv? t #\,)
;; tuple (x,) (x,y) etc.
(take-token s)
(cons (arglist-to-tuple #f #t (parse-arglist s #\) ) ex)
(cons (arglist-to-tuple s #f #t (parse-arglist s #\) ) ex)
#t))
((eqv? t #\;)
(cons (arglist-to-tuple
s
#f
;; consider `(x...; ` the start of an arglist, since it's not useful as a block
(vararg? ex)
Expand Down
4 changes: 3 additions & 1 deletion src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -1768,7 +1768,9 @@
(current-vals '())
(expr #f))
(if (null? L)
(merge expr (to-nt current-names current-vals))
(or (merge expr (to-nt current-names current-vals))
;; if that result is #f the named tuple is empty
'(call (core NamedTuple)))
(let ((el (car L)))
(cond ((or (assignment? el) (kwarg? el))
(if (not (symbol? (cadr el)))
Expand Down
2 changes: 1 addition & 1 deletion test/namedtuple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ end
@test Meta.lower(Main, Meta.parse("(; f(x))")) == Expr(:error, "invalid named tuple element \"f(x)\"")
@test Meta.lower(Main, Meta.parse("(;1=0)")) == Expr(:error, "invalid named tuple field name \"1\"")

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

# splatting
Expand Down
4 changes: 2 additions & 2 deletions test/syntax.jl
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ macro test999_str(args...); args; end

# blocks vs. tuples
@test Meta.parse("()") == Expr(:tuple)
@test Meta.parse("(;)") == Expr(:block)
@test_skip Meta.parse("(;)") == Expr(:tuple, Expr(:parameters))
@test Meta.parse("(;;;;)") == Expr(:block)
@test_throws ParseError Meta.parse("(,)")
@test_throws ParseError Meta.parse("(;,)")
Expand Down Expand Up @@ -1322,7 +1322,7 @@ end
@test Meta.parse("-(x)^2") == Expr(:call, :-, Expr(:call, :^, :x, 2))
@test Meta.parse("-(a=1)^2") == Expr(:call, :-, Expr(:call, :^, Expr(:(=), :a, 1), 2))
@test Meta.parse("-(x;y)^2") == Expr(:call, :-, Expr(:call, :^, Expr(:block, :x, LineNumberNode(1,:none), :y), 2))
@test Meta.parse("-(;)^2") == Expr(:call, :-, Expr(:call, :^, Expr(:block), 2))
@test_skip Meta.parse("-(;)^2") == Expr(:call, :-, Expr(:call, :^, Expr(:tuple, Expr(:parameters)), 2))
@test Meta.parse("-(;;;;)^2") == Expr(:call, :-, Expr(:call, :^, Expr(:block), 2))
@test Meta.parse("-(x;;;)^2") == Expr(:call, :-, Expr(:call, :^, Expr(:block, :x), 2))
@test Meta.parse("+((1,2))") == Expr(:call, :+, Expr(:tuple, 1, 2))
Expand Down