<?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-753668960778118906</id><updated>2011-09-21T19:03:10.426+02:00</updated><category term='autovivification'/><category term='perfectionism'/><category term='GCD'/><category term='contributing'/><category term='SQL'/><category term='web'/><category term='mv'/><category term='Perl 5'/><category term='hash'/><category term='community'/><category term='projects'/><category term='open source'/><category term='vulnerabilities'/><category term='motivation'/><category term='hackathon'/><category term='contextual variables'/><category term='Quota.pm'/><category term='bind variables'/><category term='Apache'/><category term='proto'/><category term='mother'/><category term='precedence'/><category term='Rådhusplassen'/><category term='ML'/><category term='humor'/><category term='Fcntl'/><category term='system'/><category term='feather'/><category term='security'/><category term='ClamAV'/><category term='humour'/><category term='moral'/><category term='NPW 2009'/><category term='Perl'/><category term='Lisbon'/><category term='laziness'/><category term='line length'/><category term='File::Path'/><category term='Digest::MD5'/><category term='alcohol'/><category term='Unicode'/><category term='permissions'/><category term='adverbial'/><category term='PR'/><category term='DateTime'/><category term='photo'/><category term='Firefox'/><category term='YAPC'/><category term='Oslo'/><category term='scriptlets'/><category term='Perl 6'/><category term='exponents'/><category term='elegance'/><category term='flowers'/><category term='blogging'/><category term='autodie'/><category term='Unix'/><category term='sandbox'/><category term='role-playing'/><category term='Rakudo *'/><category term='crazy'/><category term='inspiration'/><category term='beautiful'/><category term='gender bias'/><category term='clutter'/><category term='shell'/><category term='Schwartz'/><category term='dice'/><category term='IRC'/><category term='CGI'/><category term='code'/><category term='Euclid'/><category term='Iron Man'/><category term='friends'/><category term='bots'/><category term='NPW 2006'/><category term='constant'/><category term='program'/><category term='mst'/><category term='rename'/><category term='trivial'/><category term='coding style'/><category term='time'/><category term='PHP'/><category term='meta'/><category term='prepared statements'/><category term='File::Copy'/><category term='modulo'/><category term='Ruby'/><category term='Oslo.pm'/><category term='hobby'/><category term='Rakudo'/><category term='virus'/><category term='Rakudo ng'/><category term='operators'/><category term='md5'/><category term='one-liners'/><category term='error checking'/><category term='expert'/><category term='zip'/><title type='text'>How Can I Explain This?</title><subtitle type='html'>A blog mostly about Perl; the community, the language and its variants, programming Perl, Perl annoyances, Perl joys, etc.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>bakkushan</name><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>55</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-753668960778118906.post-4808332107293893627</id><published>2011-07-25T21:46:00.007+02:00</published><updated>2011-07-25T23:08:20.777+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rådhusplassen'/><category scheme='http://www.blogger.com/atom/ns#' term='Oslo'/><category scheme='http://www.blogger.com/atom/ns#' term='flowers'/><title type='text'>A warm and powerful time in unity</title><content type='html'>Occasionally, I have faith in my fellow Norwegians.&lt;br /&gt;&lt;br /&gt;This afternoon was one of those times.&lt;br /&gt;&lt;br /&gt;As &lt;a href="http://www.bbc.co.uk/news/world-europe-14284377"&gt;international media will tell you&lt;/a&gt;, this afternoon was very special for those of us living in Oslo.&lt;br /&gt;&lt;br /&gt;It started with a Facebook event, that rapidly spread via national media, friends talking and whatnot. If it hadn't been a planned event, it would have been a very large &lt;a href="http://en.wikipedia.org/wiki/Flash_mob"&gt;flash mob&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It was with some trepidation that my colleague and I walked towards Rådhusplassen (the city hall square), as we well knew that a gathering of tens of thousands of people would be a very decent terrorist target.&lt;br /&gt;&lt;br /&gt;The general idea was that people would gather there, carrying roses, and then walk peacefully to somewhere else (I've forgotten where). The plan did not survive. One of the major suppliers of plants and flowers said they would sponsor free roses. Every florist was out of flowers in no time, except for potted ones, it looked almost like locusts had passed by.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-Dpv-MaP6K4Y/Ti3TGEUvMwI/AAAAAAAAAZ8/iRkZGKoDAJ8/s1600/P1000373s.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://3.bp.blogspot.com/-Dpv-MaP6K4Y/Ti3TGEUvMwI/AAAAAAAAAZ8/iRkZGKoDAJ8/s320/P1000373s.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5633390810103755522" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As we walked on, the crowd density increased, until it exceeded anything I have ever experienced. We Norwegians are very fond of going downtown for our &lt;a href="http://en.wikipedia.org/wiki/Norwegian_Constitution_Day"&gt;constitution day May 17&lt;/a&gt;, or supporting events like the &lt;a href="http://en.wikipedia.org/wiki/FIS_Nordic_World_Ski_Championships_2011"&gt;Nordic World Ski Championships&lt;/a&gt; or the &lt;a href="http://en.wikipedia.org/wiki/1994_Winter_Olympics"&gt;Winter Olympics in 1994&lt;/a&gt;, and the crowds are enormous for a small country such as ours. &lt;span style="font-style:italic;"&gt;Those days and events cannot compare.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-Xy6fJTRPX1A/Ti3TOlnpmJI/AAAAAAAAAaE/1X_qh9sf_ug/s1600/P1000376s.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 320px; height: 248px;" src="http://3.bp.blogspot.com/-Xy6fJTRPX1A/Ti3TOlnpmJI/AAAAAAAAAaE/1X_qh9sf_ug/s320/P1000376s.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5633390956480403602" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The sea of flowers, the human warmth and compassion, the sense of unity of purpose – it was almost overpowering, and when Maria Mena started singing Ole Paus's &lt;a href="http://www.youtube.com/watch?v=1LHAwC9Xn38"&gt;Mitt lille land&lt;/a&gt;, I let the tears flow. At the end, we were asked to leave slowly, take care of eachother, and take our flowers – which the arrangers had planned to be placed in a single, potently meaningful place – and leave them all over Oslo.&lt;br /&gt;&lt;br /&gt;If you weren't there, I wish you were.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-34wwGrEWUQM/Ti3YLU9JGFI/AAAAAAAAAaM/af_UXolQduc/s1600/P1000378s.jpg"&gt;&lt;img style="float:clear; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 219px; height: 320px;" src="http://2.bp.blogspot.com/-34wwGrEWUQM/Ti3YLU9JGFI/AAAAAAAAAaM/af_UXolQduc/s320/P1000378s.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5633396398025676882" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-4808332107293893627?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/4808332107293893627/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=4808332107293893627' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/4808332107293893627'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/4808332107293893627'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2011/07/warm-and-powerful-time-in-unity.html' title='A warm and powerful time in unity'/><author><name>bakkushan</name><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><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-Dpv-MaP6K4Y/Ti3TGEUvMwI/AAAAAAAAAZ8/iRkZGKoDAJ8/s72-c/P1000373s.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-753668960778118906.post-550430945600804621</id><published>2010-12-24T14:04:00.005+01:00</published><updated>2010-12-24T15:31:23.415+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mother'/><title type='text'>Christmas Star</title><content type='html'>I grew up with my parents, the only child.&lt;br /&gt;&lt;br /&gt;I also grew up with friends, and had very tight and warm family ties with my father's sister's children - my cousins, my brothers in spirit.&lt;br /&gt;&lt;br /&gt;About twenty years ago, my father's health had declined so much that he could hardly work. He had recently been laid off, as a part of cutbacks just before his employer went bankrupt. Physical labour was hard on him, and we, his family, did not understand why, how, or how much. He received unemployment benefits as long as that was permissible, and then he got a job with an old friend, who owned a technical clothing store. That did not work out very well, because it was really tough on father to walk among aisles and restocking clothes. He even fainted once.&lt;br /&gt;&lt;br /&gt;The late eighties and nineties were wondrous times in many ways, but the medical profession had hardly heard about ME or COLD/COPD as we know these classifications today. Getting medical recognition that my father was effectively unable to work was almost impossible, particularly considering that he – as so many from his generation – was a smoker. If you have any kind of problems with general shortness of breath, and a doctor asks you, "do you smoke", answering "yes" was then (and apparently still is) a very, very bad idea. The smoking then becomes the only focus, and the rest of the patient's problems seem pretty irrelevant.&lt;br /&gt;&lt;br /&gt;But my father did get his disability pension.&lt;br /&gt;&lt;br /&gt;In 1994, his father - my grandfather - fell in the snow and froze to death. He had been a widower for five years. Father and his sister inherited a small farm house with a little bit of land, in Vang in Hedmark. My parents sold our house in Oslo, bought my aunt's share, and moved. I moved to an apartment in a more central location in Oslo.&lt;br /&gt;&lt;br /&gt;It was strange to not see my parents every day anymore, but it was also a sort of relief - a young grown-up probably benefits from moving, and I think I did. I certainly felt it was over due. :) But I kept regularly in touch with my parents, visited them every month or so, and we continued spending Christmas together every year, with my surviving grandmother, as we had for every Christmas since I was born in 1972.&lt;br /&gt;&lt;br /&gt;Through the years, my father's health kept declining, and he became less and less active. Traveling became a chore.&lt;br /&gt;&lt;br /&gt;In 2001, a very good friend of mine was diagnosed with particularly aggressive melanoma, but there was hope.&lt;br /&gt;&lt;br /&gt;Around the same time, my father's health was so bad that he hardly walked around, and he didn't drive a car anymore because he thought it was irresponsible and unsafe. My parents sold the farm house and the land in 2002, and moved to an apartment in central Hamar. The apartment was fairly well suited for the elderly and disabled, and it saved my mother lots of house and garden work - which of course my father could take no part in.&lt;br /&gt;&lt;br /&gt;My friend's cancer spread.&lt;br /&gt;&lt;br /&gt;I still celebrated Christmas with my parents, every after grandmother died in 2003. The same year, my friend collapsed in my arms in a seemingly epileptic fit. That was a brain tumour. The same spring, they discovered that the cancer had spread to his colon. A few friends and I were visiting him a fine May day, when he suddenly panicked, started hyperventilating, pressed his pain pump's button repeatedly and pulled the alarm string. We were ushered out by the nurses. Five minutes later, he died, shortly before his family came to see him.&lt;br /&gt;&lt;br /&gt;A couple of years later, my father was completely dependent on an electrical wheelchair, a chair or a bed - standing unaided was a risky affair. My mother and father rarely left Hamar, socially or otherwise. This was a pretty heavy burden for us to bear, my parents were both socially active before, and had many good friends. My mother was diagnosed with operable breast cancer in 2005, and the tumour and lymph cysts were surgically removed within a couple of weeks.&lt;br /&gt;&lt;br /&gt;I had started sleeping with my phone next to my pillow.&lt;br /&gt;&lt;br /&gt;We still celebrated Christmas together, and in 2007, my father took a chance, and visited his sister in Oslo for her 70th birthday. It was a wonderful day.&lt;br /&gt;&lt;br /&gt;I never went anywhere without my cellphone, and made sure that I had the wireless house phone with me even in the bathroom.&lt;br /&gt;&lt;br /&gt;In the summer of 2008, my father's brother-in-law, my uncle, was admitted to hospital because of what he thought was severe constipation. It wasn't, it was cancer. I visited him about half-way into his first week in hospital, and he was already so weak that he couldn't sit up and had to wear an oxygen mask, but he was fairly lucid. But he looked no healthier than my friend did just before he died, and right enough, a week later, my uncle was dead. My aunt and my cousins still came for my father's 70th birthday shortly afterwards, and it was a very fine celebration, despite that I had to drive my father home early because he was too tired.&lt;br /&gt;&lt;br /&gt;My father went through a lot in those later years. He broke his hip from a fall indoors, and he needed extensive home care. He was frequently in the hospital for emergency care. I started having trouble sleeping, and was constantly worried for The Phone Call.&lt;br /&gt;&lt;br /&gt;Late in 2008, my father was admitted to palliative care at Prestrud in Hamar, it was now too hard and difficult to care for him at home. My father had probably already suffered brain damage from lack of oxygen - which was untreated, because, hey, he was a smoker, and he just couldn't stop smoking - his withdrawal symptoms were too bad. And, hey, if you don't stop smoking, you don't get proper medical care.&lt;br /&gt;&lt;br /&gt;My mother and I still hoped that we could celebrate Christmas in their apartment, but it was soon obvious that it would be impossible. So we prepared to celebrate part of Christmas with him at Prestrud.&lt;br /&gt;&lt;br /&gt;I recall that Christmas Eve more vividly than most. My mother and I followed most of the old routine. The TV was on, and the traditional movie "&lt;a href="http://www.imdb.com/title/tt0075128/"&gt;The Journey to the Christmas Star&lt;/a&gt;" was showing as it always is. A character, Sonja, sings the song "Christmas Star, come to me", and I start crying.&lt;br /&gt;&lt;br /&gt;We visited father at Prestrud, had Christmas cookies, biscuits, hot chocolate with cream and a good time, all considering.&lt;br /&gt;&lt;br /&gt;A day in February, my mother called me at work. Father had pneumonia. I told my boss that I had to go, and went home to pack. Shortly afterwards, my mother called again; father was dead.&lt;br /&gt;&lt;br /&gt;It was a strange funeral. Warm and melancholic, a wonderful priest - Helge Hognestad - who had an exceptional grasp of the humanity of it all. The first part of the funeral was tough going for me, but then I held my speech for father, and talked about many of the good things and times that I associate with him. Carrying his casket was tough, too, but when the hearse drove off, I was so relieved that I couldn't stop smiling.&lt;br /&gt;&lt;br /&gt;Father's suffering was over. Mother's suffering was over. My suffering was over, too.&lt;br /&gt;&lt;br /&gt;But then came the double whammy: in late spring, mother was diagnosed with pancreatic cancer, the kind which has seen an amazing increase in surviving patients, then at an estimated whopping 5%. It was a very hard blow, but then my mother and I started talking about it, and she decided to live her life in full, for however long that was.&lt;br /&gt;&lt;br /&gt;In spite of awful side effects from chemo therapy, in spite of bloody vomit and other unsavory details, she kept on going. We went traveling together twice, my mother went alone or with others several times. She sometimes had to cancel before going, sometimes had to abort the vacation half way, but she never really gave up. We kept more in touch than before, talking at least every week, and meeting once or twice a month. We talked about good things and bad, and had a stronger relationship than in many years.&lt;br /&gt;&lt;br /&gt;She started dancing swing again. She took up bridge, which she thought she was awfully bad at after so many years. She did almost all the things she couldn't do while father was too ill to go anywhere, or too ill to be left alone.&lt;br /&gt;&lt;br /&gt;Her health kept declining, in some ways much as my father's had, but far quicker and therefore more visibly. Nobody blamed smoking, though.&lt;br /&gt;&lt;br /&gt;She got help from Hospice Sangen, a day facility for people with severe illnesses, particularly cancer patients. She had an "open return" at Hamar hospital, in case she needed medical care, there was always room there. She got home care from nurses, whenever necessary, and at regular intervals with increasing frequency.&lt;br /&gt;&lt;br /&gt;This fall, she was admitted to Hospice Lovisenberg, Sangen's "mother" facility in Oslo, for help with her significant pain medication problems; the medication just wouldn't take. She was fairly active while she stayed at Lovisenberg. Two Saturdays, she went shopping with me, the first time also with her elder sister. Lovisenberg got the pain sorted out, and on Monday a month ago - my birthday - I drove her home to Hamar again, thinking that she seemed a bit tired and reduced, but all understandable, since she had been stressing herself out a bit with packing and whatnot. Besides, she had been getting enough morphine to kill grown men several times over, on a regular basis, for weeks.&lt;br /&gt;&lt;br /&gt;The following Wednesday, we talked on the phone again. She was more tired, and felt a bit unsteady on her legs, and had therefore gotten a four-wheel walker. I decided that I wanted to check up on her after the coming weekend, which was full of plans for myself - birthday party, roleplaying, etc. I told her I was coming the following Monday, and she was happy that I wanted to.&lt;br /&gt;&lt;br /&gt;I called again on Friday during lunch hour, and my mother said: "I don't have much time left now, Jan. Can you talk to my sister?" and handed the phone over to her sister (not the same who went shopping with us just two weeks earlier). She explained to me that mother was lying on the couch (as she often did when she felt tired), but that she had hardly eaten that day, and my aunt didn't dare leave her alone. I said I'd try to get there this weekend.&lt;br /&gt;&lt;br /&gt;I talked to my boss again, tidied up a few pressing tasks at work, went home and packed. I cancelled the party and notified others that I was not coming for roleplaying or other social events. I then told my mother and aunt that I was coming that evening, got into the car, and did as I said.&lt;br /&gt;&lt;br /&gt;When I got there, we got help from a nurse so that mother could get to bed and sleep there. She was very tired, and barely coherent, though she heard and understood us.&lt;br /&gt;&lt;br /&gt;The following morning, mother couldn't even sit up without aid, and she could not drink and swallow her pills without help. My aunt came back during the day, and we convinced a supervising nurse to have a look at my mother's now fairly swollen legs. We then convinced the nurse to call for an ambulance, and had mother admitted to the hospital that Saturday night.&lt;br /&gt;&lt;br /&gt;At hospital, I called my youngest cousin, the closest person I've had to a brother, and told him briefly how it was. He said he'd come and keep me company.&lt;br /&gt;&lt;br /&gt;During the night, mother had occasional pain in spite of the better pain medication and well-adjusted morphine pump, and occasionally lucid moments. Her breathing was laboured, but when the nurses managed to adjust the morphine dosage up by a third and the bolus frequency limit down by a third, she was well relieved. I had to push the button, though, because my mother could not.&lt;br /&gt;&lt;br /&gt;In the early morning, her breathing slowed and became weaker. She was sleeping or dozing all the while, and I was holding her hand, and my cousin was holding mine.&lt;br /&gt;&lt;br /&gt;Her face was tilted slightly towards me, and one eyelid was slightly ajar, the pupil aligned with my face. She died so peacefully that I can't say exactly when it was. It was beautiful, and I wouldn't have missed it for the world.&lt;br /&gt;&lt;br /&gt;But I miss you, mother, and most of all today, and now I think of Sonja's song and cry.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-550430945600804621?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/550430945600804621/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=550430945600804621' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/550430945600804621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/550430945600804621'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2010/12/christmas-star.html' title='Christmas Star'/><author><name>bakkushan</name><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-753668960778118906.post-5931074280528415524</id><published>2010-08-01T15:05:00.002+02:00</published><updated>2010-08-01T15:10:30.087+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='community'/><category scheme='http://www.blogger.com/atom/ns#' term='Rakudo *'/><title type='text'>Community boost</title><content type='html'>It is now three days since the &lt;a href="http://rakudo.org/announce/rakudo-star/2010.07"&gt;release of Rakudo Star&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Everything has met my personal expectations, except for one major thing:&lt;br /&gt;&lt;br /&gt;There is a bunch of &lt;span style="font-weight:bold;"&gt;new&lt;/span&gt; people on #perl6, who are actively engaged in trying out Rakudo Star/Perl 6, in testing, submitting bug reports, patch suggestions, asking for help, providing help, helping themselves…&lt;br /&gt;&lt;br /&gt;I really do not have anything profound to say, but I can say this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Now we are really getting somewhere!&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-5931074280528415524?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/5931074280528415524/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=5931074280528415524' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/5931074280528415524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/5931074280528415524'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2010/08/community-boost.html' title='Community boost'/><author><name>bakkushan</name><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-753668960778118906.post-989376866050970965</id><published>2010-07-29T14:29:00.004+02:00</published><updated>2010-07-29T15:46:32.230+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='Rakudo *'/><title type='text'>Rakudo Star is here</title><content type='html'>The wait is over, and a &lt;a href="http://rakudo.org/announce/rakudo-star/2010.07"&gt;usable Rakudo-based Perl 6 distribution is ready&lt;/a&gt; for early adopters. Yay!&lt;br /&gt;&lt;br /&gt;More and more of Perl 6 is implemented in Perl 6.  That is a very good tendency.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-989376866050970965?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/989376866050970965/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=989376866050970965' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/989376866050970965'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/989376866050970965'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2010/07/rakudo-star-is-here.html' title='Rakudo Star is here'/><author><name>bakkushan</name><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-753668960778118906.post-510923512390174814</id><published>2010-03-04T17:00:00.000+01:00</published><updated>2010-03-04T17:00:04.791+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='coding style'/><category scheme='http://www.blogger.com/atom/ns#' term='error checking'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><title type='text'>Coding styles that make me twitch, part 8</title><content type='html'>One of the worst programming habits I know of, is assuming that everything will work out; you just perform the command/function call, and it has to work. In other words: do not bother checking for error conditions or propagating them, because they are not going to happen anyway. right?&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Wrong.&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;But the code works. Mostly. Except when an error condition occurs. And it will, eventually.&lt;br /&gt;&lt;br /&gt;In some instances, such code is a glorified &lt;em title="&amp;quot;Not that there's anything wrong with that&amp;quot; - some shell scripts are pretty nice"&gt;shell script&lt;/em&gt;. I have ranted about that before. But catching error conditions properly can be tricker than with in-Perl functions and modules. Especially if you have no control over what the external program does, but the original programmer did.&lt;br /&gt;&lt;br /&gt;Even with in-Perl functions and modules, you might run into, ehrm, &lt;em&gt;interesting usage&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Usually, the root of the problem is that the original programmer did not foresee that some his code could grow into something else.&lt;br /&gt;&lt;br /&gt;While it may have been a good idea to create an SQL query wrapper to hide parts of what DBI does for &lt;em title="yeah, I know"&gt;auto-committing statements&lt;/em&gt;:&lt;hr&gt;&lt;small&gt;&lt;pre&gt;sub do_sql {&lt;br /&gt;    my $qry = shift;&lt;br /&gt;    my $ignore = shift;&lt;br /&gt;    if (!$dh) {&lt;br /&gt;        &amp;amp;slogin();&lt;br /&gt;        return if (!$dh);&lt;br /&gt;    }&lt;br /&gt;    my $sh = $dh-&amp;gt;prepare($qry);&lt;br /&gt;    if ($sh &amp;amp;&amp;amp; !$sh-&amp;gt;execute) {&lt;br /&gt;        if ($sh-&amp;gt;errstr =~ /(MySQL server has\&lt;br /&gt; gone away)|(Lost connection to MySQL server)/) {&lt;br /&gt;            &amp;amp;log("Lost MySQL, reconnecting.");&lt;br /&gt;            &amp;slogin();&lt;br /&gt;            return if (!$dh);&lt;br /&gt;            $sh = $dh-&amp;gt;prepare($sqlstmt);&lt;br /&gt;            undef $sh if ($sh &amp;amp;&amp;amp; !$sh-&amp;gt;execute);&lt;br /&gt;        } else {&lt;br /&gt;            undef $sh;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &amp;amp;log("SQL failed: '$qry'.") if (!$sh &amp;amp;&amp;amp; !$ignore);&lt;br /&gt;    return $sh;&lt;br /&gt;}&lt;/pre&gt;&lt;/small&gt;&lt;hr&gt;that is no guarantee that the implementation will be &lt;em title="or even present-proof"&gt;future-proof&lt;/em&gt;, when the subroutine is used like this:&lt;hr&gt;&lt;small&gt;&lt;pre&gt;my $sh=&amp;amp;do_sql("SELECT * FROM tab1 WHERE\&lt;br /&gt; x&lt;&gt;'$cgi-&amp;gt;{data}' AND y&amp;lt;&amp;gt;42");&lt;br /&gt;if (my $res=$sh-&amp;gt;fetchrow_hashref) {&lt;br /&gt;    $cgi-&amp;gt;{ref}=$res-&amp;gt;{ref};&lt;br /&gt;}&lt;br /&gt;&amp;amp;do_sql("UPDATE tab1 SET x='$cgi-&amp;gt;{newdata}',\&lt;br /&gt; y=23, z='$cgi-&amp;gt;{ref}'");&lt;br /&gt;&amp;amp;do_sql("UPDATE tab2 SET tab1_changed='yes'");&lt;br /&gt;&amp;amp;log("Updated tab1, ready for externals");&lt;br /&gt;# Process the changes made above:&lt;br /&gt;system("/usr/local/bin/changestuff.pl");&lt;br /&gt;&amp;amp;log("Finished processing");&lt;/pre&gt;&lt;/small&gt;&lt;hr&gt;Imagine now that changestuff.pl also performs changes in the database tables mentioned above, and that the code above is called in a cron job every minute or so.&lt;br /&gt;&lt;br /&gt;Here is an attempt at listing the worst parts:&lt;ul&gt;&lt;li&gt;&lt;code&gt;do_sql&lt;/code&gt; only pretends to do proper error checking, it mostly does not do anything useful about the error situations.&lt;/li&gt;&lt;li&gt;The query result seems of little consequence.&lt;/li&gt;&lt;li&gt;There is an obvious need for bound variables in the prepared statement, but &lt;code&gt;do_sql&lt;/code&gt; does not support that. So the code pretends the problem does not exist.&lt;/li&gt;&lt;li&gt;When &lt;code&gt;do_sql&lt;/code&gt; is used for updates, there is no check whether the returned statement handle (&lt;code&gt;$sh&lt;/code&gt;) is empty or not, there is no way of knowing whether we are clobbering the database.&lt;/li&gt;&lt;li&gt;Why do we not care whether the external commands succeeds or not?&lt;/li&gt;&lt;li&gt;SQL transactions, anyone?&lt;/li&gt;&lt;li&gt;Yeah, other parts of the style sucks, too.&lt;/li&gt;&lt;/ul&gt;Now imagine the example above multiplied to thousands of lines of inter-dependant code.&lt;br /&gt;&lt;br /&gt;I am happy to say that I do not see things like this &lt;em&gt;too&lt;/em&gt; often.&lt;br /&gt;&lt;br /&gt;However, cleaning up code like this is a PITA, and it is often easier just to close your eyes, add your own code, and leave well enough alone.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-510923512390174814?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/510923512390174814/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=510923512390174814' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/510923512390174814'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/510923512390174814'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2010/03/coding-styles-that-make-me-twitch-part.html' title='Coding styles that make me twitch, part 8'/><author><name>bakkushan</name><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-753668960778118906.post-5435491516599092417</id><published>2010-02-25T16:42:00.001+01:00</published><updated>2010-02-25T16:44:16.458+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='coding style'/><category scheme='http://www.blogger.com/atom/ns#' term='operators'/><category scheme='http://www.blogger.com/atom/ns#' term='precedence'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><title type='text'>Coding styles that make me twitch, part 7</title><content type='html'>&lt;h2&gt;Parentheses and precedence&lt;/h2&gt;&lt;small&gt;This week, I will strive to be better at explaining the problem scope, while heroically and miraculously maintaining brevity.&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;I used to be annoyed at seeing extraneous parentheses with the ternary conditional operator pair &lt;strong&gt;&lt;code&gt;? :&lt;/code&gt;&lt;/strong&gt;, but then I &lt;a href="http://php.net/manual/en/language.operators.comparison.php"&gt;discovered that the PHP language designers decided to break precedence&lt;/a&gt; (see example #3). So I have stopped twitching as much as I used to when seeing parentheses galore in that context.&lt;br /&gt;&lt;br /&gt;In Perl Best Practices, Damian Conway notes that even though the low-precedence logic operators &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;not&lt;/code&gt; and &lt;code&gt;or&lt;/code&gt; may seem &lt;em&gt;nicer&lt;/em&gt;, they can confuse the reader regarding the intended meaning of the code. But he does not &amp;mdash; as far as I can recall or find &amp;mdash; address how these relates to parentheses and precedence &lt;small&gt;(I suppose that should be &lt;em&gt;"parentheses &amp;amp;&amp;amp; precedence"&lt;/em&gt;)&lt;/small&gt;.&lt;br /&gt;&lt;br /&gt;I start twitching when someone insists on using parentheses like this (imagine that the example was more convoluted):&lt;pre&gt;if (expr1 ||&lt;br /&gt;    (expr2 &amp;amp;&amp;amp; expr3) ||&lt;br /&gt;    expr4&lt;br /&gt;    ...)&lt;/pre&gt;That &lt;em&gt;does not help understanding&lt;/em&gt;. It confuses me, as the read, regarding &lt;em&gt;your intentions&lt;/em&gt;. Is there a piece of code missing, perhaps a little bit of &lt;code&gt;|| expr&lt;strong&gt;2b&lt;/strong&gt;&lt;/code&gt; or &lt;code&gt;|| expr&lt;strong&gt;3b&lt;/strong&gt;&lt;/code&gt;?&lt;br /&gt;&lt;br /&gt;Sometimes, I even see misguidedly mixed-in letter-literal operators:&lt;pre&gt;if (expr1 or&lt;br /&gt;    (expr2 &amp;amp;&amp;amp; expr3) or&lt;br /&gt;    (!expr4)&lt;br /&gt;    ...)&lt;/pre&gt;&lt;br /&gt;I much prefer seeing&lt;pre&gt;if (expr1 ||&lt;br /&gt;    expr2 &amp;amp;&amp;amp; expr3 ||&lt;br /&gt;    expr4&lt;br /&gt;    ...)&lt;/pre&gt;or&lt;pre&gt;if (expr1&lt;br /&gt;    || expr2 &amp;amp;&amp;amp; expr3&lt;br /&gt;    || expr4&lt;br /&gt;    ...)&lt;/pre&gt;depending on what floats your boat in the most stylish way imaginable.&lt;br /&gt;&lt;br /&gt;I would have thought that the logical and/or/not part of operator precedence would be easy to understand. It is essentially the same in most programming languages: Ruby, Python, Perl, Java, C, ... and not even PHP managed to mess this one up.&lt;br /&gt;&lt;br /&gt;The chance that anyone is going to be confused by your code because of these parentheses not being there is far, far smaller than the chance that they are going to be confused by their presence.&lt;br /&gt;&lt;br /&gt;I have heard the defense &lt;em&gt;"but the code is so non-obvious that I had to add them!"&lt;/em&gt; Well, &lt;em&gt;make your code obvious instead&lt;/em&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-5435491516599092417?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/5435491516599092417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=5435491516599092417' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/5435491516599092417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/5435491516599092417'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2010/02/coding-styles-that-make-me-twitch-part_25.html' title='Coding styles that make me twitch, part 7'/><author><name>bakkushan</name><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-753668960778118906.post-1357543324339398143</id><published>2010-02-18T21:23:00.003+01:00</published><updated>2010-02-26T20:34:03.547+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='coding style'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><category scheme='http://www.blogger.com/atom/ns#' term='clutter'/><title type='text'>Coding styles that make me twitch, part 6</title><content type='html'>&lt;strong&gt;Edit:&lt;/strong&gt; &lt;em&gt;There are, apparently, strong feelings that I should not post my personal preferences. Reader discretion advised: &lt;strong&gt;this post expresses my personal opinions regarding a limited use case for file handling and filehandles, and must not be read as general advise on how to deal with filehandles in Perl, and so on.&lt;/strong&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Today's theme is: unnecessary variable clutter.&lt;pre&gt;my $fh = new Filehandle("/usr/bin/somecmd someargs |");&lt;br /&gt;while (my $l=&amp;lt;$fh&amp;gt;) {&lt;br /&gt;    if ($l=~m/foo bar zot/) {&lt;br /&gt;&lt;em&gt;        # lots of code that does not depend on&lt;br /&gt;        # a variable file handle, nor creative&lt;br /&gt;        # usage of &lt;strong&gt;$l&lt;/strong&gt; where &lt;strong&gt;$_&lt;/strong&gt; could not be used&lt;br /&gt;        # implicitly just as easily&lt;/em&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;Sure, there &lt;em&gt;are&lt;/em&gt; situations where it makes sense to assign filehandles to variables, or using &lt;code&gt;$l&lt;/code&gt; instead of &lt;code&gt;$_&lt;/code&gt;, but the above example is not one of them. I found no particular reason why the original programmer had used &lt;code&gt;new Filehandle&lt;/code&gt;, either.&lt;br /&gt;&lt;br /&gt;Perl 5 has, on purpose, made this easier for us than in the above example:&lt;pre&gt;open my $FH, '-|', '/usr/bin/somecmd someargs'&lt;br /&gt;    or croak "OMG\n";&lt;br /&gt;while (&amp;lt;$FH&amp;gt;) {&lt;br /&gt;    if (/foo bar zot/) {&lt;br /&gt;        # lots of code&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/753668960778118906-1357543324339398143?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/1357543324339398143/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=1357543324339398143' title='19 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/1357543324339398143'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/1357543324339398143'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2010/02/coding-styles-that-make-me-twitch-part.html' title='Coding styles that make me twitch, part 6'/><author><name>bakkushan</name><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>19</thr:total></entry><entry><id>tag:blogger.com,1999:blog-753668960778118906.post-3639531009391075013</id><published>2010-02-11T01:33:00.003+01:00</published><updated>2010-02-11T01:49:39.512+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='operators'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><category scheme='http://www.blogger.com/atom/ns#' term='exponents'/><title type='text'>Missing feature</title><content type='html'>A few hours ago, I suddenly had a bright(?) idea, or desire if you will:&lt;br /&gt;&lt;br /&gt;Proper (Unicode) exponents in Perl.&lt;br /&gt;&lt;br /&gt;That is, I want to be able to write 2&lt;sup&gt;2&lt;/sup&gt;, 4&lt;sup&gt;137&lt;/sup&gt;, 3&lt;sup&gt;-9&lt;/sup&gt;, etc. &lt;em&gt;and have Perl understand them&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;For Perl 5, I suspect someone would use a source filter to implement it.&lt;br /&gt;&lt;br /&gt;For Perl 6, &lt;a href="http://perlpilot.blogspot.com/"&gt;PerlJam&lt;/a&gt;++ suggested introducing each  of the exponents as postfix operators, using this example for squaring:&lt;pre&gt;our &amp;amp;postfix:&amp;lt;&lt;sup&gt;2&lt;/sup&gt;&amp;gt; := &amp;amp;infix:&amp;lt;**&amp;gt;.assuming(b =&amp;gt; 2);&lt;/pre&gt;But then a negative exponent would complicate things a bit.&lt;br /&gt;&lt;br /&gt;It's a thought, anyway, and not one that I'd want to distract more pressing implementation concerns.&lt;br /&gt;&lt;br /&gt;And ifwhen someone decides that this is a good idea to have in the language core, I'll start nagging about &lt;a href="http://en.wikipedia.org/wiki/Knuth%27s_up-arrow_notation"&gt;Knuth's up-arrow notation&lt;/a&gt;. Not that I'd want anyone attempt calculating 4&amp;uarr;&amp;uarr;&amp;uarr;&amp;uarr;4.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-3639531009391075013?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/3639531009391075013/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=3639531009391075013' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/3639531009391075013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/3639531009391075013'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2010/02/missing-feature.html' title='Missing feature'/><author><name>bakkushan</name><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-753668960778118906.post-9058131186463084664</id><published>2010-02-04T00:21:00.004+01:00</published><updated>2010-02-04T00:34:41.892+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><title type='text'>Spooky</title><content type='html'>This is just a small anecdote.&lt;br /&gt;&lt;br /&gt;Tonight, I finished a small Perl 5 script that I've been wanting to complete for a while, but where I was a bit nervous that I'd fsck it up right and good.&lt;br /&gt;&lt;br /&gt;It was a script designed to handle two tab-separated text sources; one a list of tournament IDs and tournament names, the other a list of player results, one line per result with the player ID, tournament &lt;em&gt;name&lt;/em&gt;, position and score achieved.&lt;br /&gt;&lt;br /&gt;I achieved this by creating a hash of hashes for each file, referencing the first while parsing the other, and &lt;em&gt;bravely inserting the data into a single database table&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;I tested my code piece for piece while building it, which is sensible in itself, but what spooked me was this:&lt;br /&gt;&lt;br /&gt;There was not a single bug.  The script did what it was supposed to do, all along.&lt;br /&gt;&lt;br /&gt;That's not supposed to happen.&lt;br /&gt;&lt;br /&gt;I need a drink.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-9058131186463084664?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/9058131186463084664/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=9058131186463084664' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/9058131186463084664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/9058131186463084664'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2010/02/spooky.html' title='Spooky'/><author><name>bakkushan</name><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-753668960778118906.post-7481565918768458989</id><published>2010-01-29T18:24:00.000+01:00</published><updated>2010-01-29T18:24:23.560+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='laziness'/><category scheme='http://www.blogger.com/atom/ns#' term='Rakudo ng'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='Rakudo *'/><category scheme='http://www.blogger.com/atom/ns#' term='Rakudo'/><title type='text'>Rakudo ng - what will it mean for us?</title><content type='html'>If you've been hanging around the right blogs and the #perl6 IRC channel on Freenode, then you've probably seen references to a slightly mysterious "ng", or "Rakudo ng".&lt;br /&gt;&lt;br /&gt;That's the upcoming (next) version (generation) of Rakudo, which will form the basis for &lt;strong&gt;Rakudo *&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;In essence, this is a refactoring/rewrite of Rakudo for the purpose of better compliance with the specification and performance improvements (yay). The old Rakudo master made it difficult &amp;mdash; if not impossible &amp;mdash; to implement several essential parts of the Perl 6 spec and top priorities on the Rakudo roadmap.&lt;br /&gt;&lt;br /&gt;In January, this has led to less focus on the current Rakudo version's bugs and gotchas, and instead on working to prepare &lt;strong&gt;ng&lt;/strong&gt; as the new master branch &amp;mdash; that is, &lt;em&gt;the Rakudo that you will be downloading the next time&lt;/em&gt;. &lt;br /&gt;&lt;br /&gt;For those of us who do some Perl 6 coding in Rakudo, this means that we can expect a nice little bunch of incompatibilities as compared to the current master. And yes, it's very close, so it's time to prepare.&lt;br /&gt;&lt;br /&gt;Here's a list of the blindingly obvious things I think we need to watch out for:&lt;ul&gt;&lt;li&gt;Older Rakudo was not in line with parts of the spec that &lt;strong&gt;ng&lt;/strong&gt; will be.&lt;/li&gt;&lt;li&gt;The spec has changed. &lt;em&gt;&lt;small&gt;(&lt;strong&gt;ng&lt;/strong&gt; development has uncovered several necessary changes.)&lt;/small&gt;&lt;/em&gt;&lt;/li&gt;&lt;li&gt;Older Rakudo is in line with parts of the spec that &lt;strong&gt;ng&lt;/strong&gt; perhaps isn't.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Rakudo ng&lt;/strong&gt; is, of course, not feature complete when it replaces older Rakudo as the master.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;In other words: let's not fool ourselves into thinking that we all of a sudden have a new Rakudo that's both compatible with the older as well as being spec compliant.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The good news about Rakudo ng&lt;/h2&gt;&lt;p&gt;If you judge by the above paragraphs, you'd think that Rakudo ng was bad for Perl 6 developers. But that's far off the mark. I prodded #perl6 and &lt;a href="http://use.perl.org/~pmichaud/journal/"&gt;Patrick Michaud&lt;/a&gt; before publishing this post, and here's a brief summary of (most of) the improvements we can see coming with Rakudo ng as opposed to the current implementation.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Most of the top priorities of the Rakudo roadmap will be implemented!&lt;/li&gt;&lt;li&gt;Laziness will mostly work (the spec is undergoing change)&lt;/li&gt;&lt;li&gt;Performance improvements, many due to laziness&lt;li&gt;Array/List/Parcel/etc. will be compliant with the updated spec&lt;/li&gt;&lt;li&gt;Protoregexes&lt;/li&gt;&lt;li&gt;Better longest token matching&lt;/li&gt;&lt;li&gt;Meta-operators are really meta, and generated on demand&lt;/li&gt;&lt;li&gt;The base object metamodel is far closer to the spec than before&lt;/li&gt;&lt;li&gt;Major portions of the metamodel are implemented in Perl 6&lt;/li&gt;&lt;li&gt;Array and hash vivification will work properly&lt;/li&gt;&lt;li&gt;Lexical subs and variables work properly&lt;/li&gt;&lt;li&gt;Operators have the correct names (with angles)&lt;/li&gt;&lt;li&gt;Subs have the correct sigils (with ampersands)&lt;/li&gt;&lt;li&gt;Phasers work, and the phaser model is much improved&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Our programs will need a bit of attention. I recommend &lt;a href="http://dev.perl.org/perl6/lists/"&gt;subscribing to perl6-language&lt;/a&gt; for up-to-date information about changes to the specification and language discussions.&lt;br /&gt;&lt;br /&gt;There's still &lt;a href="http://wiki.github.com/rakudo/rakudo/ng-major-features-needed"&gt;a lot of work to be done&lt;/a&gt;, and I'm sure the Perl 6 developers are happy for any help they can get.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-7481565918768458989?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/7481565918768458989/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=7481565918768458989' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/7481565918768458989'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/7481565918768458989'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2010/01/rakudo-ng-what-will-it-mean-for-us.html' title='Rakudo ng - what will it mean for us?'/><author><name>bakkushan</name><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-753668960778118906.post-4251863728434636754</id><published>2010-01-21T22:40:00.003+01:00</published><updated>2010-01-21T22:51:07.583+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><title type='text'>"Your Unix Is Leaking Perl"</title><content type='html'>That has to be one of the weirdest statements I've read in, oh, at least fifteen minutes.&lt;a href="#1"&gt;&lt;sup&gt;[1]&lt;/sup&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.smbc-comics.com/index.php?db=comics&amp;id=1768"&gt;&lt;img src="http://zs1.smbc-comics.com/comics/20100121after.gif" height="50%" width="50%"&gt;&lt;/a&gt;&lt;small&gt;&lt;br /&gt;&lt;em&gt;(The image is a link to the original strip; if you've got javascript enabled, you can see this bonus strip by hovering over the burgundy red button below to the left.)&lt;/em&gt;&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;A huge thanks to &lt;a href="http://www.smbc-comics.com"&gt;Saturday Morning Breakfast Cereal&lt;/a&gt; for this piece of wisdom, but I'm afraid that Zach Weiner got it backwards when he thought that would be expensive.&lt;br /&gt;&lt;br /&gt;May I suggest that when a computer "leaks Perl", it does so because the (hopefully brilliant) Perl programmer is contributing a lot to CPAN?&lt;br /&gt;&lt;br /&gt;;)&lt;br /&gt;&lt;br /&gt;&lt;a name="1"&gt;&lt;/a&gt;&lt;br /&gt;&lt;small&gt;Yes, I've been communicating with customers lately, how did you guess?&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-4251863728434636754?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/4251863728434636754/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=4251863728434636754' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/4251863728434636754'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/4251863728434636754'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2010/01/your-unix-is-leaking-perl.html' title='&quot;Your Unix Is Leaking Perl&quot;'/><author><name>bakkushan</name><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-753668960778118906.post-6433229299481615531</id><published>2010-01-14T16:45:00.007+01:00</published><updated>2010-01-14T18:56:05.028+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='feather'/><category scheme='http://www.blogger.com/atom/ns#' term='Apache'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><title type='text'>feather.perl6.nl - a Sysadminish Tale</title><content type='html'>&lt;small&gt;&lt;pre&gt;&amp;lt;@Juerd&amp;gt; frettled: Blog about the mess you found when&lt;br /&gt;         you first logged in on feather yesterday :)&lt;/pre&gt;&lt;/small&gt;&lt;hr /&gt;Sure.&lt;br /&gt;&lt;br /&gt;This will, incidentally, also explain why Trac is kindof unavailable now.&lt;br /&gt;&lt;br /&gt;feather.perl6.nl is a Xen guest (a virtual machine, hereafter "VM") that's hosting several important services for the Perl 6 community. There's SVN web access, a &lt;a href="http://trac.edgewall.org/"&gt;Trac&lt;/a&gt; installation, and a bunch of other stuff I honestly don't know the half of.&lt;br /&gt;&lt;br /&gt;Recently, the VM started running out of memory too often for comfort.  What was going on?  Juerd asked for help in tracking down the problem, as he didn't have the time to do so himself.  And needing some distraction from work -- something to help me procrastinate -- I volunteered.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://jani.at.ifi.uio.no/pics/headbash.gif"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 113px; height: 113px;" src="http://jani.at.ifi.uio.no/pics/headbash.gif" alt="" border="0" /&gt;&lt;/a&gt; By now, you're probably banging your head on your keyboard in sympathy with me for saying something that may have been slightly less than brilliant. You know the feeling; Matt Trout reaches his right hand towards you, the world is suddenly in slow-motion, you see his hand closing in on you, his grin widening, and a voice saying &lt;em&gt;"thhhhhaaaaannnnnkssss ffffooooorrr vooooluuunnnteeeerrriiiinnnnng"&lt;/em&gt;, and you're basically up that creek with all the mud and dirt in it.&lt;br /&gt;&lt;br /&gt;After handing over an SSH public key and getting sudo access (yeah, yeah, &lt;a href="http://jani.at.ifi.uio.no/pics/headbash.gif"&gt;I know&lt;/a&gt;), I had a look anyway.&lt;br /&gt;&lt;br /&gt;First, I went on a brief but wild goose chase, finding some error messages regarding ConsoleKit which appeared to be more frequent just before the server went out of memory, checked the Debian version (an unholy mix of Debian unstable and Debian experimental with lots of package updates pending someone's attention), and generally tried to get a feel of how the system was configured.&lt;br /&gt;&lt;br /&gt;We already knew that Apache somehow might be responsible for gobbling up available memory, so my first action was to have a look at the last 100,000 lines of the Apache access log, using a simplistic log analysis script.&lt;br /&gt;&lt;br /&gt;But which log?  There were three Apache log directories to choose from.  I (correctly) guessed that the one called simply &lt;code&gt;/var/log/apache2&lt;/code&gt; might be the interesting one, the others seemed to be legacy directories which should have been removed ages ago.&lt;br /&gt;&lt;br /&gt;According to the script, there were 0 accesses in the last 100,000 lines.&lt;br /&gt;&lt;br /&gt;Knowing the script, that was not so strange, because it makes a few assumptions regarding the log format, using a regexp belonging to the days before named captures and whatnot:&lt;small&gt;&lt;pre&gt;while (&amp;lt;&amp;gt;) {&lt;br /&gt;  if (/^(\S+) (\S+) - - \[[^\]]*\] \"(GET|POST) \S*&lt;br /&gt;       HTTP(|\/1\.[01])\" \d{3} (\d+) \"/) {&lt;/pre&gt;&lt;/small&gt;The regexp line has been split for the sake of the line width of this blog.  There's nothing to be proud of here.&lt;br /&gt;&lt;br /&gt;Anyway, I first had to remove the first capture; feather's logs weren't showing the virtualhost as the first column, and access types were most certainly not limited to only GET and POST:&lt;small&gt;&lt;pre&gt;frettled@feather:~$ sudo awk '{print $6}' /var/log/apache2/access.log|&lt;br /&gt;sort -u&lt;br /&gt;"CHECKOUT&lt;br /&gt;"CONNECT&lt;br /&gt;"DELETE&lt;br /&gt;"GET&lt;br /&gt;"HEAD&lt;br /&gt;"MERGE&lt;br /&gt;"MKACTIVITY&lt;br /&gt;"OPTIONS&lt;br /&gt;"POST&lt;br /&gt;"PROPFIND&lt;br /&gt;"PROPPATCH&lt;br /&gt;"PUT&lt;br /&gt;"REPORT&lt;/pre&gt;&lt;/small&gt;Right.&lt;br /&gt;&lt;br /&gt;After straightening that up (and adding &lt;code&gt;%v&lt;/code&gt; to the &lt;code&gt;LogFormat&lt;/code&gt; specifications in the Apache config for future use), I got the following result:&lt;small&gt;&lt;pre&gt;Use of uninitialized value $size in addition (+)&lt;br /&gt;at /usr/local/sbin/bandwidthips line 39, &lt;&gt; line 1002.&lt;br /&gt;Use of uninitialized value $size in addition (+)&lt;br /&gt;at /usr/local/sbin/bandwidthips line 40, &lt;&gt; line 1002.&lt;br /&gt;Use of uninitialized value $size in addition (+)&lt;br /&gt;at /usr/local/sbin/bandwidthips line 44, &lt;&gt; line 1002.&lt;/pre&gt;&lt;/small&gt;AAAARRGH! Idiot! Imbecile! Inept half-wit! Yep, I'd forgotten to renumber my captures. See, this is why Perl should be in version &lt;strong&gt;5.10.1&lt;/strong&gt; or &lt;strong&gt;6&lt;/strong&gt; when fiddling with those bloody annoying regexps.&lt;small&gt;&lt;pre&gt;frettled@feather:~$ sudo tail -100000 /var/log/apache2/access.log|&lt;br /&gt;/usr/local/sbin/hitips|head&lt;br /&gt;193.200.132.146: Bytes = 14329487 (3.44%), Hits = 51503 (51.82%)&lt;br /&gt;66.249.71.2: Bytes = 132116084 (31.73%), Hits = 18111 (18.22%)&lt;br /&gt;66.249.71.37: Bytes = 50846948 (12.21%), Hits = 6236 (6.27%)&lt;br /&gt;93.158.149.31: Bytes = 54880221 (13.18%), Hits = 1894 (1.9%)&lt;br /&gt;71.194.15.106: Bytes = 460200 (0.11%), Hits = 1894 (1.9%)&lt;br /&gt;209.9.237.232: Bytes = 433388 (0.1%), Hits = 1686 (1.69%)&lt;br /&gt;193.200.132.135: Bytes = 1726871 (0.41%), Hits = 1635 (1.64%)&lt;br /&gt;193.200.132.142: Bytes = 429358 (0.1%), Hits = 1609 (1.61%)&lt;br /&gt;208.115.111.246: Bytes = 8461415 (2.03%), Hits = 1238 (1.24%)&lt;br /&gt;67.218.116.133: Bytes = 18945415 (4.55%), Hits = 1126 (1.13%)&lt;/pre&gt;&lt;/small&gt;So, uhm, around 52% of the hits come from feather3.perl6.nl, and nearly 25% from Google's indexer. Lovely.&lt;br /&gt;&lt;br /&gt;Looking at the accesses from feather3, I quickly saw that they mostly had to do with svnweb.&lt;br /&gt;&lt;br /&gt;Juerd had already stopped Apache, but someone -- I don't know who -- started it again at 12:00, probably anxious that SVN and such didn't work.&lt;br /&gt;&lt;br /&gt;I then followed the running processes using the &lt;code&gt;top&lt;/code&gt; command, updating each second (&lt;code&gt;top d1&lt;/code&gt;), sorting by memory usage (typing &lt;code&gt;M&lt;/code&gt; while top was running), hoping to catch some quickly growing processes.&lt;br /&gt;&lt;br /&gt;Nopes.  None, zilch, nada.  Nothing that appeared horribly wrong.  Sure, the &lt;code&gt;apache2&lt;/code&gt; processes used some memory (30-60 MB resident set, 50-100 virtual), but nothing appeared to be out of the ordinary.  I changed the update frequency to each third second -- &lt;code&gt;top&lt;/code&gt; sometimes uses an inordinate amount of CPU, depending on magic -- and waited.  After a while, a couple of &lt;code&gt;apache2&lt;/code&gt; processes were using more CPU and memory than the others, around 60-90 MB resident.  And they were growing.  And according to &lt;code&gt;lsof&lt;/code&gt;, they were active in the svnweb directory (and used a metric shitload of libraries).  And after growing, they didn't release memory, they just kept on using it.  But it wasn't enough to use up memory, there was still a bunch of free RAM.&lt;br /&gt;&lt;br /&gt;So that was perhaps svnweb's fault, then?&lt;br /&gt;&lt;br /&gt;Maybe.&lt;br /&gt;&lt;br /&gt;But then my time ran out, and I had to drop the ball, leaving the &lt;code&gt;top&lt;/code&gt; process running.&lt;br /&gt;&lt;br /&gt;Five minutes later, the memory ran out again.  It's just as if someone was waiting for me to go idle in order to produce the problem that I was looking for.&lt;br /&gt;&lt;br /&gt;Sigh.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://jani.at.ifi.uio.no/blogpics/0c3af3a9a3ba054047f6fdeed41ef4ed.png"&gt;&lt;img src="http://jani.at.ifi.uio.no/blogpics/0c3af3a9a3ba054047f6fdeed41ef4ed.png" heigth="253" width="400" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;svnweb kindof remained the main suspect, until Juerd caught whatever was happening at the right time.&lt;br /&gt;&lt;br /&gt;And catching what happens at the right time is bloody important.&lt;br /&gt;&lt;br /&gt;Here's what he found, using Apache's server status:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://jani.at.ifi.uio.no/blogpics/5e6f1b41fb0beb7f878d01fe3b069776.png"&gt;&lt;img src="http://jani.at.ifi.uio.no/blogpics/5e6f1b41fb0beb7f878d01fe3b069776.png" width="400" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Well, that's not svnweb.  That's Trac.  And the IP addresses belong to Google.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://jani.at.ifi.uio.no/blogpics/837c8ca338c036903129875e8147f0c0.png" width="400"&gt;&lt;img src="http://jani.at.ifi.uio.no/blogpics/837c8ca338c036903129875e8147f0c0.png" width="400" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And that's spam, effectively creating a &lt;a href="http://en.wikipedia.org/wiki/DoS"&gt;DoS&lt;/a&gt; or &lt;a href="http://en.wikipedia.org/wiki/DDoS#Distributed_attack"&gt;DDoS&lt;/a&gt; attack on our services as a side effect when search engines try to index the Trac webpages.  It probably isn't intentional, but &lt;strong&gt;spammers just don't care&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;So, what can we do to protect feather from suffering from such attacks in the future?&lt;br /&gt;&lt;br /&gt;There's a lot that can be done.  It takes effort.  It takes time.  It takes someone.&lt;br /&gt;&lt;br /&gt;Here are a few suggestions on how to improve the robustness of the kind of services feather provides:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Add a &lt;a href="http://en.wikipedia.org/wiki/Captcha"&gt;captcha&lt;/a&gt; to the web form. The disadvantage is that this does not really save processing resources, but it probably should be done anyway.&lt;/li&gt;&lt;li&gt;Add an unnecessary and bogus input field to the web form, e.g. "Phone number". This input field should be hidden with CSS so that web browsers don't display it, and if someone submits anything with data with that field's name, then you can be nearly 100% certain it's spam from someone who's used a web scraper before automatically filling the form. Filter it out.&lt;/li&gt;&lt;li&gt;Change the webserver delegation architecture, so that each Apache process isn't loading tens of megabytes of libraries and keeping them in memory. Off-loading to shorter-living FastCGI daemons or similar solutions, or even sacrificing program startup speed by using CGI+suexec, etc., may be decent starting points.&lt;/li&gt;&lt;li&gt;Consider using a front-end proxy like &lt;a href="http://varnish.projects.linpro.no/"&gt;Varnish&lt;/a&gt; to gloss over underlying nastiness.&lt;/li&gt;&lt;li&gt;Start with a new VM and migrate services to that one, gradually.&lt;/li&gt;&lt;li&gt;Document configuration choices and what each web service does/is there for, so that the next sysadmin coming along can make educated guesses quicker. :)&lt;/li&gt;&lt;/ul&gt;These tasks can rather easily be split into manageable one-person projects.&lt;br /&gt;&lt;br /&gt;Does this sound interesting to you, or did I lose you at the third line of this blog entry?&lt;br /&gt;&lt;br /&gt;Pop in on &lt;code&gt;#perl6&lt;/code&gt; on the &lt;a href="http://freenode.net/irc_servers.shtml"&gt;freenode IRC network&lt;/a&gt; and say so.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-6433229299481615531?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/6433229299481615531/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=6433229299481615531' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/6433229299481615531'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/6433229299481615531'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2010/01/featherperl6nl-sysadminish-tale.html' title='feather.perl6.nl - a Sysadminish Tale'/><author><name>bakkushan</name><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-753668960778118906.post-8004013513556964090</id><published>2010-01-05T22:10:00.005+01:00</published><updated>2010-01-05T22:39:26.792+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='constant'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='Unicode'/><title type='text'>Typing More Or Less</title><content type='html'>Not too long ago, there was a bit of minor cleanup in the Perl 6 specification regarding the use of whatever (*); there were some inconsistencies in how it behaved, depending on context.&lt;br /&gt;&lt;br /&gt;The net result is that you now must use &lt;code&gt;@arr[*-1]&lt;/code&gt; to get the last element, you cannot get away with simply using &lt;code&gt;@arr[*]&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Some may feel that this extra typing is bothersome, especially if you have a Unicode-friendly keyboard setup.&lt;br /&gt;&lt;br /&gt;However, we can sneak our way past this problem by using a &lt;code&gt;constant&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;This also works with the current release of Rakudo, so it's not quite science fiction:&lt;pre&gt;constant &amp;Omega; = *-1;&lt;/pre&gt;Or, if you're feeling Cyrillic rather than Greek:&lt;pre&gt;constant &amp;#1120; = *-1;&lt;/pre&gt;Now we can substitute our nice constant for &lt;code&gt;*-1&lt;/code&gt; anywhere in the following code:&lt;pre&gt;my @letters = 'a'..'z';&lt;br /&gt;say '&amp;rarr;'~@letters[*-1];&lt;br /&gt;&amp;rarr;z&lt;/pre&gt;Like so:&lt;pre&gt;constant &amp;Omega; = *-1;&lt;br /&gt;my @letters = 'a'..'z';&lt;br /&gt;say '&amp;rarr;'~@letters[&amp;Omega;];&lt;br /&gt;&amp;rarr;z&lt;/pre&gt;And, of course, you can do this with other things that are so tedious to type when you're dealing with maths:&lt;pre&gt;constant &amp;pi; = pi;&lt;br /&gt;say '&amp;rarr;'~&amp;pi;&lt;br /&gt;&amp;rarr;3.14159265358979&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-8004013513556964090?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/8004013513556964090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=8004013513556964090' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/8004013513556964090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/8004013513556964090'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2010/01/typing-more-or-less.html' title='Typing More Or Less'/><author><name>bakkushan</name><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-753668960778118906.post-8641755256383205181</id><published>2009-12-31T00:31:00.004+01:00</published><updated>2009-12-31T01:06:19.862+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NPW 2009'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='community'/><category scheme='http://www.blogger.com/atom/ns#' term='PR'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><title type='text'>2009 In Perl</title><content type='html'>Repeat after me: I will not pretend to be an analyst or doomsayer, even though the end (of 2009) is nigh.&lt;br /&gt;&lt;br /&gt;In 2009, Perl grew up a bit more, both as a language and as a community.&lt;br /&gt;&lt;H2&gt;Language Development&lt;/H2&gt;Perl 5.10.1 came with a pony to those of us who fear the .0 releases.&lt;br /&gt;&lt;br /&gt;The Perl 5.11 development tree got started, and it looks like it is rolling on rails. At this rate, we will see 5.12.0 quicker than you can say antidisestablishmentarianism.&lt;br /&gt;&lt;br /&gt;... Perl 6 has made progress both on the specification side and in implementations -- yep, that is plural.  It is sometimes confusing when naming changes under your feet, but it is acceptable while the spec is still settling.&lt;br /&gt;&lt;H2&gt;Community&lt;/H2&gt;In 2009, I think I saw more openness regarding the internal conflicts in the Perl community as a whole; there were abundant admissions that we were not communicating nearly as well as we should, that there was at least a small amount of internal bickering over the present and future state of the onion -- onions, I must inject, tend to come in many shapes and flavours, and are not always the same inside -- really, which way we are going, are we having a conflict or not (yes we are -- no we are not -- huh, are we talking? -- pass the chips), and get off my lawn before I shoot or hug you.&lt;br /&gt;&lt;br /&gt;In brief, it looks to me like 2009 was the year when the community showed renews signs of self-awareness.&lt;br /&gt;&lt;br /&gt;But much more happened.  We got a closer focus on Perl visibility, from my POV mainly owing to Matt S. Trout's lightning talk challenge from NPW 2009, plus a whole range of people working on other PR aspects for ourselves.  And mst still keeps his hair colour.  Wow.&lt;br /&gt;&lt;H2&gt;Other Stuff&lt;/H2&gt;I made new friends, I learned a lot, I even got to help out a bit, and I hope that this will continue in 2010.&lt;br /&gt;&lt;br /&gt;I hope you will too.&lt;br /&gt;&lt;br /&gt;Happy new year!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-8641755256383205181?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/8641755256383205181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=8641755256383205181' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/8641755256383205181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/8641755256383205181'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/12/2009-in-perl.html' title='2009 In Perl'/><author><name>bakkushan</name><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-753668960778118906.post-8740606379457704622</id><published>2009-12-21T21:56:00.003+01:00</published><updated>2009-12-21T22:46:33.446+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='dice'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Dice Roller Deconstructed</title><content type='html'>As promised, here are the elements of last week's dice rolling code:&lt;br /&gt;&lt;br /&gt;&lt;small&gt;&lt;pre&gt;use v6;&lt;/pre&gt;&lt;/small&gt;This is a nice way to say that we are in Perl 6 land.&lt;br /&gt;&lt;br /&gt;&lt;small&gt;&lt;pre&gt;subset D10 of Int where 1..10;&lt;/pre&gt;&lt;/small&gt;A "D10" is a 10-sided die, and it can only have integer values in the range 1..10. Subtyping Int is an acceptable way of taking care of that.&lt;br /&gt;&lt;br /&gt;&lt;small&gt;&lt;pre&gt;sub is_success (D10 $roll, D10 $target) {&lt;/pre&gt;&lt;/small&gt;Here, I am already using the subtype D10 of Int. This subroutine compares the rolled die $roll with the target number $target, and is called from the subroutine &lt;code&gt;roll()&lt;/code&gt; for each die in the dice pool. I chose to create an explicit subroutine because it seems a bit clearer what happens in the special case of a rolled 10, which means that you get to re-roll that die for a potential new success.&lt;br /&gt;&lt;br /&gt;&lt;small&gt;&lt;pre&gt;    my $n = 0;&lt;br /&gt;    if ($roll == 10) {&lt;br /&gt;        say "10 again";&lt;br /&gt;        $n += roll 1,$target;&lt;br /&gt;    }&lt;/pre&gt;&lt;/small&gt;If we roll a 10, then the &lt;code&gt;roll()&lt;/code&gt; subroutine is called with a dice pool of 1 and the same target number as we got originally for determining success.&lt;br /&gt;&lt;br /&gt;&lt;small&gt;&lt;pre&gt;    $roll &amp;gt;= $target ?? $n + 1 !! $n;&lt;br /&gt;}&lt;/pre&gt;&lt;/small&gt;We always return the number of successes from the roll for the "10 again" rule (if it happened), and in case this roll was a success, we return an additional success.&lt;br /&gt;&lt;br /&gt;&lt;small&gt;&lt;pre&gt;sub roll (Int $poolsize where { $_ &amp;gt; 0 }, D10 $target? = 8) {&lt;/pre&gt;&lt;/small&gt;The dice pool size can of course not be negative, but it also cannot be zero; you always get to roll a die, so I have added a type constraint for that. The target number is optional, defaults to 8, and has to be possible with a D10.&lt;br /&gt;&lt;br /&gt;&lt;small&gt;&lt;pre&gt;    my D10 @rolls = (1..10).pick($poolsize, :replace);&lt;/pre&gt;&lt;/small&gt;From left to right:&lt;ul&gt;&lt;li&gt;&lt;code&gt;@rolls&lt;/code&gt; is an array that will contain the results of the normal die rolls&lt;/li&gt;&lt;li&gt;&lt;code&gt;(1..10).pick($poolsize&lt;/code&gt; is a way of picking &lt;code&gt;$poolsize&lt;/code&gt; dice having possible values in the range 1..10 and "rolling" (randomizing) each of them.&lt;/li&gt;&lt;li&gt;&lt;code&gt;pick($poolsize, :replace)&lt;/code&gt; means that we not only pick a result, but we also make it possible to achieve the same result again. Specifically, it is important for us that each die can have ANY value, not just values that have not been picked before. &lt;small&gt;The semantics of &lt;code&gt;pick()&lt;/code&gt; are explained in &lt;a href="http://perl6advent.wordpress.com/2009/12/15/day-15-pick-your-game/"&gt;.pick your game&lt;/a&gt; (the 15th gift in the Perl 6 Advent Calendar).&lt;/small&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;small&gt;&lt;pre&gt;    say "Roll: " ~ @rolls.sort.join(",");&lt;/pre&gt;&lt;/small&gt;&lt;code&gt;@rolls.sort.join(",")&lt;/code&gt; sorts the elements of the &lt;code&gt;@rolls&lt;/code&gt; array and stringifies them joined with a comma, e.g. "1,2,3,3,4" for &lt;code&gt;@rolls = 4,1,3,2,3&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;small&gt;&lt;pre&gt;    [+] @rolls.map: { is_success $_,$target };&lt;br /&gt;}&lt;/pre&gt;&lt;/small&gt;This piece of code maps &lt;code&gt;is_success $_,$target&lt;/code&gt; on every value in the &lt;code&gt;@rolls&lt;/code&gt; array and creates a sum of those results. In other words, it sums up the number of successfull die rolls.&lt;br /&gt;&lt;br /&gt;&lt;small&gt;&lt;pre&gt;given @*ARGS.elems {&lt;/pre&gt;&lt;/small&gt;The &lt;code&gt;@*ARGS&lt;/code&gt; array contains the command line arguments to the program, and &lt;code&gt;.elems&lt;/code&gt; therefore is the number of arguments used.&lt;br /&gt;&lt;small&gt;&lt;pre&gt;    when 2   {&lt;br /&gt;               say "Target number: " ~ @*ARGS[1];&lt;br /&gt;               continue;&lt;br /&gt;             }&lt;/pre&gt;&lt;/small&gt;This block only runs in case we have two arguments, but it explicitly says that we may not be done yet: the &lt;code&gt;continue&lt;/code&gt; statement counters the default implisit &lt;code&gt;break&lt;/code&gt; to ensure that we can match the input value against other tests.&lt;br /&gt;&lt;small&gt;&lt;pre&gt;    when 1|2 {&lt;br /&gt;               my $n = roll |@*ARGS&amp;gt;&amp;gt;.Int;&lt;br /&gt;               say "Successes rolled: " ~ $n;&lt;br /&gt;               $n &amp;gt;= 5 and say "Exceptional success!";&lt;br /&gt;             }&lt;/pre&gt;&lt;/small&gt;We start off with a &lt;em&gt;junction&lt;/em&gt; to say that either 1 or 2 is fine by us, we want both to match. Then we call &lt;code&gt;roll()&lt;/code&gt; with the same arguments we got in, but each converted to Int. &lt;em&gt;White magic.&lt;/em&gt; We store the value, and exclaim that the result is an exceptional success if it is.&lt;br /&gt;&lt;small&gt;&lt;pre&gt;    when *   {&lt;br /&gt;               $*ERR.say("roll.p6 poolsize [target]");&lt;br /&gt;               exit(64);&lt;br /&gt;             }&lt;br /&gt;}&lt;/pre&gt;&lt;/small&gt;This is the equivalent of C's &lt;code&gt;default&lt;/code&gt;, the catch-all that handles remaining uncaught cases. We print a helpful usage string to STDERR (&lt;code&gt;$*ERR&lt;/code&gt; in Perl 6) and exit with the correct Unix exit code, praying that nobody uses a different kind of system.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-8740606379457704622?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/8740606379457704622/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=8740606379457704622' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/8740606379457704622'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/8740606379457704622'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/12/dice-roller-deconstructed.html' title='Dice Roller Deconstructed'/><author><name>bakkushan</name><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-753668960778118906.post-7861456376297704474</id><published>2009-12-16T15:50:00.002+01:00</published><updated>2009-12-16T22:40:45.315+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='program'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='dice'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='role-playing'/><category scheme='http://www.blogger.com/atom/ns#' term='Rakudo'/><title type='text'>Dice Rolls for Role-Players</title><content type='html'>I realize that the title of this post is a bit of an oxymoron, because a &lt;a href="http://www.seiyuu.com/okamoto/gaming/realmen.htm"&gt;Real Role-Player&lt;/a&gt; of course doesn't roll dice often. ;)&lt;br /&gt;&lt;br /&gt;But in the cases where the Real Role-Player &lt;em&gt;does&lt;/em&gt; roll dice, wouldn't it be nice to have a computer program to forget at home rather than some even more easily mislaid dice?&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://perl6advent.wordpress.com/"&gt;Perl 6 Advent Calendar&lt;/a&gt; provided some inspiration for this post.&lt;br /&gt;&lt;br /&gt;A problem with many minor programming examples you see on the net, is that they do not take into account the needs of a role-player.  Role-players play many different systems, with different criteria for &lt;em&gt;success&lt;/em&gt; in dice rolls.  D6 (the regular six-sided cubic dice used for playing Monopoly, Yahtzee, etc.) are not used much in the majority of systems.&lt;br /&gt;&lt;br /&gt;Therefore, I'll look at the &lt;a href="http://en.wikipedia.org/wiki/Storyteller_System"&gt;Storyteller System&lt;/a&gt;, which is used in the &lt;a href="http://en.wikipedia.org/wiki/World_of_Darkness"&gt;World of Darkness&lt;/a&gt; series of games.&lt;br /&gt;&lt;br /&gt;The general principle is that you have a &lt;em&gt;pool&lt;/em&gt; of dice to roll, and you count your &lt;em&gt;successes&lt;/em&gt;, which in this system is the number of dice that have a value greater than or equal to a given &lt;em&gt;target number&lt;/em&gt; for the roll.  The standard target number is 8 in most implementations.  Five successes in the same roll is an &lt;em&gt;exceptional success&lt;/em&gt;.  Obviously, it's nice to have many dice to roll!&lt;br /&gt;&lt;br /&gt;Here's a real Perl 6 program &lt;em&gt;that works with Rakudo today&lt;/em&gt;: it accepts two command line parameters, the first being the size of the dice pool, the optional second parameter defines the target number for success:&lt;hr/&gt;&lt;small&gt;&lt;pre&gt;use v6;&lt;br /&gt;&lt;br /&gt;subset D10 of Int where 1..10;&lt;br /&gt;&lt;br /&gt;sub is_success (D10 $roll, D10 $target) {&lt;br /&gt;    my $n = 0;&lt;br /&gt;    if ($roll == 10) {&lt;br /&gt;        say "10 again";&lt;br /&gt;        $n += roll 1,$target;&lt;br /&gt;    }&lt;br /&gt;    $roll &amp;gt;= $target ?? $n + 1 !! $n;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;sub roll (Int $poolsize where { $_ &amp;gt; 0 }, D10 $target? = 8) {&lt;br /&gt;    my D10 @rolls = (1..10).pick($poolsize, :replace);&lt;br /&gt;    say "Roll: " ~ @rolls.sort.join(",");&lt;br /&gt;    [+] @rolls.map: { is_success $_,$target };&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;given @*ARGS.elems {&lt;br /&gt;    when 2   {&lt;br /&gt;               say "Target number: " ~ @*ARGS[1];&lt;br /&gt;               continue;&lt;br /&gt;             }&lt;br /&gt;    when 1|2 {&lt;br /&gt;               my $n = roll |@*ARGS&amp;gt;&amp;gt;.Int;&lt;br /&gt;               say "Successes rolled: " ~ $n;&lt;br /&gt;               $n &amp;gt;= 5 and say "Exceptional success!";&lt;br /&gt;             }&lt;br /&gt;    when *   {&lt;br /&gt;               $*ERR.say("roll.p6 poolsize [target]");&lt;br /&gt;               exit(64);&lt;br /&gt;             }&lt;br /&gt;}&lt;/pre&gt;&lt;/small&gt;&lt;hr/&gt;Thanks to &lt;a href="http://perlgeek.de/blog-en/"&gt;moritz&lt;/a&gt;++ for ironing out two annoying mistakes!&lt;br /&gt;&lt;br /&gt;Here are a few usage examples:&lt;hr/&gt;&lt;pre&gt;&lt;b&gt;$ perl6 roll.p6&lt;/b&gt;&lt;br /&gt;roll.pl poolsize [target]&lt;br /&gt;&lt;br /&gt;&lt;b&gt;$ perl6 roll.p6 5&lt;/b&gt;&lt;br /&gt;Roll: 1,2,7,8,9&lt;br /&gt;Successes rolled: 2&lt;br /&gt;&lt;br /&gt;&lt;b&gt;$ perl6 roll.p6 5 2&lt;/b&gt;&lt;br /&gt;Target number: 2&lt;br /&gt;Roll: 1,2,2,4,9&lt;br /&gt;Successes rolled: 4&lt;br /&gt;&lt;br /&gt;&lt;b&gt;$ perl6 roll.p6 5 4&lt;/b&gt;&lt;br /&gt;Target number: 4&lt;br /&gt;Roll: 6,8,9,10,10&lt;br /&gt;10 again&lt;br /&gt;Roll: 8&lt;br /&gt;10 again&lt;br /&gt;Roll: 2&lt;br /&gt;Successes rolled: 6 - Exceptional success!&lt;/pre&gt;&lt;hr/&gt;There are no comments in this piece of code, I want people to try to understand it as-is, based on the &lt;a href="http://perl6advent.wordpress.com/"&gt;Perl 6 Advent Calendar&lt;/a&gt;. If you have any questions, comments, corrections, etc., don't hesitate, just write!&lt;br /&gt;&lt;br /&gt;In my next blog entry, I'll pick the program apart and comment on what I've done and why, and who knows, maybe someone has come up with an elegant solution to the same problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-7861456376297704474?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/7861456376297704474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=7861456376297704474' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/7861456376297704474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/7861456376297704474'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/12/dice-rolls-for-role-players.html' title='Dice Rolls for Role-Players'/><author><name>bakkushan</name><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-753668960778118906.post-607178019070602280</id><published>2009-12-09T18:43:00.003+01:00</published><updated>2009-12-10T02:08:25.328+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='modulo'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='ML'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='elegance'/><category scheme='http://www.blogger.com/atom/ns#' term='Euclid'/><category scheme='http://www.blogger.com/atom/ns#' term='GCD'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><title type='text'>GCD - A Small Language Enthuser</title><content type='html'>&lt;pre&gt;fun gcd (x:int,y:int) : int =&lt;br /&gt;    case x of 0 =&amp;gt; y&lt;br /&gt;  | _ =&amp;gt if x &amp;lt; 0 then gcd(y,0-x) else&lt;br /&gt;         if y &amp;lt; 0 then gcd(0-y,x) else&lt;br /&gt;         if y &amp;gt x then gcd(y-x,x) else gcd(x-y,y);&lt;/pre&gt;&lt;blockquote&gt;&lt;strong&gt;&lt;em&gt;"But that's not Perl!"&lt;/em&gt;&lt;/strong&gt;&lt;/blockquote&gt;Yeah, yeah, I hear you.&lt;br /&gt;&lt;br /&gt;I'll rectify that minor detail in a bit.&lt;br /&gt;&lt;br /&gt;But first, an anecdote.&lt;br /&gt;&lt;br /&gt;Back in the late &lt;span title="tee-hee"&gt;nineteennineties&lt;/span&gt;, I was studying computer science, and one of the classes was about program specification and verification.&lt;br /&gt;&lt;br /&gt;Several of the students already had a background with several programming languages, some were &lt;em&gt;functional&lt;/em&gt;, some were &lt;em&gt;imperative&lt;/em&gt;, and other languages were a bit confused about what they really were.&lt;br /&gt;&lt;br /&gt;When studying program specification and verification, you either become rather obsessed with program correctness -- and hopefully elegance -- or you fail  spectactularly.&lt;br /&gt;&lt;br /&gt;There are several ways to muster enthusiasm when dealing with such studies; they can be rather, ehrm, theoretical.&lt;br /&gt;&lt;br /&gt;I therefore flitted about, flirting with various programming languages, comparing them with the eagerness that young idealists do.&lt;br /&gt;&lt;br /&gt;For some reason, I found Euclid's &lt;a href="http://en.wikipedia.org/wiki/Euclidean_algorithm" title="Greatest Common Divisor"&gt;GCD algorithm&lt;/a&gt; to be particularly fascinating, for reasons unknown to men to this day.&lt;br /&gt;&lt;br /&gt;The Perl version I saw was rather awful, and &lt;em&gt;technically incorrect&lt;/em&gt;:&lt;pre&gt;sub gcd {&lt;br /&gt;    if (!$_[0]) {&lt;br /&gt;        return $_[1];&lt;br /&gt;    }&lt;br /&gt;    if ($_[1] &amp;gt; $_[0]) {&lt;br /&gt;        return gcd ($_[1]-$_[0],$_[0]);&lt;br /&gt;    }&lt;br /&gt;    return gcd ($_[0]-$_[1],$_[1]);&lt;br /&gt;}&lt;/pre&gt;Yikes. I mean, eep. And Perl &lt;em&gt;does&lt;/em&gt; have a modulo operator.&lt;pre&gt;sub gcd {&lt;br /&gt;    my ($x, $y) = @_;&lt;br /&gt;    $y ? gcd ($y, $x % $y) : abs $x;&lt;br /&gt;}&lt;/pre&gt;I won't claim that the above code is the epitome of elegance, but it solves the problem in a general and easily read way &lt;small&gt;(I admit a prejudice against $_[N])&lt;/small&gt;, while retaining correctness.&lt;br /&gt;&lt;br /&gt;&lt;small&gt;This is, BTW, one place where some golfers miss the boat; the GCD cannot be a negative integer. That's why the ML code at the top is so verbose.&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;Small challenges like these kept me going, and it can be an inspiring way to learn details in a new language. So, what would it look like in Perl 6?&lt;pre&gt;sub gcd (Int $x, Int $y) {&lt;br /&gt;    $y ?? gcd($y, $x % $y) !! $x.abs;&lt;br /&gt;}&lt;/pre&gt;What's your favourite algorithm for playtesting languages?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-607178019070602280?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/607178019070602280/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=607178019070602280' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/607178019070602280'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/607178019070602280'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/12/gcd-small-language-enthuser.html' title='GCD - A Small Language Enthuser'/><author><name>bakkushan</name><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-753668960778118906.post-1816814811069435852</id><published>2009-12-01T18:22:00.004+01:00</published><updated>2009-12-01T18:44:03.641+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NPW 2009'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Oslo'/><category scheme='http://www.blogger.com/atom/ns#' term='NPW 2006'/><category scheme='http://www.blogger.com/atom/ns#' term='Oslo.pm'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><title type='text'>Oslo.pm Past and Future</title><content type='html'>In case the title wasn't a give-away: this is a non-technical blog entry.&lt;br /&gt;&lt;br /&gt;I became an &lt;a href="http://oslo.pm.org/" title="Oslo.pm website, Norwegian text"&gt;Oslo.pm&lt;/a&gt; member by signing up for the mailing list shortly after the &lt;a href="http://www.perlworkshop.no/"&gt;Nordic Perl Workshop&lt;/a&gt; 2009. That's cheap (well, free!), easy, and therefore newbie-friendly.&lt;br /&gt;&lt;br /&gt;Last week, I dropped in at the general assembly and exercised my speaking and voting rights, and got an inside scoop on how this Perl organization works. The board members were, after all, the guys who did a terrific job arranging not only this spring's workshop, but also mostly the same people who held the workshop of 2006, which also went quite well.&lt;br /&gt;&lt;br /&gt;From my point of view, Oslo.pm has come from being an anonymous group to a rather solid little volunteer organization. Before 2006, I'd have said "huh?" if someone asked me who might have anything to do with Perl in Norway, afterwards, I knew there was something called Oslo.pm, and so did a few people in Europe and the USA. After NPW 2009, I think it's safe to say that the organization is now known as a stable and capable group of Perl mongers. That's a decent achievement, especially in this age, when it seems like almost nobody (in Norway) is willing to do anything free of charge.&lt;br /&gt;&lt;br /&gt;So what did they think about themselves, and what's going to happen in the near future?&lt;br /&gt;&lt;br /&gt;True to the Norwegian spirit, they were modest and self-disparaging, but they were very happy that the attendees were apparently happy, even months later.&lt;br /&gt;&lt;br /&gt;Salve J. Nilsen, the Great Leader of 2009, bowed and said farewell to the post of chairman, and now Marcus Ramberg is at the helm.&lt;br /&gt;&lt;br /&gt;The new Oslo.pm board will attempt to increase local activity, and there will probably be some kind of technical talk on the first Wednesday of almost every month in 2010. They aim to increase cooperation with local Perl-using companies, as well as aiming for some cross-language and language agnostic sessions.&lt;br /&gt;&lt;br /&gt;First out is tomorrow's Perl 5.10 session at Redpill Linpro, which I'm sure will be technically rewarding for those who show up. I plan to!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-1816814811069435852?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/1816814811069435852/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=1816814811069435852' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/1816814811069435852'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/1816814811069435852'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/12/oslopm-past-and-future.html' title='Oslo.pm Past and Future'/><author><name>bakkushan</name><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-753668960778118906.post-2572349087265513179</id><published>2009-11-25T22:28:00.003+01:00</published><updated>2009-11-25T22:49:02.202+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='beautiful'/><category scheme='http://www.blogger.com/atom/ns#' term='moral'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='expert'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><title type='text'>The morality of helping</title><content type='html'>Yesterday, a friend asked me, &lt;em&gt;"are you a Perl expert?"&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;I answered in the only way possible: &lt;em&gt;"eeeeh..."&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;It turned out that my friend did not ask for help for himself, but for someone else, who had posted a programming class question on a non-programming bulletin board.&lt;br /&gt;&lt;br /&gt;The poor fellow was struggling with a question of parsing a two-column input to generate a certain output format, essentially also two-column, except with a slightly different layout.&lt;br /&gt;&lt;br /&gt;On Usenet, there was - and maybe still is - a long-standing tradition of &lt;em&gt;not&lt;/em&gt; solving people's homework for them. The reasoning behind this is that we do not learn quite as well when people solve our problems for us, as when we struggle with them ourselves.&lt;br /&gt;&lt;br /&gt;In some cases, school questions would be met with derision, in other cases with genuinely unhelpful and false answers, and sometimes with helpful clues about how to solve the problem; where to look, tips for using stepping debuggers, which book chapter or manual page would clarify the problem, etc.&lt;br /&gt;&lt;br /&gt;Okay, that is fair enough.&lt;br /&gt;&lt;br /&gt;The guy had gotten only one answer, from another guy who regretted that he had not touched Perl in ages, and therefore could not help.  &lt;em&gt;And I thought that Perl was like learning a particularly catchy, but annoying song: you might think that you have forgotten, but then someone hums or whistles the tune, and &lt;strong&gt;WHAM&lt;/strong&gt; - there it is, stuck in your head again.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;So I had a look.  Maybe I could provide a hint or two, you never know.  I know my way around some of the less scary parts of Perl 5 City, anyway.&lt;br /&gt;&lt;br /&gt;This guy had essentially nailed the problem semantically, but he was evidently struggling with his code, it just did not work.&lt;br /&gt;&lt;br /&gt;I immediately saw a few major concerns:&lt;ol&gt;&lt;li&gt;Some parts were copy-pasted from bad textbook Perl.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Some parts must have come from a poor programming education.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The code was overly complex and verbose.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;There was no error checking or debug print-outs.&lt;/em&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;And it would take me more time to helpfully point out these things than write something that might be a solution myself.&lt;/li&gt;&lt;/ol&gt;The moral dilemma then was:&lt;br /&gt;&lt;br /&gt;Should I help the guy out by tearing his code apart and pointing out all the flaws that made it thoroughly lousy code, thereby provoking a true emo-American melodrama?&lt;br /&gt;&lt;br /&gt;Or should I just write an alternate solution, with sound error-checking, simplicity, and debug print-outs?&lt;br /&gt;&lt;br /&gt;In this case, I thought the latter was the way to go.  I put the code up anonymously somewhere, gave the link to my friend, and perhaps the fellow with the problem now has a better understanding of how simple and beautiful Perl can be.&lt;br /&gt;&lt;br /&gt;Yeah, right.  :D&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-2572349087265513179?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/2572349087265513179/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=2572349087265513179' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/2572349087265513179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/2572349087265513179'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/11/morality-of-helping.html' title='The morality of helping'/><author><name>bakkushan</name><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-753668960778118906.post-2986740577170024623</id><published>2009-11-15T23:56:00.006+01:00</published><updated>2009-11-16T00:57:31.739+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='projects'/><category scheme='http://www.blogger.com/atom/ns#' term='perfectionism'/><category scheme='http://www.blogger.com/atom/ns#' term='alcohol'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='time'/><category scheme='http://www.blogger.com/atom/ns#' term='hobby'/><category scheme='http://www.blogger.com/atom/ns#' term='motivation'/><category scheme='http://www.blogger.com/atom/ns#' term='Rakudo'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><title type='text'>What stops me from using Perl 6, today?</title><content type='html'>Since I got hooked on the Perl community, and got a taste of Perl 6, I've been wondering about:&lt;ol&gt;&lt;li&gt;what, exactly, is it that I could use Perl 6 for, right now?&lt;/li&gt;&lt;li&gt;why am I not actively using Perl 6 now?&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Those are easy questions, but answering is hard, so this may be a long post.&lt;br /&gt;&lt;br /&gt;Sure, the points listed below are not exactly Perl 6 specific; I could probably have picked some other programming language, but I somehow feel more comfortable in the way that Perl 6 &lt;em&gt;still is Perl&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;What I could use Perl 6 for right now&lt;/h2&gt;&lt;br /&gt;I think it's fair to say that using Perl 6 today mostly means using Rakudo, and that I wouldn't use it in what we popularly call a "production setting". But many of us programmers, sysadmins, geeks and nerds have perfectly suitable &lt;em&gt;hobby&lt;/em&gt; projects, where we won't have clients wringing our necks if there is three minutes of downtime in a month, or if we don't deliver the Speedy Gonzalez of services; we have projects that are neither computing performance constrained or stability constrained.&lt;br /&gt;&lt;br /&gt;So that's where I could have started using Perl 6 half a year ago, and of course still can.&lt;br /&gt;&lt;br /&gt;I know I can use Perl 6 for e.g. a fairly complex web site using Web.pm and Squerl for a SQLite backend. It will probably work just fine, for a lot of projects.&lt;br /&gt;&lt;br /&gt;I know I can use it for lots of one-liner scripts.&lt;br /&gt;&lt;br /&gt;I know that in some regards, Perl 6 will outperform classic Perl 5 in terms of &lt;em&gt;programmer time&lt;/em&gt; spent. An example is the &lt;code&gt;given-when&lt;/code&gt; control structure, which (to me) is semantically superior to &lt;code&gt;if-elsif-elsif-elsif&lt;/code&gt;. Programmer time is important to me, I hate coding too much for menial tasks. And I'm sorry to say that Perl 5.10 doesn't &lt;em&gt;do it yet for me&lt;/em&gt;, as I cannot rely on its presence, even for hobby projects.&lt;br /&gt;&lt;br /&gt;And I know I can use Perl 6 to refresh some of the knowledge about programming language specifics (terminology, technique, methodology, etc.) that I've allowed to rust since I left university in 2001.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Concrete projects, in no particular order&lt;/h3&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;web page for registration of pool billiards tournament results; it's not performance critical, and the users could check and verify the dataset themselves after input&lt;/li&gt;&lt;br /&gt;&lt;li&gt;conversion of historical results data in CSV format to a database; one-time job, needs manual verification no matter what programming language I use to do it&lt;/li&gt;&lt;br /&gt;&lt;li&gt;contributing to the Temporal.pm specification and implementation in Perl 6&lt;/li&gt;&lt;br /&gt;&lt;li&gt;personal web gallery generation; I positively loathe most of the online galleries, because they sooner rather than later are discovered to have HUGE, GAPING security vulnerabilities&lt;/li&gt;&lt;br /&gt;&lt;li&gt;blogging tool; I'm not very comfortable with blog software running on servers, either, and whatever blogging I do, it's not actual &lt;em&gt;work&lt;/em&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;That's quite a lot, isn't it? It ought to have been enough to get me going in a jiffy!&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Why I'm not actively using Perl 6 now&lt;/h2&gt;&lt;br /&gt;This may be a surprise to some: it's not because of a lack of matureness in the tools, a lack of confidence in the language or tools, stability issues, etc. As I tangentially mentioned above, I believe there is no technical hindrance for me to start coding on a hobby project.&lt;br /&gt;&lt;br /&gt;I have plenty of hobby projects to choose from.  They are also quite manageable in terms of eventual lines of code.&lt;br /&gt;&lt;br /&gt;However, there is something holding me back, and that's a certain degree of perfectionism mixed with procrastination fever.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.shadowcat.co.uk/blog/matt-s-trout/" title="Matt S. Trout"&gt;mst&lt;/a&gt; mentioned during the NPW hackathon this spring that perfectionism was a barrier against getting started.  If you're too obsessed with getting things right at first, at wanting to avoid failure, procrastinating is too easy.  Getting slightly intoxicated &lt;small&gt;(yup, drinking alcohol, which of course is only a recourse for adults)&lt;/small&gt; is a way of reducing your own perfection anxiety. This is almost exactly what Randall Munroe's xkcd calls the &lt;em&gt;Ballmer Peak&lt;/em&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://xkcd.com/323/"&gt;&lt;img src="http://imgs.xkcd.com/comics/ballmer_peak.png" title="Ballmer Peak" height="296" width="326" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;But I don't sleep too well after drinking alcohol, and I also tend to do hobby projects in my "running breaks" during work hours, in which case alcohol intake may be a &lt;strong&gt;very bad idea&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;In addition, my time at work is a series of interruptions, which really isn't conductive to sitting down and learning something new and complex.&lt;br /&gt;&lt;br /&gt;When I get home from work, I'm usually so fed up with computers that I don't want to have anything to do with them.&lt;br /&gt;&lt;br /&gt;So my spare time, whatever is left of it, usually isn't spent on programming.  Note that I don't even do these projects in a programming language I already know well; they are on hold regardless of that.&lt;br /&gt;&lt;br /&gt;All in all, there's nothing much wrong with Perl 6.&lt;br /&gt;&lt;br /&gt;Blaming the immaturity of Rakudo would just be a silly excuse.  There's something wrong with my capacity for finding the time to get down and dirty with it, that's what; I'm apparently not currently capable of saying honestly:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;em&gt;This is my Perl 6 hour.  This hour, I'm going to do Perl 6 stuff, and this time is sacred.&lt;/em&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-2986740577170024623?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/2986740577170024623/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=2986740577170024623' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/2986740577170024623'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/2986740577170024623'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/11/what-stops-me-from-using-perl-6-today.html' title='What stops me from using Perl 6, today?'/><author><name>bakkushan</name><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-753668960778118906.post-2021623310401190365</id><published>2009-11-09T00:49:00.005+01:00</published><updated>2009-11-09T11:07:37.940+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IRC'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='bots'/><title type='text'>What the #perl6 IRC bots do</title><content type='html'>Do you feel like a n00b on #perl6, like I do, and wonder what the different bots do?&lt;br /&gt;&lt;br /&gt;I keep forgetting what they are, so here's a list for you and me both:&lt;br /&gt;&lt;br /&gt;&lt;dl&gt;&lt;br /&gt;&lt;dt&gt;dalek&lt;/dt&gt;&lt;dd&gt;Announces commits (mainly to rakudo, nqp-rx and the Perl 6 book)&lt;/dd&gt;&lt;br /&gt;&lt;dt&gt;hugme&lt;/dt&gt;&lt;dd&gt;Used for hugging another user without "direct" contact: &lt;pre&gt;hugme: hug masak&lt;/pre&gt;&lt;/dd&gt;&lt;br /&gt;&lt;dt&gt;ilbot2&lt;/dt&gt;&lt;dd&gt;Near-realtime IRC logs with automatic link generation to &lt;a href="http://irclog.perlgeek.de"&gt;irclog.perlgeek.de&lt;/a&gt;. The original ilbot sucked, according to moritz.&lt;/dd&gt;&lt;br /&gt;&lt;dt&gt;ilogger2&lt;/dt&gt;&lt;dd&gt;Another logging bot&lt;/dd&gt;&lt;br /&gt;&lt;dt&gt;lambdabot&lt;/dt&gt;&lt;dd&gt;Keeps track of karma ("moritz++" adds one to moritz's karma score, "frettled--" subtracts one from mine)&lt;/dd&gt;&lt;br /&gt;&lt;dt&gt;lisppaste3&lt;/dt&gt;&lt;dd&gt;Announces entries pasted to &lt;a href="http://paste.lisp.org/new/perl6"&gt;http://paste.lisp.org/new/perl6&lt;/a&gt; (which is where we paste code and other stuff, so that we avoid spamming the channel too much, and also don't have to worry about creating our own temporary web pages)&lt;/dd&gt;&lt;br /&gt;&lt;dt&gt;masak&lt;/dt&gt;&lt;dd&gt;Submits rakudo bugs. &lt;small&gt;Aw, okay, then, he's not a bot, just a really nice guy!&lt;/small&gt;&lt;/dd&gt;&lt;br /&gt;&lt;dt&gt;mubot&lt;/dt&gt;&lt;dd&gt;Also tracks karma, attempting to be slightly less annoying than lambdabot. mubot is clever enough to recognize that your nick may vary slightly from time to time and channel to channel. mubot is written in Perl 6!&lt;/dd&gt;&lt;br /&gt;&lt;dt&gt;p6eval&lt;/dt&gt;&lt;dd&gt;Perl 6 code evaluation bot. We use this for live testing of code that may be of interest to others; it chats back to the channel. &lt;code&gt;perl6: my $a;&lt;/code&gt; will result in a test against several Perl 6 interpreters (elf, mildew, mildew-js, pugs, rakudo, sprixel), &lt;code&gt;nqp: say('foo')&lt;/code&gt; tests nqp-rx, &lt;code&gt;std: my $a&lt;/code&gt; will parse the expression with &lt;strong&gt;STD.pm&lt;/strong&gt;.&lt;/dd&gt;&lt;br /&gt;&lt;dt&gt;phenny&lt;/dt&gt;&lt;dd&gt;Our secretary. Sample usage: &lt;pre&gt;phenny, tell frettled I'll get back to you on that&lt;/pre&gt;phenny will then let me know when I become active on the channel again.&lt;/dd&gt;&lt;br /&gt;&lt;dt&gt;pointme&lt;/dt&gt;&lt;dd&gt;Provides links to projects tracked by &lt;a href="http://github.com/masak/proto"&gt;proto&lt;/a&gt;. Example usage: &lt;small&gt;&lt;pre&gt;&amp;lt; carlin&amp;gt; pointme: rssbot&lt;br /&gt;&amp;lt; pointme&amp;gt; carlins's rssbot is at &lt;a href="http://github.com/carlins/rssbot"&gt;http://github.com/carlins/rssbot&lt;/a&gt;&lt;/pre&gt;&lt;/small&gt;pointme is written in Perl 6!&lt;/dd&gt;&lt;br /&gt;&lt;dt&gt;pugs_svn&lt;/dt&gt;&lt;dd&gt;Tracks commits to the pugs repository, most of which are changes to the test suite and spec.&lt;/dd&gt;&lt;br /&gt;&lt;dt&gt;zaslon&lt;/dt&gt;&lt;dd&gt;Tracks blog posts from a certain group of bloggers. Zaslon is written in Perl 6!&lt;/dd&gt;&lt;br /&gt;&lt;/dl&gt;&lt;br /&gt;&lt;br /&gt;Thanks to carlin, Juerd, jnthn and moritz for late night clarifications!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-2021623310401190365?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/2021623310401190365/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=2021623310401190365' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/2021623310401190365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/2021623310401190365'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/11/what-perl6-irc-bots-do.html' title='What the #perl6 IRC bots do'/><author><name>bakkushan</name><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-753668960778118906.post-6659670284520341333</id><published>2009-11-03T19:33:00.000+01:00</published><updated>2009-11-03T19:50:56.056+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vulnerabilities'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='permissions'/><category scheme='http://www.blogger.com/atom/ns#' term='Fcntl'/><category scheme='http://www.blogger.com/atom/ns#' term='Unix'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><title type='text'>Checking and fixing Unix file modes</title><content type='html'>Among other tasks in my sysadmin role at a web hosting provider, I work with fallout from poorly designed PHP code - which is ubiquitous - and I use Perl 5 to perform a bunch of semi-automated tasks.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;small&gt;If you just want to see how I utilize the &lt;code&gt;Fcntl&lt;/code&gt; module, look &lt;a href="#code20091103"&gt;further down&lt;/a&gt;.&lt;/small&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;One of the many things that tend to go wrong is the assumption that PHP always runs as mod_php (blatantly disregarding php-cgi, suphp, and other per-user PHP frameworks), and therefore directories (folders) and files used by PHP "must be" prepared with &lt;code&gt;chmod 777&lt;/code&gt; &lt;code&gt;chmod 666&lt;/code&gt;. The latter number is a &lt;strong&gt;BIG FRIGGIN' HINT&lt;/strong&gt;, it's the &lt;strong&gt;number of the beast&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Whenever documentation tells you to use the &lt;strong&gt;number of the beast&lt;/strong&gt; for your &lt;code&gt;chmod&lt;/code&gt; command, that documentation is also telling you to lube up and bend over.&lt;br /&gt;&lt;br /&gt;Unfortunately, customers and users don't necessarily see this gotcha; no matter how good the hosting provider's documentation is, they'll naturally trust the software monger's instructions.&lt;br /&gt;&lt;br /&gt;That means that the hosting provider ought to have tools available for identifying and fixing such writable directories and files. There are many wrong ways of doing it, one is:&lt;code&gt;chmod -R&lt;/code&gt;, since that touches ALL files, recursively, overwriting the ctime stamp. An okay way is to use &lt;code&gt;find&lt;/code&gt;, which (in most versions) allow you to fix things up quite neatly (&lt;code&gt;bash/sh&lt;/code&gt; compatible syntax, GNU find compatible options, &lt;code&gt;$dir&lt;/code&gt; represents the directory to fix recursively, &lt;code&gt;$user&lt;/code&gt; is the username whose files you want to change):&lt;pre&gt;find $dir -xdev -user $uname \&lt;br /&gt;\( \( -perm /og=w -exec chmod og-w {} \; \) -o \&lt;br /&gt;   \( -perm /g=w -exec chmod g-w {} \; \) -o \&lt;br /&gt;   \( -perm /o=w -exec chmod o-w {} \; \) \)&lt;/pre&gt;Phew, that was quite a mouthful, but it's rather nice in resource usage, and it doesn't cross filesystem boundaries (&lt;code&gt;-xdev&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;So why would I want to do this in Perl, you ask?&lt;br /&gt;&lt;br /&gt;&lt;em&gt;"Eeerrr. Good question, let me tell you why!"&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;There are &lt;strong&gt;many&lt;/strong&gt; other problems to look for, which it is sensible to look for while you're at it, just to mention a few:&lt;ul&gt;&lt;li&gt;Backdoors&lt;/li&gt;&lt;li&gt;Hidden IFRAMEs&lt;/li&gt;&lt;li&gt;Malicious JavaScript&lt;/li&gt;&lt;li&gt;Malware URLs&lt;/li&gt;&lt;li&gt;Malware redirects (e.g. in .htaccess)&lt;/li&gt;&lt;li&gt;Outdated software versions&lt;/li&gt;&lt;li&gt;Root exploits&lt;/li&gt;&lt;li&gt;Spamming scripts&lt;/li&gt;&lt;li&gt;Viruses&lt;/li&gt;&lt;/ul&gt;These things belong in a program, not a teeny weeny Unix one-liner, or even a set of them.&lt;br /&gt;&lt;br /&gt;While you're at it, you might want to create a log of what you found, and perhaps which line numbers are relevant for which files, both for pointing out where to consider fixing things, as well as having something to use for debugging your false positives.&lt;br /&gt;&lt;br /&gt;&lt;a name="code20091103"&gt;&lt;/a&gt;&lt;h2&gt;The code&lt;/h2&gt;&lt;br /&gt;Here's how I identify the files with too liberal write permissions, utilizing the &lt;code&gt;Fnctl&lt;/code&gt; module. The filename is stored in &lt;code&gt;$_&lt;/code&gt;, the user's real UID in &lt;code&gt;$r_uid&lt;/code&gt;, and I also store various file information and what kind of file we're looking at.&lt;pre&gt;use Fcntl ':mode';&lt;br /&gt;&lt;br /&gt;my %badperms;&lt;br /&gt;my ($dev,$ino,$mode,$nlink,&lt;br /&gt;    $uid,$gid,$rdev,$size) = lstat($_);&lt;br /&gt;my $g_write = $mode &amp;amp; S_IWGRP;&lt;br /&gt;my $o_write = $mode &amp;amp; S_IWOTH;&lt;br /&gt;my ($isfile,$isdir,$islink) = (-f _, -d _, -l _);&lt;br /&gt;&lt;br /&gt;my $filetype = $isfile ? "File" : \&lt;br /&gt;   $isdir ? "Directory" : \&lt;br /&gt;   $islink ? "Symlink" : "Other";&lt;br /&gt;my $fn = $_;&lt;br /&gt;&lt;br /&gt;# Writable for others                                                    &lt;br /&gt;if (!$islink &amp;amp;&amp;amp; ($g_write || $o_write)) {&lt;br /&gt;    $badperms{$fn} =&lt;br /&gt;        sprintf ("%s: [%04o] %s\n", $filetype,&lt;br /&gt;                 S_IMODE($mode), $fn);&lt;br /&gt;}&lt;/pre&gt;In a future post, I'll try to get back with how this fits in my bigger picture of vulnerability detection.&lt;br /&gt;&lt;br /&gt;As always, suggestions for improvements and questions are very welcome.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-6659670284520341333?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/6659670284520341333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=6659670284520341333' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/6659670284520341333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/6659670284520341333'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/11/checking-and-fixing-unix-file-modes.html' title='Checking and fixing Unix file modes'/><author><name>bakkushan</name><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-753668960778118906.post-1414006292564002703</id><published>2009-10-26T23:56:00.006+01:00</published><updated>2009-10-28T23:01:35.362+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scriptlets'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='trivial'/><title type='text'>Small and cute shell and Perl scriptlets</title><content type='html'>Once upon a time, the world was full of small and cute shell and Perl scripts that served a small but useful purpose, and which were shared freely - just because hackers were nice guys. So we bring some of these around with us, in slightly modified or improved versions.&lt;br /&gt;&lt;br /&gt;I'd like to carry on the tradition of sharing some of these before they are lost, even though they are about as trivial as you can get.&lt;br /&gt;&lt;br /&gt;&lt;a name="Eval"&gt;&lt;/a&gt;&lt;span style="font-size:130%;"&gt;Eval&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here's one that I picked up at the University of Oslo 10-15 years ago, which I still use, just out of habit. The file is traditionally named &lt;code&gt;Eval&lt;/code&gt;, and I believe this particular version was concocted by Kjetil T. Homme (who has some other &lt;a href="http://kjetilho.at.ifi.uio.no/hacks/"&gt;nice hacks&lt;/a&gt;, BTW). The idea is to have an easy-to-use command line calculator:&lt;pre&gt;#! /bin/sh -&lt;br /&gt;&lt;br /&gt;exec perl -e '$a = ('"$*"');&lt;br /&gt; if ($a == int($a)) {&lt;br /&gt;   print $a, "\n";&lt;br /&gt; } else {&lt;br /&gt;   printf ("%.3f\n", $a);&lt;br /&gt; }'&lt;/pre&gt;So what's the point?&lt;br /&gt;&lt;br /&gt;For me, it's the ease of use, and not least the ease of installability. All I need is a Perl version that understands a very simple set of commands. I don't have to worry whether &lt;code&gt;bc&lt;/code&gt; or &lt;code&gt;dc&lt;/code&gt; is installed, I don't have to open a GUI, and I can work with fairly advanced expressions. They just have end up as valid Perl.&lt;br /&gt;&lt;br /&gt;&lt;a name="7"&gt;&lt;/a&gt;&lt;span style="font-size:130%;"&gt;7&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Did you ever forget exactly which octal code to use for the ASCII letter 'h', or the hex number for the backtick (`) character? &lt;code&gt;7&lt;/code&gt; to the rescue!&lt;pre&gt;#! /usr/bin/perl -C&lt;br /&gt;&lt;br /&gt;for (32..126) {&lt;br /&gt;    printf "%3d 0x%02X 0%03o 0b%08b %c\n", ($_)x5;&lt;br /&gt;}&lt;/pre&gt;And if you still haven't made the transition to Unicode/UTF-8, printing the printables in e.g. a Latin character set may still be interesting; create a copy of the file called &lt;code&gt;8&lt;/code&gt;, which works on the range 160..255 instead. Or be fancy with basename checking and all that. :)&lt;br /&gt;&lt;br /&gt;&lt;a name="Answer"&gt;&lt;/a&gt;&lt;span style="font-size:130%;"&gt;Answer&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When I write scripts that do potentially Dangerous Stuff on production servers &lt;small&gt;(that happens way too often)&lt;/small&gt;, I usually like to include some code that tells the user to think a bit before continuing. That is, I don't want all scripts to be fire-and-forget. This is another classical piece of code, which I've massaged for my own needs (and perhaps your needs as well?):&lt;pre&gt;print "About to run $code.\n\n";&lt;br /&gt;print "Are you sure? (y/N): ";&lt;br /&gt;my $answer = &amp;lt;STDIN&amp;gt;;&lt;br /&gt;chop $answer;&lt;br /&gt;if ($answer !~ /^y(es)?$/i) {&lt;br /&gt;    die "Okay, aborting.\n";&lt;br /&gt;} else {&lt;br /&gt;    print "Okay, continuing!\n";&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/753668960778118906-1414006292564002703?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/1414006292564002703/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=1414006292564002703' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/1414006292564002703'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/1414006292564002703'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/10/small-and-cute-shell-and-perl.html' title='Small and cute shell and Perl scriptlets'/><author><name>bakkushan</name><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-753668960778118906.post-3149238388853251788</id><published>2009-10-19T17:18:00.002+02:00</published><updated>2009-10-19T17:22:05.987+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Iron Man'/><category scheme='http://www.blogger.com/atom/ns#' term='mst'/><title type='text'>183 days of Iron Man blogging</title><content type='html'>Today it's 183 days - more than half a year - since I started blogging, spurred on by mst's lightning talk at NPW 2009.&lt;br /&gt;&lt;br /&gt;That ain't half bad.&lt;br /&gt;&lt;br /&gt;But &lt;a href="http://www.shadowcat.co.uk/blog/matt-s-trout/"&gt;he's still not losing his bet yet, argh!&lt;/a&gt; :D&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-3149238388853251788?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/3149238388853251788/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=3149238388853251788' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/3149238388853251788'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/3149238388853251788'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/10/183-days-of-iron-man-blogging.html' title='183 days of Iron Man blogging'/><author><name>bakkushan</name><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-753668960778118906.post-6589043269528711468</id><published>2009-10-19T16:45:00.002+02:00</published><updated>2009-10-19T17:15:45.158+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perfectionism'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='coding style'/><category scheme='http://www.blogger.com/atom/ns#' term='prepared statements'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><category scheme='http://www.blogger.com/atom/ns#' term='CGI'/><category scheme='http://www.blogger.com/atom/ns#' term='bind variables'/><title type='text'>Coding styles that make me twitch, part 5</title><content type='html'>Let us say that we have some code using DBI - old-fashioned, but it still works, kindof.&lt;br /&gt;&lt;br /&gt;How would you like to see the following in a 6000 line CGI script you're supposed to debug?&lt;pre&gt;&lt;br /&gt;    my $sth=&amp;amp;query("SELECT id FROM invoices WHERE invoiced='N'");&lt;br /&gt;    my $invoiced=$sth-&gt;rows;&lt;br /&gt;&lt;br /&gt;    my $sth2=&amp;amp;query("SELECT count(*) nusers FROM users \&lt;br /&gt;LEFT JOIN people ... # long SQL statement&lt;br /&gt;    my $row2 = $sth2-&amp;gt;fetchrow_hashref;&lt;br /&gt;    my $nusers = $row2-&amp;gt;{nusers};&lt;br /&gt;&lt;br /&gt;    my $sth3=&amp;amp;query("SELECT count(*) npeople FROM users \&lt;br /&gt;LEFT JOIN people ... # long SQL statement&lt;br /&gt;    my $row3 = $sth3-&amp;gt;fetchrow_hashref;&lt;br /&gt;    my $npeople = $row3-&amp;gt;{npeople};&lt;br /&gt;&lt;br /&gt;    my $sth4=...&lt;/pre&gt;And then, after carefully checking scope, you discover that the variables $sth2, $row2, $sth3, $row3, $sth4, $row4 etc. &lt;strong&gt;are not used anywhere else within the same scope&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Would you develop a tick?&lt;br /&gt;&lt;br /&gt;I did, and the tick didn't lessen in strength when I discovered unsafe variable interpolation as well as a sub &lt;code&gt;query&lt;/code&gt; that used &lt;code&gt;$dbh-&amp;gt;prepare($qtext)&lt;/code&gt; but didn't allow passing of usable parameters, such as, you know, &lt;strong&gt;bind variables&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;I've started on &lt;em title="read: rewriting"&gt;"refactoring"&lt;/em&gt; the real life code this example is based on, but I get depressed from the sheer amount of work in fixing many problems at once. Maybe I should pick up drunken coding to become less perfectionist.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-6589043269528711468?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/6589043269528711468/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=6589043269528711468' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/6589043269528711468'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/6589043269528711468'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/10/coding-styles-that-make-me-twitch-part_19.html' title='Coding styles that make me twitch, part 5'/><author><name>bakkushan</name><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-753668960778118906.post-7010716437723491621</id><published>2009-10-12T00:54:00.003+02:00</published><updated>2009-10-12T00:54:00.506+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='autodie'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><category scheme='http://www.blogger.com/atom/ns#' term='Digest::MD5'/><title type='text'>Use Digest::MD5 - it's easy</title><content type='html'>In my previous entry, I presented and purposefully ignored a rather non-portable way of getting an MD5 sum from a file:&lt;pre&gt;$md5 = `md5sum $filename.new | awk '{ print $1 }'`;&lt;br /&gt;$md5 =~ s/\n$//;&lt;br /&gt;&lt;/pre&gt;There are stupider and better ways of doing this in the system call, but it completely ignores the problem that the command is not always called &lt;code&gt;md5sum&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Digest::MD5&lt;/code&gt; comes to the rescue!&lt;pre&gt;&lt;br /&gt;use autodie; # Hee-hee&lt;br /&gt;use Digest::MD5;&lt;br /&gt;my $digester = Digest::MD5-&gt;new;&lt;br /&gt;open(FH,"&lt;$filename.new");&lt;br /&gt;$digester-&gt;addfile(*FH);&lt;br /&gt;my $md5 = $digester-&gt;hexdigest;&lt;br /&gt;&lt;/pre&gt;Okay, that looks slightly over-complicated, one might argue that Digest::MD5 should hide the file handle fiddling from the user. The value added comes when you have a chunk of data already in a variable, then you just do &lt;code&gt;use Digest::MD5 qw(md5_hex);&lt;/code&gt; and call &lt;code&gt;md5_hex($data)&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Oh, and I snuck in &lt;a href="http://search.cpan.org/dist/autodie/" title="autodie"&gt;something else again&lt;/a&gt;, didn't I.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-7010716437723491621?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/7010716437723491621/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=7010716437723491621' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/7010716437723491621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/7010716437723491621'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/10/use-digestmd5-its-easy.html' title='Use Digest::MD5 - it&apos;s easy'/><author><name>bakkushan</name><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-753668960778118906.post-4750532330549392328</id><published>2009-10-06T00:17:00.006+02:00</published><updated>2009-10-06T00:53:44.445+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mv'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='File::Path'/><category scheme='http://www.blogger.com/atom/ns#' term='rename'/><category scheme='http://www.blogger.com/atom/ns#' term='md5'/><category scheme='http://www.blogger.com/atom/ns#' term='system'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><category scheme='http://www.blogger.com/atom/ns#' term='File::Copy'/><title type='text'>Coding styles that make me twitch, part 4</title><content type='html'>All too often, I see code like this:&lt;pre&gt;&lt;br /&gt;$md5 = `md5sum $filename.new | awk '{ print $1 }'`;&lt;br /&gt;$md5 =~ s/\n$//;&lt;br /&gt;if ($md5 ne $origmd5) {&lt;br /&gt;  system("mv $filename $filename.old");&lt;br /&gt;  system("mv $filename.new $filename");&lt;br /&gt;  …&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Well, you get the idea.&lt;br /&gt;&lt;br /&gt;Sure, Perl can pretend to be a glorified shell script, but there are perfectly well-functioning internal functions for these things.&lt;br /&gt;&lt;br /&gt;Let's ignore the non-portability of the &lt;code&gt;md5sum&lt;/code&gt; command for the time being, and also avoid shaving that &lt;code&gt;awk&lt;/code&gt; call down with &lt;code&gt;cut&lt;/code&gt; and an enclosing &lt;code&gt;echo -n $(…)&lt;/code&gt; - we're here for the Perl, not the shell, right?&lt;br /&gt;&lt;br /&gt;The above &lt;code&gt;system()&lt;/code&gt; calls can easily be replaced with the following to save yourself a few unnecessary forks:&lt;pre&gt;&lt;br /&gt;rename($filename,"$filename.old") and&lt;br /&gt;rename("$filename.new",$filename);&lt;br /&gt;&lt;/pre&gt;Note the slight refinement of using &lt;code&gt;and&lt;/code&gt; to avoid clobbering the file. But the documentation for &lt;code&gt;rename()&lt;/code&gt; suggests that we use &lt;code&gt;move()&lt;/code&gt; from &lt;code&gt;File::Copy&lt;/code&gt; instead:&lt;pre&gt;&lt;br /&gt;use File::Copy qw(mv);&lt;br /&gt;mv($filename,"$filename.old") and&lt;br /&gt;mv("$filename.new",$filename);&lt;br /&gt;&lt;/pre&gt;Similarly, there are nice built-in functions for many other frequent victims of &lt;code&gt;system()&lt;/code&gt;, e.g.:&lt;pre&gt;&lt;br /&gt;chmod&lt;br /&gt;chgrp + chown&lt;br /&gt;link&lt;br /&gt;mkdir&lt;br /&gt;rmdir&lt;br /&gt;symlink&lt;br /&gt;unlink&lt;br /&gt;&lt;/pre&gt;And of course there is a bunch of more or less helpful modules on CPAN &lt;small&gt;(in addition to the already mentioned &lt;code&gt;File::Copy&lt;/code&gt;)&lt;/small&gt;, e.g. &lt;code&gt;File::Path&lt;/code&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-4750532330549392328?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/4750532330549392328/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=4750532330549392328' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/4750532330549392328'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/4750532330549392328'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/10/coding-styles-that-make-me-twitch-part.html' title='Coding styles that make me twitch, part 4'/><author><name>bakkushan</name><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-753668960778118906.post-6284535865298081475</id><published>2009-09-30T23:21:00.000+02:00</published><updated>2009-09-30T23:21:13.530+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='contributing'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='community'/><category scheme='http://www.blogger.com/atom/ns#' term='Iron Man'/><category scheme='http://www.blogger.com/atom/ns#' term='inspiration'/><category scheme='http://www.blogger.com/atom/ns#' term='blogging'/><title type='text'>Contributing to Perl</title><content type='html'>Inspiration is a big bother, at least when you don't have it.&lt;br /&gt;&lt;br /&gt;I never felt that I had anything to contribute to the Perl community until the Nordic Perl Workshop this year, when I suddenly was involved in a small way.&lt;br /&gt;&lt;br /&gt;I'm still involved in a small way, and only occasionally, but that works rather well.&lt;br /&gt;&lt;br /&gt;In retrospect, my expectation that contributing would be a Big Deal turned out be wrong.&lt;br /&gt;&lt;br /&gt;I don't have to solve all the problems in the world, and I don't have to solve the Big Ones, either.&lt;br /&gt;&lt;br /&gt;It doesn't even take much of my time, and this level of contribution is one that suits many people.&lt;br /&gt;&lt;br /&gt;Inspiration comes from the impression I have that there are many more people like me, and that all those little trickles of water we add to the pool are enough to keep the more active contributors going.&lt;br /&gt;&lt;br /&gt;What is difficult, however, is to keep up with the Iron Man blogging challenge.  I knew it would be when I got started, but I figured that there would always be something to write about without seeming too inane.&lt;br /&gt;&lt;br /&gt;Today's post shows that I was wrong on that count.  :D&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-6284535865298081475?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/6284535865298081475/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=6284535865298081475' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/6284535865298081475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/6284535865298081475'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/09/contributing-to-perl.html' title='Contributing to Perl'/><author><name>bakkushan</name><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-753668960778118906.post-3715648505493129626</id><published>2009-09-23T22:30:00.003+02:00</published><updated>2009-09-23T22:39:09.780+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='crazy'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='friends'/><title type='text'>I blame society</title><content type='html'>This is only vaguely Perl-related.&lt;br /&gt;&lt;br /&gt;This weekend, I visited Abigail and her spouse in their home in the Netherlands.&lt;br /&gt;&lt;br /&gt;I know Abigail from several settings, and Perl is one of them; Abigail has taught me many cool finesses in Perl 5, which has saved me considerable time both personally and professionally.&lt;br /&gt;&lt;br /&gt;The friendships and connections we make "virtually" can also be very strong &lt;span title="In Real Life" style="text-decoration: underline; font-style: italic"&gt;IRL&lt;/span&gt;, and I feel that has been the case with us.&lt;br /&gt;&lt;br /&gt;If there is a point to this post, then that is: visit your Perl friends!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-3715648505493129626?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/3715648505493129626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=3715648505493129626' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/3715648505493129626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/3715648505493129626'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/09/i-blame-society.html' title='I blame society'/><author><name>bakkushan</name><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-753668960778118906.post-7413132568687463757</id><published>2009-09-13T21:55:00.006+02:00</published><updated>2009-09-13T22:34:28.462+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='adverbial'/><title type='text'>Some ways that Perl 6 is grand, part 3 of ?</title><content type='html'>I'll be really brief this time, I promise!&lt;br /&gt;&lt;br /&gt;Several things about Perl 6 are there to save programmer time. Some of them even will do so. ;) This week's favourite is pure laziness. Let's imagine we have one of those lists with month names in them again, and for some odd reason only want to do something to each third month.&lt;pre&gt;for ^12 :by(3) {&lt;br /&gt;  say @months[$_];&lt;br /&gt;}&lt;/pre&gt;I think that's just neat.&lt;br /&gt;&lt;br /&gt;The caret notation is the "upto" operator, and shorthand for a range from 0 and &lt;em&gt;up to&lt;/em&gt; its argument. So in the example above, we're asking for a range from 0 and up to 12.&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;by&lt;/code&gt; adverbial is new in the specification. It denotes the increments for the upto operator, and allows e.g. real numbers, so that you can increment by 0.25 if it makes sense for your code to do so.&lt;br /&gt;&lt;br /&gt;The above example then essentially iterates over &lt;code&gt;0, 3, 6, 9&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;by&lt;/code&gt; adverbial isn't yet implemented in Rakudo &lt;small&gt;(well, duh, the spec just saw it added)&lt;/small&gt;, where you have to settle for this for now:&lt;pre&gt;for ^4 {&lt;br /&gt;  say @months[$_*3];&lt;br /&gt;}&lt;/pre&gt;… and something different if you want to increment by 0.25. I hope you don't want to increment through the list of months by 0.25.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-7413132568687463757?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/7413132568687463757/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=7413132568687463757' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/7413132568687463757'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/7413132568687463757'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/09/some-ways-that-perl-6-is-grand-part-2.html' title='Some ways that Perl 6 is grand, part 3 of ?'/><author><name>bakkushan</name><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-753668960778118906.post-2910113159667260097</id><published>2009-09-06T21:28:00.008+02:00</published><updated>2009-09-06T22:43:52.313+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='contextual variables'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><title type='text'>Print-and-log in Perl 6</title><content type='html'>In one of my early blog entries, "&lt;a href="http://howcaniexplainthis.blogspot.com/2009/05/simple-print-and-log-subroutine.html"&gt;Simple print-and-log subroutine&lt;/a&gt;", I shared a small piece of code that has been a nice, every-day tool - in Perl 5.&lt;br /&gt;&lt;br /&gt;Today, I set about converting that to a naïve Perl 6 version, and being quite the Perl 6 n00b still, I ran into a few hurdles along the way.&lt;br /&gt;&lt;br /&gt;The hurdles were easy enough to avoid, once &lt;a href="http://use.perl.org/~masak/journal/"&gt;masak&lt;/a&gt;++ and &lt;a href="http://perlgeek.de/blog-en/"&gt;moritz&lt;/a&gt;++ had bonked my head sufficiently.&lt;br /&gt;&lt;br /&gt;I'll walk through the code, step by step, to illustrate what I learned today, and what others might need to know.&lt;blockquote&gt;&lt;pre&gt;use v6;&lt;/pre&gt;&lt;/blockquote&gt;Ah, first, remember this statement. It's a nice hint for other software if you want to continue using the &lt;code&gt;.pl&lt;/code&gt; file suffix instead of &lt;code&gt;.p6l&lt;/code&gt; etc.&lt;blockquote&gt;&lt;pre&gt;my $verbose = 1;&lt;br /&gt;my $logfile = "/tmp/test.log";&lt;br /&gt;&lt;br /&gt;my $*PREFIX = "plog";&lt;/pre&gt;&lt;/blockquote&gt;Variables starting with the &lt;em&gt;twigil&lt;/em&gt; &lt;code&gt;$*&lt;/code&gt; is what we call &lt;em&gt;contextual variables&lt;/em&gt;, and &lt;a href="http://use.perl.org/~pmichaud/journal/39585?from=rss"&gt;they just started working yesterday in Rakudo&lt;/a&gt;. Contextual variables follow a dynamic call path. When we reuse this variable later, it will depend on which call path we followed.&lt;blockquote&gt;&lt;pre&gt;sub plogwarn ($msg)&lt;br /&gt;{ &lt;br /&gt;  my $*PREFIX = "plogwarn";&lt;/pre&gt;&lt;/blockquote&gt;$*PREFIX now has a different value only for the cases where we've called the &lt;code&gt;plogwarn&lt;/code&gt; subroutine, and the subsequent call to &lt;code&gt;plog&lt;/code&gt; inherits this value.&lt;blockquote&gt;&lt;pre&gt;  plog $msg,1;&lt;/pre&gt;&lt;/blockquote&gt;Oh, BTW, it's really, REALLY important to keep track of where you add whitespace or not. I'd been sleeping and class, and forgotten completely that &lt;code&gt;plog($msg,1)&lt;/code&gt; would call &lt;code&gt;plog&lt;/code&gt; with the parameters &lt;code&gt;$msg&lt;/code&gt; and &lt;code&gt;$1&lt;/code&gt;, while &lt;code&gt;plog ($msg,1)&lt;/code&gt; would call &lt;code&gt;plog&lt;/code&gt; with the single parameter &lt;code&gt;($msg,$1)&lt;/code&gt; (yep, a list). It may be safer to avoid parentheses altogether when you're not dealing with lists - except when you have to.&lt;blockquote&gt;&lt;pre&gt;}&lt;br /&gt;&lt;br /&gt;sub plogdie ($msg)&lt;br /&gt;{ &lt;br /&gt;  my $*PREFIX = "plogdie";&lt;br /&gt;  plog $msg,2;&lt;br /&gt;  exit 1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;sub plog ($msg is copy, $level?)&lt;/pre&gt;&lt;/blockquote&gt;The &lt;a href="http://perlcabal.org/syn/S06.html#Parameter_traits"&gt;trait&lt;/a&gt; &lt;code&gt;is copy&lt;/code&gt; means that I want to make a copy of the incoming parameter &lt;code&gt;$msg&lt;/code&gt;, so that I can modify it inside of &lt;code&gt;plog&lt;/code&gt;. Normally, parameters in Perl 6 are read-only and pass-by-reference (though not "reference" as you know it from Perl); the parameter as named is merely an alias for the actual variable. I can change the parameter in the caller if I use &lt;code&gt;is rw&lt;/code&gt;, but that's not what I want to do here. The question mark in the second parameter - &lt;code&gt;$level?&lt;/code&gt; - means that the parameter is optional, and I've used that in both &lt;code&gt;plogwarn&lt;/code&gt; and &lt;code&gt;plogdie&lt;/code&gt; above.&lt;blockquote&gt;&lt;pre&gt;{ &lt;br /&gt;  my $dt = Time.gmtime.date.iso8601&lt;br /&gt;         ~ " "&lt;br /&gt;         ~ Time.gmtime.time.iso8601;&lt;/pre&gt;&lt;/blockquote&gt;Normally, I'd use &lt;code&gt;localtime&lt;/code&gt;, but this is NYI &lt;small&gt;(not yet implemented)&lt;/small&gt; in &lt;code&gt;Temporal.pm&lt;/code&gt;.&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;  $msg = ($dt,"[$*PREFIX]",$msg).join(" ");&lt;/pre&gt;&lt;/blockquote&gt;Here, I abuse that &lt;code&gt;is copy&lt;/code&gt; to save myself one precious variable, just as an example.&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;  if $verbose {&lt;br /&gt;    given $level {&lt;br /&gt;      when 1 { warn $msg; }&lt;br /&gt;      when 2 { die $msg; }&lt;br /&gt;      default { say $msg; }&lt;br /&gt;    }&lt;/pre&gt;&lt;/blockquote&gt;The &lt;a href="http://perlcabal.org/syn/S04.html#Switch_statements"&gt;&lt;code&gt;given…when&lt;/code&gt;&lt;/a&gt; construct is similar to the &lt;code&gt;switch…case&lt;/code&gt; construct in other languages, but subtly different, as it allows more possible values and value types than most. Coming from a world of Perl 5.8 and older, this is simply lovely.&lt;blockquote&gt;&lt;pre&gt;  }&lt;br /&gt;  # Append message to $logfile&lt;br /&gt;  my $*OUT = open $logfile, :a;&lt;/pre&gt;&lt;/blockquote&gt;Here's another use of a contextual variable, but this time it's the one normally associated with STDOUT. &lt;code&gt;print FILEHANDLE $msg&lt;/code&gt; is no longer necessary, because you can always assign $*OUT in its own scope. The &lt;code&gt;open&lt;/code&gt; statement has &lt;code&gt;:a&lt;/code&gt; to indicate that I'm opening for append (so the syntax is less unixy than Perl 5's &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;).&lt;blockquote&gt;&lt;pre&gt;  say $msg;&lt;br /&gt;  $*OUT.close;&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;This is how we can use the three subroutines, and the output should illustrate the different contextuals nicely:&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;plog("Oh, hello, there, sweetie.");&lt;br /&gt;plogwarn("Consider yourself warned");&lt;br /&gt;plogdie("Die, frackin' monster, die!");&lt;/pre&gt;&lt;/blockquote&gt;…outputs…&lt;blockquote&gt;&lt;pre&gt;2009-09-06 19:59:32 [plog] Oh, hello, there, sweetie.&lt;br /&gt;2009-09-06 19:59:32 [plogwarn] Consider yourself warned&lt;br /&gt;2009-09-06 19:59:32 [plogdie] Die, frackin' monster, die!&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;And here's the complete example code, which works with the current Rakudo:&lt;blockquote&gt;&lt;pre&gt;use v6;&lt;br /&gt;&lt;br /&gt;my $verbose = 1;&lt;br /&gt;my $logfile = "/tmp/test.log";&lt;br /&gt;my $*PREFIX = "plog";&lt;br /&gt;&lt;br /&gt;sub plogwarn ($msg)&lt;br /&gt;{ &lt;br /&gt;  my $*PREFIX = "plogwarn";&lt;br /&gt;  plog $msg,1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;sub plogdie ($msg)&lt;br /&gt;{ &lt;br /&gt;  my $*PREFIX = "plogdie";&lt;br /&gt;  plog $msg,2;&lt;br /&gt;  exit 1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;sub plog ($msg is copy, $level?)&lt;br /&gt;{ &lt;br /&gt;  my $dt = Time.gmtime.date.iso8601&lt;br /&gt;         ~ " "&lt;br /&gt;         ~ Time.gmtime.time.iso8601;&lt;br /&gt;&lt;br /&gt;  $msg = ($dt,"[$*PREFIX]",$msg).join(" ");&lt;br /&gt;&lt;br /&gt;  if $verbose {&lt;br /&gt;    given $level {&lt;br /&gt;      when 1 { warn $msg; }&lt;br /&gt;      when 2 { die $msg; }&lt;br /&gt;      default { say $msg; }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  # Append message to $logfile&lt;br /&gt;  my $*OUT = open $logfile, :a;&lt;br /&gt;  say $msg;&lt;br /&gt;  $*OUT.close;&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-2910113159667260097?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/2910113159667260097/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=2910113159667260097' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/2910113159667260097'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/2910113159667260097'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/09/print-and-log-in-perl-6.html' title='Print-and-log in Perl 6'/><author><name>bakkushan</name><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-753668960778118906.post-1799905557789113842</id><published>2009-08-31T23:17:00.009+02:00</published><updated>2009-09-03T16:42:45.491+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='hash'/><category scheme='http://www.blogger.com/atom/ns#' term='zip'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><title type='text'>Some ways that Perl 6 is grand, part 2 of ?</title><content type='html'>Okay, this is really part 1b of ?, but…&lt;br /&gt;&lt;br /&gt;In my &lt;a href="http://howcaniexplainthis.blogspot.com/2009/08/some-ways-that-perl-6-is-grand-part-1.html"&gt;earlier post&lt;/a&gt;, I used the zip operator to join two lists into a hash.&lt;br /&gt;&lt;br /&gt;There was one obvious use of the operator that escaped me at the time, and that was how I sometimes need to create a new hash from the keys of two hashes, or keys and values. And now I think it's starting to look neat:&lt;pre&gt;my %A = { a =&amp;gt; 1, b =&amp;gt; 2 };&lt;br /&gt;my %B = { z =&amp;gt; 9, y =&amp;gt; 8 };&lt;br /&gt;&lt;br /&gt;my %AB = %A.keys Z %B.keys;&lt;br /&gt;# { "a" =&amp;gt; "z", "b" =&amp;gt; "y" }&lt;br /&gt;&lt;br /&gt;%AB = %A.keys Z %B.values;&lt;br /&gt;# { "a" =&amp;gt; 9, "b" =&amp;gt; 8 }&lt;/pre&gt;However, this is a bit unpredictable, since the hash key order is undefined. So if you expect sorted keys, do that at the same time:&lt;pre&gt;%AB = %A.keys.sort Z %B.keys.sort;&lt;br /&gt;# { "a" =&amp;gt; y, "b" =&amp;gt; z }&lt;br /&gt;&lt;br /&gt;# Sort by B's values - two variants&lt;br /&gt;%AB = %A.keys.sort Z map { %B{$_} }, %B.keys.sort;&lt;br /&gt;%AB = %A.keys.sort Z %B.sort.map( { .value } );&lt;br /&gt;# { "a" =&amp;gt; 8, "b" =&amp;gt; 9 }&lt;/pre&gt;The equivalent Perl 5.10 version would be:&lt;pre&gt;use List::MoreUtils qw/zip/;&lt;br /&gt;my @k = sort(keys(%A));&lt;br /&gt;my @v = map { $B{$_} }, sort(keys(%B));&lt;br /&gt;%AB = zip @k, @v;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I now have a nice-ish argument for upgrading to Perl 5.10.1 on $workplace's servers. :D&lt;br /&gt;&lt;br /&gt;&lt;a href="http://use.perl.org/~masak/journal/"&gt;masak&lt;/a&gt;++ &lt;small&gt;for helping a tired me with the map expression.&lt;/small&gt;&lt;br /&gt;&lt;a href="http://svok.blogspot.com/"&gt;Chas. Owens&lt;/a&gt;++ &lt;small&gt;for spotting the missing use statement for Perl 5.&lt;/small&gt;&lt;br /&gt;Pm++ &lt;small&gt;for another way of sorting by value, just what I was hoping for!&lt;/small&gt;&lt;br /&gt;isec++ &lt;small&gt;for spotting a missing sort() for Perl 5.&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-1799905557789113842?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/1799905557789113842/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=1799905557789113842' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/1799905557789113842'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/1799905557789113842'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/08/some-ways-that-perl-6-is-grand-part-2.html' title='Some ways that Perl 6 is grand, part 2 of ?'/><author><name>bakkushan</name><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>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-753668960778118906.post-6023067578287505382</id><published>2009-08-23T22:52:00.007+02:00</published><updated>2009-08-24T20:49:45.132+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='autovivification'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><title type='text'>Autovivification - a reminder</title><content type='html'>Most of you already know this by heart, but the odd reader may have forgotten.&lt;br /&gt;&lt;br /&gt;Autovivification is what we call the process of automatically creating entries in built-in data structures (Perl 5: array/list and hash), usually at the time we check whether an inner element exists or not.&lt;br /&gt;&lt;br /&gt;This can be a royal PITA, if you don't pay attention to the problem. That's why it keeps being mentioned.&lt;br /&gt;&lt;br /&gt;Here's a simple example:&lt;pre&gt;&lt;br /&gt;my %hash;&lt;br /&gt;my $n;&lt;br /&gt;while (!exists ($hash{x}) &amp;&amp; $n &lt; 5) {&lt;br /&gt;    $n++;&lt;br /&gt;    if (!exists ($hash{x}{y}) {&lt;br /&gt;        print "hash{x}{y} does not exist: $n\n";&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Q: &lt;/span&gt;How many times does the above while loop run in Perl 5?&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;A: &lt;/span&gt;Once.&lt;br /&gt;&lt;br /&gt;The simple matter of checking the existence of the inner hash resulted in an entry being created for &lt;code&gt;$hash{x}&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;That means that tests like these should be written more carefully:&lt;pre&gt;&lt;br /&gt;…&lt;br /&gt;    if (defined ($hash{x})) {&lt;br /&gt;        if (!exists ($hash{x}{y}) {&lt;br /&gt;            print "$n: hash{x}{y} does not exist.\n";&lt;br /&gt;        }&lt;br /&gt;    } else {&lt;br /&gt;        print "$n: hash{x} is undefined.\n";&lt;br /&gt;    }&lt;br /&gt;…&lt;/pre&gt;&lt;br /&gt;This prints &lt;code&gt;$n: hash{x} is undefined.&lt;/code&gt; (with an incrementing $n) five times.&lt;br /&gt;&lt;br /&gt;&lt;hr&gt;&lt;b&gt;Edit 2009-08-24 18:49 UTC: &lt;/b&gt;MST commented that there is an &lt;a href="http://search.cpan.org/~vpit/autovivification-0.03/lib/autovivification.pm"&gt;autovivification module on CPAN&lt;/a&gt; that lets us say &lt;code&gt;no autovivification;&lt;/code&gt; - and it's even &lt;em&gt;lexically scoped&lt;/em&gt;! That's just $notreallyanexpletive brilliant! Thanks, Matt, and thanks, Vincent!&lt;hr&gt;&lt;br /&gt;&lt;br /&gt;Oh, BTW, Perl 6 has a useful &lt;a href="http://perlcabal.org/syn/S09.html#Autovivification"&gt;specification for autovivification&lt;/a&gt;, which illuminates the problem further.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-6023067578287505382?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/6023067578287505382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=6023067578287505382' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/6023067578287505382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/6023067578287505382'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/08/autovivification-reminder.html' title='Autovivification - a reminder'/><author><name>bakkushan</name><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-753668960778118906.post-4299361765694921805</id><published>2009-08-16T11:36:00.004+02:00</published><updated>2009-08-16T12:12:10.493+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='community'/><title type='text'>Hash key sort order - a Perl 6 community sunshine story</title><content type='html'>&lt;span style="font-style:italic;"&gt;&lt;blockquote&gt;The order of hash keys is implementation dependent and arbitrary. Unless %hash is altered in any way, successive calls to .keys, .kv, .pairs, .values, or .iterator will iterate over the elements in the same order.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://perlcabal.org/syn/S09.html#Hashes"&gt;S09 - Hashes&lt;/a&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;br /&gt;This is new. It may not actually say much, but it does say what was implicit before, so that there is little room for doubt.&lt;br /&gt;&lt;br /&gt;So here's my little sunshine story about how easy it is to clarify a part of the spec.&lt;br /&gt;&lt;br /&gt;In my &lt;a href="http://howcaniexplainthis.blogspot.com/2009/08/some-ways-that-perl-6-is-grand-part-1.html"&gt;previous post&lt;/a&gt;, I used an imaginary case for showing off some features of Perl 6 - some of which also are available in Perl 5.10, as mentioned by Robert 'phaylon' Sedlacek in a comment.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;This wasn't the only useful comment, I think there's a bit to be learned by reading those, so please do.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;But I digress from the point of this post, which is a question that was raised in another comment to last Sunday's post:&lt;br /&gt;&lt;span style="font-style:italic;"&gt;&lt;blockquote&gt;&lt;br /&gt;By the way, do you know where the behavior of ~%h is spec'ed? I keep getting the keys back in the same order I put them in and don't know if that is an implementation quirk or a feature.&lt;br /&gt;&lt;br /&gt;- Chas. Owens&lt;br /&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;br /&gt;The spec wasn't very clear about this; &lt;a href="http://perlcabal.org/syn/S32/Containers.html#Hash"&gt;S32/Containers - Hash&lt;/a&gt; said that certain iterator methods iterate &lt;span style="font-style:italic;"&gt;"… the elements of %hash in no apparent order, but the order will be the same between successive calls to these functions, as long as %hash doesn't change."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://perlcabal.org/syn/S09.html#Hashes"&gt;S09 - Hashes&lt;/a&gt; didn't say anything about it at all.&lt;br /&gt;&lt;br /&gt;I said I would ask around. Thanks to the excellent community channel #perl6 on Freenode, I got an answer similar to this: no, this is unspecified/undefined behaviour, but feel free to come up with a better way of saying it, and update the synopses.&lt;br /&gt;&lt;br /&gt;And how hard is it to update the synopses?  Not at all!  If we want to contribute, we get access.  It's as easy and simple as that.&lt;br /&gt;&lt;br /&gt;First, you need to check out the (part of) the svn repository that you want to contribute to:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;svn co http://svn.pugscode.org/pugs/docs/Perl6&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Then you change whatever you want to change, preferably discuss it with some of the experienced souls on #perl6 or e.g. the Perl 6 language &lt;a href="http://dev.perl.org/perl6/lists/"&gt;mailing list&lt;/a&gt;, show diffs on e.g. &lt;a href="http://gist.github.com/165868"&gt;gist.github.org&lt;/a&gt; or &lt;a href="http://paste.lisp.org/display/85318"&gt;paste.lisp.org&lt;/a&gt;, and if you think you're doing the right thing - commit the change.&lt;br /&gt;&lt;br /&gt;"But I can't commit, I only have read access" you might say. Just ask in any of the mentioned fora for a "commit bit" and state your e-mail address and preferred username, and someone will help you out with that part.&lt;br /&gt;&lt;br /&gt;As we say on #perl6: community++&lt;br /&gt;&lt;br /&gt;I got started, will you join me?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-4299361765694921805?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/4299361765694921805/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=4299361765694921805' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/4299361765694921805'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/4299361765694921805'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/08/hash-key-sort-order-perl-6-community.html' title='Hash key sort order - a Perl 6 community sunshine story'/><author><name>bakkushan</name><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-753668960778118906.post-4862199392680242815</id><published>2009-08-09T23:58:00.013+02:00</published><updated>2009-08-10T11:24:22.590+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><title type='text'>Some ways that Perl 6 is grand, part 1 of ?</title><content type='html'>&lt;small&gt;(After YAPC::Europe in Lisbon, we no longer say "awesome", we say "grand". ;))&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;In Lisbon, there were several talks that aided us to a better understanding of how Perl 6 may be more pleasant and useful than Perl 5.8, or even Perl 5.10.&lt;br /&gt;&lt;br /&gt;I thought I'd try to illuminate some of these as I progress in my own knowledge of Perl 6.&lt;br /&gt;&lt;br /&gt;First choice: the &lt;a href="http://www.pmichaud.com/2009/pres/oscon-perl6op/slides/slide9b.html"&gt;zip operator&lt;/a&gt; and the new quoting syntax for generating lists and selecting items from hashes:&lt;small&gt;&lt;pre&gt;&lt;br /&gt;my @months = &amp;lt;Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec&amp;gt;;&lt;br /&gt;my %days = @months Z 31,28,31,30,31,30,31,31,30,31,30,31;&lt;br /&gt;say "Days in March: " ~ %days&amp;lt;Mar&amp;gt;;&lt;br /&gt;say "Days in June: {%days&amp;lt;Jun&amp;gt;}";&lt;br /&gt;say ~%days;&lt;/pre&gt;&lt;/small&gt;That was quite a bit in one go. :) First, I create a new list of abbreviated month names. Then I combine the list of months with a list of days in that month &lt;small&gt;(for 2009, obviously)&lt;/small&gt; using the zip (Z) operator, and print the number of days in March and June. Finally, I pretty-print each month with the corresponding number of days.&lt;br /&gt;&lt;br /&gt;The result looks like this:&lt;small&gt;&lt;pre&gt;&lt;br /&gt;Days in March: 31&lt;br /&gt;Days in June: 30&lt;br /&gt;Jan     31&lt;br /&gt;Feb     28&lt;br /&gt;Mar     31&lt;br /&gt;Apr     30&lt;br /&gt;May     31&lt;br /&gt;Jun     30&lt;br /&gt;Jul     31&lt;br /&gt;Aug     31&lt;br /&gt;Sep     30&lt;br /&gt;Oct     31&lt;br /&gt;Nov     30&lt;br /&gt;Dec     31&lt;br /&gt;&lt;/pre&gt;&lt;/small&gt;Now imagine what that would have to look like in plain Perl 5.&lt;br /&gt;&lt;br /&gt;There are several new things here that makes your programming days easier:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The well-known sigils $, @ and % are now used in a consistent manner. @ signifies a list, % signifies a hash, also when you access items by index.&lt;/li&gt;&lt;li&gt;Interpolation of non-scalars is now handled with curly brackets {}.&lt;/li&gt;&lt;li&gt;Building a list can be done using commas, no parentheses are necessary.&lt;/li&gt;&lt;li&gt;Building a quoted list can be done using angle brackets, which are auto-quoting.&lt;/li&gt;&lt;li&gt;Accessing a hash item is done using angle brackets, which should be welcome to those of use who don't use US/UK keyboards (bye-bye to &lt;code&gt;{'argh'}&lt;/code&gt;, but it still works).&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;say&lt;/span&gt; is a new pretty-printing friend, which automatically adds newlines.&lt;/li&gt;&lt;li&gt;The concatenation operator is now tilde (~) instead of a period.&lt;/li&gt;&lt;li&gt;As a unary prefix operator, tilde by default stringifies a hash pair-wise with newline separators (while a list is stringified with space separators). It is possible to change this behaviour in derived subclasses.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;small&gt;Edit 2009-08-10 08:34-09:18 UTC: Clarified and added interpolation.&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-4862199392680242815?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/4862199392680242815/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=4862199392680242815' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/4862199392680242815'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/4862199392680242815'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/08/some-ways-that-perl-6-is-grand-part-1.html' title='Some ways that Perl 6 is grand, part 1 of ?'/><author><name>bakkushan</name><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>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-753668960778118906.post-7876376821290357655</id><published>2009-08-04T19:44:00.002+02:00</published><updated>2009-08-04T19:50:42.811+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lisbon'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='YAPC'/><title type='text'>Mini report from YAPC::Europe 2009</title><content type='html'>The second day of the conference is now finished.&lt;br /&gt;&lt;br /&gt;Yet again, the lightning talks have been a great source of entertainment, but the best regular entertainment were probably Paul Fenwick's and Damian Conway's sparring ... in Klingon.&lt;br /&gt;&lt;br /&gt;If you can lay your hands on the video of their respective talks, see them in order, and enjoy the show.&lt;br /&gt;&lt;br /&gt;You might also learn some really interesting Perl as well, or fall deep into the pits of insanity.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-7876376821290357655?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/7876376821290357655/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=7876376821290357655' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/7876376821290357655'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/7876376821290357655'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/08/mini-report-from-yapceurope-2009.html' title='Mini report from YAPC::Europe 2009'/><author><name>bakkushan</name><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-753668960778118906.post-1452491203656146117</id><published>2009-07-31T00:43:00.003+02:00</published><updated>2009-07-31T01:11:47.552+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='YAPC'/><title type='text'>YAPC::Europe 2009</title><content type='html'>Here we go again!&lt;br /&gt;&lt;br /&gt;Thankfully, my employer thought that this year's YAPC::Europe (Corporate Perl) could be relevant for me, and so I'm going, hoping to learn yet more from all the excellent minds present there (modulo swine flu, I suppose ...).&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://yapceurope2009.org/ye2009/schedule"&gt;schedule&lt;/a&gt; contains way too many interesting subjects at the same time, but I'm happy to say that there's plenty of breathing room and time for socializing.&lt;br /&gt;&lt;br /&gt;And this time, I'm bringing a computer, so that I can pretend to be doing something useful.  Haha.&lt;br /&gt;&lt;br /&gt;See you there!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-1452491203656146117?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/1452491203656146117/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=1452491203656146117' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/1452491203656146117'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/1452491203656146117'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/07/yapceurope-2009.html' title='YAPC::Europe 2009'/><author><name>bakkushan</name><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-753668960778118906.post-7123644806458271314</id><published>2009-07-27T23:30:00.004+02:00</published><updated>2009-07-28T00:01:11.113+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='open source'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='gender bias'/><title type='text'>Perl, open source and gender bias</title><content type='html'>Recently, I have been reading a discussion regarding gender bias in the tech industry.&lt;br /&gt;&lt;br /&gt;I realize it is a problem, but for the past years, it has been more of an intellectual realization than something that hit me in the gut. Perhaps it has something to do with the work place culture where I have been working, combined with the informal technical fora I have seen, as well as the general state of things here in Norway.&lt;br /&gt;&lt;br /&gt;However, these things are perhaps not talked about quite as much as they should, and today I re-learned that although things may seem mostly rosy, they are not necessarily so.&lt;br /&gt;&lt;br /&gt;Kirrily "Skud" Robert has been active in various open source contexts for years, and should be no stranger to the Perl community. She recently held a presentation at OSCON -- &lt;a href="http://infotrope.net/blog/2009/07/25/standing-out-in-the-crowd-my-oscon-keynote/"&gt;Standing Out in the Crowd&lt;/a&gt; -- where she discussed some of the challenges when women are in minority, and experiences with open source projects where they are in majority.&lt;br /&gt;&lt;br /&gt;What kicked me in the gut this time was the rather low percentage of women involved in Perl. While better than open source in general, it seems excessively low.&lt;br /&gt;&lt;br /&gt;But Skud does not sling mud at the Perl community. Instead -- if I understand her correctly -- she aims to help open source communities -- and I suppose particularly new projects -- to utilize the resourcefulness of women in development, to reduce the gender bias by increasing the overall activity.&lt;br /&gt;&lt;br /&gt;I can only recommend that you read the presentation, and contemplate the issue for yourself.&lt;br /&gt;&lt;br /&gt;It certainly made me think. Again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-7123644806458271314?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/7123644806458271314/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=7123644806458271314' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/7123644806458271314'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/7123644806458271314'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/07/perl-open-source-and-gender-bias.html' title='Perl, open source and gender bias'/><author><name>bakkushan</name><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-753668960778118906.post-7946014591402873488</id><published>2009-07-21T00:36:00.003+02:00</published><updated>2009-07-21T00:47:26.055+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sandbox'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><title type='text'>A comment on sandboxing and web security</title><content type='html'>In "&lt;a href="http://use.perl.org/~Ovid/journal/39323"&gt;What I Want In Firefox (Parrot)&lt;/a&gt;", Ovid expresses his desire for Perl 6 scripting functionality, with the caveat &lt;em&gt;"if the sandbox is secure enough"&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Aha, &lt;strong&gt;there's your problem&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;The Firefox developers clearly didn't have sandboxing in mind when they designed the browser, scripts are essentially free to do what they wish at least with the DOM, as well as access many central browser functions, &lt;strong&gt;plus&lt;/strong&gt; a bunch of things that we really don't want security vulnerabilities for.&lt;br /&gt;&lt;br /&gt;Another problem is that JavaScript is fundamentally entrenched in Firefox; too much of Firefox internals are based on JavaScript, and I suspect that a Perl 6 addition would only work so-so at best, even if that hypothetical secure sandbox existed.&lt;br /&gt;&lt;br /&gt;Oh, and BTW: the example commits one of the great no-nos of web programming: pushing server side security into the browser, which essentially is &lt;strong&gt;no security at all&lt;/strong&gt;, as seen form the server's point of view.&lt;br /&gt;&lt;br /&gt;Why am I being so negative all of a sudden? Well, it might be sudden for this blog, but I've been working with security related cleanup and detection in the context of Linux system administration for a few years now. It's not enjoyable, I can tell you, and it definitely colours my perception of these things. Also, I've had a fair bit to do with thinking about security earlier.&lt;br /&gt;&lt;br /&gt;Recommended reading (that should be required) for web programmers:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://innocentcode.thathost.com/"&gt;Innocent Code&lt;/a&gt; by Sverre H. Huseby (a buddy of mine), ISBN: 978-0470857441&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-7946014591402873488?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/7946014591402873488/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=7946014591402873488' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/7946014591402873488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/7946014591402873488'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/07/comment-on-sandboxing.html' title='A comment on sandboxing and web security'/><author><name>bakkushan</name><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-753668960778118906.post-5652287052928651379</id><published>2009-07-17T00:04:00.002+02:00</published><updated>2009-07-17T00:12:03.132+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Iron Man'/><category scheme='http://www.blogger.com/atom/ns#' term='meta'/><title type='text'>Iron Man going strong</title><content type='html'>90 days on ...&lt;br /&gt;&lt;br /&gt;English, German, Hebrew, Japanese, Magyar, Perl 5, Perl 6, Russian, ...&lt;br /&gt;&lt;br /&gt;We're positively flourishing here!&lt;br /&gt;&lt;br /&gt;When &lt;a href="http://www.shadowcat.co.uk/blog/matt-s-trout/"&gt;mst&lt;/a&gt; announced the Iron Man concept in his lightning talk at NPW 2009, I felt inspired, but I didn't expect it to work this well.&lt;br /&gt;&lt;br /&gt;There are many extremely interesting blogs out there, sharing knowledge and experience at a level I definitely didn't expect.&lt;br /&gt;&lt;br /&gt;It feels unique, it's wonderful, and I hope this will continue snowballing!&lt;br /&gt;&lt;br /&gt;Thanks, guys!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-5652287052928651379?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/5652287052928651379/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=5652287052928651379' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/5652287052928651379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/5652287052928651379'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/07/iron-man-going-strong.html' title='Iron Man going strong'/><author><name>bakkushan</name><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-753668960778118906.post-3208836698325369651</id><published>2009-07-08T00:49:00.004+02:00</published><updated>2009-07-14T23:35:25.239+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='coding style'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><title type='text'>Coding styles that make me twitch, part 3</title><content type='html'>Today's twitchiness is sponsored by ... no, wait, I don't have sponsors. Ah, well.&lt;br /&gt;&lt;br /&gt;I have an issue with people who insist on using &amp;lt;"&amp;gt; as a string delimiter when the (static) string itself contains that very character. It gets fugly all too soon:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;my $html_output = "&amp;lt;a href=\"http://www.example.com/foobar/$pagename.html\" title=\"Oh, a link to $pagename\"&amp;gt; ...\n";&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;It's so easy to avoid having to quote the &amp;lt;"&amp;gt; while still allowing variable interpolation:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;my $html_output = qq(&amp;lt;a href="http://www.example.com/foobar/$pagename.html" title="Oh, a link to $pagename"&amp;gt; ...\n);&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Since the example is HTML (and could be e.g. SQL), and it might be multi-line, why not ...&lt;br /&gt;&lt;pre&gt;my $html_output = &amp;lt;&amp;lt;EOL;&lt;br /&gt;&amp;lt;a href="http://www.example.com/foobar/$pagename.html"&lt;br /&gt;   title="Oh, a link to $pagename&amp;gt;&lt;br /&gt;EOL&lt;/pre&gt;&lt;br /&gt;That wasn't so hard? Or fugly?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-3208836698325369651?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/3208836698325369651/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=3208836698325369651' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/3208836698325369651'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/3208836698325369651'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/07/coding-styles-that-makes-me-twitch-part.html' title='Coding styles that make me twitch, part 3'/><author><name>bakkushan</name><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-753668960778118906.post-1952651301690924319</id><published>2009-07-02T00:09:00.007+02:00</published><updated>2009-07-11T12:12:22.860+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='humour'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='humor'/><title type='text'>Ruby users anonymous</title><content type='html'>Last weekend, I visited a couple of friends -- Ina and Stig -- and being nerdy geeks, we (well, Stig and I, anyway) ended up chatting about programming and stuff.&lt;br /&gt;&lt;br /&gt;Stig has just started programming Perl again, after a long period where he'd probably claim to be apostate.&lt;br /&gt;&lt;br /&gt;Everybody, meet &lt;a href="http://www.fsck.no/"&gt;Stig&lt;/a&gt;. Stig used to program Ruby, &lt;a href="http://www.fsck.no/2009/07/following-perl-6-hackaton-in-oslo-i-was.html"&gt;but now he's recovering&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;small&gt;Edit: Stig's blog address injected.&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;I hope this shows that there's hope for the ones who got lost.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-1952651301690924319?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/1952651301690924319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=1952651301690924319' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/1952651301690924319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/1952651301690924319'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/07/ruby-users-anonymous.html' title='Ruby users anonymous'/><author><name>bakkushan</name><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-753668960778118906.post-4583211822463114698</id><published>2009-06-24T09:58:00.006+02:00</published><updated>2009-06-24T10:25:39.885+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ClamAV'/><category scheme='http://www.blogger.com/atom/ns#' term='virus'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><title type='text'>Virus scanning with File::Scan::ClamAV</title><content type='html'>This is almost ridiculously &lt;span style="font-style: italic;"&gt;easy&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Problem: a bunch of user directories need virus scanning and per-user reports&lt;br /&gt;&lt;br /&gt;Solution: A Perl script using File::Scan::ClamAV&lt;br /&gt;&lt;br /&gt;Prerequisites:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A unixy OS&lt;/li&gt;&lt;li&gt;Perl 5.8 or 5.10&lt;/li&gt;&lt;li&gt;A functional and running clamd, preferably listening to a socket&lt;/li&gt;&lt;li&gt;The module File::Scan::ClamAV (and its dependencies)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The following code could (after some sensible adjustments) run in a loop through all usernames on your system.&lt;pre&gt;&lt;br /&gt;use File::Scan::ClamAV;&lt;br /&gt;# (...)&lt;br /&gt;# $dir contains the full path of the user's directory&lt;br /&gt;my $av = new File::Scan::ClamAV (find_all =&gt; 1,&lt;br /&gt;                                 port =&gt; '/tmp/clamd.socket');&lt;br /&gt;# find_all means that we wish to recurse directories.&lt;br /&gt;# /tmp/clamd.socket is where my clamd has its socket.&lt;br /&gt;# Other clamd configurations may differ.&lt;br /&gt;&lt;br /&gt;unless ($av-&gt;ping) {&lt;br /&gt;    plogdie "clamd isn't running, aborting virus scan";&lt;br /&gt;} else {&lt;br /&gt;    plog "Performing virus scan for $uname";&lt;br /&gt;&lt;br /&gt;    # Save virus information per username ($uname).&lt;br /&gt;    # Note! scan() returns a hash.&lt;br /&gt;    $a_viruses{$uname} = $av-&gt;scan($dir);&lt;br /&gt;&lt;br /&gt;    if ($a_viruses{$uname}) {&lt;br /&gt;        my @vfiles = sort keys %{$a_viruses{$uname}};&lt;br /&gt;        plog "$uname has ".@vfiles." viruses.";&lt;br /&gt;&lt;br /&gt;        # Home assignment: print contents of $a_viruses{$uname}&lt;br /&gt;        # to a file, using the sorted list @vfiles.&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/753668960778118906-4583211822463114698?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/4583211822463114698/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=4583211822463114698' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/4583211822463114698'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/4583211822463114698'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/06/virus-scanning-with-filescanclamav.html' title='Virus scanning with File::Scan::ClamAV'/><author><name>bakkushan</name><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-753668960778118906.post-3732154188553592643</id><published>2009-06-15T14:01:00.006+02:00</published><updated>2009-06-15T16:30:38.288+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='one-liners'/><title type='text'>Frequently freaky freakin' one-liners</title><content type='html'>So, hey, I'm sitting here without anything good to blog about, probably like most people on the net.&lt;br /&gt;&lt;br /&gt;I'm wondering what daily Perl usage that's even vaguely useful that I do, which could be improved upon.&lt;br /&gt;&lt;br /&gt;Ah, of course, triple-f one-liners!&lt;br /&gt;&lt;br /&gt;As a tool, the perl command often seems to replace a jungle of echo + egrep + cut + tr + sed + awk and whatnot. &lt;code&gt;perl -nawe&lt;/code&gt; and &lt;span style="font-weight:bold;"&gt;ctrl+r&lt;/span&gt; (reverse i-search) in bash are good friends of mine, but after using the same one-liners a few times in a row, I usually end up converting them to tidy files with &lt;code&gt;Getopt::Long&lt;/code&gt;, comments and other insanities.&lt;br /&gt;&lt;br /&gt;And at some stage later, I say to myself: damnit, I should've coded this more generally, I start a recode, get distracted, solve a new problem with one-liners, and the circle of life goes on.&lt;br /&gt;&lt;br /&gt;Do I need professional help?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-3732154188553592643?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/3732154188553592643/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=3732154188553592643' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/3732154188553592643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/3732154188553592643'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/06/frequently-freaky-freakin-one-liners.html' title='Frequently freaky freakin&apos; one-liners'/><author><name>bakkushan</name><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-753668960778118906.post-6901387531929851915</id><published>2009-06-08T12:31:00.011+02:00</published><updated>2009-06-09T02:33:21.462+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='DateTime'/><title type='text'>DateTime performance hit</title><content type='html'>This is mainly in answer to the comment to my previous post on revisiting &lt;b&gt;plog&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;plog&lt;/b&gt; is a piece of code ready for copy+paste into whatever codebase you're in at the moment, and almost completely agnostic. Yes, in code where I'm already using DateTime, then I use those routines.&lt;br /&gt;&lt;br /&gt;You could also create a small sub to hide the "nasty idiom".&lt;br /&gt;&lt;br /&gt;Or you could use Date::Format instead (ca. 10 kB codebase instead of 110 kB, and between one and two orders of magnitude quicker for this particular purpose):&lt;br /&gt;&lt;pre&gt;require Date::Format;&lt;br /&gt;@lt = localtime();&lt;br /&gt;$dt = strftime("%Y-%m-%d %T",\@lt);&lt;/pre&gt;&lt;br /&gt;Of course, that leaves you with the problem of whether the TimeDate packages are installed or not, and another test for that.&lt;br /&gt;&lt;br /&gt;Besides, the bloat is not exactly insignificant if you have code that's running repeatedely.&lt;br /&gt;&lt;br /&gt;The following example with 100,000 repetitions may seem ludicrous, but I actually have production code where timestamped log entries run into that order of magnitude. And yes, I would very much like to save that extra time.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Edit 2009-06-09 00:32 UTC: &lt;/span&gt;thanks to Dave Rolsky for the simplified testing code, and to Ilmari for reminding me of POSIX::strftime, which I'd previously rejected based on other people's claims that it was dog slow. I've removed the home-grown tests in favour of the results from &lt;a href="http://jani.at.ifi.uio.no/tmp/dt-bench"&gt;a slightly modified version&lt;/a&gt; of Dave's sample test script.&lt;br /&gt;&lt;br /&gt;Here are the numbers for 100k iterations, times derived from the rates:&lt;br /&gt;&lt;table border="0" cell-padding="1"&gt;&lt;tr&gt;&lt;th&gt;Solution&lt;/th&gt;&lt;th&gt;Time&lt;/th&gt;&lt;th&gt;Rate&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;DateTime&lt;/td&gt;&lt;td align="right"&gt;490.2 s&lt;/td&gt;&lt;td align="right"&gt;204/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;DateTime (cached tz)&lt;/td&gt;&lt;td align="right"&gt;76.7 s&lt;/td&gt;&lt;td align="right"&gt;1 304/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Date::Format&lt;/td&gt;&lt;td align="right"&gt;6.4 s&lt;/td&gt;&lt;td align="right"&gt;15 528/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;POSIX&lt;/td&gt;&lt;td align="right"&gt;3.3 s&lt;/td&gt;&lt;td align="right"&gt;30 030/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;localtime&lt;/td&gt;&lt;td align="right"&gt;0.6 s&lt;/td&gt;&lt;td align="right"&gt;163 934/s&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-6901387531929851915?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/6901387531929851915/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=6901387531929851915' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/6901387531929851915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/6901387531929851915'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/06/datetime-performance-hit.html' title='DateTime performance hit'/><author><name>bakkushan</name><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>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-753668960778118906.post-2344337942618456452</id><published>2009-06-07T23:24:00.005+02:00</published><updated>2009-06-08T00:02:06.740+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='DateTime'/><title type='text'>Print-and-log revisited</title><content type='html'>A month ago, I made a post with a simple print-and-log subroutine called &lt;span style="font-weight: bold;"&gt;plog&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;I was recently asked two questions about this piece of code, and I'll answer them briefly now:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;"What's up with the curly braces on a separate line after the sub declaration?"&lt;/li&gt;&lt;li&gt;"Why don't you use DateTime?"&lt;/li&gt;&lt;/ol&gt;Okay, those should be easy to answer while retaining the illusion of clue:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;That's merely a personal preference, it quickly aids me in noticing whether something is a subroutine or a control statement block. I am aware that many Perl programmers disagree, and prefer all blocks to start in the same way regardless of what kind of block it is.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;DateTime is an external module which, believe it or not, is &lt;span style="font-weight: bold;"&gt;not&lt;/span&gt; installed on all systems. Some people would also argue that it's bloated and slow. But in case you want to use DateTime instead, and/or check whether it's available run-time, then ... well, see below.&lt;/li&gt;&lt;/ol&gt;&lt;pre&gt;sub plog&lt;br /&gt;{&lt;br /&gt;  my $msg = shift;&lt;br /&gt;  my $level = shift;&lt;br /&gt;  my $dt;&lt;br /&gt;  eval {&lt;br /&gt;    require DateTime;&lt;br /&gt;    $dt = DateTime-&gt;now(time_zone=&gt;'local')-&gt;strftime("%F %T");&lt;br /&gt;  };&lt;br /&gt;  if ($@) {&lt;br /&gt;    my @lt = localtime;&lt;br /&gt;    # Format current datetime manually:&lt;br /&gt;    $dt = sprintf("%d-%02d-%02d %02d:%02d:%02d",&lt;br /&gt;                  $lt[5]+1900,$lt[4]+1,&lt;br /&gt;                  $lt[3],$lt[2],$lt[1],$lt[0]);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;(...)&lt;/pre&gt;As you can see, there isn't much code saved by using DateTime, even if we know it's already installed and don't need to add paranoia. The method of extracting data from localtime() is well-known, proven, and fairly nice on resources. Use DateTime if you want to, but perhaps it's best to save it for when you need to do more complicated stuff.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-2344337942618456452?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/2344337942618456452/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=2344337942618456452' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/2344337942618456452'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/2344337942618456452'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/06/print-and-log-revisited.html' title='Print-and-log revisited'/><author><name>bakkushan</name><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-753668960778118906.post-1201420693835102269</id><published>2009-05-30T01:02:00.003+02:00</published><updated>2009-07-14T23:35:12.746+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='coding style'/><category scheme='http://www.blogger.com/atom/ns#' term='line length'/><title type='text'>Coding styles that make me twitch, part 2</title><content type='html'>I'll make today's post short, because it's all about line length.&lt;br /&gt;&lt;br /&gt;Limiting the length of code lines is something I try to be good at, not because I think the next guy will have a VT100 terminal and needs a friendly piece of code, but because of basic readability.&lt;br /&gt;&lt;br /&gt;When we read an ordinary text, e.g. in a book (you remember books, right?), there is usually quite few characters printed on each line. Here are a few from Douglas Coupland's JPod:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;the door to see that all my new furniture was gone, and my&lt;br /&gt;original furniture hadn't come back. &lt;span style="font-style:italic;"&gt;Fuck.&lt;/span&gt; I phoned Greg,&lt;br /&gt;but realized he was on Cathay Pacific 889, headed to Hong&lt;br /&gt;Kong. I phoned Mom.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Notice how the text area is even narrower than that in this friendly blog?&lt;br /&gt;&lt;br /&gt;This comes from a long tradition in printing, it isn't as if they couldn't have squeezed twice as many words in there, if the print was only smaller. But if the print was smaller, they'd probably make the book narrower as well.&lt;br /&gt;&lt;br /&gt;It's far easier to read something when you don't have to move your eyes around too much from line to line. This is important to both slow and quick readers.&lt;br /&gt;&lt;br /&gt;So, back to coders who make lines of 100+ characters:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;What in friggin' Ruritania&lt;/span&gt; are you thinking? Not much, that's what.&lt;br /&gt;&lt;br /&gt;*GROWL*&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-1201420693835102269?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/1201420693835102269/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=1201420693835102269' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/1201420693835102269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/1201420693835102269'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/05/coding-styles-that-makes-me-twitch-part_30.html' title='Coding styles that make me twitch, part 2'/><author><name>bakkushan</name><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-753668960778118906.post-886411264636138115</id><published>2009-05-22T22:55:00.002+02:00</published><updated>2009-05-22T23:23:31.022+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Quota.pm'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><title type='text'>Querying quotas with Quota.pm</title><content type='html'>I never claimed that this blog would be an exercise in expertise. ;)&lt;br /&gt;&lt;br /&gt;Prerequisites: Unixy OS with quotas enabled, Perl 5.8.8, Quota.pm 1.6.3.&lt;br /&gt;&lt;br /&gt;I always like to provide some sort of progress display for my programs. As a sysadmin, there are times when it might be prudent to check users' files without inspecting them by hand, e.g. when checking for &lt;a href="http://blog.unmaskparasites.com/"&gt;parasitical exploits in websites&lt;/a&gt;. The number of files and/or amount of disk space used seem like reasonable measurements for keeping track of that progress.&lt;br /&gt;&lt;br /&gt;So you &lt;span style="font-weight:bold;"&gt;use Quota;&lt;/span&gt; and get coding, right?&lt;br /&gt;&lt;br /&gt;Except that you may not know beforehand whether you're scanning a local file system, or a remote file system, and Quota.pm requires that you have a magical device identifier before asking what the quota is.&lt;br /&gt;&lt;br /&gt;The manual says that you should do something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;my $r_uid; # User's real UID&lt;br /&gt;my $dev = Quota::getqcarg($directory);&lt;br /&gt;&lt;br /&gt;my @quotadata = Quota::query($dev, $r_uid);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now we've got some nice quota data, in the following order:&lt;br /&gt;&lt;br /&gt;Current blocks used, block soft limit, block hard limit, soft block time limit, current inodes used, inode soft limit, inode hard limit, soft inode time limit.&lt;br /&gt;&lt;br /&gt;But no, there's a catch! If you run this on the local file server, rather than via NFS/RPC, then Quota::query() will barf, because $dev is erroneous. How did that happen?&lt;br /&gt;&lt;br /&gt;Well, Quota::query() doesn't work if the device is local!&lt;br /&gt;&lt;br /&gt;So we have to do this after calling Quota::getqcarg():&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;if ($dev =~ m{^/dev/}) {&lt;br /&gt;    $dev = "127.0.0.1:$directory";&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The irony is then that there appears to be a need for an RPC listener on the loopback device, at least.&lt;br /&gt;&lt;br /&gt;Anyway, I hope this is useful; it helped me to make tings Just Work.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-886411264636138115?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/886411264636138115/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=886411264636138115' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/886411264636138115'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/886411264636138115'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/05/querying-quotas-with-quotapm.html' title='Querying quotas with Quota.pm'/><author><name>bakkushan</name><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-753668960778118906.post-2978780858342395236</id><published>2009-05-15T00:51:00.008+02:00</published><updated>2009-07-14T23:34:59.946+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='coding style'/><title type='text'>Coding styles that make me twitch, part 1</title><content type='html'>We'll see how long this particular series gets.&lt;br /&gt;&lt;br /&gt;I'll try to come up with some example of coding styles that annoy me, and post about it.&lt;br /&gt;&lt;br /&gt;First off is the appended conditional at the end of long one-line Swiss knife code snippets:&lt;br /&gt;&lt;code&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;my @var = sort { length($b) &lt;=&gt; length($a) } split /[-.,_+ ]/ , $input{longvariablename} if defined $input{longvariablename} &amp;amp;&amp;amp; length $input{longvariablename} &gt; 4;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;(Yes, that's supposed to be one line, though it doesn't look like it.)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Please, pretty please, don't append conditionals at the end of long one-liners.&lt;br /&gt;&lt;br /&gt;Really, just don't, m'kaaay.&lt;br /&gt;&lt;br /&gt;Code should, unless it's a one-off one-liner in your shell prompt, be maintainable for others.  "Others" includes yourself some time in the future, when you've forgotten what the (insert mst-inspired expletives here) you were thinking at the time you coded the stuff.&lt;br /&gt;&lt;br /&gt;The above example isn't particularly complex, or difficult to understand, but it's all on one line, and hardly is easy to parse even if you've got that 170 char wide window to code in.&lt;br /&gt;&lt;br /&gt;A few parentheses, a helper variable and a few more lines -- preferably keeping well within 80 columns -- surely won't hurt that badly.&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;pre&gt;&lt;br /&gt;my $lvn = $input{longvariablename};&lt;br /&gt;if (defined $lvn &amp;&amp; length($lvn) &gt; 4) {&lt;br /&gt;    my @var = sort { length($b) &lt;=&gt; length($a) }&lt;br /&gt;              split (/[-.,_+ ]/, $lvn);&lt;br /&gt;}&lt;/pre&gt;&lt;/span&gt;&lt;br /&gt;Of course, these are just my personal opinions, and I won't be knocking on your door with a baseball bat in hand if you don't do as I suggest.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-2978780858342395236?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/2978780858342395236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=2978780858342395236' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/2978780858342395236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/2978780858342395236'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/05/coding-styles-that-makes-me-twitch-part.html' title='Coding styles that make me twitch, part 1'/><author><name>bakkushan</name><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-753668960778118906.post-3653942229592053608</id><published>2009-05-07T03:41:00.006+02:00</published><updated>2009-05-07T03:59:36.788+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><title type='text'>Simple print-and-log subroutine</title><content type='html'>I find that I have a use for this almost all the time. It's a silly little set of subs, but in my role as sysadm, I often need to go back and see what all those printed messages were.&lt;br /&gt;&lt;br /&gt;So here is my not-so-elegant workhorse for when I need to stuff things into logs, and shuffling modules isn't an option. I hope it's useful for someone else, too.&lt;br /&gt;&lt;br /&gt;Dependencies, assumptions and prerequisites:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt; Perl 5-ish&lt;/li&gt;&lt;li&gt;Pre-defined global variables:&lt;ul&gt;&lt;li&gt;   $level - log level (undef = normal, 1 = warn, 2 = die)&lt;/li&gt;&lt;li&gt;   $logfile - a logfile that we can append to&lt;/li&gt;&lt;li&gt;   $msgprefix - a program or subroutine specific prefix&lt;/li&gt;&lt;li&gt;   $verbose - whether to print to STDOUT&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Preferably disabled output buffering&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Usage:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;amp;plog("Log this");&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&amp;amp;plogwarn("Warn about and log this");&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&amp;amp;plogdie("Log this and die");&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The code:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sub plogwarn&lt;br /&gt;{&lt;br /&gt;   my $msg = shift;&lt;br /&gt;   &amp;amp;plog ($msg,1);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;sub plogdie&lt;br /&gt;{&lt;br /&gt;   my $msg = shift;&lt;br /&gt;   &amp;amp;plog ($msg,2);&lt;br /&gt;   exit 1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;sub plog&lt;br /&gt;{&lt;br /&gt;   my $msg = shift;&lt;br /&gt;   my $level = shift;&lt;br /&gt;   my @lt = localtime;&lt;br /&gt;   # Format current datetime sensibly:&lt;br /&gt;   my $dt = sprintf("%d-%02d-%02d %02d:%02d:%02d",&lt;br /&gt;                    $lt[5]+1900,$lt[4]+1,&lt;br /&gt;                    $lt[3],$lt[2],$lt[1],$lt[0]);&lt;br /&gt;   warn "$dt $0: sub plog: No message!\n" unless defined $msg;&lt;br /&gt;   unless (open(F,"&gt;&gt;$logfile")) {&lt;br /&gt;       warn "$dt $0: sub plog: Failed to open logfile ($logfile) for write.\n";&lt;br /&gt;   } else {&lt;br /&gt;       print F "$dt $msgprefix$msg\n";&lt;br /&gt;       close F;&lt;br /&gt;   }&lt;br /&gt;   if ($verbose) {&lt;br /&gt;       unless (defined($level)) {&lt;br /&gt;           print "$dt $msgprefix$msg\n";&lt;br /&gt;       } elsif ($level == 1) {&lt;br /&gt;           warn "$dt $msgprefix$msg\n";&lt;br /&gt;       } elsif ($level == 2) {&lt;br /&gt;           die "$dt $msgprefix$msg\n";&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/753668960778118906-3653942229592053608?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/3653942229592053608/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=3653942229592053608' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/3653942229592053608'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/3653942229592053608'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/05/simple-print-and-log-subroutine.html' title='Simple print-and-log subroutine'/><author><name>bakkushan</name><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-753668960778118906.post-2386724808417944963</id><published>2009-04-30T12:02:00.002+02:00</published><updated>2009-04-30T12:08:48.782+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Schwartz'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 5'/><title type='text'>Schwartzian Transform - Perl 5 vs. Perl 6</title><content type='html'>This isn't quite news, but it's a cool little bit of code anyway.&lt;br /&gt;&lt;br /&gt;Perl 5:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@sorted = map  { $_-&gt;[0] }&lt;br /&gt;          sort { $a-&gt;[1] cmp $b-&gt;[1] }&lt;br /&gt;          map  { [$_, foo($_)] }&lt;br /&gt;               @unsorted;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Perl 6:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@sorted = @unsorted.sort: { .uc };&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I'm willing to claim that Perl 6 makes this a bit more readable, in spite of the smoke, mirrors and curtains.&lt;br /&gt;&lt;br /&gt;Read more about the &lt;a href="http://en.wikipedia.org/wiki/Schwartzian_transform"&gt;Schwartzian Transform in Wikipedia&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-2386724808417944963?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/2386724808417944963/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=2386724808417944963' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/2386724808417944963'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/2386724808417944963'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/04/schwartzian-transform-perl-5-vs-perl-6.html' title='Schwartzian Transform - Perl 5 vs. Perl 6'/><author><name>bakkushan</name><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-753668960778118906.post-3396654756988146861</id><published>2009-04-27T01:02:00.008+02:00</published><updated>2009-04-27T14:03:44.624+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='proto'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><title type='text'>Perl 6 - how to get started</title><content type='html'>Are you curious about Perl 6, and wonder how to get started?&lt;br /&gt;&lt;br /&gt;Use &lt;a href="http://github.com/masak/proto/tree/master"&gt;proto&lt;/a&gt;, &lt;a href="http://masak.org/carl"&gt;Carl Mäsak&lt;/a&gt;'s Perl 6 installer (which will download &lt;a href="http://www.parrot.org/"&gt;parrot&lt;/a&gt; and &lt;a href="http://rakudo.org/"&gt;rakudo&lt;/a&gt; for you).&lt;br /&gt;&lt;br /&gt;Just make sure you have Perl 5 &lt;span style="font-style: italic;font-size:85%;" &gt;(5.8.8 or 5.10.0)&lt;/span&gt;, &lt;a href="http://git-scm.com/download"&gt;git&lt;/a&gt; and &lt;a href="http://subversion.tigris.org/getting.html"&gt;svn&lt;/a&gt; installed first!&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;code&gt;jani@knuth ~/prog/proto &gt;./proto&lt;br /&gt;&lt;br /&gt;*** CONFIG FILE CREATED ***&lt;br /&gt;&lt;br /&gt;Greetings. I have created a file 'config.proto' that you may want to review.&lt;br /&gt;Next time you run './proto', these settings will be used to bootstrap your&lt;br /&gt;system into a working Perl 6 installation.&lt;br /&gt;&lt;br /&gt;If you're new to this, or if configure settings scare you, you probably want&lt;br /&gt;the default settings anyway. The most important ones are:&lt;br /&gt;Rakudo   -&gt; /ping/knuth/home0/jani/prog/rakudo&lt;br /&gt;Projects -&gt; /ping/knuth/home0/jani/prog&lt;br /&gt;&lt;br /&gt;jani@knuth ~/prog/proto &gt;./proto&lt;br /&gt;Downloading Perl 6...downloaded&lt;br /&gt;&lt;b&gt;Building Perl 6...&lt;/b&gt;&lt;/code&gt;&lt;br /&gt;&lt;hr /&gt;This part may take a while; parrot is now building stuff for you, and when it's finished, you can run the perl6 binary:&lt;br /&gt;&lt;hr /&gt;&lt;code&gt;Building Perl 6...built&lt;br /&gt;jani@knuth ~/prog/proto &gt;cd ../rakudo&lt;br /&gt;jani@knuth ~/prog/rakudo &gt;ls -F&lt;br /&gt;CREDITS       MANIFEST  Test.pm  parrot/  perl6.o    perl6_s1.pbc  tools/&lt;br /&gt;Configure.pl  Makefile  build/   perl6*   perl6.pbc  src/&lt;br /&gt;LICENSE       README    docs/    perl6.c  perl6.pir  t/&lt;br /&gt;jani@knuth ~/prog/rakudo &gt;&lt;b&gt;./perl6&lt;br /&gt;&gt; sub sum (*@numbers) { return [+] @numbers; }; say +(sum &amp;lt;1 2 3&amp;gt;)&lt;br /&gt;6&lt;/b&gt;&lt;/code&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;See? Easy! Now get testing!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-3396654756988146861?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/3396654756988146861/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=3396654756988146861' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/3396654756988146861'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/3396654756988146861'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/04/perl-6-how-to-get-started.html' title='Perl 6 - how to get started'/><author><name>bakkushan</name><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-753668960778118906.post-2310023518021761497</id><published>2009-04-21T23:54:00.003+02:00</published><updated>2009-04-21T23:58:30.594+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='Iron Man'/><title type='text'>Enlightened Perl Iron Man Competition</title><content type='html'>Well, if &lt;a href="http://www.shadowcat.co.uk/blog/matt-s-trout/iron-man/"&gt;this isn't inspiring&lt;/a&gt; ...&lt;br /&gt;&lt;br /&gt;This week, I hope to dedicate some time to what I said I was going to do at the NPW 2009 Hackathon, which was to spec complex number representation and presentation.&lt;br /&gt;&lt;br /&gt;Thanks to pmichaud, I've at least confirmed my suspicions on &lt;span style="font-style:italic;"&gt;which parts of the spec&lt;/span&gt; to do my changes in.&lt;br /&gt;&lt;br /&gt;Maybe I fail, maybe I don't, but I think Perl 6 is definitely worth the effort.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-2310023518021761497?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/2310023518021761497/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=2310023518021761497' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/2310023518021761497'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/2310023518021761497'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/04/enlightened-perl-iron-man-competition.html' title='Enlightened Perl Iron Man Competition'/><author><name>bakkushan</name><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-753668960778118906.post-8867424605805090310</id><published>2009-04-19T15:40:00.003+02:00</published><updated>2009-04-21T09:03:38.179+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NPW 2009'/><category scheme='http://www.blogger.com/atom/ns#' term='photo'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='hackathon'/><title type='text'>Group Photos</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_osl3fbyMd28/Sesp-W82oFI/AAAAAAAAARg/aCeBHyo7Yas/s1600-h/9269_NPW_Hackathon_Group.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 166px;" src="http://3.bp.blogspot.com/_osl3fbyMd28/Sesp-W82oFI/AAAAAAAAARg/aCeBHyo7Yas/s320/9269_NPW_Hackathon_Group.jpg" alt="" id="BLOGGER_PHOTO_ID_5326397135585189970" border="0" /&gt;&lt;/a&gt;LR:&lt;br /&gt;&lt;span style="font-size:85%;"&gt;ilmari, nothingmuch, claes, szabgab, krunen, ingy, baest, masak, TimToady, &lt;span style="font-style: italic;"&gt;Ellen&lt;/span&gt;\&lt;br /&gt;trafl, jrockway, batman, pnu, jnthn, pmichaud, abigail, &lt;span style="font-style: italic;"&gt;Gloria&lt;/span&gt;\&lt;br /&gt;mst, sjn, mberends, marcus, sadrak&lt;br /&gt;Photographer: frettled&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_osl3fbyMd28/Sesp-Q6M9JI/AAAAAAAAARY/_CS6pXy9KPw/s1600-h/9263_NPW_Hackathon_Group.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_osl3fbyMd28/Sesp-Q6M9JI/AAAAAAAAARY/_CS6pXy9KPw/s320/9263_NPW_Hackathon_Group.jpg" alt="" id="BLOGGER_PHOTO_ID_5326397133963457682" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;And, finally, &lt;a href="http://blog.ingy.net/2009/04/social-fork.html"&gt;as prompted by Ingy&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_osl3fbyMd28/SesrDHd9I3I/AAAAAAAAARo/0HWhEL6lUgc/s1600-h/9259_NPW_Hackathon_Group.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 174px;" src="http://3.bp.blogspot.com/_osl3fbyMd28/SesrDHd9I3I/AAAAAAAAARo/0HWhEL6lUgc/s320/9259_NPW_Hackathon_Group.jpg" alt="" id="BLOGGER_PHOTO_ID_5326398316840035186" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-8867424605805090310?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/8867424605805090310/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=8867424605805090310' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/8867424605805090310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/8867424605805090310'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/04/group-photos.html' title='Group Photos'/><author><name>bakkushan</name><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><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_osl3fbyMd28/Sesp-W82oFI/AAAAAAAAARg/aCeBHyo7Yas/s72-c/9269_NPW_Hackathon_Group.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-753668960778118906.post-1345112285699800298</id><published>2009-04-19T12:17:00.000+02:00</published><updated>2009-04-19T12:31:30.379+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NPW 2009'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl 6'/><category scheme='http://www.blogger.com/atom/ns#' term='hackathon'/><title type='text'>NPW 2009 Hackathon</title><content type='html'>The &lt;a href="http://www.perlworkshop.no/npw2009/"&gt;NPW 2009&lt;/a&gt; &lt;a href="http://www.perlfoundation.org/perl6/index.cgi?oslo_perl_6_hackaton_2009"&gt;Hackathon&lt;/a&gt; is well into its second day, and I've learned quite a bit about Perl 6 and more about Perl 5 than I expected.&lt;br /&gt;&lt;br /&gt;I didn't originally intend to participate in the Hackathon, and I'm not doing &lt;span style="font-style:italic;"&gt;much&lt;/span&gt;, but it's definitely worth it.&lt;br /&gt;&lt;br /&gt;Yesterday, I stated a goal of adding to &lt;a href="http://svn.pugscode.org/pugs/docs/Perl6/Spec/"&gt;the spec&lt;/a&gt; a description of how complex numbers should be represented and presented, since that was apparently at least partially unclear.&lt;br /&gt;&lt;br /&gt;This lead me into a quagmire of other things I needed to do first, and the "ooh, shiny!" phenomenon lead me astray a few times, ganged up with my general desire to have a functional working environment (Unicode strings in PODs didn't go down well with my current Latin 1-based working environment and the then-installed Perl version), as well as problems getting irssi on my side&lt;br /&gt;But I did get to participate and act as distraction in an entertaining and useful discussion regarding types in Perl 6, as well as host a social dinner for those who wanted a break from the hackathon.&lt;br /&gt;&lt;br /&gt;Today, I'm picking up where I left off, trying to form a mental picture of the spec that's good enough to add and/or change relevants bits of it.&lt;br /&gt;&lt;br /&gt;The rest of the guys are adding code and doing other useful things. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/753668960778118906-1345112285699800298?l=howcaniexplainthis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://howcaniexplainthis.blogspot.com/feeds/1345112285699800298/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=753668960778118906&amp;postID=1345112285699800298' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/1345112285699800298'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/753668960778118906/posts/default/1345112285699800298'/><link rel='alternate' type='text/html' href='http://howcaniexplainthis.blogspot.com/2009/04/npw-2009-hackathon.html' title='NPW 2009 Hackathon'/><author><name>bakkushan</name><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>
