> There are other means of finding information than Google. Really.
This is really only a very minor point in my argument, so I dont want to put the focus on this. But really, no. Googling 'myprogramminglanguage conceptimtryingtofigureout' is my first, second and third line of defence. Yes, I could read the reference manual from top to bottom, and if I already knew about the existence of your article then im sure that would be a great help too. But the situation one finds oneself in is seeing two asterikses and not even being aware they are particular to function definitions/invocations. Im fluent in many different languages and well versed in CS concepts and jargon, but I had no idea what to search for when first trying to figure out the meaning of these symbols, and that does not happen often to me. -- http://mail.python.org/mailman/listinfo/python-list |
On Mon, Dec 12, 2011 at 10:53 AM, Eelco Hoogendoorn
<[hidden email]> wrote: > Googling 'myprogramminglanguage conceptimtryingtofigureout' is my first, > second and third line of defence. Yes, I could read the reference manual > from top to bottom, and if I already knew about the existence of your > article then im sure that would be a great help too. Python in particular has very poor internal search. I don't recommend searching the Python docs for anything that you can search for externally using Google, duckduckgo, etc, etc. ChrisA -- http://mail.python.org/mailman/listinfo/python-list |
In reply to this post by Eelco Hoogendoorn
On Mon, 12 Dec 2011 00:44:38 +0100, Eelco Hoogendoorn wrote:
>> No more so than any other form of punctuation. Plus and minus + - may >> be so common that just about everyone knows it, but how about | == @ % >> and even . (dot)? None of these things will be obvious to newbies who >> have never programmed before. Oh well. > >> Some things you just have to learn. > > > Yes, some things you just have to learn. Nonetheless, I strongly prefer > explicit logical operators over |, would much rather have 'equals' > instead of ==, which is stylistic in line with 'is' and explicitly > distinguishes between equality and identity comparisons. No more, or less, explicit than the difference between "==" and "is". > As for %; it is > entirely unclear to me why that obscure operation ever got its own > one-character symbol. Ill take 'mod', or even better, 'modulus' any day > of the week. Modulo is hardly an obscure operation. "What's the remainder...?" is a simple question that people learn about in primary school. And you can blame C for the use of % instead of mod or modulo. > The dot is clearly quantitatively in another realm here. 90% of typical > python code is attribute accesses. I can't imagine what sort of Python code you have seen that you consider 90% attribute access "typical". I've just run the Python tokenizer over my startup.py file, and I get these results: {'COMMENT': 24, 'DEDENT': 29, 'NL': 46, 'NAME': 256, "':'": 30, 'NEWLINE': 83, "'-'": 1, 'NUMBER': 1, "'['": 1, "','": 17, "')'": 37, "'('": 37, "'%'": 2, "'.'": 48, "'=='": 1, "'*'": 1, 'INDENT': 29, "']'": 1, "'='": 28, 'ENDMARKER': 1, 'STRING': 19} That gives attribute access being a little less than 7% of the source code. For the decimal module, the figure is a little less than 5%. > The dot is entirely unambigious and > cannot be mistaken for anything else. It reads like a book. The dot can be easily mistaken for a comma, or for a bit of grit on the monitor, especially at smaller type sizes, or for those with poor eyesight. [...] >> It is also misleading because args are not collected into a list, but >> into a tuple. > > In case you wanted a tuple youd write tuple(args), obviously. Exactly > that added flexibility is half of my case in favor. Why shouldnt it be a > list when I want it to? What sort of list? A built-in list, or whatever sort of object you get when you call the thing currently bound to the name "list"? If you can supply any function at all, what happens if I write this: def func(parg, dict(foo), list(bar)): ... How about this? def func(parg, myfunc(x)): ... What is x now? Should Python try to accumulate arguments by position, or by keyword, or try both and hope one will succeed? Which order should it try first? I believe that your proposal leads to an over-generalisation "call arbitrary functions when handling parameter lists". I don't believe you need this added complication. If you want to your var args as a list, call list(args) inside your function. >> Worse, it suggests that one should be able to generalise to something >> like this: > >> def func(parg, str(args), int(kwargs), my_func(more_args)): > >> which is incoherent. > > Sorry, but I dont get this point at all. Does ** suggests one should be > able to generalize to ***? The rules are the rules. You have missed that the generalization is not just to multiple "chunks" of arguments, but also to arbitrary functions. I thought that both ideas were equally incoherent, but ironically you suggest about that you should be able to call arbitrary functions: tuple, list, attrdict. What else? str? int? > The real questions, in my mind, are: > > 1) How useful is this added flexibility? Not insanely, but I can see it > making a lot of code significantly more clean. I don't. I see it making a small amount of code more verbose and less clean. > And: > > 2) How fundamental is collection packing/unpacking? One can easily argue > that it is indeed quite fundamental and therefore deserves its own terse > symbols, I feel. In Python, tuple unpacking and packing (actually applies to any collection, not just tuples) is *very* fundamental. That's why we can do things like this: a, b, c = my_list x, y = y, x > However, if more flexibility is indeed deemed > desirable, such terse syntax quickly gives way to a more verbose one. > Can you come up with some terse symbols that will be able to express all > of the below and dont make you wish you hadnt rather typed out the > names? > > head, tuple(tail) = iterable In Python 3, that is spelled: head, *tail = iterable tail = tuple(tail) > head, list(tail) = iterable head, *tail = iterable > head, str(tail) = somestring This is ambiguous, I'm not sure what exactly you expect to get as the string. It could arguable be any of: tail = ''.join(map(repr, tail)) tail = ''.join(map(str, tail)) tail = str(tail) or even head, tail = somestring[0], somestring[1:] > head, generator(tail) = mygenerator And this is most easily spelled: head, tail = next(mygenerator), mygenerator -- Steven -- http://mail.python.org/mailman/listinfo/python-list |
Steven D'Aprano wrote:
> Modulo is hardly an obscure operation. "What's the remainder...?" is a > simple question that people learn about in primary school. Well, sort of. The way I remember it, the remainder was just something that fell out as a side effect of division -- the annoying bit left over that you didn't know what to do with. We weren't taught to think of "finding the remainder" as a distinct operation that's useful in its own right. Once we were taught to do proper division with decimal points and everything, the concept of a remainder seemed to get discarded and was never mentioned again. A couple of years later we were briefly introduced to the concept of modulo arithmetic, but as far as I remember, the connection with division and remainders wasn't pointed out. Also, it was presented in a very abstract way, and I couldn't see any practical application for it at the time. (At that age, it hadn't occurred to me that some of the stuff we were being shown might be just pure mathematics for its own sake, and I was often thinking to myself, "Why am I being taught this?") It wasn't until much later when I got into programming that I began to see all the connections and applications. For people who don't become programmers, I suspect they never have much use for remainders in everyday life. Now, in a desperate attempt to stop rambling and get back on topic... > Eelco Hoogendoorn wrote: >>The dot is clearly quantitatively in another realm here. Also it has almost unchallenged supremacy as the attribute access operator in just about every language having some form of struct concept, going back to around Algol 68. Spelling of the mod operator is much more variable. > {'COMMENT': 24, 'DEDENT': 29, 'NL': 46, 'NAME': 256, "':'": 30, > 'NEWLINE': 83, "'-'": 1, 'NUMBER': 1, "'['": 1, "','": 17, "')'": 37, > "'('": 37, "'%'": 2, "'.'": 48, "'=='": 1, "'*'": 1, 'INDENT': 29, "']'": > 1, "'='": 28, 'ENDMARKER': 1, 'STRING': 19} > > That gives attribute access being a little less than 7% of the source > code. However, it's clearly the most commonly used *operator* by a large margin. > The dot can be easily mistaken for a comma, Not in my code, because I always put a space after a comma, and never after an attribute-access dot. (And if you can't tell whether there's a space there or not, you need a bigger font or better glasses. :-) Also, dots sit nicely under my little finger where they're easy to type. I like dots. Dots are a great goodness. -- Greg -- http://mail.python.org/mailman/listinfo/python-list |
In reply to this post by Eelco Hoogendoorn
For what it's worth, googling for "python asterisk"
gives this as the very first result: http://www.technovelty.org/code/python/asterisk.html which tells you exactly what you're probably wanting to know if you ask that. To check that this phenomemon isn't restricted to asterisks in particular, I also tried "python plus equals" and got http://stackoverflow.com/questions/2347265/what-does-plus-equals-do-in-python which is also a pretty good result. So the rule of thumb seems to be: if you're trying to google for punctuation, try spelling it out. -- Greg -- http://mail.python.org/mailman/listinfo/python-list |
In reply to this post by Eelco Hoogendoorn
On 12/11/2011 6:53 PM, Eelco Hoogendoorn wrote:
>> There are other means of finding information than Google. Really. > > This is really only a very minor point in my argument, so I dont want to > put the focus on this. On the contrary, it is a major point. You want us to change the language so you can program by Google. Sorry, aint't gonna happen. > Googling 'myprogramminglanguage conceptimtryingtofigureout' is my first, > second and third line of defence. Yes, I could read the reference manual > from top to bottom, and if I already knew about the existence of your > article then im sure that would be a great help too. You left out skimming the table of contents and using the index. On the Windows version of the docs, one can just type the entry wanted in the entry box on the Index tab and the lookup is done for you. Two chars to type for '**'. > But the situation > one finds oneself in is seeing two asterikses and not even being aware > they are particular to function definitions/invocations. If you find a symbol in a particular context, the entry for the context seems a reasonable place to start. -- Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list |
In reply to this post by Steven D'Aprano-11
> No more, or less, explicit than the difference between "==" and "is".
== may be taken to mean identity comparison; 'equals' can only mean one thing. Of course 'formally' these symbols are well defined, but so is brainf*ck > Modulo is hardly an obscure operation. "What's the remainder...?" is a > simple question that people learn about in primary school. So is 'how much wood would a woodchucker chuck if a woodchucker could chuck wood?'. But how often does that concept turn up in your code? > And you can blame C for the use of % instead of mod or modulo. I didnt know one of Python's design goals was backwards compatibility with C. > I can't imagine what sort of Python code you have seen that you consider > 90% attribute access "typical". I've just run the Python tokenizer over > my startup.py file, and I get these results: Yes, that was a hyperbole; but quite an often used construct, is it not? > If you can supply any function at all, what happens if I write this: You cannot; only constructors modelling a sequence or a dict, and only in that order. Is that rule clear enough? > I believe that your proposal leads to an over-generalisation "call > arbitrary functions when handling parameter lists". I hope the above clears that up. It is as much about calling functions as ** is about raising kwargs to the power of. > I don't believe you > need this added complication. If you want to your var args as a list, > call list(args) inside your function. We dont strictly 'need' any language construct. Real men use assembler, right? > > head, tuple(tail) = iterable > In Python 3, that is spelled: > head, *tail = iterable > tail = tuple(tail) Yes, I know. How is that not a lot more verbose and worse than what I have proposed in all possible ways? > head, tail = somestring[0], somestring[1:] Well yes, splendid; we can do that with lists too since the dawn of Python. What you are saying here in effect is that you think the head/tail syntax is superfluous; that youd rather see it eliminated than generalized. > head, tail = next(mygenerator), mygenerator Which again of course works, but is yet again of entirely different form than any of the above solutions, while conceptually doing the same thing. Certainly, there is room for improved elegance here? -- http://mail.python.org/mailman/listinfo/python-list |
In reply to this post by Gregory Ewing
On 12/12/2011 3:09 AM, Gregory Ewing wrote:
> people who don't become programmers, I suspect they never > have much use for remainders in everyday life. Huh? Funny you should say 'everyday'. It is now 10 o'clock. In 20 hours, it will be (10+20) % 12 == 6 o'clock. It is now day 1 of the week. In 9 days it will be day (1+9) % 7 == 3 of the week. Mental calculations are helped by the fact that (a+b) % c == a%c + b%c, so that would actually be 1+2==3. Timekeeping is mostly remaindering, slightly obscured by using 12 instead of 0. -- Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list |
Terry Reedy <[hidden email]> wrote:
> calculations are helped by the fact that (a+b) % c == a%c + b%c, so As long as we understand that == here does not mean "equal", only "congruent modulo c", e.g try a = 13, b = 12, c = 7. Nick -- http://mail.python.org/mailman/listinfo/python-list |
In reply to this post by Terry Reedy
On 12 December 2011 15:36, Terry Reedy <[hidden email]> wrote:
> Huh? Funny you should say 'everyday'. It is now 10 o'clock. In 20 hours, it > will be (10+20) % 12 == 6 o'clock. It is now day 1 of the week. In 9 days it > will be day (1+9) % 7 == 3 of the week. Mental calculations are helped by > the fact that (a+b) % c == a%c + b%c You mean (a + b) % c == (a%c + b%c) % c :) -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list |
In reply to this post by Nick Dokos
On Tue, Dec 13, 2011 at 2:55 AM, Nick Dokos <[hidden email]> wrote:
> Terry Reedy <[hidden email]> wrote: >> calculations are helped by the fact that (a+b) % c == a%c + b%c, so > > As long as we understand that == here does not mean "equal", only > "congruent modulo c", e.g try a = 13, b = 12, c = 7. This is the basis of the grade-school "casting out nines" method of checking arithmetic. Set c=9 and you can calculate N%c fairly readily (digit sum - I'm assuming here that the arithmetic is being done in decimal); the sum of the remainders should equal the remainder of the sum, but there's the inherent assumption that if the remainders sum to something greater than nine, you digit-sum it to get the true remainder. (Technically the sum of the digits of a base-10 number is not the same as that number mod 9, but if you accept that 0 == 9, it works fine.) ChrisA -- http://mail.python.org/mailman/listinfo/python-list |
In reply to this post by Arnaud Delobelle-3
On Tue, Dec 13, 2011 at 3:15 AM, Arnaud Delobelle <[hidden email]> wrote:
> > You mean (a + b) % c == (a%c + b%c) % c > > :) It's just integer wraparound. Modulo 9 is the same as "render this number in base 9 and take the last digit" (and printing a number in base 9 would normally be done with mod 9 division), and most people can wrap their heads around the way an odometer wraps around. ChrisA -- http://mail.python.org/mailman/listinfo/python-list |
In reply to this post by Chris Angelico
On Monday, December 12, 2011 12:44:27 PM Chris Angelico did opine:
> On Tue, Dec 13, 2011 at 2:55 AM, Nick Dokos <[hidden email]> wrote: > > Terry Reedy <[hidden email]> wrote: > >> calculations are helped by the fact that (a+b) % c == a%c + b%c, so > > > > As long as we understand that == here does not mean "equal", only > > "congruent modulo c", e.g try a = 13, b = 12, c = 7. > > This is the basis of the grade-school "casting out nines" method of > checking arithmetic. Set c=9 and you can calculate N%c fairly readily > (digit sum - I'm assuming here that the arithmetic is being done in > decimal); the sum of the remainders should equal the remainder of the > sum, but there's the inherent assumption that if the remainders sum to > something greater than nine, you digit-sum it to get the true > remainder. > > (Technically the sum of the digits of a base-10 number is not the same > as that number mod 9, but if you accept that 0 == 9, it works fine.) > > ChrisA And that is precisely the reason I have failed to understand why the 1-10 decimal system seems to have hung on for several hundred years when it is clearly broken. Cheers, Gene -- "There are four boxes to be used in defense of liberty: soap, ballot, jury, and ammo. Please use in that order." -Ed Howdershelt (Author) My web page: <http://coyoteden.dyndns-free.com:85/gene> Grub first, then ethics. -- Bertolt Brecht -- http://mail.python.org/mailman/listinfo/python-list |
gene heskett <[hidden email]> wrote:
> On Monday, December 12, 2011 12:44:27 PM Chris Angelico did opine: > > > On Tue, Dec 13, 2011 at 2:55 AM, Nick Dokos <[hidden email]> > wrote: > > > Terry Reedy <[hidden email]> wrote: > > >> calculations are helped by the fact that (a+b) % c == a%c + b%c, so > > > > > > As long as we understand that == here does not mean "equal", only > > > "congruent modulo c", e.g try a = 13, b = 12, c = 7. > > > > This is the basis of the grade-school "casting out nines" method of > > checking arithmetic. Set c=9 and you can calculate N%c fairly readily > > (digit sum - I'm assuming here that the arithmetic is being done in > > decimal); the sum of the remainders should equal the remainder of the > > sum, but there's the inherent assumption that if the remainders sum to > > something greater than nine, you digit-sum it to get the true > > remainder. > > > > (Technically the sum of the digits of a base-10 number is not the same > > as that number mod 9, but if you accept that 0 == 9, it works fine.) > > > > ChrisA > > And that is precisely the reason I have failed to understand why the 1-10 It's not clear from the above what you mean by "that is presicely the reason": what is "that"? > decimal system seems to have hung on for several hundred years when it is > clearly broken. > "broken" how? Thanks, Nick -- http://mail.python.org/mailman/listinfo/python-list |
In reply to this post by gene heskett-4
On 12/12/2011 12:46 PM, gene heskett wrote:
> On Monday, December 12, 2011 12:44:27 PM Chris Angelico did opine: > <snip> >> This is the basis of the grade-school "casting out nines" method of >> checking arithmetic. Set c=9 and you can calculate N%c fairly readily >> (digit sum - I'm assuming here that the arithmetic is being done in >> decimal); the sum of the remainders should equal the remainder of the >> sum, but there's the inherent assumption that if the remainders sum to >> something greater than nine, you digit-sum it to get the true >> remainder. >> >> (Technically the sum of the digits of a base-10 number is not the same >> as that number mod 9, but if you accept that 0 == 9, it works fine.) >> >> ChrisA > And that is precisely the reason I have failed to understand why the 1-10 > decimal system seems to have hung on for several hundred years when it is > clearly broken. > other number base will have similar modulo characteristics, except for base 2, where all numbers are congruent modulo 1, so it doesn't do much for checking values. For example, if you were using a number system of base 8, you could do "casting out sevens" by adding the digits together. -- DaveA -- http://mail.python.org/mailman/listinfo/python-list |
In reply to this post by Eelco Hoogendoorn
On Mon, Dec 12, 2011 at 5:21 AM, Eelco <[hidden email]> wrote:
> You cannot; only constructors modelling a sequence or a dict, and > only > in that order. Is that rule clear enough? The dict constructor can receive either a sequence or a mapping, so if I write this: def func(a, b, dict(c)): what will I get? Probably I would want the equivalent of: def func(a, b, **c): but you seem to be saying that I would actually get the equivalent of this: def func(a, b, *c): c = dict(c) Cheers, Ian -- http://mail.python.org/mailman/listinfo/python-list |
In reply to this post by Eelco Hoogendoorn
On Dec 12, 7:09 pm, Ian Kelly <[hidden email]> wrote:
> On Mon, Dec 12, 2011 at 5:21 AM, Eelco <[hidden email]> wrote: > > You cannot; only constructors modelling a sequence or a dict, and > > only > > in that order. Is that rule clear enough? > > The dict constructor can receive either a sequence or a mapping, so if > I write this: > > def func(a, b, dict(c)): > > what will I get? Probably I would want the equivalent of: > > def func(a, b, **c): > > but you seem to be saying that I would actually get the equivalent of this: > > def func(a, b, *c): > c = dict(c) > > Cheers, > Ian Im not sure if I was clear on that, but I dont care what the constructors accept; I meant to overload on the concept the underlying type models. Dicts model a mapping, lists/tuples model a sequence. MI deriving from both these models is illegal anyway, so one can unambigiously overload on that trait. The syntax only superficially resembles 'call the dict constructor with the object passed into kwargs'. What its supposed to mean is exactly the same as **kwargs, but with added flexibility. -- http://mail.python.org/mailman/listinfo/python-list |
On Mon, Dec 12, 2011 at 11:17 AM, Eelco <[hidden email]> wrote:
> Im not sure if I was clear on that, but I dont care what the > constructors accept; I meant to overload on the concept the underlying > type models. Dicts model a mapping, lists/tuples model a sequence. MI > deriving from both these models is illegal anyway, so one can > unambigiously overload on that trait. False. >>> from collections import * >>> class Foo(Sequence, Mapping): ... def __init__(self, items): ... self._items = items ... def __getitem__(self, item): ... return self._items[item] ... def __len__(self): ... return len(self._items) ... >>> foo1 = Foo(range(5, 10)) >>> foo2 = Foo({'one': 1, 'two': 2}) >>> foo1[3] 8 >>> foo2['one'] 1 Or are you saying that only classes specifically derived from list, tuple, or dict should be considered, and custom containers that are not derived from any of those but implement the correct protocols should be excluded? If so, that sounds less than ideal. Cheers, Ian -- http://mail.python.org/mailman/listinfo/python-list |
In reply to this post by Eelco Hoogendoorn
> False.
I stand corrected. > Or are you saying that only classes specifically derived from list, > tuple, or dict should be considered, and custom containers that are > not derived from any of those but implement the correct protocols > should be excluded? If so, that sounds less than ideal. That might be a desirable constraint from an implementational/ performance aspect anyway, but I agree, less than ideal. Either way, its not hard to add some detail to the semantics to allow all this. Even this function definition: def func(Foo(args), Foo(kwargs)) ...could even be defined unambigiously by overloading first on base type, and if that does not uniquely determine the args and kwargs, fall back on positionality, so that: def func(Foo(args), dict(kwargs)) def func(list(args), Foo(kwargs)) would be uniquely defined as well. -- http://mail.python.org/mailman/listinfo/python-list |
In reply to this post by Eelco Hoogendoorn
To get back on topic a little bit, lets get back to the syntax of all
this: I think we all agree that recycling the function call syntax is less than ideal, since while it works in special contexts like a function signature, its symmetric counterpart inside a function call already has the meaning of a function call. In general, we face the problem of specifying metadata about a variable, or a limited form of type constraint. What we want is similar to function annotations in python 3; in line with that, we could have more general variable annotations. With an important conceptual distinction; function annotations are meaningless to python, but the annotations I have in mind should modify semantics directly. However, its still conceptually close enough that we might want to use the colon syntax here too. To distinguish it from function annotations, we could use a double colon (double colon is an annotation with non-void semantics; quite a simple rule); or to maintain an historic link with the existing packing/unpacking syntax, we could look at an augmented form of the asteriks notation. For instance: def func(list*args, dict*kwargs) <- list-of-args, dict-of-kwargs def func(args::list, kwargs::dict) <- I like the readability of this one even better; args-list and kwargs-dict And: head, deque*tail = somedeque head, tail::deque = somedeque Or some variants thereof -- http://mail.python.org/mailman/listinfo/python-list |
Free forum by Nabble | Edit this page |