5 Julia control

5 Julia control

Julia control flow

Exception handling

task:

Control flow provided in Julia

  • Compound expression: begin and (;)
  • Conditional evaluation: if-elseif-else and?: (ternary operator)
  • Short-circuit evaluation: &&, || and chained comparisons
  • Repeat evaluation: loop: while and for
  • Exception handling: try-catch, error and throw
  • Task (also called coroutine): yieldto

Compound expression

begin block

z = begin
     x = 1
     y = 2
     x + y
    end
>>3

(;)Chain

z = (x = 1; y = 2; x + y)

The value of these two expressions is the value of the last expression.

Conditional extremum

if x <y
    println("x is less than y")
elseif x> y
    println("x is greater than y")
else
    println("x is equal to y")
end

The judgment condition must be trueorfalse of a

if 1
    println("test...")
end
>>TypeError: non-boolean (Int64) used in boolean context

while loop

i = 5
while i <= 5
         println(i)
         i += 1
       end

The above loop is written in a for loop as

for i = 1:5
    println(i)
end

for can also traverse any container

for i in [1,2,3,4,5]
    println(i)
end

other usage of for

for i in "abcd"
    println(i)
end

for i in 1:2:10
    println(i)
end

for i in 10:-2:1
    println(i)
end

[x^2 for x in 1:4]
[x^2 for x ∈ 1:5]
[(x, x^2) for x ∈ 1:5]

for (i,x) in enumerate(1:4:20)
    println(i, "", x)
end

collect(enumerate(1:4:20))

The usage of continue and break is basically the same as in other languages, so I won't talk about it here.

Variable scope

for i in 1:5
    x = i
end

At this time, if you view the value of x outside the for loop, it will prompt error, because the variable x is only inside the for loop.

If you want to use x outside of for, you have to write

for i in 1:5
    global x = i
end

If we define x externally in advance

x = 10
for i in 1:5
    x = i
end

At this time, x is still 10, because x is local by default in for

Exception handling

sqrt(-1)
>>DomainError with -1.0:
sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).

Stacktrace:
 [1] throw_complex_domainerror(::Symbol, ::Float64) at .\math.jl:31
 [2] sqrt at .\math.jl:479 [inlined]
 [3] sqrt(::Int64) at .\math.jl:505
 [4] top-level scope at In[4]:1

try
    sqrt(-1)
catch
    println("pass")
end

sqrt_second(x) = try
           sqrt(x[2])
       catch y
           if isa(y, DomainError)
               sqrt(complex(x[2], 0))
           elseif isa(y, BoundsError)
               sqrt(x)
           end
       end

The finally statement usually causes the program to exit prematurely, making certain operations impossible to execute. The keyword finally can solve such problems. No matter how the program exits, the finally statement will always be executed.

f = open("file")
try
    # operate on file f
finally
    close(f)
end

It may be try, catchand finallyeven used together, finallyin catchexecution after handling exceptions.

Task (also called coroutine)

It is called symmetric coroutine, lightweight thread, cooperative multitasking, etc. (It is different from threads, which will be discussed in parallel computing later)

If a calculation is performed as a task, it is likely to be interrupted by other tasks. After the original task is resumed, it will continue to work from where it was interrupted. This process looks a lot like a function call, but there are two points. different:

  1. Task switching does not require any space, so any number of tasks can be switched without considering stack issues.
  2. Task switching can be done in any order.

Tasks are more suitable for the producer-consumer model, where one process is used to produce value and the other is used to consume value. The consumer cannot simply call the producer to get the value, because the execution time of the two is not necessarily coordinated. In the task, both can run normally.

Julia provides Channel to solve the problem of producer-consumer collaboration. In fact, Channel is a FIFO (first-in first-out) queue. Use the put!and take!function to achieve concretely.

function producer(c::Channel)
           put!(c, "start")
           for n=1:4
               put!(c, 2n)
           end
           put!(c, "stop")
end

Then we create a Channel component to consume values.

chnl = Channel(producer)
take!(chnl)
>>"start"
take!(chnl)
>>2
take!(chnl)
>>4
take!(chnl)
>>6
take!(chnl)
>>8
take!(chnl)
>>"stop"

You can also use a forloop

for x in Channel(producer)
    println(x)
end
>>start
  2
  4
  6
  8
  sotp

Between the two calls put!(), the execution of the producer is suspended, and the consumer takes over control at this time.

A feature of the task is that as the task ends, the channel object will be automatically closed without human intervention.

Put the general function in the task:

function mytask(n)
    for i=1:n
        println(i)
    end
end

taskHdl = @task mytask(10)
println(istaskdone(taskHdl))
schedule(taskHdl)
println(current_task())
println(istaskdone(taskHdl))
>>false
1
2
3
4
5
6
7
8
9
10
Task (runnable) @0x000000000d41eb30
true
Reference: https://cloud.tencent.com/developer/article/1653097 5 Julia Control-Cloud + Community-Tencent Cloud