CoffeeScript Undefined - coffeescript

In javascript to check if a variable was never created, we just do
if (typeof MyVariable !== "undefined"){ ... }
I was wonder how I do that in coffeescript?... I try something like
if (MyVariable?false){ ... }
but this check if MyVariable is a function if so that will call MyVariable(false) if not that will call void(0) or something like that.

Finally I found this easy way to do it:
if (MyVariable?){ ... }
that will generate:
if (typeof MyVariable !== "undefined" && MyVariable !== null){ ... }
UPDATE 04/07/2014
Demo Link

First, to answer your question:
if typeof myVariable isnt 'undefined' then # do stuff
Magrangs' solution will work in most cases, except when you need to distinguish between undefined and false (for example, if myVariable can be true, false or undefined).
And just to point out, you shouldn't be wrapping your conditions in parentheses, and you shouldn't be using curly braces.
The then keyword can be used if everything is on the same line, otherwise use indentation to indicate what code is inside of the condition.
if something
# this is inside the if-statement
# this is back outside of the if-statement
Hope this helps!

This answer is for an older version of coffeescript. See Jaider's answer above if you want a more up to date answer (as of July 2014)
This coffeescript does what you want I think:
if not MyVariable?
MyVariable = "assign a value"
Which produces:
if (!(typeof MyVariable !== "undefined" && MyVariable !== null)) {
MyVariable = "assign a value";
}
N.b. if you make an assignment to MyVariable first, even if you set MyVariable to undefined as in this code, then this compiles to:
if (!(MyVariable != null)) {
MyVariable = "assign a value";
}
I believe this works because the != used by CoffeeScripts Existential Operator (the question mark) coerces undefined to be equal to null.
p.s. Can you actually get if (MyVariable?false){ ... } to work? It doesn't compile for me unless there's a space between the existential operator and false i.e. MyVariable? false which then makes CoffeeScript check it like a function because of the false which it thinks is a parameter for your MyVariable, for example:
if MyVariable? false
alert "Would have attempted to call MyVariable as a function"
else
alert "but didn't call MyVariable as it wasn't a function"
Produces:
if (typeof MyVariable === "function" ? MyVariable(false) : void 0) {
alert("Would have attempted to call MyVariable as a function");
} else {
alert("but didn't call MyVariable as it wasn't a function");
}

typeof MyVariable isnt "undefined"
from js2coffee

In addition to Jaider's answer above (I couldn't comment due to insufficient reputation), be careful that it's a different case if it's something inside an object/array:
someArray['key']?
will be converted to:
someArray['key'] != null
Screenshot from js2coffee.org:

I just use:
if (myVariable)
//do stuff
As undefined is falsy it will only do stuff if myVariable is not undefined.
You just have to be aware that it will 'do stuff' for values that are 0, "" and null

The cleanest way I've found to assign a variable to an undefined and not-null variable is using unless:
unless ( myVar? )
myVar = 'val'

Why not just use the OR idiom?
myVar or 'val'
So, the result will equal myVar, unless it is undefined in which case it will equal 'val'.

Related

Is it possible to use a string variable in if condition in Swift?

I'm new to iOS development and wondering if I could pass a string variable inside if statement? Here's my pseudo code:
x = 1
func myFunc() -> String {
myString = "x == 1"
return myString
}
if(myfunc()) {
code i want to execute
}
I am currently getting the following error: "'String' is not convertible to 'Bool'"
Is there a way I can do this?
You should use a comparison operator for this.
if myString == myFunc() {
// your code
}
If statement always wants a condition that can return a bool value. i.e. true and false.
In your above code, you are not providing sufficient data to if statement so that it can calculate whether the result iss true or false.
When you compare it like if myString == myFunc() , if statement will compare the string and return true if string matches else false.
if the string matches, it will execute the code that is within if conditions scope. Otherwise it will calculate the else condition.
UPDATE1:
I see you have updated the question, so you want to check if myFunc() is empty or not?
For that you can compare it with empty string.
if myFunc() == "" {
// your code
}
UPDATE2:
Question: (asked in comment) instead of writing "if(x == 1)" i am trying to use a variable so my if statement is "if(stringVaraible)" where stringVariable = "x ==1". Basically I am asking if it is possible to turn a string into normal code
Answer: No, you can't do that. Swift is a compiled language, not interpreted like Ajax. Read more here: https://stackoverflow.com/a/30058875/8374890
It's very specific and clear that you can't use String as boolean. The approach you can take is well known like..
if(myString == "x == 1") {
code i want to execute
}
or
if(desiredString == myFunc()) {
code i want to execute
}

Optionals and unwrapping

What I am trying to accomplish is this - I have two text fields and I want to print() a message to the console if the username text field .isEmpty or if the password field .isEmpty. The first thing I noticed is that the text fields are optional as they of course can be empty. So could anyone explain to me some of the syntax and reasoning behind the following code samples?
Q1: Why must I unwrap after the .isEmpty?
if(self.username.text?.isEmpty)! {
print("Something!")
}
Q2: Why does this syntax not work when you include an or operator?
if(self.username.text?.isEmpty || self.password.text?.isEmpty)! {
print("Please provide username and password!")
}
Q3: Why can I not unwrap directly after the .isEmpty?
if(self.username.text?.isEmpty! || self.password.text?.isEmpty!) {
print("Please provide username and password!")
}
Q1:
You must unwrap, because the text property can be nil. Maybe because it is a valid value, maybe because it's an artifact of Objective-C conversion and it is really nil_resettable.
Using ! is unsafe, because it can crash whenever you access the text, if it is unset.
Try something like this
if self.username.text?.isEmpty == false {
print("Something!")
}
Swift has an implicit non optional to optional promotion if the required type is optional.
At first it was Bool? == Bool and it got changed to Bool? == Bool?
Q2: Why does this syntax not work when you include an or operator?
let a: Bool? = self.username.text?.isEmpty
let b: Bool? = self.password.text?.isEmpty
let c = a || b // the problem here is that `Bool?` doesn't implement
// the operator `||` as it's not clear how this would
// work with optionals.
You want to do:
guard let username = self.username.text,
let password = self.password.text,
!username.isEmpty,
!password.isEmpty {
print("Please provide username and password!")
return
}
// code using username as String and password as String (not optionals)
Q3:
You need to fix your parenthesizing.
if (self.username.text?.isEmpty)! || (self.password.text?.isEmpty)! {
print("Please provide username and password!")
}
Please remember not to use ! in production code. This is unsafe. Use the variant from Q2.
Q1: Why must I unwrap after the .isEmpty?
if(self.username.text?.isEmpty)! {
print("Something!")
}
The if statement structure forces you to have true/false in the body, to simplify:
let condition = false
if condition {...}
When you unwrap this statement self.username.text?.isEmpty you are telling the compiler "I promise that it is never nil" even that it could be.
Q2: Why does this syntax not work when you include an or operator?
The same reason as before the input for or/and operator must be not nil (unwrapped).
Notice the line below. If you try and evaluate this statement, you will see that you are attempting to unwrap a boolean, with two optionals as parameters.
if(self.username.text?.isEmpty || self.password.text?.isEmpty)! {
Q3: Why can I not unwrap directly after the .isEmpty?
I am guessing here, based on the issue you presented.
isEmpty is not an optional, it can be true/false, therefore cannot be unwrapped.
This statement self.username.text?.isEmpty is optional, it can be true/false/nil and can be unwrapped.
I hope it helps to make things clearer. Reading about optionals and analyzing Apple's code examples might help even more.

Conditional instructions in swift

I am trying to write in swift something that should be very basic, but I can't seem to get a handle on it :
First, I create a global variable. For example:
var xx:Int
Then, I want to create a conditional instruction. Something like :
if (xx == 1){
//do something
}
else if (xx == 2) {
//do something else
}
I can do this very easily in Objective-C, but I can't seem to be able to do it in Swift. I have looked everywhere, and don't seem to find the answer.
With the code you provided you're probably getting the error: "Variable xx used before initialized". This is happening because the declaration of the variable is incomplete, you neither gave a value to the variable nor told the compiler it is an optional. You have three options:
Give a initial value to it; var xx: Int = //value here
Declare it as an optional (doing this you say that it may not have a value, if it does the code will be executed, if it doesn't it won't); var xx: Int?
Force unwrap the variable (it still an optional, but if you force-unwrap it you're assuring the compiler that the variable will have a value when needed, otherwise it'll crash); var xx: Int!
Or you can say var xx = Int() that way it's initialized and the default initialization is equal to 0. This is different than the other answers and allows you to have a value from the get go if you're not sure what value might be assigned during runtime.
In addition to the other poster's point that you must assign an initial value before you can use xx, you also need to lose the parentheses around the condition in your if statement:
var xx:Int
xx = 2
if xx == 1
{
//do something
}
else if xx == 2
{
//do something else
}

Redundancy with optional variables in swift - is there an elegant solution?

This might be seen as a minor issue, but it just looks ugly in the code and I would like to solve it.
I have an optional variable declared and would like to change it later, if it is not empty (!= nil) The code for this is:
First declare
private var myVariable: Int? // Optional Integer variable
Later decrement, when not empty
{
if myVariable != nil {myVariable!--} // Same condition in "if" and in unwrapping
}
I need the ! even when it is assured with the if-condition that the variable has a value. This is redundant and means that Swift must do the same comparison twice.
Is there a more elegant way in doing this?
My current Xcode Version is 6.3.
Just as examples, you could do the following:
myVariable?++
myVariable?--
myVariable? += 10
This uses optional chaining - if myVariable has non-nil a value, it is unwrapped and incremented. Otherwise the statement returns nil.
Answer to your question is Optional Chaining.
myVariable?--
if let myVariable = myVariable { //if - let unwrapping
myVariable-- //don't need the suffix now
}
I belive the point of giving "!" after variable is so the Swift doesn't need to double check. You said with "!" that the myVariable is not nil and it has a value so it won't double check.

Reason for assigning optional to new variable in conditional statement in Swift

I'm going through the swift docs, and in the optional segment, it talks about using the question mark -- ? -- to signify variables that might be nil. This can be used in an if statement to check for nil, but in the docs they assign the optional to a new variable in the conditional. Is there a reason for this?
For Example, it is presented in the docs similar to this:
// Declare an optional string (might be nil)
var optionalString: String? = "Hello"
// Assigns optionalString to new variable before checking if nil
if let string = optionalString {
println("\(optionalString) is not nil!")
}
else {
println("\(optionalString) is nil")
}
However, this runs just fine for me in tests:
var optionalString: String? = "Hello"
// Assigns optionalString to new variable before checking if nil
if optionalString {
println("\(optionalString) is not nil!")
}
else {
println("\(optionalString) is nil")
}
Question
Is there a reason to assign optionalString to a new variable string in the conditional statement?
Take a look at the section on Optional Chaining in the docs. In the example you cite, there's not much difference. But in other cases, an if-let construction lets you get at an unwrapped value that comes from a series of optional references and method calls, without using implicit unwraps that can crash your app if you haven't considered all the possible bindings for a value in a chain.
It's also useful if you want to avoid recomputing a value. You can use it in a lot of the same ways you'd use an assignment in a conditional in (Obj)C (remember if (self = [super init])).
For example, if the optional being tested comes from a computed property:
var optionalName: String? {
get {
if checkTouchID() {
return "John Appleseed"
} else {
return nil
}
}
}
var greeting = "Hello!"
if optionalName != nil {
greeting = "Hello, \(optionalName)"
}
Paste that into a playground, along with a stub implementation of checkTouchID() that returns true, and you'll immediately see in the results area that the optionalName getter is executing twice. (This would be a problem in a more realistic scenario, because you probably don't want code like this to implicitly checkTouchID() or downloadFromServer() or billApplePay() twice.) If you use an if-let construction instead, you'll only execute the getter once.
In a series of chained optionals (like if let johnsStreet = john.residence?.address?.street in the docs linked above), you don't want to rewrite the whole chain in the body of the if statement, much less recompute it.
I think the purpose of that assignment was to demonstrate the use of "let" within the if conditional clause. I don't see a meaningful difference between the provided code and your own.
From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/il/jEUH0.l
“If the optional value is nil, the conditional is false and the code in braces is skipped. Otherwise, the optional value is unwrapped and assigned to the constant after let, which makes the unwrapped value available inside the block of code.”