# Inconsistencies in Julia syntax and semantics

**URL:** <https://discourse.julialang.org/t/inconsistencies-in-julia-syntax-and-semantics/78577>\
**Category:** Internals & Design\
**Created:** [March 27, 2022, 11:50pm UTC](https://discourse.julialang.org/t/inconsistencies-in-julia-syntax-and-semantics/78577 "2022-03-27T23:50:42Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![nharr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nharr/32/24698_2.png) [@nharr](https://discourse.julialang.org/u/nharr)\
**Post date:** [March 27, 2022, 11:50pm UTC](https://discourse.julialang.org/t/inconsistencies-in-julia-syntax-and-semantics/78577/1 "2022-03-27T23:50:43Z")

</div>

I’m not sure where is right for an average user to put their thoughts, but I’ll give it a try here.

I’m interested in some inconsistencies (as I see them) in Julia that I can only guess arose from its developmental roots (MATLAB as one influence?):

- Using `size` instead of `shape` as a complement to `reshape`
- Dot notation before for operators and after for functions (.+ vs sin.(…))
- Range indexing returning a copy but passing arrays into functions resulting in a view

These inconsistencies are small – they have little to do with functionality – but I see reconciling them as a way to improve the language. There may be others too. In general, I would be interested in removing any inconsistencies in the core language where possible. Making fundamental details consistent within the language leads to more ease in using the language, especially for those starting out. I value this higher than similarity to other languages or maintaining long traditions. Understandable if others have different priorities. It’s definitely something that would wait for a version jump from 1 to 2 since the initial effect on the entire ecosystem would be significant.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [March 28, 2022, 12:58am UTC](https://discourse.julialang.org/t/inconsistencies-in-julia-syntax-and-semantics/78577/2 "2022-03-28T00:58:56Z")

</div>

> [@nharr](#):
>
> Range indexing returning a copy but passing arrays into functions resulting in a view

passing array into a function is not slicing, it’s just pass-by-sharing.

> [@nharr](#):
>
> Using `size` instead of `shape` as a complement to `reshape`

`length` vs. `resize`? it’s just some wording, `shape` is not occupied I guess technically we can have `const shape = size`.

> [@nharr](#):
>
> Dot notation before for operators and after for functions (.+ vs sin.(…))

this is to eliminate ambiguity, if you use post-fix instead of in-fix, it’s consistent

```julia
julia> (+).([1,2], [3,4])
2-element Vector{Int64}:
 4
 6

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [March 28, 2022, 1:11am UTC](https://discourse.julialang.org/t/inconsistencies-in-julia-syntax-and-semantics/78577/3 "2022-03-28T01:11:01Z")

</div>

> [@nharr](#):
>
> Using `size` instead of `shape` as a complement to `reshape`

[`size`, `reshape` not consistent · Issue #22665 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/22665). Also this is not a syntax.

> [@nharr](#):
>
> Dot notation before for operators and after for functions (.+ vs sin.(…))

See full discussion here. [Alternative syntax for `map(func, x)` · Issue #8450 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/8450). There are debate over `.sin` vs `sin.`. TL;DR is roughly that `.sin` would be a version of `sin` that’s broadcasting which is not the current meaning of the syntax. However, with `sin.()` and with the follow up syntax change, the `.()` becomes the broadcasting call operator and it is consistent with other broadcasting operators. Essentially we picked this syntax since the meaning of it is more useful.

> [@nharr](#):
>
> Range indexing returning a copy but passing arrays into functions resulting in a view

Passing array into functions does not result in a view, it’s literally passing the same object. The “inconsistency” you are talking about is basically that `b = a` is the same object whereas `b = a[:]` is a copy, or that `a[:]` is not the same as `a`. That’s not really a trivial consistency to require and there has been talk about whether `a[:]` should be view by default. So far though, it seems that copy by default and view with `@view` is a good enough compromise. (Also, this is not syntax, this is semantics but I digress)

---

<div class="post-metadata">

**Author:** ![nharr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nharr/32/24698_2.png) [@nharr](https://discourse.julialang.org/u/nharr)\
**Post date:** [March 29, 2022, 1:41am UTC](https://discourse.julialang.org/t/inconsistencies-in-julia-syntax-and-semantics/78577/4 "2022-03-29T01:41:33Z")

</div>

> [@jling](#):
>
> this is to eliminate ambiguity

I don’t see. Could you explain what ambiguity it eliminates? I’m seeing the relationship between operators and functions as part of the motivation for consistency in how the dot syntax is used.

@yuyichao Thanks for the links. It’s good to see these things have been discussed before.

> [@yuyichao](#):
>
> the `.()` becomes the broadcasting call operator

I had never thought that `.()` would be considered an operator. I saw the parallel with operators just being functions with extra allowed syntax, e.g. `+(1, 2)` being the same as `1 + 2`. In fact, it still doesn’t make full sense to me. To broadcast `+` one has to use `.+([1,2], [3,4])`, while `+.([1,2], [3,4])` gives an error. I didn’t find exactly why `sin.(...)` had to be used instead of `.sin(...)` in those threads. Are you saying the fusing broadcasting was somehow impossible with the latter syntax?

> [@yuyichao](#):
>
> this is not syntax, this is semantics

Yes, I’m talking about the whole combination of how Julia appears to and is used by the user – syntax, naming, semantics. (I would need to change the discussion title, but don’t have the option.) The range indexing did need more explanation. I didn’t mean that both operations had a one-to-one relationship. Rather, I was pointing out how mutable objects, like arrays, should be handled consistently by the language: if a copy is desired, then an explicit call to `copy` should be made, otherwise a view is used. When an array is passed into a function, it is received by the function as a reference to the same object in memory, not a copy. When an element within an array is indexed that element itself is accessed, not a copy. I would expect then that when I index a sequence of elements within an array, those same elements in memory would be accessed, not a copy. And for any of these cases if I want a copy, I should do it explicitly.

As an addendum about performance (since that is a main objective in Julia), returning a view into an array always uses less memory and sometimes uses less time (depending on the access pattern). Returning a copy always uses more memory and sometimes uses less time. So defaulting to returning a view would be a win and a tie instead of a loss and a tie.

---

<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 29, 2022, 6:33am UTC](https://discourse.julialang.org/t/inconsistencies-in-julia-syntax-and-semantics/78577/5 "2022-03-29T06:33:58Z")

</div>

> [@nharr](#):
>
> When an element within an array is indexed that element itself is accessed, not a copy. I would expect then that when I index a sequence of elements within an array, those same elements in memory would be accessed, not a copy.

These two cases actually perform equivalently wrt copying elements. With both `b = a[123]` and `b = a[123:456]`, one cannot use `b` to set any element in `a`: they are both semantically copies of the element(s) in the original array, if they are immutable themselves. For elements that are mutable, they can of course be mutated through `b`, and those changes would be visible through `a` - again, same in both cases.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [March 29, 2022, 7:31am UTC](https://discourse.julialang.org/t/inconsistencies-in-julia-syntax-and-semantics/78577/6 "2022-03-29T07:31:40Z")

</div>

> [@nharr](#):
>
> Dot notation before for operators and after for functions (.+ vs sin.(…))

I have also wished occasionally that operators were dotted like this: `x +. y`, I think it would be easier to remember. I _do_ think that putting the dot after the function was the right call, but it should perhaps have been like that for operators too.

> [@jling](#):
>
> if you use post-fix instead of in-fix, it’s consistent
> 
> ```julia
> julia> (+).([1,2], [3,4])
> 
> ```

IMHO this example actually makes it worse, not better 😬 But, yes, it is indeed consistent for function call syntax.

I also wish slices made views, but that’s not actually an inconsistency.

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [March 29, 2022, 8:22am UTC](https://discourse.julialang.org/t/inconsistencies-in-julia-syntax-and-semantics/78577/7 "2022-03-29T08:22:17Z")

</div>

> [@nharr](#):
>
> about performance (since that is a main objective in Julia), returning a view into an array always uses less memory and sometimes uses less time (depending on the access pattern). Returning a copy always uses more memory and sometimes uses less time. So defaulting to returning a view would be a win and a tie instead of a loss and a tie.

Well I support this default choice as it’s safer (and you have the faster option). E.g. if you would return a view to an array from a function, and share memory, even to other functions, and overwrite each others memory, arbitrarily down the line, it seems like a recipe for disaster.

It reminded me of Rich Hickey’s excellent keynote (my favorite programming talk), i.e. that is an instance of what he calls place-oriented programming (as opposed to “information technology”):

> **[Keynote: The Value of Values](https://www.infoq.com/presentations/Value-Values/)**
>
> Rich Hickey compares value-oriented programming with place-oriented programming concluding that the time of imperative languages has passed and it is the time of functional programming.

> **[What is place oriented thinking?](https://clojureverse.org/t/what-is-place-oriented-thinking/5076)**
>
> I’ve heard Rich Hickey talk about it, and it’s mentioned around. I feel that it relates to immutability, references, and how Clojure’s state management. But I don’t feel like I understand it. Any takers? Teodor

What seems possible, is an optimization, that Julia’s compiler would “add” (invisible) `@view` where it can proof the end-result the same. At some cost to compile time… Maybe this is only likely to work with-in functions, and I haven’t checked, I doubt it’s done already. Also some tools could help (linters, or not the right tool?) by suggesting this, then you would make it explicit in your code, with no compilation-time cost.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [March 29, 2022, 9:12am UTC](https://discourse.julialang.org/t/inconsistencies-in-julia-syntax-and-semantics/78577/8 "2022-03-29T09:12:19Z")

</div>

> [@Palli](#):
>
> Maybe this is only likely to work with-in functions, and I haven’t checked, I doubt it’s done already.

> <https://github.com/JuliaLang/julia/pull/43800>
>
> This commit ports \[EscapeAnalysis.jl\](https://github.com/aviatesk/EscapeAnalysis….jl) into Julia base.
> You can find the documentation of this escape analysis at \[this GitHub page\](https://aviatesk.github.io/EscapeAnalysis.jl/dev/)\[^1\].
> 
> \[^1\]: The same documentation will be included into Julia's developer
> documentation by this commit.
> 
> This escape analysis will hopefully be an enabling technology for various
> memory-related optimizations at Julia's high level compilation pipeline.
> Possible target optimization includes alias aware SROA (#43888),
> array SROA (#43909), \`mutating\_arrayfreeze\` optimization (#42465),
> stack allocation of mutables, finalizer elision and so on\[^2\].
> 
> \[^2\]: It would be also interesting if LLVM-level optimizations can consume
> IPO information derived by this escape analysis to broaden
> optimization possibilities.
> 
> The primary motivation for porting EA in this PR is to check its impact
> on latency as well as to get feedbacks from a broader range of developers.
> The plan is that we first introduce EA in this commit, and then merge the
> depending PRs built on top of this commit like #43888, #43909 and #42465
> 
> This commit simply defines EA inside Julia base compiler and
> enables the existing test suite with it. In this commit, we just run EA
> before inlining to generate IPO cache. The depending PRs, EA will be
> reran after inlining to be used for various local optimizations.
> 
> \---
> 
> \- \[x\] IPO cache generation
> \- \[x\] improve performance (reduce additional allocations to ~105% or such)
