On Sunday, June 2, 2013 1:58:30 PM UTC-5, Steven D'Aprano wrote: > On Sun, 02 Jun 2013 10:04:00 -0700, Rick Johnson wrote:
Oh Steven, you've really outdone yourself this time with the theatrics. I hope you scored some "cool points" with your minions. Heck, you almost had me convinced until i slapped myself and realized your whole argument is just pure BS. For the sake of the lemmings, i must dissect your BS and expose it's methane emitting innards for all to smell. > > Many > > languages provide a function, method, or statement by which users can > > write easily to stdout, and Python is no exception with it's own "print" > > function. However, whilst writing to stdout via "print" is slightly less > > verbose than calling the "write" method of "sys.stdout", we don't really > > gain much from this function except a few keystrokes... is this ALL > > print should be? A mere syntactical sugar? > > Perhaps you should read the docs before asking rhetorical questions, > because the actual answer is, No, print is not mere syntactical sugar > saving a few keystrokes. > [...] And perhaps you should read a dictionary and obtain (at minimum) a primary school level education in English before making such foolish statements, because, OBVIOUSLY you don't know the definition of "syntactical sugar"... shall i educate you? ############################################################ # Wikipedia: "syntactic sugar" # ############################################################ # In computer science, syntactic sugar is syntax within a # # programming language that is designed to make things # # easier to read or to express. It makes the language # # "sweeter" for human use: things can be expressed more # # clearly, more concisely, or in an alternative style that # # some may prefer[...] # ############################################################ The print function is the very definition of a "syntactic sugar". For example: print("some sting") is much more readable than: sys.stdout.write("some string"+"\n") or: sys.stderr.write("some string"+"\n") or: streamFoo.write("blah") But wait, there's more! ############################################################ # Wikipedia: "syntactic sugar" (continued) # ############################################################ # [...]Specifically, a construct in a language is called # # syntactic sugar if it can be removed from the language # # without any effect on what the language can do: # # functionality and expressive power will remain the same. # ############################################################ Again, the removal of a print function (or print statement) will not prevent users from calling the write method on sys.stdout or sys.stderr (or ANY "stream object" for that matter!) The only mistake i made was to specify stdout.write specifically instead of generally referring to the print function as a sugar for "stream.write()". > > I've found that many subtle bugs are caused by not limiting the inputs > > to sane values (or types). And with Python's duct typing > [...] > > and implicit > > casting to Boolean, you end up with all sorts of misleading things > > happening! Maybe you're testing for truth values and get a string > > instead; which screws everything up!!! > Only if you're a lousy programmer who doesn't understand Python's truth > model. I understand the Python truth model quite well, i just don't happen to like it. Implicit conversion to Boolean breaks the law of "least astonishment". Many times you'll get a result (or an input) that you expect to be a Boolean, but instead is a string. A good example of poor coding is "dialog box return values". Take your standard yes/no/cancel dialog, i would expect it to return True|False|None respectively, HOWEVER, some *idiot* decided to return the strings 'yes'|'no'|'cancel'. If you tried to "bool test" a string (In a properly designed language that does NOT support implicit Boolean conversion) you would get an error if you tried this: py> string = " " py> if string: ... do_something() ERROR: Cannot convert string to Boolean! However, with Python's implicit conversion to Boolean, the same conditional will ALWAYS be True: because any string that is not the null string is True (as far as Python is concerned). This is an example of Python devs breaking TWO Zens at once: "explicit is better than implicit" "errors should NEVER pass silently" And even though Python does not raise an error, it should! > > A "wise programmer" may think he's solved the problem by writing a > > function called "debugprint" that looks like this: > > > def debugprint(*args): > > if DEBUG == True: > > print(*args) > No no no, that's not how you do it. It should be: > if DEBUG == True == True: > Wait, no, I got that wrong. It should be: > if DEBUG == True == True == True: > Hang on, I've nearly got it! > if DEBUG == True == True == True == True: > Or, you could program like a professional, and say: > if DEBUG: Obviously you don't appreciate the value of "explicit enough". if VALUE: is not explicit enough, however if bool(VALUE) or at least: if VALUE == True is "explicit enough". Whereas: if VALUE == True == True is just superflous. But that's just one example. What about this: if lst: I don't like that because it's too implict. What exactly about the list are we wanting to test? Do we want to know if we have list object or a None object, OR, do we want to know if we have a list object AND the list has members? I prefer to be explicit at the cost of a few keystrokes: if len(lst) > 0: Covers the "has members" test and: if lst is not None covers the "existence" test. I know Python allows me to be implicit here, however, i am choosing to be explicit for the sake of anyone who will read my code in the future but also for myself, because being explicit when testing for truth can catch subtle bugs. Consider the following: What if the symbol `value` is expected to be a list, however, somehow it accidentally got reassigned to another type. If i choose to be implicit and use: "if value", the code could silently work for a type i did not intend, therefore the program could go on for quite some time before failing suddenly on attribute error, or whatever. However, if i choose to be explicit and use: "if len(VALUE) > 0: then the code will fail when it should: at the comparison line. Because any object that does not provide a __len__ method would cause Python to raise NameError. By being "explicit enough" i will inject readability and safety into my code base. (that's twice you've been schooled in one reply BTW!) > By the way, why is DEBUG a constant? Doesn't that defeat the purpose? Hmm, I agree!. You're actually correct here. We should not be reassigning constants should we? (<--rhetorical) In correcting me you've exposed yet another design flaw with Python. Sadly Python DOES allow reassignment of CONSTANTS. > > * But even if you are willing to cope with all the "switch- > > on-and-off" nonsense, are you willing to have you code slowed by > > numerous calls to a dead function containing a comparison that will > > always be false? > And of course you have profiled your application, and determined that the > bottleneck in performance is the calls to debugprint, because otherwise > you are wasting your time and ours with premature optimization. > Life is hard. Sometimes you have to choose between performance and > debugging. Only if your language does not provide a proper debugprint function or provide the tools to create a proper debug print function. I detest true global variables, however, there are some legitimate reasons for true globals in every language. This "debugprint" problem is one of those reasons. > > This > > realization has brought me to the conclusion that Python (and other > > languages) need a "scoped print function". What is a "scoped print > > function" anyway? Well what i am proposing is that Python include the > > following "debug switches" in the language: > > > ------------------------------ > > Switch: "__GLOBALDEBUG__" > > ------------------------------ > > Global switching allows a programmer to instruct the interpreter to > > IGNORE all print functions or to EVALUATE all print functions by > > assigning a Boolean value of True or False respectively to the global > > switch (Note: global switch always defaults to True!). > If you really care about this premature optimization, you can do this: > if __debug__: > print("whatever") That's hideous! Two lines of code to make a single debug message, are you joking? I realize Python will allow me to place the entire statement on one line, however i refuse to do that also. I am very strict about my block structure and styles, and even the consistent inconsistency of the great GvR will not sway me away from adherence to my consistent readable style. > You then globally disable these print calls by running Python with the -O > switch. > > Any script that includes the assignment "__GLOBALDEBUG__ = False" will > > disable ALL debug print messages across the entire interpreter > > namespace. In effect, all print statements will be treated as comments > > and ignored by the interpreter. No dead functions will be called and > > no false comparisons will be made! > > > (Note: __GLOBALDEBUG__ should not be available in any local namespace > > but accessed only form the topmost namespace. Something like: > > __main__.__GLOBALDEBUG__ = Boolean > Python does not work like that. Perhaps you should learn how to program > in Python before telling us how it should be improved? And perhaps you should listen to diverse ideas and be open to change instead of clinging to your guns and religion. > > ------------------------------ > > Switch: "__LOCALDEBUG__" > > ------------------------------ > > Local switching allows a programmer to turn on (or off) debug messages > > in the module it was declared. Not sure if this should be more > > specific than modules; like classes, blocks, or functions??? Of course > > this declaration will be overridden by any global switch. > So, it will be utterly useless then, since __LOCALDEBUG__ has no effect, > and __GLOBALDEBUG__ overrides it. Great. Of course global debug overrides local debug, what's the purpose of global switching if it cannot override local switching? "__GLOBALDEBUG__ = False" would disables ALL debug messages EVERYWHERE. Yes, you are correct on this issue. It would be the same as setting a command line switch. However, you misunderstand __LOCALDEBUG__. When global debugging is "on" "__LOCALDEBUG__ = False" will disable debug messages ONLY in the module for which it was declared. -- http://mail.python.org/mailman/listinfo/python-list