<< operator for arrays


#1

Any chance to overload operator << (or any other) to mean push! as a syntactic sugar?
e.g.

a = [1,2,3]
a << factorial(5)  # a = [1,2,3,120]

Seems to be clearer and simpler than

push!(a, factorial(5))

#2
f(x) = x << 3

What does this code do when you read it in a file? How would you document f?

Taking from another language that abused <<:

http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Ro-equivalent

C.163: Overload only for operations that are roughly equivalent

Reason Having the same name for logically different functions is confusing and leads to errors when using generic programming. Example > Consider:

void open_gate(Gate& g);   // remove obstacle from garage exit lane
void fopen(const char* name, const char* mode);   // open file

The two operations are fundamentally different (and unrelated) so it is good that their names differ.

void open(Gate& g);   // remove obstacle from garage exit lane
void open(const char* name, const char* mode ="r");   // open file

The two operations are still fundamentally different (and unrelated) but the names have been reduced to their (common) minimum, opening opportunities for confusion.


#3

I agree. May be another operator could fit.


#4

My initial thought was: yeah, an operator for this would be cool, but then remembered writing Scala code and how too many operators can have a downside: https://stackoverflow.com/questions/7888944/what-do-all-of-scalas-symbolic-operators-mean)


#5

Why not just DIY using arrow operators?

julia> ↦(x,a) = pushfirst!(a::AbstractArray,x)
↦ (generic function with 1 method)

julia> ↤(a,x) = push!(a::AbstractArray,x)
↤ (generic function with 1 method)

julia> 3 ↦ [1,2]
3-element Array{Int64,1}:
 3
 1
 2

julia> [1,2] ↤ 3         
3-element Array{Int64,1}:
 1                       
 2                       
 3                       

#6

Operators don’t give any hint that they are mutating which is not ideal.


#7

I think its fare to discuss the possibility for a generally accepted operators for specific base functions. If everybody started DIYing operators for base functions, then reading unfamiliar Julia code would become cumbersome.


#8

Why does pushing to an array need an operator?


#9

Can we use :champagne: for pop!?


#10

Or it would look like APL.


#11

Are you sure that open in Julia open only file?


#12

Also command objects; those are not unrelated operations.


#13

I am sure it doesn’t open the gate to the garage though :wink:


#14

Well, there is a list of mutating operators: +=, -=, *=, etc.
Some similar operators (using =) are not: <=, >=

On the other hand, I think that this combination is not used jet: +>, <+

a <+ factorial(5)  # a = [1,2,3,120]

The less sign (<) gives some notion of direction and the + sign some notion of addition.

Well, this is just an idea and probably will stay as that because the reasons already presented.


#15

Actually, neither += nor *= nor any of the similar operators is mutating in general. They all create a new value which is independent of the previous values because:

x += y

is transformed into

x = x + y

which creates a new value which just happens to also be called x.

This is a common misconception about Julia because those operators are mutating in many languages, like Python for example.


#16

BTW f(a, b) = a * b could mean multiply (numbers, arrays) or concatenate (strings) or append (char to string) or combine (two chars to string) or logical and for booleans or …


#17
julia> <| = push!;
julia> x = []
julia> x <| 1

This next ones a bit suss

julia> (x$$)  = print(x); 
julia> 1 $ 2

There is a good range of special chars from ‘z’ + 40 to 120 that you can get at with clipboard(), eg ‘«’ is ‘z’+49


#18

Those are all a form of multiplication. Concatenation is the group operation in the non-commutative free group over letters. I got to explain this recently to an algebraist and she was delighted.


#19

And opening gate is not a form of opening?


#20

Sure, that wasn’t my example. If you think that gate opening fits into the meaning of the generic open function, go to town. The real litmus test is if it’s plausible that one might be able to write useful generic code that abstracts over file opening and gate opening. It’s common to do such abstraction over files versus processes which is why they share a generic function. It’s pretty unclear if gate opening satisfies that criterion but I suppose it’s possible. On the other hand, it’s 100% clear that bit shifting and array appending do not fit into a common abstraction.