tyggerjai: (Default)
[personal profile] tyggerjai
This post is brought to you by recent excursions in The Lacuna Expanse. You can probably skip this post and go straight there, unless you're a perl weenie. If you *are* a perl weenie, you may enjoy TLE. Not only is their API published and well documented, they encourage scripting and bot writing. You could, legitimately, write a bot to run your entire empire, and never log in again, and they'd be cool with that.


Anyway.
I have never been a fan of perl's map function.

There. I've said it. It confuses me, and makes me feel stupid. Partly, of course, this is self-fulfilling - I don't like it, so I don't use it, so I don't understand it when I see it, so I fear it, so I don't like it ....

Working in Lisp a bit recently has, oddly, increased both my understanding *and* my dislike. So I'd like to be educated.

Dear perl hackers. Does map give me *anything* other than syntactic sugar, or perhaps the opposite?

Part of this stems from recently getting up to speed with Python, which has Only One Way To Do It, which means, when you see It, you know exactly what It Is Doing. I've been reading a lot of other people's perl lately, some of it quite old and crufty, and I'm struck by the tendency of perl hackers to be clever. And that's nice, and all, but sometimes it's not. And oh, I know, the community is diverse and all, but it does my head in to go to "help" communities that emphasise clear and readable code, and then say "And you know that annoying 4 line foreach loop? You can replace it with a single line of incomprehensible punctuation using map, in case carriage return is expensive on your machine!".

Which said, I may be missing something. Should I be using map, and if so, why? What does it give me other than shorter code? Do you find it just as easy to parse as a nice foreach loop, or can you do things with it that you just couldn't do with foreach?

On a related note, I think this has something to do with my innate distrust of "$_". I know, I know, "$_" is a defining characteristic of the language, but still. It's *clever*, and I don't always like clever. So map not only generally has $_ scattered throughout, but by definition, when reading it, you get to $_ before you have *any* idea what actual set the map is working on.

This, I suppose, is why I no longer code for a living, but I wonder how much of it really does just have to do with perl.


(no subject)

Date: 2010-11-10 02:09 pm (UTC)
thorfinn: <user name="seedy_girl"> and <user name="thorfinn"> (Default)
From: [personal profile] thorfinn
If you must code in Perl, get Damian Conway's Perl Best Practices book, and Perl::Critic. Really.

Perl has a zillion ways to do it, PBP gives you one, and good reasons why you should do that one.

As for map? There are good reasons why a functional idiom is neater than a procedural one, and if you follow the PBP rules, it's even quite readable.

map itself is relatively boring on its own, but in combination with the other "functions for list data": grep, join, reverse, and sort, it can be a fairly huge amount neater, more concise *and* more readable than the procedural equivalent.

ETA: You are right that perl hackers *do* have a tendency to be overly clever. Functional paradigm coding is not *necessarily* overly clever, but is often misused that way.
Edited (speling eror) Date: 2010-11-11 03:00 am (UTC)

(no subject)

Date: 2010-11-10 02:12 pm (UTC)
kareila: "PERL!" (perl)
From: [personal profile] kareila
I think you're right that a foreach loop is usually easier to read than a map, because it encourages use of whitespace, comments, and named variables instead of $_, plus it has the advantage of allowing complex operations on each step of the loop.

A more helpful way to think of map might be in the context of data pipes. It's common to see something like @newlist = map { ... } sort { ... } grep { ... } @oldlist. You can unfold the map and grep into a foreach, but not the sort, because it operates over the entire list, not each individual element.

Bug 3161 has a great example of what I would consider a "bad" (nonintuitive if not broken) foreach loop that I replaced with a map.

(no subject)

Date: 2010-11-10 02:38 pm (UTC)
thorfinn: <user name="seedy_girl"> and <user name="thorfinn"> (Default)
From: [personal profile] thorfinn
I don't like unfolding grep into a foreach. :-/ next has its uses, but it's such a hugely more verbose way of expressing the same thing, and looks less understandable to me.

That's actually one of my mild annoyances with Python - I can't conveniently express a filter in-line, unless there's a built in boolean function already that does the job I want.

I can certainly define my own boolean method right there, but I don't want to have to define and name a single use method when the method body code is itself smaller than the method name and definition. It's a minor negative consequence of a lack of braces and syntactically significant whitespace. Probably outweighed by a number of the other positive factors of that choice, but still, annoying.

(no subject)

Date: 2010-11-10 02:46 pm (UTC)
sophie: A cartoon-like representation of a girl standing on a hill, with brown hair, blue eyes, a flowery top, and blue skirt. ☀ (Default)
From: [personal profile] sophie
Despite what I said to you in that bug, I actually agree that foreach is more readable. I generally agree with [personal profile] tyggerjai; map is something I normally can't grok. I normally have to look it up each time I encounter it.

But, you know. I think there's kind of a pressure here to use map and such, since the rest of the code uses it.

(and yes, the foreach works with lexically scoped variables too)
Edited (Adding markup.) Date: 2010-11-10 02:47 pm (UTC)

(no subject)

Date: 2010-11-10 06:37 pm (UTC)
thorfinn: <user name="seedy_girl"> and <user name="thorfinn"> (Default)
From: [personal profile] thorfinn
Perl was written by a linguist, and explicitly designed to have the same usability as English.

I.e., you can just start speaking it, it will be horrendous, but it will work. Just don't expect to re-use it afterwards.

Writing really really good Perl is about as hard as writing really really good English. That is to say, *really fucking hard*.

This is why I keep banging on about Damian Conway's Perl Best Practices. It's the equivalent of the Oxford Dictionary plus a complete grammar and usage style guide like Fowler or Strunk&White. Then you have Perl::Tidy and Perl::Critic to implement those rules, which is the equivalent of your spellchecker and grammar checker *and* an editor looking over your shoulder at all times.

Perl Code written to comply with Conway's PBP is generally readable, no matter who wrote it and how damn "clever" or not they are trying to be. It may not be bug free, and the code may still raise the question of "why did you do that?", but you can always read the code and understand what it actually does.

(no subject)

Date: 2010-11-13 05:44 am (UTC)
From: [personal profile] morganjaffit
"Perl was written by a linguist, and explicitly designed to have the same usability as English."

It strikes me that there's no sane linguist on the planet who would ever design a language like English. It's a bad starting place for a whole bunch of reasons (not least of which is the aforementioned difficulty speaking it goodly).

(no subject)

Date: 2010-11-13 06:37 am (UTC)
From: (Anonymous)
There's a strong argument to be made that the success of English is precisely its ugly fuzziness and ease of entry level usage. The whole point is the lack of design consistency and ability to say things in a billion different ways...

As for designed languages, well, Esperanto worked out great! ;-)

(no subject)

Date: 2010-11-13 06:42 am (UTC)
thorfinn: <user name="seedy_girl"> and <user name="thorfinn"> (Default)
From: [personal profile] thorfinn
Bugger. The above comment was me.
Edited Date: 2010-11-13 06:42 am (UTC)

(no subject)

Date: 2010-11-13 07:09 am (UTC)
From: [personal profile] morganjaffit
"There's a strong argument to be made that the success of English is precisely its ugly fuzziness and ease of entry level usage. The whole point is the lack of design consistency and ability to say things in a billion different ways..."

I think it's the opposite, actually. Because English has been spread through colonial influence, it's become fuzzy and developed a low level entry case. Ie, English was shaped by it's spread, not spread due to its shape.

If you were developing a programming language, you could make the argument that this means its a good model due to having a decent amount of user testing. I wouldn't make a strong case that this makes sense for a programming language, though. Unless of course you happen to be a colonial power in a dominant position willing to force your code practices onto the nations you've dominated.

(no subject)

Date: 2010-11-13 08:38 am (UTC)
thorfinn: <user name="seedy_girl"> and <user name="thorfinn"> (Default)
From: [personal profile] thorfinn
Nah, English was all fucked up before they started conquering The Empire... Anglish, Romans, Saxons, Vikings, Normans... Half of Europe has landed in England and colonised it.

As for whether it's a good idea for a programming language? For a "proper" programming language, gah, no it's terrible. OTOH for cobbling some stuff together that mostly works without having to think too hard that you don't expect to have a long lifetime? It's great.

(no subject)

Date: 2010-11-13 10:33 am (UTC)
From: [personal profile] morganjaffit
I think that makes the point though, which is that language changes by movement, colonisation, and conquest - not that there's an innate property of English (fuzziness) that's responsible for its success and movement. Precisely why Esperanto has no success.

As for the times and places for different programming languages, well, I'll obviously defer to your thoughts there. Although their spread does have a lot the same properties - ie, they generally tend to move with colonisation rather than necessarily being "better" or more appropriate. You need to be good enough, and have a vector of propagation and colonisation.

(no subject)

Date: 2010-11-13 12:16 pm (UTC)
thorfinn: <user name="seedy_girl"> and <user name="thorfinn"> (Default)
From: [personal profile] thorfinn
I think the linguistics argument is that English became more flexible due to those successive waves of conquest, and because of that flexibility it was easier for people to actually use it.

I'm fairly sure the argument is that with many other empire-conquest languages, you either get creoles between the empire-lingo and local-lingo which then develop into their own "proper" language, or you actually wind up with both in common usage and they remain distinct... whereas with English it's been a little more common to wind up with heavy English usage by the conquered including loss of local language quite quickly. It's all messy though and all reverse reasoning... not anything anyone can really prove. :-) But yes, conquest/colonisation definitely plays a big part in the spread.

I do agree, many programming languages are definitely popular "just because everyone uses them" for a particular field, not necessarily because that one is better than the available alternatives. Enterprise Java, PHP Web "programming", unix shell scripting, Flash web games... Yech. :-) All have much better alternatives, but they've got a lot of entrenched usage and so they'll all be around a good long while.

(no subject)

Date: 2010-11-10 02:49 pm (UTC)
sophie: A cartoon-like representation of a girl standing on a hill, with brown hair, blue eyes, a flowery top, and blue skirt. ☀ (Default)
From: [personal profile] sophie
I hate $_ with a passion. Hate hate hate.

I never use it in my code unless I'm forced to.

(for some of my other thoughts on this post, see my reply to [personal profile] kareila's comment above.)
Edited (Oops, hit Update too soon.) Date: 2010-11-10 02:50 pm (UTC)

(no subject)

Date: 2010-11-11 02:23 am (UTC)
thorfinn: <user name="seedy_girl"> and <user name="thorfinn"> (Default)
From: [personal profile] thorfinn
Yeah, one of my personal rules of thumb is that if I take the variable name length, and apply it as the power of 2, that is the maximum number of lines of code that that name should be "in scope" for. :-)

For a 1 letter variable, that means two 78 character lines, maximum... so if I need $_ for more lines than that, it's probably bad, and I should do it some other way. :-)
Edited (First person, not second. :-)) Date: 2010-11-11 02:25 am (UTC)

(no subject)

Date: 2010-11-10 09:24 pm (UTC)
From: [personal profile] jeamland
If you want to see Python's equivalent to that, look up the list comprehension. It's syntactic sugar that lets you apply a map and a filter in a one-liner. The nice thing about it is that making them overly complicated is quite difficult since you'd have to break them across lines and the resulting ugliness tends to make you not want to. The general idea is:

result = [func(x) for x in stuff if test(x)]

Where func(x) and test(x) are statements. x is your $_ equivalent except you get to choose its name and stuff is your source iterable. Python 3.something gives you dictcomps which are the same thing over dictionary keys.

(no subject)

Date: 2010-11-10 10:09 pm (UTC)
From: [personal profile] jeamland
That's kinda the point I was getting at in terms of it getting ugly really fast if you try to do too much. If, however, you're trying to do a quick transform on a list it's nice and expressive. The kinds of things I use it for are:

strings = [str(x) for x in maybe_strings]
less_than_5 = [x for x in numbers if x < 5]
numbers_if_not_none = [int(x) for x in things if x is not None]

and the like. Anything that's more complicated than that generally gets done in a for loop.

(no subject)

Date: 2010-11-11 02:11 am (UTC)
thorfinn: <user name="seedy_girl"> and <user name="thorfinn"> (Default)
From: [personal profile] thorfinn
It's always the programmer's fault. ;-)

(no subject)

Date: 2010-11-11 03:21 am (UTC)
sophie: A cartoon-like representation of a girl standing on a hill, with brown hair, blue eyes, a flowery top, and blue skirt. ☀ (Default)
From: [personal profile] sophie
Yeah, you can do that sort of thing in Perl too, it's just not as pretty. For example, your second example would be this one-liner in Perl:

@less_than_5 = grep { $_ < 5 } @numbers;

The third example is more difficult if you *really* want a one-liner, since you're modifying the array as well:

@numbers_if_not_none = map { int($_) } grep { defined($_) } @things;

I wouldn't write that second one as a one-liner, myself. I would do:

my @numbers_if_not_none = ();
foreach my $number (@things) {
  if (defined($number)) { push(@numbers_if_not_none, int($number)); }
}


Some other people might write the line in the loop as:

push(@numbers_if_not_none, int($number)) if defined($number);

...but I personally prefer putting the if first.
Edited (Forcing the indent. (And, you know, actually using the right code.)) Date: 2010-11-11 03:22 am (UTC)

(no subject)

Date: 2010-11-12 10:33 am (UTC)
afuna: Cat under a blanket. Text: "Cats are just little people with Fur and Fangs" (Default)
From: [personal profile] afuna
$_ in Perl is kinda like "this" in JavaScript -- easy to write, harder to read *g* (Also easy to get wrong, though "this" may be a bit harder just because of nasty cross browser issues, ugh)

Profile

tyggerjai

Прекрасное Далеко

Слышу голос из Прекрасного Далека
Он зовет меня в прекрасные края
Слышу голос голос спрашивает строго
А сегодня что для завтра сделал я

Expand Cut Tags

No cut tags