# Keyword behaves differently using \`;\` or \`,\`

**URL:** <https://discourse.julialang.org/t/keyword-behaves-differently-using-or/78233>\
**Category:** Internals & Design\
**Created:** [March 21, 2022, 7:02pm UTC](https://discourse.julialang.org/t/keyword-behaves-differently-using-or/78233 "2022-03-21T19:02:05Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [March 21, 2022, 7:02pm UTC](https://discourse.julialang.org/t/keyword-behaves-differently-using-or/78233/1 "2022-03-21T19:02:05Z")

</div>

Is this intended? It had @ccoffrin and I quite confused (not the subtle difference between `,` and `;`):

```julia
julia> sum(0.0 for i in []; init = 0.0)
0.0

julia> sum(0.0 for i in [], init = 0.0)
ERROR: ArgumentError: reducing over an empty collection is not allowed
Stacktrace:
  [1] _empty_reduce_error()
    @ Base ./reduce.jl:299
  [2] mapreduce_empty(f::Function, op::Base.BottomRF{typeof(Base.add_sum)}, T::Type)
    @ Base ./reduce.jl:342
  [3] reduce_empty(op::Base.MappingRF{var"#36#37", Base.BottomRF{typeof(Base.add_sum)}}, #unused#::Type{Tuple{Any, Float64}})
    @ Base ./reduce.jl:329
  [4] reduce_empty_iter
    @ ./reduce.jl:355 [inlined]
  [5] reduce_empty_iter
    @ ./reduce.jl:354 [inlined]
  [6] foldl_impl
    @ ./reduce.jl:49 [inlined]
  [7] mapfoldl_impl
    @ ./reduce.jl:44 [inlined]
  [8] #mapfoldl#214
    @ ./reduce.jl:160 [inlined]
  [9] mapfoldl
    @ ./reduce.jl:160 [inlined]
 [10] #mapreduce#218
    @ ./reduce.jl:287 [inlined]
 [11] mapreduce
    @ ./reduce.jl:287 [inlined]
 [12] #sum#221
    @ ./reduce.jl:501 [inlined]
 [13] sum
    @ ./reduce.jl:501 [inlined]
 [14] #sum#222
    @ ./reduce.jl:528 [inlined]
 [15] sum(a::Base.Generator{Base.Iterators.ProductIterator{Tuple{Vector{Any}, Float64}}, var"#36#37"})
    @ Base ./reduce.jl:528
 [16] top-level scope
    @ REPL[36]:1

```

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [March 21, 2022, 7:05pm UTC](https://discourse.julialang.org/t/keyword-behaves-differently-using-or/78233/2 "2022-03-21T19:05:09Z")

</div>

I guess the answer is “yes”, but it is sure confusing:

```nohighlight
julia> f() = sum(0.0 for i in [], init = 0.0)
f (generic function with 1 method)

julia> g() = sum(0.0 for i in []; init = 0.0)
g (generic function with 1 method)

julia> @code_lowered f()
CodeInfo(
1 ─ #9 = %new(Main.:(var"#9#10"))
│ %2 = #9
│ %3 = Base.vect()
│ %4 = Base.product(%3, 0.0)
│ %5 = Base.Generator(%2, %4)
│ %6 = Main.sum(%5)
└── return %6
)

julia> @code_lowered g()
CodeInfo(
1 ─ #11 = %new(Main.:(var"#11#12"))
│ %2 = #11
│ %3 = Base.vect()
│ %4 = Base.Generator(%2, %3)
│ %5 = (:init,)
│ %6 = Core.apply_type(Core.NamedTuple, %5)
│ %7 = Core.tuple(0.0)
│ %8 = (%6)(%7)
│ %9 = Core.kwfunc(Main.sum)
│ %10 = (%9)(%8, Main.sum, %4)
└── return %10

```

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [March 21, 2022, 7:11pm UTC](https://discourse.julialang.org/t/keyword-behaves-differently-using-or/78233/3 "2022-03-21T19:11:31Z")

</div>

These both work so it’s about generator parsing I think:

```julia
julia> sum((0.0 for i in []); init = 0.0)
0.0

julia> sum((0.0 for i in []), init = 0.0)
0.0

```

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [March 21, 2022, 7:13pm UTC](https://discourse.julialang.org/t/keyword-behaves-differently-using-or/78233/4 "2022-03-21T19:13:54Z")

</div>

Yeah, the one with the comma is equivalent to

```julia
sum(0.0 for i in [], init in 0.0)

```

Perhaps if numbers were not iterable then the error message would be better.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [March 21, 2022, 7:15pm UTC](https://discourse.julialang.org/t/keyword-behaves-differently-using-or/78233/5 "2022-03-21T19:15:33Z")

</div>

Ah actually the keyword in the second example is parsed as a third arg of the generator expression, which seems to be ignored, so the whole thing acts as if no keyword had been set. That’s why this works as well `sum(0.0 for i in [], init = 0.0; init = 0.0)`, so the generator doesn’t care about this syntax appendage. I would think this is a parsing bug then.

```julia
julia> Meta.@dump sum(0.0 for i in [], init = 0.0)
Expr
  head: Symbol call
  args: Array{Any}((2,))
    1: Symbol sum
    2: Expr
      head: Symbol generator
      args: Array{Any}((3,))
        1: Float64 0.0
        2: Expr
          head: Symbol =
          args: Array{Any}((2,))
            1: Symbol i
            2: Expr
              head: Symbol vect
              args: Array{Any}((0,))
        3: Expr
          head: Symbol =
          args: Array{Any}((2,))
            1: Symbol init
            2: Float64 0.0

```

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [March 21, 2022, 7:23pm UTC](https://discourse.julialang.org/t/keyword-behaves-differently-using-or/78233/6 "2022-03-21T19:23:15Z")

</div>

I’m squarely in the field “_ **always** _ use semicolon for keyword arguments and forget about those nasty edge cases where a comma would be a problem”.

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [March 21, 2022, 7:27pm UTC](https://discourse.julialang.org/t/keyword-behaves-differently-using-or/78233/7 "2022-03-21T19:27:21Z")

</div>

We do get a better error message if the first iterator in the generator expression is not empty:

```julia
julia> struct A end

julia> sum((i, j) for i in [1, 2], j = A())
ERROR: MethodError: no method matching iterate(::A)

```

But if the first iterator is empty, then we still get the original error message:

```julia
julia> sum((i, j) for i in [], j = A())
ERROR: ArgumentError: reducing over an empty collection is not allowed

```

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [March 21, 2022, 7:46pm UTC](https://discourse.julialang.org/t/keyword-behaves-differently-using-or/78233/8 "2022-03-21T19:46:49Z")

</div>

Python:

```python
In [2]: sum(1 for _ in [], start=0)
  File "<ipython-input-2-646ca842f927>", line 1
    sum(1 for _ in [], start=0)
        ^
SyntaxError: Generator expression must be parenthesized

In [3]: sum((1 for _ in []), start=0)
Out[3]: 0

```

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [March 22, 2022, 6:39am UTC](https://discourse.julialang.org/t/keyword-behaves-differently-using-or/78233/9 "2022-03-22T06:39:05Z")

</div>

I once honestly thought it’s a bug in sum, and created an issue: [https://github.com/JuliaLang/julia/issues/39669](https://github.com/JuliaLang/julia/issues/39669).  
Turns out this is just due to the lack of ; or () indeed.

---

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [March 22, 2022, 8:01am UTC](https://discourse.julialang.org/t/keyword-behaves-differently-using-or/78233/10 "2022-03-22T08:01:23Z")

</div>

I am curious about these nasty edge cases.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [March 22, 2022, 2:47pm UTC](https://discourse.julialang.org/t/keyword-behaves-differently-using-or/78233/11 "2022-03-22T14:47:50Z")

</div>

I told you, I forgot what they are because I don’t run into them anymore 🙂

But for example the syntax `f(; a)` for `f(; a=a)` works only if you explicitly use the semicolon. Or also slurping all the keyword arguments, `f(x; kwargs...)`, works only with semicolon and not the colon. There are probably other things that wouldn’t work but I just don’t remember them. I’m pretty sure I already ran into the issue reported at the top of this thread, before stopping using the comma. My suggestion is: always use the semicolon to start the list of keyword arguments. By “always” I mean literally _ **always** _, also when there are no positional arguments.

---

<div class="post-metadata">

**Author:** ![StevenWhitaker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevenwhitaker/32/9749_2.png) [@StevenWhitaker](https://discourse.julialang.org/u/StevenWhitaker)\
**Post date:** [March 22, 2022, 3:07pm UTC](https://discourse.julialang.org/t/keyword-behaves-differently-using-or/78233/12 "2022-03-22T15:07:18Z")

</div>

> [@jar1](#):
>
> `SyntaxError: Generator expression must be parenthesized`

But apparently only in that case, because this works without parentheses:

```python
>>> sum(1 for i in [1,2,3])
3

```

But I’m not sure why Python requires parentheses when keyword arguments are involved, because the language doesn’t seem to allow multidimensional generators like Julia does:

```python
>>> (1 for i in [1,2,3], j in [1,2])
  File "<stdin>", line 1
    (1 for i in [1,2,3], j in [1,2])
                       ^
SyntaxError: invalid syntax

```

so it seems like there is no ambiguity to resolve by requiring parentheses.

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [March 22, 2022, 6:07pm UTC](https://discourse.julialang.org/t/keyword-behaves-differently-using-or/78233/13 "2022-03-22T18:07:39Z")

</div>

The keyword is optional so it is disambiguating between

```python
sum((x for x in xs), y)
sum(x for x in (xs, y))

```

---

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [March 22, 2022, 9:17pm UTC](https://discourse.julialang.org/t/keyword-behaves-differently-using-or/78233/14 "2022-03-22T21:17:21Z")

</div>

Thanks. I am also in the habit of always using the colon, albeit for the more superficial reason that doing so forces me to remind myself of how I defined my functions and keep them consistent.
