The code result is:
num1 is Optional(5)
num2 is Optional(5)
num2 is 5
I want to know why in if{} num2 is an optional value, but print "num2 is 5"
var optionalNum : Int? = 5
let num1 = optionalNum
print("num1 is \(num1)")
if let num2 = optionalNum {
print("num2 is \(optionalNum)")
print("num2 is \(num2)")
} else {
print("optionalNum does not hold a value")
}
When you write
if let num2 = optionalNum { ...
You are performing an optional binding.
In plain english it means
If optionalNum contains a value, then
create a new constant num2 containing that value
AND execute the block inside the { ... }
AND make available the new num2 constant inside the block
So inside the block num2 is NOT an optional. So when you print it you get the plain value. This is the reason why it prints
num2 is 5
Related
I'm working on a code where I need to get 2 user inputted integers and output the smaller one. I am new to swift, and every time I try to get a user to input an integer, I get this error "Value of optional type 'String?' must be unwrapped to a value of type 'String'". I don't understand why I always need to put a "!" after readLine(), but thats what it makes me do.
print("Enter the first integer")
let int1 = Int(readLine()!)
print("Enter the second integer")
let int2 = Int(readLine()!)
let small_int = min(int1!, int2!)
print("The smaller integer is", small_int)
As you can read in docs:
The string of characters read from standard input. If EOF has already been reached when readLine() is called, the result is nil.
... so, simplified, readLine(strippingNewline:) always doesn't have to return value and it also can return nil (no value), so return type is String? which is optional type which says that your constant is String or nil
If you need to get non-optional value you can either force-unwrap optional value or check if value exists and if does, assign some non-optional constant/variable using optional binding. The same you can do for Int initializer which can also return nil since not every String is necessarily a integer
print("Enter the first integer")
let input1 = readLine()
print("Enter the second integer")
let input2 = readLine()
if let string1 = input1, let int1 = Int(string1), let string2 = input2, let int2 = Int(string2) {
let small_int = min(int1, int2)
print("The smaller integer is", small_int)
} else {
print("Invalid input")
}
alternatively you can use default value so if value is nil your constant will be assigned with given default value
print("Enter the first integer")
let int1 = Int(readLine() ?? "") ?? 0
print("Enter the second integer")
let int2 = Int(readLine() ?? "") ?? 0
let small_int = min(int1, int2)
print("The smaller integer is", small_int)
I recommend writing your code in a defensive way. That includes dealing with unexpected results.
Both, readline() and Int() can return nil. As the other answer already explained, readline returns nil if you have reached EOF.
So my recommendation is to use the ?? operator to provide alternative values for the failure cases. For example: let line = readline() ?? “”.
Alternatively, especially inside methods, you may want to bail out early with guard and have the actual work at the end of the method with validated and non-nil inputs.
With that in mind, your example can be rewritten like this:
let line = readline() ?? “”
let int1 = Int(line) ?? 0
//...
Or as a method with guard:
func smallerInteger() -> Int? {
print("Enter the first integer")
guard let line1 = readline() else {
return nil
}
guard let int1 = Int(line1) else {
return nil
}
print("Enter the second integer")
guard let line2 = readline() else {
return nil
}
guard let int2 = Int(line2) else {
return nil
}
return min(int1, int2)
}
Of course this can be improved by returning both an Int? and an Error? like (Int?, Error?) or with the latest Swift, a Result.
I'm trying to understand better the closures in swift and I've tried to create a silly function with a completion handler that returns a value but this value goes nowhere...
here's what I did..
func productToString(num: Int,num2: Int,completion: (Int)->String){
let result = num * num2
completion(result)
}
let numberToString = productToString(num: 3, num2: 6) { (res) -> String in
return "string:\(res)"
}
print(numberToString) // print statement prints ()
when I tried to save this return value in a variable it returned just a pair of curvy brackets.
how should I use this return value?
You're returning the value into the productToString function but not doing anything else with it.
func productToString(num: Int,num2: Int,completion: (Int)->String){
let result = num * num2
completion(result) // <--- Your return value ends up here
}
If you want to print the result you have to return it again out of the productToString function.
func productToString(num: Int,num2: Int,completion: (Int)->String) -> String {
let result = num * num2
return completion(result)
}
Sidenote: The empty brackets that are printed are an empty tuple which is equivalent to Void in Swift.
I'm writing a macOS Command Line Tool in Xcode. The variable "num1" keeps returning nil. I declared it in the beginning so it should be a global variable. How can I address this?
var num1: Int!
if userChoice == "add" {
print("Enter first number")
if let num1 = readLine() {
}
}
print ("\(num1)")
As mentioned, you have two num1 variables. The 2nd one is scoped to just the block of the 2nd if statement.
You also have an issue that readLine returns an optional String, not an Int.
You probably want code more like this:
var num1: Int?
if userChoice == "add" {
print("Enter first number")
if let line = readLine() {
num1 = Int(line)
}
}
print ("\(num1)")
Of course you may now need to deal with num1 being nil.
One option is to properly unwrap the value:
if let num = num1 {
print("\(num)")
} else {
print("num1 was nil")
}
Call the second num1 something else.
Put something in the if.
var num1: Int!
if userChoice == "add" {
print("Enter first number")
if let num2 = readLine() {
// This if-let runs if num2 is not nill.
print ("\(num2)")
num1 = Int(num2)
}
}
print ("\(num1)")
I am looking for help to increment a hexadecimal by 1. An example of this might be "000001" or "AD02D3" and increment to "000002" or "AD02D4". I can't figure out how to do this in Swift. If I convert to an Int:
var num2 = Int(str, radix: 16)
I loose all the preceding zeros and there are difficulties converting back.
Any suggestions?
Save the string length in a variable
Convert to an integer Int(str, radix: 16)
Add 1 to the integer
Use a format string with the saved length and specifying leading "0"s
Create the new string for the format function
let str = "00000A"
let len = str.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)
let num2 = Int(str, radix: 16)! + 1
let newStr = NSString(format: "%0\(len)X", num2) as String
print("newStr: \(newStr)") // newStr: 00000B
import Foundation
func inc(s: String)->String? {
if let i = Int(s,radix: 16)?.successor() {
return String(format: "%0\(s.characters.count)X", arguments: [i])
} else {
return nil
}
}
let arr0 = ["01","0000FE00","FFFFFF"]
let arr1 = arr0.flatMap{ inc($0) }
print(arr1) // ["02", "0000FE01", "1000000"]
I was trying to understand Function Scope vs Gobal Scope, with the below example:
<script>
// The following variables are defined in the global scope
var num1 = 2,
num2 = 3,
name = "Chamahk";
// This function is defined in the global scope
function multiply() {
return num1 * num2;
}
console.log(multiply()); // Returns 60
// A nested function example
function getScore () {
var num1 = 20,
num2 = 30;
function add() {
var num1 = 200,
num2 = 300;
return name + " scored " + (num1 * num2);
}
return add();
}
console.log(getScore()); // Returns "Chamahk scored 60000"
</script>
I googled and found that Global Scoped variable can be accessed using this. changing the return code to
return name + " scored " + (this.num1 * this.num2);
gave output as "Chamahk scored 6", means this is accessing the global var num1 and num2.
This is clear, but what i wanted to know, how to access the num1 and num2 declared in getScore() function
.i.e. to get the output as 600.
I have to say your question is a little confusing.
Generally you would want to use parameters to your functions, to pass values around.
The reason you are getting 60000, is because in your add function you are setting num1, and num2 to 200 and 300.
If you changed your add function to take num1, and num2 as parameters, and not redeclare them, you could pass in your values in getScore();
e.g return add(num1, num2);
<script>
// The following variables are defined in the global scope
var num1 = 2,
num2 = 3,
name = "Chamahk";
// This function is defined in the global scope
function multiply(num1, num2) {
return num1 * num2;
}
console.log(multiply(num1, num2)); // Returns 6!!!
// A nested function example
function getScore () {
var num1 = 20,
num2 = 30;
function add(num1, num2) {
return name + " scored " + (num1 * num2);
}
return add(num1, num2);
}
console.log(getScore()); // Returns "Chamahk scored 60000"
</script>