Sunday, March 16, 2014

Helper Functions

Three weeks ago I examined one strange topic that occurred while using helper functions. I published the post and thought I was over and done with the subject. But then I came across this post on piazza, I realized that there was territory here which had been approached, but not explained thoroughly.

My question is: what are the different ways of using helper functions, particularly when the helper is recursive?

As an example problem: take a list of strings, stick them all together, in order (recursively). Recall the recursive string-sticker-together algorithm:

def string_together(x: 'list of str') -> str:
if len(x) == 2:
return x[0] + x[1]
else:
return string_together(y[:-1]) + y[-1]

Now, the task: given a list of strings, string them together, then returns a tuple of three copies of that string three times in a single line. Yes, there are going to be easier ways to do this: I'm only considering options that require a recursive helper function. I'll call this function add_strings.

I'm going to investigate options, considering what happens in a shell after calling:

>>> from xx import add_strings


Method one: the module-level helper

The idea here is that the helper is just another function defined in xx. Standard stuff.

def add_strings(y): y = string_together(y) return y,y,y def string_together(x): if len(x) == 2: return x[0] + x[1] else: return string_together(x[:-1]) + x[-1]

The first thing you should know is that a syntax error in string_together will cause the line

from xx import add_strings

to raise SyntaxError. Actually, the existence of any syntax error in the file will cause that import to raise SyntaxError.

So the specific thing you should know about this method is that the line

from xx import add_strings

does not import string_together. That is, if you then try to do anything with string_together, you get a NameError.


Method two: the nested helper

This is very similar to the previous method; the only difference is that the helper is located inside the main function.

def add_strings2(y):
    def string_together2(x):
        if len(x) == 2:
            return x[0] + x[1]
        else:
            return string_together2(y[:-1]) + y[-1]
    y = string_together2(y)
    return y,y,y

This seemed to have exactly the same behaviour as the previous method, so I looked it up. To summarize my research, nested helpers are useful  for functions that return functions, helpful in terms of readability, but otherwise serve no additional purpose. But hey, readability is good.

On the other hand, if you have to run these functions, say, ten million times, the nested helper version is actually a few seconds slower. This is due to (I presume) string_together having to be redefined at each call of the function.

Method three: the "modal helper"

This is a bit harder. Also, there might be a better name for it (but it looks modal to me), and it's about as tried-and true as "Meta-Recursion". Still, it works. The idea is that the function is its own recursive helper, but only on the recursive calls.

def add_strings3(y, helper=False):
    if helper:
        if len(y) == 2:
            return y[0] + y[1]
        else:
            return add_strings3(y[:-1], True) + y[-1]
    else:
        y = add_strings3(y, True)
        return y,y,y     

This has the advantage that there is no internal function that you might not have access to. It's comparable in speed to the module-level helper. Is it more readable? Probably not, but it's simple.


Random slogs of the week!  (explanation here)

C - Average. Probably not worth looking at, unless you want to read all of the slogs.
B - Above Average. One or two neat things. Maybe try it  if you're looking for content on those particular topics.
A - Excellent. Lots on interesting ideas that aren't easy to find elsewhere. Probably worth visiting; I'd expect to find more interesting content here in the future.
D - Below Average. Not reader-friendly. Maybe take a look to make sure you're not making the same mistakes.
F - Fail. Fatally flawed; for example, not having any content. I hope I don't find any of these.


  • I love the writing style. Light and entertaining.
  • It's really a diary, a collection of feelings. The most interesting of those I've come across thus far. Also, diaries are better than checklists.
  • It's really short. I've said it once, I'll say it again, having short posts is not inherently good or bad. Here, however, where the content is not complex, I could do with a bit more.
  • The updates are really sparse. :(
  • Rating: D+   It was just unique enough that I hope he/she'll come back...
csc148 slog by muc
  • A bit of a diary, but not too much
  • Talks about time management, or at least the need for it.
  • Suffers from being more explicit in the problems than the solutions. 
  • Posting not weekly, but frequent enough I'm confident it'll update in the future.
  • He's taking real analysis!? A math major myself, I'm still impressed.
  • Rating: C+   The only flaw is that there's nothing... intriguing about it -- I'm not convinced that you'll thank me for it ("neat things!") if I recommend it to you.
SLOG1 by Rashid Gaziyev
  • Two posts: OOP, and recursion. Man, this person is determined to do the bare minimum. On the other hand, I'm fairly confident that there is to be at least one future post.
  • The first post is a checklist. Literally. It answers questions one-by-one as listed on the slog handout. I would say that he had missed the part about discussing the way the course is being operated -- except that he seems to have addressed that, too. Thorough.
  • The second post is in a completely different (I guess he got feedback) and much better style. He gives an original (I think) example, always good. Beyond that, a lot of fact-stating.
  • Rating: C+   I really am not impressed, but I just can't come up with more justification.
CSC148 SLOG by GR
  • Talks about course material, and goes beyond lecture content. That is what I'm looking for.
  • The author is even clever, at least a few times. Nice.
  • Reading the first posts: the author really needs to learn how to break down their paragraphs. Reading the newer posts: the author did learn that.
  • A couple small grammar errors, inconsistencies, could use cleaning up.
  • A reference to another slog. Good.
  • Long, long posts (damn, I suffer from that, too)
  • Rating: A+
CSC 148 Winter by Wenfeng. J
  • Whoa, look at that template. Unsure whether I like it, but it stands out.
  • Another unhelpful TA comment. I'm going to assume that the post was changed retroactively, because that comment doesn't really seem relevant.
  • A bit of a diary again. The author does a good job of relating everything back to the course, for the most part.
  • Tells us what his difficulties are, doesn't tell us about his approach or resolution. (This is recurring, isn't it. I'm going to need a clever name. How about... "pity-party"? Yeah, I think that gets the message across...)
  • His examples are confusing :( More explanation would be helpful.
  • He seems to only post technical requirement for the specific assigned topics (the complaint being that most of the posts feel very different from the two technical ones).
  • The most recent post is formatted differently from the others. And it's ugly. I wonder if the author realizes.
  • Rating: C+
That's all for now. Until next week, may you use combinations of Google and firsthand experimentation.
As always, I anxiously await any and all comments.

--David

No comments:

Post a Comment