var x: String? = "Help me"
if let value = x && value == "Fine" {
print("Good!")
}
Error: Use of unresolved identifier 'Value'
var x: String? = "Help me"
if let value = x && value == "Fine" {
print("Good!")
}
Error: Use of unresolved identifier 'Value'
As per Swift operator precedence rule, it reads like this:
if let value = (x && (value == "Fine")) { ... }
Which, as you can see, uses value
to set value.
What you want is to check if value
is not nil, then check if value == "Fine"
It is done like this in Swift
if let value = x, value == "Fine" {
...
}
Or sometimes a more preferable spacing/indentation:
if let value = x,
value == "Fine" {
...
}
Here's the Precedence rule that Swift uses (I couldn't find the official reference anywhere else).
Another way to approach it: if x == "Fine" { ... }
.
Because you're checking a specific value, there isn't much value to conditionally binding value
. If it's bound, it'll always have the value "Fine"
. If you need to use that as a value, I think it would be better to just extract it out, use it in your if
's predicate, and then in the body.
This works because Swift is implicitly promoting "Fine"
into an optional string, which allows for ==
comparison.
Ah, I remembe now. Thanks!
Just curious, what if I want ||
instead of &&
?
if let value = x || value == "Fine" {
is it possible to compactly express this?
The precedence is, from highest to lowest; ==
, &&
, ||
, =
, so the order doesn't change.
Secondly, It wouldn't make sense even if you're doing
(let value = x) || (value == "Fine")
does it?
Also, =
has lowest precedence, so whatever you do, it's all part of the assignment.
yes, my code doesn't make sense. sorry. Wasn't thinking
I mean to ask:
var x: String? = "Help me"
var y = "foo"
if let value = x && y == "foo" {. // <=== possible to express this?
print("Good!")
}
I see what you mean, precedence is done before type checking. So you're essentially writing, as before:
if let value = (x && (y == "foo")) { ... }
Since y
and "foo"
are String
, they can compare, and returns Bool
(we have that declared in the standard library somewhere). This is then equivalent to:
if let value = (x && true) { ... }
but the problem is that we don't have String? && Bool
operator, or more formally:
func &&(lhs: String?, rhs: Bool) -> ReturnType { ... }
At least, not in standard library. So it'll just be compile error.
As was hinted, you can define operator between 2 types yourself, or even declare a new operator, eg =~=~=
, when you find it convenient.
PS
As @AlexanderM said, inside the if
block the value
is always "Fine"
anyway, so you might as well just do if x == "Fine" { ... }
In Swift, an if
statement (or a guard
statement or a while
statement) takes a âcondition-listâ. The Swift Programming Language gives the grammar for a condition-list:
condition-list â condition | condition
,
condition-list
condition â expression | availability-condition | case-condition | optional-binding-condition
Of relevance to your question are the condition alternatives âexpressionâ and âoptional-binding-conditionâ:
let value = x
is an optional-binding-condition.y == "foo"
is an expression.The condition-list grammar shows that you need to separate your conditions with a comma (,
), and not anything else (like &&
or ||
). Thus:
if let value = x, y == "foo" { ... }
Not sure if this is your issue, but something to keep in mind is if let
and guard let
are not boolean operations. This took me an annoyingly long time to incorporate into how I think about these statements .
In the C-based-languages was used to if statements always evaluate to a single boolean. That model doesn't really fit what's functionally happening with Optional Binding. See @mayoff's explanation for more details. The way I think about it is if
behaves more like a function with arguments, one of which could be a boolean condition, rather than a simple boolean evaluation.