For class MyClass.MyMember
And ArrayofMyClass = [ Instance1, Instance2 ... ]
Can we have:
ArrayofMyClass..MyMember = [ Instance1.MyMember, Instance2.MyMember ... ]
Combining the standard "." for object member and Julia "." for vectorising an operator.
We currently allow ..
to be used as a user- or package-defined operator, which has led to its use in things like Interval arithmetic, EllipsisNotation, and more. So unfortunately changing this would be quite breaking. There's also a competing proposal in https://github.com/JuliaLang/julia/issues/20502 for nested broadcast.
I could have sworn we had an issue for this, but it looks like we just brought it up in the comments of https://github.com/JuliaLang/julia/issues/19169#issuecomment-257475800.
Another idea is to have a clojure-ish synax (.a)
meaning x -> x.a
. But of course _.a
is pretty much just as good.
What about overloading the "." operator and just use x.a
ie, x.a = [x[1].a x[2].a .... ] if x is an array.
Unfortunately, that's not possible because it's ambiguous if you're doing access on the array itself or its elements. Array
itself doesn't have any Julia-accessible fields, but other arrays may. Here's a good example 鈥斅爎anges are arrays that have fields, and Dates are elements that have fields. In this case the names are distinct, but it's entirely possible that some other element type might happen to use the same field names.
julia> using Dates
julia> r = now():Day(1):now()+Day(2)
2019-08-06T12:58:14.878:1 day:2019-08-08T12:58:14.878
julia> r.start
2019-08-06T12:58:14.878
julia> r[1].instant
Dates.UTInstant{Millisecond}(63700779494878 milliseconds)
julia> map(x->x.instant, r)
3-element Array{Dates.UTInstant{Millisecond},1}:
Dates.UTInstant{Millisecond}(63700779494878 milliseconds)
Dates.UTInstant{Millisecond}(63700865894878 milliseconds)
Dates.UTInstant{Millisecond}(63700952294878 milliseconds)
It also just violates the general principle of "don't conflate scalar operations with their vectorized forms" which is the mess we originally inherited from slower languages that need to do that. Let's not make that mistake all over again.
With #24990 or similar, you could do (_.a).(myarray)
or myarray .|> _.a
It also just violates the general principle of "don't conflate scalar operations with their vectorized forms" which is the mess we originally inherited from slower languages that need to do that. Let's not make that mistake all over again.
But this principle is far from uniform across widely-used julia packages. E.g. one can represent a "table" either as a dataframe, or as an array of named tuples. For a dataframe-table extracting a specific field of each row is easy: df[!, :field_name]
; for a named tuple array there is no short notation to that, and the official way is getindex.(df, :field_name)
.
It gets more and more verbose with just one or two additional levels of nesting, e.g. getindex.(getindex.(getindex.(df, :field_name), 3), :inner_field)
. Compare it with (hypothetical) df..field_name.[3]..inner_field
. You can almost get this syntax using the hack from https://discourse.julialang.org/t/neat-way-of-broadcasting-getindex-and-getfield/28706 and inserting a couple of brackets.
Most helpful comment
It also just violates the general principle of "don't conflate scalar operations with their vectorized forms" which is the mess we originally inherited from slower languages that need to do that. Let's not make that mistake all over again.