I'm trying to create a loop than continues to take input until the input gives the command to break the loop. What I'm doing now looks a little like this:
int start = 1;
while (start == 1) {
//Program statement
}
However, I feel as though there is an easier, more effective way to create a loop that repeats until the user gives the command to stop it. Does something like that exist?
A common idiom to express a "forever" loop in C and other C-like languages, including Objective-C, is to use an empty for:
for(;;) {
// statements
}
You should do it like this:
while(true)
{
if( exit_condition)
{
break;
}
}
do{
userInput = readUserInput()
}while(userInput != exit_condition)
Any loop as for, while, or even goto can do this job. If you put a condition instead of "true" in the loop, You can reduce code and doesn't need to use the "break" statement.
Related
The count is 4 at the end of the code below. I expected 0. Why is it 4? How can I get 0?
var count = 0;
"hello".forEach {
if(it == 'h')
{
println("Exiting the forEach loop. Count is $count");
return#forEach;
}
count++;
}
println("count is $count");
Output:
Exiting the forEach loop. Count is 0
count is 4
return#forEach does not exit forEach() itself, but the lambda passed to it ("body" of forEach()). Note that this lambda is executed several times - once per each item. By returning from it you actually skip only a single item, so this is similar to continue, not to break.
To workaround this you can create a label in the outer scope and return to it:
var count = 0;
run loop# {
"hello".forEach {
if(it == 'h')
{
println("Exiting the forEach loop. Count is $count");
return#loop;
}
count++;
}
}
This is described here: https://kotlinlang.org/docs/returns.html#return-at-labels
Note that the use of local returns in previous three examples is similar to the use of continue in regular loops. There is no direct equivalent for break, but it can be simulated by adding another nesting lambda and non-locally returning from it
It is 4 because the forEach call the lambda passed to it for each character in the string, so the return#forEach in your code return for the first element. You can use a for loop and use break to obtain 0.
return#forEach returns from the lambda function. But the forEach function is a higher-order function that calls the lambda repeatedly for each item in the iterator. So when you return from the lambda, you are only returning for that single item in the iterator. It is analogous to using continue in a traditional for loop.
If you want to exit iteration in a higher-order function completely, you have to use labels. And as I type this, I see another answer already shows how to do that, but I'll leave this in case the different explanation helps.
If your objective is to count the number of characters before 'h', you could do something like this:
val numCharsBeforeH = "hello".takeWhile { it != 'h' }.length
From your comment to Tenfour04's answer:
This is not very convenient. Why didn't the makers of Kotlin create a "break" equivalent?
Here is a quote of the "Loops" section of the Coding conventions:
Prefer using higher-order functions (filter, map etc.) to loops.
Exception: forEach (prefer using a regular for loop instead, unless
the receiver of forEach is nullable or forEach is used as part of a
longer call chain).
When making a choice between a complex expression using multiple
higher-order functions and a loop, understand the cost of the
operations being performed in each case and keep performance
considerations in mind.
Indeed, using a regular for loop with break does what you expect:
var count = 0;
for (char in "hello") {
if (char == 'h') {
println("Breaking the loop. Count is $count")
break
}
count++
}
println("count is $count")
Output:
Breaking the loop. Count is 0
count is 0
Except for very simple operations, there are probably better ways to do what you need than using forEach.
I'm tyring to make kind of macros by using scripts of WoW itself.
And I heard that the script of WoW is based on Lua.
Though I've used Obj-C ,Swift and C++ for several years, Embarrassingly it was quite hard to write down some code with Lua.(eventhough it was quite short.)
I'm trying to return boolean value by function for if statement in for loops.
If it was Obj-C, it would be like below.
-(void) script {
Bool on = NO;
NSArray* zone = [#"Feralas",#"The hinterlands",#"Duskwood"];
for(int i = 0 ; i < 3 ; i ++) {
if([self clearCheck:i]) {
NSLog(#"stone on! -> %#",zone[i]);
on = YES;
}
}
if (!on) {
NSLog(#"No Stone Today..");
}
}
-(Bool) clearCheck:(int)index {
return [C_QuestLog IsQuestFlaggedCompleted:index+44329];
}
And A Lua code I tried is below
local o,z=false,{"Feralas","The hinterlands","Duskwood"}
function f(x) return C_QuestLog.IsQuestFlaggedCompleted(44329+x) end
for i=1,3 do
if f(i) then do
print("stone on! -> ",z[i])
o=true
end
end
if not o then do
print("no stone today..")
end
What did i miss? and How Should it be?
I hope someone could help me from this difficulty...
You're probably seeing an error message like
'end' expected (to close 'if' at line ...) near
That's because you have a superfluous do in your code that "steals" the end you provided for the if. So you're short one end per if statement.
Remove do after then.
Lua 5.4 Reference Manual: 3.3.4 Control Structures
stat ::= if exp then block {elseif exp then block} [else block] end
Aside from that your code is syntactically correct.
in my code I have the following if statement:
if (a.count >= 2) {
t2 = array[b % a.count];
array[0] = t2;
}
I have another if statement that goes like the first. What I want it to do is if a <= 0 then goto a certain line, or skip over certain parts of code. How would I do this? I was thinking something along the lines of
if (a.count <= 0) {
goto line 96
}
This wouldn't work, the syntax is wrong, but how would I do this?
Goto statements are generally considered bad programming and excessive utilization of them can lead to code that is hard to maintain and debug.
That said, if/else/else if provide all the functionality you need.
I recommend putting the code you need to run inside that if statement in a separate method and then calling it from the if statement.
if (a.count <= 0) {
nameOfNewMethod();
}
//somewhere else
- (void) nameOfNewMethod {
//code here
}
Put the lines of code you want to "goto" in a function (or if appropriate, a block) and call the function (or block). If there are lines of code you want to skip, you can always return early out of a function, or use an else block?
There is in fact a goto command in Objective-C. To utilize it, you have to create a label, ex:
marker:
and jump to it like so within the same method:
goto marker;
But you can't declare any variables between those two commands. All the variables have to be created before the jump so that they still exist after.
Here's an example of how to use goto:
int x = 0;
if (a.count <= 0) {
goto marker;
}
x = 5;
marker:; // <-- semi-colon indicates the label is followed by an empty statement, thus allowing for immediate variable declaration
int y = x + 7;
In that case, if a.count <= 0, y == 7, else y == 12.
When normally using a for-in-loop, the counter (in this case number) is a constant in each iteration:
for number in 1...10 {
// do something
}
This means I cannot change number in the loop:
for number in 1...10 {
if number == 5 {
++number
}
}
// doesn't compile, since the prefix operator '++' can't be performed on the constant 'number'
Is there a way to declare number as a variable, without declaring it before the loop, or using a normal for-loop (with initialization, condition and increment)?
To understand why i can’t be mutable involves knowing what for…in is shorthand for. for i in 0..<10 is expanded by the compiler to the following:
var g = (0..<10).generate()
while let i = g.next() {
// use i
}
Every time around the loop, i is a freshly declared variable, the value of unwrapping the next result from calling next on the generator.
Now, that while can be written like this:
while var i = g.next() {
// here you _can_ increment i:
if i == 5 { ++i }
}
but of course, it wouldn’t help – g.next() is still going to generate a 5 next time around the loop. The increment in the body was pointless.
Presumably for this reason, for…in doesn’t support the same var syntax for declaring it’s loop counter – it would be very confusing if you didn’t realize how it worked.
(unlike with where, where you can see what is going on – the var functionality is occasionally useful, similarly to how func f(var i) can be).
If what you want is to skip certain iterations of the loop, your better bet (without resorting to C-style for or while) is to use a generator that skips the relevant values:
// iterate over every other integer
for i in 0.stride(to: 10, by: 2) { print(i) }
// skip a specific number
for i in (0..<10).filter({ $0 != 5 }) { print(i) }
let a = ["one","two","three","four"]
// ok so this one’s a bit convoluted...
let everyOther = a.enumerate().filter { $0.0 % 2 == 0 }.map { $0.1 }.lazy
for s in everyOther {
print(s)
}
The answer is "no", and that's a good thing. Otherwise, a grossly confusing behavior like this would be possible:
for number in 1...10 {
if number == 5 {
// This does not work
number = 5000
}
println(number)
}
Imagine the confusion of someone looking at the number 5000 in the output of a loop that is supposedly bound to a range of 1 though 10, inclusive.
Moreover, what would Swift pick as the next value of 5000? Should it stop? Should it continue to the next number in the range before the assignment? Should it throw an exception on out-of-range assignment? All three choices have some validity to them, so there is no clear winner.
To avoid situations like that, Swift designers made loop variables in range loops immutable.
Update Swift 5
for var i in 0...10 {
print(i)
i+=1
}
I've responded to threads here (or at least commented) with answers containing code like this, but I'm wondering if it's good or bad form to write a series of if branches with one (or more) of the branches doing nothing in them, generally to eliminate checking for null in every branch.
An example (C# code):
if (str == null) { /* Do nothing */ }
else if (str == "SomeSpecialValue")
{
// ...
}
else if (str.Length > 1)
{
// ...
}
instead of:
if (str != null && str == "SomeSpecialValue")
{
// ...
}
else if (str != null && str.Length > 1)
{
// ...
}
And, of course, this is just an example, as I tend to use these with larger and more complex classes. And in most of these cases, a null value would indicate to do nothing.
For me, this reduces the complication of my code and makes sense when I see it. So, is this good or bad form (a code smell, even)?
I prefer doing it like this-
if (str != null)
{
if (str == "[NULL]")
{
// ...
}
else if (str.Length > 1)
{
// ...
}
}
I think you can always "reword" an if with an empty body into it's negation with a body, and that it looks better and makes more sense.
I would normally put a return or something like that in the first if:
void Foo()
{
if (str == null) { return; }
if (str == "SomeSpecialValue")
{
// ...
}
else if (str.Length > 1)
{
// ...
}
}
If you can't do this, because the function does something else after the if/else, I'd say it's time to refactor, and split the if/else part out into a separate function, from which you can return early.
It is indeed good to avoid the following, because it needlessly re-checks one of the conditions (the fact that the compiler will optimize this away is beside the point--it potentially makes more work for folks trying to read your code):
if (str != null && str == "SomeSpecialValue")
{
// ...
}
else if (str != null && str.Length > 1)
{
// ...
}
But it's also rather bizarre to do what you suggested, below:
if (str == null) { /* Do nothing */ }
else if (str == "SomeSpecialValue")
{
// ...
}
else if (str.Length > 1)
{
// ...
}
I say this is bizarre because it obfuscates your intent and defies the reader's expectations. If you check for a condition, people expect you to do something if it is satisfied--but you're not. This is because your intent is not to actually process the null condition, but rather to avoid a null pointer when you check the two conditions you're actually interested in. In effect, rather than having two conceptual states to handle, with a sanity provision (non-null input), it reads instead like you have three conceptual states to handle. The fact that, computationally, you could say there are three such states is beside the point--it's less clear.
The usual case approach in this sort of situation is as Oren A suggested--check for the null, and then check the other conditions within the result block:
if (str != null)
{
if (str == "SomeSpecialValue")
{
// ...
}
else if (str.Length > 1)
{
// ...
}
}
This is little more than a matter of readability-enhancing style, as opposed to an issue of code smell.
EDIT: However, if you're set on the do-nothing condition, I do very much like that you included a "do nothing" comment. Otherwise, folks might think you simply forgot to complete the code.
In this particular case I will return early and it makes code easier to read
if (string.IsNullOrEmpty(str)) { return; }
I like to put an explicit return statement.
Yes it is a code smell.
One indication is that you thought to ask this question.
Another indication is that the code looks incomplete- as if something should belong there. It may be readable sure, but it feels off.
When reading that code, an outsider has to stop for a second and use brainpower to determine if the code is valid/complete/correct/as intended/adjective.
user359996 hit the nail on the head:
I say this is bizarre because it obfuscates your intent and defies the reader's expectations.
Your first example is perfectly readable to me -- doesn't smell at all.
It all depends on context. If putting an empty if statement makes the code more readable, then go for that.
It's readable, whether it is good or bad depends upon what you are trying to achieve - generally long nested "goes-on-forever" type if statements are bad. Don't forget about static string methods baked into the framework: string.IsNullOrEmpty() and string.IsNullOrWhiteSpace().
Your if (str == null) { /* Do nothing */ } line is unusual, but does have one positive point: it is letting other developers know up front that you are deliberately doing nothing for that case, with your long if/else if structure your intentions could become unclear if you changed it to
if (str != null)
{
/* carry on with the rest of the tests */
}