The Other Worlds Shrine

Your place for discussion about RPGs, gaming, music, movies, anime, computers, sports, and any other stuff we care to talk about... 

  • Perl, I'm leaving you.

  • Somehow, we still tolerate each other. Eventually this will be the only forum left.
Somehow, we still tolerate each other. Eventually this will be the only forum left.
 #119629  by Kupek
 Wed Mar 26, 2008 9:59 am
Not that I did too much in it, but Perl was my scripting language of choice. I've now replaced it with Python. I find it easier to concisely express what I want, and what I produce is far more readable. My latest task was generating Gnuplot graphs for a bunch of .csv data files in a directory after doing a simple average on the data. It turned out much cleaner than I expected:
Code: Select all
#! /usr/bin/env python

import os, csv, Numeric, Gnuplot

def pow2_range(start, finish):
        for i in range(start, finish):
                yield 2**i

def set_options(graph, points):
        graph('set datafile separator ","')
        graph('set xlabel "unroll factor"')
        graph('set ylabel "execution time (s)"')

        graph('set xtics (' + points + ')')
        graph('set xrange [0:130]')

def main():

        points = ','.join(['"%s" %s' % (str(i), str(i)) for i in pow2_range(1,8)])
        colors = ['-1', '1', '3', '-1', '1', '3']

        multi = Gnuplot.Gnuplot()
        set_options(multi, points)

        for color, file in zip(colors, sorted([f for f in os.listdir('.') if f.endswith('.csv') and not f.endswith('_avg.csv')])):

                graph = Gnuplot.Gnuplot()
                graph.title(file.replace('.csv', '').replace('_', ' '))

                set_options(graph, points)

                avg_nm = file.replace('.csv', '_avg.csv')
                avg_f = open(avg_nm, 'wb')
                avg = csv.writer(avg_f)
                for row in csv.reader(open(file, 'rb')):
                        avg.writerow([str(int(row[0])), str(Numeric.average([float(i) for i in row[1:]]))])
                avg_f.flush()

                graph.plot(Gnuplot.File(avg_nm, with='linespoints'))
                graph.hardcopy(file.replace('.csv', '.ps'), color=True)

                multi.replot(Gnuplot.File(avg_nm, with='linespoints lt ' + color))

        multi.hardcopy('all.ps', color=True)

if __name__ == "__main__":
        main()
Further than that, I'll actually consider it over C++ for my next significant programming project. (I'm tempted to port what I have over to Python, as I know some of it would be easier to express. I don't because I've yet to find a parsing framework in Python that I like, I am nominally concerned about runtime performance, and it doesn't seem like a wise use of my time.)

As an intro to the language, I found Dive Into Python helpful.

Yes, I realize this is of interest to about two or three of you.

 #119633  by Lox
 Wed Mar 26, 2008 10:21 am
I was actually considering learning Perl because there are many uses here at work (parsing binary files and things like that). But maybe I'll take a look at Python instead.

 #119659  by Andrew, Killer Bee
 Wed Mar 26, 2008 7:11 pm
Oh shit yeah! Python is my language of choice. It's beautiful.

 #119660  by RentCavalier
 Wed Mar 26, 2008 8:41 pm
You guys are such NERDS.

 #119661  by Andrew, Killer Bee
 Wed Mar 26, 2008 8:56 pm
What are you, 12?

Oh wait, that's right. You are.

 #119662  by Kupek
 Wed Mar 26, 2008 9:12 pm
RentCavalier wrote:You guys are such NERDS.
Keep that in mind when I post pictures from my BJJ tournament.

 #119663  by SineSwiper
 Wed Mar 26, 2008 9:17 pm
Image

Okay, first of all, just based on the code you submitted, Python does not use sigils, which makes Perl infinitely cleaner than Python. (Or to quote Larry Wall: "Things that are different should look different.") Second, CPAN kicks the shit out of PYPI, and the level of support on CPAN is outstanding.

I also find the lack of braces to support code blocks kinda disturbing, but then again, maybe I'm just used to semi-colon languages and gave up that "one command per line" limitation when I gave up BASIC.

Lox, don't listen to him. Perl is easier and more versatile to use than Python.

Here's an example of how to do a lot with a language and only need a little bit of code:
Code: Select all
#!/usr/bin/perl
##############################################################################
# Check Opt-Out Requests                                                     #
# E-mail: Brendan Byrd <byrd.b@someserver.com>                               #
##############################################################################

$username = "work-sensitive";
$password = "work-sensitive";

$sendmail_loc = "/usr/sbin/sendmail";
$datapath = "/var/apache2/htdocs/data";

##############################################################################

use Net::POP3;
if ($pop = Net::POP3->new('mail.someserver.com', Timeout => 20)) {
   if ($pop->login($username, $password) > 0) {
      my $msgnums = $pop->list;
      if (scalar keys %$msgnums) {
         # Load deny list
         open(DENY,"$datapath/denyemail-optout.txt") || die "Cannot open denyemail-optout.txt!";
         while (my $line = <DENY>) { $DENY{lc($1)} = 1 if ($line =~ /([\w\.\-]+\@someserver.com)/i); }
         close(DENY);
         
         # Check messages
         foreach my $msgnum (keys %$msgnums) {
            my $msg = $pop->top($msgnum, 0);
            my ($from_mail, $subject_mail, $subject, $email);
            for (my $j = 0; $j < @$msg; $j++) {
               if    ($$msg[$j] =~ /^From:.*?([\w\.\-]+\@someserver.com)/i) { $from_mail = $1; }
               elsif ($$msg[$j] =~ /^Subject: (Remove Me:\s*([\w\.\-]+\@someserver.com))$/i) { $subject = $1; $subject_mail = $2; }
               elsif ($$msg[$j] =~ /^Subject: (.+)$/i) { $subject = $1; }
               # spam/loop prevention
               elsif ($$msg[$j] =~ /^Auto-Submitted:/i) { undef $from_mail; undef $subject_mail; last; }
               elsif ($$msg[$j] =~ /^Precedence:/i)     { undef $from_mail; undef $subject_mail; last; }
            }

            $email = ($subject_mail ? lc($subject_mail) : lc($from_mail));
            #print "$email\t$subject\n";
            unless ($email =~ /mailer-daemon|^owner-|-request\@/i || $DENY{$email} || $SENDMAIL{$email} || !$email) {
               #print "--- Good!\n";
               $SENDMAIL{$email} = $subject;

               # Add to opt-out list
               open(OPTOUT, ">>$datapath/denyemail-optout.txt") || exit;
               print OPTOUT "$email\n";
               close(OPTOUT);
            }
            
            $pop->delete($msgnum);
         }
      }
   }

   $pop->quit;
}

# Send acknowledgement e-mails
foreach my $email (keys %SENDMAIL) {
   if (-x $sendmail_loc) { open(MAIL, "|$sendmail_loc -t") || &tech_error("Can't use $sendmail_loc!"); }
   else                  { next; }

   print MAIL "Message-ID: <optout.".time.".$email>\n";
   print MAIL "From: Some Company Update Opt-Out <optout\@someserver.com>\n";
   print MAIL "Reply-To: Some Company Customer Care <somecompany\@someserver.com>\n";
   print MAIL "X-Mailer: Some Company Update Opt-Out\n";
   print MAIL "MIME-Version: 1.0\n";
   print MAIL "Auto-Submitted: auto-replied\n";
   print MAIL "To: $email\n";
   print MAIL "Organization: Some Company\n";
   print MAIL "Subject: Re: $SENDMAIL{$email}\n";
   print MAIL "Content-Type: text/plain; charset=US-ASCII\n\n";

   print MAIL "Your request to be removed from future email notifications from Some Company\n";
   print MAIL "has been received and acknowledged.  If you have any questions about your service,\n";
   print MAIL "please send us an e-mail at somecompany\@someserver.com.  Thank you for choosing\n";
   print MAIL "Some Company as your high speed Internet provider!\n\n";
   
   print MAIL "--\n";
   print MAIL "Some Company\n";
   print MAIL "http://www.someserver.com/\n";
   close(MAIL);
}

 #119664  by Kupek
 Wed Mar 26, 2008 9:52 pm
Let's not turn this into a pissing contest. I prefer Python over Perl, but I'm not saying you have to. Understood? Good.

Okay. I don't want to have to explicitly say something that the language/compiler/interpreter/runtime can figure out. I use C++ extensively, so trust me when I say I write a lot of scaffolding code. Why should I have to explicitly say "this is a scalar" or "this is a hash" every time I use an object? I find having to do so muddies up the code. That shouldn't be my job, it's should be the language's job. Python is dynamically typed, but object coercion is not as loose as Perl. I actually find this cleaner; there are no subtle bugs from accidentally using scalar vs. list semantics. If the runtime expects a list, and it gets a scalar, error.

The support at the level of CPAN isn't really a concern for me.

I know what you mean about the braces and semi-colons, but it's actually one of the reasons I picked up Python. Braces and semi-colons are not necessary to figure out what you mean. Visually, they get in the way of what I want to actually say. I don't see it as a limitation, but freeing, because I waste less vertical space with end braces.

Last, the object-oriented support in Python is much, much cleaner than in Perl. Perl's object system is basically a hack. I'm actually not a huge OO person, but when I do want to define classes and create objects, I don't want to feel like I'm doing work the language should.

 #119667  by SineSwiper
 Wed Mar 26, 2008 10:39 pm
Kupek wrote:Let's not turn this into a pissing contest. I prefer Python over Perl, but I'm not saying you have to. Understood? Good.
Yeah, yeah, it's just that I've been an avid supporter of Perl for the 10 years that I've used it and I think if people want to try to pick up a first or second language, they should use Perl. Used to C++, Java, or JavaScript? Fine, try out Python.
Kupek wrote:Okay. I don't want to have to explicitly say something that the language/compiler/interpreter/runtime can figure out. I use C++ extensively, so trust me when I say I write a lot of scaffolding code. Why should I have to explicitly say "this is a scalar" or "this is a hash" every time I use an object? I find having to do so muddies up the code. That shouldn't be my job, it's should be the language's job. Python is dynamically typed, but object coercion is not as loose as Perl. I actually find this cleaner; there are no subtle bugs from accidentally using scalar vs. list semantics. If the runtime expects a list, and it gets a scalar, error.
Yeah, but if you're trying to pass a scalar and it needs a list, it SHOULD error. After all, you obviously didn't understand what the procedure required and you acknowledged that fact by putting in sigil for a scalar. In a non-sigil language, it might have accepted the variable, so you spend hours trying to figure out why it's printing only a single item or a reference to an item, etc. And if you actual want to convert a scalar to a list, it's blindly simple: ($scalar) instead of $scalar.

Let's also not forget that you can still have contexts in Perl:
Code: Select all
my @sort_list = sort @list;
my $length_of_list = @list;
Of course, the biggest reason for sigils is READABILITY! I want to know what type of variable it is when I look at it directly. I DO NOT want to keep going back to the top of the program just to see the declaration over and over again. (And don't get me started on variable naming schemes that add some lowercare type declaration prefix. That's an ugly bandaid to a gaping wound.)
Kupek wrote:The support at the level of CPAN isn't really a concern for me.
It should. You used four modules for the script above. One of the projects I'm going to be working on involves reading emails, parsing out the attachments, and posting Remedy tickets. I'm glad that I don't have to worry about building the following from stratch: POP3 interface, MIME reader, PDF reader, Excel reader, Word reader, HTTP interface, and ARS interface. Can you get all of that from PYPI? It doesn't even have the ability to look at the documentation at a glance, and that's a must to figure out if the module is any good or not.
Kupek wrote:I know what you mean about the braces and semi-colons, but it's actually one of the reasons I picked up Python. Braces and semi-colons are not necessary to figure out what you mean. Visually, they get in the way of what I want to actually say. I don't see it as a limitation, but freeing, because I waste less vertical space with end braces.
Yeah, but one wrong move with indentation and you're fucked. Seems like it's easy to get lost without some symbolic structure.

Plus, I can do a lot with adding more readability to a statement:
Code: Select all
if ($aaa == 45 || $bbb eq 'asd' || @ccc > 5 ||
    $ddd == 99 || $eee eq 'jkl' || @fff > 10)
{
   my $ggg;
   $ggg = 'colon'     if ($qqq =~ /\:/);
   $ggg = 'semicolon' if ($qqq =~ /\;/);
   $ggg = 'five'      if ($qqq =~ /5/);
   $ggg = 'at-sign'   if ($qqq =~ /\@/);
}
Whitespace should be my way of adding readability into the program, not a functional requirement to the language.
Kupek wrote:Last, the object-oriented support in Python is much, much cleaner than in Perl. Perl's object system is basically a hack. I'm actually not a huge OO person, but when I do want to define classes and create objects, I don't want to feel like I'm doing work the language should.
Granted, Perl wasn't designed for OO at first, but I think the solution they had was pretty good. Instead of obj.method, it's $obj->method. It's a few more symbols, but it works out.

 #119672  by Andrew, Killer Bee
 Wed Mar 26, 2008 10:56 pm
Sigils are syntactic noise.
SineSwiper wrote:
Code: Select all
my @sort_list = sort @list;
my $length_of_list = @list;
Are you telling me you can't immediately tell the types of the variables above without the sigils? In Python, this would be:
Code: Select all
sorted_list = sorted (our_list)
list_length = len (our_list)
OH GOD WHAT COULD THOSE VARIABLES BE

Sane names imply type. If they don't, you're doing something wrong.
SineSwiper wrote:Whitespace should be my way of adding readability into the program, not a functional requirement to the language.
Who doesn't indent anyway? Forcing it just means you can remove that much more syntactic noise from your code.
SineSwiper wrote:Granted, Perl wasn't designed for OO at first, but I think the solution they had was pretty good. Instead of obj.method, it's $obj->method. It's a few more symbols, but it works out.
Dude, an object model is more than just the syntactic means by which you access a method or attribute. In Python, everything is an object, and the object model is completely consistent. Perl's object model was hacked in and you can tell.

 #119677  by SineSwiper
 Wed Mar 26, 2008 11:06 pm
Andrew, Killer Bee wrote:Sane names imply type. If they don't, you're doing something wrong.
So, you're saying that you like putting the word "_list" and "_array" and "_hash" on the end of your variables?

 #119678  by Andrew, Killer Bee
 Wed Mar 26, 2008 11:17 pm
No. I'm saying that given sane names and context I should be able to discern a variable's type. For example, I could guess that a variable called "books" might be a list containing Book instances. In that case the @ prefix or _list suffix is redundant.

 #119685  by Kupek
 Thu Mar 27, 2008 1:09 am
Frankly, I think Python is perhaps the best "first language" for someone to learn programming in because there's very little magic - and by magic I mean necessary scaffolding that beginners have to write, but require concepts they don't yet understand. The only modern language with less scaffolding is Scheme, which I also think is a good first language.

I encountered this when I taught intro to programming labs that used Java. One of my students asked me what <tt>public static void main(String args[])</tt> meant, and I was about to give a correct answer, along with an explanation of what each piece meant and how it fit into the Java language when I caught myself. This student doesn't need to understand that now, and it would probably confuse the issue. I basically told the student they'd eventually learn what all of it meant, but at the moment, think of it as the magic you have to tell the compiler to get your programs to work.

Sigils reduce readability for me and many people. I guess we'll just have to disagree on that issue, because I can't see it any other way. The way Perl denotes objects gives very limited information, anyway. Sure, it's a scalar, but what kind? I'm just as happy removing that entirely. Also, keep in mind most of my coding time is spent in C/C++ where I have to explicitly state everything, so I have plenty of experience with statically typed languages. (And C++0x is getting an <tt>auto</tt> keyword to mean "make this variable's type the same as the expression assigned to it," which would save me a bunch of typing.)

As for the module support, I meant what I saw worked good enough for me to get what I wanted done, and I bet that will remain true. I also mean that I have an interest in the language itself. I have an interest in programming languages for their own sake, and in that context, I find Python very attractive.

Again, with white space, I write oodles of C/C++. And I've done it long enough to conclude that braces just get in my way.

Oh god, I wasn't talking about the syntax for OO in Perl. I meant how it's actually implemented. Inheritance is through an ISA array? I have to bless my objects? That's me doing work the language should do for me.

 #119686  by Ishamael
 Thu Mar 27, 2008 2:53 am
Python beats Perl simply due to Python's better support for OO concepts. It's really not a competition. If you could somehow duplicate the same programmer, and have one copy star with Python and the other start with Perl, the one beginning with Python will be much more productive much faster. Simpler OO lets you build larger, more complicated systems more easily than no-OO or crappy OO (Perl).

Again, it's not that you can't do OO in Perl - it's just that the learning curve is steeper compared to other languages.

Perl's main advantage is CPAN. There's a HUUUUGE library of supported goodies in virtually every area you can think of sitting on CPAN for free. It's hard to explain how awesome CPAN is. But CPAN is "just" a library at the end of the day. The problem is that Perl the Language has stagnated for probably about 10 years now while the likes of Ruby and Python have blown by it. And it doesn't seem like Perl 6 is ever going to be done.

 #119687  by SineSwiper
 Thu Mar 27, 2008 8:23 am
OO just gets in my way sometimes. I don't like using it unless I'm dealing with modules. I seem to write something faster in Perl than, say, JavaScript. I'm used to both languages, but I find that I have to refer to the DOM Inspector a lot just to make sure that I'm referencing an object correctly.
Kupek wrote:Sigils reduce readability for me and many people. I guess we'll just have to disagree on that issue, because I can't see it any other way. The way Perl denotes objects gives very limited information, anyway. Sure, it's a scalar, but what kind?
Well, it could be a string, a number, or a reference. And you can refer to it as a string, a number, or a reference without actually having to declare it as such. I hate long lists of declaractions. (Something I dislike with "use strict", but it does help with variable misspellings and keeps the lists to a minimum.)

I'm sorry you feel that way about sigils, but I guess I can't really argue over what seems to be a personal preference.
Kupek wrote:I'm just as happy removing that entirely. Also, keep in mind most of my coding time is spent in C/C++ where I have to explicitly state everything, so I have plenty of experience with statically typed languages.
Which is why I say that maybe Python suits you better, since you learned C/C++ FIRST and then a higher-level language like Python.

I still think that Perl is the best first or second language. It was designed by a linguist and it shows. The language seems to flow more like English than Python does. Consider one of your lines:
Code: Select all
for color, file in zip(colors, sorted([f for f in os.listdir('.') if f.endswith('.csv') and not f.endswith('_avg.csv')])): 
PC LOAD LETTER? What the fuck does that mean? "Sorted f for f in os.listdir"? I know what sorted means and I gather the os.listdir thing. What the hell is "f for f in"? Here's the same statement in Perl:
Code: Select all
opendir(DIR, '.') || die "can't open current dir: $!";
foreach my $file (sort grep { /\.csv$/ && !/_avg\.csv$/ } readdir(DIR)) {
   my $color = shift(@colors);
It just seems to read more Englishly to me. Sure, it's a few more lines in this case, but at least you're doing some error checking first. You know that you're opening a directory first, then entering a loop, with variables from the directory read that is grepped by .csv (but not _avg.csv) and sorted, and you grab a color from the color list to use.

Blah, whatever, I'm tired of arguing with this many Perl haters. I've taught it to a few people and they love it, as well as the people have used it as their primary language.

 #119688  by Kupek
 Thu Mar 27, 2008 10:06 am
Keep in mind I already know and used Perl. And also keep in mind Python is not my second, third or even fourth language. I have experience with imperative, functional and logic programming. Before you attribute my preference of Python to how I first learned to program, remember I probably have experience in more languages and paradigms than you do. I don't point this out to argue that my opinion is better than yours, but that you should think twice before disregarding it as accident.

List comprehensions are one of the reasons I like Python. So, this,
Code: Select all
sorted([f for f in os.listdir('.') if f.endswith('.csv') and not f.endswith('_avg.csv')])
Is equivalent to
Code: Select all
temp = []
for f in os.listdir('.'):
     if f.endswith('.csv') and not f.endswith('_avg.csv'):
          temp.append(f)
temp = sorted(temp)
What list comprehensions buy you is a reduction in temporary values. This is a huge win for expressivity and productivity. Also notice that I state explicitly in the for loop that two values - a tuple, actually - are used as iteration variables. Your example in Perl doesn't state that explicitly, it's something I have to figure out by reading the body.

As an aside, that list compression can also be expressed as
Code: Select all
sorted(filter(lambda f: f.endswith('.csv') and not f.endswith('_avg.csv'), os.listdir('.')))
What "reads" better to you is largely a result of experience. Your main language for many years has been Perl, and you've had little exposure to Python, so of course Perl will seem more natural. I personally find Python much more natural.

You should take the time to learn some more languages. Even if you don't switch to developing in them, you can't help but pick up on some new concepts with a new language, which change how you code in your primary language. C++ is still my primary language, and my usage of it has changed considerably as I've learned how to think more functionally.

 #119707  by Tessian
 Thu Mar 27, 2008 5:30 pm
NERD FIGHT!!!
Image
Image

Next round: Plastic pocket protectors vs Metal pocket protectors

Sorry guys, couldn't resist... this just screams NERD at even me, and I like to program!

 #119750  by Tessian
 Fri Mar 28, 2008 5:33 pm
wow, I killed the thread-- go me?

 #119758  by SineSwiper
 Fri Mar 28, 2008 10:44 pm
No, not really. I was just tired of arguing about it and being outnumbered. They can have their Python lovefest.

 #119762  by Ishamael
 Fri Mar 28, 2008 11:16 pm
SineSwiper wrote: They can have their Python lovefest.
That just sounds gay. I'm switching back to Perl.

 #119764  by SineSwiper
 Fri Mar 28, 2008 11:26 pm
Yeah, because a Perl necklace is much better?

I'm here all week. Try the veal.

 #119770  by Oracle
 Sat Mar 29, 2008 1:00 am
I am so glad I got out of coding.

 #119782  by Ishamael
 Sat Mar 29, 2008 1:42 pm
Oracle wrote:I am so glad I got out of coding.
I wouldn't call giving glory hole BJs at truck stops a step up.

 #119783  by Tessian
 Sat Mar 29, 2008 3:03 pm
Ishamael wrote:
Oracle wrote:I am so glad I got out of coding.
I wouldn't call giving glory hole BJs at truck stops a step up.
He's not the one sticking his dick through glory holes at truck stop bathrooms so at least he's a step above you ;)