How to use the macro @label and @goto

Dear all,

I want to know how to use @label and @goto. Can you give me an example to use them?
Many thanks.

2 Likes

The Julia docs probably should have an example.

The function below is horrendous, it is defined only for the purpose of this example, it could be rewritten to be much better but then it would not serve the purpose of illustrating @goto/@label.

The only motive I think it is reasonable to use @goto is to break out of multiple loops at once. Other languages allow the keyword break to be accompanied by a number indicating how many nested loops the break is affecting (from the inner to outer). Julia does not have this feature so, for this specific use case, @goto is more elegant than adding a lot of flags and ifs to achieve the same effect.

julia> function has_zero(A)
           i, j = 0, 0
           for outer i in 1:size(A, 1)
               for outer j in 1:size(A, 2)
                   if iszero(A[i, j])
                       @goto after_loop
                   end
               end
           end
           @label after_loop
           if iszero(A[i, j])
               return i, j
           end
           return false
       end
has_zero (generic function with 1 method)

julia> A = [1 2 3; 4 5 6]
2×3 Array{Int64,2}:
 1  2  3
 4  5  6

julia> has_zero(A)
false

julia> A = [1 2 3; 0 5 6]
2×3 Array{Int64,2}:
 1  2  3
 0  5  6

julia> has_zero(A)
(2, 1)

4 Likes

What is the advantage of @goto and @label? In your example, Why not directly write the codes as below?

function has_zero(A)
                  i, j = 0, 0
                  for outer i in 1:size(A, 1)
                      for outer j in 1:size(A, 2)
                          if iszero(A[i, j])
                              return i, j
                          end
                      end
                  end
                  return false
              end
1 Like
julia> using Multibreak

julia> @multibreak function has_zero(A)
           i, j = 0, 0
           for outer i in 1:size(A, 1)
               for outer j in 1:size(A, 2)
                   if iszero(A[i, j])
                       break; break
                   end
               end
           end
           if iszero(A[i, j])
               return i, j
           end
           return false
       end
has_zero (generic function with 1 method)

The @multibreak macro rewrites the double break to exactly the same @goto and @label construction, of course.

2 Likes

You have the answer above:

1 Like

@Henrique_Becker @GunnarFarneback Thanks for both of your help.

GOTO was routinely written in older programming languages, but it was mostly abandoned decades ago in favor of structured programming, like for-loops, methods, try-catch-finally. The structures are effectively ways to write the more maintainable GOTO patterns, so GOTO stills show up in the lowered and compiled code that the compiler makes from the structures.

Julia’s @goto and @label has such niche uses that the only application people can immediately think of is multi-level breaks from nested loops, yet it’s been demonstrated in this thread that specific purpose could be written with improved syntax enabled by @multibreak. Unlike historical GOTO, Julia’s @goto’s ability to jump around the code is limited somewhat, but it can still easily make a program much harder to follow than typical structures. Treat it as a relic of the past, a last resort to dust off if you run into a surprising case where the typical structures would be harder to follow than the equivalent @goto version.

3 Likes

Thanks so much.

1 Like