# Use condition result inside conditional

I find myself with some frequency having to test a condition and, if that condition returns some value, do something with that value. For example:

``````x = [ 1, 2, 3 ]
itest = findfirst(isequal(2),x) # get value
if itest != nothing # test condition
deleteat!(x,itest) # use value
end
``````

This can be done without defining `test` outside the conditional, but calling `findfirst` twice:

``````if findfirst(isequal(2),x) != nothing  # test condition
i = findfirst(isequal(2),x) # get value again
deleteat!(x,i) # use value
end
``````

Is there a way to use a more clean syntax as in the second case, but without repeating the `findfirst` command?

In particular, this becomes useful if I want to add other associated conditionals:

``````x = [ 1, 2, 3 ]
if findfirst(isequal(2),x) != nothing
i = findfirst(isequal(2),x)
deleteat!(x,i)
elseif findfirst(isequal(3),x) != nothing
i = findfirst(isequal(3),x)
deleteat!(x,i)
end
``````

The alternative here is to split the conditional into independent `if end` blocks, when that is the same, with temporary `itest` variables before each one:

``````itest = findfirst(isequal(2),x)
if itest != nothing
deleteat!(x,itest)
end
itest = findfirst(isequal(3),x)
if itest != nothing
deleteat!(x,itest)
end
``````

For a one-liner, I arrived to this:

`````` i = findfirst(isequal(2),x); i != nothing && deleteat!(x,i)
i = findfirst(isequal(3),x); i != nothing && deleteat!(x,i)
``````

Is there a cleaner way to write this? Particularly in the case of `elseif` statements, which are not necessarily the same thing as the multiple `if end` blocks.

1 Like

The following works:

``````foo() = 3

if (x = foo()) !== nothing
println(x)
end
``````

This works because in Julia, assignment is an expression, not just a statement.

4 Likes

Any particular reason here for using `!==` instead of `!=` ?

Actually `isnothing` would have been a better choice on my part.

`===`/`!==` is sometimes held to be slightly better/more efficient when itâ€™s possible to use it, see for example.

3 Likes

@patrick-kidger, how would you use `isnothing()` in this situation? Thanks in advance.

The following works:

``````foo() = 3

if !isnothing(begin x = foo() end)
println(x)
end
``````

To be honest Iâ€™d probably stick with using `!==` for readability. Itâ€™s not really important either way.

3 Likes

Thanks, didnâ€™t know one could do this kind of stuff, but it looks a bit twisted.

1 Like

Yeah, I sometimes wish we had something like the `if-let` or `when-let` macros that exist in some LISP-y languages.

Defining one in Julia could look something like this:

``````# WARNING: proof of concept only!
macro when_let(assignment, body)
var = assignment.args[1]
quote
let \$assignment
if \$var !== nothing
\$body
end
end
end |> esc
end
``````
``````julia> x = [1, 2, 3];

julia> @when_let i = findfirst(isequal(2), x) begin
deleteat!(x, i)
end
2-element Array{Int64,1}:
1
3
``````

One thing that bothers me about such a macro is that it hard-codes the comparison against `nothing`. This is OK for LISPs, where `nil` is used as the `false` boolean anyway. This is also OK in Julia for functions like `findfirst` or `match`, which return `nothing` as a base case. But I still feel like a `when-let` macro would be more â€śJulianâ€ť if it allowed specifying an arbitrary predicate. Iâ€™ve never found a good, readable syntax for this, thoughâ€¦

4 Likes

One used to be able to do this kind of stuff, back when everyone learnt C in the course of learning to program. Nowadays, itâ€™s best avoided, because the kids all think youâ€™ve stuffed up by using `=` where you meant `==`, and file bug reports.

2 Likes