Is there a particular reason to favor stepping into multiple blocks vs. short cutting? For instance, take the following two functions in which multiple conditions are evaluated. The first example is stepping into each block, while the second example short cuts. The examples are in Python, but the question is not restricted to Python. It is overly trivialized as well.
def some_function():
if some_condition:
if some_other_condition:
do_something()
vs.
def some_function():
if not some_condition:
return
it not some_other_condition:
return
do_something()
Favoring the second makes code easier to read. It's not that evident in your example but consider:
def some_function()
if not some_condition:
return 1
if not some_other_condition:
return 2
do_something()
return 0
vs
def some_function():
if some_condition:
if some_other_condition:
do_something()
return 0
else:
return 2
else:
return 1
Even if the function has no return value for the "failed" conditions, writing the functions with inverted ifs way makes placing breakpoints and debugging easier.
In your original example where would you place the breakpoint if you wanted to know whether your code is not running because some_condition or some_other_condition failed?
Related
I realize that it's not valid ruby but what would be the technical hurdles to implement the below functionality into the Ruby core language (of say v2.3)?
variable = 1 if condition else -1
I'd also like to allow the following for more generic use.
variable = { 1 } if condition else { -1 }
I'm very open to requiring an "end" at the end.
I get that a ternary can easily accomplish this but I'm looking for a more readable inline-if that allows an else.
I get that I can make a function which does this via any number of styles but I'd prefer to have it as readable as possible.
Thanks.
EDIT: I hate editing questions for obvious reasons.
In response to the question of how the generic option is more ruby-esque, see the below example (I needed newlines).
variable = {
operation_one
operation_two
...
SUCCESS_STATUS_CODE
} if loaded_dependencies else {
do_detailed_logging
FAILURE_STATUS_CODE
}
if variable then
it_worked
else
explain_why
end
Because your example, while it seems readable to you, has too many ambiguities in other cases.
Not to mention that ruby has a way to do this, and it's the ternary operator. To say that your example is more ruby-like, is almost like wondering why the wheelbase of the Ford Mustang wasn't longer, and that it would be more "Mustang-like" if it was.
But here are some issues with your proposal, starting from your example:
variable = { 1 } if condition else { -1 }
Here you've given your "if else" bit a lower precedence than the "=".
In other words:
variable = ({ 1 } if condition else { -1 })
That's a serious problem, because it breaks the currently allowed:
variable = 1 if condition
The precedence for that statement is:
(variable = 1) if condition
And that's important. No assignment happens if the condition is false.
This can be a really big deal, for example if the lvalue (left side) actually has side-effects. For example:
var[0] = 1 if condition
The lookup for "var[0]" is a method in whatever class object var is, and while [] doesn't usually have side-effects, it can - and now you are going to do those side effects even if the condition is false.
And I won't even get into:
variable = { 1 } if condition if condition2 else { -1 }
But if you don't like it, you can always write your own language and see what happens!
I have this program that I am working on that is supposed to find the sum of the first 1000 prime numbers. Currently all I am concerned with is making sure that the program is finding the first 1000 prime numbers, I will add the functionality for adding them later. Here is what I have:
#!/usr/bin/ruby
def prime(num)
is_prime = true
for i in 2..Math.sqrt(num)
if (num % i) == 0
is_prime = false
else
is_prime = true
end
end
return is_prime
end
i = 2
number_of_primes = 0
while number_of_primes < 1000
prime = prime(i)
if prime == true
number_of_primes++
end
i++
end
When i try to run the program I get the following feedback:
sumOfPrimes.rb:32: syntax error, unexpected keyword_end
sumOfPrimes.rb:34: syntax error, unexpected keyword_end
what gives? Any direction is appreciated.
Ruby doesn't have ++ operator, you need to do += 1
number_of_primes += 1
Unasked for, but a few pieces of advice if you're interested:
One of the cool things about Ruby is that question marks are legal in method names. As such you'll often find that 'predicate' methods (methods that test something and return true or false) end with a question mark, like this: odd?. Your prime method is a perfect candidate for this, so we can rename it prime?.
You use a local variable, is_prime, to hold whether you have found a factor of the number you're testing yet - this is the kind of thing you'd expect to do in an imperative language such as java or C - but Ruby has all sorts of cool features from functional programming that you will gain great power and expressiveness by learning. If you haven't come across them before, you may need to google what a block is and how the syntax works, but for this purpose you can just think of it as a way to get some code run on every item of a collection. It can be used with a variety of cool methods, and one of them is perfectly suited to your purpose: none?, which returns true if no items in the collection it is called on, when passed to the code block you give, return true. So your prime? method can be rewritten like this:
def prime? num
(2..Math.sqrt(num)).none? { |x| num % x == 0 }
end
Apart from being shorter, the advantage of not needing to use local variables like is_prime is that you give yourself fewer opportunities to introduce bugs - if for example you think the contents of is_prime is one thing but it's actually another. It's also, if you look carefully, a lot closer to the actual mathematical definition of a prime number. So by cutting out the unnecessary code you can get closer to exposing the 'meaning' of what you're writing.
As far as getting the first 1000 primes goes, infinite streams are a really cool way to do this but are probably a bit complex to explain here - definitely google if you're interested as they really are amazing! But just out of interest, here's a simple way you could do it using just recursion and no local variables (remember local variables are the devil!):
def first_n_primes(i = 2, primes = [], n)
if primes.count == n then primes
elsif prime? i then first_n_primes(i + 1, primes + [i], n)
else first_n_primes(i + 1, primes, n)
end
end
And as far as summing them up goes all I'll say is have a search for a ruby method called inject - also called reduce. It might be a bit brain-bending at first if you haven't come across the concept before but it's well worth learning! Very cool and very powerful.
Have fun!
Recursion makes backtracking easy as it guarantees that you won't go through the same path again. So all ramifications of your path are visited just once. I am trying to convert a backtracking tail-recursive (with accumulators) algorithm to iteration. I heard it is supposed to be easy to convert a perfectly tail-recursive algorithm to iteration. But I am stuck in the backtracking part.
Can anyone provide a example through code so myself and others can visualize how backtracking is done? I would think that a STACK is not needed here because I have a perfectly tail-recursive algorithm using accumulators, but I can be wrong here.
If the function is actually recursive, then the transformation is as follows (and this is what a compiler which understand TCO will do for you, so you shouldn't have to do it yourself):
Original:
function func(a1, a2, a3...)
... doesn't contain either return or call
return val
...
return func(x1, x2, x3...)
...
... etc.
Converted to:
function func(a1, a2, a3...)
func: // label for goto (yuk!)
...
return val // No change
...
a1 = x1; a2 = x2; a3 = x3...; goto func;
...
... etc.
In order to make this transformation work with mutually co-recursive functions, you need to combine them into a single function, each of which comes with a label. As above, simple return statements are not altered, and return foo(...) turn into assignment to parameter variables followed by goto foo.
Of course, when combining the functions, you may need to rename local variables to avoid conflicts. And you will also lose the ability to use more than one top-level function, unless you add something like a switch statement (with gotos) at the top entry point, before any label. (In fact, in a language in which allowed goto case foo, you could just use the case labels as labels.)
The use of goto is, of course, ugly. If you use a language which preferably guarantees tail-call optimization, or failing that, at least makes a reasonable attempt to do it and reports when it fails, then there is absolutely no motivation to replace the recursive solution, which (in my opinion) is almost always more readable.
In some cases, it's possible to replace the goto and label with something like while (1) { ... }or other such loops, but that involves replacing thegotos withcontinue` (or equivalent), and that won't work if they're nested inside of other loops. So you can actually waste quite a lot of time making the ugly transformation slightly less ugly, and still not end up with a program as readable as the original.
I'll stop proselytizing recursion now. :)
Edited (I couldn't help it, sorry)
Here's a back-tracking n-queens solution in Lua (which does do TCO), consisting of a tail-recursive solver and a tail-recursive verifier:
function solve(legal, n, first, ...)
if first == nil -- Failure
then return nil
elseif first >= n -- Back-track
then return solve(legal, n, ...)
elseif not legal(first + 1, ...) -- Continue search
then return solve(legal, n, first + 1, ...)
elseif n == 1 + select("#", ...) -- Success
then return first + 1, ...
else -- Forward
return solve(legal, n, 0, first + 1, ...)
end
end
function queens_helper(dist, first, second, ...)
if second == nil
then return true
elseif first == second or first - dist == second or first + dist == second
then return false
else
return queens_helper(dist + 1, first, ...)
end
end
function queens_legal(...) return queens_helper(1, ...) end
-- in case you want to try n-rooks, although the solution is trivial.
function rooks_legal(first, second, ...)
if second == nil then return true
elseif first == second then return false
else return rooks_legal(first, ...)
end
end
function queens(n) return solve(queens_legal, n, 0) end
Very simple question:
Specifically in Python (since Python actually has "strongly recommended" style guidelines specified in PEP 8, but really this applies to any language), should a function with an if clause that always returns have the alternative code in an else clause or not? In other words, func_style_one() and func_style_two() in the following piece of code are (obviously) exactly equivalent:
def func_style_one():
if some_conditional_function():
do_something()
return something()
else:
do_something_else()
return something_else()
def func_style_two():
if some_conditional_function():
do_something()
return something()
do_something_else()
return something_else()
Obviously, the best and most readable style depends on the situation, and opinions will vary greatly on which is better, but I'm asking which is specifically preferred by the core Python community. (e.g. Which is used more often in the standard library, all other things being equal?)
As a rule of thumb, you should always avoid adding unneccessary complexity to your code, whatever the language. It also often is a good idea to try to split your code into semantically meaninful subsections.
Given these heuristics, there is no definitive answer. It really boils down to what you are trying to achieve.
I'll demonstrate this with examples.
If we have a function that checks for various error conditions before proceeding, it could make sense to write it without else:
def do_stuff():
if error1():
return cleanup_and_fail()
return ok()
This is better as you often end up checking several errors in similar fashion in a sequence:
def do_stuff():
if error1():
return cleanup_and_fail()
if error2():
return do_different_cleanup_and_fail()
return ok()
However, if your function instead branches to two equal branches, it could semantically make more sense to you else:
def do_stuff():
if option1():
return do_option1()
else:
return do_option2()
This is because you often end up adding several other options with elif:
def do_stuff():
if option1():
return do_option1()
elif:
return do_option2()
else:
return do_option3()
To summarize: think about the semantics of your code and choose syntax accordingly.
Consider the following code in C:
for(int i=0; i<10 && some_condition; ++i){
do_something();
}
I would like to write something similar in Python. The best version I can think of is:
i = 0
while some_condition and i<10:
do_something()
i+=1
Frankly, I don't like while loops that imitate for loops. This is due to the risk of forgetting to increment the counter variable. Another option, that addressess this risk is:
for i in range(10):
if not some_condition: break
do_something()
Important clarifications
some_condition is not meant to be calculated during the loop, but rather to specify whether to start the loop in the first place
I'm referring to Python2.6
Which style is preferred? Is there a better idiom to do this?
This might not be related, but there's what I'm used to do... If some_condition is simple enough, put it in a function and filter items you iterate over:
def some_condition(element):
return True#False
for i in filter(some_condition, xrange(10)):
pass
You can use this approach also when you iterate over some list of elements.
selected = filter(some_condition, to_process)
for i, item in enumerate(selected):
pass
Again, this might not be your case, you should choose method of filtering items depending on your problem.
In general, the "range + break" style is preferred - but in Python 2.x, use xrange instead of range for iteration (this creates the values on-demand instead of actually making a list of numbers).
But it always depends. What's special about the number 10 in this context? What exactly is some_condition? Etc.
Response to update:
It sounds as though some_condition is a "loop invariant", i.e. will not change during the loop. In that case, we should just test it first:
if some_condition:
for i in xrange(10):
do_something()
for loops with a constant upper bound are a bit rare in Python. If you are iterating over somearray, you might do:
for i in xrange(len(somearray)):
if not some_condition:
break
do_sth_with(i, somearray[i])
or, better:
for i, item in enumerate(somearray):
if not some_condition:
break
do_sth_with(i, item)