Skip to content

Commit

Permalink
make generator expressions consume all following comma-separated expr…
Browse files Browse the repository at this point in the history
…essions
  • Loading branch information
JeffBezanson committed Feb 18, 2016
1 parent 0d4fec3 commit bc0956b
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 22 deletions.
27 changes: 15 additions & 12 deletions doc/manual/arrays.rst
Original file line number Diff line number Diff line change
Expand Up @@ -224,25 +224,28 @@ demand, instead of allocating an array and storing them in advance
(see :ref:`_man-interfaces-iteration`).
For example, the following expression sums a series without allocating memory::

.. doctest::

julia> sum(1/n^2 for n=1:1000)
1.6439345666815615

When writing a generator expression with multiple dimensions, it needs to be
enclosed in parentheses to avoid ambiguity::
When writing a generator expression with multiple dimensions inside an argument
list, parentheses are needed to separate the generator from subsequent arguments::

julia> collect(1/(i+j) for i=1:2, j=1:2)
ERROR: function collect does not accept keyword arguments
julia> map(tuple, 1/(i+j) for i=1:2, j=1:2, [1:4;])
ERROR: syntax: invalid iteration specification

In this call, the range ``j=1:2`` was interpreted as a second argument to
``collect``. This is fixed by adding parentheses::
All comma-separated expressions after ``for`` are interpreted as ranges. Adding
parentheses lets us add a third argument to ``map``::

julia> collect((1/(i+j) for i=1:2, j=1:2))
2x2 Array{Float64,2}:
0.5 0.333333
0.333333 0.25
.. doctest::

Note that ``collect`` gathers the values produced by an iterator into an array,
giving the same effect as an array comprehension.
julia> map(tuple, (1/(i+j) for i=1:2, j=1:2), [1:4;])
4-element Array{Any,1}:
(0.5,1)
(0.333333,2)
(0.333333,3)
(0.25,4)

.. _man-array-indexing:

Expand Down
14 changes: 4 additions & 10 deletions src/julia-parser.scm
Original file line number Diff line number Diff line change
Expand Up @@ -1474,10 +1474,7 @@
((eqv? c closer) (loop (cons nxt lst)))
((eq? c 'for)
(take-token s)
(let ((gen (parse-generator s nxt #f)))
(if (eqv? (require-token s) #\,)
(take-token s))
(loop (cons gen lst))))
(loop (cons (parse-generator s nxt) lst)))
;; newline character isn't detectable here
#;((eqv? c #\newline)
(error "unexpected line break in argument list"))
Expand Down Expand Up @@ -1532,11 +1529,8 @@
`(dict_comprehension ,@(cdr c))
(error "invalid dict comprehension"))))

(define (parse-generator s first allow-comma)
(let ((r (if allow-comma
(parse-comma-separated-iters s)
(list (parse-iteration-spec s)))))
`(generator ,first ,@r)))
(define (parse-generator s first)
`(generator ,first ,@(parse-comma-separated-iters s)))

(define (parse-matrix s first closer gotnewline)
(define (fix head v) (cons head (reverse v)))
Expand Down Expand Up @@ -1968,7 +1962,7 @@
ex))
((eq? t 'for)
(take-token s)
(let ((gen (parse-generator s ex #t)))
(let ((gen (parse-generator s ex)))
(if (eqv? (require-token s) #\) )
(take-token s)
(error "expected \")\""))
Expand Down
2 changes: 2 additions & 0 deletions test/parse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -347,3 +347,5 @@ end
# issue #14683
@test_throws ParseError parse("'\\A\"'")
@test parse("'\"'") == parse("'\\\"'") == '"' == "\""[1] == '\42'

@test_throws ParseError parse("f(2x for x=1:10, y")

0 comments on commit bc0956b

Please sign in to comment.