<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress.com" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>lazy-programming &amp;laquo; WordPress.com Tag Feed</title>
	<link>http://en.wordpress.com/tag/lazy-programming/</link>
	<description>Feed of posts on WordPress.com tagged "lazy-programming"</description>
	<pubDate>Sat, 05 Dec 2009 20:38:59 +0000</pubDate>

	<generator>http://en.wordpress.com/tags/</generator>
	<language>en</language>

<item>
<title><![CDATA[Wii vs. iPhone? Or Lazy Developers vs. Giving A Shit?]]></title>
<link>http://ianismoderatelyinteresting.wordpress.com/2009/08/05/wii-vs-iphone-or-lazy-developers-vs-giving-a-shit/</link>
<pubDate>Wed, 05 Aug 2009 00:01:51 +0000</pubDate>
<dc:creator>IanM</dc:creator>
<guid>http://ianismoderatelyinteresting.wordpress.com/2009/08/05/wii-vs-iphone-or-lazy-developers-vs-giving-a-shit/</guid>
<description><![CDATA[I recently read a news story (here) where a &#8220;tell-tale programmer&#8221; talks about the diffi]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I recently read a news story (<a href="http://www.411mania.com/games/news/111982" target="_blank">here</a>) where a &#8220;tell-tale programmer&#8221; talks about the difficulties of developing games for the Wii.</p>
<p>He argues that the Wii&#8217;s lack of processing power &#38; memory in comparison to contemporaries, Xbox 360 &#38; PS3, make it extremely difficult to develop a game that can function on all three systems and stand up (in terms of quality) in it&#8217;s own right.</p>
<p>He even goes as far as to say that Apple&#8217;s iPhone is more powerful than the Wii itself. A contentious statement indeed!</p>
<p>This may be indicative of  software companies and developers slipping into the mindset that <em>more power = better games</em>.</p>
<p>Well, it makes games <em>look </em>nicer, for sure. But if better looks did, in fact, equal better games then most titles for the Xbox 360 and the PS3 would be outstanding. But the truth is, they aren&#8217;t.</p>
<p>In fact, some of them suffer from a lack of imagination and such severe shallow beauty they wouldn&#8217;t even make it as a member of Girls Aloud.</p>
<p>The formula for making better games is no secret and has been known for years. But, while keenly observed by some, it is often foolishly ignored by others; <em>&#8220;better gameplay = better games&#8221;</em>.</p>
<p><!--more--></p>
<p>Ok, so if the iPhone actually <em>is</em>more powerful a gaming platform than the Wii, then that&#8217;s fair enough, but power has never been a selling point for the Wii (or even an issue for most consumers) and to complain of its&#8217; shortcomings in this area is to completely miss the point. Additionally, for a professional games programmer to complain about it is the equivalent of a bad workman blaming his tools.</p>
<p>First of all, the abilities and power of the top three consoles are very different, it&#8217;s not a level playing field and never has been. Nor should it be.</p>
<p>What the Wii lacks in power, it makes up for in innovation. What the Xbox lacks in innovation it makes up for in being the versatile all rounder. And, what the PS3 lack in versatility it makes up for in being cutting edge with it&#8217;s Blu Ray drive &#38; HD options. The fact they&#8217;re different is crucial to their success.</p>
<p>Since Pong &#38; Space Invaders first appeared there&#8217;s never been a time where gaming systems have been equal in terms of power or ability. You quite simply have to tailor your software to fit within the confines of the hardware&#8217;s abilities. If you don&#8217;t want to, then develop and build your own system and best of luck to you.</p>
<p>If it&#8217;s just raw power you want, there&#8217;s always a bigger fish, so to speak. And the biggest fish isn&#8217;t the biggest for very long. Even as recently as the Nintendo Gameboy.</p>
<p>The Gameboy was, on a purely technical level, the least powerful and least advanced of the competing handhelds of the time (SEGA&#8217;s &#8216;Game Gear, ATARI&#8217;s &#8216;Lynx&#8217; and NEC&#8217;s &#8216;Turbo Express&#8217;). What stood it head &#38; shoulders above those technologically superior machines were two important things;</p>
<p>1, software support - it had a ton of great games, and</p>
<p>2, it wasn&#8217;t the most extravagantly powerful or advanced handheld on the market so it was relatively cheap to make and priced competitively.</p>
<p>Complaining about a lack of power or memory in the Wii is like knowing you don&#8217;t like liquorice, eating it anyway and then complaining that it <em>tastes like liquorice</em>. Or, to put it another (more relevant) way, it&#8217;s like taking a hi res picture from your 15 megapixel camera and resizing for the internet at 72DPI - all about scaling and optimisation.</p>
<p>Nintendo have positioned the Wii in the marketplace masterfully. They promote it as a fun console, family friendly, appealing to the &#8216;casual&#8217; gamer and is more interactive than sitting in front of the telly with a control pad. It sells because of innovation (or gimmicks, depending on your point of view), and fun. <em>Not</em> power.</p>
<p>In fact, it&#8217;s great that some developers (Nintendo included) still remember the old school mantra; &#8216;gameplay is king&#8217; and are innovating ways to keep surprising us.</p>
<p>Now, I have nothing against the XBox or PS3, but no amount of full HD, photo-realism, swanky physics engines or fancy lighting/bloom effects (all of which could also be regarded as gimmicks, albeit next gen spangly shiny ones) can disguise a shoddy title and fool the gamer. After all, &#8216;you can&#8217;t polish a turd&#8217;.</p>
<p>Historically, limited hardware has always forced software developers who are willing to push the envelope to improve and innovate rather than just taking a rubbish game, tacking on some fancy bells &#38; whistles (just because they CAN) then selling it based on appearance rather than merit or depth.</p>
<p>A good example of this is the recent &#8216;Ghostbusters&#8217; game&#8230;</p>
<p>It looks great on every platform, but the Wii version was creatively simplified, giving it more of a cartoon appearance (like the old &#8216;Real Ghostbusters&#8217; cartoon) so it would run well on that platform. One size does not fit all and <em>that</em> is the essence of good porting from a high end graphics platform to a limited or less powerful one.</p>
<p>Fueling this lazy &#8216;one size fits all&#8217; approach to programming is the lack of any real platform-exclusivity anymore.</p>
<p>To make as much money as possible for the developer it seems <em>every </em>game has to be released on <em>every</em> platform and, as not all platforms are created equal, the results will vary if developers can&#8217;t be bothered to optimise their titles to play to the strengths of each system.</p>
<p>Back when you had to ask yourself the question &#8221;Will I the NES or will I the Mastersystem?&#8221; or &#8220;Maybe the Megadrive&#8230; or will I the SNES?&#8221;, you faced a straightforward choice over what to expect from your console in terms of power and the games you had access to.</p>
<p>In-house (1st party) developers, like Nintendo&#8217;s and SEGA&#8217;s (back when they still built &#38; sold hardware) have the luxury of being supported by the giant corporate structure of an established hardware manufacturer (albeit on with excellent reputations for games development) and can concentrate on quality rather than rushing out a title to keep debtors from the door.</p>
<p>External (3rd party) developers are much more time and money conscious. They have to focus more on commercial viability and getting a game developed, finished and on the shelves in time for busy buying periods (like Christmas) than unfeasibly long and deep R&#38;D. As a result, quality often suffers and we end up with a glut of underachieving, over-hyped (and usually buggy) games on the shelves. Obviously this isn&#8217;t always the case as 3rd party developers have given us some awesome games recently (Bethesda&#8217;s &#8216;Fallout 3&#8242; and Rockstar&#8217;s &#8216;Grand Theft Auto&#8217; series), but the ratio of hits is disproportionately small when compared to the misses.</p>
<p>If you buy a PS3 now, I&#8217;m pretty sure there&#8217;s only a handful of games you wouldn&#8217;t be able to get on the Xbox, and even then (as with the case of Rockstar games&#8217; &#8216;GTA IV&#8217;) most third party developers will eventually forego the &#8216;exclusivity&#8217; privilege in order to sell more units. It&#8217;s basic business sense to sell you product to the most people as possible.</p>
<p>Unfortunately for the PS3 though, there&#8217;s no single game that is so good, <em>only </em>available on the PS3 and has enough appeal to the masses that those masses would buy the system just to play it. Of course, Sony (manufacturer of the PS3) are battling against their own uncharacteristically poor business decisions too. Instead of a regular (and comparatively cheap) DVD drive, they stuck in an expensive Blu-Ray instead.</p>
<p>Turns out nobody really wants this next gen drive if it costs 50% more than the competitor and thus they priced themselves out of the market. This is especially acute due to, as I mentioned earlier,  most games on the PS3 also being available on the cheaper (and far more popular &#38; well supported)  X-Box.</p>
<p>Also, unlike the PS3, the X-box 360 (if you buy a hard drive for it) is backwardly compatible with (most of) your old games from the original X-Box so you don&#8217;t have to start your (expensive) games collection off from scratch again.</p>
<p>Then there&#8217;s the &#8216;killer app&#8217; phenomenon. Or, in the PS3&#8217;s case; the killer app <em>&#8216;problem&#8217;</em>.</p>
<p>A &#8216;killer app&#8217; is slang for a game that is <em>so </em>good people will buy whatever system it&#8217;s on just to play it and, try as they might, Sony just <em>haven&#8217;t</em> got one for the PS3.</p>
<p>Examples of killer apps for previous Playstation generations were the &#8216;Metal Gear Solid&#8217;, &#8216;Resident Evil&#8217; and &#8217;Gran Turismo&#8217; franchises.</p>
<p>They were not only exclusive to the Playstation but they were <em>so </em>good they were games to buy a Playstation for (killer apps). That seems to have changed this time though as the latest Metal Gear game, &#8216;Guns Of The Patriots&#8217;, while a critical success among hardcore game journalists and similarly hard-core gamers, had its&#8217; initial fire of excitement doused by heavy criticism from non-hardcore franchise fans and the more general gaming media about there being more expositionary cutscenes than actual gameplay (in perhaps another case of programmers making things <em>beautiful </em>rather than <em>fun</em>).</p>
<p>Indeed, the game presents around 30 minutes of relentless opening cinematics before you actually take control and <em>&#8216;do&#8217;</em> something when first starting to play the game. This kind of detachment from the experience may provide plot and drama but it also removes you from having an active role in the game. Not the kind of game to just pick up &#38; play.</p>
<p>Similarly, Gran Turismo (while an excellent driving simulator) is really not a mainstream game either. To get the most out of it, you need to tinker with your car&#8217;s mechanics so much you may as well just study mechanical engineering in <em>real life </em>and make some decent money in F1 instead of staring squinty-eyed at your TV adjusting the slip diff (whatever that is) another few millimetres (if that&#8217;s even how you adjust it) to take corners better.</p>
<p>Resident Evil, while it may have <em>started </em>life as a Playstation exclusive, is now selling itself to anyone with a console and a pad. It&#8217;s also a great example of how game programmers took an existing game and developed it specifically for the Wii by implementing a fantastic control system unique to the system. It then sold bucketloads. Just shows you what brains can do when brawn is out of the equation.</p>
<p>When a genuine killer app <em>does</em> come along (e.g the aforementioned Grand Theft Auto) exclusivity only benefits the hardware manufacturer as the software developer can&#8217;t sell across multiple platforms and thus limiting their audience significantly.</p>
<p>The best killer apps can determine a console&#8217;s success or failure. It may already be too late for the PS3 as sales figures continue to underwhelm and maybe the only good thing to come from it will ultimately be a very hard (and expensive) lesson about how <em>not </em>to sell consoles in future.</p>
<p>As an example of the &#8216;killer app&#8217; in action, the reason I wanted a SNES back in 1992 was because of Super Mario World, the reason I bought an N64 in 1998 was because Goldeneye came with it, I bought a Playstation because of Resident Evil and a Gameboy in the early 90&#8217;s because of Tetris.</p>
<p>The original X-Box had Halo &#38; Halo 2. Those games were so huge and well received that when Halo 3 was announced for the X-Box 360, parting with the cash for the new console became an easy decision for gamers (established and newbies); it was just a means to an end in order to play the latest in the series of a smash hit first person shooter. Indeed, it was so huge on launch day that it made news all over the world and many shops had midnight openings to cater for demand.</p>
<p>Now, all this talk of good games determining the success of a console may seem like a tangent that&#8217;s moved far away from the original point of this piece (and, to be honest, it kinda is), but if &#8216;good games maketh the console&#8217; then &#8216;good gameplay maketh the game&#8217;. And this is what it all comes back to; developers complaining about not enough power from the Wii to make the games good enough.</p>
<p>So, to get back to this original point in the form of a metaphor, would the Ford car company complain about having to design a different engine for a Fiesta after they&#8217;ve finished the engine design for the Focus Coupe Cabriolet? Of course not. There&#8217;s already the understanding that each model, no matter how powerful needs it&#8217;s own engine and that engine is specific to the model operating well within it&#8217;s class.</p>
<p>Instead, this &#8216;tell-tale programmer&#8217; has made that Coupe engine, shoehorned it into the Fiesta with little regard and now blames the Fiesta when its&#8217; gearbox, clutch and suspension can&#8217;t handle it.</p>
<p>As a consumer, we make a choice whether to buy the Coupe or the Fiesta. That choice will probably come down to a matter of budget, expectation and preference. What we expect regardless though is good performance whatever road we drive it on. I don&#8217;t expect to buy a Fiesta and then discover I can&#8217;t drive on the motorway because the engine is too small.</p>
<p>If a software company made the decision to develop games then whatever system they develop for will have limitations. So, instead of doing a bad job then blaming the <em>system </em>for not handling it properly, do it right so the system can run it or don&#8217;t do it at all.</p>
<p>If the Wii can&#8217;t handle it then don&#8217;t release it.</p>
<p>Although, before complaining too much, maybe take a look at some of the excellent Wii games that don&#8217;t seem to struggle with the hardware to produce fantastic results.  Start with Super Mario Galaxy, Guitar Hero, Zelda, Super Smash Brothers, Resident Evil 4 &#38; Lego Star Wars.</p>
<p>Maybe the lure of a lucrative cross-platform cash-in is too much to resist sometimes, but if games that were previously fine on other systems are ruined and your reputation goes downhill along with it, why bother?</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[  Cartoons  @Geo TV]]></title>
<link>http://greenwhiteandtv.wordpress.com/2009/06/29/cartoons-geo-tv/</link>
<pubDate>Mon, 29 Jun 2009 09:24:13 +0000</pubDate>
<dc:creator>teeveejunkie</dc:creator>
<guid>http://greenwhiteandtv.wordpress.com/2009/06/29/cartoons-geo-tv/</guid>
<description><![CDATA[At Geo TV channel we have to go through a very &#8220;yawning &#8221; segment , which is cartoons by]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><div id="previewbody" style="display:block;">At Geo TV channel we have to go through a very &#8220;yawning &#8221; segment , which is cartoons by Zaidi.<br />
This segment is boring as an old record and have no timing or sense of humor behind it.<br />
Dialect, dialogue and script are usually weightless&#8230;Despite some interesting topics there is no punch line or spontaneity in this telecast ever..</div>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Whats Cooking....]]></title>
<link>http://greenwhiteandtv.wordpress.com/2009/04/05/whats-cooking/</link>
<pubDate>Sun, 05 Apr 2009 13:22:02 +0000</pubDate>
<dc:creator>teeveejunkie</dc:creator>
<guid>http://greenwhiteandtv.wordpress.com/2009/04/05/whats-cooking/</guid>
<description><![CDATA[Our midmornings, afternoons, and even nites are filled with dozens of cooking shows on  our cable ch]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><em>Our midmornings, afternoons, and even nites are filled with dozens of cooking shows on  our cable channels&#8230; and we  are only talking about  presented from Pakistani channels&#8230;. we also  have to take BBC, andother food network type cooking shows&#8230;. There is a long list of hosts which are good at cooking and were known lready before this trend started  on tv ,like Rahat on Geo, and Mehboob, andZakir  etc&#8230;</em></p>
<p><em> However most of   these people you will see answering live calls from remote towns    for  ingredients  or   to praise&#8230;some cooking  shows   are promoting healthy food rest is only focusing on &#8230;   Food. . apparently they have too much air time available &#8230; will see whole dish prepared in front of you&#8230;. there is no time restrictions to use elasped time or double dishes to show whole thing finished&#8230;</em></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[They can cook on screen ...]]></title>
<link>http://greenwhiteandtv.wordpress.com/2009/03/02/they-can-cook-on-screen/</link>
<pubDate>Mon, 02 Mar 2009 19:37:40 +0000</pubDate>
<dc:creator>teeveejunkie</dc:creator>
<guid>http://greenwhiteandtv.wordpress.com/2009/03/02/they-can-cook-on-screen/</guid>
<description><![CDATA[Since private TV channels  are on the boom cooking show are a must feature on all of them. Youwill f]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Since private TV channels  are on the boom cooking show are a must feature on all of them. Youwill find every type of  personalities cooking in front of camera , with lots of oil ads  and  pretty anchors.</p>
<p>Shows like cooking with Chef Rahat , or Shai kicked the host out,   these ladies take live calls and cook too.From biryani to Pizza and cake to dal they have every recipe in their sleeve.</p>
<p>Guys are not behind  in this matter. We  are actually pleasantly surprised  to see Pakistan men, trying to cook and be good at it. It seems like a good trend for our  Nation where men  usually don`t get up to get their own glass of water. Chef Zakir, and Mehboob are the most popular among ladies.There this one new programme where they are focusing on desserts , which seems  very useful.</p>
<p>There are two whole  channels devoted to cooking by the name of &#8220;Masala Tv&#8221; and &#8220;Zauq&#8221;.After morning shows you will find chefs on every channel,  and on exclusively  devoted  to food channels too.</p>
<p>How ever there are two things  which are very  confusing&#8230; They do not  taste  what they cook, even their anchors do not try tasting after cooking  is done, which is very  unnatural. Is it some type of Desi conduct ? Code?  At the time of so much modrenity, it is hard to understand that they don&#8217;t show natural  behaviour.</p>
<p>Other thing is they take too much time in live cooking, one can use some things half ready and get on with a dish&#8230; but usually they  spend as much time on screen ,as they actually would do in  their  own kitchens. This is the luxury only TV in Pakistancan provide due to   high ratio of ads. You will see  kids acting like helpers too in  shows  on Wikkid.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Talking ! we are good at.]]></title>
<link>http://greenwhiteandtv.wordpress.com/2009/02/18/talking-we-are-good-at/</link>
<pubDate>Wed, 18 Feb 2009 20:12:33 +0000</pubDate>
<dc:creator>teeveejunkie</dc:creator>
<guid>http://greenwhiteandtv.wordpress.com/2009/02/18/talking-we-are-good-at/</guid>
<description><![CDATA[At time we seem to lose track of &#8221; Talk Shows&#8221; every Pakistani Tv channel is presenting.]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><span style="color:#ff00ff;">At time we seem to lose track of &#8221; Talk Shows&#8221; every Pakistani Tv channel is presenting. If we leave the Serious debate programmes aside , only morning shows are a long list&#8230; from our out spoken Nadia k to Amber w, and Amna, and Ghazal S, then Shaista W and list goes on&#8230; They all run for almost 2 hours and usually compete to blabber most. Thanx to Nadia khan , now it is a trend that you have to be yourself on tv `s expensive airtimne and you playing cute all nation have to take. They all have to be funny and witty and have to ask personal and irrelavent question to their guests. Ratio for women anchors is amazingly high, even established actresses interviewing serious politicians.Marinma k, to Nadia J, and Atiqa O, zQ all joind this band wagon. Then there are &#8220;Golden girls&#8221; who are most hard to swallow.<br />
- Why can`t we keep a balance, between being modren, liberal and being fair we should not try to sell every thing with a pretty face.<br />
- Or on the otherhand some will try to throw paint on billboards and try to ban Tv at once.<br />
- People should get to be anchors, or producers on their special ability to conduct their jobs , on merits, not on their glamour and being a known face .<br />
- This is a kind of reverse discrimination. </span></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Batteries Included: Lazy Lists version 0.3]]></title>
<link>http://dutherenverseauborddelatable.wordpress.com/2008/05/18/batteries-included-lazy-lists-version-03/</link>
<pubDate>Sun, 18 May 2008 18:40:52 +0000</pubDate>
<dc:creator>yoric</dc:creator>
<guid>http://dutherenverseauborddelatable.wordpress.com/2008/05/18/batteries-included-lazy-lists-version-03/</guid>
<description><![CDATA[An updated version of the Lazy List module for OCaml has just been uploaded to Batteries Included an]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p style="text-align:justify;">An updated version of the Lazy List module for OCaml has just been uploaded to <a href="https://forge.ocamlcore.org/frs/?group_id=17">Batteries Included</a> and submitted to <a href="http://www.google.fr/url?sa=t&#38;ct=res&#38;cd=1&#38;url=http%3A%2F%2Fcode.google.com%2Fp%2Focaml-extlib%2F&#38;ei=v3cwSNH2MqPw-AL39cWIAg&#38;usg=AFQjCNEjWtWFbDXOLrRn-qxFA8-MlL8Ikg&#38;sig2=JV6e1hqE0-KmC5HpgwIeWQ">ExtLib</a>. See the release notes for more details.</p>
<p style="text-align:justify;">In addition, I am currently using this module to write a parser combinator library for OCaml. This library has reached early testing stage and will hopefully be added to Batteries Included soon.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Quelques mots de programmation paresseuse]]></title>
<link>http://dutherenverseauborddelatable.wordpress.com/2008/05/11/quelques-mots-de-programmation-paresseuse/</link>
<pubDate>Sun, 11 May 2008 20:20:22 +0000</pubDate>
<dc:creator>yoric</dc:creator>
<guid>http://dutherenverseauborddelatable.wordpress.com/2008/05/11/quelques-mots-de-programmation-paresseuse/</guid>
<description><![CDATA[Ces jours-ci, je travaille beaucoup avec et sur OCaml, que ce soit pour le projet ExtraPol (dont je ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p style="text-align:justify;">Ces jours-ci, je travaille beaucoup avec et sur OCaml, que ce soit pour le projet ExtraPol (dont je finirai bien par vous glisser quelques mots) ou pour <a href="https://forge.ocamlcore.org/mail/admin/index.php?group_id=17">Batteries Included</a> (la rénovation en cours de la bibliothèque standard de OCaml). En particulier, je viens de finaliser un module de <a href="https://forge.ocamlcore.org/frs/shownotes.php?release_id=12">gestion des listes paresseuses</a>. Paresseuses ? Oui, paresseuses.</p>
<p style="text-align:justify;">Attardons-nous un moment sur le concept de <em>paresse</em> en programmation.</p>
<p><!--more--></p>
<h2>En Java (ou C++ ou C# ou &#8230;)</h2>
<p style="text-align:justify;">Presque tous les langages de programmation permettent, de manière restreinte, de définir des expressions paresseuses, c&#8217;est-à-dire des expressions dont le résultat n&#8217;est calculé que s&#8217;il peut influencer l&#8217;exécution du programme. Ainsi, en Java, nous pourrons définir la méthode <code>isEquals</code> suivante :</p>
<pre class="brush: java;">
bool isEquals(Object x)
{
  return x &amp;&amp; x.equals(myObject);
}
</pre>
<p style="text-align:justify;">Ici, au cours de l&#8217;exécution de cette fonction, <code>x.equals(myObject)</code> ne sera ffectivement évalué que si <code>x</code> n&#8217;est pas <code>null</code>. Java définit ainsi trois opérateurs paresseux <code>&#38;&#38;</code>, <code>&#124;&#124;</code> et <code>?:</code> : dans chacun des trois cas, à l&#8217;exécution du programme, la première opérande est évaluée avant de décider que faire de la deuxième (et de la troisième, dans le cas de <code>?:</code>). Ces constructions sont très utiles, mais sont loin de couvrir toutes les circonstances dans lesquelles la paresse peut s&#8217;avérer utile.</p>
<p style="text-align:justify;">Ainsi, imaginons un instant que nous souhaitons écrire une bibliothèque de journalisation, dont le rôle est d&#8217;enregistrer des messages dans un fichier au fur et à mesure de l&#8217;exécution du programme. Ajoutons une contrainte : les messages ne doivent être effectivement enregistrés que lorsque le journal est activé, par exemple parce que l&#8217;utilisateur est en mode de débogage :</p>
<pre class="brush: java;">
void log(String s)
{
   if(LOG) stream.println(s);
}
</pre>
<p>La méthode <code>log</code> sera typiquement invoquée des centaines de fois durant l&#8217;exécution du code, sous la forme suivante :</p>
<pre class="brush: java;">
void myFunction(int i, int j, int k)
{
   myLog.log(&quot;Entering myFunction(&quot;+i+&quot;, &quot;+j+&quot;, &quot;+j+&quot;)&quot;);
   //...
   myLog.log(&quot;Leaving myFunction()&quot;);
}
</pre>
<p style="text-align:justify;">Des centaines de fois, nous aurons donc besoin de calculer le résultat de <code>"Entering myFunction("+i+", "+j+", "+j+")"</code>, soit trois conversions d&#8217;entiers en chaînes de caractères, 6 concaténations de chaînes de caractères et un gaspillage de mémoire vive que nous pourrions éviter lorsque <code>LOG</code> est <code>false</code>. Comment faire pour éviter ce gaspillage ? La première possibilité consiste à exposer la valeur de <code>LOG</code> à tout le programme et à laisser le programmeur écrire plutôt</p>
<pre class="brush: cpp;">
void myFunction(int i, int j, int k)
{
   if(LOG) myLog.log(&quot;Entering myFunction(&quot;+i+&quot;, &quot;+j+&quot;, &quot;+j+&quot;)&quot;);
   //...
   if(LOG) myLog.log(&quot;Leaving myFunction()&quot;);
}
</pre>
<p style="text-align:justify;">Malheureusement, cette transformation nous oblige à contaminer tout le programme avec ce champ <code>LOG</code>, au détriment de la lisibilité et de l&#8217;extensibilité. En C ou C++, on pourrait cacher ce <code>LOG</code> derrière une macro, cette fois au détriment du débogage, de la modularité et de la robustesse. En Java, si nous n&#8217;avons pas une telle possibilité, nous pouvons utiliser des classes anonymes  pour arriver aux mêmes fins :</p>
<p>Commençons par modifier notre bibliothèque de journalisation :</p>
<pre class="brush: java;">
public interface LazyString
{
   public String toString();
}

void log(Object s)
{
   if(LOG) stream.println(s.toString());
}
</pre>
<p style="text-align:justify;">L&#8217;interface LazyString n&#8217;est guère contraignante : elle se contente de promettre que les objets qui l&#8217;implantent dispoent bien d&#8217;une méthode publique String toString(), qui servira à extraire de l&#8217;objet une chaîne de caractères. La différence avec ce qui précède est que nous pouvons nous débrouiller pour que la construction de la chaîne de caractères n&#8217;ait lieu qu&#8217;au moment où la méthode println est invoquée. En particulier, cette construction n&#8217;aura jamais lieu si <code>LOG</code> est false. Pour utiliser cette nouvelle version du journal, nous pourrons réécrire myFunction de la manière suivante :</p>
<pre class="brush: java;">
void myFunction(int i, int j, int k)
{
   myLog.log(new LazyString() { public String toString() { return &quot;Entering myFunction(&quot;+i+&quot;, &quot;+j+&quot;, &quot;+j+&quot;)&quot; });
   //...
   myLog.log(&quot;Leaving myFunction()&quot;);
}
</pre>
<p style="text-align:justify;">Est-ce la fin de l&#8217;histoire ? Pas tout à fait. Pour le moment, en Java, nous ne pouvons pas améliorer la syntaxe lors de l&#8217;appel de <code>log</code> &#8212; en tant que langage, Java est connu pour sa lourdeur syntaxique. En l&#8217;absence d&#8217;un préprocesseur digne de ce nom, nous ne pourrons rien faire de ce côté-là. Par contre, nous pouvons nous attaquer à un autre problème, qui se posera dès que nous serons confrontés à une méthode <code>log</code> à peine peu plus complexe :</p>
<pre class="brush: java;">
void log(Object s)
{
   if(LOG_TO_FILE) file_stream.println(s.toString());
   if(LOG_TO_WINDOW) text_pane.out.println(s.toString());
   if(LOG_TO_STATUSBAR) statusbar.setText(s.toString());
}
</pre>
<p style="text-align:justify;">Ici, <code>s.toString()</code> sera invoqué trois fois et calculera trois fois le même résultat. Pour un exemple aussi simple que le nôtre, ce n&#8217;est pas encore bien grave, mais on peut imaginer des contextes dans lesquels le calcul serait suffisamment long pour que ce délai soit inacceptable.</p>
<p style="text-align:justify;">Qu&#8217;à cela ne tienne, il suffit de réécrire <code>log</code> de manière à retenir la valeur de <code>s.toString()</code>. Voire mieux, nous pouvons encapsuler tout ceci dans une classe plus générique :</p>
<pre class="brush: java;">
public interface Result&lt;T&gt;
{
   public T getValue();
}
public abstract class Lazy&lt;T&gt;
{
   private boolean computed = false;
   private T value = null;
   /**
    * Proceeds to the actual computation.
    * This method will only be called once.
    */
   protected abstract T value();
   public final synchronized T getValue()
   {
      if(computed == false)
      {
        value       = value();
        computed = true;
      }
      return value;
   }
}

public abstract class LazyString extends Lazy&lt;String&gt;
{
   public String toString()
   {
      return this.getValue();
   }
}
</pre>
<p>En modifiant <code>myFunction</code> pour utiliser cette nouvelle version de <code>LazyString</code>, nous obtenons :</p>
<pre class="brush: java;">
void myFunction(int i, int j, int k)
{
   myLog.log(new LazyString() { protected String value() { return &quot;Entering myFunction(&quot;+i+&quot;, &quot;+j+&quot;, &quot;+j+&quot;)&quot; });
   //...
   myLog.log(&quot;Leaving myFunction()&quot;);
}
</pre>
<p style="text-align:justify;">Qu&#8217;avons-nous gagné ? Nous avons maintenant sous la main une interface Result&#60;T&#62; qui permet de représenter une opération. Si l&#8217;objet qui implante Result&#60;T&#62; est en fait un Lazy&#60;T&#62;, le calcul ne sera effectué que si son résultat est effectivement consulté. Si le résultat est consulté plusieurs fois (potentiellement par plusieurs threads différents), le calcul n&#8217;est toujours effectué qu&#8217;une seul fois.</p>
<p style="text-align:justify;">Nous venons d&#8217;ajouter une dose d&#8217;évaluation paresseuse à Java.</p>
<p style="text-align:justify;">Pour aller plus loin, regardons du côté de la programmation fonctionnelle &#8212; et des structures de données paresseuses.</p>
<h2>Du côté de la programmation fonctionnelle</h2>
<p>Commençons par réécrire en OCaml la première version de nos fonctions :</p>
<pre class="brush: python;">
let log s = if should_log then output stream s
</pre>
<p style="text-align:justify;">Nous venons de définir, comme en Java, une fonction nommée log, qui accepte comme paramètre un argument s &#8212; ici, une chaîne de caractères. Le contenu de la fonction log instruit d&#8217;écrire s sur un certain flux stream, si une certaine valeur booléenne should_log est vraie. Comme en Java, nous invoquerons cette fonction depuis my_function, à l&#8217;aide de :</p>
<pre class="brush: python;">
let my_function i j k =
  log (sprintf &quot;Entering my_function %i %i %i&quot; i j k);
  (* ... *)
  log &quot;Leaving my_function&quot;
</pre>
<p style="text-align:justify;">Jusque-là, à part les parenthèses et l&#8217;utilisation de la fonction <code>sprintf</code>, rien de bien différent. De nouveau, il est nécessaire de convertir i, j et k en chaînes de caractères et de procéder à quelques concaténations.</p>
<p style="text-align:justify;">À partir d&#8217;ici, comme en Java, nous pouvons définir équivalent de Lazy&#60;T&#62;, que nous appellerions probablement <code>'a lazy</code>, doté d&#8217;un constructeur qui acceptera en argument une fonction dont le résultat est un <code>'a</code>, etc. La transformation de notre code pour convertir log en appel paresseux est globalement similaire à ce que nous ferions en Java. De fait, tout ceci n&#8217;est pas nécessaire puisque puisque la programmation paresseuse est en fait une primitive du langage. Le mot-clé <code>lazy</code> introduit une expression de type <code>'a Lazy.t</code>, c&#8217;est-à-dire dont le résultat est de type <code>'a</code> et ne sera calculé que s&#8217;il est nécessaire. La fonction <code>force : 'a Lazy.t -&#62; 'a</code> permet alors de consulter le résultat d&#8217;une valeur ainsi mise en réserve, en la calculant au passage si nécessaire. De fait, notre version définitive ressemblera à</p>
<pre class="brush: python;">
open Lazy
let log s =
  if should_log_1 then output stream_1 (force s);
  if should_log_2 then output stream_2 (force s);
  if should_log_3 then output stream_3 (force s)

let my_function i j k =
  log (lazy (sprintf &quot;Entering my_function %i %i %i&quot; i j k));
  (* ... *)
  log (lazy &quot;Leaving my_function&quot;)
</pre>
<p style="text-align:justify;">Notons au passage qu&#8217;il ne serait pas possible de réécrire directement lazy sous la forme d&#8217;une fonction OCaml. Pour réinventer <code>lazy</code>, il serait nécessaire de passer par Camlp4 ou d&#8217;accepter des notations légèrement plus lourdes.</p>
<h2>Et alors ?</h2>
<p style="text-align:justify;">Il va falloir que je vous avoue quelque chose : je me moque complètement de la fonction <code>log</code>. Dans la programmation paresseuse, le plus intéressant, c&#8217;est bien les structures de données.</p>
<p>Tenez, en Java, nous pouvons très bien redéfinir la notion d&#8217;itérateurs de la manière suivante :</p>
<pre class="brush: java;">
public interface MyIterator&lt;T&gt;
{
  public Lazy&lt;MyIterator&lt;T&gt;&gt; next();
  public T value;
}
</pre>
<p>Un itérateur est ici un objet capable de contenir une valeur&#8230; et de renvoyer un autre itérateur, qui représente la suite de l&#8217;itération. On écrira de même en OCaml :</p>
<pre class="brush: python;">
type 'a my_iterator = Iterator of 'a * 'a my_iterator Lazy.t
</pre>
<p>Complétons cette définition pour nous autoriser à construire des itérations <em>finies</em> :</p>
<pre class="brush: python;">
type 'a node =
 &amp;#124; Nil
 &amp;#124; Cons of 'a * 'a lazy_list
type 'a lazy_list = ('a node) Lazy.t
</pre>
<p style="text-align:justify;">Nous venons de définir la notion de <em>liste paresseuse</em>. Une liste paresseuse est une valeur paresseuse qui, une fois évaluée, produit soit le résultat <code>Nil</code> (la liste vide), soit un résultat de la forme <code>Cons(h, t)</code> où <code>h</code> est une valeur et <code>t</code> est la suite de la liste paresseuse.</p>
<p style="text-align:justify;">À partir de cette définition, nous pouvons construire une fonction <code>range</code>, qui servira à représenter un intervalle d&#8217;entiers :</p>
<pre class="brush: python;">
let rec range i j =
 if i &gt;= j then Nil
 else            range (i+1) j
</pre>
<p>Ainsi, en OCaml, <code>range 0 100000</code> calculera les nombres 0, 1, &#8230;, 100000 au fur et à mesure qu&#8217;ils seront demandés.</p>
<p style="text-align:justify;">À partir de là, nous pouvons définir les transformations habituelles sur les structures de données. Ainsi, pour convertir (paresseusement) une liste paresseuse en une autre, comme pour les listes habituelles, nous pouvons définir la fonction <code>map</code> :</p>
<pre class="brush: python;">
let rec map f l = match force l with
  &amp;#124; Nil            -&gt; lazy Nil
  &amp;#124; Cons (h,t) -&gt; lazy Cons (f h, map f t)
</pre>
<p style="text-align:justify;">Cette fonction <code>map</code>, qui sera l&#8217;un des premiers outils que nous placerons dans notre bibliothèque de gestion des listes paresseuses, applique une fonction successivement à chaque élément d&#8217;une liste paresseuse, de manière à obtenir une nouvelle liste paresseuse. Pour doubler tous les éléments de notre intervalle précédent, nous écrirons donc</p>
<pre class="brush: python;">
map (( * ) 2) (range 0 100000)
</pre>
<p style="text-align:justify;">De la même manière, nous pouvons définir le nécessaire pour filtrer les éléments d&#8217;une liste afin de n&#8217;en garder que ceux qui vérifient une propriété donnée, le tout sous la forme d&#8217;une fonction <code>filter</code>, qui rejoindra <code>map</code> dans notre bibliothèque standard.</p>
<pre class="brush: python;">
let rec filter f l = match Lazy.force l with
  &amp;#124; Nil -&gt; lazy Nil
  &amp;#124; Cons(h,t) -&gt; lazy (Cons (f h, filter t))
</pre>
<p style="text-align:justify;">Et à ce prix-là, définissons une fonction <code>iter</code>, tout aussi standard, qui nous permettra d&#8217;appliquer une fonction impérative à tous les éléments d&#8217;une liste paresseuse, de la même manière que la boucle for de Python ou la nouvelle boucle for de Java :</p>
<pre class="brush: python;">
let rec iter f l = match force l with
  &amp;#124; Nil            -&gt; ()
  &amp;#124; Cons (h,t) -&gt; f h; iter t
</pre>
<p style="text-align:justify;">En combinant tout ce qui précède, nous pouvons faire afficher les carrés parfaits de l&#8217;ensemble des nombres pairs des nombres de l&#8217;intervalle [0; 100000].</p>
<pre class="brush: python;">
let is_square x =
  let y = int_of_float (sqrt (float_of_int x)) in
  x = y * y

iter print_int (filter is_square (map (( * ) 2) (range 0 100000)))
</pre>
<p style="text-align:justify;">Comme la liste n&#8217;est consultée qu&#8217;une seule fois, grâce à la magie de la paresse et du ramasse-miettes, tout ceci se fera fait sans avoir à allouer la mémoire vive nécessaire pour retenir tous les entiers entre 0 et 100000.</p>
<p style="text-align:justify;">Jusqu&#8217;ici, toutes les opérations que nous avons vues auraient pu être implantées, peut-être avec quelques difficultés, en utilisant des <em>itérateurs</em> ou des <em>générateurs</em>, tels que ceux que définissent les bibliothèques Java, C#, JavaScript, Python, OCaml etc. Tout comme les listes paresseuses, les itérateurs et générateurs permettent de représenter des suites d&#8217;informations qui ne seront effectivement calculées que lorsqu&#8217;elles seront effectivement consultées. Mais à la différence des listes paresseuses, les itérateurs/générateurs oublient les informations immédiatement après les avoir fournies. Si les itérateurs et générateurs sont très utiles &#8212; et probablement plus optimisés que les listes paresseuses pour les exemples précédents &#8212; leur champ d&#8217;application s&#8217;arrête dès que les données peuvent être utilisées plusieurs fois.</p>
<p style="text-align:justify;">Ainsi, considérons l&#8217;une des applications majeures des itérateurs/générateurs et des listes paresseuses : l&#8217;analyse de langages, et plus particulièrement l&#8217;analyse lexicale et syntaxique d&#8217;un code source. Le plus fréquemment, on commence par considérer le fichier d&#8217;entrée comme un itérateur/générateur de caractères. Un filtre, l&#8217;<em>analyseur lexical</em>, s&#8217;applique alors à cet itérateur pour le transformer en itérateur de <em>lexèmes</em> &#8212; c&#8217;est le rôle d&#8217;outils tels que Lex, Flex ou, aussi surprenant que cela puisse paraître, Sax. Ce deuxième itérateur est alors consommé par un <em>analyseur syntaxique</em>, dont le rôle est de produire un arbre de syntaxe abstraite, qui représentera le code source en mémoire vive &#8212; c&#8217;est, cette fois, le rôle d&#8217;outils tels que Bison, Yacc ou DOM. Ces derniers, ainsi que [presque tous] leurs concurrents, consultent à l&#8217;avance k lexèmes depuis l&#8217;itérateur de lexème, pour un certain k fixé lors de la conception de l&#8217;analyseur, émettent des hypothèses en partant de ces k lexèmes, et ne peuvent pas revenir en arrière, en cas d&#8217;erreur, de plus de k pas. À l&#8217;inverse, et de manière très schématique, les combinateurs de parseurs construits sur des listes paresseuses, tels que Parsec (pour Haskell) ou PLC (pour OCaml), ne sont pas limités par ces k lexèmes d&#8217;avance, puisqu&#8217;ils peuvent à volonté revenir en arrière dans la liste. Un élément ne disparaît de la liste paresseuse que lorsque sa valeur ne peut plus influencer l&#8217;exécution du programme. Cette conception à base de listes paresseuses se paye en termes de performances et de consommation de mémoire mais offre beaucoup plus de flexibilité, notamment la possibilité de construire ou de modifier dynamiquement des analyseurs syntaxiques.</p>
<p style="text-align:justify;">Avant de conclure sur la comparaison entre itérateurs et listes paresseuses, précisons brièvement qu&#8217;il est aisé de construire l&#8217;un par-dessus l&#8217;autre : un itérateur est une liste paresseuse qui oublie ses éléments au fur et à mesure qu&#8217;ils sont consommés, alors qu&#8217;une liste paresseuse est un itérateur qui retient ses éléments jusqu&#8217;à intervention du ramasse-miettes. Ainsi, dans la bibliothèque sur laquelle je travaille, la conversion d&#8217;une liste paresseuse en itération s&#8217;est écrite, jusqu&#8217;à une récente optimisation :</p>
<pre class="brush: python;">
let enum l =
  let reference = ref l in
    Enum.from (fun () -&gt; match next !reference with
			 &amp;#124; Cons(x,t) -&gt; reference := t; x
			 &amp;#124; Nil          -&gt; raise Enum.No_more_elements )
</pre>
<p style="text-align:justify;">Dans cet extrait de code, nous commençons par déclarer une variable modifiable nommée <code>reference</code> et qui désignera initialement le premier élément de la liste. Nous définissons alors une fonction anonyme qui, lorsqu&#8217;elle sera appelée, renverra l&#8217;élément actuel désigné par <code>reference</code>, ou, si nous avons dépassé la fin de la liste, lancera une exception <code>Enum.No_more_elements</code> pour signaler que l&#8217;itérateur est terminé. La fonction <code>Enum.from</code> construit l&#8217;itérateur dont le comportement est donné par cette fonction.</p>
<p style="text-align:justify;">À l&#8217;inverse, pour convertir un itérateur en liste paresseuse, nous employons la fonction suivante :</p>
<pre class="brush: python;">
let of_enum e =
  let rec aux () =
    lazy (match Enum.get e with
      &amp;#124;	Some x -&gt; Cons (x, aux () )
      &amp;#124; None    -&gt; Nil )
  in aux ()
</pre>
<p style="text-align:justify;">Dans l&#8217;extrait, nous commençons par définir une boucle que nous nommons <code>aux</code> et dons le contenu est paresseux. À chaque fois qu&#8217;un nouvel élément de la liste est consulté, nous consommons la valeur du prochain élément de notre itérateur. Si celui-ci existe, nous l&#8217;appelons <code>x</code>, et ce <code>x</code> constitue le prochain élément de notre liste, tandis que la suite de la liste sera donnée par le résultat de la prochaine invocation de la boucle <code>aux</code>. Dans le cas contraire, la liste est terminée.</p>
<h2>Références :</h2>
<ul>
<li>Pour plus de détails sur la distinction entre générateurs, itérateurs et listes paresseuses, je vous invite à consulter <a href="http://home.pipeline.com/~hbaker1/Iterator.html">Iterators: Signs of Weakness in Object-Oriented Languages, par Henry G. Baker</a>.</li>
<li>Pour plus de détails sur le module de listes paresseuses de Batteries Included, le code source est disponible <a href="https://forge.ocamlcore.org/frs/shownotes.php?release_id=12">sur OCaml Forge</a>. Le code source du module Enum, qui définit des itérateurs pour OCaml, est disponible avec le reste de la bibliothèque ExtLib, <a href="http://code.google.com/p/ocaml-extlib/">sur Google Code</a>.</li>
<li>Pour plus de détails sur la programmation paresseuse en OCaml, le <a href="http://caml.inria.fr/pub/docs/manual-ocaml/libref/Lazy.html">guide de référence</a> est à votre disposition.</li>
<li>Enfin, rendons à César ce qui appartient à César. Si l&#8217;évaluation paresseuse vous intéresse, vous êtes vivement encouragés à vous informer sur le langage de programmation Haskell, dans lequel toutes les évaluations sont paresseuses par défaut.</li>
</ul>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Batteries Included Preview: Lazy Lists]]></title>
<link>http://dutherenverseauborddelatable.wordpress.com/2008/05/10/batteries-included-preview-lazy-lists/</link>
<pubDate>Sat, 10 May 2008 20:17:47 +0000</pubDate>
<dc:creator>yoric</dc:creator>
<guid>http://dutherenverseauborddelatable.wordpress.com/2008/05/10/batteries-included-preview-lazy-lists/</guid>
<description><![CDATA[A quick note to inform that I have made available the first preview of a module for OCaml Batteries ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p style="text-align:justify;">A quick note to inform that I have made available the first preview of a  module for OCaml Batteries Included module: Lazy Lists for OCaml. This module adds the ability to manipulate lists composed of elements which are only computed whenever their value is first needed. In particular, such lists may be used as a more powerful replacement for streams &#8212; or to port interesting algorithms from Haskell.</p>
<p style="text-align:justify;">Code may be found <a href="https://forge.ocamlcore.org/frs/download.php/13/lazy_lists_0_2.tgz">here</a>.</p>
</div>]]></content:encoded>
</item>

</channel>
</rss>
