Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 481 Vote(s) - 3.52 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How case works in if-case

#1
An old C programmer could use some help with Swift.

I don't understanding something about the if-case syntax. E.g.:

if case 20...30 = age {
print ("in range.")
}

The `case 20...30 = age` appears to be the conditional test for the `if` statement. So I was initially confused to see the assignment operator ('=') used instead of a comparison operator ('==').

Ok, I thought to myself, that probably means the `case` statement is actually a function call that returns a boolean value. The returned value will then satisfy the comparison test in the `if` statement.

As an experiment, I tried treating the the `case` statement like a regular conditional test and placed parentheses around it. Swift will happily accept `if (x == 5)` or `if (true)`. But `if (case 20...30 = age)` generates an error. So the `case` statement doesn't seem to behave like function.

I'm just curious to understand what's happening here. Any insight would be greatly appreciated.
Reply

#2
# Range Containment
Use the [~=][1] operator, as @Alexander mentioned.
```
if (1...10).contains(n) {
print("pass")
}

switch n {
case 1...10: print("pass")
default: print("bug")
}

if case 1...10 = n {
print("pass")
}

if 1...10 ~= n {
print("pass")
}
```
You can even do Ranges of Characters:
```
if "a"..."z" ~= "a" {
print("pass")
}
```
___

# Overloading ~=
I made a couple overloads, so that you can not only check for Range, but also Arrays and Sets
```
func ~=<T: Equatable> (pattern: [T], value: T) -> Bool { return pattern.contains(value) }
func ~=<T: Equatable> (pattern: Set<T>, value: T) -> Bool { return pattern.contains(value) }
func ~=<T: Equatable> (pattern: Set<T>, value: Set<T>) -> Bool { return pattern.union(value).count < pattern.count + value.count }
```
Which allows you to do this:
```
if [1, 2, 3] ~= 2 {
print("pass")
}

if [1, 2, 3] ~= [3, 4, 5] {
print("pass")
}
```
___

# Tuples

However, when using tuples, you'll still have to use **if case**

```
if case (1...10, 1...10) = (number1, number1) {
print("0")
}
```
You can even do the ```_``` syntactic sugar
```
if case (1...10, _) = (number1, number1) {
print("0")
}
```
___

# Optionals
```
if case .some = Optional(number) {
print("pass")
}

if case .some(let x) = Optional(number) {
print(x)
}

if case let x? = Optional(number) {
print(x)
}
```


[1]:

[To see links please register here]

Reply

#3
Even though the correct answer has already been given, still there is one option left:

`20...30` is a **ClosedRange** and has a built-in method which is more readable that can do work for you: `contains`

if (20...30).contains(age) {
print ("in range.")
}
Reply

#4
Just another note about these Swift operators. One must remember that Swift has a very advanced and abstracted compiler, so keywords are just keywords, and their behavior depends on their usage.
Unlike C (and other syntactically related languages from C++ to JavaScript), where `if` is simply used to test a Boolean value (or something that can be converted to one), in Swift, the concept of the `if` statement is much more broad. **I generally think of it gating access to a scope by using a variety of techniques, including Boolean tests.**

You can think of `if`, `guard`, `while`, and `repeat`-`while` as more general control flow statements, with much more advanced behavior. Certainly they can still test a Boolean value, but they can also test other conditions as well. In your scenario, the condition being tested is whether some variable matches a defined pattern (does `age` match the pattern `20...30`).

You can also test whether a variable was successfully set to a non-`nil` value (`if let`). The result of the `let` operation doesn't ever return a Boolean, but since it occurs within the `if` statement, the Swift runtime knows that it's part of the control flow. Also note that this slightly changes the behavior of `let`, insofar as any code inside the `if` block now sees the new non-`nil` value and is assured it's not `nil`.

These behaviors can also be combined with commas, like this:

if !skipAgeTest, // `if` tests a Boolean
let age = Double(ageString), // `if` tests optional assignment
case 20...30 = age // `if` tests pattern matching
{
// `age` variable exists and is not `nil` and is between `20` and `30`, inclusive
}

so the concept of `if let` or `if case` being separate operators is... not exactly thinking about it in the right way.

And like I said, this syntax is also valid in other control flows:

while !skipAgeTest,
let age = Double(ageString),
case 20...30 = age {
// `age` is validated
// Probably also change `ageString` while we're in here
}


guard !skipAgeTest,
let age = Double(ageString),
case 20...30 = age
else {
// `age` is invalid, and not available in this block
}
// `age` is valid


Reply

#5
@matt does a good job of explaining what that code does. I'm here to suggest a better alternative.

You can use the [`~=`][1] operator to check ranges. It's a regular operator/function that just returns a `Bool`, with no special language magic.

if 20...30 ~= age {
print ("in range.")
}


[1]:

[To see links please register here]

Reply

#6
The operator is `if case`, so you can't put parentheses. The syntax and behavior are based on those of the `case` statement in a Swift `switch` statement (see [my online book](

[To see links please register here]

) if you need details). In a `case` statement, `20...30` is an interval, used as a _pattern_, which operates by using `contains` against the interval. The equals sign is indeed truly confusing, but that was their first attempt at a syntax for expressing what the `case` statement should be comparing with (i.e. the _tag_ that comes after the `switch` keyword in a `switch` statement).

So, if you understand this:

switch age {
case 20...30:
// do stuff
default:break
}

... then you understand how it is morphed directly into this:

if case 20...30 = age {
// do stuff
}

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through