PEP 0448 – Additional Unpacking Generalizations
python.org
python.org
(defmacro pep448 [f & args]
(let [unpack? #(and (list? %) (= (first %) '$))]
`(apply ~f (concat ~@(map #(if (unpack? %) (second %) [%]) args)))))
which can be used like this: (pep448 + ($ [2 3]) 4 ($ [5 6 7]))
=> 27
A bit verbose, so you probably wouldn't do it this way in real life. Thankfully there are generally easier and more elegant ways to handle this kind of situation.a = b | c
makes perfect sense, vs:
a = b.copy()
a.update(c)
Personally I'd have gone for the practicality beats purity side of things here, but oh well.
I think there a design guideline for Python that says roughly if you can create an operator/function with a combination of 2 or 3 operators, then it probably is not worth adding. This keeps standard library relatively small and easy to memorize. Many other language keep adding various flavors of operators (and types, too) despite the fact you can easily build one from another.
Personally I find well-chosen names to help readability and may help avoid code duplication. There are 2 or 3 operator long things very much worth naming (see for example https://gist.github.com/piotrklibert/a0849f26523cad3d594e#fi...).
It's a style I call "modern literate," which tries to emulate "literate programming" without extra-language tools. Jeremy Ashkenas uses it in his works, most notably Underscore.js and Backbone.js: the code is simultaneously a manual and a tutorial. See: http://backbonejs.org/docs/backbone.html
> There are 2 or 3 operator long things very much worth naming
I don't understand your example. But I am talking about functions that are part of the libraries (especially standard ones). How you refactor your code is a different matter.
https://hg.python.org/cpython/file/3.5/Misc/NEWS
https://docs.python.org/3.5/whatsnew/3.5.html
Relevant bug tracker issue is http://bugs.python.org/issue2292
Mailing list discussions:
https://mail.python.org/pipermail/python-ideas/2013-July/thr...
https://mail.python.org/pipermail/python-ideas/2015-January/...
https://mail.python.org/pipermail/python-dev/2015-January/th...
https://mail.python.org/pipermail/python-dev/2015-February/t...
Do you mean 9 years ago?
-e-
But the real answer to your question is because I keep running into problems that have more elegant solutions in 3.x
(Not that I agree.)
I've long wanted to do
for server in (server1, server2, *other_servers):
Instead of
for server in [server1, server2] + other_servers
def combined(*dicts):
return {k: v
for dict_ in dicts
for k, v in dict_.items()}
dicts = [({'a': 'a', 'b': 'b'}, {'b': 'bb'}),]
assert [{'a': 'a', 'b': 'bb'}] == [combined(a, b) for a, b in dicts]What you mistake for readability is familiarity: after you read a word you need to associate a meaning with it. It takes longer to interpret the meaning of things you didn't see before while grabbing a meaning from a cache is nearly instantaneous. You understood this difference in comprehension speed as a readability difference.
My main point is that it makes no sense to talk about readability without first getting used to the grammar and vocabulary of a language. In this case, it's unfamiliar feature in an otherwise normal environment, but it gets worse. There are people who believe they can judge the readability of entirely alien (to them) languages and it hurts those languages reputation pretty badly. Lisps are the prime example of this.
def L(*vargs):
return vargs
tada. >>> stuff = ['c','d','e']
>>> L('a','b', *stuff)
('a', 'b', 'c', 'd', 'e')
Just like that. >>> L(*stuff, 'a', 'b')
SyntaxError: only named arguments may follow *expression
>>> L(*stuff, *stuff)
SyntaxError: invalid syntaxMore of these + performance, please, and I am happy with you, Python.