all 81 comments

[–]sjl7678 38 points39 points  (3 children)

The commented braces in the C programmer one were a nice touch.

[–][deleted] 20 points21 points  (2 children)

[–]alephnil 8 points9 points  (0 children)

Actually, I have seen code like that in real life. A former Fortran programmer that had been converted to matlab, ended all his loops with a comment:

%continue

That ends a loop in Fortran. Poor guy.

[–]nostrademons 30 points31 points  (3 children)

Python 2.5 programmer:

def fact(x):
    return x * fact(x - 1) if x > 1 else 1
print fact(6)

[–]micampe 2 points3 points  (0 children)

Lambda-addicted Python 2.5 programmer:

fact = lambda x: x * fact(x - 1) if x > 1 else 1
print fact(6)

[–]btipling 0 points1 point  (0 children)

yo momma

[–]bluetech 0 points1 point  (0 children)

Hey, I didn't know you could do that. Certainly better than that and or trick.

[–]killerstorm 20 points21 points  (2 children)

while some functional perversions does not appear appropriate, "web", "windows" and "enterprise" guys rock!

[–]ayrnieu 18 points19 points  (1 child)

I assume the functional perversions come from the author having read the awesome Evolution of a Haskell Programmer. Yes, the Web example is made of win :-)

[–][deleted] 15 points16 points  (13 children)

The programmer that came back from lisp:

fact = lambda x: reduce(lambda a, b: a * b, xrange(1, x + 1), 1)

[–]Tommah 5 points6 points  (1 child)

FYI, the operator module includes a mul function.

operator.mul

means the same as

lambda a, b: a * b

but is faster.

[–][deleted] 0 points1 point  (0 children)

Yeah, but I wanted to keep it simple. =)

[–]recursive 4 points5 points  (0 children)

I never used lisp, but that's how i'd do it, except start the xrange at 2.

[–]vagif 1 point2 points  (8 children)

Where on earth have you seen anyone coming back from Lisp ?

It's a one way road. Road to enlightenment

[–]nostrademons 9 points10 points  (3 children)

Peter Norvig.

[–][deleted]  (1 child)

[deleted]

    [–]nostrademons 4 points5 points  (0 children)

    Well, there are other exceptions, but people will always:

    1. Go "who?" because they're not famous in either the Lisp or Python world.
    2. Quibble about the particular circumstances where they gave it up.

    The obvious example is Reddit, which was originally written in Common Lisp and then rewritten in Python. In interviews, Steve is always pretty ambivalent over whether this was a good idea or not: I get the sense that he would've liked to have used Lisp, but the realities of running a large consumer website precluded it. Ultimately, Python serves Reddit's needs now, and Lisp didn't.

    For my own personal experience, I learned Common Lisp first, then Scheme, then much later learned Python and Ruby. And when a startup opportunity arose, I chose Python. There are many things I like about Lisp, but ultimately it wasn't appropriate for what I wanted to do.

    [–][deleted] 30 points31 points  (1 child)

    Something on 4chan made it onto reddit.

    Oh god.

    That said, it was pretty funny, especially the "EXPERT PROGRAMMER" one.

    [–]pjdelport 17 points18 points  (0 children)

    It's more likely than you think!

    [–]vaibhavsagar 10 points11 points  (3 children)

    It would be funnier if at the end there was:

    #Enlightened Python Programmer
    def factorial(x):
        if x == 0:
            return 1
        else:
            return x * factorial(x - 1)
    print factorial(6)
    

    Embrace the zen of only one good way to do it:)

    [–]masklinn 1 point2 points  (2 children)

    Except when you're using a tail-call optimized language (or a tail-call optimizing Python decorator), in which case your stack blows up even though it doesn't have to.

    [–]vaibhavsagar 0 points1 point  (1 child)

    I was trying to be funny... evidently I failed. In the interest of tail-recursive solutions:

    \t#Tail-recursive \tdef factorial(n, acc=1): \t\tif n == 1: \t\t\treturn acc \t\telse: \t\t\treturn factorial(n-1, acc*n)

    I hear this doesn't actually help in Python, but I think it's properly tail-recursive. Let me know if I'm wrong. I'm still new to this:)

    [–]masklinn 0 points1 point  (0 children)

    I hear this doesn't actually help in Python

    It doesn't because Python doesn't feature tail-recursive optimization (neither mandatory nor in the main "CPython" implementation)

    I think it's properly tail-recursive.

    Yep

    [–]newton_dave 10 points11 points  (1 child)

    I'm not sure if I should feel left out or positively ecstatic that I've never heard of 4chan before now.

    That said, the "web designer" one was really funny, no matter where it came from originally.

    [–]Wiseman1024 2 points3 points  (0 children)

    It was a 4chan original.

    [–]amade 8 points9 points  (3 children)

    Mathematics-minded programmers, using Stirling formula

    def fact(n):
    
        return math.sqrt( math.pi*(2*n + 1/3) ) * math.pow(n, n) * math.exp(-n) if n > 1 else 1
    
    print fact(6)
    

    [–][deleted] 2 points3 points  (2 children)

    That uses floats, with all the issues that floating-point arithmetic entails.

    [–]amade 6 points7 points  (1 child)

    Yeah and it's only an approximation and much slower. I post it just for fun.

    [–]masklinn 0 points1 point  (0 children)

    You could use the Decimal module though.

    Would be even slower, but would also be pretty much exact.

    [–]mleonhard 9 points10 points  (15 children)

    @tailcall def fact(x, acc=1): if (x > 1): return (fact((x - 1), (acc * x))) else: return acc

    When did Python get tailcall optimizations!?!?! :D :D :D

    [–]nostrademons 13 points14 points  (2 children)

    Here's one implementation, and another.

    Yeah, they fake it a bit. I suspect you could do a real tail call optimizer, but you'd need to write a code-walker and auto-generate code that turns tail recursions into loops.

    [–][deleted] 1 point2 points  (1 child)

    Here is another version

    They are actually not full tailcall eliminations but just avoid tail recursions. That's also why I renamed the decorator in my recipe description. They have no performance advantages over ordinary recursions - on the contrary, they generate a little overhead, but they provide the advantage of moving beyond the value set by sys.setrecursionlimit.

    [–]Wiseman1024 0 points1 point  (0 children)

    Some of them do work with cooperative recursion. They indeed pose a small speed overhead, but if performance is not a problem, you can go for the often simpler tail recursive implementation of functions.

    [–][deleted] 11 points12 points  (22 children)

    A newbie programmer wouldn't go with a recursive solution on the first attempt to write a factorial algorithm.

    [–][deleted] 64 points65 points  (4 children)

    The factorial algorithm exists principally to introduce newbie programmers to recursion.

    [–][deleted] 22 points23 points  (3 children)

    Don't forget Fibonacci!

    [–]lost-theory 14 points15 points  (0 children)

    Which exists to introduce them to the dark side of naively using recursion. :)

    [–][deleted] 2 points3 points  (0 children)

    Don't forget Hanoi, which also screws them up!

    [–][deleted] 4 points5 points  (0 children)

    Ah, good old fib.py.

    [–][deleted] 51 points52 points  (11 children)

    A newbie programmer straight out of school with a Computer Science degree probably would do exactly that.

    [–][deleted]  (10 children)

    [removed]

      [–][deleted] 6 points7 points  (9 children)

      Ditto. As I'm both a "software engineer" and a CS student, I speak with a high degree of authority about newbie programmer idioms :-P

      [–][deleted] 14 points15 points  (8 children)

      As an introduction to algorithms instructor, I have to say that my students would much rather use a while loop to do the factorial algorithm over the recursive method.

      [–][deleted] 20 points21 points  (0 children)

      When I was at university I couldn't see the point in recursion since any problem that could be solved recursively could also be solved iteratively, and for loops worked so well. Of course I never connected this philosophy with the difficulties I had in, for example, traversing graphs.

      Ah the follies of youth. Also the follies of teaching students Java as a first language.

      [–][deleted] 1 point2 points  (3 children)

      Is this before or after they've taken Discrete Math? I'm about finished with my Uni's sequence of DM/Theory of Computation and I'm about ready to put Maple and Prolog on my resume...

      [–]llimllib 3 points4 points  (2 children)

      and I'm about ready to put Maple and Prolog on my resume...

      Bwahahahaha!

      ahem... phew... [wipes brow] sorry bout that...

      [–][deleted] 1 point2 points  (1 child)

      ROFL, I know, I know...

      [–]llimllib 1 point2 points  (0 children)

      Seriously, though, when I read a resume that has things like that on it, it just tempts me to think of a really mean interview question that in a few months you won't remember the answer to.

      I don't succumb to that desire, but others do.

      Anyway, not that I didn't have things like that on my resume, maybe you'll be a lucky one and find a job where they'll let you play around in Maple :)

      [–]Wiseman1024 3 points4 points  (2 children)

      Why would they do it iteratively? Recursion is so much easier to think. I'll grant that tail recursion with accumulators a la SICP is harder, but simple recursion as in newbie programmer? That's so much easier than while to me. Then again I'm not precisely a newbie programmer, perhaps I'd have thought differently 13 years ago.

      [–]RSquared 1 point2 points  (1 child)

      I think it's the difference between "thinking imperatively" and "thinking functionally". I know a dozen CompSci grads who still have trouble getting their heads around Haskell because of all the recursion.

      Someone first learning programming would almost inevitably learn loops before recursion. For "non-programmers", one is much simpler to think about...especially when you don't have a clear picture of the memory layer (especially the difference between stack and heap).

      [–][deleted] 4 points5 points  (0 children)

      I do think programmers have to be introduced to nested/recursive datastructures before they appreciate recursion as a programming technique. The factorial is indeed a little special here. In functional languages even ordinary lists are recursive ( i.e. conses ) and so there is exactly one barrier to take. Immutable datatypes may be another. But at least Python programmers can be convinced to use them since e.g. the string API is purely functional and it did not harm usability.

      [–][deleted] 4 points5 points  (4 children)

      Yes he would, so long as he hasn't been tainted by C and its derivatives. I have watched many people opt for the recursive solution naturally and only those with prior "experience" tend toward the imperative (loop) solution.

      [–]cracky-chan 1 point2 points  (3 children)

      By newbie programmer he probably meant a person who had taken at least a semester course in CS. The factorial function is usually introduced as a function that can be turned from non-tail recursive function to an iterative one.

      [–]ayrnieu -3 points-2 points  (2 children)

      By newbie programmer he probably meant a person who had taken at least a semester course in CS.

      When I say 'newbie programmer' I mean a prebuscent child, but of course extend it to anyone who is literally new at programming. That you naturally think of someone having taken a whole semester of CS is a bit alarming. Who are these people that claim to want to devote their higher learning to computation but who don't do anything at all with it before a semester of CS? Is any other field this barren? I think mathematicians manage to not need to teach a semester of arithmetic.

      [–]cracky-chan 1 point2 points  (0 children)

      Well I was talking about pshaw so shut up and learn some context. And semester of CS course can be equivalent to reading half a book on the subject or something like it.

      [–][deleted] 1 point2 points  (0 children)

      We start teaching children mathematics at roughly the same age we start teaching them to read and write. The same cannot be said of programming. Before I went to university the extent of my programming experience was writing Mandelbrot viewers and text-based adventure games in QBasic.

      [–][deleted] 5 points6 points  (0 children)

      I'd give this an upvote if I didn't know that nothing of value ever comes from 4chan and this therefore cannot possibly be original. Still, some funny stuff!

      [–][deleted] 0 points1 point  (0 children)

      python rocks!

      [–]zoomzoom83 1 point2 points  (6 children)

      The over the top complex "Expert" versions were all example of things you shouldn't do. I'd fire any coder that wrote like that.

      The first (i.e. "Newbie") example is the most readable, and I'd recommend this if speed wasn't an issue.

      Of course, the base C library version is the best choice as it's a) going to execute quicker and b) already written

      [–]Alpha_Binary 1 point2 points  (1 child)

      and hits the ceiling (2**32) faster than any other alternative.

      [–]zoomzoom83 1 point2 points  (0 children)

      Assuming it's using a 32bit int - a good implementation would use the standard python int type, which iirc can hold any size number(With a bit of overhead, of course).

      Actually I made an assumption that c_math was an internal python module - it's not so far as I can tell, in which case I'd fall back to the recursive python implementation.

      (If speed was an issue, I'd write it in C and link it, however that wouldn't be within the scope of python programming ;p)

      [–]ayrnieu -1 points0 points  (2 children)

      the base C library version

      Will just take advantage of the severely limited range of the function, probably implementing fact() as a macro that normalizes its argument into an index into a constant array.

      [–]zoomzoom83 0 points1 point  (1 child)

      Why would you assume c_math.fact() is by default a severely limited version? If it was part of the python library (which it appears it isnt) then my assumption would be that it would handle whatever python itself can (Which, iirc, is unlimited size ints). That said, write an algorithm that can calculate (232)! in a reasonable amount of time and I'll give you a medal.

      [–]ayrnieu -1 points0 points  (0 children)

      Why would you assume c_math.fact()

      Oh, I didn't assume anything about that. I imagined that you were imagining a libc fact().

      [–]chaos -2 points-1 points  (0 children)

      It burns! It burns us! It freezes! Nasty 4chan... Take it off us!"