Unused Variable Warning in ReasonML - reason

When I use Invalid_argument() variant exception in a switch case, it expects a string argument.
let subStr = try(String.sub(input^, index, 1)) {
| Invalid_argument(err) => ""
};
but if I don't use the err variable, it shows an unused variable warning.

Unused variables are prefixed by a _ in Reason.
Instead of
Invalid_argument(err)
you have to use
Invalid_argument(_err)

Related

Why outside of block swift can't see value assigned to a uninitialized variable in the block?

What is the mechanism of declaring w/o value in Swift5 ? Does the first assign become the real declaration ?
And, should we avoid to declare without value in Swift?
var v:String;
if true {
v = "Hello"
print(v) // print "Hello" when without the print below
}
print(v) // variable 'v' used before being initialized
var v:String="";
if true {
v = "Hello"
print(v) // print "Hello"
}
print(v) // print "Hello"
Well, the message is not very helpful, and that's the problem. This pattern (which I call computed initialization) is perfectly legal and useful and — amazingly — you can even use let instead of var. But you must initialize the uninitialized variable by all possible paths before you use it. So you have:
var v:String
if true {
v = "Hello"
}
print(v) // error
But hold my beer and watch this:
var v:String
if true {
v = "Hello"
} else {
v = "Goodbye"
}
print(v) // fine!
Or even:
let v:String
if true {
v = "Hello"
} else {
v = "Goodbye"
}
print(v) // fine!
Amazing, eh?
Now, you might say: OK, but true will always be true so it's silly to make me fulfill the "all paths" rule. Too bad! The compiler insists anyway, and then lets you off later with a warning that the else won't be executed. But a warning lets you compile; an error doesn't. The truth is that your example is very artificial. But this is a real-life possibility:
let v:String
if self.someBoolProperty {
v = "Hello"
} else {
v = "Goodbye"
}
print(v) // fine!
Not only is this sort of thing legal, it is actually the pattern that Apple recommends under certain slightly tricky circumstances. For instance, it is used in Apple's own example code showing how to use the Swift 5 Result struct:
let result: Result<Int, EntropyError>
if count < AsyncRandomGenerator.entropyLimit {
// Produce numbers until reaching the entropy limit.
result = .success(Int.random(in: 1...100))
} else {
// Supply a failure reason when the caller hits the limit.
result = .failure(.entropyDepleted)
}
So this is because swift compiles your code and notices that your value var v:String; is undeclared before being used which makes it an "optional" value. Even though you are assigning it within the if statement, if you were to get rid of the true value it is possible that the if statement would never run therefore no value will ever be stored in v, thus it would be used before "assigned".
So to answer your question if you want your value to be an optional and possible empty value declare v as the following var v:String? if you would like it to be a non-optional value with a value always stored within v you should declare it as the following var v = "". Swift will interpret this declaration as a String.
To answer your second question, defining without values in swift is 100% allowed, it really just depends on how you want to handle your code. I use optional values in my code all the time, but I don't necessarily like optionals so i usually like to declare my values such as var v = "" that way if the value is empty my UI or whatever else i'm manipulating won't break. But if i need to ensure a value is present i will have to make my value optional so i can use an if statement to check whether it's a valid value or not.
Shorter version of what I'm trying to say is, you are receiving the compiler warning because you are declaring v as a non-optional value rather than an optional value.

Swift variable name with ` (backtick)

I was browsing Alamofire sources and found a variable name that is backtick escaped in this source file
open static let `default`: SessionManager = {
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
return SessionManager(configuration: configuration)
}()
However in places where variable is used there are no backticks. What's the purpose of backticks?
Removing the backticks results in the error:
Keyword 'default' cannot be used as an identifier here
According to the Swift documentation :
To use a reserved word as an identifier, put a backtick (`)before and after it. For example, class is not a valid identifier, but `class` is valid. The backticks are not considered part of the identifier; `x` and x have the same meaning.
In your example, default is a Swift reserved keyword, that's why backticks are needed.
Example addendum to the accepted answer, regarding using reserved word identifiers, after they have been correctly declared using backticks.
The backticks are not considered part of the identifier; `x` and x
have the same meaning.
Meaning we needn't worry about using the backticks after identifier declaration (however we may):
enum Foo {
case `var`
case `let`
case `class`
case `try`
}
/* "The backticks are not considered part of the identifier;
`x` and x have the same meaning" */
let foo = Foo.var
let bar = [Foo.let, .`class`, .try]
print(bar) // [Foo.let, Foo.class, Foo.try]
Simply put, by using backticks you are allowed to use
reserved words for variable names etc.
var var = "This will generate an error"
var `var` = "This will not!"

Swift for in loop: use var get warning to use let, use let get error

I have the following code in a swift file:
func testDictionary(dict :Dictionary<String,AnyObject>) {
var str = ""
for var key in dict.keys {
str += key + ":" + dict[key]!.description + "\n"
}
self.alert("Dict", message: str)
}
The above code produces a warning on the user of var in the for loop, which is:
Variable 'key' was never mutated; consider changing to 'let' constant
However when I change var to let I get the following error:
'let' pattern cannot appear nested in an already immutable context
Why do I get a warning when the suggested correction is a compiler error?
Neither var nor let is needed in the statement.
Type this:
for key in dict.keys {
str += key + ":" + dict[key]!.description + "\n"
}
I think the answer here is that the for-in loop by default provides a key that is already a constant. Therefore using the let keyword is redundant. When you used the var keyword, you were saying you wanted a variable key, but you never change it, therefore you don't need to use var.

How to read swift headers

When I cmd click the split function in Xcode, it takes me to the header file. This is what it reads
public func split(maxSplit: Int = default, allowEmptySlices: Bool = default, #noescape isSeparator: (Self.Generator.Element) throws -> Bool) rethrows -> [Self.SubSequence]
How does the following implementation work with above declaration?
someString.characters.split { $0 == "." }
Let's break it down:
public func split(maxSplit: Int = default, allowEmptySlices: Bool = default, #noescape isSeparator: (Self.Generator.Element) throws -> Bool) rethrows -> [Self.SubSequence]
maxSplit: The first parameter, maxSplit, allows you to specify the maximum number of pieces that the sequence will be split into. The default is Int.max.
allowEmptySlices: The second parameter, allowEmptySlices specifies whether or not two consecutive separators in the sequence should lead to an empty slice. The default is false. For example if you had a String, "A..B", and you split on the . character, you could end up with either two (["A", "B"]) or three (["A", "", "B"]) items in the output array depending on what you pass for this parameter.
isSeparator: The last parameter is the closure that you pass to identify where to split the sequence.
Since both maxSplit and allowEmptySlices have default arguments, you don't need to include them in your function call unless you want to change them. The only parameter that you have to supply is the isSeparator closure.
In your case, you called:
someString.characters.split { $0 == "."}
...which is the equivalent of:
someString.characters.split(maxSplit: Int.max, allowEmptySlices: false) { $0 == ".' }
You could also write your function call like this:
someString.characters.split(isSeparator: { $0 == "." })
The way that you have written it makes use of the "trailing closure" syntax. If a function takes a closure as it's final argument, you can move the closure outside the parentheses like this:
someString.characters.split() { $0 == "." }
And if the function takes only one argument (not counting any default arguments that you are not supplying) then you can omit the parentheses altogether:
someString.characters.split { $0 == "." }
At the highest level, what happens is that split iterates through the sequence of characters. It tests each character using the supplied closure, and if the closure returns true, it splits the sequence on that character. In your case it will split the sequence of characters every time it locates a ".".
Some other notes:
rethrows: The whole function is marked rethrows. It will throw an error, but only if the closure that you pass for the isSeparator argument throws an error itself. Note that the isSeparator parameter allows you to pass a closure that throws an error, but you don't have to. Any time a function accepts a closure that throws an error, it will also accept a closure that does not throw. This is because non-throwing functions are a sub-type of throwing functions.
#noescape: The isSeparator parameter is marked #noescape. That simply means that nothing in the closure will survive past the end of the call to split.
Your line someString.characters.split { $0 == "."} uses the default values for maxSplit and allowEmptySlices and specifies a custom closure for isSeparator. Some longer version of calling the function split is:
let arr = str.characters.split(Int.max, allowEmptySlices: false) { (char) -> Bool in
char == "."
}
Since the above code uses the same values as the actual defaults (Int.max and false) you can remove the first two parameters and since the closure is the last parameter (making it a trailing closure) you can omit the entire parameter and simply write a closure in the following way:
let arr = str.characters.split { (char) -> Bool in
char == "."
}
Now we can simplify the closure by omitting the specific signature:
let arr = str.characters.split { $0 == "." }
someString.characters.split { $0 == "."}
is equivalent to
someString.characters.split(isSeparator: { $0 == "."})
the closure in your code is called a trailing closure, closures that are the last parameter to a function can be placed after the function declaration, and if no other parameters remain, you can also omit ().
The first two parameters have default values, so they can be omitted, leading to the simplified call you posted.

What is Optional({}) at Alamofire mean when i create output of JSON

When I create output of JSON using Alamofire, I saw this in my console
What does Optional({}) mean?
Optional({
0 = (
All,
""
);
C2001 = (
"ARAI Bay Side"
);
C2002 = (
"ARAI Fukuoka"
);
})
I am newbie to swift and this, so any ideas?
What Alamofire gives you is an optional variable, because it can't predict in advance whether the request will succeed and have output or fail and have none.
Similarly, it also gives you an error? variable (note the ?, which means it's also an optional) that will be nil if the request succeeded or will be something (most likely an NSError) if an error occurred.
You can check with if yourVariable != nil to see whether the optional variable is set (contains something), in which case you'll be able to unwrap it with yourVariable!.
You can also use the following :
if let yourUnwrappedVariable = yourVariable!
to unwrap the variable into a new (non-optional) yourUnwrappedVariable variable and execute the code in that if block if the variable was set (contained something, wasn't nil), this time without needing to unwrap the variable again like the previous example (here you already have the yourUnwrappedVariable variable and can use it right away in that if block).
Finally, if you're sure the variable will always be set, you can unwrap it by passing it followed by a ! sign to whatever method call you want like so :
myMethod(initWithData: yourVariable!, anotherArgument: anotherValue)
If the variable ever happens to not contain anything, an exception will be thrown.
What you are seeing is the output from global functions like print() or println(), which enclose optional descriptions inside Optional( ), unless the value of the optional is nil, in which case just nil is printed.
If you have this:
var foo: Int?
foo = 7
println(foo)
The output is Optional(7)
whereas
println(foo!)
just prints 7