Not sure what I'm doing wrong here, but here's the trivial code that's breaking:
if 10 & (1<<18) {
return
}
This gives me:
'Int' is not convertible to 'Bool'
What is wrong?
Unlike in C where you can write...
if (x) { }
... which is really a non-zero check:
if (x != 0) { }
You must test for a boolean condition in Swift. Add != 0 to your statement:
if 10 & (1<<18) != 0 {
return
}
Swift 4 : Check that
Your method has a correct return type which the caller is expecting
eg: func yourMethod() -> Bool
The caller method has parentheses () at the end yourMethod()
Related
Not sure what I'm doing wrong here, but here's the trivial code that's breaking:
if 10 & (1<<18) {
return
}
This gives me:
'Int' is not convertible to 'Bool'
What is wrong?
Unlike in C where you can write...
if (x) { }
... which is really a non-zero check:
if (x != 0) { }
You must test for a boolean condition in Swift. Add != 0 to your statement:
if 10 & (1<<18) != 0 {
return
}
Swift 4 : Check that
Your method has a correct return type which the caller is expecting
eg: func yourMethod() -> Bool
The caller method has parentheses () at the end yourMethod()
I have a method, and it contains the following:
let downloadNextPagination = {
if current.integerValue < amount.integerValue {
if current.integerValue != amount.integerValue - 1 {
return true
}
}
return false
}
if downloadNextPagination() {
// Do something
}
This code will not compile: Unable to infer closure return type in current context
Changing the definition of downloadNextPagination to
let downloadNextPagination: () -> Bool
fixes the issue. Question is: Why can Swift not work out the correct type of the closure here? All code paths return Bool, yet this can't be worked out? Is this a fundamental limitation / am I missing something in my understanding here, or is this simply a question of improving the compiler's type inference ability and something like this may well work come Swift 3?
Swift can currently infer only single-return closures. You can rewrite your closure to:
let downloadNextPagination = {
return current.integerValue < amount.integerValue && current.integerValue != amount.integerValue - 1
}
So in Objective-C when using Booleans it's possible, and encouraged, to write code using a variable's non-zero value as it's boolean value, which means you can write code like this:
if (someBool) {
// Stuff
}
Also, there are reasons why code like the following is discouraged:
if (someBool == YES) {
// Might run into problems here
}
The reasons why checking a boolean against another boolean are better explained here, but briefly the issue is just that when you're comparing equality to YES or NO directly, you're actually comparing against 1 and 0, respectively. Since Objective-C allows for using non-zero values as a truth value, you could end up comparing something that should be considered true against YES and have the expression resolve to NO, e.g.
int trueNumber = 2;
if (trueNumber == YES) {
// Doesn't run because trueNumber != 1
}
Is this still an issue in Swift? Code style issues aside, if I see something like the following
var someBool = true
if someBool == true {
// stuff
}
is that going to be an issue, or does it not really matter? Are these C-style comparisons still happening under the hood, or is there something built into the Swift BooleanType that prevents these issues?
The if <something> {} structure in Swift requires the <something> to conform to the BooleanType protocol which is defined like this:
public protocol BooleanType {
/// The value of `self`, expressed as a `Bool`.
public var boolValue: Bool { get }
}
If the type doesn't conform to this protocol, a compile-time error is thrown. If you search for this protocol in the standard library you find that the only type that conforms to this protocol is Bool itself. Bool is a type that can either be true or false. Don't think of it as the number 1 or 0, but rather as On/Off Right/Wrong.
Now this protocol can be conformed to by any nominal type you want, e.g.:
extension Int : BooleanType {
public var boolValue : Bool {
return self > 0
}
}
Now if you do this (you shouldn't honestly), you're defining it by yourself what "True" and "False" means. Now you'd be able to use it like this (again, don't do this):
if 0 {
...
}
Swift has Bool type. This is different from objective-c's BOOL which is not actual type. It is actually typedef unsigned char. When swift expects Bool you have to give it Bool otherwise it is compile error. The following code will not compile because check is not Bool
let check = 2
if check {
}
But this will work because == returns Bool
let check = 2
if check == 2 {
}
To understand the ObjC style, you need to go back to C. In C, this statement:
if (something) {
// Do something
}
will evaluate to false if something is null or 0. Everything else evaluate to true. The problem is C doesn't have a boolean type. Objective-C added YES and NO which is basically 1 and 0. So:
if (aBoolValue == YES) { } // Work as expected
if (anIntValue == YES) { } // False unless anIntValue == 1
The "discouraged" recommendation was to align with the behaviour in C. Swift has no such backward compatibility requirements. You can't write these:
if anIntValue { } // Syntax error
if anObject { } // Syntax error
Instead, the expression must evaluate to a boolean value:
if anIntValue != 0 { } // Ok
if anObject != nil { } // Ok
Let's say I have function which returns optional. nil if error and value if success:
func foo() -> Bar? { ... }
I can use following code to work with this function:
let fooResultOpt = foo()
if let fooResult = fooResultOpt {
// continue correct operations here
} else {
// handle error
}
However there are few problems with this approach for any non-trivial code:
Error handling performed in the end and it's easy to miss something. It's much better, when error handling code follows function call.
Correct operations code is indented by one level. If we have another function to call, we have to indent one more time.
With C one usually could write something like this:
Bar *fooResult = foo();
if (fooResult == null) {
// handle error and return
}
// continue correct operations here
I found two ways to achieve similar code style with Swift, but I don't like either.
let fooResultOpt = foo()
if fooResult == nil {
// handle error and return
}
// use fooResultOpt! from here
let fooResult = fooResultOpt! // or define another variable
If I'll write "!" everywhere, it just looks bad for my taste. I could introduce another variable, but that doesn't look good either. Ideally I would like to see the following:
if !let fooResult = foo() {
// handle error and return
}
// fooResult has Bar type and can be used in the top level
Did I miss something in the specification or is there some another way to write good looking Swift code?
Your assumptions are correct—there isn't a "negated if-let" syntax in Swift.
I suspect one reason for that might be grammar integrity. Throughout Swift (and commonly in other C-inspired languages), if you have a statement that can bind local symbols (i.e. name new variables and give them values) and that can have a block body (e.g. if, while, for), those bindings are scoped to said block. Letting a block statement bind symbols to its enclosing scope instead would be inconsistent.
It's still a reasonable thing to think about, though — I'd recommend filing a bug and seeing what Apple does about it.
This is what pattern matching is all about, and is the tool meant for this job:
let x: String? = "Yes"
switch x {
case .Some(let value):
println("I have a value: \(value)")
case .None:
println("I'm empty")
}
The if-let form is just a convenience for when you don't need both legs.
If what you are writing is a set of functions performing the same sequence of transformation, such as when processing a result returned by a REST call (check for response not nil, check status, check for app/server error, parse response, etc.), what I would do is create a pipeline that at each steps transforms the input data, and at the end returns either nil or a transformed result of a certain type.
I chose the >>> custom operator, that visually indicates the data flow, but of course feel free to choose your own:
infix operator >>> { associativity left }
func >>> <T, V> (params: T?, next: T -> V?) -> V? {
if let params = params {
return next(params)
}
return nil
}
The operator is a function that receives as input a value of a certain type, and a closure that transforms the value into a value of another type. If the value is not nil, the function invokes the closure, passing the value, and returns its return value. If the value is nil, then the operator returns nil.
An example is probably needed, so let's suppose I have an array of integers, and I want to perform the following operations in sequence:
sum all elements of the array
calculate the power of 2
divide by 5 and return the integer part and the remainder
sum the above 2 numbers together
These are the 4 functions:
func sumArray(array: [Int]?) -> Int? {
if let array = array {
return array.reduce(0, combine: +)
}
return nil
}
func powerOf2(num: Int?) -> Int? {
if let num = num {
return num * num
}
return nil
}
func module5(num: Int?) -> (Int, Int)? {
if let num = num {
return (num / 5, num % 5)
}
return nil
}
func sum(params: (num1: Int, num2: Int)?) -> Int? {
if let params = params {
return params.num1 + params.num2
}
return nil
}
and this is how I would use:
let res: Int? = [1, 2, 3] >>> sumArray >>> powerOf2 >>> module5 >>> sum
The result of this expression is either nil or a value of the type as defined in the last function of the pipeline, which in the above example is an Int.
If you need to do better error handling, you can define an enum like this:
enum Result<T> {
case Value(T)
case Error(MyErrorType)
}
and replace all optionals in the above functions with Result<T>, returning Result.Error() instead of nil.
I've found a way that looks better than alternatives, but it uses language features in unrecommended way.
Example using code from the question:
let fooResult: Bar! = foo();
if fooResult == nil {
// handle error and return
}
// continue correct operations here
fooResult might be used as normal variable and it's not needed to use "?" or "!" suffixes.
Apple documentation says:
Implicitly unwrapped optionals are useful when an optional’s value is confirmed to exist immediately after the optional is first defined and can definitely be assumed to exist at every point thereafter. The primary use of implicitly unwrapped optionals in Swift is during class initialization, as described in Unowned References and Implicitly Unwrapped Optional Properties.
How about the following:
func foo(i:Int) ->Int? {
switch i {
case 0: return 0
case 1: return 1
default: return nil
}
}
var error:Int {
println("Error")
return 99
}
for i in 0...2 {
var bob:Int = foo(i) ?? error
println("\(i) produces \(bob)")
}
Results in the following output:
0 produces 0
1 produces 1
Error
2 produces 99
Code
struct test
{
private real value;
this(real value)
{
this.value = value;
}
bool opUnary(string op)() if (op == "!")
{
return !value;
}
}
void main()
{
test a = 123.12345;
bool b = !a;
}
Compilation error
prog.d(19): Error: expression a of type test does not have a boolean value
http://ideone.com/Kec81
Also tested on dmd 2.053, 2.054
What's wrong with my code?
You cannot overload the ! operator in D - see http://www.d-programming-language.org/operatoroverloading.html#Unary for a list of overloadable unary operators. Without knowing what you're doing, it's hard to suggest a work around, it might be worth looking at alias this though - http://www.d-programming-language.org/class.html#AliasThis.