Disclaimer: The majority of the programmers that I have known in real life that have a significant (and very vocal) dislike of Python's whitespace requirements have all written code like that above (this is my from-memory reproduction of actual code that one of them wrote). Python sucks because it's "restricting" them from being "expressive" with their code.
Sadly, you can write code just like that in Python. I don't know what that perl snippet does, my caches have long since flushed ;) -- but here's a Python snippet that's relatively dense:
def foo(y): return lambda x: {str(i) : '_{}'.format(i**y) for i in range(x)}
Yep. An order of magnitude more time is spent reading and maintaining a line of code than is spent writing it. Readability adds a tiny amount of time to the writing, but makes reading and maintainability so much better.
Was just reviewing colleague's code with them the other day. Hit some blocks like this (not quite as offensive, but tackling a bit in one line), and hell if they knew what was going on in their own code.
I've never posted about whitespace sensitivity before today, so maybe I don't fit in the group you're pointing at, but I don't like Python's whitespace sensitivity either.
Not because I want to write everything on one line, but because it's an extra step when trying to understand what code does.
For instance, a piece of code is misbehaving, not being called as part of the block it visually appears part of. In a bracket/paren language I can highlight one bracket and my editor shows which one matches. In Python I have to figure out what the indentation is built from, spaces or tabs, and make sure there's no ambiguity there.
We have developers here that are claiming they wrote things in Python for their PHD, and yet when I look at their code in any language there are tabs and spaces mixed in the same line, with inconsistent indentation. Multiple people have tried to express the issue or teach ways to deal with it, to no avail.
The fact of the matter is that whitespace is by definition invisible, and that makes it hard for people to grasp its importance. Basing control flow on invisible characters is asking for trouble.
To quote PEP 20:
> Explicit is better than implicit.
Brackets are explicit, whitespace is implicit. You only can see whitespace by the gaps between visible characters, and then you have to guess. Is it an actual U+0020 like you see 99% of the time? Is it an nbsp? It it a tab that happens to stop after the width of a space? You don't know until you encounter an error or turn on whitespace rendering.
Was it copied and pasted from www.python-help-7575.com, which uses a platform that favors punctuation spaces? Was it copied from a site that didn't wrap their code in <code> or <pre>? (I see this all the time in comment systems on programming blogs) Should we claim that copying and pasting code in a beginner targeted language is something you do at your own risk?
> In Python I have to figure out what the indentation is built from, spaces or tabs, and make sure there's no ambiguity there.
The following program throws a TabError in Python 3:
def demo():
print("1 tab")
print("8 spaces")
It does work in Python 2, but I'm pretty sure the majority of developers have 4 space wide tabs by now, meaning they won't be able to mix tabs and spaces in Python 2 code either.
EDIT: So Hacker News has code blocks, but doesn't strip the indentation that is required to introduce them. So you'll have to lead the 2 leading spaces in each line if you want to try this out for yourself.
> So Hacker News has code blocks, but doesn't strip the indentation that is required to introduce them. So you'll have to lead the 2 leading spaces in each line if you want to try this out for yourself.
Your example is good, but the technical issues experienced in posting your example are perfect.
Alternative syntax for short one liner functions (e.g. As recently added to C#, always in scala) can reduce a lot of this friction without sacrificing formatting guidelines. However, I'm not sure if it's in python's philosophy to explore such things.
It has a prototype that says it accepts a list of arguments (this is the default in perl though).
Prototypes are mostly for giving hints to the compiler on how to unambiguously parse calls to your function later. For an anonymous sub, it's pointless because you assign its value to a variable, and then brackets are required when calling it.
return
It returns the result of the map (this default in perl is to return the result of the last expression & everything is an expression though)
map
same as python map(code, list)
{ "@{[ <some stuff> ]}" }
This is a particular perl goof for interpolating array lookups into a string. Usually, perl's sigils let variables be interpolated without any issue, but since we're using $_[0] to use the first element of the @_ array, it's ambiguous with $_ . '[0]'.
The @{} dereferences the contents of the braces as an array, and [] creates a new arrayref. The arrayref has one element, and perl's default stringification of an array (join them all with no separator) means that it… iterpolates the thing inside the @{[]} into the surrounding string.
This is pointless though, since it's the only thing in the string. The author might have been trying to give a string context to force stringification of the thing, but the dot operator already provides that context.
$_[0] . $_
This is a string of the first element of … hmm. Not of the currently-mapped element (that's $_). $_[0] refers to the first element of @_. This makes a new value which is the concatenation of the first element with the current element.
@$_
This is a short way of writing @{ $_ }: dereference the arrayref that's stored in $_. But $_ is not set anywhere, so I assume this is a typo of @_
I would have written this as:
my $prefixer = sub { my($prefix , @rest) = @_; return map { $prefix.$_ } @_ };
And it would work like this:
say $prefixer->('Hi_', 1, 'str', 7);
> 'Hi_Hi_Hi_1Hi_strHi_7'
If I follow correctly, the equivalent in K would be
{,/(*t),/:t:$x}
Flatten (,/) the first element of the list (*t) joined with each element of the list (a,/:b), where t is the input x cast to a list of strings (t:$x). Curly braces make the expression an anonymous function, and since no argument names are specified explicitly the name x is the single input argument.