5 ms·
I'm a Clojure guy that just wrote my first Pylons app. Here's my impression: 1. Python doesn't suck. I was able to mix FP & OOP approaches to get to my goal
by francoisdevlin 16y ago
I'm a Clojure guy that just wrote my first Pylons app. Here's my impression:
1. Python doesn't suck. I was able to mix FP & OOP approaches to get to my goal fairly quickly.
2. iPython was fun to use, helped out a lot, but it's not SLIME.
3. Guido has an excellent goal with making code readable, and significant white space is not a bad choice. However, I find being able to analyze active data structures in a Clojure namespace to be a superior way to learn about a system.
4. Python's libraries are pretty good, and it's already been written. As a first impression, Python libs are much better to use than Clojure wrapped java libs. I'm going to look into porting SQLAlachemy to Clojure, it rocks.
5. Paster has a ton of functionality. I'd like to see a similar Clojure tool, maybe Lien can evolve into that.
6. I would like to see more FP constructs natively available in Python.
7. __method__ is an interesting convention. You can have an object implement the right method, and your object works with Python syntax. However, I find it to be a poor man's version of Clojure's protocols (Full Disclojure, I have a conflict of interests here).
8. Decorators are an interesting way to do functional composition, but I prefer comp and monads. Way more versatile.
9. INSERT MACRO RANT HERE
That's all I've got for now. I'm sure I forgot something.
SFD
edit: grammar & spelling
- gaius 16y agoPoint 6, we are lucky to keep the ones we have, Guido is not keen on map, reduce, etc.
- yummyfajitas 16y agoWhile Guido is not keen on reduce, I don't think he has any desire to eliminate list comprehensions (which are equivalent to map/filter).
- silentbicycle 16y agoIn other words, list comprehensions are the Pythonic version of same.
- sunqiang 16y agoand Generator Expressions[1], a lazy version of list comprehensions [1]: http://www.python.org/dev/peps/pep-0289/ http://www.python.org/dev/peps/pep-0289/
- silentbicycle 16y agoYeah, but generators have been done much better. Look at Icon, Lua, or Prolog.
- endtime 16y agoI wonder why. I never really use map over list comps, but I've used reduce in several situations where a comprehension wouldn't have been appropriate.
- leif 16y agoRe: 8, you don't need decorators to compose functions: def comp(f, g): def h(*args, **kwargs): return g(f(*args, **kwargs)) # fix up h.__doc__ and friends return h or simply (lambda the, args: g(f(the, args))(x, y) (don't remember comp's semantics, is (comp f g) = f o g or g o f?) too long; don't read: Decorators are certainly cool, but semantically they represent something more like a pattern than a FP construct. A decorator represents something you might want to do to lots of functions, a property you want all instances of a function to have without writing it explicitly into each function. Function composition is more along the lines of having two functions which are interesting on their own, but which sometimes you want to compose. With decorators, it would also be awkward to compose multiple functions. Observe: def compose_with(g): def decorator(f): def decorated_function(*args, **kwargs): return g(f(*args, **kwargs)) return decorated_function return decorator def h(x): math.sqrt(x) @compose_with(h) def g(x): 2 * x @compose_with(g) def f(x): x + 1 versus (for some reasonable definition of apply...) def compose(*fns): def composition(*args, **kwargs): return reduce((lambda computed, next_fn: next_fn.apply(computed)), fns, (args, kwargs)) return composition # define fns as above without decorator hogof = compose(f, g, h)
- francoisdevlin 16y agoTo expand on what I was thinking with #8, here's how I'd implement a decorator in Clojure (def my-decor (partial comp decor-bevior)) Done.
- leif 16y agoWell, what python calls a "decorator" is just a function that accepts a function and returns a function with roughly similar functionality. In python, the old way to decorate functions was def my_decorator(f): ... def my_function(...): ... my_function = my_decorator(my_function) and the new "@my_decorator" syntax is just sugar for this. Function composition is only one of many things you can do with decorators. You could implement a K-combinator with them if you wanted to: def kestrel(x): "decorates a function to evaluate that function, but then return x" def decorator(f): def g(*args, **kwargs): f(*args, **kwargs) return x return g return decorator @kestrel(4) def foo(x): y = x + 1 print y return y foo(5) # => 4, but prints 6
- metageek 16y ago9. INSERT MACRO RANT HERE Macros are the main reason I decided to create Adder, a Lisp-on-Python with minimal impedance mismatch. Unfortunately, the first macro-heavy program I wrote turned out to be really slow, because macros engage the compiler, which, of course, is in Python. When I first tried it, it took something like 50s at 2.4GHz, virtually all of which was the compiler. (The compiler runs at load time; obviously, saving the compiled code for the next run would help.) I got it down to...let me try it now...7s at 3GHz, but that's still too slow for a 200-line program. If anybody's interested, the code's on Github [1]. To see the macro-heavy example, look at samples/html.+, which is an HTML generator. The framework takes 169 lines; the sample page starts at line 171. To see the output, run: ./adder.py samples/html.+ [1] http://github.com/metageek/adder http://github.com/metageek/adder (Edit: it requires Python 3.x.)
- silentbicycle 16y ago> Unfortunately, the first macro-heavy program I wrote turned out to be really slow, because macros engage the compiler, which, of course, is in Python. The Python byte-compiler, specifically, appears to be fairly slow. I hadn't really thought much about this, but while contributing to a benchmark yesterday (http://news.ycombinator.com/item?id=1800396 http://news.ycombinator.com/item?id=1800396), it wound up staring me in the face. There's actually surprisingly little difference performance-wise in running Lua from source vs. precompiled (both pretty fast), whereas the difference between Python and pyc in my benchmark was wider than every other possible pair in the chart except python interpreted vs. "echo Hello World". (I didn't have any JVM languages, though.) I don't really do eval-based metaprogramming in Python, but do so on occasion in Lua. I thought I felt better about doing so because Lua is syntactically much simpler (and has scoping rules that make avoiding unexpected variable capture easy), but the Lua compiler itself also appears to be substantially faster than Python's. (It doesn't do much analysis, but still usually runs faster than Python.) And yes, it's not as good as straight-up Lisp macros, but Lua's reflection also covers a lot of low-hanging fruit that macros would otherwise handle. The biggest thing lacking in Lua compared to Lisp is an explicit compile-time phase for static metaprogramming. (Code generation is an inferior alternative.) Lisp macros win big in part because they can avoid the overhead of parsing, but parsing Lua is fairly cheap thanks to its small, LL(1) grammar (http://www.lua.org/manual/5.1/manual.html#8 http://www.lua.org/manual/5.1/manual.html#8).
- pjscott 16y agoIt's funny, but the thing I miss most from Common Lisp when I write in other languages is the LOOP macro. It's ugly, and non-lispy, but most loops I have to write can be expressed clearly and concisely using LOOP, and writing the equivalent code in another language is annoying. I'm tempted to create a LOOP clone for Clojure, then laugh villainously as I unleash it upon the world.
- leif 16y ago> I'm tempted to create a LOOP clone for Clojure, then laugh villainously as I unleash it upon the world. DOOOO IT
- sedachv 16y agoLoop, like structured editing (Paredit), is one of those Interlisp things that's very controversial and divisive. There's tons of really wild ideas in Interlisp that seemed to be the half-baked acid trip ideas of West Coast hippies at the time, that are just starting to become rediscovered in the past couple of years (pervasive undo -> reversible debugging, DWIM-like autosuggestions in more places), and even the implementation techniques used are still innovative (for example the error-trapping implementation of Conversational Lisp (http://docs.google.com/viewer?a=v&q=cache:4GnEnGS2XXkJ:citeseerx.ist.psu.edu/viewdoc/download%3Fdoi%3D10.1.1.99.5401%26rep%3Drep1%26type%3Dpdf+%22conversational+lisp%22&hl=en&gl=ca&pid=bl&srcid=ADGEEShXWxn-mRgD0X-rMQN8IFezuWx7CRduPKQjuZWX2Qo1-BneEpeKTwpl5mMBxygVHRFiPkx37Sq3sY-hZN-GusSJAlZAXqxpSwjgF4uK0sXwFAb_zoygkiNO9MinjQxudj8C0nF5&sig=AHIEtbQiXOK77aVM2PKV9gYI-ek1oG1q1A http://docs.google.com/viewer?a=v&q=cache:4GnEnGS2XXkJ:c...) is quite similar to how Geoff Wozniak approached auto-defining functions (http://exploring-lisp.blogspot.com/2008/01/auto-defining-functions.html) http://exploring-lisp.blogspot.com/2008/01/auto-defining-fun...)
- lispm 16y agoLOOP is not from Interlisp. It comes straight from Maclisp. 'LOOPS' from Interlisp is something entirely different: an object-oriented extension to Interlisp.
- 16y ago
- morphir 16y ago<cite>2. iPython was fun to use, helped out a lot, but it's not SLIME.</cite> what exactly were you thinking about?
- beza1e1 16y ago6. I would like to see more FP constructs natively available in Python. FP constructs such as? Map is there. Reduce is one import away. There is nice syntax for list comprehensions. What do you miss?
- masklinn 16y ago> significant white space Nit: significant indentation. Mostlanguageshavesignificantwhitespace, somemorethanothers (for instance, at least in 1.8, Ruby seems to have more whitespace issues than Python)
- mzl 16y agoThe fun alternative language example is of course Fortran, where at least early versions disregarded whitespace.