<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-11940592</id><updated>2012-01-10T10:49:00.650Z</updated><category term='Win32::IdentifyFile'/><title type='text'>The Darke Side</title><subtitle type='html'>Python people refer to Perl as 'the dark side' - geddit?</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>74</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-11940592.post-8307361818116838334</id><published>2011-08-17T09:54:00.001+01:00</published><updated>2011-08-17T09:55:36.972+01:00</updated><title type='text'>Perl - the way ahead</title><content type='html'>Wow! I've just been knocked off my feet.&lt;br /&gt;&lt;br /&gt;I'm at YAPC::Europe (Yet Another Perl Conference) in Riga, and just listened to the vision for Perl 5's future. Jesse Vincent is the Perl 5 Pumpking, essentially the project manager. His vision is to evolve Perl 5 into a modern language (he did not use those words, but that's the gist).&lt;br /&gt;&lt;br /&gt;Old Perl is 5.14, the current stable release. The idea is to introduce changes, like a fixed smartmatch, and deprecate the stuff that was preventing Perl 5 from moving forward because of the need for backward compatibility. Backward compatibility in the future will be provided by stating which version of Perl we should use - but still complete backward compatibility will not be guaranteed.&lt;br /&gt;&lt;br /&gt;By moving platform specific features out of the base and into modules (as in Python), the base gets to be small and easier to maintain, and maybe even faster. Deprecating features then removing them should have the same effect.&lt;br /&gt;&lt;br /&gt;What a shame this was not decided on ten years ago, still, better late than never. There will be issues with CPAN. Modules are usually only maintained for one version, the current stable one if you are lucky. Backward compatibility will be an issue with modules. The 'use version' directive (hopefully) will be lexical, so modules will be able to run on a later release (mostly, maybe). But of course they won't be able to run on an earlier release - but we have that issue right now. CPAN will need to search/tag/group modules by base release, that should not be hard, but it needs to be done before the issues arise at 5.16.&lt;br /&gt;&lt;br /&gt;So where does that leave Perl 6? Perl 6 is not dead, but rather it takes the pressure off it. Most people (me included) looked to Perl 6 for the future, and all the smart stuff that's in Python that I can't do in Perl. No longer. Perl 5 will move forward, alongside its sister language. The possibility of Perl 5 overtaking Perl 6 was not discussed.&lt;br /&gt;&lt;br /&gt;The times, they are a-changing.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-8307361818116838334?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/8307361818116838334/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=8307361818116838334&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/8307361818116838334'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/8307361818116838334'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2011/08/perl-way-ahead.html' title='Perl - the way ahead'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-4451620754791603015</id><published>2011-04-07T10:18:00.005+01:00</published><updated>2011-04-07T10:28:54.331+01:00</updated><title type='text'>Installing Python 3.2 Tkinter on Linux</title><content type='html'>A quick note for the install. Tkinter is not installed by default with Python 3.2 on Linux unless the tk development pack is installed. Where that is documented I could not say.&lt;br&gt;&lt;br&gt;On Red Hat derived distributions this would be using (under user root):&lt;br&gt;&lt;span style="font-family:courier new;"&gt;yum install tk-devel &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br&gt;Make sure you do this &lt;em&gt;before&lt;/em&gt; building Python. It is required for&lt;span style="font-family:courier new;"&gt; idle&lt;/span&gt;, which is named &lt;span style="font-family:courier new;"&gt;idle3&lt;/span&gt; (and that is not obvious either).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-4451620754791603015?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/4451620754791603015/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=4451620754791603015&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/4451620754791603015'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/4451620754791603015'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2011/04/installing-python-32-tinter-on-linux.html' title='Installing Python 3.2 Tkinter on Linux'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-6387671721385121171</id><published>2010-12-27T11:49:00.002Z</published><updated>2010-12-27T12:01:58.133Z</updated><title type='text'>A Christmas present from the monks</title><content type='html'>After what seems an age I finally got promotion to Prior, next stop (in 3000 XP points time) is Monsignor. My best node was &lt;a href="http://www.perlmonks.com/?node_id=851683"&gt;Unexpected Output&lt;/a&gt; with a score of (strangely) 42.&lt;br /&gt;&lt;br /&gt;It's weird, I get such a buzz from helping people with Perl it is almost adictive.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-6387671721385121171?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/6387671721385121171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=6387671721385121171&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/6387671721385121171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/6387671721385121171'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2010/12/christmas-present-from-monks.html' title='A Christmas present from the monks'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-7624307247643637841</id><published>2010-11-01T16:52:00.004Z</published><updated>2010-11-01T17:08:59.958Z</updated><title type='text'>Python msvcrt.locking trials and tribulations</title><content type='html'>It should be easy. All I wanted to do is to replace my C demos which use flock with a nice homely Python version on Windows. I wanted to stick with the standard library so I could just slot it into the existsing course (so I couldn't use the Locking module on PyPi).&lt;br /&gt;&lt;br /&gt;A simple demo to start with:&lt;br /&gt;1. Process 1: lock a region, write a record, pause&lt;br /&gt;2. Process 2: attempt to lock the same region&lt;br /&gt;3. Allow Process 1 to release the lock&lt;br /&gt;4. Process 2 continues&lt;br /&gt;&lt;br /&gt;Converting the code was easy (I thought), but no matter what I did I always found the region was locked for the second process - the lock was not being released.&lt;br /&gt;&lt;br /&gt;I blame the documentation, and possibly the implementation.&lt;br /&gt;&lt;br /&gt;What is not obvious is that the current file position must be reset to the original locking position before the lock gets released. The write (of course) advances the current file position, so by the time we do the unlock we are unlocking a region for which we don't have the lock in the first place! Wouldn't it be better if msvcrt.locking returned a lock object, saving the file position? Anyway, here is my completed demo:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;"""&lt;br /&gt;   lock_w.py&lt;br /&gt;&lt;br /&gt;   Run two copies, each in its own terminal session.&lt;br /&gt;   Allow one to write a number of records, then switch&lt;br /&gt;   to the other showing that it blocks on the same record.&lt;br /&gt;   Switch back and release the lock, and show that the&lt;br /&gt;   blocked process proceeds.&lt;br /&gt;&lt;br /&gt;   Also run with lock_r to demonstrate interaction with&lt;br /&gt;   read locks.&lt;br /&gt;&lt;br /&gt;   Default filename is rlock.dat&lt;br /&gt;&lt;br /&gt;   Clive Darke QA&lt;br /&gt;"""&lt;br /&gt;&lt;br /&gt;import msvcrt&lt;br /&gt;import os&lt;br /&gt;import sys&lt;br /&gt;import time&lt;br /&gt;from datetime import datetime&lt;br /&gt;&lt;br /&gt;REC_LIM   = 20&lt;br /&gt;&lt;br /&gt;if len(sys.argv) &lt; 2:&lt;br /&gt;    pFilename = "rlock.dat"&lt;br /&gt;else:&lt;br /&gt;    pFilename = sys.argv[1]&lt;br /&gt;&lt;br /&gt;fh = open(pFilename, "w")&lt;br /&gt;&lt;br /&gt;# Do only once&lt;br /&gt;Record = dict()&lt;br /&gt;Record['Pid'] = os.getpid()&lt;br /&gt;&lt;br /&gt;for i in range(REC_LIM):&lt;br /&gt;    Record['Text'] = "Record number %02d" % i&lt;br /&gt;    Record['Time'] = datetime.now().strftime("%H:%M:%S")&lt;br /&gt;&lt;br /&gt;    # Get the size of the area to be locked&lt;br /&gt;    line = str(Record) + "\n"&lt;br /&gt;    &lt;br /&gt;    # Get the current start position&lt;br /&gt;    start_pos  = fh.tell()          &lt;br /&gt;    &lt;br /&gt;    print "Getting lock for",Record['Text']&lt;br /&gt;    msvcrt.locking(fh.fileno(), msvcrt.LK_RLCK, len(line)+1)&lt;br /&gt;    fh.write(line)       # This advances the current position&lt;br /&gt;    &lt;br /&gt;    raw_input("Written record %02d, clear the lock?" % i)&lt;br /&gt;    &lt;br /&gt;    # Save the end position&lt;br /&gt;    end_pos = fh.tell()&lt;br /&gt;    &lt;br /&gt;    # Reset the current position before releasing the lock&lt;br /&gt;    fh.seek(start_pos)&lt;br /&gt;    msvcrt.locking(fh.fileno(), msvcrt.LK_UNLCK, len(line)+1)&lt;br /&gt;    &lt;br /&gt;    # Go back to the end of the written record&lt;br /&gt;    fh.seek(end_pos)&lt;br /&gt;    &lt;br /&gt;    print      &lt;br /&gt;&lt;br /&gt;fh.close()&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-7624307247643637841?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/7624307247643637841/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=7624307247643637841&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/7624307247643637841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/7624307247643637841'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2010/11/python-msvcrtlocking-trials-and.html' title='Python msvcrt.locking trials and tribulations'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-310019690542718370</id><published>2010-10-13T11:12:00.002+01:00</published><updated>2010-10-13T12:12:31.674+01:00</updated><title type='text'>Update</title><content type='html'>I try to keep these posts technical, but I have not blogged in a while so I'll break with tradition.&lt;br /&gt;&lt;br /&gt;I have been teaching a lot of Python.  Mostly this has been Python 2, but some clients want Py3.  Unfortunately not everyone understands how Open Source language releases work, and some internally assumed that no-one would want Python 2 training as soon as Python 3 was released.&lt;br /&gt;&lt;br /&gt;I have to confess that, having done a lot of Python recently, moving back to Perl is rather a drudge.  Python is not perfect, but I now find the syntax of Perl unnecessarily fussy, and Perl 6 is even worse.  I mean fussy in the sense that Perl code is to Python as a doily is to a beer-mat.&lt;br /&gt;&lt;br /&gt;Talking of Perl 6, with the release of Rakudo Star I thought (hoped) that we would get a flood of requests for courses, but we have not had one.  Rakudo Star is, I guess, still too early, and I suppose early adopters are happy to learn it themselves.&lt;br /&gt;&lt;br /&gt;Meanwhile, roughly half of the delegates that I am teaching Python have come from Perl.  There does not appear to be a consistent reason for this, and often it is not the practitioner's decision anyway.  It appears to be the perception of where Perl is in the scheme of things.  Its all about image and marketting.  What can Perl do about that?  Perl 6, but Python is catching up.&lt;br /&gt;&lt;br /&gt;Here is a simple example.  One of the nice things about Perl is the way that lists can be used:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;($one, $two, @fred) = qw(The quick brown fox);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Cannot do that in Python 2, but in Python 3:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;one, two, *fred = ('The', 'quick', 'brown', 'fox')&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The * indicates a greedy list (and you though Python didn't have sigils?).  No qw() equivalent yet though, and Perl array and hash slices are still more powerful.  Unless you know better...&lt;br /&gt;&lt;br /&gt;Now I learn that Civilisation V is using Lua as its scripting language because Python (used in Civ. IV) is too slow.  Is Lua next on my list?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-310019690542718370?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/310019690542718370/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=310019690542718370&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/310019690542718370'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/310019690542718370'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2010/10/update.html' title='Update'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-2947530634882219383</id><published>2010-08-05T08:46:00.004+01:00</published><updated>2010-08-05T08:52:45.357+01:00</updated><title type='text'>Sony Vaio Windows 7 "No Internet access"</title><content type='html'>This error has been driving me crazy. I got it when trying to connect to certain WiFi's, but not all. Surfing the web gave various solutions, none of which worked. I eventually cracked it by accident, so I'm posting it in the hope I might prevent someone else from going insane. It is far too late for me.&lt;br /&gt;&lt;br /&gt;Sony bundles all sorts of clever programs on its laptops. It's mostly concerned with multi-media, but one of them concerns us - VAIO Control Center (sic). So go to start/"All Programs" and select it. Now select "Network Connections", then "VAIO Smart Network".&lt;br /&gt;Here be Dragons.&lt;br /&gt;&lt;br /&gt;VAIO Smart Network creates "profiles". Click on "Advanced", recognise that stupid dialogue displayed at start-up? Click "Settings" (bet you never thought of going there).&lt;br /&gt;Now select "Profile Settings" from the left panel. Yes, I know this navigation is tortuous, but we are nearly there. From here you can edit one of your profiles, or create a new one. When a new profile is created from the desktop dialogue when it first connects, it defaults everything to the previous settings. It was carrying over a DNS setting I had from another connection, and that was preventing me from connecting. Select the "IP and DNS" tab and ensure that "Obtain an IP address automatically" and "Obtain DNS server address automatically" are both selected (it was the later which screwed me).&lt;br /&gt;&lt;br /&gt;The profile is selected by the name of the network. One thing that Sony engineers did not take into account in their design is a name collision. That is, two distinctly different networks having the same name.  Many of our training centres have WiFi's, and they all are named the same, however they have different DNS addresses. That allowed me to connect to one training centre successfully, but then fail at all the others because the profile remembered the DNS address from the previous site. Going through the Microsoft Windows network settings did not detect where this was being held, because Sony were causing the problem not Microsoft (for once).&lt;br /&gt;&lt;br /&gt;Hope this helps.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-2947530634882219383?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/2947530634882219383/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=2947530634882219383&amp;isPopup=true' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/2947530634882219383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/2947530634882219383'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2010/08/sony-vaio-windows-7-no-internet-access.html' title='Sony Vaio Windows 7 &quot;No Internet access&quot;'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-6631726607656737949</id><published>2010-07-25T09:26:00.005+01:00</published><updated>2010-08-02T10:58:53.658+01:00</updated><title type='text'>A view from EuroPython 2010</title><content type='html'>I have just returned from EuroPython which was, like last year, in Birmingham, UK. This post will not go into too much technical detail, email if you need more. I'm guessing that the reader does not want to know how Python implements IEEE 754 floating point format (that's even mentioned in the Programming Foundations course, do try to keep up!). It requires about 4000 lines of C code to convert between float and text - no, you didn't want to know that.&lt;br /&gt;Neither am I going to give a blow-by-blow account of each talk - they are available on the europython 2010 website.&lt;br /&gt;There were just under 400 delegates this year - slightly down on last year. The organisers should not be concerned though: early indications from rival conference YAPC Europe (Yet Another Perl Conference) is that attendance is approximately half of last year.&lt;br /&gt;Organisation was slightly better than 2009, a number of lessons appear to have been learnt. Talk streams were still patchy, but I guess that's inevitable.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Multiprocessing, the GIL, and threading&lt;/strong&gt;&lt;br /&gt;The conference was opened by Russel Winder who impressed last year as well. The theme was very familiar to me, it told the story that Intel, and others, have been banging on about for a couple of years now - the fact that multi-core CPUs are here to stay and currently the only way to get the increase in speed beloved of developers. Russel went much further though, with my brain screaming ME TOO! Where Intel's solutions are distinctly small scale with core numbers in single figures, Russel spoke of much larger clusters (note the term). His contention was that current hardware solutions with cache are not scalable beyond 16, and neither are software solutions using threads. Message passing systems, like MPI, are a more likely future than threading systems like TBB or OpenMP. And no one in their right mind would be programming native threads. Here, here. A thousand times, here, here. All these lessons were learnt on mainframes in the 1970s: those that ignore history are destined to repeat it. It is a great shame that Russel's talk was rushed.&lt;br /&gt;&lt;br /&gt;That did not stop discussion in the conference about the vagaries of the Global Interpreter Lock (GIL), the much maligned excuse for not doing multithreading in Python. Hey guys: multithreading is hard, error prone, and not necessarily all that faster. Let's just accept that and move on. There will be a reworked GIL in Python 3.2, work which has come out of Google's "Unladen Swallow" project. It will be interesting to see how much that helps (?) and what excuses people will use to avoid multithreading in the future.&lt;br /&gt;&lt;br /&gt;I was browsing one of the book stalls, looking at an Advanced Python book when it hit me how much Python has moved forward in the past couple of years. The section on Multiprocessing mentioned an out-of-date module, not Subprocess and Multiprocessing. I dismissed the book as "out-of-date" even though the first edition was 2008 - QA's own Python courses have always covered those two modules. Then I realised that we have only had our own courses for about a year, although I have been tinkering with Python for (wow!) over ten years.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Python's progress&lt;/strong&gt;&lt;br /&gt;&lt;span class=" transl_class" id="4" title="Click to correct"&gt;Version &lt;/span&gt;2.7 of Python was released on 4th July. OK, I'll update the QAPYTH2 course material as soon as someone gives me the time. (Actually many of the significant changes in 2.7 are back-ports from Python 3.1, so I can flitch the material from my Python 3 course. Just don't tell the boss). Python 2.7 is the last Python 2 major release. &lt;span class=" transl_class" id="3" title="Click to correct"&gt;Version&lt;/span&gt; 3.1 is now the only Python development stream, although 2.7 will continue to be maintained for around five years. When I started writing our own Python course material in late 2008 I was interrupted by the Python 3.0 release literally as I was writing the PowerPoint slides. I decided that a new course on Python 2 was daft, and switched to Python 3. It just so happened that I thought that Python 3 was a vast improvement for the language as well (don't cry for me, Perl 6). Six months later at EuroPython 2009 I realised I might have made a mistake, so I back-ported the course material to Python 2. I ended-up with two courses and "let the market decide". One year on and we have taught many more Python 3 courses than Python &lt;span class=" transl_class" id="2" title="Click to correct"&gt;2&lt;/span&gt;. and we are in a great position to move forward, unencumbered by legacy Python. Maybe it wasn't such a bad idea to target Python 3, but it was scary to be ahead of the curve.&lt;br /&gt;&lt;br /&gt;Python 3.2 should be out around the end of the year. One speaker gave January 2011 and another said "before the end of this year". Take your pick. Christmas? Python 3.3 was mentioned a few times, it should include Google's "Unladen Swallow" (yes Ian, it is from "Monty Python and the Holy Grail") with a target of a 5 times performance improvement (European or Asian?). No dates yet.&lt;br /&gt;&lt;br /&gt;My impression is that many developers still have not realised the benefits of Python 3, and have no plans to move over. They will.&lt;br /&gt;&lt;br /&gt;It looks like Python will overtake Visual Basic in the Tiobe stakes in the next few months (it passed Perl a couple of years ago). Are developers realising the benefits of Python? They are.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The cheese shop (the Python module repository: PyPi)&lt;/strong&gt;&lt;br /&gt;(Recent course delegate: "but the Monty Python cheese shop had no cheese in it!". Me: "neither has PyPi")&lt;br /&gt;&lt;br /&gt;One of the main benefits of Perl (what?) is CPAN. Dave Cross (well-known Perlmonger) has said that this was the main reason for not moving to Python. Well Dave, Python just had its 10,000th module uploaded (round of applause). Actually I'm not so sure that is such a good thing, duplication and crud makes navigation difficult. Still, it's an indication of popularity and progress.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;One of the main benefits of Python 2 against Python 3 is the cheese chop. Here too Python 3 is catching up. The module numbers are still only a few hundred, but there major modules are appearing all the time, for example NumPy (numerical processing) was just released for Python 3.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Wot I learnt&lt;/strong&gt;&lt;br /&gt;Quite a lot, as always. I learnt the expression for such as &lt;span style="font-family:courier new;"&gt;__path__&lt;/span&gt; is "dunder path". Nice one. I also learnt about the importance of the new unittest module (that'll have to go in) and changes in the way import works for Python 3.2. I discovered how technicians lie about language comparisons to their managers to justify using a cool product (actually, I already knew that). Speakers were at times less than accurate with their comparisons against Perl.&lt;br /&gt;&lt;br /&gt;I learnt how HTML5 is going to make Microsoft Silverlight obsolete. Well the speaker did not actually say that, but I can dream.&lt;br /&gt;&lt;br /&gt;There were some fascinating statistics, like there are more people in India with access to a mobile 'phone than to a flush toilet (please don't take the comparison further). I would love to use that in a course if only I could find the derivation.&lt;br /&gt;&lt;br /&gt;The portability issues of using ActiveX are well-known to anyone using Microsoft's remote desktop (there are no portability issues - it's not portable), but apparently not to the South Korean government.&lt;br /&gt;&lt;br /&gt;The spec. for HTML1 was three pages, for HTML5 is 900. That's progress.&lt;br /&gt;&lt;br /&gt;Oracle had a stand at the conference, and they were giving out DVD's with developer's resource on for, let's see, Linux, PHP, Ruby, Python, and Oracle VM. Hummm, spot the missing language. Me: "What about Perl then?"; Oracle chappie: "oh, that's only used by system administrators for scripting". Go figure.&lt;br /&gt;&lt;br /&gt;And you can write cool games in Python, drive neat little robots, automate PowerPoint slides (I gotta get me some of that, and the robot stuff). And the Python Software Foundation are as cheerfully disorganised as everyone else. As with all conferences, it is always nice to have opinions confirmed, and to be able to say from time to time "actually, I knew that".&lt;br /&gt;&lt;br /&gt;Oh, and I saw a great example for "If then else for the lazy" in our UNIX fundamentals course:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;./configure &amp;amp;&amp;amp; make&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Finally...&lt;/strong&gt;&lt;br /&gt;Python is self-assured, confident, and looking forward. The community is proud of its product, and itself. So they should be.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-6631726607656737949?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/6631726607656737949/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=6631726607656737949&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/6631726607656737949'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/6631726607656737949'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2010/07/view-from-europython-2010.html' title='A view from EuroPython 2010'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-3733074472410215755</id><published>2010-03-04T19:40:00.005Z</published><updated>2010-10-13T13:58:45.991+01:00</updated><title type='text'>Python exercise - alternative solution</title><content type='html'>I promised to post an alternative solution to a Python exercise for an on-site today. For other interested parties, the code lists unused ports from /etc/services:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import sys&lt;br /&gt;&lt;br /&gt;# set the file name depending on the operating system&lt;br /&gt;if sys.platform == 'win32':&lt;br /&gt;    file = r'C:\WINDOWS\system32\drivers\etc\services'&lt;br /&gt;else:&lt;br /&gt;    file = '/etc/services'&lt;br /&gt;&lt;br /&gt;# Create an empty dictionary&lt;br /&gt;ports = dict()&lt;br /&gt;&lt;br /&gt;# Iterate through the file, one line at a time&lt;br /&gt;for line in open(file):&lt;br /&gt;&lt;br /&gt;   # Ignore lines starting with '#' and those containing only whitespace&lt;br /&gt;   if line[0:1] != '#' and not line.isspace():&lt;br /&gt;&lt;br /&gt;       # Extract the second field (seperated by \s+)&lt;br /&gt;       pp = line.split(None, 1)[1]&lt;br /&gt;&lt;br /&gt;       # Extract the port number from port/protocol&lt;br /&gt;       port = pp.split ('/', 1)[0]&lt;br /&gt;&lt;br /&gt;       # Convert to int, then store as a dictionary key&lt;br /&gt;       port = int(port)&lt;br /&gt;       ports[port] = None&lt;br /&gt;   &lt;br /&gt;       # Give up after port 200&lt;br /&gt;       if port &gt; 200: break&lt;br /&gt;&lt;br /&gt;# Print any port numbers not present as a dictionary key&lt;br /&gt;for num in xrange(1,201):&lt;br /&gt;    if not num in ports:&lt;br /&gt;        print "Unused port", num&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Here is a smaller solution using Regular Expressions:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import sys,re&lt;br /&gt;&lt;br /&gt;file = r'C:\WINDOWS\system32\drivers\etc\services' \&lt;br /&gt;    if sys.platform == 'win32' else '/etc/services'&lt;br /&gt;&lt;br /&gt;found = set()&lt;br /&gt;for line in open(file):       &lt;br /&gt;    m = re.search(r'^[^#].*\s(\d+)/(tcpudp)\s',line)&lt;br /&gt;    if m:&lt;br /&gt;       port = int(m.groups()[0])&lt;br /&gt;       if port &gt; 200: break&lt;br /&gt;       found.add(port)&lt;br /&gt;     &lt;br /&gt;print set(range(1,201)) - found   &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-3733074472410215755?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/3733074472410215755/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=3733074472410215755&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/3733074472410215755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/3733074472410215755'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2010/03/python-exercise-alternative-solution.html' title='Python exercise - alternative solution'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-4297490964100065061</id><published>2010-01-29T09:40:00.004Z</published><updated>2010-01-29T10:05:14.365Z</updated><title type='text'>On the takeover of Sun by Oracle</title><content type='html'>I guess I might as well comment - everyone else and his dog is doing so.  A collegue said "A sad, sad day for FOSS".  I know what he means, but actually I disagree.  Take-overs and mergers will always happen.  &lt;br /&gt;&lt;br /&gt;It is occasions like this that demonstrate the power of FOSS.  FOSS gives us choice, and we can choose to stay with MySQL or migrate to PostgreSQL, which all the smart people were using anyway.  IMHO, technically PostgreSQL knocks MySQL into a cocked hat, and the Oracle takeover of MySQL could give PostgreSQL the increase in popularity it deserves.  Other databases are available.&lt;br /&gt; &lt;br /&gt;Sun blew hot and cold on FOSS anyway, I could never figure out what their policy was.  Java probably has too much momentum of its own for Oracle to screw it up, although if anyone can....  Never underestimate the ability of corporates to kill things off by hubris (I used to work for Computer Associates).&lt;br /&gt; &lt;br /&gt;There will always be other languages, other databases, other operating systems.&lt;br /&gt;&lt;br /&gt;Other hardware?&lt;br /&gt;&lt;br /&gt;Back in the 1980s a collegue (Haydn Moston - are you still around?) told me that CISC (Complex Instruction Set Computer) chips could never last beyond 2000, and RISC (Reduced Instruction Set Computer) chips were the only way to go.  The i386 familiy is CISC, and Sun Sparc is the most well-known RISC.  &lt;br /&gt;&lt;br /&gt;Intel are running out of steam and having to use multi-core, ten years out was actually not bad Haydn.  I'm not sure that the switch to multi-core is connected specifically with CISC, but the possible loss of RISC machines is my biggest worry with the Oracle takeover.  The number of mainstream instruction sets out there is disapointingly small.  How I hate monocultures.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-4297490964100065061?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/4297490964100065061/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=4297490964100065061&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/4297490964100065061'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/4297490964100065061'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2010/01/on-takeover-of-sun-by-oracle.html' title='On the takeover of Sun by Oracle'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-3328093210846328309</id><published>2010-01-07T14:53:00.006Z</published><updated>2010-04-10T17:27:19.730+01:00</updated><title type='text'>File notification events on Windows</title><content type='html'>One of my most popular posts is example code for Inotify on Linux. I have also been asked for similar code for Windows, so yer tis:&lt;br /&gt;&lt;br /&gt;There are two different interfaces available on Win32, I prefer ReadDirectoryChangesW because it is easier to control:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;// ------------------------------------------------------------------&lt;br /&gt;// Clive Darke QA Training&lt;br /&gt;// ReadDirectoryChangesW example&lt;br /&gt;// ------------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;#define _WIN32_WINNT 0x0400      // &lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&gt;&lt;br /&gt;#include &amp;ltiostream&amp;gt&lt;br /&gt;#include &amp;ltwindows.h&amp;gt&lt;br /&gt;&lt;br /&gt;void DisplayLastError( LPSTR lpszText );&lt;br /&gt;&lt;br /&gt;// ------------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;int main ( int argc, char *argv[] )&lt;br /&gt;{&lt;br /&gt;   HANDLE hDir;&lt;br /&gt;   DWORD dwReturned;&lt;br /&gt;   BOOL bResult;&lt;br /&gt;   FILE_NOTIFY_INFORMATION *pNotify;&lt;br /&gt;   &lt;br /&gt;   if ( argc &lt; 2 )&lt;br /&gt;   {&lt;br /&gt;      cerr &lt;&lt; "You must supply a directory name" &lt;&lt; endl;&lt;br /&gt;      return 1;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // Note FILE_FLAG_BACKUP_SEMANTICS, which is the strange&lt;br /&gt;   // attribute required to get a handle to a directory.   &lt;br /&gt;&lt;br /&gt;   hDir = CreateFile (&lt;br /&gt;          argv[1],                            // pointer to the file name&lt;br /&gt;          FILE_LIST_DIRECTORY,                // access (read-write) mode&lt;br /&gt;          FILE_SHARE_READ|FILE_SHARE_DELETE,  // share mode&lt;br /&gt;          NULL,                               // security descriptor&lt;br /&gt;          OPEN_EXISTING,                      // how to create&lt;br /&gt;          FILE_FLAG_BACKUP_SEMANTICS,         // file attributes&lt;br /&gt;          NULL                                // file with attributes to copy&lt;br /&gt;        );&lt;br /&gt;&lt;br /&gt;   char Buffer[MAX_PATH] = {0};&lt;br /&gt;&lt;br /&gt;   while (TRUE )&lt;br /&gt;   {&lt;br /&gt;      char szAction[42];&lt;br /&gt;      char szFilename[MAX_PATH];&lt;br /&gt;&lt;br /&gt;      bResult = ReadDirectoryChangesW (hDir, &amp;Buffer, sizeof(Buffer),&lt;br /&gt;      TRUE, FILE_NOTIFY_CHANGE_FILE_NAME, &amp;dwReturned, NULL, NULL);&lt;br /&gt;    &lt;br /&gt;   if ( !bResult )&lt;br /&gt;      break;&lt;br /&gt;    &lt;br /&gt;   pNotify = (FILE_NOTIFY_INFORMATION *) Buffer;&lt;br /&gt;&lt;br /&gt;   switch (pNotify-&gt;Action)&lt;br /&gt;   {&lt;br /&gt;    case FILE_ACTION_ADDED :    {&lt;br /&gt;     strcpy (szAction, "added");&lt;br /&gt;     break;&lt;br /&gt;    case FILE_ACTION_REMOVED :&lt;br /&gt;     strcpy (szAction, "removed");&lt;br /&gt;     break;&lt;br /&gt;    case FILE_ACTION_MODIFIED :&lt;br /&gt;     strcpy (szAction, "modified");&lt;br /&gt;     break;&lt;br /&gt;    case FILE_ACTION_RENAMED_OLD_NAME :&lt;br /&gt;     strcpy (szAction, "renamed");&lt;br /&gt;     break;&lt;br /&gt;    case FILE_ACTION_RENAMED_NEW_NAME :&lt;br /&gt;     strcpy (szAction, "renamed");&lt;br /&gt;     break;&lt;br /&gt;          default:&lt;br /&gt;     strcpy (szAction, "Unknown action");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;      wcstombs( szFilename, pNotify-&gt;FileName, MAX_PATH);&lt;br /&gt;     cout &lt;&lt; "File " &lt;&lt; dwerror =" GetLastError();" lpmessagebuffer =" NULL;"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-3328093210846328309?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/3328093210846328309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=3328093210846328309&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/3328093210846328309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/3328093210846328309'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2010/01/file-notification-events-on-windows.html' title='File notification events on Windows'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-7533805605198525844</id><published>2009-12-08T11:19:00.001Z</published><updated>2009-12-08T11:21:37.950Z</updated><title type='text'>ASSOC on Windows 7</title><content type='html'>A while back I posted some suggestions for .bat files to run cmd.exe sessions for Python. I use these a lot for PHP and Perl as well. However there is an issue with them on Windows 7. "Out of the box", the ASSOC command gives "Access is denied", even though the user is an Administrator.&lt;br /&gt;&lt;br /&gt;My first thought was to turn off the dreaded User Account Control settings, but that changed nothing. The eventual solution was to go into regedit and grant my user full control on registry key HKEY_CLASSES_ROOT, which is where the file associations are held. Fortunately Windows security for keys (and directories) is based on inheritence, and so keys within that hive will have the same permissions by default.&lt;br /&gt;&lt;br /&gt;I can see why file association sould be seen as a security risk, so why don't Microsoft finally admit that the filename is not a good way to identify the file type, and use magic numbers like everyone else? Microsoft Office files, and other Microsoft proprietry formats, all contain magic numbers, and if you place one of these files onto Linux then it identifies them correctly without the need for file extensions.&lt;br /&gt;&lt;br /&gt;UNIX's #! line for script files is a consequence of the magic number system. It is simple and incredibly flexible. When C# was developed the format of the .exe files (PE) had to change to support it. If they implemented #! then Microsoft would not have had that problem.&lt;br /&gt;&lt;br /&gt;When I wrote the yash shell I simply read the commands from STDIN. On UNIX I needed no special code to support yash scripts - just the #! line. But on Windows I had to associate a file extension.&lt;br /&gt;&lt;br /&gt;If I want to run Python 2 and Python 3 on the same machine on UNIX or Linux then I just have different #! lines at the top of the script. On Windows, because they have the same file extension, I have to redo the file associations every time I want to run one of them. Dire.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-7533805605198525844?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/7533805605198525844/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=7533805605198525844&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/7533805605198525844'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/7533805605198525844'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2009/12/assoc-on-windows-7.html' title='ASSOC on Windows 7'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-2564427122625641789</id><published>2009-08-11T15:56:00.003+01:00</published><updated>2010-03-16T13:42:59.551Z</updated><title type='text'>A winning feature of Perl 6</title><content type='html'>So what features do Python programmers love to say about their code?  First off they like to crow about how clean their code looks without sigils, those nasty $, @, %, &amp;, * that Perl programmers have to put up with.  Ah, but that means you cannot do any interpolation in Python strings, because Python does not know the difference between bare text and a variable name.&lt;br /&gt;&lt;br /&gt;Anyway, Python uses _ and __ (double underscore) to change the behaviour of variables, if these are not sigils then what is?  Python uses an @ to prefix a decorator.  Sounds like a sigil to me.&lt;br /&gt;&lt;br /&gt;Perl 6 mandates that variables are declared using 'my' (or some other scope indicator), but Python does not require that.  This means that in Python you cannot declare a variable for scope inside a local block, like an 'if' or loop.&lt;br /&gt;&lt;br /&gt;Python does not use braces to delimit a block.  Nice, unless you need to declare an empty block, so you need a 'pass' statement (reminds me of NEXT-SENTENCE).&lt;br /&gt;&lt;br /&gt;Most of that is trivial to be honest, none is important enough to make a strong case either way.&lt;br /&gt;&lt;br /&gt;So what is?  Threading.&lt;br /&gt;&lt;br /&gt;A recuring theme at the EuroPython conference was the fact that CPython is not truely multi-threaded because of the GIL (Global Interpreter Lock).  Ruby has the Global VM Lock.  There are various implementations which bypass this issue, Jython and Iron Python do not have a problem with multi-threading but both are several versions behind and I won't be holding my breath for a Python 3 version.  Google is apparently working on a CPython version which eliminates the GIL, but again that is some way off.&lt;br /&gt;&lt;br /&gt;In a classic "sour grapes", the Python community say that threading is too difficult anyway, so use processes instead.  Very few people at the conference were swallowing that line.&lt;br /&gt;&lt;br /&gt;Multithreading should be a selling point of Perl 6 and Parrot, but unfortunately is not yet complete and will not be in Rakudo Star.  That is a great pity.  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-2564427122625641789?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/2564427122625641789/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=2564427122625641789&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/2564427122625641789'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/2564427122625641789'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2009/08/winning-feature-of-perl-6.html' title='A winning feature of Perl 6'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-6950244840660012838</id><published>2009-08-05T05:10:00.002+01:00</published><updated>2009-08-11T16:36:47.950+01:00</updated><title type='text'>Perl 6 gets a release date!</title><content type='html'>Big news from the current Perl conference YAPC Europe 2009 here in Lisbon is that Rakudo * (star) will be released in spring 2010.  Rakudo is Perl 6 on Parrot, which is an equivalent to the JVM or CLI.&lt;br /&gt;&lt;br /&gt;Is that an official Perl 6 release?  Well, it is the nearest to official that you will see.  The Perl 6 team are keen to point out that there will be no such thing as a official version, just different implementations.  I guess they are looking at Python for their inspiration there.&lt;br /&gt;&lt;br /&gt;This could be make-or-break for Perl.  It shouldn't be, Perl 5 will continue no matter what, but the new stuff is what will make Perl cool again in the eyes of the fashion conscious.   We all know that fashion is fickle, illogical, and driven more by hormones than intellect.  We also know how important it is in decision making.    Much as it would like to, the Perl community cannot pretend that Perl 6/Rakudo is too far away to worry about.  It is six months away.&lt;br /&gt;&lt;br /&gt;My worry is that expectations will be high - the release will be incomplete and they are very open about that.  The Rakudo "pumpking" (project manager), Patrick Michaud, sees this as a test release to encourage people to write applications to find bugs and feed back into the development.  Trouble is that companies have been burned too often in the past to invest in applications on an incomplete and possibly flaky platform.  &lt;br /&gt;&lt;br /&gt;The dilemma is that if something is not released soon then Perl will have missed the boat - which is already upping anchor and about to steam away.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Update: &lt;/strong&gt; read the comments from &lt;strong&gt;Pm&lt;/strong&gt; - they are very good.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-6950244840660012838?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/6950244840660012838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=6950244840660012838&amp;isPopup=true' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/6950244840660012838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/6950244840660012838'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2009/08/perl-6-gets-release-date.html' title='Perl 6 gets a release date!'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-690423415630136183</id><published>2009-06-24T14:14:00.002+01:00</published><updated>2009-06-24T14:19:54.174+01:00</updated><title type='text'>Perl 6 Questions and further information</title><content type='html'>This is following a recent Perl 6 seminar I gave.&lt;br /&gt;&lt;br /&gt;Perl 5 style is still supported.&lt;br /&gt;&lt;br /&gt;Named parameters go into %_&lt;br /&gt;Unnamed parameters go into @_&lt;br /&gt;&lt;br /&gt;Subroutines can be predefined with:&lt;br /&gt;&lt;pre&gt;sub foo {…}&lt;/pre&gt;&lt;br /&gt;… is known as the "yadayadayada" operator.&lt;br /&gt;&lt;br /&gt;Lexically scoped subroutines:&lt;br /&gt;&lt;pre&gt;my sub mysub () is context { …}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Optional parameters: ? now comes after the parameter name.&lt;br /&gt;&lt;pre&gt;sub mysub ($value, @harry, %ash, $opt?) {…} &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Named parameters: prefix is now : , instead of + and are optional unless they have a ! suffix.&lt;br /&gt;&lt;pre&gt;sub named ($value, :@harry!, :%ash, :$other) {…}&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;named(42, other = 'fred', harry = @files);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Slurpy parameters, like perl 5 lists and arrays, are prefixed *&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;C style prototypes&lt;br /&gt;&lt;/strong&gt;Are not supported. It appears that when a subroutine is called before it is defined the parameter resolution still works correctly. However a runtime error is reported, not a compile time error (as it would with Perl 5 prototypes).&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Dynamic types&lt;/strong&gt;&lt;br /&gt;These are called "traits". See Synopsis 12: Objects.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Zip operator&lt;/strong&gt;&lt;br /&gt;Has changed, it is now 'Z'. Behaviour with different length arrays has also changed between pugs and Rakudo, the result uses the shortest:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;my @array = qw(The quick brown fox);&lt;br /&gt;my @brray = qw(Now is the time for all);&lt;br /&gt;&lt;br /&gt;my @all = @array Z @brray;&lt;br /&gt;say @all.elems();&lt;br /&gt;say @all[];&lt;br /&gt;&lt;br /&gt;@all = @brray Z @array;&lt;br /&gt;say @all.elems();&lt;br /&gt;say @all[];&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Gives:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;8&lt;br /&gt;TheNowquickisbrownthefoxtime&lt;br /&gt;8&lt;br /&gt;NowTheisquickthebrowntimefox&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Important further change&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;When testing these changes in Rakudo I ran up against a change I had almost forgotten. When calling a subroutine, no whitespace is allowed between the sub name and the open parentheses. That slowed me up until I remembered. A backward step IMHO.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-690423415630136183?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/690423415630136183/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=690423415630136183&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/690423415630136183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/690423415630136183'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2009/06/perl-6-questions-and-further.html' title='Perl 6 Questions and further information'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-6385153391162892466</id><published>2009-06-23T10:09:00.002+01:00</published><updated>2009-06-23T10:10:55.324+01:00</updated><title type='text'>MySQL VARCHAR limits</title><content type='html'>A delegate recently queried the size limit on a VARCHAR field in MySQL.  Our course documentation states a maximum of 255 characters: that is correct.  For larger fields use TEXT.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-6385153391162892466?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/6385153391162892466/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=6385153391162892466&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/6385153391162892466'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/6385153391162892466'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2009/06/mysql-varchar-limits.html' title='MySQL VARCHAR limits'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-6135688747220271022</id><published>2009-06-17T10:57:00.002+01:00</published><updated>2009-06-17T11:03:57.688+01:00</updated><title type='text'>Perl 6 Questions</title><content type='html'>I recently gave a short talk on Perl 6, and a number of questions arose.  I will answer those questions as soon as I can, but unfortunately other fires need fighting right now.&lt;br /&gt;&lt;br /&gt;One of the reasons for the delay is that the syntax for subroutines for Perl 6 has changed again, and in fact my slides are now out of date.  That also means that pugs and Rakudo are incompatible in a major way - they have always been out of step to some extent.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-6135688747220271022?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/6135688747220271022/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=6135688747220271022&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/6135688747220271022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/6135688747220271022'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2009/06/perl-6-questions.html' title='Perl 6 Questions'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-6204532368091517745</id><published>2009-04-24T08:24:00.004+01:00</published><updated>2009-05-05T10:01:52.337+01:00</updated><title type='text'>Moving into the light?</title><content type='html'>A long time since my last post.  Aside from bread-and-butter stuff, my activity has been on Python.  There have been various upheavals in the business, and we aquired a Python 2 course.  It wasn't too hot, and needed updating.  Around the end of 2008 Python 3 was released, so I decided it would make sense to create a new course based on Python 3.&lt;br /&gt;&lt;br /&gt;That is almost finished, but it turns out that it might have been premature, since no one seems to be in a particular hurry to move to Py3.  That's a shame, because I am quite impressed.  There have been issues, performance has been one of them (although I can't say I noticed any problems).  In June 2009 a new version, 3.1, should be released, and that has a number of new features.  So, having done all that work on a new course, I will have to hack it again come June.  That's the problem with the bleading edge.&lt;br /&gt;&lt;br /&gt;I have read of Python's ease of use, and never really believed it.  After all, there are so many vested interests and religious wars that it is difficult to get a balanced view.  I have to say that, after a little practice, Python is very easy to pickup.  I have found myself &lt;em&gt;just coding&lt;/em&gt;.  The number of times I have to look something up gets less and less.  I'm not sure I am fluent yet, but I'm close, and I reckon that is the fastest I have ever picked up another language.&lt;br /&gt;&lt;br /&gt;Will Perl 6 be as easy?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-6204532368091517745?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/6204532368091517745/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=6204532368091517745&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/6204532368091517745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/6204532368091517745'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2009/04/moving-into-light.html' title='Moving into the light?'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-8154981854679521660</id><published>2009-02-07T16:03:00.005Z</published><updated>2009-02-07T16:28:27.290Z</updated><title type='text'>App::sh2p Version 0.05 now on CPAN</title><content type='html'>I always knew this would be a long project, although I'm heartened as to how far it has gone.  It appears to have been useful to some people.  It is a feature of Open Source that the only time I can be really sure it is being used is when I get bug reports - which could be rather off-putting to anyone without the skin of a rhino.&lt;br /&gt;&lt;br /&gt;This latest release, version 0.05, fixes quite a few bugs, and adds support for things like trap (signal handling).  In my defence, most of the bugs are missing support for certain features, and it is still in beta.  I still have not got pipelines sorted out (that is a huge job), or $?, but they will come eventually.  I only get to work on this in odd moments, evenings and so on, and it is difficult to find the time for development stints of more that two hours.  I could really do with spending a couple of solid days on it.&lt;br /&gt;&lt;br /&gt;One problem I had was in inserting a marker into a string which would indicate a token delimiter.  Everything I tried clashed in someway with a real data item.  I solved it eventually by using a gash reference, but I can't help thinking there must be a more elegant solution.&lt;br /&gt;&lt;br /&gt;I have also started using OO techniques more - this product really does benefit from that.  &lt;br /&gt;&lt;br /&gt;I am now using the profiler and Coverage for my tests, but have not sorted out a good way to integrate my command-line tests.  The "Perl Testing" book has ideas, but they require CPAN modules and I would rather not increase the number of dependencies.  If you download this program and are dismayed at the tests (I basically check the thing will load) then be assured that I have a test suite of over 90 scripts, just one of which is my regression test script which currently has 55 test paragraphs within it.  Each time I find a bug or add a feature I add a test, just like I should.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-8154981854679521660?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/8154981854679521660/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=8154981854679521660&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/8154981854679521660'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/8154981854679521660'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2009/02/appsh2p-version-005-now-on-cpan.html' title='App::sh2p Version 0.05 now on CPAN'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-592420234397430622</id><published>2008-12-19T08:28:00.002Z</published><updated>2008-12-19T08:39:29.271Z</updated><title type='text'>Shock! Horror!! A delegate ate my machine!</title><content type='html'>OK, he didn't actually &lt;span style="font-style: italic;"&gt;eat &lt;/span&gt;it, but he did exploit a "feature" of CentOS I was unaware of.  The halt, reboot, and poweroff programs can be called from an ordinary user if that user is logged on to the console at the time.  Our classroom users have very simple passwords, but the point is that these can be called from a non-root user.&lt;br /&gt;&lt;br /&gt;I found &lt;b&gt;a&lt;/b&gt; fix (with thanks to Mr. Google) but I'm sure there is probably a better one.  Right now this will do, since it appears to work, but I'll try and find an alternative.&lt;br /&gt;&lt;br /&gt;In &lt;b&gt;/etc/security/console.apps&lt;/b&gt; there is a config file for the programs mentioned (and others).  Set each one to something like (for example):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;USER=nobody&lt;br /&gt;PROGRAM=/sbin/poweroff&lt;br /&gt;SESSION=true&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Of course having better passswords would help...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-592420234397430622?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/592420234397430622/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=592420234397430622&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/592420234397430622'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/592420234397430622'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2008/12/shock-horror-delegate-ate-my-machine.html' title='Shock! Horror!! A delegate ate my machine!'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-3694087407358859920</id><published>2008-09-05T12:15:00.003+01:00</published><updated>2008-09-05T12:20:57.868+01:00</updated><title type='text'>Function redirection</title><content type='html'>I just came across this:&lt;br /&gt;&lt;pre&gt;function myfunc {  &lt;/pre&gt;&lt;pre&gt;    echo 'Hollow world' &lt;/pre&gt;&lt;pre&gt;} &gt; outfile&lt;/pre&gt;&lt;br /&gt;Works with Bourne style functions as well, and is in the POSIX standard. It should not be a surprise, since it just follows the same standard as 'if' and loops, but I have never seen it before. It certainly is not our shell course (yet). Seen it before?&lt;br /&gt;&lt;br /&gt;Here is a neat trick:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;outfile=one.out&lt;br /&gt;&lt;br /&gt;function myfunc {&lt;br /&gt;    echo 'Hollow world'&lt;br /&gt;} &gt; $outfile&lt;br /&gt;&lt;br /&gt;outfile=two.out&lt;br /&gt;myfunc&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Which file gets written to, one.out or two.out? Interestingly it is two.out. In other words the variable is resolved at runtime, not function declaration time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-3694087407358859920?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/3694087407358859920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=3694087407358859920&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/3694087407358859920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/3694087407358859920'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2008/09/function-redirection.html' title='Function redirection'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-1085579169598784800</id><published>2008-08-31T19:09:00.003+01:00</published><updated>2008-08-31T19:25:24.123+01:00</updated><title type='text'>App::sh2p - shell to perl converter</title><content type='html'>Just uploaded to CPAN, this has been a pet project of mine for a while (see perlmonks &lt;a href="http://www.perlmonks.com/?node_id=577182"&gt;here&lt;/a&gt; ). It is currently only a alpha release, and you &lt;em&gt;know&lt;/em&gt; what that means.&lt;br /&gt;&lt;br /&gt;Converting UNIX shell scripts creates problems and my script (with associated modules) do not answer them all. The syntax of shell programs is very loose, almost anarchic. This is not a criticism of shells - they have a dual role to play in providing a usable command-line interface, as well as acting as a programming language. I target the POSIX shell, but there are many variations, not least those created by Sun. The Korn shell has moved on considerably from ksh88, and the syntax of the latest versions is complex. I make no attempt at the more esoteric parts of ksh93 syntax, expansions and extended globbing. There are annoying inconsistencies, fore example, what is the difference between:&lt;br /&gt;&lt;br /&gt;[ $x -a $b ]&lt;br /&gt;&lt;br /&gt;and&lt;br /&gt;&lt;br /&gt;[[ $x -a $b ]]&lt;br /&gt;&lt;br /&gt;I shall leave the reader to ponder (hint: -a has a different meaning to the Bourne-shell [ and the Korn shell [[).&lt;br /&gt;&lt;br /&gt;As you might gather, this is not a simple syntax conversion. Take $? for example: that can be applied to any shell command you like and at any point in the program. Not many languages work like that, certainly Perl does not. Fortunately not many people use $? in shell scripts for anything other than testing the result of a child process - not unlike its use in Perl (there is a difference in the detail).&lt;br /&gt;&lt;br /&gt;Right now App::sh2p attempts to remove some of the leg-work from conversion, and I hope t is useful.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-1085579169598784800?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/1085579169598784800/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=1085579169598784800&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/1085579169598784800'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/1085579169598784800'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2008/08/appsh2p-shell-to-perl-converter.html' title='App::sh2p - shell to perl converter'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-1369089231405594095</id><published>2008-07-10T09:37:00.002+01:00</published><updated>2008-07-10T09:41:55.196+01:00</updated><title type='text'>Flip-flop operator</title><content type='html'>I have been using the flip-flop operator in Perl for ages, equating it with sed and awk line addressing.  However a question just came up that asked how we process from a specific line until end-of-file.  In sed and awk the last line of the file is denoted by &lt;strong&gt;$&lt;/strong&gt;, but that does not work in Perl for obvious syntax reasons.&lt;br /&gt;&lt;br /&gt;I had to think about that: the solution is to use &lt;strong&gt;eof&lt;/strong&gt;().  So, to list a file from line 20 we can use:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;while (&lt;&gt;)&lt;br /&gt;{&lt;br /&gt;   print if 20..eof &lt;br /&gt;}  &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-1369089231405594095?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/1369089231405594095/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=1369089231405594095&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/1369089231405594095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/1369089231405594095'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2008/07/flip-flop-operator.html' title='Flip-flop operator'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-1353232929523636749</id><published>2008-07-10T09:00:00.001+01:00</published><updated>2008-07-10T09:01:30.401+01:00</updated><title type='text'>Promotion!</title><content type='html'>When I signed on to Perlmonks this morning I got:&lt;br /&gt;&lt;br /&gt;You have 24 votes left today.&lt;br /&gt;You gained 16 experience points. They really complement your eyes.&lt;br /&gt;Your new level imbues you with super-powers! Check out Level 13: Curate for the details!&lt;br /&gt;You have 991 points until level 14 - Priest.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-1353232929523636749?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/1353232929523636749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=1353232929523636749&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/1353232929523636749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/1353232929523636749'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2008/07/promotion.html' title='Promotion!'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-6602196428141533285</id><published>2008-06-23T09:39:00.001+01:00</published><updated>2008-06-23T09:56:11.660+01:00</updated><title type='text'>The trials of a CPAN author</title><content type='html'>As mentioned previously I have a module called Win32::EnvProcess.  The CPAN people (modules@cpan.org) don't like that name, although I'm not sure why.  Changing a name is not clearly defined, and I don't get answers to email.  Hey ho, it doesn't stop Win32::EnvProcess from being found and downloaded.&lt;br /&gt;&lt;br /&gt;And that's the trouble with being a developer – people will actually try and use the stuff.  So I get queries, and I get bug reports.&lt;br /&gt;&lt;br /&gt;Generally the email queries are sensible, and I have had a few over the past week.  First I, or rather a user, had an issue with Microsoft Visual Studio 2005, which is a version I haven't got around to using.  It seems that good ol' Microsoft decided to fix the "DLL hell" problem by introducing a 'manifest' file into its link/load phase.  So now we get "manifest hell" instead - the issues are well documented on the web.  Of course the Perl MakeMaker does not generate a manifest file for its DLLs, and so my module wouldn't load and run.  After some blind alleys and investigation I found a patch for MakeMaker, via perlmonks which I passed on.   Of course that meant I had to document the thing as well.  Meanwhile I found a small memory leak.  OK, so that was worth it.&lt;br /&gt;&lt;br /&gt;Then I got a bug report saying that the installation failed if the user did not have a C/C++ compiler.  OK, I would have thought that if the product included an XS file, and the documentation showed compilation steps, then that would have been obvious.  Clearly not, so more lines to the doc.&lt;br /&gt;&lt;br /&gt;A user sent a "it would be great if…" feature request.  "Good idea", I thought.  "Simple patch", I thought.  Only one of those thoughts was correct.  Well you see it all worked on my Windows machines, it's just that it failed everywhere else.  It wasn't until one of the cpan testers sent me a copy of his environment block that I cracked it.  Their environment blocks were bigger than a hard limit I set – size matters.  I hate hard limits and try and avoid them, but in this case I have to set one to a file mapping object.  It's just that I was not handling the overflow case correctly.&lt;br /&gt;&lt;br /&gt;There is nothing like a sustained bout of debugging to improve the diagnostics available in code.  And of course I found another (unrelated) buglett as well – a possible race condition.&lt;br /&gt;&lt;br /&gt;Then another bug report, this time someone is trying to compile the module under cygwin.  Cygwin is a UNIX emulation environment, and this module is called Win32::EnvProcess – the clue is in the name.  I check the OS name in the tests, but the thing won't compile and link anywhere except Windows.  Of course not, RTFM.  Alright, so Cygwin runs under Windows but it doesn't give access to the Windows kernel, it pretends it is UNIX.&lt;br /&gt;&lt;br /&gt;Don't get me started about Strawberry Perl, just don't.  Alright then.  Strawberry Perl is a laudable package of open source products to enable you to install Perl without any dreaded Micro$osft licences.  Good, great stuff, more power to them.  Except that the Perl installation tools, like MakeMaker, doesn't really support it.  So more magic in my Makefile.PL, already burdened by this stupid manifest issue.  UNIX?  Pah, that's easy.&lt;br /&gt;&lt;br /&gt;Version 0.05 of Win32::EnvProcess has just been uploaded.  God bless her, and all who sail in her.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-6602196428141533285?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/6602196428141533285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=6602196428141533285&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/6602196428141533285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/6602196428141533285'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2008/06/trials-of-cpan-author.html' title='The trials of a CPAN author'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-6511649328368284689</id><published>2008-05-09T20:34:00.002+01:00</published><updated>2008-05-09T20:54:09.307+01:00</updated><title type='text'>Win32::StreamNames - new version!</title><content type='html'>My CPAN module Win32::StreamNames had a bug - I know, unbelieveable.  Happens to the best of us.  The symptoms were that empty data streams were not returned.  It is now fixed in version 1.03 which I just uploaded.&lt;br /&gt;&lt;br /&gt;The bug was an unexpected (and undocumented) behaviour of the Win32 API BackupRead when it finds an empty stream, and I discovered the fix just by experimentation.  Good old Microsoft, guarenteed to keep life interesting.&lt;br /&gt;&lt;br /&gt;Thanks to Frederic Medico for reporting the error.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-6511649328368284689?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/6511649328368284689/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=6511649328368284689&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/6511649328368284689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/6511649328368284689'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2008/05/win32streamnames-new-version.html' title='Win32::StreamNames - new version!'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-3993096644697080881</id><published>2008-05-01T06:26:00.005+01:00</published><updated>2008-05-01T06:36:41.341+01:00</updated><title type='text'>Yet another time calculation in Perl</title><content type='html'>This is specifically for a delegate I am teaching right now. If I understand the requirements correctly, we hae two times in HH:MM:SS format and we wish to calculate the difference. I know, what if the times are on different days? No answer was given to that one, so I have assumed they are on the same day (today, to be exact).&lt;br /&gt;This will probably change because the specification is a bit "wooly".&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;use Time::Local;&lt;br /&gt;&lt;br /&gt;sub str2time&lt;br /&gt;{&lt;br /&gt;   my $in = shift;&lt;br /&gt;   my ($hour, $min, $sec) = split (/:/, $in);&lt;br /&gt;   my ($mday,$mon,$year) = (localtime(time))[3,4,5];&lt;br /&gt;   my $retn;&lt;br /&gt; &lt;br /&gt;   # timelocal throws an exception on an invalid date/time&lt;br /&gt;   eval {&lt;br /&gt;      $retn = timelocal($sec,$min,$hour,$mday,$mon,$year);&lt;br /&gt;   };&lt;br /&gt; &lt;br /&gt;   return $retn;   # undef on error&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;print "Please enter the first time in HH:MM:SS format: ";&lt;br /&gt;my $intime = &amp;lt;STDIN&amp;gt;;&lt;br /&gt;chomp $intime;&lt;br /&gt;&lt;br /&gt;my $time1 = str2time($intime);&lt;br /&gt;&lt;br /&gt;die "Invalid time: $intime\n" if !defined $time1;&lt;br /&gt;  &lt;br /&gt;print "Please enter the 2nd   time in HH:MM:SS format: ";&lt;br /&gt;$intime = &amp;lt;STDIN&amp;gt;;&lt;br /&gt;chomp $intime;&lt;br /&gt;&lt;br /&gt;my $time2 = str2time($intime);&lt;br /&gt;&lt;br /&gt;die "Invalid time: $intime\n" if !defined $time1;&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;my $diff;&lt;br /&gt;if ( $time1 &gt; $time2 ) {&lt;br /&gt;    $diff = $time1 - $time2&lt;br /&gt;}&lt;br /&gt;else {&lt;br /&gt;    $diff = $time2 - $time1&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;my $mins  = int($diff / 60);&lt;br /&gt;my $hours = int($mins / 60);&lt;br /&gt;$mins     = $mins - ($hours * 60);&lt;br /&gt;my $secs  = $diff - ($mins  * 60);&lt;br /&gt;&lt;br /&gt;printf "Difference: %02d:%02d:%02d\n", $hours,$mins,$secs;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-3993096644697080881?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/3993096644697080881/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=3993096644697080881&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/3993096644697080881'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/3993096644697080881'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2008/05/yet-another-time-calculation-in-perl.html' title='Yet another time calculation in Perl'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-4281025724863795470</id><published>2008-04-18T10:51:00.003+01:00</published><updated>2008-04-18T11:07:16.786+01:00</updated><title type='text'>Away from the dark side - Python</title><content type='html'>Our Python guy is off sick, so I've spent a week hacking the language.  I had looked at Python a few years ago, but this time its personal.&lt;br /&gt;&lt;br /&gt;So these are the impressions of a novice - and someone coming from Perl at that.  I will probably come-up with justifications and solutions for the shortfalls as I learn, they are probably a mark or my ignorance rather than anything wrong with Python.  Having said that, I was surprised how many things are missing.&lt;br /&gt;&lt;br /&gt;The good &lt;br /&gt;1.  Forced code formatting&lt;br /&gt;2.  No stupid sigils&lt;br /&gt;3.  OO built-in&lt;br /&gt;4.  Default variables in a function are not global&lt;br /&gt;5.  Documentation&lt;br /&gt;6.  OS specifics are removed from the core &lt;br /&gt;7.  Excellent string handling&lt;br /&gt;8.  Intuitive file IO&lt;br /&gt;9.  Method calls on built-in types instead of weird system variables&lt;br /&gt;10. No GOTO&lt;br /&gt;&lt;br /&gt;The bad (IMHO)&lt;br /&gt;1.  No constants&lt;br /&gt;    Even True and False can be altered!&lt;br /&gt;2.  No scoping within loops and 'if' statements&lt;br /&gt;    All variables outside functions are globals&lt;br /&gt;3.  No interpolation - an effect of the lack of sigils I guess&lt;br /&gt;4.  Comparisons between numbers and strings give unexpected results, and NO WARNINGS! A poor and surprising feature&lt;br /&gt;5.  I know ++, --, +=, etc. are arguably poor coding, but I missed them.&lt;br /&gt;&lt;br /&gt;Still, 10 good and only 5 bad.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-4281025724863795470?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/4281025724863795470/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=4281025724863795470&amp;isPopup=true' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/4281025724863795470'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/4281025724863795470'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2008/04/away-from-dark-side-python.html' title='Away from the dark side - Python'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-4753505072118765488</id><published>2008-02-13T13:40:00.002Z</published><updated>2008-02-13T13:49:16.799Z</updated><title type='text'>Win32::EnvProcess</title><content type='html'>YAPM (Yet Another Perl Module) which I just uploaded to PAUSE.&lt;br /&gt;&lt;br /&gt;This module enables the user to alter or query an unrelated process's &lt;br /&gt;environment variables.&lt;br /&gt;&lt;br /&gt;Windows allows a process with sufficient privilege to run code in another &lt;br /&gt;process by attaching a DLL.  This is known as "DLL injection", and is used here.  &lt;br /&gt;&lt;br /&gt;SYNOPSIS&lt;br /&gt;&lt;br /&gt;  use Win32::EnvProcess qw(:all);&lt;br /&gt;  &lt;br /&gt;  use Win32::EnvProcess qw(SetEnvProcess); &lt;br /&gt;  my $result = SetEnvProcess($pid, env_var_name, [value], ...);&lt;br /&gt;      &lt;br /&gt;  use Win32::EnvProcess qw(GetEnvProcess);&lt;br /&gt;  my @values = GetEnvProcess($pid, env_var_name, [...]);&lt;br /&gt;  &lt;br /&gt;  use Win32::EnvProcess qw(DelEnvProcess);&lt;br /&gt;  my $result = DelEnvProcess($pid, env_var_name, [...]);&lt;br /&gt;  &lt;br /&gt;  use Win32::EnvProcess qw(GetPids);&lt;br /&gt;  my @pids = GetPids($exe_name);&lt;br /&gt;&lt;br /&gt;This is another case where a question on perlmonks generated the interest.  How do I get the child to create/alter an environment variables in the parent?  Had this been on UNIX then the answer would be simple - you can't without having co-operating proceses.  On Windows however DLL injection makes this possible.&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;br /&gt;&lt;br /&gt;I have done a brief investigation on how this might be achieved on Linux, but I don't think it can fly.  The API ptrace(2) is a start, but the problem is in creating a thread in the host.  Addresses in the host can be changed, but the environment block is not at a fixed location so far as I know, and without a symbol table I'm not sure how you would find it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-4753505072118765488?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/4753505072118765488/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=4753505072118765488&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/4753505072118765488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/4753505072118765488'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2008/02/win32envprocess.html' title='Win32::EnvProcess'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-5884528302992547288</id><published>2008-01-30T12:14:00.000Z</published><updated>2008-01-30T12:24:47.345Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Win32::IdentifyFile'/><title type='text'>Win32:IdentifyFile</title><content type='html'>I just uploaded my fourth Perl CPAN module to PAUSE (the Perl Author's Upload Server).&lt;br /&gt;&lt;br /&gt;This one was written because of a conversation on perlmonks Chatterbox.  A module author was bemoaning the fact that Windows files do not have an inode number.  I waded in to say that they do, kinda.  However it's not easy to use, and requires a C API to be called.  Hence the module, written using XS.&lt;br /&gt;&lt;br /&gt;There are two functions, IdentifyFile() and CloseIdentifyFile().&lt;br /&gt;&lt;br /&gt;IdentifyFile() returns 3 components to uniquely identify the file or directory.  In list context these are returned as a 3 item list, in scalar context they are joined together as a single string using ':'.  It is therefore simple to compare two identities in perl, using 'eq'.&lt;br /&gt;&lt;br /&gt;Just getting this information could result in a race condition.  The file could be deleted, possibly by another process, between getting the information and using it in a test.  Worse, another file might be created with the same file index meanwhile.  To prevent this scenario, files (or directories) are opened internally by IdentifyFile(), and kept open until CloseIdentifyFile() is called (files are not physically deleted until all open file handles are closed).&lt;br /&gt;&lt;br /&gt;I wonder how many people think of that when using an inode number on UNIX?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-5884528302992547288?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/5884528302992547288/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=5884528302992547288&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/5884528302992547288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/5884528302992547288'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2008/01/win32identifyfile.html' title='Win32:IdentifyFile'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-5808286628611726125</id><published>2008-01-23T03:23:00.000Z</published><updated>2008-01-23T03:31:15.315Z</updated><title type='text'>UNIX command equivalents in Perl</title><content type='html'>I realise I said I would post a new update in an ealier post. Well this is not it!&lt;br&gt; For the very latest list see my perlmonks post: &lt;a href=http://www.perlmonks.com/?node_id=627015&gt;UNIX command equivalents in Perl&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-5808286628611726125?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/5808286628611726125/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=5808286628611726125&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/5808286628611726125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/5808286628611726125'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2008/01/unix-command-equivalents-in-perl.html' title='UNIX command equivalents in Perl'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-7236447067096548881</id><published>2008-01-21T02:28:00.000Z</published><updated>2008-01-21T02:34:34.300Z</updated><title type='text'>First impressions in India</title><content type='html'>On the road again, or rather "10 cramped hours in cattle class".   &lt;br /&gt;&lt;br /&gt;My hotel is a Marriott, not everyone's cup of tea, but I think they are excellent.  In my previous job we always stayed in them, nowadays I rarely get the chance; usually the hotel is um, economic.  Anyway, the luxury of the hotel is in stark contrast with the surroundings.  Quite a culture shock, it is like living in a travelogue.&lt;br /&gt;&lt;br /&gt;Stereotypical taxi from the airport, including the dangly bits on the mirror.  Streets being brushed by doubled-up women holding rushes, and this at 1:30 AM.  The reflective safety jackets were particularly incongruous.  And yes, there was even a cow in the road.&lt;br /&gt;&lt;br /&gt; The guards, sniffer-dog, and metal detectors at the hotel entrance were a bit of a shock.  The helpful and polite staff are overwhelming.  I think I have said "thank-you" more than any other phrase since I got here.&lt;br /&gt;&lt;br /&gt;Walking out of the hotel on Sunday morning I was surrounded by tricycle drivers wanting to take me for a tour.  When I politely declined they disappeared, and I was not bothered again.  Just outside the hotel the poverty is heart-rending, yet the busy road ignores them.  I have never seen anyone riding side-saddle on a motorbike while wearing a sari before.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-7236447067096548881?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/7236447067096548881/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=7236447067096548881&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/7236447067096548881'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/7236447067096548881'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2008/01/first-impressions-in-india.html' title='First impressions in India'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-7372773620093068065</id><published>2008-01-04T12:01:00.002Z</published><updated>2009-06-29T08:16:12.111+01:00</updated><title type='text'>(Windows) What is the difference between a thread's HANDLE and its ID?</title><content type='html'>There seems to be some doubt amoung my peers over the use of a Thread ID, referred to here as a TID.&lt;br /&gt;&lt;br /&gt;The most obvious difference between a HANDLE and a TID is that a HANDLE is specific to a process, whereas a TID is system wide.&lt;br /&gt;&lt;br /&gt;A HANDLE is actually an unsigned int (whereas a UNIX file descriptor is a signed int) and is an index into the process's Handle Table, which is maintained by kernel.&lt;br /&gt;&lt;br /&gt;A TID is a type of Client ID, the other type of Client ID being a PID (Process ID).  TIDs and PIDs are generated in the same namespace and used by the kernel to identify these objects system wide.&lt;br /&gt;&lt;br /&gt;So, why would you need the TID?  You don't.  At least, not often.  A TID may be passed between processes, and another process can then get a HANDLE to that thread using the OpenThread() API.&lt;br /&gt;&lt;br /&gt;Yes, you can manipulate threads in other processes - the caveat being that security may stop you, particularly in Windows Vista.  Once you have a HANDLE to another thread you can do all those wonderful things, Suspend, Resume, Wait, GetExitCode, as you can if the thread is in the same process.  One of the useful APIs in this context is PostThreadMessage().  &lt;em&gt;This sentence is mis-leading, PostThreadMessage takes a TID, see comment from Hibou57 below.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;BTW: make sure that HANDLE is closed, the thread cannot truly die until all HANDLEs to it are closed - that is how GetExitCodeThread() works.  And you thought zombies only occurred on UNIX?&lt;br /&gt;&lt;br /&gt;It is possible to use DuplicateHandle() to get a handle opened by another process, but that is far more painful than the MSDN implies.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-7372773620093068065?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/7372773620093068065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=7372773620093068065&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/7372773620093068065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/7372773620093068065'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2008/01/windows-what-is-difference-between.html' title='(Windows) What is the difference between a thread&apos;s HANDLE and its ID?'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-1934966470417693342</id><published>2007-12-05T17:33:00.001Z</published><updated>2007-12-05T17:57:39.944Z</updated><title type='text'>Linux inotify example</title><content type='html'>&lt;pre&gt;&lt;br /&gt;#include &amp;ltsys/types.h&amp;gt&lt;br /&gt;#include &amp;ltsys/stat.h&amp;gt&lt;br /&gt;#include &amp;ltfcntl.h&amp;gt&lt;br /&gt;#include &amp;ltstring.h&amp;gt&lt;br /&gt;#include &amp;ltstdio.h&amp;gt&lt;br /&gt;#include &amp;lterrno.h&amp;gt&lt;br /&gt;#include &amp;ltsys/inotify.h&amp;gt&lt;br /&gt;&lt;br /&gt;void get_event (int fd, const char * target);&lt;br /&gt;void handle_error (int error);&lt;br /&gt;&lt;br /&gt;/* ----------------------------------------------------------------- */&lt;br /&gt;&lt;br /&gt;int main (int argc, char *argv[])&lt;br /&gt;{&lt;br /&gt;   char target[FILENAME_MAX];&lt;br /&gt;   int result;&lt;br /&gt;   int fd;&lt;br /&gt;   int wd;   /* watch descriptor */&lt;br /&gt;&lt;br /&gt;   if (argc &lt; 2) {&lt;br /&gt;      fprintf (stderr, "Watching the current directory\n");&lt;br /&gt;      strcpy (target, ".");&lt;br /&gt;   }&lt;br /&gt;   else {&lt;br /&gt;      fprintf (stderr, "Watching %s\n", argv[1]);&lt;br /&gt;      strcpy (target, argv[1]);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   fd = inotify_init();&lt;br /&gt;   if (fd &lt; 0) {&lt;br /&gt;      handle_error (errno);&lt;br /&gt;      return 1;&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   wd = inotify_add_watch (fd, target, IN_ALL_EVENTS);&lt;br /&gt;   if (wd &lt; 0) {&lt;br /&gt;      handle_error (errno);&lt;br /&gt;      return 1;&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   while (1) {&lt;br /&gt;      get_event(fd, target);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* ----------------------------------------------------------------- */&lt;br /&gt;/* Allow for 1024 simultanious events */&lt;br /&gt;#define BUFF_SIZE ((sizeof(struct inotify_event)+FILENAME_MAX)*1024)&lt;br /&gt;&lt;br /&gt;void get_event (int fd, const char * target)&lt;br /&gt;{&lt;br /&gt;   ssize_t len, i = 0;&lt;br /&gt;   char action[81+FILENAME_MAX] = {0};&lt;br /&gt;   char buff[BUFF_SIZE] = {0};&lt;br /&gt;&lt;br /&gt;   len = read (fd, buff, BUFF_SIZE);&lt;br /&gt;   &lt;br /&gt;   while (i &lt; len) {&lt;br /&gt;      struct inotify_event *pevent = (struct inotify_event *)&amp;buff[i];&lt;br /&gt;      char action[81+FILENAME_MAX] = {0};&lt;br /&gt;&lt;br /&gt;      if (pevent-&gt;len) &lt;br /&gt;         strcpy (action, pevent-&gt;name);&lt;br /&gt;      else&lt;br /&gt;         strcpy (action, target);&lt;br /&gt;    &lt;br /&gt;      if (pevent-&gt;mask &amp; IN_ACCESS) &lt;br /&gt;         strcat(action, " was read");&lt;br /&gt;      if (pevent-&gt;mask &amp; IN_ATTRIB) &lt;br /&gt;         strcat(action, " Metadata changed");&lt;br /&gt;      if (pevent-&gt;mask &amp; IN_CLOSE_WRITE) &lt;br /&gt;         strcat(action, " opened for writing was closed");&lt;br /&gt;      if (pevent-&gt;mask &amp; IN_CLOSE_NOWRITE) &lt;br /&gt;         strcat(action, " not opened for writing was closed");&lt;br /&gt;      if (pevent-&gt;mask &amp; IN_CREATE) &lt;br /&gt;         strcat(action, " created in watched directory");&lt;br /&gt;      if (pevent-&gt;mask &amp; IN_DELETE) &lt;br /&gt;         strcat(action, " deleted from watched directory");&lt;br /&gt;      if (pevent-&gt;mask &amp; IN_DELETE_SELF) &lt;br /&gt;         strcat(action, "Watched file/directory was itself deleted");&lt;br /&gt;      if (pevent-&gt;mask &amp; IN_MODIFY) &lt;br /&gt;         strcat(action, " was modified");&lt;br /&gt;      if (pevent-&gt;mask &amp; IN_MOVE_SELF) &lt;br /&gt;         strcat(action, "Watched file/directory was itself moved");&lt;br /&gt;      if (pevent-&gt;mask &amp; IN_MOVED_FROM) &lt;br /&gt;         strcat(action, " moved out of watched directory");&lt;br /&gt;      if (pevent-&gt;mask &amp; IN_MOVED_TO) &lt;br /&gt;         strcat(action, " moved into watched directory");&lt;br /&gt;      if (pevent-&gt;mask &amp; IN_OPEN) &lt;br /&gt;         strcat(action, " was opened");&lt;br /&gt; &lt;br /&gt;   /*&lt;br /&gt;      printf ("wd=%d mask=%d cookie=%d len=%d dir=%s\n",&lt;br /&gt;              pevent-&gt;wd, pevent-&gt;mask, pevent-&gt;cookie, pevent-&gt;len, &lt;br /&gt;              (pevent-&gt;mask &amp; IN_ISDIR)?"yes":"no");&lt;br /&gt;&lt;br /&gt;      if (pevent-&gt;len) printf ("name=%s\n", pevent-&gt;name);&lt;br /&gt;   */&lt;br /&gt;&lt;br /&gt;      printf ("%s\n", action);&lt;br /&gt;      &lt;br /&gt;      i += sizeof(struct inotify_event) + pevent-&gt;len;&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;}  /* get_event */&lt;br /&gt;&lt;br /&gt;/* ----------------------------------------------------------------- */&lt;br /&gt;&lt;br /&gt;void handle_error (int error)&lt;br /&gt;{&lt;br /&gt;   fprintf (stderr, "Error: %s\n", strerror(error));&lt;br /&gt;&lt;br /&gt;}  /* handle_error */&lt;br /&gt;&lt;br /&gt;/* ----------------------------------------------------------------- */&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-1934966470417693342?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/1934966470417693342/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=1934966470417693342&amp;isPopup=true' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/1934966470417693342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/1934966470417693342'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2007/12/linux-inotify-example.html' title='Linux inotify example'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-5222229788588570734</id><published>2007-09-10T13:22:00.000+01:00</published><updated>2007-09-10T13:34:05.554+01:00</updated><title type='text'>Just for fun</title><content type='html'>Everone knows that the points system on &lt;a href="http://www.perlmonks.org"&gt;Perlmonks&lt;/a&gt; is just a bit of fun, but it does give me a warm feeling to login today and get:&lt;br /&gt;&lt;br /&gt;You have 20 votes left today.&lt;br /&gt;You gained 15 experience points, isn't that nice?&lt;br /&gt;Congratulations, you have been promoted to Chaplain!&lt;br /&gt;You have 598 points until level 12 - Deacon.&lt;br /&gt;&lt;br /&gt;That is from 272 writeups in about a year-and-a-half.&lt;br /&gt;&lt;br /&gt;I wish there was a site like perlmonks for PHP!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-5222229788588570734?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/5222229788588570734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=5222229788588570734&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/5222229788588570734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/5222229788588570734'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2007/09/just-for-fun.html' title='Just for fun'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-3827727964218378084</id><published>2007-08-31T08:15:00.000+01:00</published><updated>2007-08-31T08:33:12.495+01:00</updated><title type='text'>Parallelism</title><content type='html'>I have been attending an "Train The Trainer" (TTT) session at Intel in order to teach their new Parallel programming courses.  An excellent week, surrounded by some real experts in the field.  Several points stand out:&lt;br /&gt;&lt;br /&gt;The "free lunch" for developers really is over, and the industry will not know what hit it.  Software design and building is about to change, and it will be painful.  Strangly, a programmer who had been asleep for 20 years and has suddenly awoke would not see anything new.  That programmer might well be better equipped for the multi-core world than those that "kept current".    Why?  Because the skills practiced then will be even more important now, and the sloppy programming that has become so commonplace will no longer do the job.&lt;br /&gt;&lt;br /&gt;Revealing comment:&lt;br /&gt;The lead Intel instructor (an authority on parallel processing) was asked how people who have built everything on OO would cope with parallel processing.  The answer was:  "They are screwed!".&lt;br /&gt;&lt;br /&gt;Now you might say that we have been doing multi-threading for years.  Yes, but that is not parallel processing.  Multi-threading is usually about splitting I/O tasks: GUI windows, overlapped comms and disk I/O are typical.  Parallel processing is about splitting (decomposing) processor tasks, which is a whole new barrel of fish.   At least, it is for most people.&lt;br /&gt;&lt;br /&gt;This revolution has started, but is not yet in full flow, and won't be for a couple of years.  The reason is that there is well enough work for an extra CPU with other processes, like services, and the multi-threading we have right now.  The real need willl be with quad and 8 (oct?)-core processors.&lt;br /&gt;&lt;br /&gt;Watch this space&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-3827727964218378084?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/3827727964218378084/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=3827727964218378084&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/3827727964218378084'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/3827727964218378084'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2007/08/parallelism.html' title='Parallelism'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-7897340946617157052</id><published>2007-07-10T14:19:00.000+01:00</published><updated>2007-07-10T14:42:19.269+01:00</updated><title type='text'>The real jungle</title><content type='html'>Just back from teaching Perl in Singapore.  The real highlight for me, apart from teaching Perl of course, was the view of the Malaysian jungle on the flight in.  The area looks tiny on the map, but it is vast.  An amazing place.&lt;br /&gt;&lt;br /&gt;I found Singapore to be hot and steamy, and I &lt;span style="font-style: italic;"&gt;am&lt;/span&gt; talking about the climate.  The place has still not shaken off its colonial past.  Its own character does come through sometimes, and more power to it.  The people seem to be friendly and open without the hang-ups of many large cities.  Of course I was only there for a week and I only saw a small part of it.&lt;br /&gt;&lt;br /&gt;As usual I looked at scripts that delegates brought in.  I have also had a couple of scripts from other people recently.   I see very common bad practices regularly:&lt;br /&gt;&lt;br /&gt;No use warnings&lt;br /&gt;No use strict&lt;br /&gt;    All production scripts should have these set.&lt;br /&gt;&lt;br /&gt;Calling subroutines using the &amp; prefix.  Why do people do this?  Because that is the way we used to do it in perl 4, and people do not update their skills.  The &amp; prefix ignores prototype checking, and passes the current value of @_ into the call if no other argument is specified.  Don't do it!&lt;br /&gt;&lt;br /&gt;Calling external programs instead of Perl built-ins.  I have seen `date` used instead of localtime(), `cd $dir`, `pwd`, `mkdir`, `rm`, `egrep`, and so on.  This is not just lazy, it is grossly inefficient.  It is also a security risk, by the way.   I published a list of UNIX commands and perl equivalents, I will try and update it soon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-7897340946617157052?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/7897340946617157052/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=7897340946617157052&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/7897340946617157052'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/7897340946617157052'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2007/07/real-jungle.html' title='The real jungle'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-8669717631135632320</id><published>2007-06-25T22:07:00.000+01:00</published><updated>2007-06-25T22:09:25.648+01:00</updated><title type='text'>The threading jungle</title><content type='html'>&lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;Multi-threading has been around a long time.&lt;span style=""&gt;  &lt;/span&gt;I first heard the term in the mid-1980s when discussing how ICL were going to host UNIX on VME.&lt;span style=""&gt;  &lt;/span&gt;The first real implementation I saw was on Apollo NCS, a system that had many innovative features.&lt;span style=""&gt;  &lt;/span&gt;ICL, VME, and Apollo have all gone, victims of acquisitions.&lt;span style=""&gt;  &lt;/span&gt;Threads remain.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;Multi-threading hit the mainstream with Windows NT, the system was built on it.&lt;span style=""&gt;  &lt;/span&gt;The consensus around us UNIX hackers was that Microsoft had to encourage threads because their processes were so inefficient - no fork/exec you see.&lt;span style=""&gt;  &lt;/span&gt;Probably utter twaddle; you know what UNIX hackers are.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;Threads brought synchronisation problems.&lt;span style=""&gt;  &lt;/span&gt;Of course they did.&lt;span style=""&gt;  &lt;/span&gt;System programmers were no strangers to this type of issue, just the context of threads was new(ish).&lt;span style=""&gt;   &lt;/span&gt;Way back when, on ICL VME, all we had were "test and set" and "decrement and set" instructions that were atomic.&lt;span style=""&gt;  &lt;/span&gt;When I were a lad we had to build our own primitives, there was a particularly handy instruction that let you not only raise an interrupt (event/signal, whatever) but allowed you to send a two-word data block with it.&lt;span style=""&gt;  &lt;/span&gt;Kids of today … don't know they're born… forty miles 't pit… etc.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;I got to write real synchronisation primitives when I did the VME port of the MIMER RDBMS in the early '80s.&lt;span style=""&gt;  &lt;/span&gt;There is nothing like having to write the damn things to understand how they work.&lt;span style=""&gt;  &lt;/span&gt;I did not design them, I hastily add - that was done by some egg-head at &lt;/span&gt;&lt;st1:place&gt;&lt;st1:placename&gt;&lt;span style="font-family: Arial;"&gt;Uppsala&lt;/span&gt;&lt;/st1:PlaceName&gt;&lt;span style="font-family: Arial;"&gt; &lt;/span&gt;&lt;st1:placetype&gt;&lt;span style="font-family: Arial;"&gt;University&lt;/span&gt;&lt;/st1:PlaceType&gt;&lt;/st1:place&gt;&lt;span style="font-family: Arial;"&gt;. The problem then, as now, is not in using the APIs, it is in understanding how they interact with your application and (more important) how the application interacts with itself.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;First rule when writing co-operating threads: things only go wrong at the worse possible moment.&lt;span style=""&gt;  &lt;/span&gt;And that is usually &lt;i style=""&gt;after&lt;/i&gt; the thing has gone into production.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;The Windows APIs are fairly easy to use, certainly compared to knitting your own.&lt;span style=""&gt;  &lt;/span&gt;The main wrinkles in using them are a few peculiarities with the C/C++ runtime-library.&lt;span style=""&gt;  &lt;/span&gt;I find it amazing that so many system engineers insist in using CreateThread instead of _beginthreadex.&lt;span style=""&gt;  &lt;/span&gt;Back in Visual Studio 2.0 this was understandable, even I did it.&lt;span style=""&gt;  &lt;/span&gt;The documentation was, um, "challenged".&lt;span style=""&gt;  &lt;/span&gt;Now, with the MSDN, there is no excuse, the problems are well documented.&lt;span style=""&gt;  &lt;/span&gt;Still people insist on using the wrong API.&lt;span style=""&gt;  &lt;/span&gt;My theory, for what it is worth, is that a call to _beginthreadex, with its associated casts, looks messy on the screen, surrounded as it is by unrivalled elegance (sic).&lt;span style=""&gt;  &lt;/span&gt;CreateThread looks good, _beginthreadex is ugly.&lt;span style=""&gt;  &lt;/span&gt;For wotsit's sake!&lt;span style=""&gt;   &lt;/span&gt;A thing of beauty with a memory leak is bad code, and I don't care what it looks like.&lt;span style=""&gt;  &lt;/span&gt;Humph.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;Still, you thought&lt;b style=""&gt; &lt;/b&gt;&lt;i style=""&gt;that&lt;/i&gt; was ugly?&lt;span style=""&gt;  &lt;/span&gt;Try finding the thread-safe RTL functions in pthreads.&lt;span style=""&gt;  &lt;/span&gt;Threads had to be retro-fitted to UNIX.&lt;span style=""&gt;  &lt;/span&gt;Many fought against it, even the hero Torvold in the clone wars, but resistance was futile.&lt;span style=""&gt;  &lt;/span&gt;Microsoft made life easy for us developers by having a whole special runtime-library just for multi-threading, ungrateful pups that we are.&lt;span style=""&gt;  &lt;/span&gt;The pthreads implementations on UNIX have no such luxury.&lt;span style=""&gt;  &lt;/span&gt;Instead there is a whole mess of different functions that are re-entrant with the _t suffix.&lt;span style=""&gt;  &lt;/span&gt;Bye-bye portability.&lt;span style=""&gt;  &lt;/span&gt;Finding which functions these are is a bit hit and miss, sometimes they are not in the man pages, and the standard only lists minimum requirements.&lt;span style=""&gt;  &lt;/span&gt;Try teaching Condition Variables to a class already spaced out by mutxes.&lt;span style=""&gt;  &lt;/span&gt;The word "predicate" makes their eyes glaze over.&lt;span style=""&gt;  &lt;/span&gt;The fixed grin is the give-away: "Gone, solid gone", as Baloo would say.&lt;span style=""&gt;  &lt;/span&gt;I'm sure Kipling was a coder, who else would write a whole poem about a conditional statement?&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt;&lt;br /&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;span style=""&gt; &lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-8669717631135632320?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/8669717631135632320/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=8669717631135632320&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/8669717631135632320'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/8669717631135632320'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2007/06/threading-jungle.html' title='The threading jungle'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-3311112213390914774</id><published>2007-05-30T15:09:00.000+01:00</published><updated>2007-05-30T15:25:47.524+01:00</updated><title type='text'>What I did on my holiday</title><content type='html'>1.  Read "Perl Hacks" again, and caught a bunch of stuff I had missed first time around.  Like, wantarray returns undef in void context.&lt;br /&gt;&lt;br /&gt;2.  Read "Parallel Programming in C with MPI and OpenMP" by Michael J. Quinn&lt;br /&gt;Very American (the first computer was ENIAC - really?)  No mention of the ICL DAP (Distributed Array Processor) - one of the first commercially available parallel processors.&lt;br /&gt;Nice to see terms like "Functional Decomposition" from the 1970s recycled to be used in a parallel computing methodology.&lt;br /&gt;It really bugs me when authors come up with "Creating Arrays at Run Time" and give code like this:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;int *A;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;A = (int *) malloc (n * sizeof(int));&lt;/span&gt;&lt;br /&gt;When there is a perfectly good feature in C99 to do it:&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: courier new;"&gt;int A[n];&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;That's it!  This is a C99 Variable Length Array, one of the more obvious features of the changes from C89.  The book was published in 2004, so why no mention?&lt;br /&gt;The author uses for loops to access arrays quite often, but there is no mention of optimisers, and the effect of optimisations on parallel processing.  Ho hum.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-3311112213390914774?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/3311112213390914774/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=3311112213390914774&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/3311112213390914774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/3311112213390914774'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2007/05/what-i-did-on-my-holiday.html' title='What I did on my holiday'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-117577792849101380</id><published>2007-04-05T13:54:00.000+01:00</published><updated>2007-04-05T13:58:48.500+01:00</updated><title type='text'>Where have you been?</title><content type='html'>Guilty.  I haven't blogged for a long time.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;What's happened?&lt;/span&gt;&lt;br /&gt;Well for starters the company I work for got taken over, and that caused a lot of dust - mostly settled now.&lt;br /&gt;&lt;br /&gt;I have been getting into the new Korn shell 93, and I hope to post something on that soon.&lt;br /&gt;&lt;br /&gt;Just today I got my "Happy Monkday" from perlmonks - I have been a monk for a year.  Good fun!&lt;br /&gt;&lt;br /&gt;Oh where is Perl 5.10?  Soon? Please!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-117577792849101380?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/117577792849101380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=117577792849101380&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/117577792849101380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/117577792849101380'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2007/04/where-have-you-been.html' title='Where have you been?'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-115704232904194482</id><published>2006-08-31T17:34:00.000+01:00</published><updated>2006-08-31T17:38:49.050+01:00</updated><title type='text'>Notifications</title><content type='html'>This is a reminder post for (selfishly) me!  Follow along if you like.&lt;br /&gt;(CPAN) Win32::ChangeNotify - does it support (Win32 API) ReadDirectoryChangesW and overlapped IO?  If not, how does it avoid missing changes?&lt;br /&gt;&lt;br /&gt;(CPAN)Linux::Inotify (and Inotify2) support the Linux kernel API inotify which (perhaps) replaces dnotify.  Supported from kernel 2.6.13.&lt;br /&gt;Neither interface is on Fedora core 4, which is 2.6.11.&lt;br /&gt;&lt;br /&gt;Further digging required.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-115704232904194482?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/115704232904194482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=115704232904194482&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/115704232904194482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/115704232904194482'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2006/08/notifications.html' title='Notifications'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-115376994499851344</id><published>2006-07-24T20:37:00.000+01:00</published><updated>2006-07-24T21:23:00.503+01:00</updated><title type='text'>Fun with Perl module loading</title><content type='html'>&lt;span style="font-weight: bold;font-family:arial;" &gt;Q.  So exactly when does a BEGIN block get executed?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;A.  As soon as it is encountered!  &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;For example, take the following code:&lt;/span&gt;&lt;br /&gt;&lt;pre style="font-family: courier new;"&gt;&lt;br /&gt;  use AModule;&lt;br /&gt;  use BModule;&lt;br /&gt;&lt;br /&gt;  BEGIN {&lt;br /&gt;     print __PACKAGE__." BEGIN block\n";&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  use AnOther;&lt;br /&gt;&lt;br /&gt;  $syntax_error = 42&lt;br /&gt;&lt;br /&gt;  print "Starting main program\n";&lt;br /&gt;  print "Ending main program\n";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;The order of execution is:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;pre&gt;   AModule BEGIN block&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   AModule main body&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   BModule BEGIN block&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   BModule main body&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   main BEGIN block&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   AnOther BEGIN block&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   AnOther main body&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   syntax error at main.pl line 18, near "print"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   Execution of main.pl aborted due to compilation errors.&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family: arial;font-family:arial;" &gt;So, the main program's BEGIN block is not necessarily the last one executed.  Granted, normally it is, since we usually use all our modules before the BEGIN block in main, but we don't have to. &lt;br /&gt;Note also that the blocks are executed even though we have a syntax error, and the program fails to compile.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: arial;font-family:arial;" &gt;Q.  What use is that?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: arial;font-family:arial;" &gt;A.  We can alter the way subsequent modules are loaded&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: arial;font-family:arial;" &gt;Usually that will be by altering @INC:&lt;/span&gt;&lt;br /&gt;&lt;pre style="font-family: courier new;"&gt;&lt;br /&gt;  BEGIN {&lt;br /&gt;     if ( defined $ENV{TESTLIB} ) {&lt;br /&gt;         unshift @INC, $ENV{TESTLIB}&lt;br /&gt;     }&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Now all subsequent module loads will search the directory in the environment variable first.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;Q. @INC is just a list of directories, Right?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;A.  Wrong!  It can also contain code references.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;References to subroutines found by the module loader will be executed as they are found:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: courier new;"&gt;&lt;br /&gt;  BEGIN {&lt;br /&gt;     print __PACKAGE__." BEGIN block\n";&lt;br /&gt;     my $code = sub { print "\@INC code\n" };&lt;br /&gt;     unshift @INC,$code;&lt;br /&gt;  }&lt;br /&gt;  use AnOther;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Gives:&lt;/span&gt;&lt;br /&gt;&lt;pre style="font-family: courier new;"&gt;&lt;br /&gt;  main BEGIN block&lt;br /&gt;  @INC code&lt;br /&gt;  AnOther BEGIN block&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;Q.  Is that it?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;A.  Of course not.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;The subroutine is passed two arguments, the code reference itself and the name of the module it is trying to load.  This enables us to track every module loaded.  So:&lt;/span&gt;&lt;br /&gt;&lt;pre style="font-family: courier new;"&gt;&lt;br /&gt;  BEGIN {&lt;br /&gt;     print __PACKAGE__." BEGIN block\n";&lt;br /&gt;     my $code = sub {&lt;br /&gt;        my (undef, $loading) = @_;&lt;br /&gt;        my ($package, $filename, $line) = caller;&lt;br /&gt;&lt;br /&gt;        print "Loading $loading from $package\n"&lt;br /&gt;     };&lt;br /&gt;     unshift @INC,$code;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  use AModule;&lt;br /&gt;  use BModule;&lt;br /&gt;  use AnOther;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Gives:&lt;/span&gt;&lt;br /&gt;&lt;pre style="font-family: courier new;"&gt;&lt;br /&gt;  main BEGIN block&lt;br /&gt;  Loading AModule.pm from main&lt;br /&gt;  AModule BEGIN block&lt;br /&gt;  AModule main body&lt;br /&gt;&lt;br /&gt;  Loading BModule.pm from main&lt;br /&gt;  BModule BEGIN block&lt;br /&gt;  BModule main body&lt;br /&gt;&lt;br /&gt;  Loading AnOther.pm from main&lt;br /&gt;  AnOther BEGIN block&lt;&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Of course, further diagnostics could be added, like filename, line, and date/time.  I'll leave that to you.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;Q. So, @INC is more powerful than its sister %INC, which is just used for diagnostics.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;A.  Err, no.  %INC is used by perl to see if a module is already loaded.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;Q.  And how is that useful?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;A.  We can force a module reload by removing its entry from %INC.  Consider:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;In one part of our code we want to force a different version of a module to be loaded (don't ask why).&lt;/span&gt;&lt;br /&gt;&lt;pre style="font-family: courier new;"&gt;  use strict;&lt;br /&gt; use warnings;                # DON'T use -w&lt;br /&gt;&lt;br /&gt; use A;&lt;br /&gt; use MyB;&lt;br /&gt; use C;&lt;br /&gt;&lt;br /&gt; A::mysub();                  # Original modules used&lt;br /&gt;&lt;br /&gt; delete $INC{'A.pm'};         # Force perl to reload&lt;br /&gt;&lt;br /&gt; unshift @INC,'mydir';        # Change @INC&lt;br /&gt; {&lt;br /&gt;    no warnings 'redefine';   # No 'redefined' warnings&lt;br /&gt;    require 'A.pm';           # Reload module&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; A::mysub();                  # Module in 'mydir' used&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Work it out yourself!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Arial;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-115376994499851344?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/115376994499851344/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=115376994499851344&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/115376994499851344'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/115376994499851344'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2006/07/fun-with-perl-module-loading.html' title='Fun with Perl module loading'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-114670646755925155</id><published>2006-05-04T02:34:00.000+01:00</published><updated>2006-05-04T02:42:25.586+01:00</updated><title type='text'>Splitting whitespace</title><content type='html'>&lt;span style="font-family:Arial;"&gt;The documentation for Perl is quite good usually, but when it comes to perldoc –f split there is so much magic involved that normal English begins to break down.  Take the default arguments, for example.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;"If EXPR is omitted, splits the $_ string. If PATTERN is also omitted, splits on whitespace (after skipping any leading whitespace)."&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;Then, later in the documentation:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;"As a special case, specifying a PATTERN of space (' ') will split on white space just as "split" with no arguments does.  … A "split" with no arguments really does a "split(' ', $_)" internally."&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;So, how many whitespace characters is that?  A single space as a delimiter implies a single space is used for the split, but it actually does 'one or more whitespace':&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;pre&gt;&lt;span style="font-family:Courier New;"&gt;   $_ = '    This    is    some    text';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;   @a = split;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;   $" = '|';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;   print "@a\n";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;/pre&gt;Produces&lt;pre&gt;&lt;span style="font-family:Courier New;"&gt;   This|is|some|text&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;span style="font-family:Arial;"&gt;So leading whitespace is ignored, and one or more whitespace is used as a delimiter.  There is a (documented) subtle difference with \s+:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;pre&gt;&lt;span style="font-family:Courier New;"&gt;   $_ = '    This    is    some    text';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;   @a = split /\s+/;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;   $" = '|';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;   print "@a\n";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;/pre&gt;Produces:&lt;pre&gt;&lt;span style="font-family:Courier New;"&gt;   |This|is|some|text&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;span style="font-family:Arial;"&gt;Notice that the first element of the resulting list is empty, which was not previously the case.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;A few questions arise from this.  First, what is this &lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;' ' &lt;/span&gt;&lt;span style="font-family:Arial;"&gt;syntax all about?  Don't we need a regular expression match?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;pre&gt;&lt;span style="font-family:Courier New;"&gt;   $_ = 'xxxThisxxisxxsomexxtext';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;   @a = split 'x';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;   $" = '|';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;   print "@a\n";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;/pre&gt;Produces:&lt;pre&gt;&lt;span style="font-family:Courier New;"&gt;    |||This||is||some||te|t&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;span style="font-family:Arial;"&gt;So it does work, except not &lt;/span&gt;&lt;em&gt;&lt;span style="font-family:Arial;"&gt;exactly &lt;/span&gt;&lt;/em&gt;&lt;span style="font-family:Arial;"&gt;the same as a single space, it does not match 'one or more' (x+), so the space is magic.  To be fair the documentation does say that &lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;' ' &lt;/span&gt;&lt;span style="font-family:Arial;"&gt;is a special case.  But the documentation &lt;/span&gt;&lt;em&gt;&lt;span style="font-family:Arial;"&gt;does not &lt;/span&gt;&lt;/em&gt;&lt;span style="font-family:Arial;"&gt;show the syntax of a string literal, it specifically shows that an RE delimited with / / is required.  Single quotes works with regular expressions, and with multiple characters (without a leading 'm').  But double quotes or other characters do not work unless preceded with 'm'.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;Second question.  What does whitespace mean?  Is &lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;' ' &lt;/span&gt;&lt;span style="font-family:Arial;"&gt;the same as &lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;\s &lt;/span&gt;&lt;span style="font-family:Arial;"&gt;in this case?  Normally, of course, it is not, but in this case it is!  &lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;' ' &lt;/span&gt;&lt;span style="font-family:Arial;"&gt;is &lt;/span&gt;&lt;em&gt;&lt;span style="font-family:Arial;"&gt;very &lt;/span&gt;&lt;/em&gt;&lt;span style="font-family:Arial;"&gt;special.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-114670646755925155?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/114670646755925155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=114670646755925155&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/114670646755925155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/114670646755925155'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2006/05/splitting-whitespace.html' title='Splitting whitespace'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-114609632494728796</id><published>2006-04-27T01:02:00.000+01:00</published><updated>2006-04-27T01:05:24.960+01:00</updated><title type='text'>Inside-out accessor methods - version 2</title><content type='html'>&lt;span style="font-family:arial;"&gt;This solution uses a hash of hash-references, which means we no longer need the nasty eval.  With thanks to the perl monks.&lt;br /&gt;&lt;/span&gt;&lt;pre&gt;&lt;br /&gt;my (%speed, %reg, %owner, %mileage);&lt;br /&gt;my %hashrefs = ( speed   =&gt; \%speed,&lt;br /&gt;                 reg     =&gt; \%reg,&lt;br /&gt;                 owner   =&gt; \%owner,&lt;br /&gt;                 mileage =&gt; \%mileage);&lt;br /&gt;                   &lt;br /&gt;sub set {&lt;br /&gt;   my ($self, $attr, $value) = @_;&lt;br /&gt;   my $key = refaddr $self;&lt;br /&gt;     &lt;br /&gt;   if ( !exists $hashrefs{$attr} ) {&lt;br /&gt;      carp "Invalid attribute name $attr";&lt;br /&gt;   }&lt;br /&gt;   else {&lt;br /&gt;      $hashrefs{$attr}{$key} = $value;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-114609632494728796?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/114609632494728796/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=114609632494728796&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/114609632494728796'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/114609632494728796'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2006/04/inside-out-accessor-methods-version-2.html' title='Inside-out accessor methods - version 2'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-114609256795807417</id><published>2006-04-26T23:58:00.000+01:00</published><updated>2006-04-27T00:16:28.070+01:00</updated><title type='text'>UNIX commands to Perl</title><content type='html'>&lt;span style="font-family:arial;"&gt;This is a rough conversion table from UNIX commands to Perl.&lt;br /&gt;Please note that there are not always direct single equivalents.&lt;br /&gt;&lt;/span&gt;&lt;pre&gt;&lt;br /&gt;&lt;strong&gt;UNIX         Perl                         Origin&lt;/strong&gt;&lt;br /&gt;.            do                           built-in&lt;br /&gt;awk          perl ;-) (often 'split')     built-in&lt;br /&gt;basename     File::Basename::basename     Base module&lt;br /&gt;cat          while(&lt;&gt;){print}             built-in&lt;br /&gt;             ExtUtils::Command::cat       Base module&lt;br /&gt;cd           chdir                        built-in&lt;br /&gt;chmod        chmod                        built-in&lt;br /&gt;chown        chown                        built-in&lt;br /&gt;cp           File::Copy                   Base module&lt;br /&gt;             ExtUtils::Command::cp        Base module&lt;br /&gt;date         localtime                    built-in&lt;br /&gt;             POSIX::strftime              Base module&lt;br /&gt;declare      see typedef &lt;br /&gt;df           Filesys::Df                  CPAN&lt;br /&gt;diff         File::Compare                Base module&lt;br /&gt;dirname      File::Basename::dirname      Base modules&lt;br /&gt;echo         print                        built-in&lt;br /&gt;egrep        while(&lt;&gt;){print if /re/}     built-in&lt;br /&gt;eval         eval                         built-in&lt;br /&gt;exec         exec                         built-in&lt;br /&gt;             pipe (co-processes)          built-in&lt;br /&gt;export       Assign to %ENV               Hash variable&lt;br /&gt;             Env::C                       CPAN&lt;br /&gt;find         File::Find                   Base module&lt;br /&gt;ftp          Net::Ftp                     Base module&lt;br /&gt;function     sub                          built-in&lt;br /&gt;grep         see egrep    &lt;br /&gt;integer      int                          built-in&lt;br /&gt;kill         kill                         built-in&lt;br /&gt;ln -s        link                         built-in&lt;br /&gt;ls           glob                         built-in&lt;br /&gt;             opendir/readdir/closedir     built-in&lt;br /&gt;             stat/lstat                   built-in&lt;br /&gt;mkdir        mkdir                        built-in&lt;br /&gt;mkpath       ExtUtils::Command::mkpath    Base module&lt;br /&gt;mv           rename                       built-in&lt;br /&gt;             ExtUtils::Command::mv        Base module&lt;br /&gt;od           ord                          built-in&lt;br /&gt;             printf                       built-in&lt;br /&gt;print        print                        built-in&lt;br /&gt;printf       printf                       built-in&lt;br /&gt;rand         rand                         built-in&lt;br /&gt;rm           unlink                       built-in&lt;br /&gt;             ExtUtils::Command::rm        Base module&lt;br /&gt;rm –f        ExtUtils::Command::rm_rf     Base module&lt;br /&gt;sed          s/// (usually)               built-in&lt;br /&gt;sleep        sleep                        built-in&lt;br /&gt;             alarm                        built-in&lt;br /&gt;sort         sort                         built-in&lt;br /&gt;source       do                           built-in&lt;br /&gt;times        times                        built-in&lt;br /&gt;touch        open()/close()               built-in&lt;br /&gt;             ExtUtils::Command::touch     Base module&lt;br /&gt;trap         %SIG                         Hash&lt;br /&gt;             sigtrap                      pragma&lt;br /&gt;typeset      my                           built-in&lt;br /&gt;typeset –I   int                          built-in&lt;br /&gt;typeset –l   lc                           built-in&lt;br /&gt;typeset –u   uc                           built-in&lt;br /&gt;typeset -Z   sprintf                      built-in&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-114609256795807417?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/114609256795807417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=114609256795807417&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/114609256795807417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/114609256795807417'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2006/04/unix-commands-to-perl_114609256795807417.html' title='UNIX commands to Perl'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-114474043954731568</id><published>2006-04-11T08:25:00.000+01:00</published><updated>2006-04-11T08:28:22.760+01:00</updated><title type='text'>Sad....</title><content type='html'>Walking across London I spotted a poster which screamed:&lt;br /&gt;&lt;strong&gt;100 Gig tickets to be won!&lt;/strong&gt;&lt;br /&gt;"Must be a big stadium", I thought....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-114474043954731568?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/114474043954731568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=114474043954731568&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/114474043954731568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/114474043954731568'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2006/04/sad.html' title='Sad....'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-114474033252109999</id><published>2006-04-11T08:24:00.000+01:00</published><updated>2006-04-11T08:25:32.543+01:00</updated><title type='text'>Accessor methods - update</title><content type='html'>I have a much better solution, with the help of the perlmonks.  I'll post it when I get chance&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-114474033252109999?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/114474033252109999/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=114474033252109999&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/114474033252109999'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/114474033252109999'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2006/04/accessor-methods-update.html' title='Accessor methods - update'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-114313100318468828</id><published>2006-03-23T15:54:00.000Z</published><updated>2006-03-23T16:24:39.510Z</updated><title type='text'>Accessor methods for inside-out objects</title><content type='html'>&lt;span style="font-family:arial;"&gt;I have just been looking at Class::Accessor, recommended by Simon Cozens at &lt;/span&gt;&lt;ahref="http://www.perl.com/pub/a/2006/01/26/more_advanced_perl.html"&gt;&lt;span style="font-family:arial;"&gt;http://www.perl.com/pub/a/2006/01/26/more_advanced_perl.html&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:arial;"&gt;. It automagically generates accessor methods, but appears to rely on a %fields type approach, and will not work on inside-out objects.&lt;br /&gt;I got to thinking. Actually generalised accessors for inside-out objects are not that difficult, not need some ev[ai]l doings.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   my %speed;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   my %reg;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   my %owner;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   my %mileage;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   sub set {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      my ($self, $attr, $value) = @_;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      my $key = refaddr $self;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;      my $hashref;&lt;br /&gt;      eval "\$hashref = \\\%$attr&lt;/a&gt;";&lt;br /&gt;&lt;br /&gt;      if ( !defined $hashref ) {&lt;br /&gt;         carp 'Invalid attribute name';&lt;br /&gt;         return;&lt;br /&gt;      }&lt;br /&gt;        &lt;br /&gt;      $hashref-&gt;{$key} = $value;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   sub get {&lt;br /&gt;      my ($self, $attr, $value) = @_;&lt;br /&gt;      my $key = refaddr $self;&lt;br /&gt;&lt;br /&gt;      my $hashref;&lt;br /&gt;      eval "\$hashref = \\\%$attr&lt;/a&gt;";&lt;br /&gt;&lt;br /&gt;      if ( !defined $hashref ) {&lt;br /&gt;         carp 'Invalid attribute name';&lt;br /&gt;         return;&lt;br /&gt;      }&lt;br /&gt;        &lt;br /&gt;      return $hashref-&gt;{$key};&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;BTW: I also found how to do formatting:  &amp;lt;pre&amp;gt;...&amp;lt;/pre&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-114313100318468828?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/114313100318468828/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=114313100318468828&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/114313100318468828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/114313100318468828'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2006/03/accessor-methods-for-inside-out.html' title='Accessor methods for inside-out objects'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-114183421459696031</id><published>2006-03-08T15:57:00.000Z</published><updated>2006-03-08T16:10:14.610Z</updated><title type='text'>More of the same..</title><content type='html'>I havn't posted for a while.  It's not that nothing has happened, its just that too much has!  I'm afraid that the blog suffers when I'm busy.  I have been madly updating our 'Advanced Perl with CGI and Web Applications' course, and I am quite pleased with the result.  As always I reckon I learnt at least as much as the delegates will (although maybe on more obscure subjects).&lt;br /&gt;For example, did you know you can use __DIE__ and __WARN__ signal handlers to trap Carp::croak and Carp::carp calls?&lt;br /&gt;&lt;br /&gt;I returned home from teaching in the USA last Saturday to my latest multiple order from Amazon: &lt;br /&gt;Object Oriented Perl by Damian Conway.  A little out of date (2000) but good nontheless, written in typical Damian style.  Hacking the Advanced Perl course (two chapters on OO) and reading this book has totally changed my views on Perl as an OO language.   The book does not contain anything on inside-out objects, but you can see that Damian was almost there.  We now have a chapter on this simple but effective means of encapsulation in the Advanced course.&lt;br /&gt;&lt;br /&gt;Number two book is the "Pickaxe book", Programming Ruby.  About time I read it, more on that later (hopefully).&lt;br /&gt;&lt;br /&gt;Number three is "PHP and MySQL Web Development".  A huge tome which (unlike OOP and Ruby) does not look like 'fun'.&lt;br /&gt;Last but not least another O'Reilly pocket book, this time the Linux one.  All these pocket books, I need huge pockets.  Not to mention another bookshelf....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-114183421459696031?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/114183421459696031/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=114183421459696031&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/114183421459696031'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/114183421459696031'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2006/03/more-of-same.html' title='More of the same..'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-113743390312582354</id><published>2006-01-16T17:46:00.000Z</published><updated>2006-01-16T17:51:43.143Z</updated><title type='text'>What a refreshing change</title><content type='html'>I'm on the West coast of Ireland, Galway, teaching.  I don't think anyone will be offended if I say that Galway is a little remote.&lt;br /&gt;The air and the Guiness are all refreshing, but what stopped me in my tracks is the co-operation between businesses.  One major international company booked me to give a course, but then said to others in Galway, "Hey, we have a technical course running this week, anyone else interested?" , and so along comes a few guys from other companies that could not justify the course on their own.  Apparently this happens all the time.&lt;br /&gt;These companies are major internationals acting like sensibile human beings.  Now why can't that happen everywhere?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-113743390312582354?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/113743390312582354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=113743390312582354&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/113743390312582354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/113743390312582354'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2006/01/what-refreshing-change.html' title='What a refreshing change'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-113638436056285252</id><published>2006-01-04T14:19:00.000Z</published><updated>2006-01-04T14:28:15.673Z</updated><title type='text'>IFS and read</title><content type='html'>&lt;span style="font-family:Arial;"&gt;I find myself continually underestimating the Korn shell. I always thought that Bash was neat because we could read into an array with &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:Courier New;"&gt;read –a&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:Arial;"&gt;, but of course we can do the same in ksh with &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:Courier New;"&gt;read –A&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:Arial;"&gt;.  The effect is to split up the input into fields around &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:Courier New;"&gt;$IFS&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:Arial;"&gt;.  But did you know we can set IFS just for a read statement?  Look carefully:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-family:Courier New;"&gt;IFS=','&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-family:Courier New;"&gt;while IFS=':' read -A line&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-family:Courier New;"&gt;do&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-family:Courier New;"&gt;   end=$(( ${#line[*]} - 1 ))&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-family:Courier New;"&gt;   if [[ ${line[$end]} != /sbin/nologin ]]&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-family:Courier New;"&gt;   then&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-family:Courier New;"&gt;      echo "${line[*]}"&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-family:Courier New;"&gt;   fi&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-family:Courier New;"&gt;done &amp;lt; /etc/passwd&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;(display all the lines in /etc/passwd whose last field is not /sbin/nologin, changing the field delimiter from colon to comma).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;The first &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:Courier New;"&gt;IFS=',' &lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:Arial;"&gt;sets IFS for the echo expansion and is &lt;/span&gt;&lt;em&gt;&lt;span style="font-family:Arial;"&gt;not &lt;/span&gt;&lt;/em&gt;&lt;span style="font-family:Arial;"&gt;overridden by the IFS on the read line.  That IFS only applies for the &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:Courier New;"&gt;read&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:Arial;"&gt;, nothing else.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;By the way, did you know that the expansion (including $*) uses the &lt;/span&gt;&lt;em&gt;&lt;span style="font-family:Arial;"&gt;first &lt;/span&gt;&lt;/em&gt;&lt;span style="font-family:Arial;"&gt;character from IFS, so order matters?  So &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:Courier New;"&gt;IFS=',.:' &lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:Arial;"&gt;gives different results to &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:Courier New;"&gt;IFS=':,.'&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:Arial;"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;All this applies to the standard POSIX shell, as well as Korn shell and Bash, and I was alerted to these features by &lt;span style="font-style: italic;"&gt;Classic Shell Scripting&lt;/span&gt; (see a previous post).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;Finally, a significant bug in pdksh has been fixed in the version with Fedora core 4 (1993-12-28 q). In early versions a pipe generated a child process on each side, so piping into a while loop was not useful, since the while loop ran in a different process to the rest of the script, and so variables could not be saved. Now it all works, consider:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;#!/bin/ksh&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;ps -ef | while read uid pid ppid c stime tty time cmd&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;         do&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;            if [[ $cmd == *xinetd* ]]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;            then&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;               break&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;            fi&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;         done&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;echo "Pid of xinetd is: $pid"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;Unfortunately this will &lt;/span&gt;&lt;em&gt;&lt;span style="font-family:Arial;"&gt;still &lt;/span&gt;&lt;/em&gt;&lt;span style="font-family:Arial;"&gt;not work in Bash, for the same reason as it did not work in the old pdksh. In Bash we can use process substitution instead, and while we are about it we may as well use an ERE (because we can):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;while read uid pid ppid c stime tty time cmd&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;do&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;   if [[ $cmd =~ '^xinetd +' ]]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;   then&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;      break&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;   fi&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;done &amp;lt; &amp;lt;(ps -ef)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;echo "Pid of xinetd is: $pid"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;The man pages for the new pdksh say process substitution works in Korn shell as well, and I am told this works on Solaris, but it does not appear to work on Linux.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-113638436056285252?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/113638436056285252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=113638436056285252&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/113638436056285252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/113638436056285252'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2006/01/ifs-and-read.html' title='IFS and read'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-113594457957160875</id><published>2005-12-30T12:03:00.000Z</published><updated>2005-12-30T12:21:00.530Z</updated><title type='text'>Toys for boys</title><content type='html'>The weather has been kind over Christmas, particularly clear skys for my *new* Meade ETX 105 - that's a telescope by the way. Not exactly the largest - only 4" and yes, size does matter, but I couldn't really justify a larger one given that it usually rains on the rare occasions when I am actually at home.&lt;br /&gt;Good views of Mars in November and early December, now good views of Saturn, and various nebula like M42 and M37.  OK, so what's that got to do with programming and stuff?&lt;br /&gt;Well, most modern telescopes have an electronic control called a "goto" system - you get the idea. This is normally controlled by a hand-held device, but can be controlled by a PC using an Open Source object model named ASCOM - Astronomy Common Object Module. &lt;br /&gt;&lt;a href="http://ascom-standards.org/faq.html"&gt;http://ascom-standards.org/faq.html&lt;/a&gt;&lt;br /&gt;Currently it appears to be written using COM, which of course is proprietry and realistically only runs on one of the many Microsoft operating systems.  OK, you can get it to run on others, but would you want to, really?&lt;br /&gt;This is one I will be looking at further.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-113594457957160875?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/113594457957160875/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=113594457957160875&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/113594457957160875'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/113594457957160875'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/12/toys-for-boys.html' title='Toys for boys'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-113517652285483383</id><published>2005-12-21T14:38:00.001Z</published><updated>2010-01-29T09:39:16.650Z</updated><title type='text'>Switching off terminal echo in Perl</title><content type='html'>A delegate recently asked me how to switch echo off for password prompting.  I couldn't remember, I thought it was Term::ReadLine.  Actually it is Term::ReadKey - as expected the Perl Cookbook reminded me.  Term::ReadKey is not a base module, but is present on ActiveState and Fedora installations, and easily installed from CPAN.  Here is a simple script that works on both Linux and Windows (despite what the documentation says) :&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;use Term::ReadKey;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;print 'Password: ';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ReadMode 'noecho';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;my $password = ReadLine;   # Corrected&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ReadMode 'normal';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;chomp $password;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;print "Password was: $password\n";&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Another delegate said something like "I guess another module will replace characters typed with asterisks".  Well, that is not so simple. After some experimentation I came up with the following script, which has to use raw terminal input and take iinto account differences between Windows and Unix/Linux:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;use Term::ReadKey;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;use strict;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;local $| = 1;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;print 'Password: ';&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;my $password = '';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;my $retn = $^O eq 'MSWin32'?"\r":"\n";&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ReadMode 'raw';&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;while (1)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   my $key;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   # Loop waiting for a key to be pressed&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   while (!defined $key)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      $key = ReadKey -1;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   last if $key eq $retn;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   $password .= $key;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   print '*';&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ReadMode 'normal';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;print "\n";&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;print "Password was: $password\n";&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Check the Term::ReadKey documentation for the arguments. Note that I have to wait for a key to be pressed this time, and write an unbuffered '*' (&lt;span style="font-family:courier new;"&gt;local $| = 1&lt;/span&gt; makes STDOUT unbuffered).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-113517652285483383?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/113517652285483383/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=113517652285483383&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/113517652285483383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/113517652285483383'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/12/switching-off-terminal-echo-in-perl.html' title='Switching off terminal echo in Perl'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-113212836544914277</id><published>2005-11-16T08:06:00.000Z</published><updated>2005-11-16T08:09:45.736Z</updated><title type='text'>Perl subroutine parameter passing - again</title><content type='html'>&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;One of the reasons Damian Conway does not like prototypes is that (his words) they do not give the results expected. Well, what results do you expect when you don't use them?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;It is sometimes said that parameters are passed into Perl subroutines by copy, and some say they are passed by reference. In fact they are passed by magic, and as we all know, any technology sufficiently advanced is indistinguishable from Perl.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;What do you expect to be printed?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;sub mysub&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;@_ = qw(one two three)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;@array = qw(The quick brown fox);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;mysub (@array);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;print "@array\n";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;We get '&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;The quick brown fox &lt;/span&gt;&lt;span style="font-family:Arial;"&gt;'. The array is unchanged, so you might think the array is passed by value. The call:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;mysub (qw(The quick brown fox));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;also works fine, so no problem. Let's change the subroutine to use a slice instead:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;sub mysub&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;@_[0,1,2] = qw(one two three)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;Now we get '&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;one two three fox&lt;/span&gt;&lt;span style="font-family:Arial;"&gt;', the array &lt;/span&gt;&lt;em&gt;&lt;span style="font-family:Arial;"&gt;is &lt;/span&gt;&lt;/em&gt;&lt;span style="font-family:Arial;"&gt;changed! Changing the elements changes the caller's array, changing the whole array does nothing! Now the line:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;mysub (qw(The quick brown fox));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;fails with "&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;Modification of a read-only value attempted…&lt;/span&gt;&lt;span style="font-family:Arial;"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;This is a &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:Arial;"&gt;run-time &lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:Arial;"&gt;error, whereas if you use a prototype:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;sub mysub (\@)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;we get a &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:Arial;"&gt;compile-time &lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:Arial;"&gt;error:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;"&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;… must be an array (not list)…&lt;/span&gt;&lt;span style="font-family:Arial;"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;If I preferred run-time over compile-time errors I would be using the Korn shell.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;Once the prototype has been specified it does not matter if we alter the caller's array in total or use a slice – the caller's code is always the same. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;OK, I admit that altering @_ direct is damn awful code, and it breaks another of Damian's rules. He's not all bad ;-) &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;I don't believe that an inconsistency in one part of Perl (prototypes) is a justification to switch to an inconsistency in another (pass by magic). Just admit the inconsistencies and celebrate them – or move to Perl 6.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-113212836544914277?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/113212836544914277/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=113212836544914277&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/113212836544914277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/113212836544914277'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/11/perl-subroutine-parameter-passing.html' title='Perl subroutine parameter passing - again'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-112978760643800461</id><published>2005-10-20T06:52:00.000+01:00</published><updated>2005-10-20T06:53:26.456+01:00</updated><title type='text'>Perl 6 at EuroOSCON</title><content type='html'>&lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;This is a brief summary of my notes from the Perl 6 and pugs sessions.&lt;span style=""&gt;  &lt;/span&gt;I have only included the stuff that was new compared to the Perl 6 Appendix in the 'Perl Programming' course.&lt;span style=""&gt;  &lt;/span&gt;I might have repeated myself.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;br /&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;use stric&lt;/span&gt;&lt;span style="font-family: Arial;"&gt;&lt;span style="font-family: courier new;"&gt;t &lt;/span&gt;and &lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;use warnings&lt;/span&gt;&lt;span style="font-family: Arial;"&gt; are on by default;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;Quotes are only required around a hash key when {} are used.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;$hash{'key'}&lt;/span&gt;&lt;span style="font-family: Arial;"&gt; becomes&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt; %hash&lt;key&gt;&lt;/span&gt;&lt;span style="font-family: Arial;"&gt;&lt;span style=""&gt;  &lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;Barewords are not allowed.&lt;span style=""&gt;  &lt;/span&gt;Ever.&lt;span style=""&gt;   &lt;/span&gt;Even for file handles.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;fail{…}&lt;span style=""&gt;  &lt;/span&gt;warn{…}&lt;span style=""&gt;  &lt;/span&gt;die{…}&lt;/span&gt;&lt;span style="font-family: Arial;"&gt;&lt;span style=""&gt;  &lt;/span&gt;throw a 'not yet implemented' type warning – the Perl 6 developers must be using that a lot ;-)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;b style=""&gt;&lt;span style="font-family: Arial;"&gt;Many improvements to interpolation:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;"{ executable code like a do block} "&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;Subroutine calls are allowed:&lt;span style=""&gt;           &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;"&amp;mysub(args)"&lt;/span&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;Interpolate an array:&lt;span style=""&gt;              &lt;/span&gt;&lt;span style=""&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;"@array[]"&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;Interpolate a hash:&lt;span style=""&gt;                 &lt;/span&gt;&lt;span style=""&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;"%hash{}"&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;sprintf is probably obsolete, printf definitely is:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;span style=""&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;print $var.as('%6.2f');&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;     &lt;/span&gt;print $hash.as("%-20s: %2.6f", "\n");&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;Control can be made over exactly what is interpolated:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;qq:c(0)/&lt;span style=""&gt;  &lt;/span&gt;/&lt;span style=""&gt;         &lt;/span&gt;# don't interpolate&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;qq:s(1)/&lt;span style=""&gt;  &lt;/span&gt;/&lt;span style=""&gt;         &lt;/span&gt;# only interpolate scalars&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;qq:s(1):a(1)/&lt;span style=""&gt; &lt;/span&gt;/&lt;span style=""&gt;         &lt;/span&gt;# interpolate scalars and arrays&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;hummmmmmm&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;Here document syntax is changed:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;my $var = q:to /END/&lt;span style=""&gt;    &lt;/span&gt;# s(1):a(1):h(1) can be added&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;…&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;END&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;Not sure where the semi-colon goes&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;Ranges have a new feature:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;x..^y&lt;/span&gt;&lt;span style="font-family: Arial;"&gt;&lt;span style=""&gt;            &lt;/span&gt;means from x up to y-1&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;x^..^y&lt;/span&gt;&lt;span style="font-family: Arial;"&gt;&lt;span style=""&gt;         &lt;/span&gt;means from x+1 to y-1&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;To open a file with an automatic chomp::&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;my $fh = open $filename&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;This can be overridden.&lt;span style=""&gt;  &lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;while (&lt;$fh&gt;) {…}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;becomes:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;while = $fh {…}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;while (&lt;&gt;){…}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;becomes&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;while = $ARGS{…} &lt;/span&gt;&lt;span style="font-family: Arial;"&gt;or&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt; while =&lt;&gt; {…}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;=&lt;&gt;&lt;/span&gt;&lt;span style="font-family: Arial;"&gt; is known as the 'fish' operator&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;There is now a 'prompt' verb&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;Most built-ins that operator on scalars and arrays are now methods:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;$var.substr(…) &lt;span style=""&gt;         &lt;/span&gt;# returns the substring&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;$var .= $var.substr(…)&lt;span style=""&gt;  &lt;/span&gt;# changes the substring&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;No need for Data::Dumper, instead:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;$var.perl()&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;And there is much more, Damian could not complete his talk because of time, and it is not downloadable.&lt;span style=""&gt;  &lt;/span&gt;I'll keep you posted as I play with pugs.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family: Arial;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-112978760643800461?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/112978760643800461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=112978760643800461&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112978760643800461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112978760643800461'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/10/perl-6-at-eurooscon.html' title='Perl 6 at EuroOSCON'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-112974849474980544</id><published>2005-10-19T19:52:00.000+01:00</published><updated>2005-10-19T20:01:34.760+01:00</updated><title type='text'>EuroOSCON - whatever.  Is Perl 6 too complex?</title><content type='html'>I asked the main man, yer actual Larry Wall, this question.  Poor guy - he is a very nice chap - thought he was just signing a book for me.  There was no one else around, so I consulted the oracle (I won't use an uppercase O, you'll get the wrong idea).&lt;br /&gt;&lt;br /&gt;Q.  Will Perl 6 still be suitable for guys who just want a better language that ksh or .bat files?&lt;br /&gt;A.  The easy things will still be easy&lt;br /&gt;&lt;br /&gt;Q.  Will Perl 6 still be suitable for sys.admin's?&lt;br /&gt;A.  Hey!  I'm still a sys.admin.&lt;br /&gt;Me: No you are not, you are a language demi-god.&lt;br /&gt;A. Shrug.  Sys.Admins will still be able to use it.&lt;br /&gt;Q. Are you saying that because that is what I want to hear?&lt;br /&gt;A. Sys.Admins will still be able to use it.&lt;br /&gt;&lt;br /&gt;Thank-you very much.&lt;br /&gt;We also discussed training strategies for Perl 6, and even for Perl 5, and I wasn't that hard on him.  Larry Wall is a very nice chap (oh, I said that).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-112974849474980544?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/112974849474980544/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=112974849474980544&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112974849474980544'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112974849474980544'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/10/eurooscon-whatever-is-perl-6-too.html' title='EuroOSCON - whatever.  Is Perl 6 too complex?'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-112974785030130680</id><published>2005-10-19T19:25:00.000+01:00</published><updated>2005-10-19T19:52:14.470+01:00</updated><title type='text'>EuroOSCON 6 - Perl 6 Update</title><content type='html'>Well I did type all this in, but the network broke when I sent it, and was lost.  You will have to wait.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-112974785030130680?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/112974785030130680/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=112974785030130680&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112974785030130680'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112974785030130680'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/10/eurooscon-6-perl-6-update.html' title='EuroOSCON 6 - Perl 6 Update'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-112974404089123672</id><published>2005-10-19T18:35:00.000+01:00</published><updated>2005-10-19T19:25:41.010+01:00</updated><title type='text'>EuroOSCON 5 - Installation Installation Installation</title><content type='html'>I saw a demo today of a brilliant web-based Perl debugger called Devel::ebug::HTML. It uses the browser, and appears to have everything you want from a visual debugger.&lt;br /&gt;BUT...&lt;br /&gt;Trying to install it is a nighmare. There is no README file, so no list of dependancies. I start downloading and installing them by hand and choke when I come to Catalyst. So I switch off my firewall (oooooooh) and run cpan, and nothing installs. Tried ppm - the same. Everything downloads OK, but every single one fails on the make - it should be using nmake on windows.&lt;br /&gt;Doing this manually would take for ever, so I give up.&lt;br /&gt;&lt;br /&gt;Other Open Source products seem to suffer from the same thing, and it is about time the community did something about it. OK, that means you and me. Something is being done about it, there are many people working on this. I appreciate the complexity, but I don't think the underlying issue is technical. It is trying to bring order to the bazaar, and I am not sure that is possible without turning it into M&amp;amp;S.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-112974404089123672?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/112974404089123672/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=112974404089123672&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112974404089123672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112974404089123672'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/10/eurooscon-5-installation-installation.html' title='EuroOSCON 5 - Installation Installation Installation'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-112965046939033292</id><published>2005-10-18T16:33:00.000+01:00</published><updated>2005-10-19T19:24:37.040+01:00</updated><title type='text'>EuroOSCON 4 - 'Ere we go, 'Ere we go, 'Ere we go!</title><content type='html'>Various speakers and sessions attended (more tonight), here is a summary:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;O'Reilly&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Book sales year on year current figures:&lt;br /&gt;C#                               down 3%&lt;br /&gt;Python                        up 30%&lt;br /&gt;VB                               down 1%&lt;br /&gt;Perl                             up 4%&lt;br /&gt;Ruby                           up &gt; %1000&lt;br /&gt;Linux(generic)            down 4%&lt;br /&gt;Read Hat                        down 24%&lt;br /&gt;Other Linux/Unix    up 2,807%&lt;br /&gt;&lt;br /&gt;Now does that tell several stories?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Waugh&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Microsoft dialog boxes:  Q. "Would you like tea or coffee?&lt;br /&gt;&lt;yes&gt;  &lt;no&gt;  &lt;cancel&gt;&lt;br /&gt;&lt;br /&gt;The other talks were just saying what a wonderful thing Open Source is, and how it is the future. Yeh Yeh Yeh.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Perl 6&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Lots of detail, I have to sort out my notes in detail - another post tomorrow.&lt;br /&gt;Damian and Larry's presentation was titled "&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Perl 6: End-game&lt;/span&gt;&lt;/span&gt;"&lt;br /&gt;Damian Conway is a trainer, and is giving 2-day Perl 6 courses &lt;span style="font-weight: bold;"&gt;NOW&lt;/span&gt;, and expects to be giving full blown Perl 6 courses next summer.&lt;br /&gt;&lt;br /&gt;Have more sessions this evening, tomorrow is quieter.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/cancel&gt;&lt;/no&gt;&lt;/yes&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-112965046939033292?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/112965046939033292/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=112965046939033292&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112965046939033292'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112965046939033292'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/10/eurooscon-4-ere-we-go-ere-we-go-ere-we.html' title='EuroOSCON 4 - &apos;Ere we go, &apos;Ere we go, &apos;Ere we go!'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-112961184624837236</id><published>2005-10-18T05:52:00.000+01:00</published><updated>2005-10-19T19:24:18.506+01:00</updated><title type='text'>EuroOSCON 3 - Perl Best Practices (2) - prototypes</title><content type='html'>L&lt;span style="font-family:arial;"&gt;ike the true geek I am, this has kept me awake all night.&lt;/span&gt;&lt;br /&gt;&lt;p class="MsoNormal"  style="font-family:arial;"&gt;Damian Conway is dead against prototypes, and says they should all die a horrible death in a pit filled with spikes.&lt;span style=""&gt;  &lt;/span&gt;&lt;br /&gt;And snakes (I forgot about the snakes).&lt;/p&gt;     &lt;p class="MsoNormal" style="font-family: arial;"&gt;Prototypes on $@% are rubbish – I agree, but \$\@\% have some advantages.&lt;/p&gt;   &lt;p  class="MsoNormal" style="font-family:arial;"&gt;Take the swap_arrays code in his book (p.196), let's think of some simple user mistookes:&lt;/p&gt;     &lt;p style="font-weight: bold; font-family: arial;" class="MsoNormal"&gt;Without prototypes:&lt;/p&gt;     &lt;p class="MsoNormal"  style="font-family:courier new;"&gt;swap_arrays(@sheep, @goats);&lt;span style=""&gt;      &lt;/span&gt;# Missed out the \&lt;/p&gt;     &lt;p class="MsoNormal"  style="margin-left: 36pt;font-family:arial;"&gt;Without prototypes, provided you are using strict, you get:&lt;/p&gt;     &lt;p class="MsoNormal" style="margin-left: 36pt; font-family: courier new;"&gt;Can't use string ("Blackface") as an ARRAY ref while "strict refs" in use at …&lt;/p&gt;   &lt;p class="MsoNormal"  style="margin-left: 36pt;font-family:arial;"&gt;&lt;o:p&gt; ("Blackface" is a sheep, we know about these things where I do live)&lt;br /&gt;&lt;/o:p&gt;&lt;/p&gt;   &lt;p class="MsoNormal" face="arial" style="margin-left: 36pt;"&gt;BUT the error is given as being in the subroutine, not at the call (where the actual error is).&lt;span style=""&gt;  &lt;/span&gt;perl also stops right there, it does not detect that the next argument is wrong as well – we need to do another run to find that.&lt;/p&gt;     &lt;p class="MsoNormal" face="arial" style="margin-left: 36pt;"&gt;Mostly if we supply the wrong type, use strict 'refs' will save our bacon (or mutton).&lt;span style=""&gt;  &lt;/span&gt;BUT:&lt;/p&gt;     &lt;p class="MsoNormal" style="margin-left: 36pt; font-family: courier new;"&gt;swap_arrays([qw(one two)], [qw(three four)]);&lt;/p&gt;     &lt;p class="MsoNormal" style="margin-left: 36pt; font-family: arial;"&gt;does not give us an error, surprisingly.&lt;span style=""&gt;  &lt;/span&gt;OK, at the end of the day we should not be calling a subroutine we do not understand, but if a user can, she will.&lt;span style=""&gt;  &lt;/span&gt;If she thinks that the two lists are flattened (Damian's assumption with prototypes), then she clearly does not understand the thing anyhow.&lt;/p&gt; &lt;p class="MsoNormal" style="margin-left: 36pt;"&gt;&lt;br /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;     &lt;p style="font-weight: bold; font-family: arial;" class="MsoNormal"&gt;With prototypes:&lt;/p&gt;     &lt;p class="MsoNormal"  style="font-family:courier new;"&gt;swap_arrays(\@sheep, \@goats);&lt;span style=""&gt;      &lt;/span&gt;# Added a&lt;span style=""&gt;  &lt;/span&gt;\&lt;/p&gt;         &lt;p class="MsoNormal"&gt;&lt;span style=""&gt;            &lt;/span&gt;&lt;span style="font-family:arial;"&gt;With a prototype we get an error for each argument at fault:&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="text-indent: 36pt; font-family: courier new;"&gt;Type of arg 1 to main::swap_arrays must be array (not reference constructor) &lt;/p&gt;   &lt;p class="MsoNormal" style="text-indent: 36pt; font-family: courier new;"&gt;Type of arg 2 to main::swap_arrays must be array (not reference constructor) &lt;/p&gt;   &lt;p class="MsoNormal" style="text-indent: 36pt; font-family: courier new;"&gt;Execution of C:\proto.pl aborted due to compilation errors.&lt;/p&gt;   &lt;p class="MsoNormal" style="text-indent: 36pt;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;   &lt;p class="MsoNormal" style="text-indent: 36pt; font-family: arial;"&gt;This time the error is reported correctly.&lt;/p&gt;     &lt;p face="arial" class="MsoNormal"&gt;&lt;span style=""&gt;            &lt;/span&gt;Also, with:&lt;/p&gt;     &lt;p class="MsoNormal" style="text-indent: 36pt; font-family: courier new;"&gt;swap_arrays([qw(one two)], [qw(three four)]);&lt;/p&gt;     &lt;p class="MsoNormal" style="margin-left: 36pt; font-family: arial;"&gt;and a prototype we get a similar error message, again identified with the correct line number.&lt;br /&gt;&lt;/p&gt; &lt;span style="font-weight: bold;font-family:arial;" &gt;And another thing&lt;/span&gt;    &lt;p face="arial" class="MsoNormal"&gt;And I nearly forgot, empty prototypes are the only way I know (other than hand-coding) of preventing any arguments being passed, as in:&lt;/p&gt;     &lt;p class="MsoNormal" style="text-indent: 36pt; font-family: courier new;"&gt;sub void_sub () { ,,, }&lt;/p&gt;     &lt;p face="arial" class="MsoNormal"&gt;Calling this subroutine would give an error at the point of the erroneous call.&lt;/p&gt;   &lt;p style="font-family: arial;" class="MsoNormal"&gt;&lt;o:p&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Volcano beats Joe&lt;/span&gt;&lt;br /&gt;&lt;/o:p&gt;&lt;/p&gt;   &lt;p style="font-family: arial;" class="MsoNormal"&gt;Let's face it though, Damian is right.&lt;span style=""&gt;  &lt;/span&gt;&lt;span style=""&gt; &lt;/span&gt;If you want a standard there cannot be exceptions.&lt;span style=""&gt;  &lt;/span&gt;The problem with prototypes is that everyone thinks they are like C/C++ prototypes, but most people don't even understand THEM.&lt;span style=""&gt;  &lt;/span&gt;Take:&lt;/p&gt;     &lt;p class="MsoNormal"&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;size_t myfunc (char string[4]);&lt;/span&gt;&lt;/p&gt;     &lt;p style="font-family: arial;" class="MsoNormal"&gt;or&lt;/p&gt;     &lt;p class="MsoNormal"&gt;&lt;span style=""&gt;     &lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;int another ();&lt;/span&gt;&lt;/p&gt;     &lt;span style=""&gt;&lt;span style=";font-family:arial;font-size:100%;"  &gt;Neither do what most people think they do, and are misleading.&lt;/span&gt;&lt;span style=";font-family:arial;font-size:100%;"  &gt;  &lt;/span&gt;&lt;span style=";font-family:arial;font-size:100%;"  &gt;So how do you expect to understand Perl prototypes on the same (false) basis?&lt;/span&gt;&lt;span style=";font-family:arial;font-size:100%;"  &gt;  &lt;/span&gt;&lt;span style=";font-family:georgia;font-size:100%;"  &gt;&lt;span style="font-family:arial;"&gt;KISS.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-112961184624837236?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/112961184624837236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=112961184624837236&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112961184624837236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112961184624837236'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/10/eurooscon-3-perl-best-practices-2.html' title='EuroOSCON 3 - Perl Best Practices (2) - prototypes'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-112956451367794696</id><published>2005-10-17T16:39:00.000+01:00</published><updated>2005-10-19T19:22:30.136+01:00</updated><title type='text'>EuroOSCON 2 - Perl Best Practices</title><content type='html'>Damian Conway's talk on this subject woke me up.&lt;br /&gt;A lot of great ideas and tips, methinks I need an extra slide at the end of each chapter on style, or something like it. Do you think people will mine a six day course? That's the problem, I keep picking up more stuff to put into the course!&lt;br /&gt;&lt;br /&gt;At least I found something to take out - subroutine prototypes.&lt;br /&gt;A packed room, with lots of experts, and it appears I was the only person who understood prototypes (except Damian, of course). That is scary, and probably indicates we sould not spend so much time on them in our course. Damian hates them, I just find them 'flaky' personally - but no more flaky than lots of other parts of Perl. Then again, it is Damian's mission to destroy flaky Perl, and we have to start somewhere...&lt;br /&gt;&lt;br /&gt;I got a chance for a brief chat with Mr. Conway (he comes from that country which just lost the ashes), but I have more questions for him. Here is a reminder for me:&lt;br /&gt;&lt;br /&gt;Why use -t *STDIN instead of STDIN?&lt;br /&gt;Shouldn't IO::Prompt offer the locale specific Y/N?&lt;br /&gt;An idea for a pragma - RegExp::NoCapture - make all parenth. groups non-capturing.  Could REs be optimised better?&lt;br /&gt;&lt;br /&gt;Some good speakers tonight - Damian Conway (again) and Larry Wall - really looking forward to that.&lt;br /&gt;&lt;br /&gt;BTW - am I grateful for downloading FireFox? The W/Lan here does not work with MS Internet Explorer. Apparently it is the same problem as I mentioned with ActiveState (see below), Or so they say.....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-112956451367794696?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/112956451367794696/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=112956451367794696&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112956451367794696'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112956451367794696'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/10/eurooscon-2-perl-best-practices.html' title='EuroOSCON 2 - Perl Best Practices'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-112954652431068047</id><published>2005-10-17T11:42:00.000+01:00</published><updated>2005-10-19T19:22:08.793+01:00</updated><title type='text'>EuroOSCON 1 - DBI</title><content type='html'>&lt;div designtimesp="24697"&gt;&lt;span designtimesp="24698" style="color: rgb(0, 0, 0);font-family:Arial;font-size:100%;"  &gt;This conference is so cool, it is Arctic.&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;  &lt;div&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;Went to the Database Tutorial this morning - another chapter to re-write! Not that there is anything wrong with the Perl Programming Appendix on DBI, but I just learnt so many cool things, that the chapter will probably double in size.&lt;br /&gt;So what did find out?&lt;br /&gt;First, my Perl knowledge is not so bad ;-) It is always worrying going up against a bunch of enthusiastic geeks, but hey, I don't think I let the side down. That was a confidence boost (even lecturers need that sometimes)&lt;br /&gt;Next:  &lt;span style="font-family:courier new;"&gt;dbi:DBM:&lt;/span&gt; is a prototyping database bundled with DBI, looks great for quick training demos&lt;br /&gt;Next:  queries can be done against a dbh, but this is not efficient (we don't mention that)&lt;br /&gt;Next:  if $sth-&gt;disconnect is not done, you can get a memory leak&lt;br /&gt;Next:  placeholders are very cool if you know how to use them (I feel lots of example slides coming on)&lt;br /&gt;Next:  I had missed dbh attributes before (set in the connect)&lt;br /&gt;Next:  Lots of things about RaiseError&lt;br /&gt;Next:  $sth metadata hashes are tied, so using these invoke method calls&lt;br /&gt;Next:  and other stuff as well&lt;br /&gt;&lt;br /&gt;A lot I already knew, like American jokes don't work on a European audience.&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;  &lt;div&gt; &lt;/div&gt;   &lt;div&gt;&lt;span style=";font-family:Arial;font-size:85%;"  &gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-112954652431068047?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/112954652431068047/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=112954652431068047&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112954652431068047'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112954652431068047'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/10/eurooscon-1-dbi.html' title='EuroOSCON 1 - DBI'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-112927472272407244</id><published>2005-10-14T08:14:00.000+01:00</published><updated>2005-10-14T08:27:51.486+01:00</updated><title type='text'>Fedora 4 /etc/profile</title><content type='html'>Found a buglet in this file this week.&lt;br /&gt;The /etc/profile file is the first file executed by a Korn shell session on login, but it has been hijacked by Bash. On Linux the Korn shell is not used much, except by training companies of course. I doubt that /etc/profile is ever tested with ksh, so it is not surprising there is a bug, however it is a shame that the mistake is such a simple one - doesn't give one much confidence.&lt;br /&gt;&lt;br /&gt;On sign-on to ksh we get a syntax error in /etc/profile, on the line:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;if [ $EUID = 0 ]; then&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The EUID shell variable is set by Bash, and is a read-only value giving the effective user-id (if you want to know the difference between effective and real user-ids, come on QAs Unix Programming course). The code is checking for a 'root' user. On Korn shell this variable is not set.&lt;br /&gt;&lt;br /&gt;The fix is quite easy, quote the variable:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;if [ "$EUID" = 0 ]; then&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;ALWAYS quote variables in single [. One of the effects of using [[ is that quotes are not necessary around a variable, and if the authors had come on QAs Mastering BASH Shell Scripts course, they would have known that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-112927472272407244?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/112927472272407244/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=112927472272407244&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112927472272407244'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112927472272407244'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/10/fedora-4-etcprofile.html' title='Fedora 4 /etc/profile'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-112844057137977740</id><published>2005-10-04T16:42:00.000+01:00</published><updated>2005-10-04T16:45:06.103+01:00</updated><title type='text'>Sneaky bat files</title><content type='html'>&lt;span style="font-family:Arial;"&gt;The ActiveState Perl implementation contains some examples of imbedding Perl inside a Windows .bat file.  Of course if we wanted to do that sort of thing in a Unix shell we would probably use a 'here' document, but bat files do not have that level of sophistication.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;The structure of these bat files is as follows:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;@rem = '--*-Perl-*--         &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;perl -x -S "%0" %*&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;goto endofperl&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;@rem ';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;#!/usr/local/bin/perl -w&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;#line 9&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;   ... Perl code ...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;     __END__&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;     :endofperl&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;The "%0" is the name of the current bat file, and %* is a list of the arguments passed into the bat file (like $0 and $* in the Korn shell and Bash).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;So we are executing the bat file as if it was a perl script!  This is where the –x option to perl comes in.  Check perlrun, -x means that the perl code starts at the #! line, and preceding lines are to be ignored.  The –S option means that %path% is used to find the perl script.   There is a problem with this.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;The quotes around "%0" would appear to protect us from imbedded spaces in the filename, but they do not.  Paths with imbedded spaces do not work with this method.  Strangely, this works if the quotes are omitted.  The implication is that most of the ActivePerl bat files do not work with imbedded spaces in path names.  &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;(The pugs Windows installation has a similar problem) &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;The –S option is not really needed.  This is because to run the bat file we need to specify a hierarchic or full pathname anyway (Explorer makes the script's directory its current directory).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;The sneaky part is the use of @rem.  &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;The bat file starts with a non-echo'ed remark:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;@rem = '--*-Perl-*--&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;… bat file stuff …&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;@rem ';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;The idea here is that, by a happy coincidence, @rem comment prefix in a bat file is a valid perl command, to assign to an array called @rem.  The assignment ends on the final comment, with a close quote (notice that the first @rem has no close quote).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;I can only guess that this is in the bat files for historical reasons, since the –x option to perl makes this trickery unnecessary.  The goto (whatever that is) is required to leap over the perl code.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;The #line directive sets the line number when error reporting, or for the die statement.  This means that we can set the line numbers relative to the start of our bat file, rather than the start of the perl code.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;Finally, the __END__ label tells perl that this is the end of the script, and ignores any junk that follows.  &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-112844057137977740?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/112844057137977740/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=112844057137977740&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112844057137977740'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112844057137977740'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/10/sneaky-bat-files.html' title='Sneaky bat files'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-112842431045537053</id><published>2005-10-04T12:10:00.000+01:00</published><updated>2005-10-04T12:11:50.460+01:00</updated><title type='text'>A link of interest</title><content type='html'>&lt;p&gt;&lt;a href="http://www.oreillynet.com/pub/wlg/7929"&gt;Will Linux Benefit from Microsoft's SNAFU in Massachusetts?&lt;/a&gt; by Tom Adelstein -- Microsoft had everything to lose in Massachusetts and did.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-112842431045537053?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/112842431045537053/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=112842431045537053&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112842431045537053'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112842431045537053'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/10/link-of-interest.html' title='A link of interest'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-112748404591768306</id><published>2005-09-23T14:34:00.000+01:00</published><updated>2005-09-23T15:00:45.923+01:00</updated><title type='text'>Unix Shell Scripts</title><content type='html'>A weekend between giving courses, thankfully back to talking Perl next week.&lt;br /&gt;I have been teaching our Korn shell course this week and I enjoyed it, but....&lt;br /&gt;Why do so many people think that Korn shell and Bash are the same?&lt;br /&gt;Bash is hugely more powerful than ksh, with Extended Regular Expressions in version 3, and possibly associative arrays soon (looking at the source, it seems most of the code is already there).   There are still things missing, for example ERE matching is supported, so wouldn't a substition statement be a small further step?&lt;br /&gt;Yes I know, danger of feature bloat.  With a little more work Bash could be the new Perl 5 ;-)  There might actually be a place for that once (if) Perl 6 takes hold (double smiley).&lt;br /&gt;&lt;br /&gt;Funny how conventional programmers tend to look down on shell scripting.  And funny how system administrators, and their ilk, are expected to write scripts with &lt;em&gt;no&lt;/em&gt; training on good programming techniques and practice.  Companies spend huge amounts making sure their applications are fast and efficient, then some poor erk runs a badly written script and screws the entire system.  Is it the erk's fault?  Maybe, but more likely the person who put them in that position.&lt;br /&gt;&lt;br /&gt;Here is my contention:  anyone can write a shell script, but it takes skill and knowledge to write a good one.&lt;br /&gt;&lt;br /&gt;I recommend: Classic Shell Scripting by Robbins and Beebe (O'Reilly) May 2005.  The best book on the subject I have come across.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-112748404591768306?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/112748404591768306/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=112748404591768306&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112748404591768306'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112748404591768306'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/09/unix-shell-scripts.html' title='Unix Shell Scripts'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-112621999465978168</id><published>2005-09-08T23:50:00.000+01:00</published><updated>2005-09-09T09:34:18.056+01:00</updated><title type='text'>Redemption</title><content type='html'>Microsoft, good ol' Microsoft, have a bunch of (useful) Perl scripts on:&lt;br /&gt;&lt;a href="http://www.microsoft.com/technet/scriptcenter/scripts/perl/prlindex.mspx"&gt;http://www.microsoft.com/technet/scriptcenter/scripts/perl/prlindex.mspx&lt;/a&gt;&lt;br /&gt;They only use Windows Management Instrumentation (WMI), and they are a bit thin of explaination of the code, but it's a start.  One day, maybe, I will get to write my "Perl Programming for Microsoft Windows" course.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-112621999465978168?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/112621999465978168/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=112621999465978168&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112621999465978168'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112621999465978168'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/09/redemption.html' title='Redemption'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-112604910470736128</id><published>2005-09-07T00:13:00.000+01:00</published><updated>2005-09-07T00:25:04.713+01:00</updated><title type='text'>Bye bye IE, hello Firefox</title><content type='html'>After downloading ActiveState Perl 5.8.7 I had problems displaying the html Perl documentation.  Turns out (http://bugs.activestate.com/show_bug.cgi?id=39240) that the Internet Explorer patches with XP SP2 "locks-down" some features, like actually displaying web pages.  Sorry, what did you say a browser is for?&lt;br /&gt;&lt;br /&gt;I'm all for security, but preventing access to web pages on the &lt;span style="font-style: italic;"&gt;local machine&lt;/span&gt;, even when it is not connected to the web?  Give me a break!&lt;br /&gt;&lt;br /&gt;So, hello Firefox!  I used it months ago, but never got around to installing it on my nice new machine.  Wel now I had a real need, and it works a treat!  I am just ashamed I took so long.&lt;br /&gt;&lt;br /&gt;So Mister Microsoft, if you want to know why I am not using your product, it is simply because it does not work - nothing personal ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-112604910470736128?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/112604910470736128/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=112604910470736128&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112604910470736128'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112604910470736128'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/09/bye-bye-ie-hello-firefox.html' title='Bye bye IE, hello Firefox'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-112550296993904891</id><published>2005-08-31T16:32:00.000+01:00</published><updated>2005-08-31T16:42:49.946+01:00</updated><title type='text'>Win32::StreamNames</title><content type='html'>A truly excelent new module has just appeared on CPAN, named Win32::StreamNames.  It returns a list of file stream names for a specified file. &lt;br /&gt; &lt;br /&gt;OK, I'll come clean.  Yes it's one of mine.  I was proudly showing off my blanket trick (see below) to another QA instructor when he said "I suppose you use a stream".  Well, aside from a small river, a stream to me is an IO channel, or maybe a Unix device driver STREAM.  This is neither.  Enhanced at NTFS5 at Windows NT 5, correction, Windows 2000 ;-), a Windows File object points to Stream control blocks, which can include a Named stream.  The names are of the form &lt;em&gt;file-name&lt;/em&gt;:&lt;em&gt;stream-name&lt;/em&gt;:$DATA.  They are not normally visible to Windows Explorer, the dir command, Perl globbing, or readdir (using Win32 API).  BackupRead Win32 API can retrieve the stream names, although it is not easy to use.  Hence the module.&lt;br /&gt;&lt;br /&gt;See it at your local CPAN mirror today! http://cpan.search.org&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-112550296993904891?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/112550296993904891/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=112550296993904891&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112550296993904891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112550296993904891'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/08/win32streamnames.html' title='Win32::StreamNames'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-112443503422343671</id><published>2005-08-19T07:49:00.000+01:00</published><updated>2005-08-19T08:03:54.236+01:00</updated><title type='text'>Blanket</title><content type='html'>While on the train, I decided to ammuse myself by writing a version of Damian Conway's 'bleach' program.  Basically it "encrypts" a perl script with whitespace, so when it is viewed it looks blank.&lt;br /&gt;The method I used (I couldn't remember Damian's exact code) is to take the ordinal number of each character in the character set, and write that number of space characters to the file. &lt;br /&gt;&lt;br /&gt;For example, 'A' is decimal 65 in the character set (ISO Latin 1 and ASCII), so for that character I write a line contining 65 spaces. To get the number I use the Perl built-in function 'ord'.   To decode I just have to get the length of each line and feed that into the 'chr' function to get back the original.&lt;br /&gt;&lt;br /&gt;I showed this to my class as an ammusement, and one delegate (thank-you Daniel) played around with it.  He discovered that if you zip the blanked file you get a very small archive.  Smaller (about two-thirds) the size of the original, zipped.  Must be the way the zip algorithm works with repeated characters.&lt;br /&gt;&lt;br /&gt;I have just thought of another tweak I can do .............&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-112443503422343671?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/112443503422343671/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=112443503422343671&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112443503422343671'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/112443503422343671'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/08/blanket.html' title='Blanket'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-111787916941769509</id><published>2005-06-04T10:56:00.000+01:00</published><updated>2005-06-04T14:33:45.296+01:00</updated><title type='text'>pdksh integer arrays</title><content type='html'>Just found a bug in pdksh version 5.2.14 – it cannot handle integers arrays correctly (pdksh is the Public Domain Korn Shell). I first discovered this with a lottery script, but actually it is very easy to reproduce:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;typeset –i array&lt;br /&gt;array[0]=42&lt;br /&gt;array[1]=43&lt;br /&gt;array[2]=44&lt;br /&gt;array[3]=45&lt;br /&gt;echo "${array[@]}"&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;gives: &lt;span style="font-family:courier new;"&gt;45 45 45 45&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;This works correctly if &lt;span style="font-family:courier new;"&gt;typeset –i&lt;/span&gt; is not used. Bash, with &lt;span style="font-family:courier new;"&gt;declare –ia array&lt;/span&gt;, works fine, as you might expect.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-111787916941769509?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/111787916941769509/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=111787916941769509&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/111787916941769509'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/111787916941769509'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/06/pdksh-integer-arrays.html' title='pdksh integer arrays'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-111722315526185191</id><published>2005-05-27T20:30:00.000+01:00</published><updated>2005-06-04T10:46:48.426+01:00</updated><title type='text'>Unix for Perl Programmers</title><content type='html'>&lt;span style="font-family:arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;This is an introduction to using the Unix API from Perl.&lt;br /&gt;&lt;br /&gt;It concentrates on POSIX compliant system calls, and introduces System V Release 4 Unix. I look at the fundamental concepts of a process and its interaction with the Unix kernel, the difference between library calls and system calls is discussed, and I give an overview of error handling. Later postings will look at API calls in detail&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;I have assumed a degree of familiarity with Perl that can be obtained by attending the QA Perl Programming course.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-family:arial;"&gt;Unix compatibility&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Unix has a long and chequered history, with a number of standards which often conflict. An attempt to standardise application code interfaces into Posix 1 (IEEE Std 1003.1, now the X-Open SUS) has not been universally adopted.&lt;br /&gt;Use defensive programming techniques where possible, for example do not hard-code system limits, but call functions at run-time to find what these are (see later).&lt;br /&gt;As Perl programmers we are protected from many of the differences between operating systems, but we are not immune from them. Most Perl statements are portable, but the lower we delve into the innards of Unix, the less portable we become. The differences are often expressed in C terms, even in the Perl documentation, so a knowledge of that language is very beneficial.&lt;br /&gt;Use the built-in Perl variable $^O to mark blocks of code you know are specific to certain versions of Unix.&lt;br /&gt;In this article I often give example code and function prototypes. Arguments and their types have been described in a generic way where possible, however you should not assume that they exactly match the systems you use, or the version of Perl.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Perl with Unix: call interfaces&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;p&gt;&lt;br /&gt;The kernel is the heart of a Unix system. Its job is primarily one of resource management; it looks after the physical resources (hardware) of the computer system and shares them amongst all of the processes that wish to use them.&lt;br /&gt;The kernel can be thought of as providing a number of services to programs, such as a file system for data and program storage, management of the RAM in the computer and a means of accessing devices attached to the computer. The details of the actual hardware are hidden from programs by the kernel; it presents a "virtual-machine" interface to the programs. The virtual-machine interface is consistent across almost all versions of Unix, regardless of hardware details.&lt;br /&gt;Programmers will occasionally require the kernel to perform some function for them, such as performing input or output, or starting a new process. Such requests are made through a number of well-known special function calls known as system calls. The set of system calls defines the interface to the kernel for programs and is kept consistent as much as possible across different variants of Unix. Nevertheless, such low level access is by definition dependant on the operating system, and often requires detailed knowledge. To enable portability, and to supply easy-to-use interfaces, a higher level language like C provides its own RunTime Library (RTL). This takes an ISO standard call and converts it into an operating system specific call, and maybe adds other features as well. Other languages and products have their own RTLs, for example an RDBMS will have a RunTime Library to enable embedded SQL to run.&lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;Perl is written in C, so uses the C RTL, and many of the built-in function calls reflect that. Sometimes these are too general, so we have available lower-level interfaces to make direct calls to kernel APIs, but remember that these were designed to be called from C, not Perl. Perl modules often make use of low-level calls, although they sometimes "cheat" by using imbedded C.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;System Calls and Library Functions&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Most Unix programs will need to make use of one or more library functions or system calls. While they may both appear to be the same from the program’s point of view, there are some important differences between library functions and system calls.&lt;br /&gt;&lt;br /&gt;System calls are the means by which a process can request services from the kernel. Services include accessing and manipulating files and devices, and process-related operations. System calls are documented in section 2 of the Unix reference manual, and are platform specific. Some Perl built-ins make system calls, and appear to be the same as the kernel call. The read() function is an example. The Perl version will make a call to the C library function fread(3) eventually, but along the way adds value. It can handle utf8 files, for example. If we want the kernel function read(2) we need to call the Perl function sysread (there is also a syswrite and a sysopen). Here are some examples:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Perl            Kernel call     Library Function&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;$$      getpid&lt;br /&gt;fork    fork&lt;br /&gt;open              fopen&lt;br /&gt;read              fread&lt;br /&gt;sysopen           open&lt;br /&gt;sysread           read &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Library functions are simply C functions written by someone else and supplied via libraries of functions. These libraries are linked to perl either statically (before the program runs) or dynamically (at run time). Using a library function does not necessarily require any help from the kernel.&lt;br /&gt;C Runtime Library functions are documented in section 3 of the Unix reference manual, but Perl does not necessarily use them. The Library functions themselves can have portability problems, so Perl often implements its own. See perldoc perlclib.&lt;br /&gt;&lt;br /&gt;The major portion of the work carried out by the various bodies that have developed standards for Unix, such as the IEEE (POSIX) and the Open Group (X/Open Portability Guide, Unix 1170, etc.) have been to standardise the names, arguments and results of library functions and system calls. The result is that it the various versions of Unix that exist today should all contain a compatible set of these, forming a standard API supporting the development of applications that can be ported with minimal efforts.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Perl system interfaces&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;There are a couple of different methods that may be used to imbed C calls into Perl. The first is the syscall interface. This allows a call to be made direct to a C function, assuming the function's prototype is defined in a header file. The h2ph utility will convert the header file to a Perl .ph file, which can then be loaded with use or require. Unfortunately the h2ph utility cannot cope with all structures and calls, so sometimes the resulting .ph files have to be "tweaked" manually to get them to compile. The most difficult part of using syscall is in converting the variable types between Perl and C, using pack and unpack. A detailed knowledge of C is required for this, as well as an understanding of the function you are about to call.&lt;br /&gt;The XS interface is much easier to use, but still needs an understanding of C. Again we convert the header file, but this time using h2xs. We imbed C code in an XS code block, then build a new module using the XS compiler (called xsubpp). This time the conversion between C and Perl variables is done automatically.&lt;br /&gt;There is a simple XS tutorial available in perldoc, called perlXStut, and the full XS documentation is in perlxs.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Converting between Perl and C&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Perl variables are held in an "internal" format, and do not usually have a 1:1 mapping with C primitive types. However, many low-level functions make C system calls, and so we often need to supply a C struct from Perl.&lt;br /&gt;&lt;br /&gt;We convert from Perl to C using the built-in function pack:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;C scalar&lt;/em&gt; &lt;span style="font-family:courier new;"&gt;= pack&lt;/span&gt; &lt;em&gt;TEMPLATE, LIST&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;where &lt;em&gt;TEMPLATE&lt;/em&gt; indicates the type of each field (see below).&lt;br /&gt;&lt;br /&gt;To convert from C to Perl we (unsurprisingly) use unpack:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Perl list&lt;/em&gt;&lt;span style="font-family:courier new;"&gt; = unpack&lt;/span&gt; &lt;em&gt;TEMPLATE, SCALAR&lt;br /&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;There are over 30 different template characters, some common ones are:&lt;br /&gt;&lt;br /&gt;A A text (ASCII) string, will be space padded.&lt;br /&gt;Z A null terminated (ASCIZ) string, will be null padded.&lt;br /&gt;c A signed char value.&lt;br /&gt;C An unsigned char value. Only does bytes. See U for Unicode.&lt;br /&gt;s A signed short value.&lt;br /&gt;S An unsigned short value (16 bits).&lt;br /&gt;i A signed integer value.&lt;br /&gt;I An unsigned integer value.&lt;br /&gt;l A signed long value.&lt;br /&gt;L An unsigned long value (32 bits).&lt;br /&gt;f A single-precision float in the native format.&lt;br /&gt;d A double-precision float in the native format.&lt;br /&gt;D A long double-precision float in the native format.&lt;br /&gt;x A null byte.&lt;br /&gt;&lt;br /&gt;for a full list see perldoc -f pack.&lt;br /&gt;&lt;br /&gt;The following example is required to call fcntl for a file lock:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;$wlock = pack 'sslli',(F_WRLCK, SEEK_SET, $rec, $rsize, 0);&lt;br /&gt;fctnl( ... ) # Some C call&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Unpack the returned flock structure:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;($locked, $pid) = (unpack 'sslli', $qlock)[2,4];&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The above examples show an interesting portability issue, they do not work on Linux 2.4. This is because the Linux implementation of the perl fcntl function does not call fcntl(2), but a lower level function, fcntl64. This means that the normal 'l', which is 32-bits, has to be doubled up:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;my $wlock = pack 'sslllli', (F_WRLCK, SEEK_SET, 0,&lt;br /&gt;$rec, 0, $rsize, 0);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;(It took me ages to figure out that Linux perl uses fcntl64, I eventually ran strace(1) on my perl script to discover why it would not work).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;POSIX module&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The POSIX module is an important tool for Perl programmers on Unix. The interfaces it provides are mostly portable, although you must still be aware of the limitations of your particular system. The POSIX 1 standard (there are actually 13 parts to POSIX) defines a C language interface, and so some functions are not applicable to Perl. Perl abstracts messy tasks like dynamic memory allocation, so strictly speaking the POSIX module does not, and cannot, provide true POSIX compliance, only POSIX functionality. Being a C interface does mean that knowledge of C is a definite advantage when understanding the documentation.&lt;br /&gt;Some POSIX functionality is provided by standard built-in Perl functions and variables, and it is generally better to use those rather than the POSIX module versions, since Perl is optimised with them, but there is not a huge difference.&lt;br /&gt;To use the POSIX module effectively requires some C knowledge, but you do not need to be an expert.&lt;br /&gt;&lt;br /&gt;Later postings will explore the POSIX module further.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Always check a function call for errors. As a rule, a return value of FALSE (0 or undef) indicates that an error occurred that prevented the system call from completing successfully. The exact details of the return values of the system calls are found on the relevant manual pages. Return values should always be checked, since undetected error conditions may cause serious problems that are more difficult to locate later in a program.&lt;br /&gt;&lt;br /&gt;Some low-level functions return a value which could be zero, yet do not wish this to indicate an error. For example the tell function returns the current file position, which could be zero (beginning of file). In this case the text value '0 but true' is returned instead of just zero. This evaluates to TRUE in Boolean context, but 0 in numeric, yet is immune to usual warnings about use of non-numeric text.&lt;br /&gt;By convention error messages should be reported to STDERR, using any of the methods shown below.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;print STDERR "Oops: $!\n" # not fatal, not trappable&lt;br /&gt;&lt;br /&gt;die "A death: $!" # fatal, but trappable&lt;br /&gt;&lt;br /&gt;warn "Will Robinson!" # not fatal, trappable&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The warn and die functions output the perl script line number, and both calls may be trapped using signal handling. The usual way to trap die is by using an eval block (exception handling).&lt;br /&gt;If a system call fails, the global variable $! will contain a system-defined error number, in numeric context, and the error text in string context. The variable $! is only set when an error occurs. It is not cleared on a successful system call. It is only safe to rely on this value when a system call has failed.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Errno module&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Unix recognises a standard set of error codes, not all system calls can return all errors. Which errors are returned by which functions are described in the manual pages.&lt;br /&gt;&lt;br /&gt;Some useful error codes and constants (conditionally exported by Errno.pm):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;EPERM &lt;/span&gt;Operation not permitted&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ENOENT &lt;/span&gt;No such file or directory&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ESRCH &lt;/span&gt;No such process&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;EIO &lt;/span&gt;I/O error&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ENOEXEC &lt;/span&gt;Exec format error&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ECHILD &lt;/span&gt;No child processes&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;EACCES &lt;/span&gt;Permission denied&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;EEXIST &lt;/span&gt;File already exists&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ENOTDIR &lt;/span&gt;Not a directory&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Note that some errors such as EAGAIN and EINTR may not be errors but indicate that a system call must be attempted again (EAGAIN because conditions were not right for the call to complete and EINTR because the call was interrupted by some other system activity).&lt;br /&gt;The package Errno defines the symbolic constants that represent system error conditions. It also defines the hash %!, which has a key for each error constant, and its value is TRUE if the error has occurred. Not all error constants are portable, so you should not assume any particular code exists in %!.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Example - Error Handling&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;use Errno; # No need to import anything&lt;br /&gt;&lt;br /&gt;my $file = 'input.txt';&lt;br /&gt;&lt;br /&gt;if ( !open (HANDLE, "$file") )&lt;br /&gt;{&lt;br /&gt;   if ($!{ENOENT})&lt;br /&gt;   {&lt;br /&gt;      print STDERR "$file does not exist\n";&lt;br /&gt;      ...&lt;br /&gt;   }&lt;br /&gt;   elsif ($!{EACCES})&lt;br /&gt;   {&lt;br /&gt;      print STDERR "$file: Permission denied\n"&lt;br /&gt;      ...&lt;br /&gt;   }&lt;br /&gt;   else&lt;br /&gt;   {&lt;br /&gt;      die "Unable to open $file: $!";&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;This example shows how Errno can be used to handle different error conditions.&lt;br /&gt;If the call failed, then after an error message is printed, the program terminates with die. This is safer than exit, particularly in a module, since it may be trapped in the calling routine.&lt;br /&gt;Errno can also import POSIX codes with:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      use Errno ':POSIX';&lt;/span&gt;&lt;br /&gt;An alternative to the Errno module is the POSIX module:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      use POSIX ':errno_h';&lt;/span&gt;&lt;br /&gt;which exports the error number constants, but not %!.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Command Line Arguments&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;When a program is executed, it is passed a variable-length list of arguments. The shell arranges for these arguments to be the command name and arguments typed at the command line.&lt;br /&gt;The argument list is accessible to the program by the array @ARGV, so the number of arguments passed can be obtained by using the array in scalar context. Unlike C, the first element is the first argument, not the program name (that is available from $0).&lt;br /&gt;There is a system-defined maximum size of the argument list. Normally, it is not allowed to be larger than 5KB or 10KB.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Option Processing&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In the past, Unix commands were written by different contributors, often employing slightly different methods of dealing with the command-line arguments of their programs. By convention, Unix program arguments are either options, which are usually single letters preceded by the "-" character, or arguments to the command itself, usually pathnames. In recent versions of Unix, a definition has been developed of a "standard" command interface, which defines a basic format for command lines. New programs should, if at all possible, be written to conform to this format.&lt;br /&gt;The format is fairly flexible, but does impose a few more restrictions:&lt;br /&gt;Options must be a single character.&lt;br /&gt;All options and their associated arguments must appear before the main arguments.&lt;br /&gt;Multiple option characters may be grouped behind a single "-", except where an option requires an argument.&lt;br /&gt;The standard module Getopt::Std offers two routines, getopt and getopts, the later being the more useful. getopts reads the command line argument list array @ARGV, and extracts valid switches into side-effect variables, or into a predefined hash. If an option is to have an associated argument, the option letter must be followed by a colon (:) character.&lt;br /&gt;Valid options are removed from @ARGV. The end of the options is signified by encountering a non-option argument (ie.. one which does not start with a "-") or the "special" option "--", which is also removed from @ARGV.&lt;br /&gt;If getopts encounters an invalid option then it prints a message on the standard error stream.&lt;br /&gt;Further features are available in the extended version Getopts::Long.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Examples - Options and Arguments&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;These two code fragments show examples of both methods of syntax.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Using global variables&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;use strict;&lt;br /&gt;use Getopt::Std;&lt;br /&gt;&lt;br /&gt;our ($opt_a, $opt_d, $opt_l);&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;getopts('ad:l');&lt;/strong&gt;&lt;br /&gt;print "a: $opt_a, d: $opt_d, l: $opt_l\n";&lt;br /&gt;print "Remaining arguments: @ARGV\n\n";&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Using a hash&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;use strict;&lt;br /&gt;&lt;br /&gt;use Getopt::Std;&lt;br /&gt;my %options;&lt;/span&gt;&lt;/span&gt;&lt;p&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;strong&gt;getopts('ad:l', \%options);&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;while (my ($key, $value) = each %options)&lt;br /&gt;{&lt;br /&gt;   print "Switch: $key, value: $value\n"&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;print "Remaining arguments: @ARGV\n";&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;When using globals, with use strict, we must pre-defined them using our. When using a hash we pass a reference.&lt;br /&gt;In both cases the value is 1, TRUE, if the switch was set. When a value is required it will be set in the side effect variable or the hash.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The Environment block&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Every process has access to a variable-length list of pointers to strings, known as environment variables.&lt;br /&gt;Environment variables can be set up from the shell with the export or setenv (csh) commands. They are useful for communicating information on a global level to multiple commands, as they can be accessed easily from within programs and shell scripts.&lt;br /&gt;To see the current environment from the shell, use the env command.&lt;br /&gt;The entire environment is made available to Perl through the hash variable %ENV. The keys are the environment variable names, with values.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;print "Home directory is ",&lt;br /&gt;exists($ENV{'HOME'})?$ENV{'HOME'}:"unknown", "\n";&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;TMTOWTDI&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;if ( exists $ENV{'HOME'} )&lt;br /&gt;{&lt;br /&gt;   print "Home directory is $ENV{'HOME'}\n"&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;   print "Home directory is unknown\n"&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The example retrieves the value of the HOME environment variable (ie.. the pathname of the user’s home directory).&lt;br /&gt;If HOME is set in the environment, its value is returned, otherwise the key will not exist, and a warning will be given. Therefore it may be advisable to check with exists first.&lt;br /&gt;Incidentally, the HOME environment variable is the default directory for the built-in chdir function (like a shell cd command). If HOME is not set, then LOGDIR is used.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Limits&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Since Unix is supported on a wide range of platforms, it is reasonable to assume that there will be differences in detail among them. For example some may allow long filenames where others may still impose the old limit of 14characters. Some may support sophisticated signal-driven job control while others may not.&lt;br /&gt;In developing Unix programs that are intended to work across a wide range of Unix implementations, it is desirable to be able to represent such properties in a platform independent manner, perhaps discovering details about a particular system at run time.&lt;br /&gt;POSIX defines a number of symbolic constants, specified in the POSIX module that govern the details of data types, their sizes and max/min values.&lt;br /&gt;Run time values can be checked using one of three functions - sysconf allows general properties such as the number of system clock ticks per second (useful in certain timing calculations), the maximum number of files that a process can hold open at one time, and the maximum number of child processes that a process can create. Properties that are more closely related to files and directories, such as the length of a filename or pathname, are discovered using the system call pathconf or fpathconf.&lt;br /&gt;Many of these “runtime” limits are also mentioned in the POSIX module, but the values here are absolute minimums. For example, a system may set the maximum number of open files per process to be any value greater than _POSIX_OPEN_MAX, usually defined as 16.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;POSIX::sysconf&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;General system limits and properties can be queried using the sysconf function. The argument is an integer symbolic constant representing the value to be queried. The return value is the current setting of the value, or -1.&lt;br /&gt;If the name parameter represents a property that is valid, but not supported, then errno will be clear even though the function returns -1. An invalid name causes the function to return -1 and set errno to EINVAL.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;$max_open = sysconf(_SC_OPEN_MAX);&lt;br /&gt;&lt;br /&gt;if (!defined $max_open)&lt;br /&gt;{&lt;br /&gt;   print STDERR "Cannot determine _SC_OPEN_MAX: $!"&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;   print "Max open files: $max_open\n";&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To check on values that can be queried using sysconf(), consult the manual page or the include files &lt;limits.h&gt;or &lt;unistd.h&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;POSIX::pathconf&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Some limits may have different values on different logical filesystems on the same overall Unix system. These are mostly related to the properties of the filesystem, such as the maximum length of a filename, or a pathname.&lt;br /&gt;To query such a value, use the POSIX::pathconf function. It is similar in its operation to sysconf, except that it requires either a pathname or a file descriptor representing an already open file to be passed in addition to the name of the limit being queried. This indicates on which filesystem the limit is being checked.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;$max_name_len = pathconf('.', _PC_NAME_MAX);&lt;br /&gt;&lt;br /&gt;if (!defined $max_name_len)&lt;br /&gt;{&lt;br /&gt;   print STDERR "Cannot determine _PC_NAME_MAX: $!"&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;   print "Max name length: $max_name_len\n";&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The return values from pathconf are the same as those from sysconf.&lt;br /&gt;fpathconf has the same functionality as pathconf, except is takes as its first argument a file descriptor instead of a file name. File descriptors will be described later.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Dates and Times&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;Unix systems count time as a number of seconds from a fixed starting point, called the Epoch, that is defined as midnight (00:00:00) on January 1st, 1970.&lt;br /&gt;This is how time is represented internally in the operating system, applications use a number of functions to translate this into the appropriate representation, taking into account timezones and daylight saving time.&lt;br /&gt;To find the number of seconds since epoch, use the time() built-in function. This can be useful for timing operations to the nearest second.&lt;br /&gt;On some systems it may be possible to use an alternative function, gettimeofday(). This function was originally part of the BSD Unix family, it is often useful because it provides a higher resolution of the time measured. To use gettimeofday() you are required to pass in an indication of a timezone as the second argument. It is acceptable to use NULL here, signifying the current timezone.&lt;br /&gt;&lt;br /&gt;For measuring time in better granularity than one second, you may use either the Time::HiRes module from CPAN, or if you have gettimeofday(2), you may be able to use the syscall interface of Perl, see the perlfaq8 manpage for details.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Displaying Dates and Times&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Although the central time representation in Unix is a count of seconds, there are many ways in which the date and time can be displayed. A collection of functions allow the programmer to convert the date from the seconds count into various formats, including formatted strings and a structured “broken-down time” representation.&lt;br /&gt;&lt;br /&gt;The most commonly used function is localtime(), which takes the basic second count and converts it to a string, in the correct timezone and ready for printing: By default the current time is returned, but output from time() can be used as an argument.&lt;br /&gt;&lt;br /&gt;The Time module offers interfaces to localtime and gmtime where the time elements are named.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;“Broken Down Time” Array&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Sometime it is desirable to obtain partial date information, for example the month or year. To do this, it is best to use an alternative representation known as “broken down time”, as returned by localtime in list context.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Index name Purpose Range Notes&lt;br /&gt;&lt;/em&gt;0        sec Seconds after minute 0-61 2 "leap seconds"&lt;br /&gt;1        min Minutes after hour 0-59&lt;br /&gt;2        hour Hours 0-23&lt;br /&gt;3        mday Day of the month 1-31&lt;br /&gt;4        mon Month of the year 0-11 July is 6 (not 7)&lt;br /&gt;5         year Years since 1900 2003 is 103&lt;br /&gt;6        wday Days since Sunday 0-6&lt;br /&gt;7       yday Days since 1 Jan 0-365&lt;br /&gt;8       isdst In Daylight Saving Time -1/0/1&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The elements in the list allow the programmer to extract any pertinent pieces of date or time information to allow more specialised calculations to be performed. The sec range requires some explanation: normally the upper limit is 59, but up to 2 extra "leap seconds" can sometimes be added.&lt;br /&gt;To translate from the number of seconds since epoch to broken down time, use localtime or gmtime:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   @dt = gmtime ( $secs );&lt;br /&gt;   @dt = localtime ($secs );&lt;br /&gt;&lt;/span&gt;If the argument is omitted the current time is used. The difference is that localtime will return the time correct in the current timezone, gmtime returns the time correct in GMT (basically this is the same as UTC).&lt;br /&gt;Alternatively, the POSIX function strftime allows the programmer to apply printf()-like formatting so that the exact format of the date can be specified when it is printed. Consult the manual page for details of the formatting options - they are considerable…&lt;br /&gt;It is possible to translate from broken down time back to seconds since epoch. To do this use the POSIX function mktime.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Many standard Unix system APIs can be called from Perl, some are built-in and some come from modules, notably POSIX.&lt;br /&gt;&lt;br /&gt;The original APIs were designed to be called from C, so knowledge of that language is useful. If you wish to know more about the C interfaces, come on QA's &lt;strong&gt;Unix Programming&lt;/strong&gt; Course.&lt;br /&gt;&lt;br /&gt;I hope to post examples of other Unix API, for example IO, Sockets, and System V IPC.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-111722315526185191?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/111722315526185191/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=111722315526185191&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/111722315526185191'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/111722315526185191'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/05/unix-for-perl-programmers.html' title='Unix for Perl Programmers'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-111478199521183748</id><published>2005-04-29T14:37:00.000+01:00</published><updated>2005-04-29T14:39:55.213+01:00</updated><title type='text'>Doh!</title><content type='html'>It all started when Ryan Air cancelled my flight to Dublin on a Sunday evening.  That meant I had to travel on the Monday, and had half an afternoon with nothing to do.  "Upgrade my laptop to Fedora Core 3!", I thought.  The Devil makes work for idle hands.&lt;br /&gt;&lt;br /&gt;Everything went wonderfully until I got to disk 4 of 4, which would not read.  I had, of course, skipped the media check as being too time consuming.  Mistake number one.&lt;br /&gt;&lt;br /&gt;There is no exit from a Linux install, so I had to remove my laptop battery to try to reboot.  Except it wouldn't, not even Windows XP (it was a dual boot machine).&lt;br /&gt;&lt;br /&gt;So I tried to rescue the hard-disk by reinstalling GRUB (the Linux boot loader), no dice.&lt;br /&gt;&lt;br /&gt;So I tried to rescue the hard-disk by booting Windows XP in rescue mode, except I had forgotten Administrator's password (it had been set under pressure a couple of years previously when attached to a client's network, and hadn't been used since).&lt;br /&gt;&lt;br /&gt;So I tried to download a password cracker, except my company had blocked such sites.&lt;br /&gt;&lt;br /&gt;So I asked someone else to get one for me, except I had not bothered to bring my floppy disk drive to Dublin.  Double doh!&lt;br /&gt;&lt;br /&gt;So I reinstalled Red Hat 9 and recovered the Linux partitions, but still could not boot Windows XP (although I could "see" them from Linux).&lt;br /&gt;&lt;br /&gt;Saturday, back home and on holiday (joke!).  Found the Toshiba recovery disk for my machine – wonderful!  Except that it blasted everything in sight, including all my Linux and Windows XP partitions. &lt;br /&gt;&lt;br /&gt;So I reinstalled Windows XP, and started reinstalling products.  (Great assistance from out support guys, I was reading emails within minutes of installing MS Office).&lt;br /&gt;&lt;br /&gt;Before I got too far I decided to reinstall Fedora (with a new disk 4).  All went OK except it would not boot – Linux or Windows!  Triple doh?!&lt;br /&gt;&lt;br /&gt;So I tried again, this time the install software crashed with an assertion failure.  After much gnashing of teeth I googled the error.  Turned out to be a "known" bug in the utility 'parted' (Bugzilla Bug 138419, if anyone is interested).  It appears that this bug was the cause of the original corruption.  I read up on the bug, and guessed that PartitionMagic might fix it from Windows, except I couldn't boot.&lt;br /&gt;&lt;br /&gt;So I found an old MS-DOS 6 boot disk, and did a swift fdisk /mbr.  That enabled me to boot Windows XP and run PartitionMagic.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Reinstalled&lt;/span&gt; Fedora – third time lucky! &lt;br /&gt;&lt;br /&gt;So now it is Friday of my one week's holiday and I have reinstalled most of my software and restored my backups.  I lost some Perl 6 work I had been doing, but I should be able to regenerate that fairly easily.&lt;br /&gt;&lt;br /&gt;Lesson's learnt:&lt;br /&gt;&lt;br /&gt;ALWAYS do a media check before a Linux install.&lt;br /&gt;Do not throw away Windows, it can get you out of a hole.&lt;br /&gt;Linux is not bug free (!).&lt;br /&gt;If you are going to trash your machine, do it when you have a week to spare.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-111478199521183748?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/111478199521183748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=111478199521183748&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/111478199521183748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/111478199521183748'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/04/doh.html' title='Doh!'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-111277266254301254</id><published>2005-04-06T08:25:00.000+01:00</published><updated>2005-04-06T17:34:36.866+01:00</updated><title type='text'>Pugs</title><content type='html'>Just downloaded the latest version: &lt;a href="http://search.cpan.org/~autrijus/Perl6-Pugs-6.0.14/"&gt;http://search.cpan.org/~autrijus/Perl6-Pugs-6.0.14/&lt;/a&gt;&lt;br /&gt;Will I ever get time to have a proper play with pugs?&lt;br /&gt;What's pugs? It is a prototype Perl 6 written in Haskell. On CPAN it is rated ***** (the highest) and deserves more.&lt;br /&gt;It is slow, and does not support all of Perl 6, but is only meant as a kinda 'proof of concept' tool. It is also great for sado's like me who can't wait for Perl 6.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-111277266254301254?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/111277266254301254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=111277266254301254&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/111277266254301254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/111277266254301254'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/04/pugs.html' title='Pugs'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11940592.post-111277085386244110</id><published>2005-04-06T07:53:00.000+01:00</published><updated>2005-04-06T17:33:05.490+01:00</updated><title type='text'>Perl 6</title><content type='html'>&lt;span style="font-family:arial;"&gt;&lt;em&gt;This is an overview of Perl 6. To avoid a posting of biblical proportions it lacks any technical detail - that will follow in further postings.&lt;/em&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Perl 6 is the next generation of the highly successfully Perl programming language. This posting discusses why Perl 6 is necessary,has had to be developed, and gives an overview of changes.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Why?&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Perl was originally written to replace the scripting language awk when Larry Wall, the author of Perl, became frustrated with awk’s limitations. Perl’s strength lay in text handling, and was an obvious choice for manipulating HTML. It became known as “the duct tape of the web”, although its design pre-dated the web boom. Perl 5, released in 1994, gave it the flexibility and power to rival conventional 4GLs, and boosted it beyond mere scripting and report generation. Successive releases of Perl added database support, references, OO, imbedded low-level code, and a huge range of add-on modules.&lt;br /&gt;&lt;br /&gt;But all is not well, ten years is a long time in IT. Essentially designed to slot between C and Unix shell programs, Perl is showing its age. The syntax of Perl 5 is undeniably situated firmly in Unix-land, yet the product has an important niche in proprietary operating systems, such as Microsoft Windows.&lt;br /&gt;&lt;br /&gt;Unix was originally a process-based system, and Perl was designed to work within that. Over recent years the advantages of multi-threading beyond "just" GUI systems have become clear, and a number of threading models are in common use. Perl has had several tries at multi-threading implementations but none have been completely satisfactory. Retrofitting multi-threading is difficult and painful.&lt;br /&gt;&lt;br /&gt;In Perl 5 Object Orientation capabilities are tacked on as an after-thought. Frankly this is not a problem for Administrators and for small projects, but it is not scalable and lacks many features expected by today's (mostly OO) programmers. For example: a Perl 5 class has no data layout imposed or inherited (inheritance is really only through methods), no data hiding or protection is available (the whole object is visible), and there is no prototype checking for method calls. In Perl 5, multi-threading and OO do not mix; if an object is passed between threads it looses its class.&lt;br /&gt;&lt;br /&gt;Perl 5 language can make it difficult to learn. That Perl has been able to get away with this is a tribute to its power and usefulness. Part of the problem has been a basic rule that, so far as possible, upgrades should be backward compatible. In other words, new features could not replace the old ones, only supplement them. "There's more than one way to do it" can be powerful but is confusing when trying to learn the &lt;em&gt;right&lt;/em&gt; way to do it.&lt;br /&gt;&lt;br /&gt;Perl has begun to loose its dominance on the web with the growth of ASP and the popularity of alternatives like JavaScript and PHP. On the application side Perl is threatened with competition from well-designed rapid development tools and the almost universal adoption of Object Orientation. On the scripting side we see the growth of modern feature-rich tools such as Bash, and the up-coming Microsoft Shell for Longhorn. Directly competing with Perl, and gaining popularity, are the OO scripting languages Ruby and Python. In the long term these could sideline Perl and destine it to the Great Recycle Bin in the sky.&lt;br /&gt;&lt;br /&gt;The source code of the Perl interpreter has been highly hacked over the years to the extent that changes are now difficult to implement without breaking apparently unrelated code. This is a common problem with software that has had to adapt to meet changing needs and expectations.&lt;br /&gt;&lt;br /&gt;If the language and culture is to survive a radical change is needed.&lt;br /&gt;&lt;br /&gt;Enter Perl 6. Perl 6 is being designed and specified - that in itself is a novelty - by a confederation of programmers from the Perl community, shepherded by Larry Wall.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;What's new?&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Perl 6 is designed for change, and an expected life of over twenty years. There is no desire for backward compatibility. compatibility, Perl 5 scripts will rarely, if ever, run directly on Perl 6. Fortunately conversion routines and transition aids are being produced.&lt;br /&gt;&lt;br /&gt;There is a price to pay for Perl 6 in the investment made in Perl 5 skills. Those who are comfortable with Perl 5 are naturally aggrieved to find they are beginners again. It should be made clear that Perl 6 is still undeniably Perl, after all it was written by Perl people who have probably invested more in Perl skills anyone else. There are a huge number of new features, but many of them are optional. As with any other product, users of Perl 6 will learn and use just those features needed to get the job done.&lt;br /&gt;&lt;br /&gt;A technical overview of changes in Perl 6 is given as an Appendix to the QA Perl 5 Programming course.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Parrot&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;In Perl 6, the language syntax and implementation internals have been separated, in a similar way to the Common Language Runtime in Microsoft's .Net product, and Sun's Java runtime. The language independent runtime component is called Parrot. Parrot is downloadable now, and you can write Parrot Assembler (PASM) if you really must. A higher level interface is Parrot Intermediate Representation, or PIR. PIR is expected to take the place of Perl 5's XS interface for low-level code.&lt;br /&gt;&lt;br /&gt;Although its aim was to drive Perl 6 code, it was realised quite early on that other similar languages could be plugged into Parrot. Implementations of Ruby, Python, Java, PHP, and others, exist or are being developed. More can be added "merely" by generating the writing the PASM or PIR interface. Part of the attraction of this approach is that objects created for Parrot may be shared, regardless of the language. The Database Interface (DBI) module from Perl 5 is being rewritten for Parrot, so it should be usable from any Parrot language. Parrot also enables general functionality such as multi-threading and garbage collection to be abstracted by the language.&lt;br /&gt;&lt;br /&gt;While there is no specific aim to compete, there is an interesting overlap between Parrot and Microsoft's .Net, more specifically between Parrot and Mono, which is the portable implementation of .Net, now owned by Novell. For example, both intend to run Python and PHP, and C# on Parrot is a possibility. Will Parrot and .Net compete head-to–head? Possibly, but it is doubtful that Parrot will run C# as fast as .Net, or that .Net will run Perl 6 in a satisfactory way.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Perl 6 OO&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Perl 6 is Object Oriented from the ground up and for many Perl programmers that will be enough reason to use it. The syntax to define a class is similar to other languages, and variables are objects. For example, to find the length of a variable we now call a method on it, rather than a library routine. Classes in Perl 6 replace packages in Perl 5, and data layout may be imposed and inherited. Private, public and protected attributes and methods are supported, as well as delegation, roles and so on.&lt;br /&gt;&lt;br /&gt;Multi-threading and OO should co-exist happily in Perl 6, but implementation details are still under wraps. The new garbage collector should remove memory leak problems that plague Perl 5 multi-threading.&lt;br /&gt;&lt;br /&gt;In Perl 6, methods and subroutines have been considerably improved, allowing all the features normally expected, including named and typed arguments, and overloading.&lt;br /&gt;&lt;br /&gt;The inclusion of Object Orientation is not to everyone’s taste, and for many users of the language it will be an irrelevance. Not every job needs OO and knowledge of OO will not be a pre-requisite to enable effective use of Perl 6.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Basic syntax and operator changes&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;There are a number of changes to the basic Perl syntax, which will be immediately obvious to a Perl 5 programmer, such as accessing an array element or hash value. Many of the syntax elements and operators are different, and some are less than obvious. This is not the place to list them, partly because they have not yet been finalised.&lt;br /&gt;&lt;br /&gt;A number of new operators are available in Perl 6, particularly for handling lists. Some allow operations on all elements in a list and others give the ability to join and match lists in a number of different ways.&lt;br /&gt;&lt;br /&gt;The reasoning behind the operator changes is to make Perl 6 easier. New Perl programmers will be able grasp its concepts more readily. Experienced Perl 5 programmers will have to learn new ways, but at least they already know the concepts and can concentrate on learning the new syntax.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Regular Expressions – Rules&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;A Regular Expression (RE) describes text of interest, usually for extraction or editing. It consists of a "meta-language", and the one chosen for Perl 5 is a well known dialect based on POSIX and used by many other languages and tools, including Microsoft .Net.&lt;br /&gt;&lt;br /&gt;Perl 6 has modified the language with the intention of clarifying it. Very few of the familiar meta-characters are changed in Perl 6, but the most significant (the one everyone is shouting about) is the use of white space. In Perl 6 white space is used as in any other part of the program - it is not significant unless quoted.&lt;br /&gt;&lt;br /&gt;Changes such as new quantifier delimiters are part of assertion syntax. Assertions are an extension of the concept of character classes that either match (true) or do not (false). Assertions return rules that can be stored meta-characters, a single or list of literals, array elements or hash keys, and even code. Many of these features can be achieved in Perl 5, but rules bring them together. The Perl 6 language itself will be expressed in rules.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Traits and Attributes&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;A feature of most scripting languages is that variables are type-less until a value is assigned to them. Later in its life the variable (and possibly its value) might change type. Perl 5 has always had that feature and, by default, so does Perl 6. For some operations typed variables are required and, although some checking is possible in Perl 5, Perl 6 extends this with optional built-in traits applied at compile-time. Aside from the additional help these supply to program logic, they also help the optimiser.&lt;br /&gt;&lt;br /&gt;Attributes enable a value to be overridden depending on its context at run-time. This is a familiar theme in Perl 5, but Perl 6 has introduced many more contexts and ways to force them.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;When?&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Good question. We were promised a development release in Quarter 3, 2005, but funding problems have caused slippage. At the time of writing a pessimistic guess is Quarter 1 2006 for the development release and Quarter 1 2007 for a production release. What state the development release will be in is anyone's guess, but for sure it's website will get a huge number of downloads from day 1. The community will make it work, and work well.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Is Perl 5 dead?&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;No, far from it. Partly because of the uncertain Perl 6 timetable, Perl 5 maintenance continues, and releases are planned for several years yet. Unlike commercial organisations, the Perl community has no interest in pressuring people to upgrade, Perl 4 maintenance continued for some time after 5 was released.&lt;br /&gt;&lt;br /&gt;Ponie is rather contrived from Perl On New Internal Engine. It is the interface required to run Perl 5 upon Parrot. It should enable some of the advantages of Parrot, like operating system abstraction, to be fitted to Perl 5. Versions of Perl 5 running with Ponie on Parrot should be available at Perl 5.12. It is intended that eventually all Perl 5 development will move to Ponie on Parrot.&lt;br /&gt;&lt;br /&gt;Perl 5 modules from CPAN should be able to run on Perl 6 via Ponie. This will reduce the problem of a lack of Perl 6 modules in the early days.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Perl 6 represents a change of emphasis for the Perl language. It should be easier to learn and use for today's generation of programmers. Existing Perl programmers will hate some changes but like others. Some will stay on Perl 5, but will be fighting a rear-guard action as the benefits of Perl 6 become more apparent.&lt;br /&gt;&lt;br /&gt;QA (&lt;a href="http://www.qa.com"&gt;www.qa.com&lt;/a&gt;) intends to produce a Perl 6 for Perl 5 Programmers course as soon as a viable version of Perl 6 is available. Pure Perl 6 courses will then follow. It is intended to continue updating the Perl 5 Programming course to keep it in line with Perl 5 maintenance releases. And of course when Perl 7 is released…&lt;br /&gt;&lt;br /&gt;From Larry Wall:&lt;br /&gt;"Perl 6 is merely the prototype for Perl 7.:-)"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;A technical overview of changes in Perl 6 is given as an Appendix to the QA Perl 5 Programming course.&lt;br /&gt;&lt;br /&gt;The Perl 6 development web site is dev.perl.org/perl6. Larry Wall's explanations are given in Apocalypses at dev.perl.org/perl6/apocalypse, with further information and examples in Exegeses, dev.perl.org/perl6/exegesis. These are a little out of date, but the Synopses at dev.perl.org/perl6/synopsis were updated in December 2004.&lt;br /&gt;&lt;br /&gt;A fortnightly digest of events in Perl 6 development is posted onto the O'Reilly Perl website, www.perl.com.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11940592-111277085386244110?l=darkeside.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darkeside.blogspot.com/feeds/111277085386244110/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11940592&amp;postID=111277085386244110&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/111277085386244110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11940592/posts/default/111277085386244110'/><link rel='alternate' type='text/html' href='http://darkeside.blogspot.com/2005/04/perl-6.html' title='Perl 6'/><author><name>Clive</name><uri>http://www.blogger.com/profile/06031966607543564115</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
