Defining a variable according to an if-else statement

question

#1

Sometimes I need to define a variable based on a branch like:

foo = []
if condition
  foo = "Julia"
else
  foo = "is awesome"
end

but I need to define it outside of the branch so that it becomes visible in the outside scope.

Is there a more idiomatic Julian way of achieving this result?


#2

Make it a local variable, e.g.


 function f(cond::Bool)
       local x

       if cond
          x = 2
       else
          x = 3
       end
       x
end

#3

@musm this saves us from typing the type of the object, right? I was thinking of doing this, but wondered if another approach with let-blocks or something existed.


#4

But if blocks don’t impact scope, so this is not needed:

julia> if rand()>.5
       a = 7
       else
       b = 9
       end                                                                                                                             
9                                                                                                                                      

julia> a                                                                                                                               
ERROR: UndefVarError: a not defined                                                                                                    

julia> b                                                                                                                               
9                                                                                                                                      

julia> function foo()
       if rand()>.5
       a = 7
       else
       b = 9
       end
       @show a
       end                                                                                                                             
foo (generic function with 1 method)                                                                                                   

julia> foo()
ERROR: UndefVarError: a not defined
Stacktrace:
 [1] macro expansion at ./show.jl:243 [inlined]
 [2] foo() at ./REPL[3]:7

julia> foo()                                                                                                                           
a = 7                                                                                                                                  
7                                                                                                                                      

(Edited to reflect mistake pointed out by @yuyichao’s )

(but this does apply to try blocks, etc., which do impact scope.)


#5

What gives you that impression? There was another recent thread claiming the same. Is it incorrectly mentioned in some doc somewhere or doesn’t work as intended in some cases?


#6

This does not check local variables.


#7

@yuyichao for some reason I assumed this didn’t work. I don’t know if it is because of an experience with a previous version of Julia, but I remember having issues with scope in this context in the past. I just tried it without predeclaring the variable and it works just fine. :blush:


#8

Why not use a ternary operator?

foo = condition ? "Julia" : "is awesome"

#9

@sbromberger, my conditions don’t fit in a line, I do the ternary operator whenever I can to increase code coverage :slight_smile:


#10

Others have cleared up your misunderstanding, so I just want to add

foo = if condition
    "Julia"
else
    "is awesome"
end

which is of course more commonly written using the ternary operator (?:).


#11

This also works:

foo = if cond
 ...
else
 ...
end

#12

Depending on how complex things are, you can create a function that encompasses your conditions, but you’ve probably already decided against ternary operators for other reasons.


#13

I like this one! Clean and express the intent perfectly.


#14

Use a ternary operator?
foo = (condition ? “Julia” : “is awesome”)