Python 2.4 Final Released 359
Eventh writes "The final release of Python 2.4 was just released. Python 2.4 is the result of almost 18 month's worth of work on top of Python 2.3. New features are, but not limited to, function decorators, generator expressions, a number of new module and more. Check out Andrew Kuchling's What's New In Python for a detailed view of some of the new features of Python 2.4. "
18 Months (Score:4, Informative)
* multi-line imports - when using imports in the form from foo import bar, baz, bing, bang, you can surround the imported names with brackets, and they can be split across lines. This is part of PEP 328.
* Farewell to OverflowWarning - as documented in PEP 237, Python no longer generates OverflowWarnings.
* function/method decorators - function and method decorators, first described in PEP 318, have been added to the language, using 'pie-decorator' syntax. Decorators are on the line before the 'def', and prefixed with an '@' sign. (PEP 318)
* Assigning to None - the compiler now treats assigning to None as a SyntaxError.
* Failed import cleanup - when a module import failed, versions of Python prior to 2.4a2 would leave a broken module in sys.modules - subsequent attempts to import the failing module would silently succeed, but use the broken module object. The import machinery now removes the failing module from sys.modules if the import fails.
* The -m command line option - python -m modulename will find a module in the standard library, and invoke it. For example, python -m pdb is equivalent to python -m
genexps (Score:5, Insightful)
From the AMK's excellent (as always) overview:
print sum(obj.count for obj in list_all_objects())
The important part is that no intermediate list is generated, because we are dealing with generators.
Generators in general kick so much ass it's not even funny.
Re:genexps (Score:2, Informative)
Yeah, generators do kick ass.
But it's important to remember that generator expressions are slower than list comprehensions. This is mainly because functions calls are expensive in Python, and when dealing with generators each iteration means one more function call.
Re:genexps (Score:3, Informative)
Yup. Like the PEP [python.org] says,
Re:genexps (Score:3, Interesting)
Re:genexps (Score:4, Informative)
Uh, you do realize that generators have nothing to do with anonymous functions, and that it's rather a simplified, understandable approach for providing coroutines? Generators are significantly more powerful than Ruby code blocks.
Re:genexps (Score:5, Insightful)
Consider the example you gave: In Ruby, you can accomplish the same thing by writing: where "objGenerator" is an object that mixes in the "Enumerable" module. An even better way (that really avoids building an intermediate list, even of integers) is: There is one thing that generators give you that blocks can't, that is very, very cool. With a generator, you can create programs with a pipeline architecture, where different steps of the pipeline all can be written as if they have the main loop.
Imagine you are writing a compiler. You could write (be easy on my syntax, I haven't written Python in a while) The beauty is that both your lexer and your parser can be written as if they have the main loop, and all they have to do is yield a token/expression when they find one. In reality, it's pipelined and you get the efficiency of not having to build up the entire list of tokens before you start parsing.
Re:genexps (Score:4, Insightful)
You could also add this to the "Enumerable" mixin: Now you can call "sum" on any object that implements "Enumerable", and the example becomes:
Re:18 Months (Score:5, Insightful)
Re:18 Months (Score:5, Funny)
My functions do each fit on one screen.
For any sufficiently large definition of screen.
function decorators (Score:4, Funny)
Finally I can make my functions so much prettier.
Re:function decorators (Score:2)
If I run into code that uses them, that's another story.
OK Trolls... (Score:3, Funny)
Re:OK Trolls... (Score:2, Insightful)
coding standards make good code, not a language. I can write bad python just as easially as I can write good perl.
Re:OK Trolls... (Score:2)
Just like a Wookie on Endor, it doesn't make sense.
Re:OK Trolls... (Score:5, Informative)
There is absolutely nothing that says you can't break things across lines. In most cases you don't even need a backslash to escape the linebreak. TRY the damn thing before criticizing it.
Re:OK Trolls... (Score:3, Interesting)
Uh, no, I don't... which is why I'm glad this is perfectly valid python syntax:
Re:OK Trolls... (Score:4, Interesting)
Someone else's script? Written in what, python? Well then I don't need to process anything. It is either valid python or not. If you're just talking about including some pre-formatted text into a python script, then just enclose it in a multi-line string (which in python are inclosed by """ (three double quotes in a row)).
I used to believe python's whitepsace-sensitive C syntax would really get on my nerves if I ever tried python, since I'm used to C and perl. Like many people, I wouldn't even give python a shot because of that whitespace issue. But one day I did because I needed to help a friend, and I actually found the language quite pleasant.
The whitepsace sensitivity didn't get in my way like I thought it would (which is to say it never got in my way, I didn't even notice it). Python's rules for whitespace are quite logical and intuitive and follow the way you're already used to indenting for readability in C or perl. When I started using python, I didn't even have to learn how the whitespace worked like I would have to learn any other syntax. The whitespace rules already worked the way I always programmed, so once I started python I had no trouble at all.
Re:OK Trolls... (Score:2)
The whitespace issue makes of course other things like copy&paste a whole lot harder too.
Overall I just wish they would introduce some kind of construct to get awa
Re:OK Trolls... (Score:2)
heh (Score:5, Funny)
print "I for one welcome our new %s overloads.!" % overloads.get_random()
Re:heh (Score:2)
department of redundancy dept. (Score:4, Funny)
generator expressions? (Score:3, Funny)
Re:aargh. (Score:2, Funny)
Can't say the same thing about Python.
On Decimal and floating point (Score:5, Interesting)
The importance of decimal arithmetic is not that it is more accurate than binary, but rather that it conforms more closely to what people expect from using decimal in daily life. These expectations are codified into various social rules such as accounting practices.
There's been some heated discussion of Python 2.4's Decimal, in this very regard, on the Lambda the Ultimate [lambda-the-ultimate.org] languages blog.
Heated Discussion? (Score:2)
No, the Decimal type isn't IEEE 754 standard. No, it doesn't solve, or intend to solve, all the world's numerical analysis problems. Yes, it is a good thing in a language intended to minimize the dissonance between user
Re:On Decimal and floating point (Score:2)
Re:On Decimal and floating point (Score:4, Funny)
Re:On Decimal and floating point (Score:2)
Incidentally, 60 = 2*2*3*5 and 360 = 2*2*2*3*3*5
Re:On Decimal and floating point (Score:5, Funny)
frozenset (Score:5, Interesting)
Re:frozenset (Score:2)
Where would you put that keyword?
s = frozen Set()
where frozen would do some kind of lookup in a table that has a non-mutable equivalent of every class?
That wouldn't make much sense. Providing a freeze() function might be more sensible, where it would always call obj.__freeze__ if applicable, telling the object to lose all the mutability...
Re:frozenset (Score:3, Informative)
python doesn't have modifiers for anything else, so it would require syntax changes. Whitespace after a python reserved word seperates it from its expression.
"frozen x = Set()" complexifies things because since day 1, an assignment returns 'None', and 'frozen None' is nonsense.
You could of course write it as a property:
x = Set()
x.become_frozen()
But it's better to consider 'frozenset' as a subclass of 'set' (or vice versa), since 'frozenset' very well fits the 'is a' paradigm, because a fr
Python annoyances (Score:2, Insightful)
Having said the above, there always seem to be 'issues'. Floating point numbers are one such issue. This release fixes that with 'Decimal'. The trouble is, you have to know about 'Decimal' before you can use it. This raises the difficulty of using Python.
I find that I writ
Re:Python annoyances (Score:2)
Having said that, I agree it takes some time to become efficient in Python. I wish/hope (ought to check again) that Python's potentially excellent built-in documentation string system becomes/is more accessible and useful. That'd help a lot with getting to know modules.
I've used 3 scripting languages over the times; I use bash for anythi
Re:Python annoyances (Score:2)
help(object)
will display docstrings in a relatively fancy way -- good for when you're figuring stuff out interactively.
Writing extensions... (Score:3, Interesting)
Re:Writing extensions... (Score:5, Informative)
Re:Writing extensions... (Score:4, Informative)
Dive into Python (Score:4, Interesting)
Supprised (Score:2)
Can one tell me why I should learn python and not any other programming language anyway?
From the little I have seen, python seems to be a command line language. Is it anywhere similar to Visual Basic, which I have come to see and experience through a GUI?
Use a toolkit (Score:3, Informative)
Re:Use a toolkit (Score:3, Informative)
Re:Supprised (Score:2)
Re:Supprised (Score:5, Insightful)
Well, some of the things I like about python:
1: tightly structured code.
2: less punctuation.
3: more readable syntax.
4: full OOP from the ground up (in contrast to perl where the OOP is bolted on with references).
5: short production cycle.
Many of these things can be found in other languages as well. So it largely comes down a matter of preference.
From the little I have seen, python seems to be a command line language. Is it anywhere similar to Visual Basic, which I have come to see and experience through a GUI?
Check out tkinter and wxPython.
Re:Supprised (Score:3, Informative)
Re:Supprised (Score:3, Insightful)
Sarcasm aside, it's not uncommon for me to work in four vastly different programming languages in a single day (usually java, ocaml, python, and C). That's not counting the ``lesser'' languages like sh, javascript, etc...
If I hear people talking about how a language or d
Re:Supprised (Score:5, Informative)
I expect this isn't the answer that true Python devotees would express, but here goes anyway: It's a very high-level, very dynamic, language that's reliably cross-platform.
"Very high-level" differentiates it from Java, which I see as more mid-level. It's also different than Perl 5, which is higher-level than Python in some ways, but convoluted and crusty in other ways (anything involving nested data structures, for example).
"Dynamic" means you can test code interactively, you don't a build process, you don't waste time enumerating things and creating redundant headers and so on.
"Reliably cross-platform" is the key. This is where Scheme and Lisp and Haskell fall down. Lisp has a standard definition, but the community is fractured by there not being a standard implementation. You can argue that diversity is good and all that, but it does tend to hurt overall. Python has a huge number of standard library modules as a result.
Is it just me? (Score:5, Interesting)
I used python in the 1.5 days. The syntax was incredibly clean. Nowadays the language has tremendous idiomatic power, any programming language researcher should be familiar with it.
But that power has brough alot of complexity. At the end of the day, languages are tools and the learning curve to understand (particularly others) python code seems to be increasing.
Re:Is it just me? (Score:2, Informative)
The "eye opener" for me was reading the Python cookbook. Almost every recipe listed 2-3 ways to do everything, most of them hard to understand and using Python "tricks". Many of them depended on new 2.x features. I realized that there are now two kinds of classes in Python for instance.
The Python community has also grown arrogant like the Perl community. If a newbie writes something that can be re-written with a list comprehension for instance, it's pretty much given that nobody will act
Re:Is it just me? (Score:5, Insightful)
List comprehensions are not "tricks," they are an extremely powerful language feature. Newbies should be taught how to use them, and translating their loop-based code into list comprehensions is probably the best way to do that.
Python can be written from either an imperative standpoint or a pseudo-functional one. Most of the highly skilled Python programmers code in the pseudo-functional style, because it is more efficient and (arguably) more elegant.
Sure, you can get into some pretty scary territory with various combinations of sum(), map(), reduce(), and list comprehensions but that's your choice. I admit that there should not be such a big performance gap between the different styles... This is due to not enough effort being spent on improving the VM.
Re:Is it just me? (Score:4, Insightful)
Since Python 2.x there is a move toward iterators and generators. Rather than seeing this as bloats I would say this Python is maturing to handle real world applications. If you are handling simple data and performance is not an issue, use regular lists. If you writing application to handle arbitrary large data set or performance is an issue, go for iterators and generators. List comprehension is a neat language construct but I don't see any need to rush rewriting anything.
Re:Is it just me? (Score:5, Informative)
To a degree, yes. Largely to the extent it has it is a result of backwards-compatibility; while the Python designers do not make the mistake of enshrining reverse compatibility above all else, they do try to avoid gratuitously compromising it.
As a result, as better ways to do things have emerged, sometime the old ways hang around and muss things up. However, for any given version there is always a "core" that you can stick to that is very close to "one best way to do it"... and despite what a first reading tells you, you really don't throw much of the language away.
For instance, while in modern Python you can say either or the latter is the "one right way to do it". Few, if any, new additions truly leave you with two equally good choices.
(One of Guido's examples is the "lambda" statement, but a lot of people, including me, rather like not needing to replace with but hey, that's life. (While that isn't code for any GUI toolkit in particular that is a pattern common to all of them.))
By and large, none of these things have affected the difficulty of learning Python from scratch and using its libraries. It has affected the difficulty of reading other people's code, but I find the alternative, "keeping the language stagnant indefinately", completely unacceptable, and frankly, reading code is hard anyhow. (I was writing code for others long before I was reading other's code.)
In fact, given as that is the alternative, "keeping the language stagnant indefinately", while I concede it is somewhat sad that we can't jump to an optimal language immediately so that nobody ever has to learn anything past their first impression (not sarcastic, that would be the ideal), that doesn't seem to be working for folks. You might try LISP, though, I gather that hasn't changed syntax, much. (Though I also gather mature programs in that language tend to start looking like their own languages themselves, so that just may move the pain...)
Re:Is it just me? (Score:4, Interesting)
How To Design Programs [htdp.org]
One semi-unique feature is that it asks you what your skill level is when you launch the environment, and tailors the feature-set accordingly.
Novices see a simple subset of the language, and experts get the full power inherent in a real-deal Lisp dialect.
Supporting software in 2.4 format? (Score:2, Interesting)
I expect some software will even die now - like McMillan Installer, as development stopped on 2.3, unless 2.4-devel has some excellent backwards compatibility with 2.3 libraries.
I'm sticking to 2.3.4 for a good while yet, don't have a use for decorators.....
Good Stuff, but not enough to make me learn it yet (Score:2, Insightful)
I've always liked Python, but I don't think this update is enough to make me learn it.
In one respect, it is exactly what I've been hoping for. No more sweeping changes or vast syntactic variances, but they have eliminated some usability problems and silly errors. It's a very mature language now, and seems to be behaving as such, this makes me happy
Still, though, they seem to be competing for a niche that Perl has a deathgrip on for me. I use Bash whenever I can, Perl when I can't or it would be ugly,
lazy question (Score:3, Interesting)
cobol (Score:3, Funny)
Actually, its useful. Every language should have it.
Re:cobol (Score:2)
CommonLisp for the 21st century?! (Score:2, Insightful)
There are two big differences. One is that CommonLisp made it a lot easier to treat programs as data and vice versa, and it had a built-in high-performance native compiler. On the other hand, Python integrates a lot better with Linux and UNIX, there are tons more libraries for it, and is easier for new users to learn.
Re:CommonLisp for the 21st century?! (Score:4, Interesting)
But seriously, Common Lisp is the Common Lisp for the 21st century. It's doing quite nicely; in the past couple of years folks have taken this "old" programming language and added excellent support for all kinds of current needs -- a Web application server (TBNL), a remarkable SQL interface (CL-SQL), general-purpose dataflow programming (Kenny Tilton's Cells), PDF typesetting and generation (CL-PDF, a rival to TeX!), OpenGL ....
(Peter Seibel's Practical Common Lisp [gigamonkeys.com] is highly recommended for the "modern" programmer interested in this "old" language. Practical examples include spam filtering, an MP3 database, and a Shoutcast server.)
Re:CommonLisp for the 21st century?! (Score:5, Informative)
Python is a lot like CommonLisp: dynamic typing, reflection, eval, lexical scoping, extensive iteration and looping constructs, strings-as-sequences, and on and on.
For once thing is the "big difference" you describe: you can't transparently process code as data. That means no MACROS, which is what makes Lisp so damn powerful.
Go back and read the original papers on hygienic macros: you don't need Lisp syntax or code-as-data in order to have a macro facility as powerful as Scheme's (and Scheme got by for many years without macros anyway). I wouldn't be surprised if Python at some point gets a hygienic macro facility. Furthermore, there is a separate data syntax for Python that takes source that looks very similar to Python code and represents it as a DOM tree.
How do you return an anonymous function from a function in Python?
In the obvious way: That part is actually more natural than doing the same in CommonLisp (Python, like Scheme, but unlike CommonLisp, does not have separate value and function slots on symbols).
How do you build a function at run time? It's not easy or obvious.
There are two things you could mean by that. The first is to build it from source or structure. You can do this: The second is to build complex functions using functions that take functions as arguments. You do that the same way you do in CommonLisp, since Python supports the same primitives: lexical closures, dynamic typing, and functions that take functions as arguments.
I think people see "lambda" and they somehow think that Python has something to do with Lisp.
I think Lisp zealots incorrectly think nothing that isn't exactly Lisp could even come close. Python, in fact, is very close to Lisp; the two big differences are syntax and lack of macros. Lack of macros can be addressed, and there are separate Python-like syntactic representations of data.
Re:Numerical programming needs an array type (Score:3, Informative)
Python "lists" are extensible 1D arrays; there is no extra indirection.
Python is working on arrays -- Numeric and Numarray -- but adoption seems slow in stuff like plot and graphics packages.
Numeric and Numarray are widely used by people who need them and they are great and mature packages. But I think the fact that they aren't used universally
Why the Decimal data type is needed (Score:3, Insightful)
>>> 1.1
1.1000000000000001
Thus, the Decimal data type was born.
From PEP 327: "The inaccuracy isn't always visible when you print the number because the FP-to-decimal-string conversion is provided by the C library, and most C libraries try to produce sensible output. Even if it's not displayed, however, the inaccuracy is still there and subsequent operations can magnify the error."
Re:Why the Decimal data type is needed (Score:3, Insightful)
Not a Python Programmer... (Score:5, Interesting)
Function Decorator Proposal/Specification [python.org]
Its nice to see a language evolve in favor of use without sacrificing readability and overall utility.
Before: After: Readable is of course in the eye of the beholder... and I am a C and Java programmer with a sizable fetish for D [digitalmars.com]. So while I don't find the syntax all that pleasing to me in terms of my own work, it certainly changes things for reading python code.
I was also stunned to learn how flexible decorators were in the previous version of python. It's refreshing to be see functions treated as objects... unless I'm mistaken about the concept.
However its a huge shame that the new decorator syntax isn't supported for classes in 2.4. Seems like that's going to become a wart on a rather consistent language syntax, IMO.
Re:Not a Python Programmer... (Score:3, Informative)
Another important part has been Python 2.2's new-style classes and descriptors [rcn.com]. Descriptors are basically objects with special methods (__get__, __set__, __delete__). When you access a class or instance attribute, instead of returning the descriptor, the a method of the descriptor is called. This is what allows clas
sigils sneaking in (Score:4, Insightful)
Welcome to the sigil club! Pandoras box is now open! '$' can't be too far behind
Re:sigils sneaking in (Score:4, Informative)
python - awesome (Score:5, Insightful)
All those funny symbols, casting back and forth in perl just getting in the way yet don't really say anything useful ... here is an example:
whether or not this is good code is not the point, I have to make it work, look at all that pointless markup, in python this same thing would look like this:
(leading . stands for a space )which version would you rather read?
or that uselessly verbose java where you have to write X number of lines before any action starts ...
Python is a simple, clean and powerful language where the real value comes tomorrow or next month, when you have to understand and modify what you wrote today. There are no objective measures of this quality you have to try it to believe it.
Just in time for Xmas! (Score:4, Funny)
cue grumbling about how Christmas is overcommericalized+etc
Re:FP! (Score:2, Funny)
Re:I *want* to be enthused, but... (Score:2, Insightful)
Re:I *want* to be enthused, but... (Score:5, Interesting)
Linus explicitly mentioned that he doesn't do anything "in the middle" - it's either kernel hacking or something trivial enough to do with bash. Just go ahead and learn Python - you will find that it's *easier* than bash, especially if your programs might have errors (which they do).
BTW, why would you want to get more proficient in C? Programmers are abandoning C in droves. It's just not programmer-time efficient to do things in C anymore. It's one thing if you are maintaining a project that was written in C originally, but for new projects, C is a non-starter.
Go read ESR's "The Art of Unix Programming", available online for free.
Re:I *want* to be enthused, but... (Score:5, Insightful)
I think one of the problems is too many people are still spreading the myth that it's essential to learn C before moving on to C++, which is totally false, C++ is a language in itself, and can be treated as such. Learning C (unless you intend to use it) is a waste of time, and I would go so far to say learning C first will make you less producive in C++, because it teaches concepts which are not applicable, or are actually bad habits when used in C++. At least that's my view on the subject.
That said, C still has its uses, but for many projects (like parent said) it's a "non-starter"
Re:I *want* to be enthused, but... (Score:2)
Re:I *want* to be enthused, but... (Score:3, Insightful)
IMHO - there are still uses for C, there are absolutely no uses for C++ nowadays. Moreover - there is no C++. I mean - I've been tracking (and sometimes using) C++ developments since the early days till recent and I can tell you - the amount of pileup that they produced in modern C++ compared even to early C++'s (not to say about more sane languages) is totally ridiculous. No - inventing a new language construct for bloody every particular problem does not make a good l
Re:I *want* to be enthused, but... (Score:2)
Maybe you shouldn't do it then: take a pointer to a string object as an argument, and modify it directly, then you don't have to return anything.
Re:I *want* to be enthused, but... (Score:2)
c = a + b;
That's how all the people do it and how C++ says you can. Do you do it any different way? (That's what I was referring to).
Re:I *want* to be enthused, but... (Score:3, Informative)
Take a look at the job market, good knowledge of C++ is still an invaluable skill.
Moreover take a look at libraries like boost [boost.org] or systems built on C++ like KDE. Well written C++ can be just as elegant as any language (it's always in the programmers hands, they can turn anything in to spaghetti). There's a reason why it's been so popular and many of its concepts are used
Re:I *want* to be enthused, but... (Score:2)
If you want to be a good programmer all-around you _have_ to know C. I suppose this statement will be true for another 20 years maybe.
Actually - C is kinda unique language in that it does what it was intended to almost perfectly. And then it does much more. Me, I have only these several micro-complains about it:
1) "->" operator is redundant. "." after pointers would've suffice and would be more elegant
Re:I *want* to be enthused, but... (Score:2)
Efficient use of programmer time is only one reason to select one language over another. I still code a lot in C on my own projects simply because I enjoy it. Yes, you heard right. I enjoy hunting down stupid off-by-one errors, iteration bugs, memory corruption, silently conflicting declarations, prototype errors, implicit casting errors, rounding
Re:I *want* to be enthused, but... (Score:3, Insightful)
That's a very good question. However, just because programming in C is difficult doesn't mean that it's the best language to write high-level languages in. C has many design flaws that people have gotten so used to, they assume there's no other way of doing things.
If you like programming in C because it's a challenge, then by all means do so. However, I would classify that hobby with people who prog
Re:I *want* to be enthused, but... (Score:3, Informative)
nice try.
C is the defacto for embedded systems. it's smaller and faster and there are libs available that make your app 1/10th the size of a regular C app.
ther are no embedded libs for C++ that are solidly tested and compata
Re:I *want* to be enthused, but... (Score:2)
Of course, this is why so many perl programs look like a complete mess, people do quick ports and don't learn how to properly use the language. Do the next guy a favor and do "man perlstyle" early on.
Re:I *want* to be enthused, but... (Score:3, Insightful)
Re:I *want* to be enthused, but... (Score:2)
Actually, a lot of language and systems designers have blinders on when it comes to the needs of large chunks of their potential user communities. In particular, numerical and scientific users get short-changed in this because most people
WTF? (Score:4, Insightful)
I'm very proficient with C, Python and Bash, and I can tell you for a fact: Bash and Python barely compete against each other.
Bash has nothing in the way of nice datatypes. Bash is very slow while Python can be nearly as fast as C (I've gotten it up to 80% when relying heavily on C libraries like regex). Bash can't do more than the most trivial things without helper programs, which while useful, takes forever because it has to keep spawning processes.
For a high level language, Bash has pathetic memory management. Pretty much the only way to get some things done is tempfiles, which is worse than malloc because they're not removed if you don't clean them up.
If you can't hold more than two languages in your head, go home and learn Java and C#. You're only going to get made fun of on slashdot.
Re:Pah (Score:2)
Re:Pah (Score:5, Funny)
Re:Pah (Score:2)
-Billy
Re:Pah (Score:2)
a = [7,8]
b,c = "5" * len(a), ("5 " * len(a))[:-1] c = c[:-1]
print b, c
Re:Pah (Score:3, Interesting)
Re:Python is a pathetic language. (Score:5, Informative)
You need to learn the language before complaining (Score:3, Interesting)
You need to learn a few Python idioms. Anyone who work with Python for a while should have no problem understanding this.
1. x and y or z is Python's version of ternary operator. If is similar to x ? y : z in C.
2. " ".join(list) is similar to string.join(" ", list). I won't go into detail here but your expresion collapse a string with multiple whitespaces into single space.
3. The lambda construct is a function factory. Thing of callback in C but Python allow for m
Re:Sets in Python (Score:5, Informative)
Re:Sets in Python (Score:2)
Re:Sets in Python (Score:2)
Simple algorithm:
1. Apply an arbitrary ordering on the elements of the set to produce a list
2. Join the list
What's so frickin' hard?
Re:Damn (Score:2, Insightful)