How to use operators as functions in Julia? - julia

I saw in someone code that they were using the + operator as if it was a function by doing +(1,2,3). Is it possible to use operators as functions in Julia?
In addition, I also saw things like A ⊗ B, where the behaviour of ⊗ was customizable. How can I do such a thing, and is there a list of symbols I can use in this way?

Yes, you indeed can use operators as functions in Julia.
From the Julia Docs:
In Julia, most operators are just functions with support for special syntax. (The exceptions are operators with special evaluation semantics like && and ||. These operators cannot be functions since Short-Circuit Evaluation requires that their operands are not evaluated before evaluation of the operator.) Accordingly, you can also apply them using parenthesized argument lists, just as you would any other function:
julia> 1 + 3 + 5
9
julia> +(1,3,5)
9
julia> 1 * 3 * 5
15
julia> *(1,3,5)
15
julia> h = *;
julia> h(1,3,5)
15
In addition, Julia allows you to define your own meaning to operators, and makes quite a few symbols available for the purpose. You can find the list of available symbols here:|
https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm
and define them as such:
⊗(a, b) = a * 3 - b # or some other arbitrary thing
a ⊗ b == a * 3 - b # true

Related

Why does Julia return different results for equivalent expressions? 6÷2(1+2) and 6÷2*(1+2)

I typed the following in Julia's REPL:
julia> 6÷2(1+2)
1
julia> 6÷2*(1+2)
9
Why are the different results output?
Presh Talwalkar says 9 is correct in the movie
6÷2(1+2) = ? Mathematician Explains The Correct Answer - YouTube
YouTube notwithstanding, there is no correct answer. Which answer you get depends on what precedence convention you use to interpret the problem. Many of these viral "riddles" that go around periodically are contentious precisely because they are intentionally ambiguous. Not a math puzzle really, it's just a parsing problem. It's no deeper than someone saying a sentence with two interpretations. What do you do in that case in real life? You just ask which one they meant. This is no different. For this very reason, the ÷ symbol isn't often used in real mathematical notation—fraction notation is used instead, which clearly disambiguates this as either:
6
- (1 + 2) = 9
2
or as
6
--------- = 1
2 (1 + 2)
Regarding Julia specifically, this precedence behavior is documented here:
https://docs.julialang.org/en/v1/manual/integers-and-floating-point-numbers/#man-numeric-literal-coefficients
Specifically:
The precedence of numeric literal coefficients is slightly lower than that of unary operators such as negation. So -2x is parsed as (-2) * x and √2x is parsed as (√2) * x. However, numeric literal coefficients parse similarly to unary operators when combined with exponentiation. For example 2^3x is parsed as 2^(3x), and 2x^3 is parsed as 2*(x^3).
and the note:
The precedence of numeric literal coefficients used for implicit multiplication is higher than other binary operators such as multiplication (*), and division (/, \, and //). This means, for example, that 1 / 2im equals -0.5im and 6 // 2(2 + 1) equals 1 // 1.

StepRange description in Julia

while working in julia programming, for creating an array instead of using a=[1:1:20...] i used a=[1:1:20] and it created an array saying "1-element Array{StepRange{Int64,Int64},1}".
What does this "1-element Array{StepRange{Int64,Int64},1}" mean? what StepRange means?
From the documentation of StepRange (type ?StepRange in the Julia REPL to see this):
StepRange{T, S} <: OrdinalRange{T, S}
Ranges with elements of type T with spacing of type S. The step
between each element is constant, and the range is defined in terms
of a start and stop of type T and a step of type S. Neither T nor S
should be floating point types. The syntax a:b:c with b > 1 and a,
b, and c all integers creates a StepRange.
So, for example
julia> typeof(1:1:20)
StepRange{Int64,Int64}
and
julia> [1:1:20]
1-element Array{StepRange{Int64,Int64},1}:
1:1:20
thus constructs a Vector (1D Array) containing one StepRange. If you want to materialize the lazy StepRange I would recommend collect(1:1:20) instead of using splatting ([1:1:20...]).
You can access start / step / stop fields of a StepRange using:
julia> r = 1:1:20
julia> r.start
1
julia> r.stop
20
julia> r.step
1

Override precedence of operator in Julia

In electrical engineering the parallel connection of impedances could be expressed by the parallel operator ∥. For a vector of impedances z[k] the following function can be defined:
function ∥(z...)
ypar = 0
for k=1:length(z)
ypar = ypar + 1/z[k]
end
return 1/ypar
end
The precedence of Julia operators is defined in https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm. The parallel operator ∥ is defined on the same precedence level as relational operators. Consider the following examples:
julia> Base.operator_precedence(:∥)
6
julia> Base.operator_precedence(:+)
9
julia> Base.operator_precedence(:*)
11
julia> Base.operator_precedence(:^)
13
In the simple case of two impedances z[1] and z[2] the parallel impedance is equal to z[1]*z[2]/(z[1]+z[2]). From my personal understanding the precedence of the parallel operator is higher or at least equal than the multiplication operator *.
My question is: how can I change the precedence of the ∥ operator from 6 to 11, 12 or 13?
I'll offer an answer you weren't looking for.
This impedance calculation is often referred to as a parallel sum, which I propose you represent with the ++ operator (two sums in parallel!). This could be defined in Julia as:
++(xs...) = 1/sum(1/x for x ∈ xs)
The precedence of ++ is the same as +. This seems undesirable at first, but I will argue that it is right.
The properties of the parallel sum—commutative, associative, and distributive—are exactly the same as addition, and the identities are just inverses of each other (0 vs. ∞). Both operators represent the addition of a component, just in different arrangements. And, just as the parallel sum can be defined in terms of the regular sum as a++b == 1/(1/a+1/b), the normal sum can be defined in terms of the parallel sum as a+b == 1/(1/a++1/b).
It turns out, it's most natural to give the parallel sum the same operator precedence as the normal sum. It's unfortunate that lots of electrical engineers give it precedence other than this—clearly because they haven't thought through the operator's properties.

In R, how can I determine the operator precedence of user defined infix operators?

Suppose I have two custom infix operators in R: %foo% and %bar%.
I have expressions that use both operators, such as:
x %foo% y %bar% z
How can I determine the operator precedence of %foo% and %bar%?
How can I change the precedence so that, for example, %bar% always executes before %foo%? In the example above this would be the same as:
x %foo% (y %bar% z)
I don't think this is explicitly documented, but implicit in the R language documentation is that infix operators are all of equal precedence and so are executed from left to right. This can be demonstrated as follows:
`%foo%` <- `+`
`%bar%` <- `*`
1 %bar% 2 %foo% 3
#5
1 %foo% 2 %bar% 3
#9
The only option I can think of would be to redefine one of the existing operators to do what you wanted. However, that itself would have repercussions so you might want to limit it to within a function.
It's also worth noting that using substitute does not change the operator precedence already set when the expression is first written:
eval(substitute(2 + 2 * 3, list(`+` = `*`, `*` = `+`)))
#10
2 * 2 + 3
#7
How can I determine the operator precedence of %foo% and %bar%?
You can't. R doesn't allow you to set the precedence of custom infix operators. User-defined infix operators have the default precedence rules which means they will be evaluated from left to right.
One reason for this limitation is that it would be extremely difficult and limiting to implement and maintain a set of precendence rules for infix operators. Imagine that you loaded an R package which comes with some custom infix operators. Then the relationship of the infix operators from the package to the %foo% and %bar% which you created would need to be defined. This will quickly become a serious burden.
As an example, imagine that package one contains infix operator %P1IF% and package two contains infix operator %P2IF%. Each package has defined that its infix operator should have the highest precedence. If you were to load both package one and two, then the following expression would be undefined:
v1 %P1IF% v2 %P2IF% v3
(v1 %P1IF% v2) %P2IF% v3 # package 2 doesn't expect this
v1 %P1IF% (v2 %P2IF% v3) # package 1 doesn't expect this
Regardless of what the precedence might be the result for one of the two packages might be incorrect.

Prolog =:= operator

There are some special operators in Prolog, one of them is is, however, recently I came across the =:= operator and have no idea how it works.
Can someone explain what this operator does, and also where can I find a predefined list of such special operators and what they do?
I think the above answer deserves a few words of explanation here nevertheless.
A short note in advance: Arithmetic expressions in Prolog are just terms ("Everything is a term in Prolog"), which are not evaluated automatically. (If you have a Lisp background, think of quoted lists). So 3 + 4 is just the same as +(3,4), which does nothing on its own. It is the responsibility of individual predicates to evaluate those terms.
Several built-in predicates do implicit evaluation, among them the arithmetic comparsion operators like =:= and is. While =:= evaluates both arguments and compares the result, is accepts and evaluates only its right argument as an arithmetic expression.
The left argument has to be an atom, either a numeric constant (which is then compared to the result of the evaluation of the right operand), or a variable. If it is a bound variable, its value has to be numeric and is compared to the right operand as in the former case. If it is an unbound variable, the result of the evaluation of the right operand is bound to that variable. is is often used in this latter case, to bind variables.
To pick up on an example from the above linked Prolog Dictionary: To test if a number N is even, you could use both operators:
0 is N mod 2 % true if N is even
0 =:= N mod 2 % dito
But if you want to capture the result of the operation you can only use the first variant. If X is unbound, then:
X is N mod 2 % X will be 0 if N is even
X =:= N mod 2 % !will bomb with argument/instantiation error!
Rule of thumb: If you just need arithmetic comparison, use =:=. If you want to capture the result of an evaluation, use is.
?- 2+3 =:= 6-1.
true.
?- 2+3 is 6-1.
false.
Also please see docs http://www.swi-prolog.org/pldoc/man?predicate=is/2
Complementing the existing answers, I would like to state a few additional points:
An operator is an operator
First of all, the operator =:= is, as the name indicates, an operator. In Prolog, we can use the predicate current_op/3 to learn more about operators. For example:
?- current_op(Prec, Type, =:=).
Prec = 700,
Type = xfx.
This means that the operator =:= has precedence 700 and is of type xfx. This means that it is a binary infix operator.
This means that you can, if you want, write a term like =:=(X, Y) equivalently as X =:= Y. In both cases, the functor of the term is =:=, and the arity of the term is 2. You can use write_canonical/1 to verify this:
?- write_canonical(a =:= b).
=:=(a,b)
A predicate is not an operator
So far, so good! This has all been a purely syntactical feature. However, what you are actually asking about is the predicate (=:=)/2, whose name is =:= and which takes 2 arguments.
As others have already explained, the predicate (=:=)/2 denotes arithmetic equality of two arithmetic expressions. It is true iff its arguments evaluate to the same number.
For example, let us try the most general query, by which we ask for any solution whatsoever, using variables as arguments:
?- X =:= Y.
ERROR: Arguments are not sufficiently instantiated
Hence, this predicate is not a true relation, since we cannot use it for generating results! This is a quite severe drawback of this predicate, clashing with what you commonly call "declarative programming".
The predicate only works in the very specific situation that both arguments are fully instantiated. For example:
?- 1 + 2 =:= 3.
true.
We call such predicates moded because they can only be used in particular modes of usage. For the vast majority of beginners, moded predicates are a nightmare to use, because they require you to think about your programs procedurally, which is quite hard at first and remains hard also later. Also, moded predicates severely limit the generality of your programs, because you cannot use them on all directions in which you could use pure predicates.
Constraints are a more general alternative
Prolog also provides much more general arithmetic predicates in the form of arithmetic constraints.
For example, in the case of integers, try your Prolog system's CLP(FD) constraints. One of the most important CLP(FD) constraints denotes arithmetic equality and is called (#=)/2. In complete analogy to (=:=)/2, the operator (#=)/2 is also defined as an infix operator, and so you can write for example:
| ?- 1 + 2 #= 3.
yes
I am using GNU Prolog as one particular example, and many other Prolog systems also provide CLP(FD) implementations.
A major attraction of constraints is found in their generality. For example, in contrast to (=:=)/2, we get with the predicate (#=)/2:
| ?- X + 2 #= 3.
X = 1
| ?- 1 + Y #= 3.
Y = 2
And we can even ask the most general query:
| ?- X #= Y.
X = _#0(0..268435455)
Y = _#0(0..268435455)
Note how naturally these predicates blend into Prolog and act as relations between integer expressions that can be queried in all directions.
Depending on the domain of interest, my recommendition is to use CLP(FD), CLP(Q), CLP(B) etc. instead of using more low-level arithmetic predicates.
Also see clpfd, clpq and clpb for more information.
Coincidentally, the operator =:= is used by CLP(B) with a completely different meaning:
?- sat(A =:= B+1).
A = 1,
sat(B=:=B).
This shows that you must distinguish between operators and predicates. In the above case, the predicate sat/1 has interpreted the given expression as a propositional formula, and in this context, =:= denotes equality of Boolean expressions.
I found my own answer, http://www.cse.unsw.edu.au/~billw/prologdict.html
Its an ISO core standard predicate operator, which cannot be bootstrapped from unification (=)/2 or syntactic equality (==)/2. It is defined in section 8.7 Arithmetic Comparison. And it basically behaves as follows:
E =:= F :-
X is E,
Y is F,
arithmetic_compare(=, X, Y).
So both the left hand side (LHS) and right hand side (RHS) must be arithmetic expressions that are evaluted before they are compared. Arithmetic comparison can compare across numeric types. So we have:
GNU Prolog 1.4.5 (64 bits)
?- 0 = 0.0.
no
?- 0 == 0.0
no
?- 0 =:= 0.0.
yes
From Erlang I think it could be good to annotate that as syntax are mostly look alike to Prolog.
=:= expression is meaning of exactly equal.
such as in JavaScript you can use === to also see if the type of the variables are same.
Basically it's same logic but =:= is used in functional languages as Prolog, Erlang.
Not much information but hope it could help in some way.
=:= is a comparison operator.A1 =:= A2 succeeds if values of expressions A1 and A2 are equal.
A1 == A2 succeeds if terms A1 and A2 are identical;

Resources