# Understanding few syntax of Julia code

I am very new to Julia language, so I started to read the documentation and all builtin functions. Now, I am learning one github project for my work. Since I am more comfortable with Python, I tried to translate Julia’s code to python by my understanding, but I got a few weird syntaxes that I didn’t understand and I got stuck with them. Can anyone point me out the meaning of those syntaxes? Thanks in advance!

syntax that I don’t understand

those julia code line that I didn’t understand because I didn’t find them either in documentations.

`var1 = Tuple{Integer, Vector}[]`

here we declare object var 1, what’s real example for that? what’s python version?

also if `X::Matrix, n::Int`, then what’s the meaning of `?` in the below? How should I code this in python?

`K = [( i >= j ? dot(view(X,:,i), view(X,:,j)) : 0.0 )::Float64 for i=1:n, j=1:n]`

I am not sure meaning of `->` in below:

``````for i=1:n
id_i = find(x -> x[1] == i, var1)
xi_i_list =  map(x -> x[2], var1[id_i])
``````

lastly, I just don’t understand the meaning of `.>` in below:

``````act= zeros(100)
alpha = zeros(10)

for i=1:100
idx = find(x::Tuple{Integer, Vector} -> x[1] == i, var1)
act[i] = sum(alpha[idx] .> 1e-3)
``````

As a newbie, I am trying to understand the role of `find()`, `map()`. To the best, I wish I could write the above Julia code with Python. But I have a hard time understanding the code. Can anyone give possible interpretations and corresponding python codes for learning purposes? Thanks in advance!

Many of these things can’t be written in Python because Python fundamentally doesn’t have the same concepts in it.

``````var1 = Tuple{Integer, Vector}[]
``````

This creates an empty array whose element type is `Tuple{Integer, Vector}` and binds that array to `var1`.

The meaning of `?` in your example is that it’s part of the ternary operator. Essentially `x ? y : z` is equivalent to the following Julia code:

``````if x
y
else
z
end
``````

`x -> x[1] == 5` creates an anonymous function. In Python these are lambdas.

``````alpha[idx] .> 1e-3
``````

is an instance of broadcasting. It’s equivalent to something like:

``````map(x -> x[idx] > 1e-3, alpha)
``````
14 Likes

Thank you! I am wondering how should we simplify this `K = [( i >= j ? dot(view(X,:,i), view(X,:,j)) : 0.0 )::Float64 for i=1:n, j=1:n]`? Is there any simple Julia code for this?

if `var1 = Tuple{Integer, Vector}[]` creates empty array, how this lines

``````act= zeros(100)
alpha = zeros(10)

for i=1:100
idx = find(x::Tuple{Integer, Vector} -> x[1] == i, var1)
act[i] = sum(alpha[idx] .> 1e-3)
``````

can be written in simpler way?

I sitll don’t understand `find()`, `map()` function. for instance, if `idi` as:

``````function idi(m::Integer, i::Integer)
return ((i-1)*m+1 : i*m)::UnitRange{Int64}
end
``````

, then what’s meaning of this: `map(i -> idi(20, i), collect(1:5))`? I should avoid asking more than one question, but it is all about syntax of Julia, and I might need Julia community support.

1 Like

For the first, `@views K = [( i >= j ? dot((X[:,i], X[:,j]) : 0.0 ) for i=1:n, j=1:n]`
For the second, I would replace the inside of the `for` loop with

``````    idx = find(x -> x[1] == i, var1)
act[i] = sum(x -> x > 1e-3, alpha[idx])
``````

Thanks a lot! how should we understand `find()` and `map()` function in julia? for instance if `idi=collect(1:10)`, then `map(10 -> idi(20, 10), collect(1:5))` ? how do write this in python? any idea? Thanks!

‘map(f, c)’ takes an anonymus function ‘f’(‘x->x^2’ is an example. x is the input, and x^2 is the output) and maps it to an iterable/collection ‘c’. Mapping means applyng the function elementwise.

But the easiest thing is to read the docs, and play with a couple of examples until you het a feel for it: Collections and Data Structures · The Julia Language

2 Likes

Nitpick: not just anonymous functions, it can also take named functions, like `sin` or `sort`.

(I mention this, because many people tend to create anonymous functions for `map`, even though it’s unnecessary, such as `map(x->sin(x), X)`, when you only really need `map(sin, X)`.)

4 Likes

Good nitpick. As I formulated myself incorrectly, I was clearly not sharp on this detail. Thanks

This provides very good examples to be addressed in Julia doc for the convenience of beginners. When I started to learn Julia, I feel really frustrated encoutering these syntax sugars and strange symbols. I think it may be a good idea to list all these things (links are OK) in a single page of the doc and make it available in the tutorial section.

3 Likes
4 Likes

Just to nitpick, Python has a ternary operator, but it is:

``````expression_if_true if condition else expression_if_false
``````

``````condition ? expression_if_true : expression_if_false
``````

So ternaries should be perfectly translatable to Python.

While this is correct, I am not sure if this helps that much someone coming from Python, because I am not sure if in Python the classic `if ... else` blocks can return values (i.e., are expressions).

1 Like

As far as I remember, the ternary operator in python has a slightly unusual syntax.

``````expr1 ? expr2 : expr3
``````

becomes

``````expr2 if expr1 else expr3
``````

which indeed is an expression returning a value. For example

``````>>> [x if x % 2 == 0 else 0 for x in range(10)]
[0, 0, 2, 0, 4, 0, 6, 0, 8, 0]``````
1 Like

I was wrong about the what expression goes in which clause in Python (have corrected it now, what a bizarre choice, to not have the condition first). However, I was saying that, different from Julia, the traditional `if ... else ..` blocks does not seem to be expressions but only statements. In other words, you can do this in Julia:

``````x = if some_condition
...
else
...
end
``````

but I am not sure you can do something like this in Python

``````x = if(condition):
...
else:
...
``````
1 Like

You’re right that Python has its main control flow structure as statements only and not expressions; this is done to mostly prevent using blocks with line breaks inside of other blocks.

3 Likes

This code is sub-optimal. `var1` is defined as `Tuple{Integer, Vector}[]` which is rather bad, since `Integer` and `Vector` are abstract types and this affect performance negatively.

It seems that the intention was to use `Tuple{Int, Vector{Float64}}[]`, i.e. `var1` is a `Vector` (`list` in python terminology) of tuples, which looks like `[(1, [1.0, 2.0]), (2, [3.0, 4.0, 5.0])]`. You can see the result of this choice in the fact, that `K` has `::Float64` annotation. Normally, compiler infer types like these automatically.

Secondly, it looks like an improper structure for the task itself, because

``````for i=1:n
id_i = find(x -> x[1] == i, var1)
xi_i_list =  map(x -> x[2], var1[id_i])
``````

just extract all values by the `i` key. For example, if `var1 = [(1, [1., 2.]), (2, [3., 4.]), (1, [5., 6.])]` then `xi_i_list` is just

``````# i = 1
[[1., 2.], [5., 6.]]

# i = 2
[[3., 4.]]
``````

or in more details, if `i == 1`, then `find` (actually it is `findall` in modern Julia, looks like this code is outdated) find all indices, where first value of the tuple is `1`, so `id_i = [1, 3]`. Following `map` extracts second element of the tuple and put them all together in a list, producing necessary result.

This looks overly complicated and not very efficient. Depending on a task, one can either use `dict` from the start, so python version would looks like

``````var1 = {1: [[1., 2.], [5., 6.]], 2: [[3., 4.]]}
``````

or (even better), make `Vector{Vector{Vector{Float64}}}`

``````var1 = [[[1., 2.], [5., 6.]], [[3., 4.]]]
``````

and `xi_i_list` is just `var1[i]`. Of course it requires accurate manipulation with `var1`, but I guess it is manageable.

If structure can’t be changed for some reasons, then you can do the following in python

``````for i in range(n):
xi_i_list = [z[1] for z in var1 if z[0] == i + 1]
``````
3 Likes

Thanks a lot for your support in the Julia community.

How could we simplify this in Julia: `K = [( i >= j ? dot(view(X,:,i), view(X,:,j)) : 0.0 )::Float64 for i=1:n, j=1:n]` ? I understand how `view()` function works but still some glitch that writing this in pythonic way. Any idea? what’s possible alternative of `collect()` in python? Thanks!

Not sure if that is simplify. But that line does the following.

With:

``````julia> X = Float64[ 1 2 ; 3 4 ]
2×2 Array{Float64,2}:
1.0  2.0
3.0  4.0

julia> using LinearAlgebra

julia> n = 2
2
``````

``````julia> K = [( i >= j ? dot(view(X,:,i), view(X,:,j)) : 0.0 )::Float64 for i=1:n, j=1:n]
2×2 Array{Float64,2}:
10.0   0.0
14.0  20.0

``````

and that can be written more explicitly as:

``````julia> K = Matrix{Float64}(undef,2,2) # Create empty 2x2 matrix
2×2 Array{Float64,2}:
2.5e-323  6.92624e-310
5.0e-324  6.92624e-310

julia> for i in 1:2
for j in 1:2
if i >= j
K[i,j] = dot(view(X,:,i),view(X,:,j))
else
K[i,j] = 0.
end
end
end

julia> K
2×2 Array{Float64,2}:
10.0   0.0
14.0  20.0

``````

If you wrap that into a function, for instance:

``````julia> function computeK(X,n)
K = Matrix{Float64}(undef,n,n)
for i in 1:n
for j in 1:n
if i>=j
K[i,j] = dot(view(X,:,i),view(X,:,j))
else
K[i,j] = 0.
end
end
end
return K
end
computeK (generic function with 1 method)

julia> computeK(X,n)
2×2 Array{Float64,2}:
10.0   0.0
14.0  20.0

``````

That is not worst than that “one-liner”:

``````julia> f(X,n) = [( i >= j ? dot(view(X,:,i), view(X,:,j)) : 0.0 )::Float64 for i=1:n, j=1:n]
f (generic function with 1 method)

julia> @btime f(\$X,\$n)
75.759 ns (1 allocation: 112 bytes)
2×2 Array{Float64,2}:
10.0   0.0
14.0  20.0

julia> @btime computeK(\$X,\$n)
58.127 ns (1 allocation: 112 bytes)
2×2 Array{Float64,2}:
10.0   0.0
14.0  20.0

``````

Actually, here, it was faster. This is an important difference relative to Python. You are not constrained to writing vectorized code all the time to get good performance.

Concerning the `collect()` of Python, if that is for garbage collection (as I could find in google), the equivalent is probably `GC.gc()`, but one does not use that very often, if the code is written carefully to avid unnecessary allocations.

1 Like

From my rapid google search, you can do somethng similar with a `numpy` array, as explained here.

In general you cannot do that in Python, and subarrays will do copies, at least that is what is explained there.

1 Like

I am not sure if Jared is referring to the `collect` of Python but instead to how to do Julia `collect` in Python.

Hi, thanks for the follow-up thread. I am saying `collect(1:10)` in julia, which I understand how `collect()` works. I am curious how should I do the same things in `numpy`.

I think I found alternative of julia’ `collect()` in python: `list(range(m, n))`