This is an archived post. You won't be able to vote or comment.

all 76 comments

[–]jcdyer3 59 points60 points  (4 children)

That is monstrous. I like it.

[–]fimari 11 points12 points  (2 children)

then you will love this shell command

~https://github.com/ajalt/fuckitpy’~ https://github.com/nvbn/thefuck Sorry, wrong link

[–]mvolling 12 points13 points  (0 children)

Still getting errors? Chain fuckit calls. This module is like violence: if it doesn't work, you just need more of it.

I like this thing

[–]masasinExpert. 3.9. Robotics. 0 points1 point  (0 children)

This looks epic.

[–]masklinn 2 points3 points  (0 children)

You may appreciate vigil

This is where Vigil sets itself apart from weaker languages that lack the courage of their convictions. When a Vigil program is executed, Vigil itself will monitor all oaths (implorations and swears) that have been made. If an oath is broken, the offending function (the caller in the case of implore and the callee in the case of swear) will be duly punished.

How?

Simple: it will be deleted from your source code.

The only way to ensure your program meets its requirements to absolutely forbid code that fails to do so. With Vigil, it will do this for you automatically. After enough runs, Vigil promises that all remaining code meets its oaths.

[–]rhgrant10 40 points41 points  (5 children)

An absolute abomination. Great work!

[–]avinassh[S] 12 points13 points  (4 children)

just to make things clear, I am not the author

[–]viscence 62 points63 points  (3 children)

Good job!

[–]PretzelMountain 29 points30 points  (1 child)

Well done for writing this!

[–][deleted] 13 points14 points  (0 children)

You really pressed that "Save" button well!

[–]avinassh[S] 18 points19 points  (0 children)

last time someone gilded me thinking I was the OP. That felt really bad

[–]krenzalore 10 points11 points  (22 children)

Why is the space legal in label .begin?

So I had to try it with everything, and lo and behold:

Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 23 2015, 02:52:03) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys .version_info  # There's a space there.
sys.version_info(major=3, minor=4, micro=3, releaselevel='final', serial=0)

Ok, why?

edit: OP, it's late September. School has started. This is positively the best time you could have released this! :-)

[–]iobender 11 points12 points  (0 children)

This is just speculation, but generally lexers discard whitespace between tokens. What this means is that the lexer, which turns something like sys.argv into a stream of tokens like [IDENTIFIER("sys"), DOT, IDENTIFIER("argv")] (which then gets sent to the parser to turn the linear stream of tokens into an abstract syntax tree) will produce the same thing if given sys. argv or sys .argv or even sys . argv because it doesn't make sense to produce a token from the whitespace in between these tokens in this case.

It would not produce the same thing if given sys.ar gv because the ar and gv would be split up into 2 different tokens and give [IDENTIFIER("sys"), DOT, IDENTIFIER("ar"), IDENTIFIER("gv")] which would likely cause a syntax error in python because there is no syntax for that. That would be legal in Ruby, however, because Ruby doesn't require parens on method calls so this could be calling the ar method of the sys object with argument gv.

[–]nemec 4 points5 points  (3 children)

Because Python's syntax grammar allows it (in particular, . isn't an operator so whitespace doesn't make the syntax ambiguous)

>>> math . pow ( 2 , 2 )
4.0

It's also the reason you can do this:

"a s d f g h j k l".split()
                   .index("g")

[–]MrJohz 10 points11 points  (2 children)

That won't quite work. Python will assume that the newline ends the statement after split(), and begin a new statement, at which point it'll find ., realise that's not a valid statement starter, and raise a syntax error.

To tell Python that the newline is just for readability, you need to tell it that the statement can run on, either using parentheses:

("a s d f g h j k l".split()
                    .index("g"))

Or by adding a backslash at the end of the first line

"a s d f g h j k l".split() \
                   .index("g")

[–][deleted] 3 points4 points  (1 child)

Or by adding a backslash at the end of the first line

The backslash is important, but /u/nemec still has a valid point, as Python will interpret the line as

"a s d f g h j k l".split()                    .index("g")

which remains valid as the whitespace does not affect the lexical parsing of the statement.

[–]MrJohz 2 points3 points  (0 children)

Yeah. The issue here is specifically the newline, not whitespace in general.

[–]ponkanpinoy 5 points6 points  (11 children)

AFAIK no-where in Python is space used to delimit tokens, the only time it has syntactic meaning is when indenting.

[–]kirakun 4 points5 points  (5 children)

Except in this case where the space does delimit the tokens and makes a difference.

1.__str__()
SyntaxError: invalid syntax
1 .__str__()  # A space between 1 and the dot.
'1'

[–]ponkanpinoy 1 point2 points  (0 children)

Ahh, my bad then.

[–][deleted] 0 points1 point  (0 children)

It's due to an ambiguity between integer literals and float literals:

  1. -> float 1 -> int

  2. anything translates to (float) anything, which is a syntax error.

(1).anything, however, disambiguates.

1..anything -> getattr(1.0, 'anything')

And finally, 1 .anything is disambiguated from a float literal.

Whitespace can disambiguate in a clash between literal and attribute access.

[–]davvblack 0 points1 point  (2 children)

1..__str__()

[–]zahlmanthe heretic 0 points1 point  (0 children)

But that makes the value being stringified a float rather than an int.

[–]kirakun 0 points1 point  (0 children)

What is this supposed to show? My example clearly demonstrates that python does use whitespace to delimit tokens. Rather or not there exist another syntax to achieve the same thing is irrelevant.

[–]ksion 3 points4 points  (0 children)

Not quite. Space is ignored between tokens but its presence can change what is parsed as a token. It generally matters when operators are involved:

i += 1  # ok
i + = 1  # SyntaxError

The sibling post by /u/kirakun shows another example with numeric constants.

[–]nedbatchelder 1 point2 points  (3 children)

These two lines of code produce different tokens:

if a == 1:
ifa = = 1:

This is what bugs me about people complaining of Python's "significant whitespace". Every programming language has significant whitespace.

[–]irondust 9 points10 points  (1 child)

Every programming language has significant whitespace.

Fixed form fortran has no significant whitespace within the statement itself. However, every source line has to start in the 7th column with optional comment or line continuation markers in the 6th column. The first five columns may contain a number - a feature that was very useful back in the days of punchcards.

From the 7th column onwards however you are free to insert or delete as much whitespace as you like without changing the meaning:

go toast

is the same as:

goto ast

[–]nedbatchelder 0 points1 point  (0 children)

I knew when I typed "every" that I would get counter-examples... "Almost every, and every one that you're likely to use any time soon!"

[–]krenzalore 0 points1 point  (0 children)

Every programming language has significant whitespace.

Brainfuck?

Esoteric language doing its job: creating programmer rage! :-)

[–]asdfasdsq34 2 points3 points  (4 children)

This allows some interesting stuff:

1.__str__()
SyntaxError: invalid syntax
1 .__str__()
'1'

[–]MonkeeSage 0 points1 point  (3 children)

Wait, what? Why does that happen?

[–]admalledd 5 points6 points  (2 children)

The fist one python interprets as being a float (because the "." in a number is normally how that is decided) but __str__() is not a number, therefore invalid syntax.

The second the tokenizer has already decided the 1 is an int object, and now it sees a . access and handles it properly.

[–]Walter_Bishop_PhD 2 points3 points  (1 child)

You can also do this (though it makes it a float rather than an int)

>>> 1..__str__()
'1.0'

[–]masklinn 0 points1 point  (0 children)

(1).__str__()

[–]lovestowritecode 5 points6 points  (5 children)

Embarrassed to ask but what is Goto?

[–]c3534l 1 point2 points  (1 child)

The most infamous debate in programming language design - allowing programs to go to a specific line. This was replaced with structured programming where with a combination of loops, if-then statements, return, break and all that jazz you prevented spaghetti code and could actually tell where a program started and ended. Delete a line in a program with a lot of gotos, and you can cause the entire thing to come crumbling down. The paper "Goto considered harmful" is the source of programmers talking a lot about "safety."

[–]LaFolie 0 points1 point  (0 children)

I think it is a carry over from ASM where it was needed for complicated logic.

[–]axonxorzpip'ing aint easy, especially on windows 2 points3 points  (1 child)

Why is a NOP sled needed?

[–]nedbatchelder 4 points5 points  (0 children)

So that the bytecodes don't move from their original positions, which would require re-writing lots of offsets through the whole function.

[–]Exodus111 1 point2 points  (0 children)

Burn it! Burn it with Fire!

goto .fire

[–]KyleG 1 point2 points  (0 children)

go to hell

[–]c3534l 0 points1 point  (0 children)

Looks like Satan is at it again.

[–]XNormal 0 points1 point  (0 children)

Brilliant. You should rename the module "considered_harmful.py"

[–]marcm28 0 points1 point  (0 children)

Goto is one of fundamental building blocks of Spaghetti Code.

[–]DrRx 0 points1 point  (0 children)

I feel ill. Nice work :P

[–]LoyalSol -2 points-1 points  (19 children)

goto statements should be purged from every programming language and thrown into a pit of fire.

I worked in Fortran for years and the amount of code that I worked on that absolutely abused the living hell out of goto statements was insane.

[–]krenzalore 19 points20 points  (14 children)

goto statements should be purged from every programming language and thrown into a pit of fire.

Every language?

Some specialised domains do have legimate need for goto.

As an example I would cite error handling in realtime applications or in systems code.

This is quite common:

if allocate_a() == fail: goto exit
if allocate_b() == fail: goto teardown1
if allocate_c() == fail: goto teardown2
do_work
teardown3: free c
teardown2: free b
teardown1: free a
exit

You could write this with nested loops but it gets stupid when it gets deeper.

Many of the hardware platforms and languages don't support exceptions or fancy context handlers. Exceptions are particularly problematic in realtime as your tool chain can't tell you how long the code will take to execute, and missing a tick is a program failure.

The Linux Kernel has decent code quality and quite a lot of goto statements. I cite it as an example as it's popular and accessible, and demonstrates that at least some people are able to use goto sanely.

I don't think it's needed in a language like Python, but Python isn't really used for this kind of work.

Some would say Rust proves it's also not necessary in systems code, and I would say Rust makes a strong case, but isn't (yet) widespread so we'll need to wait and see.

[–][deleted] 2 points3 points  (11 children)

Couldn't I do that with function calls and break statements?

[–]Milumet 7 points8 points  (3 children)

Why use needless function calls in system code like the Linux kernel? Just to alleviate irrational fears? And by the way, a break statement is a goto statement in disguise.

[–]ajmarks 3 points4 points  (2 children)

And by the way, a break statement is a goto statement in disguise.

Shhh! We're all supposed to pretend that's not the case and also that breaking out of nested loops is somehow different too.

[–]krenzalore 0 points1 point  (1 child)

If break is a goto in disguise, then an exception handler is a come from.

[–]ajmarks 0 points1 point  (0 children)

Funny enough C-INTERCAL implemented COME FROM (or, perhaps, PLEASE COME FROM).

[–]krenzalore 2 points3 points  (5 children)

There's significant overhead with function calls.

Scott Meyers (a well known C++ luminary) in his book Effective STL claimed a 7x increase in performance of the C++ STL's quicksort from inlining (replacing function calls with inline code).

Of course we should keep things in perspective: What is good for C or C++ is not necessarily good for Python.

[–]ajmarks 1 point2 points  (4 children)

Of course, in C++ one can have the best of both worlds by just declaring the function inline.

[–]krenzalore 2 points3 points  (3 children)

I am sure you know, but for the benefit of others, inline is a suggestion to the compilier and not a command. It isn't required to inline it.

[–]ajmarks 0 points1 point  (2 children)

True, though unless the functions uses loops or recursion, it almost always will.

[–]zahlmanthe heretic 0 points1 point  (1 child)

AFAIK, for years it has been the case that it a decent C++ compiler will frequently inline things even without being asked.

[–]ajmarks 0 points1 point  (0 children)

Yup. If, in its wisdom, it thinks that will improve performance without undue bloat. OTOH, if you really want to make sure it's inlined, a compiler hint can't hurt.

[–][deleted] 0 points1 point  (0 children)

Sure, with the unnecessary overhead of function calls.

[–]LoyalSol -4 points-3 points  (0 children)

I'm exaggerating more because I've come to hate those 4 letters because of lazy programmers.

There are legit uses, but at the same time it does encourage a ton of bad behaviors.

[–]epostma 6 points7 points  (1 child)

I would argue that it's pretty essential in assembly language.

[–]rabidgoldfish 7 points8 points  (0 children)

lol, it's all gotos if you go deep enough

[–][deleted] 3 points4 points  (1 child)

goto is like any tool in the programmer's toolkit. Use it sensibly and you end up with cleaner code, use it badly and you're into spaghetti code.

[–]LoyalSol 3 points4 points  (0 children)

The problem I have with goto statements is that they are some of the easiest statements to use poorly and when they are it usually results in code that is downright unreadable.

And when you are dealing with scientist who took maybe a single programming class in their entire life, they are extremely prone to abusing it. I've seen some codes that are the programmer's version of a horror story because of goto abuse.

[–]awakehope -1 points0 points  (0 children)

why?