Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I like lambda because it allows anonymous functions-- functions that can be defined on the fly (dynamically) and then thrown away. IMO, it's generally bad form for a program to be dynamically creating named functions, filling the namespace.

Also, I like map and filter because they aren't just functions in the procedural sense but combinators: you can pass them around, using them as arguments and returning them. It's much harder to pass around a syntactic entity like a list comprehension (although I'm glad list comprehensions exist; as shorthand they are great in source code.)

All this said, I haven't used Python in 3 years, in favor of purely functional languages such as Clojure and ML, so I might be way out of date.



You bring up a good point about passing map and filter around. I hadn't really thought of that.

I still prefer to user list comprehensions, and don't think it would be so bad to have map, filter, reduce live in the itertools module. This would stylistically match what is done with the comparison operator functions living in their own module, which you can import if you need to pass the functions around.


List comprehensions are great, but they're sort of a DSL-- something the syntax recognizes as special and converts to something else. It's unusual that you can pass around higher-order syntactic elements, while every modern language worth its salt allows you to pass around functions.

Common Lisp has something similar, called LOOP. Implemented as a macro, it's a within-Lisp DSL for expressing looping constructs, e.g.

(loop for i from 1 to 10 sum i) => 55

(loop for c across "bar" collect c) => (#\b #\a #\r)

It's controversial within the CL community, because the loop language looks much more like traditional languages than Lisp.


Indeed, we figured out recently that it's basically embedded Algol 68... which seems superbly fitting somehow.


Common Lisp is very, very old. Tagbody and progv, anyone?

It's an influential language, for sure, but I prefer Clojure for a number of reasons.


The automatic distaste in our industry for things that are old is a disease, a form of vanity. Old ideas are not inadequate because they are old. Most great ideas are old. Sometimes, of course, an old thing is a vestige of some ancient limitation that no longer applies. Those ones are good to clear away. But the prevailing thought process in the software industry, no less dominant for its astonishing primitivity, is to reject the old per se. The will to novelty is so extreme that it doesn't matter if the new thing is worse, only that it is newer. We want to program in new languages like we want to drive new cars (a bad analogy in Common Lisp's case, unless you assume that the older car is both faster and more fuel efficient). Lisp in general, and Common Lisp in particular, is up against this dynamic. You can't understand the reactions to it without accounting for that.

That CL contains TAGBODY is a brilliant thing. It amazes me that a language can be at once so high-level and so low-level. I haven't had occasion to use it yet, but the fact that it's there, and that the higher-level abstractions are built in terms of it, is a thing of beauty to me. (I don't know about PROGV.)


You make a great point, and I think Lisp has enough fundamental value to deserve its place as the "100-year language". In 2060, people will still be using some descendant of Lisp. On the other hand, I think some aspects of CL are outmoded. I don't like the lack of support for maps as a top-level structure, and equality in CL is seriously broken, IMO.

I'd prefer to code in CL over Java/Blub, but I prefer Clojure over CL, and probably Haskell or ML over Clojure. (Lisp has better syntax, and macros are very cool, but static typing wins for large projects, in my opinion.)


IMO, it's generally bad form for a program to be dynamically creating named functions, filling the namespace.

That's what inner functions are for. This isn't the best example, but you get the idea:

  def foo(mylist):
    def n_to_the_n(n):
      if n > 1:
        return n**n
      return 1
    return [n_to_the_n(i) for i in mylist]


Do the inner functions get cleaned up after you exit the function body?

I'm used to Lisps, where def/defun/define/defn imply internment. For example, in Clojure:

  (defn foo [list]
    (defn n-to-nth [n] (Math/pow n n))
    (map n-to-nth list))
Would intern the symbol 'n-to-nth in the current namespace. So every time I see "def", I think of something that has that (mild, almost always innocuous) side effect.


The inner function just falls out of scope, and is presumably collected.

  >>> def foo(mylist):
  ...   def n_to_the_n(n):
  ...     if n > 1:
  ...       return n**n
  ...     return 1
  ...   return [n_to_the_n(i) for i in mylist]
  ... 
  >>> print foo([1,2,3,4,5])
  [1, 4, 27, 256, 3125]
  >>> foo
  <function foo at 0x6e5f0>
  >>> n_to_the_n
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  NameError: name 'n_to_the_n' is not defined
  >>>
Note that I only made the inner function longer than necessary for illustrative purposes :-)


>I'm used to Lisps, where def/defun/define/defn imply internment. For example, in Clojure:

With regard to 'define', it doesn't work like that in Scheme. A define in a function body behaves just like a let.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: