Re: Python Interview Questions
"Peter" wrote in message news:35e7a860-fd41-4018-82f6-aabc32610...@googlegroups.com... One of my favourite questions when interviewing - and it was 100% reliable :-) - "what are your hobbies?" If the answer included programming then they were hired, if not, then they went to the "B" list. In my experience, anybody who is really interested in programming will have it as a hobby (and is keen to learn even if they don't currently have the knowledge you require) - otherwise it is "just a job". Won't they be tempted to work on their pet project instead of what they're being paid for? There's also the risk of mixing up software created at home, with that done at work, with all the intellectual property issues that might arise. -- Bartc -- http://mail.python.org/mailman/listinfo/python-list
Re: Encapsulation, inheritance and polymorphism
"Lipska the Kat" wrote in message news:c76dnv778_sw4zvnnz2dnuvz8ukdn...@bt.com... On 18/07/12 01:46, Andrew Cooper wrote: if not (you are permitted to do this): return -EPERM if not (you've given me some valid data): return -EFAULT if not (you've given me some sensible data): return -EINVAL return actually_try_to_do_something_with(data) How would you program this sort of logic with a single return statement? This is very common logic for all routines for which there is even the remotest possibility that some data has come from an untrusted source. someType result = -EINVAL //or your most likely or 'safest' result if not (you are permitted to do this): result = -EPERM if not (you've given me some valid data): result = -EFAULT if not (you've given me some sensible data): result = -EINVAL else result = -EDSOMETHING return result } //cohesive, encapsulated, reusable and easy to read But, it works differently from the above. Perhaps replace some of those "if" statements with "elif". The "return" version is handy because it provides a quick escape mechanism without cluttering up the rest of code with extra variables. -- Bartc -- http://mail.python.org/mailman/listinfo/python-list
Re: Encapsulation, inheritance and polymorphism
"Erik Max Francis" wrote in message news:gskdnwoqpkoovztnnz2dnuvz5s2dn...@giganews.com... On 07/20/2012 01:11 AM, Steven D'Aprano wrote: On Thu, 19 Jul 2012 13:50:36 -0500, Tim Chase wrote: I'm reminded of Graham's Number, which is so large that there aren't enough molecules in the universe to write it out as a power tower a^b^c^d^..., or even in a tower of hyperpowers a^^b^^c^^d^^... It was the provable upper bound to a question to which experts in the field thought the most likely answer was ... six. (The bounds have since been reduced: the lower bound is now 13, and the upper bound is *much* smaller than Graham's Number but still inconceivably ginormous.) You don't even need to go that high. Even a run-of-the-mill googol (10^100) is far larger than the total number of elementary particles in the observable Universe. But you can write it down, even as a straightforward number, without any problem. Perhaps a googolplex (10^10^100 iirc) would be difficult to write it down in full, but I have just represented it as an exponent with little difficulty. These bigger numbers can't be written down, because there will never be enough material, even using multiple systems of exponents. (A few years ago the biggest number I'd heard of was Skewes' Number (something like 10^10^10^34), but even that is trivial to write using conventional exponents as I've just shown. Graham's Number is in a different class altogether.) -- Bartc -- http://mail.python.org/mailman/listinfo/python-list
Re: simplified Python parsing question
"Eric S. Johansson" wrote in message news:mailman.2752.1343700723.4697.python-l...@python.org... On 7/30/2012 9:54 PM, Steven D'Aprano wrote: It would please me greatly if you would be willing to try an experiment. live my life for a while. Sit in a chair and tell somebody what to type and where to move the mouse without moving your hands. keep your hands gripping the arms or the sides of the chair. The rule is you can't touch the keyboard you can't touch the mice, you can't point at the screen. I suspect you would have a hard time surviving half a day with these limitations. no embarrassment in that, most people wouldn't make it as far as a half a day. Just using speech? Probably more people than you might think have had such experiences: anyone who's done software support over the telephone for a start! And in that scenario, they are effectively 'blind' too. -- Bartc -- http://mail.python.org/mailman/listinfo/python-list
Re: f python?
"Kaz Kylheku" wrote in message news:20120408114313...@kylheku.com... Worse, the one byte Unix mistake being covered is, disappointingly, just a clueless rant against null-terminated strings. Null-terminated strings are infinitely better than the ridiculous encapsulation of length + data. For one thing, if s is a non-empty null terminated string then, cdr(s) is also a string representing the rest of that string without the first character, where cdr(s) is conveniently defined as s + 1. If strings are represented as (ptr,length), then a cdr(s) would have to return (ptr+1,length-1), or (nil,0) if s was one character. No big deal. (Note I saw your post in comp.lang.python; I don't about any implications of that for Lisp.) And if, instead, you want to represent all but the last character of the string, then it's just (ptr,length-1). (Some checking is needed around empty strings, but similar checks are needed around s+1.) In addition, if you want to represent the middle of a string, then it's also very easy: (ptr+a,b). Not only can compilers compress storage by recognizing that string literals are the suffixes of other string literals, but a lot of string manipulation code is simplified, because you can treat a pointer to interior of any string as a string. Yes, the string "bart" also contains "art", "rt" and "t". But with counted strintgs, it can also contain "bar", "ba", "b", etc There are a few advantages to counted strings too... length + data also raises the question: what type is the length field? One byte? Two bytes? Four? Depends on the architecture. But 4+4 for 32-bits, and 8+8 bytes for 64-bits, I would guess, for general flex strings of any length. There are other ways of encoding a length. (For example I use one short string type of maximum M characters, but the current length N is encoded into the string, without needing any extra count byte (by fiddling about with the last couple of bytes). If you're trying to store a short string in an 8-byte field in a struct, then this will let you use all 8 bytes; a zero-terminated one, only 7.) And then you have issues of byte order. Which also affects every single value of more than one byte. Null terminated C strings can be written straight to a binary file or network socket and be instantly understood on the other end. But they can't contains nulls! Null terminated strings have simplified all kids of text manipulation, lexical scanning, and data storage/communication code resulting in immeasurable savings over the years. They both have their uses. -- Bartc -- http://mail.python.org/mailman/listinfo/python-list
Re: f python?
"Shmuel (Seymour J.)Metz" wrote in message news:4f8410ff$2$fuzhry+tra$mr2...@news.patriot.net... In <20120409111329@kylheku.com>, on 04/09/2012 at 06:55 PM, Kaz Kylheku said: If we scan for a null terminator which is not there, we have a buffer overrun. You're only thinking of scanning an existing string; think of constructing a string. The null only indicates the current length, not the amount allocated. If a length field in front of string data is incorrect, we also have a buffer overrrun. The languages that I'm aware of that use a string length field also use a length field for the allocated storage. More precisely, they require that attempts to store beyond the allocated length be detected. I would have thought trying to *read* beyond the current length would be an error. Writing beyond the current length, and perhaps beyond the current allocation might be OK if the string is allowed grow, otherwise that's also an error. In any case, there is no real need for an allocated length to be passed around with the string, if you are only going to be reading it, or only modifying the existing characters. And depending on the memory management arrangements, such a length need not be stored at all. -- Bartc -- http://mail.python.org/mailman/listinfo/python-list
Re: Newbie, homework help, please.
"someone" wrote in message news:32945367.2045.1335029313436.JavaMail.geo-discussion-forums@ynjn4... 6) Display the SHI data read from the file in the interpreter with a border around the SHI data (include a buffer of 1 line/space between the border and SHI data). An example might look like: *** * * * First Name and Last * * ENGR 109-X * * Fall 2999 * * Format Example * * * *** I'm not a Python programmer, but I'll have a go at the text formatting bit: text=["First Name and Last","ENGR 109-X","Fall 2999","Format Example"] maxwidth=0 for s in text: if len(s)>maxwidth: maxwidth=len(s) vertinchlines=6# assume 6 lines/inch hozinchchars=10# assume 10 chars/inch hozmargin=" "*hozinchchars newtext=[] for i in range(vertinchlines): newtext.append("") newtext.append(hozmargin+"*"*(maxwidth+4)+hozmargin) newtext.append(hozmargin+"* "+" "*maxwidth+" *"+hozmargin) for s in text: newtext.append(hozmargin+"* "+s+" "*(maxwidth-len(s))+" *"+hozmargin) newtext.append(hozmargin+"* "+" "*maxwidth+" *"+hozmargin) newtext.append(hozmargin+"*"*(maxwidth+4)+hozmargin) for i in range(vertinchlines): newtext.append("") for s in newtext: print (s) -- Bartc -- http://mail.python.org/mailman/listinfo/python-list
Re: Newbie, homework help, please.
"someone" wrote in message news:4068590.2196.1335038608255.JavaMail.geo-discussion-forums@ynjn4... textTuple = border(SHI) for lines in textTuple: print (lines) Thanks your Bart for trying, I don't understand how it works or if you tried to place my script in python to see if it would work, unfortunately, I tried 10 different ways plus yours, and I don't see the connection. Unless you were trying to help me see the way and I did not, sorry, but thanks for trying. The characters did show me a little more. Did you run my code fragment on it's own to see if it did the job? The code can be packaged into a function border() just like you already have: def border(text): maxwidth=0 for s in text: if len(s)>maxwidth: maxwidth=len(s) vertinchlines=6# assume 6 lines/inch hozinchchars=10# assume 10 chars/inch hozmargin=" "*hozinchchars newtext=[] for i in range(vertinchlines): newtext.append("") newtext.append(hozmargin+"*"*(maxwidth+4)+hozmargin) newtext.append(hozmargin+"* "+" "*maxwidth+" *"+hozmargin) for s in text: newtext.append(hozmargin+"* "+s+" "*(maxwidth-len(s))+" *"+hozmargin) newtext.append(hozmargin+"* "+" "*maxwidth+" *"+hozmargin) newtext.append(hozmargin+"*"*(maxwidth+4)+hozmargin) for i in range(vertinchlines): newtext.append("") return newtext And can be tested like this (obviously you will need to obtain SHI from the input file): SHI=["First Name and Last","ENGR 109-X","Fall 2999","Format Example"] textTuple = border(SHI) for lines in textTuple: print (lines) The text handling is clunky (I had to learn the Python as I went along), but with these things you just want to get something working first, then you can tweak. -- Bartc -- http://mail.python.org/mailman/listinfo/python-list
Re: Newbie, homework help, please.
"someone" wrote in message news:9071485.2215.1335040139144.JavaMail.geo-discussion-forums@yniw15... Thanks Bart for trying, it helped me out a little more by showing me a little more than I knew, but I tried and I am not sure if it does fit my example due to it was too many stars in between the lines, and not match up, but if you see any more help, that would be great, or see something I am doing wrong, or figure something out, let me know, have a great day, again, thanks Here's the example you posted: *** * * * First Name and Last * * ENGR 109-X * * Fall 2999 * * Format Example * * * *** And here's the output from both bits of code I posted, which has 'one inch' of white space all around; both examples must be viewed with a fixed-pitch font (or in 'code' mode): *** * * * First Name and Last * * ENGR 109-X * * Fall 2999 * * Format Example * * * *** Please post the output you're getting that has too many asterisks. -- Bartc -- http://mail.python.org/mailman/listinfo/python-list
Re: Newbie, homework help, please.
"someone" wrote in message news:9533449.630.1335042672358.JavaMail.geo-discussion-forums@ynmf4... On Saturday, April 21, 2012 3:44:49 PM UTC-5, BartC wrote: Hi, Bart: Thank you, your post is working now, maybe, I did something wrong, unfortunately, you are right, my setup for getting the file to pull up correctly now is an issue, At first, I got a Vertical line with it working, then I tried to tinker with it, and it fratched, lol def border(text): maxwidth=0 for s in text: if len(s)>maxwidth: maxwidth=len(s) vertinchlines=6# assume 6 lines/inch hozinchchars=10# assume 10 chars/inch hozmargin=" "*hozinchchars newtext=[] for i in range(vertinchlines): newtext.append("") newtext.append(hozmargin+"*"*(maxwidth+4)+hozmargin) newtext.append(hozmargin+"* "+" "*maxwidth+" *"+hozmargin) for s in text: newtext.append(hozmargin+"* "+s+" "*(maxwidth-len(s))+" *"+hozmargin) newtext.append(hozmargin+"* "+" "*maxwidth+" *"+hozmargin) newtext.append(hozmargin+"*"*(maxwidth+4)+hozmargin) for i in range(vertinchlines): newtext.append("") return newtext x=textfile;indat=open(x,'r');SHI=indat.read() textTuple = border(SHI) for lines in textTuple: print ("%s\n" %textTuple) The issue is trying to get the SHI to work right, but omg, this is the closes I have gotten, you are awsome, thank you very much, i guess i will just keep messing with it till i get it I had to use this code to make this work right from a file (in additon to the border() function): textfile="kkk4" # (don't use this; this was my test input) x=textfile;indat=open(x,'r'); SHI=indat.readlines() indat.close() for i in range(len(SHI)):# remove trailing '\n' from each line s=SHI[i] SHI[i]=(s[0:len(s)-1]) textTuple = border(SHI) for lines in textTuple: print (lines) Your indat.read() seemed to read all the lines as one long string. I used indat.readlines() instead. However each line has a newline char '\n' at the end. I put in a loop to get rid of that (I'm sure there's a one-line fix to do that, but as I said don't know Python). The input file I used had to have this format: First Name and Last ENGR 109-X Fall 2999 Format Example -- Bartc -- http://mail.python.org/mailman/listinfo/python-list
Re: auto increment
"Chris Rebert" wrote in message news:mailman.596.1299215244.1189.python-l...@python.org... On Thu, Mar 3, 2011 at 9:05 PM, Dan Stromberg wrote: On Thu, Mar 3, 2011 at 8:48 PM, Chris Rebert wrote: On Thu, Mar 3, 2011 at 8:41 PM, monkeys paw wrote: > Does python have an analogy to c/perl incrementer? > > e.g. > > i = 0 > i++ i += 1 If you're doing this for a list index, use enumerate() instead. There's been discussion of adding i++ to python, but it was felt that the small number of saved keystrokes didn't justify the resulting bugs. I agree. Out of curiosity, what resulting bugs? Probably things like i=(++i)+(--i), although more of being indeterminate than a bug. That assumes that ++i was intended for use in an expression, rather than just be a statement. -- Bartc -- http://mail.python.org/mailman/listinfo/python-list
Re: having both dynamic and static variables
"Steven D'Aprano" wrote in message news:4d6f26a5$0$30003$c3e8da3$54964...@news.astraweb.com... On Wed, 02 Mar 2011 19:45:16 -0800, Yingjie Lan wrote: Hi everyone, Variables in Python are resolved dynamically at runtime, which comes at a performance cost. However, a lot of times we don't need that feature. Variables can be determined at compile time, which should boost up speed. [...] This is a very promising approach taken by a number of projects. Cython and Pyrex are compilers that take Python-like code with static type declarations and use it to produce compiled C code. I got the impression the OP was talking about simply pinning down certain variables, so that a runtime name lookup (if that's in fact what Python does) was not necessary. Declaring the *type* of such variables is a different matter I think (and probably is not considered 'pythonic'; certainly it's a crude, if effective, way of getting extra performance). -- Bartc -- http://mail.python.org/mailman/listinfo/python-list
Re: having both dynamic and static variables
"Steven D'Aprano" wrote in message news:4d743f70$0$29984$c3e8da3$54964...@news.astraweb.com... On Sun, 06 Mar 2011 12:59:55 -0800, Westley Martínez wrote: I'm confused. Can someone tell me if we're talking about constant as in 'fixed in memory' or as in 'you can't reassign' or both? Python already has fixed in memory constants. They are immutable objects like strings, ints, floats, etc. Once you create a string "spam", you cannot modify it. This has been true about Python forever. What Python doesn't have is constant *names*. Once you bind an object to a name, like this: s = "spam" you can't modify the *object*, but you can rebind the name: s = "Nobody expects the Spanish Inquisition!" and now your code that expects s to be "spam" will fail. So the only new feature under discussion is a way to bind-once names, which many people call constants. Another example: pi=3.141592654 print ("pi is:",pi) pi=42 print ("pi is now:",pi) which is clearly undesirable. Many languages just don't 'get' constants; C is one (the closest it comes is '#define' and 'enum', while what it calls 'const' is really 'read-only variable'), and perhaps Python is another. But then, the dividing line between constants and 'variables' can get confused when the values involved are complex (strings and such), so might be understandable up to a point. -- bartc -- http://mail.python.org/mailman/listinfo/python-list
Re: Python CPU
"Brad" wrote in message news:01bd055b-631d-45f0-90a7-229da4a9a...@t19g2000prd.googlegroups.com... Hi All, I've heard of Java CPUs. Has anyone implemented a Python CPU in VHDL or Verilog? For what purpose, improved performance? In that case, there's still plenty of scope for that on conventional CPUs. The Java VM is fairly low level (I would guess, not being too familiar with it), while the Python VM seems much higher level and awkward to implement directly in hardware. I don't think it's impossible, but the benefits probably would not match those of improving, say, Cpython on conventional hardware. And if a Python CPU couldn't also run non-Python code efficiently, then on a typical workload with mixed languages, it could be much slower! However, wasn't there a Python version that used JVM? Perhaps that might run on a Java CPU, and it would be interesting to see how well it works. -- Bartc -- http://mail.python.org/mailman/listinfo/python-list
Re: Fibonacci series recursion error
"Steven D'Aprano" wrote in message news:4dbbb7b6$0$29991$c3e8da3$54964...@news.astraweb.com... On Sat, 30 Apr 2011 08:32:55 +0200, Peter Otten wrote: harrismh777 wrote: Ian Kelly wrote: since the fact is that if the function were properly coded, the call stack for fib(20) would never be more than 20 entries deep at any one time. Not so much... and much more ! ... because each recursion level 'return' calls fib() twice, and each of those calls fib() twice, and you get the point... I don't understand what you are trying to say -- but it's wrong ;) I don't know what M Harris thinks he is trying to say either, but the *naive* Fibonacci recursive algorithm is particularly badly performing and should be avoided. It's ironic that of the two classic algorithms used for teaching beginner programmers about recursion, neither is useful in practice. Yes, it generates lots of calls. About 22000 for fib(20), and 330 million for fib(40). That's why it's popular for benchmarks that measure performance of function calls. Using an iterative algorithm wouldn't work quite so well... -- Bartc -- http://mail.python.org/mailman/listinfo/python-list
Re: += and =+
On 13/09/2017 14:25, Andrej Viktorovich wrote: Hello, I have done mistake while trying to increment int i=1 i=+ this left i unchangeable and I got no error. But what =+ means at all? Did you mean i=+1 ? This means i is set to the value +1. Usually just written 1. Try: i=88 i=+1 and see if i now changes. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Old Man Yells At Cloud
On 17/09/2017 02:09, Steve D'Aprano wrote: On Sun, 17 Sep 2017 04:00 am, Stefan Ram wrote: Steve D'Aprano writes: "Hi, I've been programming in Python for what seems like days now, and here's all the things that you guys are doing wrong. I never ever have written a line of Python 2. I started with Python 3.6.0. Yet a very frequent mistake of mine is the imission of parentheses after »print«. That's remarkable. Do you also forget the parentheses around `len`, and `iter`, and `math.sin()`? If not, what's so special about print? It was thought of as a statement or command, not a function where you you give it one value and it returns another. print() is used for its side-effects; what relevant value does it return? print can also be used for debugging, when it might be written, deleted and added again hundreds of times. So writing all those brackets becomes irksome. 'print' needs to be easy to write. Javascript (at least the Rhino interpreter, if not others) includes a print function. It too requires parentheses: js> print 21 js: "", line 5: missing ; before statement js: print 21 js: ...^ js> print(21) Javascript I believe uses C-like syntax. C syntax is also fond of unnecessary punctuation, and its 'printf' requires a format string full of format codes. Even more of a nuisance. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Old Man Yells At Cloud
On 17/09/2017 15:42, Steve D'Aprano wrote: On Sun, 17 Sep 2017 11:51 pm, Tim Golden wrote: Print-as-a-function removed one small simplicity Presumably you've never wanted to print to something other than std.out. Actually, no. (stderror is either a Unix-ism or C-ism, or some combination). The syntax in Python 2 is horrid: print >>sys.stderr, args But I have wanted to print to a file. I wasn't aware of Py2 syntax for it, but that's not so different to what I normally use which is "@" in place of "<<". And the @, which used to be #, I think came from '#' in Basic or somewhere. I understand from your example below that in Py3, the file is specified somewhere in a list of keyword parameters. But since the print destination is quite important, it benefits from being stated up-front rather than buried somewhere near the end of all the main print operands. Presumably you've never wanted to print using a separator other than space. You simply can't do it at all in Python 2. Presumably you've never wanted to print and suppress the newline at the end of the line. With the languages I normally use, newline isn't automatically written in the first place! (I'd write either print or println.) However controlling the separator between items has been and still is a nuisance (if not using a formatting string, but this is about being able to write quick, throwaway prints). Py3's 'sep' parameter is usable, mainly by requesting no separator and adding them manually as required. So if (a,b,c,d,e) have the values ("(",10,20,30,")") and you wanted output of '(10 20 30)' I guess you would write: print (a,b," ",c," ",d,e, sep="") (The scheme I currently use is to always add a space unless suppressed with ',,', so the same requirement is written as: println a,,b,c,d,,e But they're /both/ ugly!) Presumably you've never wanted to pass print to something as a function. It can't be done in Python 2: something.register(callback=print) # SyntaxError And again, no. It has happened, and this was not in Python, that I wanted to print to a string (appending to one), or to the current location in a window or image. Then, you need a clear way specifying such a destination. Presumably you've never wanted to control when the output buffer is flushed. That's another thing you can't do in Python 2. Once more, no. I suppose it would be necessary to call a separate function, which is handier in not cluttering up the main print. Presumably you've never wanted to monkey-patch an existing function that used print by shadowing the built-in. You can't do that in Python 2, since print isn't a regular name, it can't be mocked or shadowed or replaced. Sorry, no. I've wanted to do all those things, and more. I love the new print function. For the cost of one extra character, the closing bracket, it gives you much, much more than the old print statement ever did. print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False) OK, in that case why not have both? Of course they would need to be given different names to make things easier. Then there wouldn't be any argument. No more cryptic and ugly syntax for printing to a file. Setting the argument separator is easy. Instead of an obscure and easy to miss trick to suppress the end of line, you use an obvious and self-explanatory keyword argument. movedata(a, b, action='copy', depth='shallow') Self-explanatory keyword arguments, tick; as simple as just writing: a = b probably not! -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Old Man Yells At Cloud
On 18/09/2017 04:23, Steve D'Aprano wrote: On Mon, 18 Sep 2017 11:11 am, Rick Johnson wrote: Speaking in _keystrokes_, and that's what really matters here, a print function is always three more keystrokes than a print statement. Keystrokes only matter if you are hunt'n'peck typing and need to pause between holding down the shift key and pressing the 9 key. Otherwise typing ( is little different than typing 9, its pretty much all the same regardless of what character you type. For an even half-arsed typist like myself, hitting the shift and 9 keys happens almost simultaneously. Technically it might involve two fingers but its effectively a single movement. If you micro-analyse this, not all keystrokes are equivalent. They use different fingers, different hands, the movements are different. The fact that some characters need two simultaneous keypresses is not so important. I don't hunt&peck but my typing accuracy is very poor. Shifted keys are harder (in having poorer success outcomes) because two keys are involved, the keys are somewhat outside the Qwerty zone so need a longer reach, and some synchronisation is needed (the shift must be pressed before the '('). It's not as bad as it sounds but just means that unnecessary shifted punctuation is more of a PITA than if it wasn't necessary. It's a lot worse doing this in C however; compare: print a with: printf ("%d\n",a); 8 extra punctuation characters, of which half are shifted (on my keyboard). /And/ you have to select a suitable format code. Suddenly, having to type: print (a) doesn't seem so bad. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Old Man Yells At Cloud
On 18/09/2017 15:04, Gregory Ewing wrote: Dennis Lee Bieber wrote: Pascal provides print()/println() [okay, not /statements/ but /procedures/] Actually write/writeln, and although they used parens like procedures, they had special syntax for output formatting that wasn't available to user-defined procedures, so they were at least as special as the py2 print, maybe more so. They HAD to be special, because that language was statically typed. You couldn't define a user-code procedure or function that took all possible types. That doesn't apply in Python, but it is still useful for print to be a little special. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Old Man Yells At Cloud
On 19/09/2017 11:46, Larry Martell wrote: On Mon, Sep 18, 2017 at 11:23 PM, Dan Sommers wrote: How relevant is the "people use calculators to do arithmetic" argument today? Okay, so I'm old and cynical, but I know [young] people who don't (can't?) calculate a gratuity without an app or a web page. I use a calculator all the time - not for calculating a tip though. Sometimes I use bc (when I can't find my calculator in the morass of my desk). True story - the other day I was in a store and my total was $10.12. I pulled out a $20, and the cashier (probably age 23 or so) immediately entered $20 as the amount tendered. Then I said "Let me see if I have the $0.12." I did not, but I had $0.15 so I handed her $20.15. She literally froze in place with a classic deer in the headlights stare. I said "$10.03" She said "What?" I said "$10.03 is my change." She said "What?" I said "Just give me $10." She did not reply, opened the drawer below her register, rummaged around and came out with one of those giant key calculators, and with a look of dogged determination, did the calculation, looked at me and said proudly "$10.03 is your change." My bill in a store came to £3.20 (GBP3.20), so I handed over £10.20. I was given back £16.90 in change! It turned out the cashier had entered £20.10 as the amount tendered. It was sorted out in the end. Sometimes its easier not to be bother making the figures come out better. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Old Man Yells At Cloud
On 19/09/2017 17:30, Steve D'Aprano wrote: On Tue, 19 Sep 2017 05:56 am, Roel Schroeven wrote: I do prefer Python 3's print-as-a-function because "special cases aren't special enough to break the rules", but I feel there's a case to be made for Python 2's print-as-a-statement because "(although) practicality beats purity" sometimes. Nobody has successfully made the argument that print was *better* as a statement, or given any convincing reason why print *should* be a statement. (For example, del needs to be a statement, not a function, because it needs to operate on *names* not the objects bound to the names.) All they have managed to successfully argue is that they're used to print without parens and can't unlearn the habit. The one advantage of print statement is that you save a single character when typing it. Be still my beating heart. Compared to that, the disadvantages: - it makes print a special thing that can't be treated as a first-class value, it can't be passed to functions or used as a callback or bound to a name; - because it is special, beginners have to unlearn the practice of using parens for calling functions, and stop writing print(x); - it suffers a silent failure if you inadvertently parenthesise multiple arguments: `print(x, y)` is *not* the same as `print x, y`; - it has bizarre syntax that nobody would find normal if it wasn't for long-experience; I mean, really, you end the argument list with a comma to suppress printing newlines? who thought that was a good idea? - it is difficult to control the print statement, since you can't pass keyword arguments; it's one size fits all; - which is why we ended up with that awful `print >>file, args` hack; - it can't be mocked, shadowed, monkey-patched or replaced for testing; - and you can't even write help(print) in the interactive interpreter because its a syntax error. Can't you get around all those with things like sys.stdout.write? If so, what was the point of having a discrete print statement/function at all? -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Old Man Yells At Cloud
On 19/09/2017 17:26, Larry Martell wrote: On Tue, Sep 19, 2017 at 10:30 AM, D'Arcy Cain wrote: On 09/19/2017 06:46 AM, Larry Martell wrote: True story - the other day I was in a store and my total was $10.12. I One time I was at a cash with three or four items which were taxable. The cashier rung each one up and hit the total button. She turned to me and said something like "$23.42 please." She was surprised to see that I was already standing there with $23.42 in my hand. "How did you do that" she asked. She must have thought it was a magic trick. I was just in a clothing store this weekend and there was a rack of clothes that was 50%. The sales clerk said everything on that rack was an additional 25% off, so it's 75% off the original price. I asked is it 75% off the original price or 25% off the 50% of the price. Said it's the same thing. I said no it's not. She insisted it was. I said no, let's take a simple example. If it was $100 and it was 75% off it would be $25. But if it's 50% off and then 25% off that it will be $37.50. She looked totally dumbfounded. Most people (in the general population, doubtless not in this group) seem to be confused about things like that. Your house has gone down in value by 30% this year; it will need to increase by 43% to be back where it was last year, not 30%. Value-Added-Tax in the UK increased from 17.5% to 20%, everyone was talking about a 2.5% increase in prices. The increase would actually be just over 2.1% (a £100 ex-VAT price increases from £117.50 to £120.00). Etc. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: [Tutor] beginning to code
On 20/09/2017 02:31, Bill wrote: Rick Johnson wrote: I think for most languages an intuitive syntax is not important -- C is such a language, Lisp is such a language, Perl is such a language, and there are many more -- but for Python, intuitiveness is very important. I guess it depends on what you mean by "important" ("important to the compiler", is a legitimate concern, for instance). From an intuition perspective, C++ allowing you to separate the interface of a class from it's implementation, I would say that C++ has it all over Python from the point of view of "intuitiveness". It's much easier to tell what's going on, at a glance, in a C++ program. You're being serious, aren't you? -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: [Tutor] beginning to code
On 22/09/2017 10:23, Marko Rauhamaa wrote: Bill : I figure that, internally, an address, a pointer, is being passed by value to implement pass by reference. Why do you say "they are right" above? Are you saying it's not pass by reference? "Pass by reference" could be "pass by reference to object" (Python, Java, JavaScript, Lisp) or "pass by reference to memory slot" (available to Pascal and C++). Memory slots (or lvalues, as they are known in C) are not first class objects in Python, which makes "pass by reference to memory slot" a bit tricky in Python. Python *could* add memory slots to its sanctioned collection of object types, and it *could* add special syntax to express a memory slot reference and dereference ("&" and "*" in C). However, Python doesn't need any language changes to implement memory slots. A memory slot could be defined as any object that implements "get()" and "set(value)" methods: I didn't understand your examples. Can Python be used to write, say, a swap() function that works with any argument types (not just classes or lists)? Example: def swap(&a,&b):# made up syntax a, b = b, a x=10 y="Z" swap(x,y) print (x,y) # "Z" and "10" If not, then it doesn't have reference passing as it is normally understood. A simpler example: def set(&a,value): a = value set(x,100) Here the type of x is irrelevant anyway. It doesn't even need to be initialised to anything first (that might violate something in Python, I don't know what). -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: [Tutor] beginning to code
On 22/09/2017 12:47, Chris Angelico wrote: On Fri, Sep 22, 2017 at 9:24 PM, Marko Rauhamaa wrote: Yes, following my recipe: def swap(ref_a, ref_b): a, b = ref_a.get(), ref_b.get() ref_a.set(b) ref_b.set(a) x = 10 y = "Z" swap(slot_ref(locals(), "x"), slot_ref(locals(), "y")) print(x, y) # "Z" and 10 Sure, let me just put that into a function. CPython 3.7, although I'm pretty sure most CPython versions will do the same, as will several of the other Pythons. (Side point: Your slot_ref function is rather bizarre. It's a closure AND a class, just in case one of them isn't sufficient. The following code is copied and pasted from two of your posts and is unchanged other than making try_swapping into a function.) def slot_ref(dict_or_array, key_or_index): ...class SlotRef: ...def get(self): return dict_or_array[key_or_index] ...def set(self, value): dict_or_array[key_or_index] = value ...return SlotRef() ... def swap(ref_a, ref_b): ...a, b = ref_a.get(), ref_b.get() ...ref_a.set(b) ...ref_b.set(a) ... def try_swapping(): ...x = 10 ...y = "Z" ...swap(slot_ref(locals(), "x"), slot_ref(locals(), "y")) ...print("x, y =", x, y) ... try_swapping() x, y = 10 Z Strange... doesn't seem to work. Are you saying that Python is pass-by-reference outside of a function and pass-by-value inside? Because that'd be just insane. Or maybe what you have here isn't a real reference at all. It also looks too complicated to be really useful. And I'm not sure it would work (when it does work), with more complex terms. For simple given: A = [10,20,30] B = ["X","Y","Z"] and wanting to swap A[0] and B[2]. Although these being list elements, they /could/ be exchanged via a function: def swapelems(a,i,b,j): a[i],b[j]=b[j],a[i] swapelems(A,0,B,2) Just not using a general-purpose swap function. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: [Tutor] beginning to code
On 22/09/2017 13:34, Steve D'Aprano wrote: On Fri, 22 Sep 2017 09:24 pm, Marko Rauhamaa wrote: Yes, following my recipe: def swap(ref_a, ref_b): a, b = ref_a.get(), ref_b.get() ref_a.set(b) ref_b.set(a) x = 10 y = "Z" swap(slot_ref(locals(), "x"), slot_ref(locals(), "y")) print(x, y) # "Z" and 10 No, you failed to follow Bart's instructions and answered a different question. You have to pass x and y, not strings 'x' and 'y'. The swap procedure needs to accept any variable, given as ordinary bare names swap(x, y), not written as strings, or by hard-coding x and y as the variables to swap, or by using a string and passing it to exec, or any other loophole. And being able to pass any lvalue expression, not just simple variable names. Such as a[i] or x.y, provided the term is mutable. (To make it work would require a new reference type. And extra versions of the byte-codes or whatever is used to evaluate terms such as: a, a[i], x.y that evaluate a reference rather than the value. So LOADFASTREF as well as LOADFAST) -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Call by binding [was Re: [Tutor] beginning to code]
On 24/09/2017 15:49, Steve D'Aprano wrote: On Mon, 25 Sep 2017 12:35 am, Stefan Ram wrote: WRT to assertions about Python, I try to base them on the "The Python Language Reference, Release 3.6.0" (PRL). So, WRT to parameter passing, I would use this part of the PRL: »The following constructs bind names: formal parameters to functions,« PRL 4.2.1 . Therefore, what Python does, I'd call »call by binding«. I am not aware of "call by binding" being a well-known or recognised term. Did you make it up? Also, the problem is that *any* form of function call binds *something* to the function parameters. If we consider the Pascal declaration: procedure proc(x: integer; var y: integer); and then we call it: var a, b: integer; begin a := 1; b := 2; proc(a, b); end. then 1 is bound to x and 2 is bound to y. They happen to exist in different scopes (x is local to proc, the *name* y is local to proc, but the variable is bound to y is global) but that's not important. The point I am making is that we could describe just about any and all languages with functions "call by binding", whether they are call by value like C, call by reference like Fortran, call by need like Haskell, or call by sharing like Python. Then 'binding' is either ill-defined or used wrongly. Imagine that each name (a,b,x,y) is a little box. In Pascal, the boxes for a and b contain 1 and 2 respectively. For x and y, they contain pointers (dereferenced behind the scenes). Fortran is similar (or Fortran IV was; I don't know modern ones). C works the same way: every variable has a box, and that box directly contains a value. In Python, those boxes don't contain anything, except one end of a piece of string. The other end is attached to an object. When you pass a variable to a function like this: def fn(X): A=1 fn(A) Then X gets set up with a string which has the same object at the other end as A. (And the object might have a reference count to reflect that extra string.) This is why you can't change A in the caller as there is no way to get from X's box to A's box. And the strings to the object are one-way. In the case of fn(A+2), a new object is created (with value '3', or an existing '3' might be used), a new string is attached to it, and the other is attached to X. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Beginners and experts (Batchelder blog post)
On 28/09/2017 03:33, Stefan Ram wrote: Larry Hudson writes: Hopefully NOT like this person... Since I teach nights at a local community college a programmer who couldn't program It is not clear what »this person« refers to: Do you hope one is not like that teacher who publicly is shaming one of his students, though without actually giving the name of the student. Or do you hope one is not like that student who did not turn in the assignments? The fact that programmers can't program is known since the invention of the "FizzBuzz" programmer test. But in the case of the student, one actually can't know for sure whether he only had problems with the /upgrade/ of his education, but still can program in his everyday job. So, what was the question? Quoted from earlier in the same thread: |The question is, what should a person "know" when hiring out |as a programmer? What is 'know" and what should be "known"? |Specifically with Python. Some areas of knowledge follow, a programmer should not be ignorant in all of them: I can probably manage the following, even if I hate some of it or some might be advanced: - writing FizzBuzz - writing GUI software [My own] (Writing a GUI system or using one? I've done both and try and avoid GUI completely if possible.) - writing software to analyze text files - writing software to generate images from data - writing software to analyze images - how to program operating systems via system calls - algorithms and datastructures - numerical mathematics - how to write a recursive descent parser - maths (how to transform to polar coordinates or what the use of a fourier transformation is) And I have little interest in most of this lot (my eyes glaze over just reading some of these): > - writing GUI software [Other people's] > - writing software to analyze data bases > - writing user interfaces for data bases > - how to use operating systems > - how to administer a computer > - how to use the command languages of operating systems > - how to use an editor well (e.g., vim or emacs) > - how to use UN*X tools (grep, uniq, sed, ...) > - regular expressions > - a source management tool (like git) > - design patterns > - design by contract > - OOA/OOD > - the most important libraries for Python (standard and other) > - data base design / normalization > - style (e.g. "Clean Code" by Robert Martin, pep 8, ...) > - refactors > - software engineering > - being able to read and write EBNF > - software-project managemet (e.g. Agile, "Scrum") > - computer science (complexity, NP, grammars, ...) > - test (e.g., unit test), TDD > - programming interviews (there are many books about this topic!) > - Using a real Newsreader (not Google Groups) > - common algorithms/heuristics for global optimization > - common types of statistical analyses and neural networks It seems the first group is more pure coding (and fun, a lot of it), and the second is the usual lot of tools and technologies that programmers seems to have to know about these days (and not so much fun). -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Beginners and experts (Batchelder blog post)
On 28/09/2017 12:31, Steve D'Aprano wrote: On Thu, 28 Sep 2017 09:12 pm, bartc wrote: And I have little interest in most of this lot (my eyes glaze over just reading some of these): > - how to use operating systems You've never used a system call? Written to a file? Moved the mouse? Wasn't that more this option: - how to program operating systems via system calls Which was in my first group. Using an OS, I just do the minimum necessary and don't get involved in much else. (In my first phase as a programmer, there were personnel whose job it was to do that. In the next phase, with microprocessors, there /was/ no operating system! Bliss. That phase didn't last long, but fortunately those OSes (MSDOS and the like) didn't do much so didn't get in the way either.) > - how to use an editor well (e.g., vim or emacs) You have no interest in using your editor well? I use my own editor as much as possible. That doesn't have any elaborate features that it is necessary to 'learn'. > - style (e.g. "Clean Code" by Robert Martin, pep 8, ...) Until now, I thought that people who wrote crappy code did so because they didn't know any better. This is the first time I've seen somebody state publicly that they have no interest in writing clean code. I meant I have no interest in reading books about it or someone else's opinion. I have my own ideas of what is clean code and what isn't. > - test (e.g., unit test), TDD You don't test your code? I assume this meant formal methods of testing. I suppose that makes it a lot easier to program. Just mash down on the keyboard with both hands, and say that the code is done and working correctly, and move on to the next project. *wink* Actually I used to like using random methods (Monte Carlo) to solve problems. That doesn't scale well however, at some point you have to properly think through a solution. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: I'd like to use "semantic indentation"
On 30/09/2017 19:12, Stefan Ram wrote: I would like to write source code similar to: country( 'USA' ) state( 'Alabama' ) town( 'Abbeville' ) town( 'Addison' ) state( 'Arizona' ) town( 'Apache Junction' ) town( 'Avondale ) town( 'Benson' ) using "semantic indentation". It seems I can't do this with Python. Is there any workaround? def country(x): print("C:",x) def state(x): print("S:",x) def town(x): print("T:",x) def fn(*a): pass fn( country( 'USA' ), state( 'Alabama' ), town( 'Abbeville' ), town( 'Addison' ), state( 'Arizona' ), town( 'Apache Junction' ), town( 'Avondale' ), town( 'Benson' ) ) This pretends they are arguments to a dummy function. But it probably won't work with anything that isn't also an expression. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: on a very slow function
On 02/10/2017 08:41, Peter Otten wrote: Daniel Bastos wrote: def make_sequence_non_recursive(N, x0 = 2, c = -1): "What's wrong with this function? It's very slow." last = x0 def sequence(): nonlocal last next = last last = last**2 + c return next % N return sequence x.bit_length() 12534884 So at this point it alreay would take 1.5 MB to store the number in binary. The actual format requires even a bit more memory: import sys sys.getsizeof(x) 1671344 So for every operation you have to touch a lot of memory -- and that takes time. If it recalculates 'last' once for each of those couple of dozen printed lines, that I doubt accessing a few MB of memory is the issue. More doing such a big calculation. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: on a very slow function
On 02/10/2017 14:54, Peter Otten wrote: bartc wrote: On 02/10/2017 08:41, Peter Otten wrote: Daniel Bastos wrote: def make_sequence_non_recursive(N, x0 = 2, c = -1): "What's wrong with this function? It's very slow." last = x0 def sequence(): nonlocal last next = last last = last**2 + c return next % N return sequence x.bit_length() 12534884 So at this point it alreay would take 1.5 MB to store the number in binary. The actual format requires even a bit more memory: import sys sys.getsizeof(x) 1671344 So for every operation you have to touch a lot of memory -- and that takes time. If it recalculates 'last' once for each of those couple of dozen printed lines, that I doubt accessing a few MB of memory is the issue. More doing such a big calculation. You are probably right that the calculation requires a significant amount of the total time here, but it's not just "a few MB". If you look at last = last**2 + c the required memory doubles on every iteration. You will soon run into the problem even under the (overly optimistic) assumption that the calculation requires time proportional to memory. On my machine, the iterations whizzed up the screen until I noticed it pausing on the 21st iteration, when the memory size of last was 0.5MB. When I started last as "A", and multiplied by 2 at each step, it started to pause at the 27th iteration when the size of last was 268MB. I would estimate then another 9 steps of the original (30th iteration) before memory usage has the same effect. Although it would probably already have ground to a halt long before then. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: newb question about @property
On 03/10/2017 15:39, Ian Kelly wrote: On Tue, Oct 3, 2017 at 4:41 AM, Steve D'Aprano wrote: On Tue, 3 Oct 2017 06:51 am, Bill wrote: Can you inspire me with a good decorator problem (standard homework exercise-level will be fine)? Here is a nice even dozen problems for you. Please ask for clarification if any are unclear. (1) Write a decorator which simply prints a descriptive message and the name of the decorated function once, when the function is first decorated. E.g. if you write: @decorate def spam(x): return x + 1 # for example print(spam(1)) print(spam(2)) Python should print: Decorating function spam. 2 3 Note: "spam" must not be hard-coded, it must be taken from the function being decorated. (Hint: all functions have their name available as func.__name__.) (2) Modify the decorator from (1) so that calling the wrapped function also print a descriptive message such as "Calling function spam". The expected output will be: Decorating function spam. Calling function spam. 2 Calling function spam. 3 (3) Write a decorator that checks that the decorated function's first argument is a non-empty string, raising an appropriate exception if it is not, and lets through any other arguments unchanged. (4) Same as above, except the first argument is automatically stripped of leading and trailing whitespace and forced to uppercase. (5) Write a decorator which injects the argument 10 into the list of arguments received by the wrapped function. E.g. if you write: @inject def add(a, b): return a + b @inject def sub(a, b): return a - b print(add(5), sub(5)) Python should print "15 5". (And *not* "15 -5".) (6) [ADVANCED] Modify the decorator in (5) so that it takes an argument telling it what value to inject into the list of arguments: @inject(99) def sub(a, b): return a - b print(sub(5)) will now print "94". (7) Write a decorator which checks the decorated function's two arguments are given smallest first, swapping them around if needed. (8) Write a decorator which prints the name of the wrapped function, its arguments, and the time, each time the wrapped function is called. (9) [ADVANCED] Modify the decorator from (8) to take an argument specifying the path to a file, and use the logging module to log the details to that file instead of printing them. (10) Write a decorator which adds an "cache" attribute initialised to an empty dictionary to the decorated function. (11) Write a decorator which wraps a class (not function!), and adds a "help" method to the class which prints a message as shown below. For example: @addhelp class Spam: pass @addhelp class Eggs: pass x = Spam() x.help() y = Eggs() y.help() will print: See http://example.com/Spam See http://example.com/Eggs (Hint: classes also have a __name__ attribute.) (12) [ADVANCED] Write a decorator which wraps a class, and applies the decorator from (10) above to each non-dunder¹ method in the class. That is, after: @addcaches class MyClass: def foo(self): pass def bar(self): pass print(MyClass.foo.cache, MyClass.bar.cache) should print "{} {}". ¹ Remember that dunder methods are those that start with two leading and trailing underscores: "Double UNDERscore" methods. [Sorry can't see Steve's original post.] Does all this advanced stuff (which I don't understand and which doesn't look very appealing either; hopefully I will never come across such code) still count as programming? It seems to me the equivalent of an advanced driving course teaching you how to customise your car rather than involving any actual driving. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: newb question about @property
On 04/10/2017 06:32, Steve D'Aprano wrote: On Wed, 4 Oct 2017 02:00 am, bartc wrote: Does all this advanced stuff (which I don't understand and which doesn't look very appealing either; hopefully I will never come across such code) still count as programming? I could not have hoped to see a more perfect example of the Blub effect in action if I had invented it myself. As long as our hypothetical Blub programmer is looking down the power continuum, he knows he's looking down. Languages less powerful than Blub are obviously less powerful, because they're missing some feature he's used to. But when our hypothetical Blub programmer looks in the other direction, up the power continuum, he doesn't realize he's looking up. What he sees are merely weird languages. He probably considers them about equivalent in power to Blub, but with all this other hairy stuff thrown in as well. Blub is good enough for him, because he thinks in Blub. http://www.paulgraham.com/avg.html I've seen that example brought up before. It still doesn't cut any ice. You might as well be condescending of someone who finds Joyce or Proust unreadable, and prefers McBain, Simenon or Chandler. (Sorry, can't think of any modern pulp novelists). It is just being elitist. I have a preference for keeping things simple and avoiding unnecessary complexity. But with programming languages many do have a penchant for the latter. As an example, a recent discussion on comp.lang.c was about implementing named constants. I proposed one very simple way of doing it, other people were talking about using #define, enum, const, static const, or importing constexpr and special rules for 'const' from C++. All unsatisfactory and each having their own problems. For that matter, I don't think Python has such a feature either. So that you write for example: const C = 123345 and then whenever C appears within the code, it's implemented as: LOAD_CONST (123345) I'm pretty sure that there are very complicated ways of achieving something similar, maybe with all your decorators, or using PyMacro or whatever. But not doing it straightforwardly. [Python's design makes a simple implementation harder.] Anyway, what I'm saying is that languages sometimes neglect the basics in favour of all this other stuff. You don't think that adding a cache for an expensive function is programming? If you had ten expensive functions, and you wanted to add a cache to each of them, would you write out ten separate caches (probably copying and pasting the code each time)? Or would you write a function that builds a cache and adds it to the expensive function *once*, then call it ten times, once for each function being wrapped? I'm trying to think of a real example where I've had to add a cache to to a function, whatever that even means (memoisation?). Is it looking to see if a certain combination of parameters has been used before and retrieving the return value that resulted on that occasion without having to redo the calculation? In my sort of coding that would need be done on a per-function basis because there would be other considerations. It does still sound like adding a turbo-charger to your engine, rather than actually going anywhere. That at least might be useful, but it's still not driving. But if the ultimate purpose is more speed, then piling on yet more code and more layers may be counter-productive! That you think that this is not programming is an indictment off your programming skills. These sorts of functional programming techniques go back to the 1950s, Lisp is literally the second oldest high-level language ever (only Fortran is older). You may or may not have been a hotshot in your little corner of the programming world, but there's an entire world out there. What other languages apart from Python have equivalent features to decorators and, what's the other one, descriptors? Apart from Lisp. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 04/10/2017 11:42, Stefan Ram wrote: Robin Becker writes: Given the prevalence of the loop and a half idea in python I wonder why we don't have a "do" or "loop" statement to start loops without a test. VBA has quite an orthogonal way to build loop control: pre-checked positive: Do While ... ... Loop post-checked positive: Do ... Loop While ... pre-checked negative: Do Until ... ... Loop post-checked negative Do ... Loop Until ... "endless": Do ... Loop None of them appear to be loop-and-a-halves. (Note that your reverse-indentation style is confusing! Imagine that Python was written like this: for i in R: print (i) ) Anyway I think what is needed in Python for a proper loop-and-a-half is this: while: s1 s2 do cond: s3 s4 s1, s2, s3, s4 are executed in sequence while cond is true. When cond is false, only s1, s2 are executed in that iteration, and the loop terminates. (A few syntactical details to be worked out such as whether while, do and else line up or not.) This is equivalent I think to the current: while 1: s1 s2 if cond: s3 s4 else: break But this would be a less satisfactory, ad-hoc approach. For example, there can be several such if-blocks within the same loop. They could be nested. There might not be any, so can't at a glance distinguish an endless loop from a loop-and-a-half. My proposed while-do has a less chaotic structure. It wouldn't preclude 'break' from still being used, but there would be less need. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 04/10/2017 11:57, Rhodri James wrote: On 04/10/17 10:01, Robin Becker wrote: Given the prevalence of the loop and a half idea in python I wonder why we don't have a "do" or "loop" statement to start loops without a test. See PEP 315. Guido's rejection note is here: https://mail.python.org/pipermail/python-ideas/2013-June/021610.html Oh, OK, similar to what I proposed earlier. That it was rejected is not a surprise. Programming languages seem to hate special forms for basic constructs such as looping, even though they can express more directly exactly what the coder intended. But this is what it says about it: "Please reject the PEP. More variations along these lines won't make the language more elegant or easier to learn. They'd just save a few hasty folks some typing while making others who have to read/maintain their code wonder what it means." Exactly the same could be said of pretty much any of the advanced features that /have/ been added. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 04/10/2017 14:02, Robin Becker wrote: On 04/10/2017 11:57, Rhodri James wrote: On 04/10/17 10:01, Robin Becker wrote: Given the prevalence of the loop and a half idea in python I wonder why we don't have a "do" or "loop" statement to start loops without a test. See PEP 315. Guido's rejection note is here: https://mail.python.org/pipermail/python-ideas/2013-June/021610.html seems fair enough; I suppose the cost is negligible or perhaps there's peephole optimization for this common case. Read the thread. Not having a dedicated feature means I counted at least half a dozen different ideas for implementing what the OP really wanted to do, which was expressed using C-like syntax. None of which were as obvious. And that C-like one worked because it could use an assignment within a while-condition. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: newb question about @property
On 04/10/2017 14:41, Ian Kelly wrote: On Wed, Oct 4, 2017 at 5:07 AM, bartc wrote: For that matter, I don't think Python has such a feature either. So that you write for example: const C = 123345 and then whenever C appears within the code, it's implemented as: LOAD_CONST (123345) Python has the simplest named constants of all: C = 12345 As long as you don't subsequently change it, it's a constant. And it's very simple because it works just like any other variable. Yes, but you don't want it to work like other variables! In other languages, a known compile-time constant is essential in certain contexts, but even in Python there are advantages to such a feature, for example in more opportunities for optimisation. Even if it's just so it can use LOAD_CONST instead of LOAD_GLOBAL (as such constants often are global). The problems with doing this in current CPython are first, that all such identifiers are dynamic: you can assign anything to them at any time. Also that some may be inside imported files, which the byte-code compiler will not know about until its too late. (There are ways around those but it would be an impossible sell when most people are not convinced that lightweight named constants are useful.) I'm trying to think of a real example where I've had to add a cache to to a function, whatever that even means (memoisation?). You've never used a dynamic programming algorithm? I had to look up what it means, but I still didn't see any practical examples. Probably I've done such coding, but I didn't give it a fancy name, and more likely just considered it data caching. > Descriptors are a bit unique to Python, I'll grant, but mostly they're > just used in the form of properties. Here's a list of languages that > support properties: > https://en.wikipedia.org/wiki/Property_(programming)#Example_syntax "A property, in some object-oriented programming languages, is a special sort of class member, intermediate in functionality between a field (or data member) and a method." But Python has some problems just in using fields. If you wanted say a data type with two fields called x and y, then AFAIK you just create any suitable class, but you don't need to specifically declare those two fields: class any(): pass p=any() p.x=10 p.y=20 But you also do this: p.z=30 and it magically acquires a third field! Or you want to modify p.x, but accidentally type: p.c=40 No error. Some would perceive all this as an advantage, but it means you can't just declare a lightweight struct or record 'Point' with exactly two fields x and y. You have to use other solutions ('namedtuples' or whatever, which probably are immutable so that don't work the same way). This is another example of neglecting the basics, but going for more advanced, perhaps more sexy features instead. Result? You can't just look at my 'any' class and see what fields it uses. You can't even just look at the static source code. You have to run the program to find out. And it might be different each time. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 04/10/2017 14:44, john polo wrote: In Python Programming Fundamentals 2nd ed., the author, Kent D. Lee, brings up loop and a half in ch. 3, Repetitive Tasks (p. 82). He wrote: "Whether you are writing code in Python or some other language, this Reading Records From a File pattern comes up over and over again. It is sometimes called the loop and a half problem. The idea is that you must attempt to read a line from the file before you know whether you are at the end of file or not. This can also be done if a boolean variable is introduced to help with the while loop. This boolean variable is the condition that gets you out of the while loop and the first time through it must be set to get your code to execute the while loop at least one." while not eof(f): # read next bit of the file But you need an eof(f) function that tells you if you are at the end of the file. Some people might be concerned that the status could change between checking for eof, and doing a subsequent read (but I've never had such problems). This is suitable for reading perhaps binary files in uneven chunks, which are dependent on the last bit read, so iterating over the file by line or by byte won't work. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: newb question about @property
On 04/10/2017 17:02, Rhodri James wrote: On 04/10/17 16:33, Paul Moore wrote: It's not an advantage or a disadvantage, just an approach. Many people like it, you may not. Specifically, yes you can't "just declare a lightweight struct or record with exactly two fields". Actually you can: >>> class Point: ... __slots__ = ("x", "y") ... def __init__(self, x, y): ... self.x = x ... self.y = y ... def __str__(self): ... return "({0},{1})".format(self.x, self.y) ... >>> p = Point(3,4) >>> print(p) (3,4) >>> print(p.x) 3 >>> p.x = 7 >>> print(p) (7,4) >>> p.z = 2 Traceback (most recent call last): File "", line 1, in AttributeError: 'Point' object has no attribute 'z' I pretty much never bother to do this because (bart to the contrary) But it's something you'd have to explicitly do (unless perhaps you make use of those decorators, which AFAICS can do magic). And when I tried, it didn't really work in Python 2 (extra attributes could still be created, and .__slots__ wasn't readonly); only Py3. it isn't useful if you're thinking in Pythonic terms, I clearly don't. When I do this in my non-Python language it would be just: record any = (var x,y) p := any(10,20) println p # (10,20) println p.y, p.x # 20 10 println p.len # 2 println p[2] # 20 println p = any(10,20) # 1 (compares fields) No __slots__, __init__ or __str__ need to be defined; it just works. If I needed a version suitable for foreign function interfacing, a little different: type point = struct (real64 x,y) p := point(10,20) println p # (10.,20.) println p.bytes# 16 It's not Pythonic, but it is pretty handy (I know Python can also do structs like this but it appeared to be quite a slog last time I looked.) I guess my kind of coding is somewhat less esoteric than the kind of thing I typically see in Python here. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 05/10/2017 07:57, Gregory Ewing wrote: Steve D'Aprano wrote: I recall that the Pascal compiler had to do some clever behind the scenes jiggery-pokery to get eof() to work, but that's what compilers are supposed to do: make common tasks easy for the programmer. Sometimes the jiggery-pokery worked, sometimes it didn't. For example, the following wouldn't work as expected: while not eof(input) do begin write(output, 'Enter something:'); readln(input, buffer); process(buffer); end because the eof() would block waiting for you to enter something, so the prompt wouldn't get printed at the right time. Basically, Pascal's eof-flag model was designed for batch processing, and didn't work very well for interactive use. This doesn't make sense. For interactive use, you wouldn't bother testing for eof, as you'd be testing the eof status of the keyboard. You might want a way of the user indicating end-of-data, but that's different; you don't want to abruptly send an EOF (via Ctrl-C, D, Z, Break or whatever). That would be a crass way of doing it. Besides you might want to continue interacting with the next part of the program. So the loop would be like this (Python 3; don't know why it doesn't work in Python 2): while 1: buffer = input("Enter something (Type quit to finish): ") if buffer == "quit": break print ("You typed:", buffer) # process(buffer) print ("Bye") This is a loop-and-a-half. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 05/10/2017 12:09, Chris Angelico wrote: On Thu, Oct 5, 2017 at 9:56 PM, bartc wrote: This doesn't make sense. For interactive use, you wouldn't bother testing for eof, as you'd be testing the eof status of the keyboard. You mean the way heaps and heaps of Unix programs work, processing until EOF of stdin? Yeah, totally makes no sense, man, no sense at all. Out of the hundreds, perhaps thousands of such input loops I must have written, how many needed to test EOF? Hmm, somewhere around zero I think. Oh hang on, I wasn't using Unix; does that make a difference? If you're referring to the ability to redirect stdin so that input can come from a file as well as from a live keyboard, then you're doing file handling; it's NOT interactive. (And I've used such programs where you get no prompt as to what to type, or how to finish, and you just blindly press Ctrl C, Ctrl D, Ctrl Z or Ctrl Break in turn until it stops. Really friendly. Because the program reads from stdin but assumes it comes a from a file or pipe anyway.) Note that Unix way isn't the ONLY way of doing things. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: newb question about @property
On 05/10/2017 12:29, Gregory Ewing wrote: bartc wrote: Result? You can't just look at my 'any' class and see what fields it uses. You can't even just look at the static source code. You have to run the program to find out. And it might be different each time. You can usually get a pretty good idea of what attributes a class has by looking at its definition. The vast majority of classes will either initialise their attributes in the __init__ method or provide defaults as class variables. While in theory it's possible for code to add attributes later after initialisation, in practice this is hardly ever done. Yeah, but, like many other things in this language, there are million ways of doing it. Just had a quick look, the first hit was talking about using a module 'pyrecord'. Another mentioned 'namedtuples'. Another used the '__slots__' method already mentioned (remembering the difference between old and new classes in Python 2...) One more uses a module 'recordtype'. And then there is just using a normal class, where you have to look closely at the code to see what it's implementing. It allow ad-hoc fields to be created, or it may define __init__ etc. And all with different capabilities regarding adding extra fields, having mutable records, initialising a record, comparing them, printing them, .... Am I allowed to say that it all seems a bit of a mess? -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 05/10/2017 18:01, Chris Angelico wrote: On Thu, Oct 5, 2017 at 10:26 PM, bartc wrote: On 05/10/2017 12:09, Chris Angelico wrote: On Thu, Oct 5, 2017 at 9:56 PM, bartc wrote: This doesn't make sense. For interactive use, you wouldn't bother testing for eof, as you'd be testing the eof status of the keyboard. You mean the way heaps and heaps of Unix programs work, processing until EOF of stdin? Yeah, totally makes no sense, man, no sense at all. Out of the hundreds, perhaps thousands of such input loops I must have written, how many needed to test EOF? Hmm, somewhere around zero I think. Oh hang on, I wasn't using Unix; does that make a difference? If you're referring to the ability to redirect stdin so that input can come from a file as well as from a live keyboard, then you're doing file handling; it's NOT interactive. How would you write a sort program? How would you tell it that you're done entering data? How do you do it with any kind of iterative program? It can be done with an in-band end-of-data code, although it might take some effort especially if you also want that to be invoked by pressing Ctrl-D. Then you can continue using a simple loop, and ignore dealing with 'EOF' on a keyboard. And yes, I have used sort(1) interactively, with no redirection whatsoever. Yes, I tried typing 'sort' in Linux, where it apparently hangs (same on Windows actually). The reason: because it might have killed someone to have added a message saying what you are expected to type and how to end it. (Namely, press Ctrl-D start at the start of a line in Linux, and Ctrl-Z followed by Enter, I think also at the start, in Windows.) -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: why does memory consumption keep growing?
On 05/10/2017 22:06, Fetchinson . wrote: Hi folks, I have a rather simple program which cycles through a bunch of files, does some operation on them, and then quits. There are 500 files involved and each operation takes about 5-10 MB of memory. As you'll see I tried to make every attempt at removing everything at the end of each cycle so that memory consumption doesn't grow as the for loop progresses, but it still does. import os for f in os.listdir( '.' ): x = [ ] for ( i, line ) in enumerate( open( f ) ): import mystuff x.append( mystuff.expensive_stuff( line ) ) What if you change this line to: mystuff.expensive_stuff( line ) If it's still growing (perhaps a bit less as it's not added to x), then something in mystuff is remembering data about each line. You might try removing the line completely too (temporarily of course). Other replies suggest that deleting the import [name] doesn't affect any data it contains. So might as well move it to the top where it belongs. del mystuff import mystuff mystuff.some_more_expensive_stuff( x ) You'll have to comment these lines out first I think. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 05/10/2017 23:42, Gregory Ewing wrote: bartc wrote: It can be done with an in-band end-of-data code, Then you need some way of escaping that in-band code, in case it happens to equal some of the data you want to sort. It needn't be a big deal. You can do this (you have to in Python as the normal 255 character signifying eof on a character stream is trapped): EOD=chr(26) # can be anything that is an unlikely input line. def myinput(prompt): try: return input(prompt) except EOFError: return EOD Then you can keep using a simple type of loop without worrying about EOF status: print ("Type Ctrl-Z on its own line to finish.") # Windows while 1: buffer=myinput("Enter something: ") if buffer==EOD: break print ("You typed:",buffer) # process(buffer) print ("Bye") Yes, I tried typing 'sort' in Linux, where it apparently hangs (same on Windows actually). The reason: because it might have killed someone to have added a message saying what you are expected to type and how to end it. (Namely, press Ctrl-D start at the start of a line in Linux, and Ctrl-Z followed by Enter, I think also at the start, in Windows.) How to signal EOF from the keyboard is a fundamental piece of knowledge about the OS. It's not the responsibility of individual programs to teach it to you, any more than it's your car's responsibility to explain what the steering wheel does each time you start the engine. If you have a utility that is designed to also be used interactively, but it shows absolutely nothing when you start it, like this: >sort then it stinks. You wouldn't think much of a shell prompt that literally showed nothing at all instead of something like: c:\python39> How would you even know what program you were in the middle of after the initial command has scrolled off the screen? How would you now it was still running? As typing a line into it give no response. I don't run these things often enough to remember exactly how to specify an EOF with the keyboard. It might be: - One of Ctrl C, D, Z or Break - It may or not may not only work at the start of a line - It may or not require to be followed by Enter I anyway would never inflict such an interface on my users, who would also associate Ctrl C etc with aborting a program that's gone wrong. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: why does memory consumption keep growing?
On 06/10/2017 00:38, Stefan Ram wrote: "Fetchinson ." writes: I have a rather simple program which cycles through a bunch of files, does some operation on them, and then quits. There are 500 files involved and each operation takes about 5-10 MB of memory. As you'll see I tried to make every attempt at removing everything at the end of each cycle so that memory consumption doesn't grow as the for loop progresses, but it still does. "2x 8GB DIMM DDR3-1600" cost $95.99 according to a web page. This might be in the order of magnitude of the hourly rate of a freelancing programmer. Brilliant. We can forget about freeing memory or garbage collection, just keep adding a 16GB bank of memory every few hours. It's cheaper that paying a programmer to write memory-efficient code or fixing the memory leak! (That's assuming such a program will only run on the programmer's machine and not a million consumer machines who would also need to fork out for extra memory. Their salaries may not stretch as far.) -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 06/10/2017 02:07, Steve D'Aprano wrote: On Fri, 6 Oct 2017 09:57 am, Marko Rauhamaa wrote: Waiting for input isn't "hangs". That's an ignorant and foolish thing to say, more suited for a wet-behind-the-ears newbie than somebody who claims to be a long-time old-school programmer. That's what it looks like. Is it doing something, or waiting for me to do something, or did it just hang? The Unix commandline interface is not designed to be user-friendly for newbies (or experts, for that matter). It is terse, often *painfully* so (would it have killed the author to have spelled `umount` correctly?), the UI is inconsistent, and it has a very steep learning curve -- a lot of effort is required to make a little bit of progress. OK. I'm not out to change Unix (not right now). But this style of utility was suggested as a way to write interactive input loops in Python programs, which you might expect to be friendlier. That it is, to assume from the outset that you're reading from a file, not a keyboard. And the user typing in data also has to pretend they are entering data in a file, complete with an EOF marker. That is what I object to. It is anyway not really acceptable these days for a long list of data to simply be typed in like that without any feedback at all. And 100% dependent on your typing Ctrl-D at the end and not Ctrl-C by mistake. This is not still the 1970s. But in fairness, if the author of the `sort` command had a commitment to friendliness in their programs, they could have `sort` only print a message when it is reading from stdin and writing to stdout, much as `ls` defaults to outputting control characters but automatically swaps to replacing them with ? when writing to a terminal. Surely this is a common problem that has long since been solved? You have a interactive program - even with proper prompts and feedback - and one day you want to run it as a script. (And properly, by being given the same of an actual file rather than using crude redirection.) But you don't want hundreds of dialogue lines scrolling up the screen while it's doing so. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 06/10/2017 12:04, Rhodri James wrote: On 05/10/17 19:45, bartc wrote: Yes, I tried typing 'sort' in Linux, where it apparently hangs (same on Windows actually). The reason: because it might have killed someone to have added a message saying what you are expected to type and how to end it. (Namely, press Ctrl-D start at the start of a line in Linux, and Ctrl-Z followed by Enter, I think also at the start, in Windows.) Actually it might. Linux tools are written not to assume that stdin and stdout are the console, because they frequently aren't. Extra puff written to stdout at best makes it harder to use in a pipeline, and at worst makes it useless; tools that do that tend not to get used. A lot of people aren't getting it. The internal utilities used within an operating system, primarily intended for file or redirected i/o with no live interaction, should be distinct from those designed to be used directly with a live user. Or is it against the rules of Unix to have two different versions of a program? Then you might have 'sort' for the non-interactive version, and 'isort' or whatever for the interactive. Except you simply wouldn't use an interactive version of any program that reads an arbitrary long list of uninterrupted data, no matter how the ending is indicated. You'd use a text editor, enter the lines at your leisure, go back and forth to check and edit as needed, THEN you would submit that file to 'sort'. As an actual input file. So I can't see the point of using that same pattern of input usage (reading from stream, file, pipe whatever until interrupted with an EOF signal) for a true interactive program that is used in a sensible manner. (Say, an FTP program, which has a prompt, lots of commands, and usually instant feedback. An actual dialogue. A program like 'python' might fit the bill too. Here, you can give it the name of a file, OR say nothing, and it will take input from stdin. Funnily enough, you now get a message, and a prompt. And when entering multiple lines of code, you get a prompt before each line. You can also terminate the sequence by entering a blank line. So it IS possible to do it properly after all!) -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 06/10/2017 12:51, Chris Angelico wrote: On Fri, Oct 6, 2017 at 10:41 PM, bartc wrote: > What you REALLY mean is that you can't see the point of an interactive > sort command. It doesn't fit into your workflow. And that's fine. It's > not something you'd use very often. There are other programs, however, > that behave exactly the same whether used in batch mode or interactive > mode, and where you would do exactly the same thing as I described - > provide input, and hit Ctrl-D to mark that you're done. Examples? And is there any reason why you wouldn't use a text editor to capture your input first? I can see myself noticing an error I'd made 10 lines up, which is now too late to change, and I've still got 100 lines to go. What to do? I just can't anyone wanting to use programs that work in the way you suggest. Not outside of a student exercise (read N numbers and display the average), where getting the input correct isn't so important. > And since > every one of these programs is written to read from stdin until EOF, > you can use them all in exactly the same way - type at keyboard, hit > Ctrl-D when done. So they're all at it! That doesn't mean it's a good way of doing things. So it IS possible to do it properly after all!) Actually, Python's interactive mode is completely different from its file input mode. You're not really comparing like things here. Python's incremental interpreter is *by nature* interactive, and redirecting its input does not produce the same result as running "python3 filename.py" would. Can you find yourself a better example? I gave the FTP example. (Which actually, in my version, doesn't work properly when trying redirect input into it. You have to give an actual file name.) But what's wrong with the Python example? It detects when it's given a file (as as actual parameter, or redirected), and when it's used interactively, and adapts its behaviour accordingly. It just needs a bit of effort. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 06/10/2017 12:45, Chris Angelico wrote: On Fri, Oct 6, 2017 at 9:32 PM, bartc wrote: (And properly, by being given the same of an actual file rather than using crude redirection.) Why do you call redirection "crude"? Do you not understand the value of generic solutions that work with all programs, rather than having every program implement its own "take input from file" parameter? You can disagree with the Unix philosophy all you like, but when you insult it, you just make yourself look like an idiot. Redirection is used on Windows too. I use output redirection quite frequently (to capture the output of 'dir' for example). I don't rely on > and < in my own programs. Where there's complex, mixed output, the bulk of it - the data - needs to go to a proper file, while the screen shows messages. If you don't like the word 'crude', try 'lazy'. Take this example of the gcc C compiler: > gcc -E program.c This preprocesses the code and shows the result. Typical programs will have many thousands of lines of output, but it just dumps it to the console. You /have/ to use '>' to use it practically (Windows doesn't really have a working '|' system.) Another compiler might simply write the output to a file 'program.i'. BTW if I try: > gcc https://mail.python.org/mailman/listinfo/python-list
Re: newb question about @property
On 05/10/2017 14:13, Steve D'Aprano wrote: On Thu, 5 Oct 2017 10:51 pm, bartc wrote: Am I allowed to say that it all seems a bit of a mess? You may or may not be pleased to learn that there's a push to create a "record like" or "struct like" datatype for Python 3.7 or 3.8, tentatively called a "Data Class" for now. https://www.python.org/dev/peps/pep-0557/ Yeah, maybe (looks a bit over-ambitious to me; why is it necessary to have typed fields? Or to do relative compares?) But it reminds me a bit of the xkcd cartoon about the 14 competing standards becoming 15... -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 06/10/2017 14:11, Peter J. Holzer wrote: On 2017-10-06 12:38, bartc wrote: On 06/10/2017 12:51, Chris Angelico wrote: What you REALLY mean is that you can't see the point of an interactive sort command. It doesn't fit into your workflow. And that's fine. It's not something you'd use very often. There are other programs, however, that behave exactly the same whether used in batch mode or interactive mode, and where you would do exactly the same thing as I described - provide input, and hit Ctrl-D to mark that you're done. Examples? And is there any reason why you wouldn't use a text editor to capture your input first? I can see myself noticing an error I'd made 10 lines up, which is now too late to change, and I've still got 100 lines to go. What to do? I just can't anyone wanting to use programs that work in the way you suggest. Not outside of a student exercise (read N numbers and display the average), where getting the input correct isn't so important. I regularly use at least cat, wc and od this way (plus a few of my own utilities like utf8dump). I'm sure I've used sort this way, too, though rather rarely. I usually don't type the input but paste it in, Exactly. Probably no one ever uses these programs with actual live input with the possibility of uncorrectable errors getting through. So not a good reason to use that coding pattern to write programs which ARE designed for live, interactive input: print ("Enter blank expression to quit.") while 1: buffer=input("Expr: ") if buffer == "": break try: print (eval(buffer)) except: print ("Error") print ("Done") -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 06/10/2017 14:35, Paul Moore wrote: On 6 October 2017 at 13:56, bartc wrote: If you don't like the word 'crude', try 'lazy'. Take this example of the gcc C compiler: > gcc -E program.c This preprocesses the code and shows the result. Typical programs will have many thousands of lines of output, but it just dumps it to the console. You /have/ to use '>' to use it practically (Windows doesn't really have a working '|' system.) No you don't. Ignoring the fact that "windows doesn't really have a working '|' system" (which is an oversimplification, by the way) the following all work: Python: data = subprocess.check_output(["gcc", "-E", "program.c"]) Powershell: $x = (gcc -E program.c) cmd: for /f %i in ('gcc -E program.c') do ... If gcc -E wrote its output to a file, you'd have to read that file, manage the process of deleting it after use (and handle possible deletion of it if an error occurred), etc. But if I use the -S option (show assembly listing) that DOES output to a file (program.s). If I use -fdump-tree-all, that also goes to a file (various). Writing to stdout is very often a good design. Not always, but nothing is ever 100% black and white, but sufficiently often that building an OS based on the idea (Unix) was pretty successful :-) The first computer I used was via a teletype printing on paper. If every operation producing an arbitrarily open-ended amount of output defaulted to the terminal, then it would have been totally impractical (in time taken and the amount of paper used). Even with today's consoles, 80,000 lines whizzing up the screen (when program.c contains '#include '), while not taking quite that long, still seems crazy to have as the default operating mode. But you will say, Ah but you will never see it because it will nearly always be piped into another program. And that reinforces the point I keep making: many of these are internal utilities never intended to be used as properly interactive commands. Fine, but why keep bringing them up as models of how to write true interactive programs? -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 06/10/2017 15:55, Chris Angelico wrote: On Fri, Oct 6, 2017 at 11:38 PM, bartc wrote: Have you ever worked on a slow remote session where a GUI is completely impracticable (or maybe even unavailable), and redrawing the screen is too expensive to do all the time? You absolutely have to work with line-by-line content. Not since about 1977, using 110 baud teletypes and VDUs, on a mainframe not geared to interactive use so it was unresponsive anyway. By 1981 however I was using a memory-mapped text display (of my home-made computer) which even with its 8-bit processor could update the screen at 200,000 characters per second. In other words, instantly. So what's the excuse for an unresponsive text display in 2017? What text editor do you use there? That depends; are we still in the 1970s? That's why we have the stderr stream as well as stdout. You can redirect stdout and still have messages go to the screen (via stderr); or you can redirect stderr as well, sending those messages to a logging facility. How do you do THAT with your program? I said the output was complex. Then there might be more than one output file, and one or more of the outputs need to be in an actual file. Just blithely sending /everything/ to stdout, even mixed up with stderr, might be something I'd do for a quick throwaway program, not a major application. (And since I mainly use my own languages, actually getting hold of 'stdin', 'stdout' and 'stderr' is not trivial. Creating actual named files is much easier.) Also: can you use your program to write to a file on a different computer? I can pipe a program's output into SSH. You can make a crude intercom system like this: No. I've got no idea about formal networking. (Actually, I walked out of the computer networks exam in my CS course, as I realised I knew nothing.) But as it happens, I could make computers talk to each when I was working with microprocessors, using home-made interfaces, rs232 or rs423. I wouldn't know how to do it now because it depends on other people's over-complex tech. I'm not sure what you mean by a working pipe system. Yes, the one cmd.exe gives you is not nearly as flexible as what bash gives you, but for the purposes of the examples given so far, I just don't work that way. The OS is there to launch applications, or to provide a basic API for common services such as a file system. I don't need its complicated shells. BTW if I try: > gcc "It doesn't work" is a terrible way to report this. What's the problem? Is it possibly what's described fairly clearly in the error message? It says 'no input files'. Presumably it's one of those programs that only takes input instructions from the command line, and does not look at stdin. In which case you wouldn't be able to pipe source code into it. You might actually have to tell it the name of a discrete file you want to compile. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 06/10/2017 18:42, Chris Angelico wrote: On Sat, Oct 7, 2017 at 4:13 AM, bartc wrote: So what's the excuse for an unresponsive text display in 2017? Got it. You assume that a system is a coherent computer with its peripherals, rather than being a networked collection of computers, all of them controlled from your laptop in response to a panicked email saying the web site is down. Your terminal exists on your laptop. The programs are being run on any of a number of your servers, possibly several of them concurrently. How do you handle that? What text editor do you use there? That depends; are we still in the 1970s? Nope. We're in 2017, where the "system" is often a networked collection of computers. Still no excuse. We were talking about the need to use a crude keyboard interface to serially create a file of data a line at a time rather than using a proper application for it (such as a text editor). So which bit do you have access to locally? The keyboard presumably. And the display has to be local unless you it's either got a 50' screen or you use binoculars. Are you saying the bit in the middle is remote and that is what is playing up? This is exactly the situation from the 1970s that I thought we'd long left behind! There really is no excuse for not having the minimum amount of local processing power available to be able to enter and review a few dozen lines of text without needing to involve a temperamental network. If you're stuck, whip out a tablet computer or smartphone (they should still function without connectivity) and use a preloaded text editor. Or just compose and then save an email. Even the simplest should be more sophisticated than just blindly entering text on a Linux terminal screen. (And since I mainly use my own languages, actually getting hold of 'stdin', 'stdout' and 'stderr' is not trivial. Creating actual named files is much easier.) More blub happening right there. You start out by assuming that the standard streams are unimportant, therefore you think that providing them is pointless. It's self-perpetuating. They were a creation of either C, Unix, or some combination. Certainly I had very little to with any of that for decades. I can't remember that it ever stopped me doing anything I needed to do. My own programs worked like this (showing original '#' symbol I used); print "One" # to console (also using print #0) print #f, "Two" # to file handle f print #s, "Three" # append to string s print #w, "Four" # to window or control w print #b, "Five" # to image b What would I want with stderr?! It's 2017. You should understand at least a bit about the internet and how to use it. I can use it but can't fix it when it goes wrong. I don't know if you're an idiot or a troll. Using TCP/IP networking is pretty simple (at least if you're using a real language - your own toy languages might have made it unnecessarily hard, for all I know), hardly "over-complex" by comparison to RS-232 programming. So how do you use it from Python - without using an existing Python library? Or is it only simple when someone else has made it idiot-proof? (That reminds me, at some point I have to provide a winsock2.h file for my C compiler. I may have to finally learn some of this stuff to test it.) I just don't work that way. The OS is there to launch applications, or to provide a basic API for common services such as a file system. I don't need its complicated shells. Blub rears its head again. How so? I said I have little need for most of what an OS does, in my development work, which is perfectly true. Perhaps you haven't noticed that many are using sophisticated IDEs now rather than fiddling about with command lines. (Mine is not sophisticated, but still better than a command line.) At what point will you acknowledge that there are things you do not understand that are actually useful? I can understand that people who use Unix and Linux arrange their world so that all these things are apparently indispensable. What you're trying to tell me is that because Unix provides such a tightly knit system system of utilities, stdin, stdout, files, pipes and very specific ways of using the keyword (which seems to consist of avoiding actually using it for entering data as much a possible; just using the logical idea of it), then every other text entry system in the world, in whichever OS or application, must follow exactly the same model. Because the Unix one is so great. Needless to say, I disagree. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 06/10/2017 18:55, Marko Rauhamaa wrote: bartc : The internal utilities used within an operating system, primarily intended for file or redirected i/o with no live interaction, should be distinct from those designed to be used directly with a live user. Or is it against the rules of Unix to have two different versions of a program? Then you might have 'sort' for the non-interactive version, and 'isort' or whatever for the interactive. You are right that interactive programs exist and operate very differently from what are known as *tools*. Interactive Linux programs include: LibreOffice NetworkManager Firefox Skype XBoard Emacs GIMP top gdb etc. I meant interactive programs that work with a scrolling display, as suits a program like this: while 1: print (input("?")) Considerations of the 'eof' status of a keyboard would of course be irrelevant for anything more sophisticated, either with a more organised console app, or one using a GUI. I don't know if anybody has seen a market/need for an interactive sort program, but there's nothing preventing you from writing one. For sort, there is no real need. You use a text editor to create your data. Then use existing file-based sort. So I can't see the point of using that same pattern of input usage (reading from stream, file, pipe whatever until interrupted with an EOF signal) for a true interactive program that is used in a sensible manner. So go ahead and write an interactive sort program. It might employ a mouse, joystick, iris scanner, touchscreen, sound effects or whatever facilities you would think would be useful for the human user. It wasn't me who brought up 'sort' when the subject was interactive keyboard dialogues (it was Chris I think). A program like 'python' might fit the bill too. Here, you can give it the name of a file, OR say nothing, and it will take input from stdin. Personally, I think stdin is a bit lame as a stimulus source for an interactive program. That's not even what stdin is primarily meant for; stdin is meant to be the input data for a job. Similarly, stdout is meant to be the result of the computation. Stderr, then, is used to deliver optional diagnostic messages, ie, metainfo about the computation. You really need punched tape or cards for input and output to get the full effect. Complete with all the sound effects. Sadly when I came into it, we were using mag-tape for input (with a variety of outputs). The clatter of an ASR33 printing your results was also a treat. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 06/10/2017 20:38, Grant Edwards wrote: On 2017-10-06, bartc wrote: For sort, there is no real need. You use a text editor to create your data. Then use existing file-based sort. I sort streams on stdin far more often than I sort named files. So what's been established is that 'sort' is useful for a text stream that already exists as a file or is the output of another process. What hasn't been established is why how this works this has to influence the design of simple text-based dialogues, real ones where there will likely be an actual user tapping the keys in real time. The only tenuous connection I can see, is that if 'sort' is run without any piped or redirected input, it will resort to the keyboard. Even though that method is not user-friendly and hardly anyone ever uses it in that mode. So that same unfriendly technique should be the model for text dialogues everywhere. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 06/10/2017 20:21, Chris Angelico wrote: On Sat, Oct 7, 2017 at 5:51 AM, bartc wrote: If you're stuck, whip out a tablet computer or smartphone (they should still function without connectivity) and use a preloaded text editor. Or just compose and then save an email. Even the simplest should be more sophisticated than just blindly entering text on a Linux terminal screen. Save an email and then what? You will have been able to create and review the text using normal editing methods. It will then be saved as a draft somewhere. When the sort program is back up (if that's what you're planning), then retrieve the text with copy&paste. No need to actually send it anywhere. My point is that everyone has the facility to create at least plain text documents off-line. There is no need to start some ancient terminal utility, get no response from it, then blindly type in line after line with no idea if it's doing anything with it. You need to make a change to something on a remote server. Maybe your hosts file is borked. Maybe the mail server configuration is slightly off, resulting in delayed delivery. Maybe your bindfile has an outdated record in it so half your users are getting timeouts. Whatever it is, it's almost certainly going to be managed by a text file in /etc, so you need to edit that file. How do you edit a file on a remote computer? How do you compare three instances of that file on different computers to see if one of them is different? I've no idea where you're going with this. Remember my original complaint was in treating keyboard entry like a file complete with EOF marker. They were a creation of either C, Unix, or some combination. Certainly I had very little to with any of that for decades. I can't remember that it ever stopped me doing anything I needed to do. That's Blub. You've never used it, so you don't understand its value, so you scorn it. OK, that works both ways as you've never used any of my stuff. print #w, "Four" # to window or control w print #b, "Five" # to image b I'm not sure what printing to a window or image would mean, or how it's useful, It displayed the text at the current position (using the current font, size and colour) and moved the current position to the end of the text. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 07/10/2017 00:43, Steve D'Aprano wrote: On Sat, 7 Oct 2017 12:24 am, bartc wrote: print ("Enter blank expression to quit.") I *despise* programs that do that, and would cheerfully and unapologetically take their designers, disguise them as a lettuce, and stake them out to be nibbled to death by snails. At the interactive prompt, I am frequently hitting Enter on a blank line, either by accident, or deliberately to break up the calculations into groups, or just to give myself time to think. Blank lines should be treated as "do nothing" and simply ignored, and there should be an explicit QUIT command. Um, that actually follows what interactive Python does. If you type this (I'm using <<< as the prompt as >>> confuses my newsreader's quoting system): <<< def fn(): <<<pass <<<pass At this point, you can break out by pressing the key for 'eof', or by pressing Enter at the start of a line. Even though a blank line is legal Python syntax. (Most of my real interactive programs with a command line interface programs use Escape, quit, exit, q or x to finish. Interactive Python requires quit() or exit(), complete with parentheses. Unless you've redefined quit and exit as something else, then you have to crash out by other means.) -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 07/10/2017 01:14, Ben Bacarisse wrote: bartc writes: On 06/10/2017 14:35, Paul Moore wrote: On 6 October 2017 at 13:56, bartc wrote: If you don't like the word 'crude', try 'lazy'. Take this example of the gcc C compiler: > gcc -E program.c This preprocesses the code and shows the result. Typical programs will have many thousands of lines of output, but it just dumps it to the console. You /have/ to use '>' to use it practically (Windows doesn't really have a working '|' system.) Does the Windows version of gcc not support the -o file option? I never thought of trying it. But OK, you have to use -o or > to stop the output from swamping the console. (| might work if I could find a program that captured the piped output for the purpose of browsing.) (In my IDE, if a particular C file is highlighted, then typing 'cpp' will invoke the currently selected C compiler's -E equivalent, then instantly show the result in the editor. Looking at the script for that, that does make use of the -o option, for gcc, so I must have known about it.) And a good system lets you alter that. How many labels are generated for some code? Let's see: gcc -S -o /dev/stdout t.c | grep -c '^\.L' Now gcc also permits -o - (it's a common Unix convention) but you can almost always get round less helpful programs using /dev/sdout. I'm not really arguing against this. I'm disputing the suggestion that because these utilities, which are rarely given data actually typed from the keyboard, work by reading from stdin using an eof-checking loop, that the same method must always be used in programs that really are reading data from the keyboard. I think they are different kinds of applications. (As for the ability to chain these programs together, I have the same opinion of that as doing the same in program code when you use the result of one function/method call to feed in as the argument to the next. They can both end up as long horizontal hard-to-follow (or to intercept) sequences. I'd prefer to break them up using intermediate variables in the language and intermediate files in the shell. And as you can see from my IDE's 'cpp' command, which works with 4 different C compilers (a fifth doesn't properly support -E), there are other approaches developers can use.) -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 07/10/2017 02:46, Steve D'Aprano wrote: On Sat, 7 Oct 2017 06:18 am, bartc wrote: For sort, there is no real need. You use a text editor to create your data. Then use existing file-based sort. What you mean is, *you* see no need for sorting interactively, or sorting as part of a pipeline of functions. That speaks more of your lack of imagination and closed-mindedness than any real lack. Where did I say that? The 'existing file-based sort' works from files and pipes. It's capturing the data to start with that it would be ludicrous to do interactively using such a crude interface. Personally, if I have a few (say, a dozen or so) lines I want sorted, it is much easier to: - select text from whatever application I'm using; - bring up a terminal (I almost always have one already open); - type `sort ENTER`; - middle-click to paste the lines; - type Ctrl-D; - select the output lines; - paste back into the original application; That's not entering the data interactively (such as typing 'sort' then it sits silently recording lines of text (you hope) until it sees EOF). You say the lines already exist in a text editor. Exactly what I said; you start with text that has already been entered or generated by other means. However it does seem to expose a flaw in the ability of command line tools to work with non-command line tools. So I have to copy 33,000 lines from a document, get to the terminal (keeping that document open because I'm not done with it), start 'sort', and paste those 33,000 lines into the console, then type Ctrl-D. Which then promptly prints the newly sorted 33,000 lines onto the console. Then you have to select those 33,000 lines (not easy as you now have find the midpoint of 66,000 lines of output), copy it, and paste it back into the app. Put that way, it doesn't sound very sophisticated does it? (Now I expect you're going to bombard with workarounds to fix all those issues.) (seven steps) versus: That's not what I meant at all, which is about creating the data from scratch. Here, the data STILL already magically exists somewhere! Is it possible that you guys have never had to create anything original? (How would /I/ sort a block of text in my editor? There's no built-in function, so using your approach: * Select the block * Ctrl KWfileEnter to write it to 'file' * Elsewhere, sort file2 * Back in editor, Ctrl KY Ctrl KRfile2Enter to delete then insert file2 Only four steps? Something went amiss in your analysis I think. And even these could be simplified by Using Ctrl KS and Ctrl KL to use a predefined clipboard-like filename for the intermediate. However, how hard would it for the editor to do its own sorting? Not very, as it turns out, only half a dozen lines of code (see below after sig). Now the sequence is: * Select the block * Ctrl KH How many steps did you have, seven?) I forget... it is "work harder, not smarter"? Being inefficient is a good thing, right? Okay -- bartc -- proc cmd_ctrlkh <"med:*ck*ch "> (td) = if td.blockstart then isort(td.text[td.blockstart..td.blockend]) pageupdate(td) fi end -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 07/10/2017 03:18, Chris Angelico wrote: On Sat, Oct 7, 2017 at 12:50 PM, Steve D'Aprano wrote: On Sat, 7 Oct 2017 06:21 am, Chris Angelico wrote: I'm not sure what printing to a window or image would mean, or how it's useful, but sure. Print to window: Print Preview. Print to image: export to pdf or jpg or png. Except that that isn't what you get in his programming language. What you seem to get (judging from his response to the post you're quoting) is something that lets you treat a GUI window as if it were a console, printing text to it in some sort of "glass teletype" way. Leaves me wondering if he's ever taken one of his apps to a system that uses a different default font, or anything like that. Unless all his GUIs are built in HTML? (That particular language was one I was using over 20 years ago and it was an integrated part of a CAD application (and it started off pre-Windows). The app also supported printer/plotter/image destinations including PostScript. The same language could take a marked-up text file, convert it to a series of drawing elements, then render and print that page on a PS printer. Then the same with the next page. I think I did a 350-page manual like that. With pictures. My current language doesn't link its 'print' to graphic displays or images.) -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 07/10/2017 09:35, Steve D'Aprano wrote: On Sat, 7 Oct 2017 11:05 am, bartc wrote: Um, that actually follows what interactive Python does. What is "that" to which you refer? If you mean, "what I, Bart C, suggested, namely having the program exit on a blank line", then you are wrong. In the Python interactive interpreter, you can enter blank lines, and the interpreter doesn't exit. There's one priviso: blank lines are only ignored at the primary prompt >>> not the secondary prompt ... where a blank line is used to end the block. But the interpreter doesn't exit. A slight compromise for the sake of convenience at the interactive prompt. That's what I mean. Enter is used to end one state and get back to another. The same thing with my loop evaluating expressions. When you're done with with expressions, you might exit in the trivial example, or you might get back to a main command loop. Just like Python. (Most of my real interactive programs with a command line interface programs use Escape, quit, exit, q or x to finish. And how do you distinguish between calling quit from inside the function, and using quit inside the function? Huh? Most interactive programs aren't language interpreters like Python, where everything needs to be considered to be a line in the language syntax. Unfortunately ESCAPE is already used. VT100 (the terminal emulation which is used in just about all terminals) all control sequences begin with ESC. So every time you do something like press an arrow key, the terminal sends ESC followed by other stuff. It would be painful if every time you hit an arrow key, the interpreter took it as "Exit". Yes, I discovered this. So my programs that use Escape on Windows needed to use Escape Escape on Linux to get around that. Interactive Python requires quit() or exit(), complete with parentheses. Unless you've redefined quit and exit as something else, then you have to crash out by other means.) "Crash out", he says. If your intention is to prove that you're a know-nothing ignoramus, you're doing an excellent job of it. Yes, crash out. I've always considered control sequences as something out of the ordinary used when things go wrong. Eg: <<< while 1: <<< pass <<< Here it appears to hang, and nothing you type does anything except (on Windows) Ctrl-C. That's what I call crashing out. Although that stays within the interpreter. If I press Ctrl-Break instead, it aborts the interpreter too. What exactly is your problem, that anyone who has a different take on things must be an 'ignoramus'? And, to boot, an ignoramus who knows nothing? -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 07/10/2017 14:19, Steve D'Aprano wrote: On Sat, 7 Oct 2017 11:06 pm, bartc wrote: Ctrl-K to enter "operate on selected text" mode; Y to Delete Ctrl-K to enter "operate on selected text" mode; R to Read from a file (at last an actual mnemonic command!) enter a file name That's five steps. Are we counting steps or keystrokes? And now you have two "temporary" files, file and file2, which need to be deleted. Two more steps that you conveniently don't count. Actually I keep a set of 9 scratch file names just for such purposes. So overwriting and deleting don't matter. (Apparently the names are offensive to some so I won't mention them, but they're easy to type.) And you think that memorising these non-standard keyboard shortcuts Ctrl-KW Ctrl-KY Ctrl-KR I believe these used to be WordStar commands, if anyone can remember that. is better than memorising Ctrl-D which works across thousands of applications? Good for you. You probably would love Emacs, except other people use it, and therefore you will hate it. [...] However, how hard would it for the editor to do its own sorting? Yes, it is a mystery to me why so few editors include a "sort lines" function. I don't know if you're being sarcastic here or not, so I don't know if you mean few editors have 'sort' or most of them do. Neither do I get the point you're making. But it's a little ironic that it took less time to add such a feature than I spent writing about it in a post! -- bart -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 07/10/2017 14:19, Steve D'Aprano wrote: On Sat, 7 Oct 2017 11:06 pm, bartc wrote: So I have to copy 33,000 lines from a document, Don't be daft. Nobody says that stdin is a sufficient interface for a heavy-weight task like that. With 33000 lines of text, I absolutely would save them to a permanent file on disk, because I wouldn't want to risk having the application crash or the power go off just as I've typed line 32999 and lose the lot. You're missing something I think. The 33K lines already exist elsewhere, and have been copied to the clipboard. So you won't lose anything if the power goes off, assuming the original are secure. For 33000 lines, having one extra temporary file floating around is a cost worth paying. For 33 lines, it is not. I was demonstrating the crudeness of copying and pasting to a console window rather than between proper applications. That was easier to show with a larger example which highlighted some of the practical aspects. You want a one-size fits all solution. Are you capable of understanding that different tasks and different scenarios are often best solved using different techniques? [...] Put that way, it doesn't sound very sophisticated does it? Nobody said it was sophisticated. That's the whole point: having sort read from stdin as you type into the terminal is the LEAST sophisticated, simplest, most bare-bones, basic technique that works. You do remember this was about using programs /like/ sort as a model for writing true interactive scrolling text apps? I said it was a poor model because sort is normally used with files and pipes. You're trying to keep it as a viable model because, sometimes, sort can also be used with pasted text which sort reads as as though it had been typed in real time (not from a pipe or file anyway). OK, I'm not suggesting doing away with that. But it is still a bad model of text application to use elsewhere, even if extra prompts were added. For one thing, it only reads one block of data, then it stops. A more typical text application will be doing different things requiring different entry modes. -- bartc -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 07/10/2017 15:45, Grant Edwards wrote: On 2017-10-07, bartc wrote: Interactive Python requires quit() or exit(), complete with parentheses. Nonsense. On Unix you can just press ctrl-D (or whatever you have configured as eof) at the command prompt. On windows, it's Ctrl-Z . Steve spoke about the 'usual quit/exit/bye' commands. If you type 'quit' in interactive Python, then it says: Use quit() or Ctrl-Z plus Return to exit Same for exit. So in Python, IF you want to use quit or exit to terminate, you have to use quit() or exit() instead. So please explain how what I wrote was nonsense. Unless you've redefined quit and exit as something else, then you have to crash out by other means.) Admit it, you're just trolling. FFS, NOW what's wrong? IF you DO redefine those names, then you DO have to use other means to terminate. I happen to call those means 'crashing out', because it's like yanking the plug rather than using the on/off switch. Especially on Windows where the usual Ctrl C doesn't work, so you resort to Ctrl-Break will which actually abort it. Ctrl Z is uncommon. I suspect it's you trying to deliberately wind ME up. I'm getting fed up with this thread now. -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 07/10/2017 17:28, Steve D'Aprano wrote: On Sun, 8 Oct 2017 01:15 am, bartc wrote: You do remember this was about using programs /like/ sort as a model for writing true interactive scrolling text apps? I don't remember any such thing. I remember you *claiming* that, but if anyone actually did make that claim, I haven't seen it. bart: > This doesn't make sense. For interactive use, you wouldn't bother > testing for eof, as you'd be testing the eof status of the keyboard. > ChrisA: > You mean the way heaps and heaps of Unix programs work, processing > until EOF of stdin? Yeah, totally makes no sense, man, no sense at > all. bart: > If you're referring to the ability to redirect stdin so that input can > come from a file as well as from a live keyboard, then you're doing > file handling; it's NOT interactive. ChrisA: > How would you write a sort program? How would you tell it that you're > done entering data? -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 08/10/2017 10:12, Steve D'Aprano wrote: On Sun, 8 Oct 2017 02:06 am, bartc wrote: Thousands of Python programmers on Windows successfully learned to use Ctrl-Z ENTER back in the days of Python 1.5, before quit/exit were added as a convenience for beginners, and many of them probably still use it. Actually I NEVER normally use Python in interactive mode. Only to test how it works interactively. When I use Python, it's from my IDE. I'm getting fed up with this thread now. This thread would be a lot less frustrating if you would enter into it with a spirit of open-minded enquiry rather than an overbearing sense of superiority that anything others do that you don't must be worthless. Frustrating for whom? It seems to me that it's pretty much everyone here who has an overbearing sense of superiority in that everything that Unix or Linux does is a million times better than anything else. Even with things like building applications (eg. trying to build CPython from sources), they are designed from the ground up to be inextricably linked to Linux scripts, utilities, makefiles, installation schemes, or designed to work with the Linux-centric gcc C compiler. Then when they don't work as well anywhere else, it's because Linux is so much better! No, it's because they were non-portably designed around Linux and therefore designed NOT to work well anywhere else. It is also slightly frustrating for me when I see how Python is developing, with layer after layer and library after library piled on to achieve some fantastically complicated solution (one of 48 different ones to choose from) to replicate some basic functionality that could have been done in 5 minutes if GvR had decided to add it right at the start. But this is a Python group and I have to restrain myself from such comments to avoid getting lynched. There is nothing wrong with Python! -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 07/10/2017 15:40, Steve D'Aprano wrote: On Sat, 7 Oct 2017 11:54 pm, bartc wrote: So my programs that use Escape on Windows needed to use Escape Escape on Linux to get around that. Or you could just follow the expected Unix interface instead of inventing your own. Your job is to port an editor that people have been using for 30 years to Linux. The first thing you do is to change all the commands and shortcuts to match what is typical on Linux? So that no-one who was familiar with it as it was can actually use it? Back in the days when I used a Mac (long before OS X), I used to hate it when Windows developers would port their software to Mac. With the exception of a few big software companies like Microsoft, who had actual Mac teams, they would do what you do: completely ignore the Apple UI guidelines and port their unfamiliar and arbitrary user interfaces to the Mac software, making it essentially unusable. What is it with those who write OSes in that they have to tell everyone how to run the show? An OS's job is to run programs and do whatever the program requests. BTW, how did the Apple UI guidelines come about; where they copying existing practice, or did /they/ decide to come up with something new and incompatible with anything else? And if the former, then you ask the same question of Xerox or whoever. Just look at any interactive page on the web, they all work differently. People are used to it. And it allows innovation. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 08/10/2017 12:22, Paul Moore wrote: When developing scripts, applications, or any form of code, I use good ideas from anywhere, as I doubt that I have the monopoly on knowing the perfect way to write code. Some of those good ideas come from Unix-based systems. That's not "because Linux is so much better", it's because someone other than me had a good idea, and I acknowledge the fact. When developing code I use whatever tools and techniques I like. But if I want to someone else to build one of my applications, I make it as easy as possible for them, even to to the extent of translating it to a language that they will be able to build. Here, for example, is a C compiler (which, actually, is not written in C, but is presented as a C program): www.bcas.freeuk.com/mcc64.c One file only. But it is only for 64 bits. Build on Windows or Linux (for Linux it is 'gcc -m64 mcc64.c -omcc -lm'). Runs on either (but generates code for win64 ABI). Another: www.bcas.freeuk.com/pcc64.c, a byte-code interpreter, builds and runs on either OS, one file. That needs a separate byte-code compiler, www.bcas.freeuk.com/qcc64.c. Again, one file. Again, runs on either OS. And I believe each file works with any C compiler. (Actually, I just found it had a dependency on a Windows time function; I've removed that temporarily for this upload.) See the pattern here? Simplicity not complexity. Consideration for others by making life easier.) -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 08/10/2017 13:05, Chris Angelico wrote: On Sun, Oct 8, 2017 at 10:46 PM, bartc wrote: Just look at any interactive page on the web, they all work differently. People are used to it. And it allows innovation. Maybe it's just that you're not old enough to have worked with text editors that predate CUA? That might explain your confusion about what should be standardized. I first used line editors in the 1970s. When I started writing graphics apps, graphics was very new, at least in the low-end business computer world (the one that was soon dominated by the IBM PC). So there was little existing practice to copy from. (And actually, I had my hands full either designing the graphics boards, or writing the drivers, graphics libraries, providing the fonts and so on (plus the languages), all the underlying stuff needed to make it all work.) However as graphics became more mainstream then yes I did adopt some commonly expected styles (menubars for example). As for Alt-F4, if that generates a WM_CLOSE message for example, then I would be obliged to deal with it. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 08/10/2017 17:13, Chris Angelico wrote: On Mon, Oct 9, 2017 at 2:01 AM, bartc wrote: However as graphics became more mainstream then yes I did adopt some commonly expected styles (menubars for example). As for Alt-F4, if that generates a WM_CLOSE message for example, then I would be obliged to deal with it. Yes, it usually does generate that. Why? Because your desktop manager translates concrete user actions into abstract events like "close window" - and does so according to a number of standards. In case you haven't noticed, those standards are not 100% consistent across platforms. So that means that... On Sun, Oct 8, 2017 at 10:46 PM, bartc wrote: On 07/10/2017 15:40, Steve D'Aprano wrote: Or you could just follow the expected Unix interface instead of inventing your own. Your job is to port an editor that people have been using for 30 years to Linux. The first thing you do is to change all the commands and shortcuts to match what is typical on Linux? So that no-one who was familiar with it as it was can actually use it? ... yeah, you absolutely *should* follow your OS's conventions, and you automatically *will* if you're using a properly-designed GUI toolkit. Why should it be different with the console? For instance, anyone on Linux will understand what this prompt notation means: Use config file: [~/.flurblerc] Yep, definitely follow your host platform's conventions. Yeah, well, some people like to be sheep, others like to be individuals**. I start in computing at a time when an application was the only thing running on a computer, at least, when people had personal computers of their own. Then it really didn't matter what went on outside, as nothing did. (That approach seems to have become popular again with tablets and things usually having one application occupying the screen at a time.) And within an application, it can do what it likes. With regards to editing, there are some common conventions that I absolutely hate: * Left and right keys, and backspace and delete keys, that don't regard the left and right ends of a line as hard stops; they just keep going. OK-ish for word processing, but not for line-oriented code. * Clicking on a box containing text and the whole thing being highlighted. Now you're on tenterhooks as the slightest move and everything disappears. You might be able able to press Ctrl Z to get it back (yes, the same Ctrl Z that's supposed to terminate applications!) but it's still highlighted. * Clicking backspace on a web page doing the same as the Back button. Now, backspace is used for editing text within forms. It's very annoying if, after half an hour filling in a form, somehow the current box loses the focus (the cursor), but you proceed to press backspace space several time before noticing. Like my first complaint, but in spades. * Under Windows, if you press Shift while Caps Lock is on, you get lower case letters. I've never, ever wanted to do this (probably no one else has). My own editor doesn't obey that convention: shift-A will always come out as 'A' whatever the caps lock setting. There are dozens more, yet you are surprised why sometimes I prefer doing things my own way? There are good reasons! (**I was in the audience of a Michael Palin interview a couple of weeks back. (You know, an actual Python!) Before he came on the audience was programmed to respond to the word 'individuals' by all saying 'Yes, we are all individuals!'. Apart from me, obviously.) -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 08/10/2017 19:10, Chris Angelico wrote: On Mon, Oct 9, 2017 at 3:50 AM, bartc wrote: You assume that since *you* have never needed to produce one lower-case letter in a block of upper-case, that "probably no one else has", and then you make it impossible to do that in your editor. Only when caps-lock is stuck on (then the feature may have be of some use at last). However my editor also makes it very easy to reverse or change case of existing text. The advantage of Shift working one-way is that it is guaranteed to give you a capital letter without you needing to check the caps-lock status or checking the screen to see that it was typed as capitals. That is 100 times more useful than the rare time you have to add a lower case letter in a sea of capitals and can't be bothered to turn off caps lock. I have wanted to produce a lower-case letter by holding Shift. I've read that other people have had exactly the same trouble. I don't believe that my pattern of typing English text is that different from most other people's, and I've ALWAYS found that 'feature' annoying, so from that I might infer that plenty of others do too. In fact, if I start off MS Word, with caps lock unknowingly on, and type Shifted-T, unshifted-H, unshifted-E, that will temporarily display 'tHE' before it gets auto-corrected to the intended 'The'. I wonder why it does that? According to you, people WANT to type tHE. BTW, all the typewriters I've used do exactly what I want. If caps lock is on (shift-lock there), then pressing Shift doesn't reverse it. So, what happened to existing practice there, typewriters hadn't been around long enough? > I have also used this behaviour to > detect and recognize faults of various sorts. Do you understand the > concept of debugging a system by getting more information, not less? I've no idea what you're talking about there. > Yep. Good reasons like that you're a moron. > Yeah, well, some people like to be standards-compliant, others like to > be irrelevant morons. I started to be angry when I saw these insults now I'm just rather depressed. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 09/10/2017 06:15, Gregory Ewing wrote: Grant Edwards wrote: Which took it from RSX-11. Or probably more specifically from FILES-11. I woldn't be surprised if the enineers at DEC got it from somewhere else before that. Quite possibly it goes back to the very earliest DEC OS that had files, whatever that was. The reason for it was that the file system only kept track of file sizes in blocks, not bytes, so some way was needed to mark the end of a text file part way through a block. Ctrl-Z was just code 26 or [what I've always called] ETX or end-of-text. I'd used DEC quite a bit (including rsx-11m) but only became aware of ETX when using CP/M. (Where it had a annoying habit, IIRC, of copying files in text mode so that it stopped at the first ETX byte.) And actually, until recently, I added ETX (followed by 0 for good measure) as a sentinel in a function reading a file into a block of memory (now I just use 0 for that purpose). But I don't consider that these internal uses, some of which are archaic, belong in a user interface. [Looking it up now, actual ETX is code 3, or Ctrl-C, and EOT is code 4. So how 26 - apparently code SUB, whatever that means - ended up being used to mark the end of text files, I don't know.] -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 09/10/2017 05:49, Chris Angelico wrote: Generally, my preferred editor is nano, since it lives within those requirements but still has a decent UI. It's not always available though, and it's useful to know how to manage without it. But even though you won't always be doing this sort of thing, it's definitely something that a *programming language designer* should be aware of. Basic networking is critical to any modern language. That's an odd opinion given that modern languages don't even want to have basic input and output as part of the language; they're offloaded to a library. And in your example, which I don't really understand, it seems more like the headache of the application. (Where a language allows elements of a program to be disseminated across a network, that's rather different, and an advanced feature that only some languages might have. Not all.) -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: on = style
On 09/10/2017 07:40, Abdur-Rahmaan Janhangeer wrote: hi just a quick question, why is my_pens = 4 my_pencils = 5 is preffered to my_pens = 4 my_pencils = 5 *referring to = symbol alignment I will sometimes line things up, if a block of assignments are related: red = 1 green = 2 blue= 3 There might sometimes be extra maintenance if you then add: turquoise = 4 and have to readjust the others, or you add: yellow= 201 and prefer the number should be aligned right-justified: red = 1 green = 2 blue = 3 turquoise = 4 yellow= 201 but it's not hard. Although it might not be worth doing until a program is finished. Compare to: red = 1 green = 2 blue = 3 turquoise = 4 yellow = 201 -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: The "loop and a half"
On 09/10/2017 01:37, boB Stepp wrote: On Sun, Oct 8, 2017 at 5:36 AM, bartc wrote: And Bart, when large numbers of technical experts in their fields have spent many hours/months/years, yea, even several decades, developing these software systems, why do you think that you, all by yourself, know better? In some fields, then yes! The problem with experts is that they do like to pile layer upon layer, plus another layer to deal with the complexity created by the previous layers! For example, I write compilers, including a C compiler. But I couldn't start compiling the CPython sources (with any compiler actually), because the first step was running a 30,000-line configure script, for Linux. I work on Windows. However there is now a solution using VS2015. There was a thread on this subject in May 2017, and there I recounted my attempts at using VS2015 to build CPython. A copy of that I've put here: https://pastebin.com/raw/V76WP1Ha (Raw text so no adverts.) CPython is 250K lines I think; a fast compiler ought to be able to deal with a program like that in one second (depending on how many files it's split up into). Now look at that link. Experts Building big cumbersome, complicated systems is easy. Making them small and simple is harder. Can you not see how frustrating this is for people who have spent good chunks of their lives trying to do the best they can on these software systems? Only if they concede I might have a point. I haven't seen much sign of that! I doubt anyone using *nix systems, which are massively popular, is going to start feeling insecure due to the opinions of one guy. You say (in a bit I see I've snipped), that non *nix people read these forums. But my experience is that the majority of people who post (in c.l.p and comp.lang.c) are using *nix. It's unbalanced. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 11/10/2017 14:16, Marko Rauhamaa wrote: C++'s main problem is that it tries to solve the wrong problem. A C++ compiler seeks to make sure your program doesn't have bugs. That noble (but futile) goal makes it painful to program in C++. It's painful to program for lots of reasons, I don't think that is the main one. The ideas behind C++'s many features individually make perfectly good sense - on paper. Until you look at ghastly examples of C++ source code and it really hurts your eyes. Python and C don't try to protect you. In return, you get syntactic convenience that probably enhances the quality of your programs. Python, maybe. C syntax isn't as painful as C++ but I still have a lot of trouble with it. (Eg. the variable declaration 'char(*(*x[3])())[5]'. The name of the variable can be found lurking in that lot somewhere, but what's the type?) Not so convenient. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 11/10/2017 15:52, breamore...@gmail.com wrote: On Wednesday, October 11, 2017 at 3:14:51 PM UTC+1, bartc wrote: On 11/10/2017 14:16, Marko Rauhamaa wrote: Python and C don't try to protect you. In return, you get syntactic convenience that probably enhances the quality of your programs. Python, maybe. C syntax isn't as painful as C++ but I still have a lot of trouble with it. (Eg. the variable declaration 'char(*(*x[3])())[5]'. The name of the variable can be found lurking in that lot somewhere, but what's the type?) Not so convenient. https://cdecl.org/ tells me that your variable declaration is a syntax error so maybe not much of an example. Perhaps you didn't write or paste it properly. The site tells me that: char(*(*x[3])())[5] (with or without a trailing semicolon) means: declare x as array 3 of pointer to function returning pointer to array 5 of char (Example taken from page 122 of the C book "K&R2", in a section about writing a program to make sense of complex declarations.) Anyway that fact you either tripped up on typing it, or that you had to use a special tool to find out what it meant, sort of reinforces my point... -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 11/10/2017 15:36, Chris Angelico wrote: On Thu, Oct 12, 2017 at 1:14 AM, bartc wrote: Python, maybe. C syntax isn't as painful as C++ but I still have a lot of trouble with it. (Eg. the variable declaration 'char(*(*x[3])())[5]'. The name of the variable can be found lurking in that lot somewhere, but what's the type?) Not so convenient. People love showcasing stupid examples like that. But how often do you REALLY make declarations that complex? That's not technically strawmanning, since C syntax does indeed include that, but you're cherry-picking the most extreme example. Sure. Statistically most declarations are going to be things like 'int' or 'char*. But more complicated ones (usually not as bad as the example), crop up often enough to be a nuisance. I may see them more than others because I very often need to interface one of my languages with some API defined in C, and I need to exactly understand what the types are so that I can create compatible ones. Anyone else can just include the apposite headers and be done with it without needing to see what's inside. While on the subject of C syntax, here are some fun ambiguities: f(x);// call function with arg x, or declare x of type f? a*b; // multiply a by b, or declare b of type pointer to a? (a)*b// multiply a by b, or cast *b to type a? I understand that in C++, you also have things like this, but in spades. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 11/10/2017 17:16, Jonathan Cast wrote: On Wed, 2017-10-11 at 15:14 +0100, bartc wrote: On 11/10/2017 14:16, Marko Rauhamaa wrote: Python and C don't try to protect you. In return, you get syntactic convenience that probably enhances the quality of your programs. Python, maybe. C syntax isn't as painful as C++ but I still have a lot of trouble with it. (Eg. the variable declaration 'char(*(*x[3])())[5]'. The name of the variable can be found lurking in that lot somewhere, but what's the type?) Not so convenient. I believe the type of any variable in C is the same as its declaration, but with the variable name deleted. Yes, I think we got that... So: char (*(*[3])())[5] ..which doesn't help, and in fact makes things worse, as now you don't have a start point at which to start unravelling it. You have to do it from the inside out. That is, an array of 3 pointers to functions that return pointers to arrays of 5 characters. But you left out the dozen steps needed to get from that to this! Anyway if such a type can be more clearly expressed like this, why doesn't a language simply allow that, or near enough? Why does it need to be cryptic, or require an external tool to encode and decode (there is a reason that CDECL exists) or require the programmer to apply an algorithm? -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 11/10/2017 19:30, Chris Angelico wrote: On Thu, Oct 12, 2017 at 5:22 AM, Grant Edwards The easiest way to make stuff like that readable is to unroll them into a sequence of typedefs. But, a lot of people never really learn how to do that... The most complexity you'll usually see is a function that accepts/returns a pointer, and those generally should be typedef'd. But even if not, they're still not anything like as bad as the mythical examples that get touted as "why C is bad" or "why variable declarations are bad" or "why type declarations are bad". IME typedefs can make things worse, especially if used even for basic types. Then you spend your time tracing back typedefs to see what they mean (was it a char, or struct or what?). C can combine the abstruseness of its type declarations, overuse of macros, and overuse of #if/ifdef blocks to render a lot of code a complete nightmare to try and understand. Or debug. Or maintain. Or port. Or implement (if testing a compiler). I've looked at some of my generated C code, and here's one common example, not a complex type: tokenrec * (*)[] But I couldn't figure that out from the top of my head. Bear in mind this was in a parameter list that can change the meaning of []. I looked at the original source and that type is written like this: ref [] ref tokenrec 'ref' means 'pointer to', and it can also be written like this: pointer [] pointer tokenrec In English, 'pointer to array of pointer to tokenrec'. See how the source language corresponds almost exactly to the English, and both are written left to right. Now go back and look at the C version - where do you even start? Are those parentheses significant? (I've no idea.) The most complex of /my/ types to appear in generated C is probably this, used as a cast in this assignment: pcptr = (*(int64 * (**) (void))pcptr)(); (Original source is this: pcptr := ref ref function=>ref int64(pcptr)^^() In English, the cast is 'pointer to pointer to function returning pointer to int64'. The line includes two dereferences (^^) which /I think/ account for two of the "*" in the C version. Which * are dereferences, and which are part of the type, or indeed whether only one * is the dereference, I have absolutely no idea. Great language...) -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 11/10/2017 20:30, Chris Angelico wrote: On Thu, Oct 12, 2017 at 3:29 AM, Rhodri James wrote: On 11/10/17 15:36, Chris Angelico wrote: That's only really one level more complex than declarations I use fairly regularly (I am an embedded system programmer most of the time). On the other hand, I never actually do declare things in that way: typedef is your friend, and makes your C code much easier to read. I wouldn't consider embedded systems to be the most common kind of C coding out there, particularly when people compare against C++ (I don't remember ever hearing of anyone doing embedded work in C++, though I'm sure it does happen). Nevertheless, you're exactly right about the typedefs. Writing crazily complicated type declarations without typedefs is like writing massively nested list comprehensions without intermediate variables. Hey look, Python's terrible! Or maybe they're just non-idiomatic examples. Look at my last example posted a few minutes before this. You'd say the C needed typedefs. But in the original language, type declarations are clear enough that they don't need typedefs. The typedefs help to mitigate a problem in one language that doesn't exist in the other. Surely it's better to have neither the cryptic type nor the typedef. Everything would be much cleaner. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 11/10/2017 21:52, breamore...@gmail.com wrote: >> More importantly is the fact that due to your magnificent performance recently you have been promoted to be the General Manager of my Dream Team. Thanks, I guess. You can of course cement your place when you explain how, in your language, converting an invalid piece of user input, which should be an integer, is always converted to zero, and how you handle the inevitable divide by zero errors that will always, eventually, occur. You mean it shouldn't do what happens here (Py3): a = input("? ").split() x = int(a[0]) y = int(a[1]) print (x,y) print (x/y) and somebody enters '10 0' ? I don't think you can do much about that. However since that thread I've tweaked the way I do this, so that here [non-Python code]: print "? " readln a, b# read each as int, float or string println a/b# floating point divide this produces these a/b results for various inputs: 10 20 # 0.50 10,20 # 0.50 10skjhf 20 # error, divide string by int 17.9 2 # 8.95 10 # error, divide int by string ("") # (blank) error, divide string by string .1e10 1e5 # 1.00 ten twenty # error, divide string by string For throwaway programs, or for testing, or for trusted input, this is perfectly reasonable. For perfect error checking, you need to do a bit more work on either verifying input, or using more sophisticated parsing. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 11/10/2017 23:03, Gregory Ewing wrote: bartc wrote: tokenrec * (*)[] > the original source and that type is written like this: ref [] ref tokenrec The idiomatic way to write that type in C would be tokenrec ** The original has an extra pointer so idiomatic C might be more: tokenrec *** But this still defines a different type, namely: pointer to pointer to pointer to tokenrec not: pointer to array of pointer to tokenrec If you want to lose all array information, and really don't care if you're dealing with a pointer, or an array (and don't mind changing how such a value is passed, and how it is accessed) then this is fine for you. You just have to access a 'tokenrec ***args' parameter as ***args. Or **args[i]. Or *args[i][j]. **(args[i]). Or ***args. Or args[i][j][k]. Yes, any combination will work! Only one will be correct. In the original source, it can only be accessed one way - the correct way. Using the non-idiomatic 'tokenrec *(*)[]' in C imposes some extra constraints, but doesn't do the full job. However my complaint was about the syntax; the type system of C is another subject. (How I ended up talking about C in this group I don't know. But yesterday I mentioned Python in the C group, so ...) -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 12/10/2017 09:23, Christian Gollwitzer wrote: Am 12.10.17 um 01:15 schrieb Stefan Ram: Define a function »g« with a parameter »x« of type »int«, so that this function »g« returns a pointer to another function. This other function has a parameter of type »char« and returns a double value. Ok /Without/ a typedef. And WHY would you do that? Typedefs do not cost money. They cost extra effort in devising them, writing them, and having to trace them when someone else is reading the code. Try this: typedef double (*countdown_rate_func) (char letter); countdown_rate_func select_rate_func(int level); // I've substituted 'x' by 'level' // and 'g' by 'select_rate_func' for clarity Those substitutions don't help, as I'm trying to see how well it matches the original spec. If I change them back (not easy to tell which bit is whic): typedef double (*F) (char); F g(int x); No, sorry, it doesn't really cut it. It is still cryptic. It doesn't help that C doesn't use a keyword to introduce a function (like, say, 'function'). You still need to know that double (*F) is a pointer to a function returning double, and that double *F is a function returning a pointer to a double. It also introduces this arbitrary name 'F', which if you encounter it in source, means you know have to search for this typedef. (And the requirement was a definition not a declaration.) I claim that the above is quite clear, it declares a function in a Countdown game engine, which, depending on the level, returns a different function to rate the weight of the individual letters. Renaming 'g' and 'x' to be more meaningful, and introducing a parameter name that is not needed, is a different subject. And actually I found your 'countdown_rate_func' and 'select_rate_func' names confusing (the two are actually of different rank, but both end in _func). Your exercise results in the line noise double (*g(int x))(char) (thanks to Ben for doing the exercise), which is not extremely bad, but still does tell nothing about the intent of that line. Using any sane syntax for type (AND function) declarations, writing Stefan's function is straightforward. For example**: function g(int x) => ref function(char)real = return nil end Just transcribed exactly as written (I could have used 'x:int' maybe). If I translate this to C, then it gives me: static double (*g(int32 x)) (char) { return 0; } It's a piece of cake. It shows how important the right syntax can be; you write what you have to write, then get on with the rest of the coding. Oh, and it's also very easy to read. It's a mystery to me actually; there is zero cost to devising, implementing and using the most helpful syntax, and actually there are real benefits. So why use something so bizarre? (**This is my actual language but as someone guessed, this part is derived from Algol68.) -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 12/10/2017 06:39, Grant Edwards wrote: On 2017-10-11, Gregory Ewing wrote: Neil Cerutti wrote: I dig const qualifiers, even though I'm comletely fine with their absence from Python. Out of curiosity, do you have any insights into why you like them in C++, if you don't miss them in Python? I like them in C because it allows the linker to place them in ROM with the code. It also _sometimes_ provides useful diagnostics when you pass a pointer to something which shouldn't be modified to something that is going to try to modify it. It's one of these features that on paper sound good. In practice, it's just useless extra clutter. It's used to: (1) Define named constants; except (in C) they can't be used like constant expressions, you can take their addresses, and accidentally or maliciously change their values. (2) Declare data to be put into read-only memory as you say. That's fine with a 'const int * p', but what about a 'int * const p'? (Or is it the other way around? Whatever...). Or any other hybrid type where some elements are const and some aren't. (3) Pass data that is supposed to be read-only, but with any even slightly complex type, it won't work (the head of a linked list for example, where the node elements need to be writeable). It gives a false sense of security. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 12/10/2017 11:39, Stefan Ram wrote: bartc writes: (1) Define named constants; except (in C) they can't be used like constant expressions, you can take their addresses, and accidentally or maliciously change their values. When I think of »const«, I do not think of ROM. »const« makes code more readable, because it conveys the intentions of the author and simplifies the mental variable model of the reader. »const« helps to find inadvertend modifications. void f( const int i ){ if( i = 4 )putchar( 'x' ); } That's two undesirable language features: (1) Having to use 'const' in front of every simple parameter, so that 'const' now dominates every program; (2) Mixing up '=' and '=='. You're saying it's OK to use both as they sort of cancel each other out! (Other languages solve the =/== problem by either not allowing assignment within an expression, or by using a symbol for it that isn't so easily mistaken for equality.) -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 12/10/2017 16:18, Marko Rauhamaa wrote: Grant Edwards : Using const with strings in C with amateurish libraries is a headache because _some_people_ will write their declarations so as to require pointers to mutable strings even when they have no intention of mutating them. Those people should be hunted down and slapped with a herring until they understand the error of their ways. Hear, hear. The standard library is much better about that. You lost me there. Seriously, though. C strings are not the most problematic issue. How about other structures? What about: long ftell(FILE *stream); int fgetpos(FILE *stream, fpos_t *pos); Should that be "const FILE *stream"? In general, C record definitions (opaque structs) that represent encapsulated classes don't take a "const" in any context. They *could* but that isn't the tradition. For example, here's a random function from the Linux kernel: static bool tcp_fastopen_cookie_gen(struct request_sock *req, struct sk_buff *syn, struct tcp_fastopen_cookie *foc) { if (req->rsk_ops->family == AF_INET) { const struct iphdr *iph = ip_hdr(syn); __be32 path[4] = { iph->saddr, iph->daddr, 0, 0 }; return __tcp_fastopen_cookie_gen(path, foc); } #if IS_ENABLED(CONFIG_IPV6) if (req->rsk_ops->family == AF_INET6) { const struct ipv6hdr *ip6h = ipv6_hdr(syn); struct tcp_fastopen_cookie tmp; if (__tcp_fastopen_cookie_gen(&ip6h->saddr, &tmp)) { struct in6_addr *buf = (struct in6_addr *) tmp.val; int i; for (i = 0; i < 4; i++) buf->s6_addr32[i] ^= ip6h->daddr.s6_addr32[i]; return __tcp_fastopen_cookie_gen(buf, foc); } } #endif return false; } If you took a working C program and removed all the consts, it would still work. I don't think the language would miss them if they were to disappear. It is anyway too crude a technique for the things people like to apply it to. > > Note how both "req" and "syn" could well be declared as "const" > pointers but are not. const pointer, or pointer to const struct? Or both? With a const struct, you are stopped from directly modifying elements, but if an element is a pointer, nothing stops you writing to what the pointer points to, unless that has a const target too. And then you've going to have problems doing normal updates. This constness just insinuates itself everywhere. -- bartc -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 13/10/2017 07:16, Gregory Ewing wrote: Steve D'Aprano wrote: On Fri, 13 Oct 2017 03:37 pm, Gregory Ewing wrote: If the compiler can tell where p is initially pointing, it could put the pointer in read-only memory. If it's read-only, how can the compiler write to it? (I come from the days when ROM was actual ROM, burned in at the factory.) So, the factory is allowed to write to it. Possibly it's writing data that came from... a compiler? A memory that couldn't be written to at all, ever, would be a bit useless! It's read-only in the same sense as a printed book; you can't change the marks already on the page. I've programmed EPROMS. Neither the C language nor the concept of 'const' attributes for data ever came into it. While executable code doesn't really need it. It is simply not a necessity. You just arranged for writeable portions of memory to be at different locations than that containing the code and fixed data. Sometimes it was only data. 'const' is anyway the wrong sort of attribute to use, as I've already explained. For example: const int A = rand(); // inside a function A is written to multiple times at runtime. It can't go into actual read-only memory like a ROM. And it might have trouble going into a memory page with read-only attributes. 'const' tries to do too many things, most of them poorly, although it does a very good job at adding clutter. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 13/10/2017 12:49, Peter J. Holzer wrote: On 2017-10-13 10:37, Steve D'Aprano wrote: or written by a dedicated hardware device: https://en.wikipedia.org/wiki/Programmable_read-only_memory And in this case there will be a tool which will read the object file and send the contents of the read-only sections to the device which writes the ((E)E)PROM. First time I did this was with a home-made programmer directly connected to a keyboard. I had to press the right key to generate the 7-bit pattern I wanted (I can't remember what I did about the 8th bit), burn it into the current location then step the address counter to the next. No mistakes were tolerated. It worked. And finally, the most frequent case: The OS will will read the executable into RAM, mark those pages from the read-only sections as read-only in the page table and start it. Or as I did it, on a home-made computer with two banks of 16KB RAM, one bank had the editor, compiler and source code, the other the generated code. Just before running it, I would flip a switch to write-protect the first bank in case something went wrong. (I didn't have floppies only slow, unreliable tape, so things had to be memory-resident as much as possible.) And, actually, even now machines don't have that much control: you create a large table of data at runtime, but it is still in writeable memory, and accidental or malicious code could write into it. No matter that the C source may have had a few consts sprinkled about. (It's bit like those incredibly annoying anti-piracy messages and videos you get on DVDS. No actual pirate would ever see them, only honest people who have no intention of copying!) Even if data is actually in write-protected memory, attempts to write to it will cause a crash. On my home-made system, they just did nothing. Much more graceful. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 13/10/2017 14:16, Chris Angelico wrote: On Sat, Oct 14, 2017 at 12:00 AM, bartc wrote: Even if data is actually in write-protected memory, attempts to write to it will cause a crash. On my home-made system, they just did nothing. Much more graceful. The novice thinks his job is to stop the program from crashing. The expert knows that a crash is actually far FAR better than silently doing nothing. For a novice, seeing 'Segmentation fault (core dumped)' is better? There, a friendlier, more useful error message is called for ('writing into read-only memory' is a good start). But the idea of having memory which is permanently or temporarily write-protected is also useful: you can do what you like to it and it won't change, and such an attempt wouldn't necessarily be an error. For example, you're drawing a series of points or connected lines into a window to form a shape. But part of the shape is outside the window. So you fix the logic and try again. You don't want it to crash if you gave it coordinates (corresponding to memory beyond the window limits) outside the boundaries. It's just a technique, like greying out certain menu options - clicking them will do nothing, but you won't get an error message and you don't want to allow them anyway, risking more serious consequences. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 13/10/2017 14:22, Marko Rauhamaa wrote: BTW, the original reason for C requiring declarations in the first place wasn't readability. Rather, it was to make compilation possible in the first place. It is interesting that C++ and Java have taken steps to remove such information where the compiler can know or guess it from the context. The compiler might be able to, after analysing 100,000 lines of prior code and applying complex algorithms. But what about the poor user reading the code? Or can that now only be done with the aid or a browser that analyses 100,000 lines and applies that same algorithm? We mustn't forget the person writing the code, who may have a certain type in mind for X, but their (I nearly said 'his') analysis may not match the compiler's. Annotations can be useful. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 13/10/2017 15:59, Julien Salort wrote: Le 12/10/2017 à 17:57, bartc a écrit : With a const struct, you are stopped from directly modifying elements, but if an element is a pointer, nothing stops you writing to what the pointer points to, unless that has a const target too. And then you've going to have problems doing normal updates. This constness just insinuates itself everywhere. That is not very different from the mutable/immutable concept in Python, is it ? A tuple is immutable, but if it contains a mutable object, nothing prevents you from mutating it. Does it mean you think the mutable/immutable concept of Python is flawed? When you put it like that, then yes! But it depends on how you define the value of a tuple. If that is a recursive definition that includes all nested object levels, then it would be harder to keep the whole thing constant. If you look only one level deep, then it can be fully immutable (never mind that some elements could be functions that will give a different result each time they are evaluated). -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 13/10/2017 16:33, Steve D'Aprano wrote: On Sat, 14 Oct 2017 01:30 am, Chris Angelico wrote: For a novice, seeing 'Segmentation fault (core dumped)' is better? Better than silently doing nothing? YES. Absolutely it is. Chris, you forget that for Bart, his user-base is only himself. If he programs his home-made system to silently ignore writes to write-protected memory, that counts as the "...unless explicitly silenced" part of "Errors should never pass silently...". If that means his software is riddled with bugs, it will affect only himself, and no novices will be harmed. You're making light of a scheme that was extremely effective in a computer system with otherwise unprotected memory, that could write anywhere, including over all the code and over the OS. Without that write protection, what would have happened? Either it would go completely haywire, or hang, or could subtly change resident programs in dangerous ways. Or I could put that switch in then I could be CERTAIN that essential programs and data were untouched no matter what happened. So if it worked well then without needing to abort and report a message, why can't a scheme like that work now? BTW, when you're developing a new bit of hardware or software, and you're not part of team, then the user-base is normally just yourself. Nothing wrong with that, but you seem to like belittling people with such comments. What was the userbase when GvR started Python? -- Bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: Lies in education [was Re: The "loop and a half"]
On 13/10/2017 15:39, Steve D'Aprano wrote: On Fri, 13 Oct 2017 11:54 pm, Gregory Ewing wrote: Neil Cerutti wrote: I can tell at a glance if a parameter is expected to be modifiable just by looking at the function signature. The question is why doesn't anyone feel the need to be able to do that for Python functions? Whether a function modifies things passed to it is just as important to know in Python as it is in C. Lots of people would like Python to have a "freeze" function that can make immutable objects, it is a moderately common feature request. Some people (myself included) would like a "const" declaration that gives us names that can only be bound to once: const spam = "NOBODY expects the Spanish Inquisition!!!" # Okay spam = "foo" # Error. Presumably also: const def f: const class c: const import i I don't mind if that is a runtime error, although a compile time error would be nicer. This would be of most use when the byte-code compiler (assuming there is one) knows about them. But many will be inside imported modules whose contents, AIUI, are not visible to the byte-code compiler. And then they would be accessed as: i.spam So this would be a const attribute. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: An endless loop
On 15/10/2017 03:10, Stefan Ram wrote: I made an error I made a thousand times before. I had programmed an endless loop. But never did I see before so clear why it's called an endless loop. (Tested in IDLE.) from turtle import * reset(); reset(); shape( 'turtle' ); showturtle() def poly( n, length ): i = 0 while i < n: forward( length ) left( 360/n ) poly( 5, 100 ) done() I assume you're talking about the while-loop (because on my machine, it hangs just using 'from turtle...' or 'import turtle'). That looks to be a repeat-N-times loop. There isn't a dedicated statement for that, the closest Python feature would be 'for i in range(n)' with i a dummy loop variable. -- bartc -- https://mail.python.org/mailman/listinfo/python-list
Re: An endless loop
On 15/10/2017 12:20, Chris Angelico wrote: On Sun, Oct 15, 2017 at 9:15 PM, bartc wrote: I assume you're talking about the while-loop (because on my machine, it hangs just using 'from turtle...' or 'import turtle'). (Machine was screwed up I think, as I had to restart it shortly after for other reasons. When the turtle graphics worked.) That looks to be a repeat-N-times loop. There isn't a dedicated statement for that, the closest Python feature would be 'for i in range(n)' with i a dummy loop variable. You can use that or "for _ in range(n)" as a pretty effective form of that loop. I've never had a problem with it. Python doesn't need another type of loop. I could understand that sentiment if there were already dozens. But I believe there's only, what, two loop types? To implement a number of basic looping requirements which, if not that numerous, are somewhat more than two. Not exactly taxing the grey matter which already has those extra loop types in mind, and has to find a way to express them in terms of only two. -- bartc -- https://mail.python.org/mailman/listinfo/python-list