<?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-3887060946333002264</id><updated>2011-12-09T21:57:56.682-08:00</updated><category term='mobile'/><category term='linux'/><category term='spread betting'/><category term='scheme'/><category term='Ecology'/><category term='Java'/><category term='forex'/><title type='text'>Andrew Whaley's blog</title><subtitle type='html'>A blog on various stuff that interests me which is mostly the Scheme programming language at the moment.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://andrewwhaley.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://andrewwhaley.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Andrew Whaley</name><uri>http://www.blogger.com/profile/05346078852977103014</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>12</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3887060946333002264.post-1734767467064537849</id><published>2011-07-31T12:20:00.000-07:00</published><updated>2011-07-31T12:50:31.025-07:00</updated><title type='text'>Upgrading from Mac OS X Snow Leopard with PGP to OS X Lion</title><content type='html'>I have just been through a world of pain upgrading from Snow Leopard with PGP Whole Disk Encryption to Mac OS X Lion with FileVault whole disk encryption. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Anyone who uses a Mac within a financial institution and many others will be required to use some form of whole disk encryption. Until Lion was released, the only option was PGP WDE version 10 and above. Unfortunately PGP never seems to be compatible with the latest OS updates like 10.6.8 so you are prevented from updating hence my desire to get off PGP and use FileVault2 built into Lion. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;PGP advise against upgrading to Lion because, low and behold, it's incompatible but it can be done by following these steps :-&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1. Decrypt your hard drive with PGP (takes several hours),&lt;/div&gt;&lt;div&gt;2. Uninstall PGP,&lt;/div&gt;&lt;div&gt;3. Remove your EFI password if you have one set,&lt;/div&gt;&lt;div&gt;4. Backup your data (although not strictly needed, it would be imprudent not to),&lt;/div&gt;&lt;div&gt;5. Use Boot Camp assistant to create the minimum 20GB Windows partition - see why below,&lt;/div&gt;&lt;div&gt;6. Without installing Windows, use boot camp assistant to remove the Windows partition you just created !&lt;/div&gt;&lt;div&gt;7. Purchase and download the Lion installer but don't run it !&lt;/div&gt;&lt;div&gt;8. In the installer.app file, show contents and then use Disk Utility to burn the InstallESD.dmg file to a blank DVD - this gives you a bootable Lion install DVD which you may need later.&lt;/div&gt;&lt;div&gt;9. Install Lion by running the installer from your hard disk.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Steps 5 and 6 seem pointless but these are necessary in order to replace the Master Boot Record on your hard disk which PGP has polluted and which prevents Lion from installing it's recovery partition. Without the recovery partition you cannot install FileVault and you also cannot fix the very common Lion login problem where none of your accounts are migrated so you cannot login post install !&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After install you should have Lion installed and with luck the recovery partition is installed. There is a good chance that you can't login at this stage so you need to boot from the recovery partition by holding down Cmd-R or Alt during boot up. If this doesn't work and you are presented with the login box again then you have no recovery partition and you'll need to boot from the DVD by holding down the Alt key with the DVD in the drive.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Once in recovery, start a terminal and type 'resetpassword' and then select the root user and set a password. Reboot and login as root and then recreate your accounts using the same home directories and you won't have lost any data. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you don't have a recovery partition, try steps 5 and 6 again and then reinstall from the DVD - your data should still be there afterwards.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Once installed with the recovery partition, setup up FileVault from the Preferences / Security menu and you'll have no future need of PGP or any need to fear software updates. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3887060946333002264-1734767467064537849?l=andrewwhaley.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrewwhaley.blogspot.com/feeds/1734767467064537849/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andrewwhaley.blogspot.com/2011/07/upgrading-from-mac-os-x-snow-leopard.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/1734767467064537849'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/1734767467064537849'/><link rel='alternate' type='text/html' href='http://andrewwhaley.blogspot.com/2011/07/upgrading-from-mac-os-x-snow-leopard.html' title='Upgrading from Mac OS X Snow Leopard with PGP to OS X Lion'/><author><name>Andrew Whaley</name><uri>http://www.blogger.com/profile/05346078852977103014</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3887060946333002264.post-4786742667626344940</id><published>2009-08-21T00:13:00.000-07:00</published><updated>2009-08-24T01:48:55.489-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mobile'/><title type='text'>Symbian is dead, long live Linux</title><content type='html'>I've always been a huge fan of mobile computing devices and thought that the Psion palmtop computers of the 1990's and early 2000's represented the best in practical design that could be achieved in this format.&lt;br /&gt;&lt;br /&gt;Psion pioneered the Symbian operating system that was used on their Series 5 devices but was also popular on many high end smartphones from Nokia and Sony-Ericsson. One of my favourite devices was the &lt;a href="http://en.wikipedia.org/wiki/Psion_Revo"&gt;Psion Revo&lt;/a&gt; as this was the perfect combination of small size but with a usuable keyboard and screen. Being launched in 1999, it was groundbreaking for the time but with only 8MB of storage, a 30MHz ARM processor and no connectivity, it is of limited use in today's media rich and connected world.&lt;br /&gt;&lt;br /&gt;After the Psion my next device was a &lt;a href="http://en.wikipedia.org/wiki/Sony_Ericsson_P910"&gt;Sony-Ericsson P910i&lt;/a&gt;, this is a smartphone also running Symbian but this time with GPRS connectivity, bluetooth, 96MB internal memory and expandable upto 1GB using memory stick pro duo. This was a great piece of kit that offered media, a web browser (Opera) and the usual PDA type functions with great handwriting recognition. I also used this with a separate bluetooth GPS receiver and TomTom Mobile software as a SatNav for the car. The P910 did pretty much everything the iPhone does but 4 years earlier, it's clunky by comparison and is showing it's age now.&lt;br /&gt;&lt;br /&gt;Alas, times move on and the P910i suffers from a dated browser that doesn't support Ajax, Flash and many other modern features and connectivity is limited to GPRS which is slow and expensive. So it was time to upgrade but to what ?&lt;br /&gt;&lt;br /&gt;The obvious choice is the iPhone but at around £600 (£100 purchase + £30/month) this is a serious outlay on a toy. Also, the browser doesn't support Flash or Java and the development tools are all closed. Furthermore you can't develop on it unless you have a Mac (another £1000 outlay for a computer worth £400 !) and you can't distribute your software unless Apple approves it. There's the Ipod Touch as a cheaper alternative but this has no GPS and still suffers from the closed development environment. So this option is ruled out for me.&lt;br /&gt;&lt;br /&gt;Next consideration are the Google Android phones like the &lt;a href="http://www.htc.com/www/product/hero/overview.html"&gt;HTC Hero &lt;/a&gt;which is a much better proposition. Under the covers they run a cut down Linux OS but with a Google Java based application environment on top. The browser supports Flash and Java. Development tools are freely available and there is no restriction on distributing software which is written in Java. Sounds a good option but, it's still expensive at £30/month (£540 for minimum 18 month contract).&lt;br /&gt;&lt;br /&gt;So what did I go for, neither. It turns out that &lt;a href="http://www.expansys.co.uk/"&gt;Expansys &lt;/a&gt;were flogging off the &lt;a href="http://en.wikipedia.org/wiki/Nokia_N810"&gt;Nokia N810 &lt;/a&gt;cheap to make way for the new model which is due out imminently. The N810 is marketted is an 'Internet Tablet' by Nokia but it is closer in function to the original Psion palmtops than to modern smartphones but was perfect for my needs with :-&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Linux OS,&lt;/li&gt;&lt;li&gt;128MB RAM + 2GB internal storage + expandable upto 32GB through MiniSD,&lt;/li&gt;&lt;li&gt;Mozilla Browser with Ajax and Flash 9 support,&lt;/li&gt;&lt;li&gt;Slide-out keyboard or handwriting recognition,&lt;/li&gt;&lt;li&gt;Built in GPS and SatNav software with UK maps,&lt;/li&gt;&lt;li&gt;Wifi&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;All for £128 (30% cheaper than an Ipod Touch). It has the disadvantage that there is no GPRS or 3G support so the internet can only be used where there is Wifi available but it has what is probably the best browser on any mobile device which can be used to access virtually any site that a desktop browser can. Even the &lt;a href="http://www.igindex.co.uk/"&gt;IG Index&lt;/a&gt; site which is highly Ajax oriented loads up and works fine albeit more slowly than on a desktop. The screen resolution is a respectable 800 x 480 so this is a genuinely usuable format packed into a small size. The Flash player works fine with YouTube and Magnatune although I've yet to get BBC iPlayer working.&lt;/p&gt;&lt;p&gt;The OS is a fairly standard Linux distribution but with a custom Windowing environment designed for touchscreen and even includes a terminal. There are plenty of applications available through the repository but porting any other open source Unix apps should be fairly trivial so long as the resource requirements aren't too great. There is also a development underway to replace the underlying Linux distro with Ubuntu so you get the benefits of Ubuntu with the touchscreen friendly window manager - perfect. &lt;/p&gt;&lt;p&gt;Physically the device is about the same size as an IPhone but slighter thicker at 14mm and noticeably heavier. It has a sturdy metal case that slides down to reveal the keyboard. It also has an integral kickstand wich mean that the device can stand up which is useful for watching videos, photo slideshows or Skype video calls. It's a well designed, solid, compact design but I still think that a traditional clamshell design like the Psion's would have been better or better still dispense with the physical keyboard and rely on the onscreen keyboard or handwriting recognition. Having said that, my attempts to use the handwriting recognition have so far been disappointing finding it very slow and practically unusable. This is a surprise considering how well it worked on the P910 which had a tenth of the processing power of this device. Perhaps it needs more practice on my part and maybe some tuning so I'll bear with it for the time being.&lt;/p&gt;&lt;p&gt;As an update, I'm loving this device and find that I'm using it more often than my laptop for casual browsing and certainly for media like watching vides on YouTube or listening to music on Magnatune. I've persevered with the handwriting recognition and get a high accuracy rate but it still remains too slow for entering anything more than a couple of words. Sometimes it won't respond at all, other times it lets you get a couple of letters ahead but then just forgets earlier letters so you have to rub out and start again. This is a bitter disappointment to me as the P910 was great, my ancient Compaq Ipaq with PocketPC was acceptable and even the humble Palm Pilot of a decade ago was better than this. So come on Nokia give us an update to this rubbish.&lt;/p&gt;&lt;p&gt;What I really like about this device is that it is a regular Linux machine with everything where you'd expect it. This means that porting software is trivially easy.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3887060946333002264-4786742667626344940?l=andrewwhaley.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrewwhaley.blogspot.com/feeds/4786742667626344940/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andrewwhaley.blogspot.com/2009/08/symbian-is-dead-long-live-linux.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/4786742667626344940'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/4786742667626344940'/><link rel='alternate' type='text/html' href='http://andrewwhaley.blogspot.com/2009/08/symbian-is-dead-long-live-linux.html' title='Symbian is dead, long live Linux'/><author><name>Andrew Whaley</name><uri>http://www.blogger.com/profile/05346078852977103014</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3887060946333002264.post-7394065066590265066</id><published>2009-08-14T14:57:00.000-07:00</published><updated>2009-08-14T15:08:46.934-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='forex'/><title type='text'>Running MetaTrader 4 under Linux</title><content type='html'>Many of the Forex brokers e.g. &lt;a href="http://www.fxcm.co.uk"&gt;FXCM&lt;/a&gt; and &lt;a href="http://www.alpari.co.uk"&gt;Alpari UK&lt;/a&gt; are now offering direct trading through MetaTrader which offers great opportunities to program 'Expert Advisors' to automate your trading. This means that you can be day trading full time whilst you're at work and asleep.&lt;br /&gt;&lt;br /&gt;Unfortunately MetaTrader is a purely Windows application but the great news is that it installs and runs fine under Wine on Ubuntu 9.04. It will install under vanilla Wine from the Ubuntu repository but unfortunately it won't run because it requires MFC libraries that aren't included in the default Wine installation.&lt;br /&gt;&lt;br /&gt;This is easily remedied by copying the following files from a Windows XP box :-&lt;br /&gt;&lt;br /&gt;-rwxrwxrwx 1 andrew andrew  924432 2003-07-16 17:28 mfc40.dll&lt;br /&gt;-rwxrwxrwx 1 andrew andrew  927504 2008-04-14 01:11 mfc40u.dll&lt;br /&gt;-rwxrwxrwx 1 andrew andrew 1028096 2008-04-14 01:11 mfc42.dll&lt;br /&gt;-rwxrwxrwx 1 andrew andrew  981760 2007-04-03 04:14 mfc42u.dll&lt;br /&gt;-rwxrwxrwx 1 andrew andrew 1060864 2003-03-18 20:20 mfc71.dll&lt;br /&gt;-rwxrwxrwx 1 andrew andrew 1047552 2003-03-18 20:12 mfc71u.dll&lt;br /&gt;-rwxrwxrwx 1 andrew andrew   22528 2008-04-14 01:11 mfcsubs.dll&lt;br /&gt;&lt;br /&gt;to your .wine/dosdevices/c:/windows/system32 directory.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3887060946333002264-7394065066590265066?l=andrewwhaley.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrewwhaley.blogspot.com/feeds/7394065066590265066/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andrewwhaley.blogspot.com/2009/08/running-metatrader-4-under-linux.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/7394065066590265066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/7394065066590265066'/><link rel='alternate' type='text/html' href='http://andrewwhaley.blogspot.com/2009/08/running-metatrader-4-under-linux.html' title='Running MetaTrader 4 under Linux'/><author><name>Andrew Whaley</name><uri>http://www.blogger.com/profile/05346078852977103014</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3887060946333002264.post-2191154956658111285</id><published>2009-07-15T06:23:00.000-07:00</published><updated>2009-09-14T12:44:05.593-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='spread betting'/><title type='text'>Spread betting with genetic programs</title><content type='html'>I met up with an &lt;a href="http://blogs.oracle.com/felcey/"&gt;old friend&lt;/a&gt; a couple of weeks ago who mentioned he was interested in &lt;a href="http://www.financial-spread-betting.com/"&gt;financial spread betting&lt;/a&gt; and the possibilities of making some money as he knew of people that made a full time living from it. I must admit, I'd often thought that it must be possible to use software to make money from the markets but hadn't realized that spread betting offered a low cost (albeit high risk) way in.&lt;br /&gt;&lt;br /&gt;It sounds rather obvious but you should be successful if you win more on your winning bets than you lose on your losing bets even though you might lose more often than you win. So the emphasis should be on profit rather than the number of times you win or lose. Reading books like '&lt;a href="http://www.nakedtrader.co.uk/"&gt;The Naked Trader&lt;/a&gt;', it seems the biggest danger is your emotions forcing you to throw good money after bad when you are losing and making you cash in your winning bets too soon when they're in profit rather than letting them grow to reach their full potential.&lt;br /&gt;&lt;br /&gt;Using software should remove the emotions providing the user follows the orders exactly and is not tempted to intervene. So I set about writing some software, in Scheme obviously, to generate a single market order for a bet on the FTSE100 index the next day based on the previous day's data. Here's an example of the daily movement :-&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/__-F14_sObgw/Sl3d8DtMYKI/AAAAAAAAAAs/WVpisrvYrTo/s1600-h/ftse100"&gt;&lt;img style="margin: 0px auto 10px; text-align: center; width: 300px; display: block; height: 165px; cursor: pointer;" id="BLOGGER_PHOTO_ID_5358683155497509026" alt="" src="http://4.bp.blogspot.com/__-F14_sObgw/Sl3d8DtMYKI/AAAAAAAAAAs/WVpisrvYrTo/s320/ftse100" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The FTSE is an ideal target for spread betting because it has a large daily movement range and the spreads offered by most companies are very tight (e.g. &lt;a href="http://www.igindex.co.uk/"&gt;IG Index &lt;/a&gt;offers only 2 points) and you can have a stop that is only 30 points away which means that can very cheaply place bets.&lt;br /&gt;&lt;br /&gt;The order might say Buy at 4280 with a stop of 30 points, no limit and a rate of £1 per point. If the market is lower than 4280 at any point during the day, your bet will be placed. For every point that the market moves up, you will gain a pound. If the market then moves downwards you will lose £1 for every point until it reaches the 30 point stop in which case you've lost your bet and are £30 poorer. If on the other hand the market had climbed 100 points you'd be &lt;strong&gt;almost&lt;/strong&gt; £100 richer (the difference is the spreads taken by the spread betting firm). If the market never came down to 4280, then your bet would not be placed and you wouldn't gain or lose anything.&lt;br /&gt;&lt;br /&gt;So the first task was to build a simulator and get hold of some historic 'intraday' data i.e. minute by minute movements in the price going back over three months. The simulator takes a list of orders and runs them in a particular day to calculate the profit or loss for each order. Wrapped around this is a harness that for each day in the set will call out to a strategy function asking for orders based on the previous days statistics. The daily and weekly profitability is then calculated for the strategy so you can decide whether it's a winner or not. You can then use the strategy to generate orders for the next day i.e. tomorrow, hopefully with confidence that it will win more than it will lose.&lt;br /&gt;&lt;br /&gt;Using the simulator, you can try out strategies that you think might work - here's one that's not bad :-&lt;br /&gt;&lt;br /&gt;&lt;div class="scheme"&gt;&lt;pre&gt;&lt;span class="comment"&gt;;; Stats used by strategy function&lt;br /&gt;&lt;/span&gt;(&lt;span class="variable"&gt;define-type&lt;/span&gt; &lt;span class="variable"&gt;stats&lt;/span&gt;&lt;br /&gt;     &lt;span class="variable"&gt;prev-open&lt;/span&gt;&lt;br /&gt;     &lt;span class="variable"&gt;prev-close&lt;/span&gt;&lt;br /&gt;     &lt;span class="variable"&gt;prev-high&lt;/span&gt;&lt;br /&gt;     &lt;span class="variable"&gt;prev-low&lt;/span&gt;&lt;br /&gt;     )&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;;; A very simple but surprisingly effective strategy&lt;br /&gt;&lt;/span&gt;(&lt;span class="keyword"&gt;define&lt;/span&gt; (&lt;span class="variable"&gt;simple-strategy&lt;/span&gt; &lt;span class="variable"&gt;stats&lt;/span&gt;)&lt;br /&gt;(&lt;span class="keyword"&gt;let&lt;/span&gt; ((&lt;span class="variable"&gt;gain&lt;/span&gt; (&lt;span class="builtin"&gt;-&lt;/span&gt; (&lt;span class="variable"&gt;stats-prev-close&lt;/span&gt; &lt;span class="variable"&gt;stats&lt;/span&gt;) (&lt;span class="variable"&gt;stats-prev-open&lt;/span&gt; &lt;span class="variable"&gt;stats&lt;/span&gt;)))&lt;br /&gt;(&lt;span class="variable"&gt;range&lt;/span&gt; (&lt;span class="builtin"&gt;-&lt;/span&gt; (&lt;span class="variable"&gt;stats-prev-high&lt;/span&gt; &lt;span class="variable"&gt;stats&lt;/span&gt;) (&lt;span class="variable"&gt;stats-prev-low&lt;/span&gt; &lt;span class="variable"&gt;stats&lt;/span&gt;)))&lt;br /&gt;(&lt;span class="variable"&gt;mid&lt;/span&gt; (&lt;span class="builtin"&gt;/&lt;/span&gt; (&lt;span class="builtin"&gt;+&lt;/span&gt; (&lt;span class="variable"&gt;stats-prev-high&lt;/span&gt; &lt;span class="variable"&gt;stats&lt;/span&gt;) (&lt;span class="variable"&gt;stats-prev-low&lt;/span&gt; &lt;span class="variable"&gt;stats&lt;/span&gt;)) &lt;span class="selfeval"&gt;2&lt;/span&gt;)))&lt;br /&gt;(&lt;span class="keyword"&gt;cond&lt;/span&gt;&lt;br /&gt;((&lt;span class="builtin"&gt;&amp;gt;&lt;/span&gt; &lt;span class="variable"&gt;gain&lt;/span&gt; &lt;span class="selfeval"&gt;10&lt;/span&gt;) (&lt;span class="builtin"&gt;list&lt;/span&gt; (&lt;span class="variable"&gt;make-order&lt;/span&gt; &lt;span class="builtin"&gt;-&lt;/span&gt; (&lt;span class="builtin"&gt;+&lt;/span&gt; &lt;span class="variable"&gt;mid&lt;/span&gt; &lt;span class="selfeval"&gt;5&lt;/span&gt;) &lt;span class="selfeval"&gt;30&lt;/span&gt; &lt;span class="selfeval"&gt;0&lt;/span&gt; &lt;span class="selfeval"&gt;1.0&lt;/span&gt;)))&lt;br /&gt;(&lt;span class="variable"&gt;else&lt;/span&gt; (&lt;span class="builtin"&gt;list&lt;/span&gt; (&lt;span class="variable"&gt;make-order&lt;/span&gt; &lt;span class="builtin"&gt;+&lt;/span&gt; (&lt;span class="builtin"&gt;+&lt;/span&gt; &lt;span class="variable"&gt;mid&lt;/span&gt; &lt;span class="selfeval"&gt;10&lt;/span&gt;) &lt;span class="selfeval"&gt;30&lt;/span&gt; &lt;span class="selfeval"&gt;0&lt;/span&gt; &lt;span class="selfeval"&gt;1.0&lt;/span&gt;))))))&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The simulator shows that this very simple strategy generates around 500 points profit over the sample three month period. (NB. past performance is no gaurantee of future performance !). Make-order takes the direction (+ for buy order or - for sell), the opening (order limit) value, stop distance, the limit distance and price per point. Note that the only input data the strategy uses is the previous day's opening, closing, high and low price. The strategy works on the basis that if the FTSE gains one day then it'll probably come down the next. Obviously this isn't a universal rule and will very often be wrong but when you're wrong you will lose at most 30 points and when you're right you could gain in excess of 100 points.&lt;br /&gt;&lt;br /&gt;Using manual analysis of the charts and computing some optimum values, I created a variation on the one above that managed to average around 1000 points profit for the period but I had no way of knowing if it was optimal or not.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Genetic Programming&lt;/span&gt;&lt;br /&gt;Genetic programming is a technique for evolving programs to solve a problem. Here our problem is to come up with a trading strategy by creating program fragments that breed and mutate over time and are evaluated against a 'fitness function' the least fit are discarded and the most fit are encouraged to breed to produce stronger offspring. In our case the fitness function is the simulator - the total profit over the three months data is all that matters. If you make a good profit you can stay and breed, if you don't you're out. Breeding (crossover) takes complete elements at random from both parents. Mutation randomly and subtly modifies one of these elements to produce something different. After many generations you get a very optimal solution to the problem you are trying to solve.&lt;br /&gt;&lt;br /&gt;Scheme is the perfect language for genetic programming because :-&lt;br /&gt;&lt;ol&gt;&lt;li&gt;You can modify code easily by manipulating lists,&lt;/li&gt;&lt;li&gt;You can evaluate your new code with eval.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;So to solve our problem we need a 'trader' :-&lt;br /&gt;&lt;br /&gt;&lt;div class="scheme"&gt;&lt;pre&gt;(&lt;span class="variable"&gt;define-type&lt;/span&gt; &lt;span class="variable"&gt;trader&lt;/span&gt;&lt;br /&gt;      &lt;span class="variable"&gt;dir-func&lt;/span&gt;&lt;br /&gt;      &lt;span class="variable"&gt;start-func&lt;/span&gt;&lt;br /&gt;      &lt;span class="variable"&gt;stop-func&lt;/span&gt;&lt;br /&gt;      &lt;span class="variable"&gt;limit-func&lt;/span&gt;&lt;br /&gt;      &lt;span class="variable"&gt;profit&lt;/span&gt;)&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Which basically is a collection of expressions that are evaluated to produce the corresponding values required for the order. The profit member is used to track which of the traders are successful.&lt;br /&gt;&lt;br /&gt;There are a population of traders that exist in a list that are initialised with random expressions :-&lt;br /&gt;&lt;br /&gt;&lt;div class="scheme"&gt;&lt;pre&gt;(&lt;span class="keyword"&gt;define&lt;/span&gt; (&lt;span class="variable"&gt;pick-from&lt;/span&gt; &lt;span class="variable"&gt;lst&lt;/span&gt;)&lt;br /&gt;(&lt;span class="builtin"&gt;list-ref&lt;/span&gt; &lt;span class="variable"&gt;lst&lt;/span&gt; (&lt;span class="variable"&gt;random-integer&lt;/span&gt; (&lt;span class="builtin"&gt;length&lt;/span&gt; &lt;span class="variable"&gt;lst&lt;/span&gt;))))&lt;br /&gt;&lt;br /&gt;(&lt;span class="keyword"&gt;define&lt;/span&gt; (&lt;span class="variable"&gt;get-random-var&lt;/span&gt;)&lt;br /&gt;(&lt;span class="variable"&gt;pick-from&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;(&lt;span class="variable"&gt;o&lt;/span&gt; &lt;span class="variable"&gt;c&lt;/span&gt; &lt;span class="variable"&gt;h&lt;/span&gt; &lt;span class="variable"&gt;l&lt;/span&gt; &lt;span class="variable"&gt;g&lt;/span&gt; &lt;span class="variable"&gt;r&lt;/span&gt; &lt;span class="variable"&gt;m&lt;/span&gt;)))&lt;br /&gt;&lt;br /&gt;(&lt;span class="keyword"&gt;define&lt;/span&gt; (&lt;span class="variable"&gt;get-random-constant&lt;/span&gt; &lt;span class="variable"&gt;x&lt;/span&gt;)&lt;br /&gt;(&lt;span class="keyword"&gt;let&lt;/span&gt; ((&lt;span class="variable"&gt;r&lt;/span&gt; (&lt;span class="builtin"&gt;-&lt;/span&gt; &lt;span class="variable"&gt;x&lt;/span&gt; (&lt;span class="variable"&gt;random-integer&lt;/span&gt; (&lt;span class="builtin"&gt;*&lt;/span&gt; &lt;span class="variable"&gt;x&lt;/span&gt; &lt;span class="selfeval"&gt;2&lt;/span&gt;)))))&lt;br /&gt;(&lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="builtin"&gt;=&lt;/span&gt; &lt;span class="variable"&gt;r&lt;/span&gt; &lt;span class="selfeval"&gt;0&lt;/span&gt;) (&lt;span class="variable"&gt;get-random-constant&lt;/span&gt; &lt;span class="variable"&gt;x&lt;/span&gt;) &lt;span class="variable"&gt;r&lt;/span&gt;))) &lt;span class="comment"&gt;;; Don't want any divide by zero errors&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;(&lt;span class="keyword"&gt;define&lt;/span&gt; (&lt;span class="variable"&gt;make-random-trader&lt;/span&gt;)&lt;br /&gt;(&lt;span class="variable"&gt;make-trader&lt;/span&gt; (&lt;span class="variable"&gt;pick-from&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;(&lt;span class="builtin"&gt;+&lt;/span&gt; &lt;span class="builtin"&gt;-&lt;/span&gt;)) (&lt;span class="variable"&gt;get-mutated-term&lt;/span&gt; (&lt;span class="variable"&gt;get-random-var&lt;/span&gt;)) (&lt;span class="variable"&gt;get-mutated-term&lt;/span&gt; (&lt;span class="variable"&gt;get-random-constant&lt;/span&gt; &lt;span class="selfeval"&gt;100&lt;/span&gt;)) (&lt;span class="variable"&gt;get-mutated-term&lt;/span&gt; (&lt;span class="variable"&gt;get-random-constant&lt;/span&gt; &lt;span class="selfeval"&gt;100&lt;/span&gt;)) &lt;span class="selfeval"&gt;0&lt;/span&gt;))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(&lt;span class="keyword"&gt;define&lt;/span&gt; (&lt;span class="variable"&gt;initialise-traders&lt;/span&gt; &lt;span class="variable"&gt;num&lt;/span&gt;)&lt;br /&gt;(&lt;span class="keyword"&gt;let&lt;/span&gt; ((&lt;span class="variable"&gt;traders&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;()))&lt;br /&gt;(&lt;span class="keyword"&gt;let&lt;/span&gt; &lt;span class="variable"&gt;nxt&lt;/span&gt; ((&lt;span class="variable"&gt;x&lt;/span&gt; &lt;span class="selfeval"&gt;0&lt;/span&gt;))&lt;br /&gt;(&lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="builtin"&gt;&amp;lt;&lt;/span&gt; &lt;span class="variable"&gt;x&lt;/span&gt; &lt;span class="variable"&gt;num&lt;/span&gt;)&lt;br /&gt;  (&lt;span class="keyword"&gt;begin&lt;/span&gt;&lt;br /&gt;    (&lt;span class="keyword"&gt;set!&lt;/span&gt; &lt;span class="variable"&gt;traders&lt;/span&gt; (&lt;span class="builtin"&gt;cons&lt;/span&gt; (&lt;span class="variable"&gt;make-random-trader&lt;/span&gt;) &lt;span class="variable"&gt;traders&lt;/span&gt;))                 &lt;br /&gt;    (&lt;span class="variable"&gt;nxt&lt;/span&gt; (&lt;span class="builtin"&gt;+&lt;/span&gt; &lt;span class="variable"&gt;x&lt;/span&gt; &lt;span class="selfeval"&gt;1&lt;/span&gt;))&lt;br /&gt;    )))&lt;br /&gt;&lt;span class="variable"&gt;traders&lt;/span&gt;))&lt;/pre&gt;&lt;/div&gt;Initialise-traders creates the population of size num using the make-random-trader functions. The expressions are based on random constants and random variables which are o - yesterdays opening value, c - yesterdays closing value, h - yesterdays high value etc. A useful function pick-from basically returns a random element from a specified list. &lt;em&gt;Update: Subsequent studies have shown that it is useful to seed the initial population with some known good specimens e.g. the simple strategy above.&lt;br /&gt;&lt;/em&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Breeding and Mutation&lt;/span&gt;&lt;br /&gt;The following function breeds two traders by selecting features from each and then adding mutation :-&lt;br /&gt;&lt;br /&gt;&lt;div class="scheme"&gt;&lt;pre&gt;(&lt;span class="keyword"&gt;define&lt;/span&gt; (&lt;span class="variable"&gt;breed&lt;/span&gt; &lt;span class="variable"&gt;t1&lt;/span&gt; &lt;span class="variable"&gt;t2&lt;/span&gt;)&lt;br /&gt;&lt;span class="comment"&gt;;; Create child from parents&lt;br /&gt;&lt;/span&gt;  (&lt;span class="keyword"&gt;let&lt;/span&gt; ((&lt;span class="variable"&gt;t&lt;/span&gt; (&lt;span class="variable"&gt;make-trader&lt;/span&gt;&lt;br /&gt;(&lt;span class="variable"&gt;pick-from&lt;/span&gt; (&lt;span class="builtin"&gt;list&lt;/span&gt; (&lt;span class="variable"&gt;trader-dir-func&lt;/span&gt; &lt;span class="variable"&gt;t1&lt;/span&gt;) (&lt;span class="variable"&gt;trader-dir-func&lt;/span&gt; &lt;span class="variable"&gt;t2&lt;/span&gt;)))&lt;br /&gt;(&lt;span class="variable"&gt;pick-from&lt;/span&gt; (&lt;span class="builtin"&gt;list&lt;/span&gt; (&lt;span class="variable"&gt;trader-start-func&lt;/span&gt; &lt;span class="variable"&gt;t1&lt;/span&gt;) (&lt;span class="variable"&gt;trader-start-func&lt;/span&gt; &lt;span class="variable"&gt;t2&lt;/span&gt;)))&lt;br /&gt;(&lt;span class="variable"&gt;pick-from&lt;/span&gt; (&lt;span class="builtin"&gt;list&lt;/span&gt; (&lt;span class="variable"&gt;trader-stop-func&lt;/span&gt; &lt;span class="variable"&gt;t1&lt;/span&gt;) (&lt;span class="variable"&gt;trader-stop-func&lt;/span&gt; &lt;span class="variable"&gt;t2&lt;/span&gt;)))&lt;br /&gt;(&lt;span class="variable"&gt;pick-from&lt;/span&gt; (&lt;span class="builtin"&gt;list&lt;/span&gt; (&lt;span class="variable"&gt;trader-limit-func&lt;/span&gt; &lt;span class="variable"&gt;t1&lt;/span&gt;) (&lt;span class="variable"&gt;trader-limit-func&lt;/span&gt; &lt;span class="variable"&gt;t2&lt;/span&gt;)))&lt;br /&gt;&lt;span class="selfeval"&gt;0&lt;/span&gt; )))&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;;; Add mutation&lt;br /&gt;&lt;/span&gt;  (&lt;span class="keyword"&gt;let&lt;/span&gt; ((&lt;span class="variable"&gt;r&lt;/span&gt; (&lt;span class="variable"&gt;random-integer&lt;/span&gt; &lt;span class="selfeval"&gt;5&lt;/span&gt;))) &lt;span class="comment"&gt;;; what to modify&lt;br /&gt;&lt;/span&gt;    (&lt;span class="keyword"&gt;cond&lt;/span&gt;&lt;br /&gt;((&lt;span class="builtin"&gt;=&lt;/span&gt; &lt;span class="variable"&gt;r&lt;/span&gt; &lt;span class="selfeval"&gt;1&lt;/span&gt;) (&lt;span class="variable"&gt;trader-dir-func-set!&lt;/span&gt; &lt;span class="variable"&gt;t&lt;/span&gt; (&lt;span class="variable"&gt;mutate&lt;/span&gt; (&lt;span class="variable"&gt;trader-dir-func&lt;/span&gt; &lt;span class="variable"&gt;t&lt;/span&gt;))))&lt;br /&gt;((&lt;span class="builtin"&gt;=&lt;/span&gt; &lt;span class="variable"&gt;r&lt;/span&gt; &lt;span class="selfeval"&gt;2&lt;/span&gt;) (&lt;span class="variable"&gt;trader-start-func-set!&lt;/span&gt; &lt;span class="variable"&gt;t&lt;/span&gt; (&lt;span class="variable"&gt;mutate&lt;/span&gt; (&lt;span class="variable"&gt;trader-start-func&lt;/span&gt; &lt;span class="variable"&gt;t&lt;/span&gt;))))&lt;br /&gt;((&lt;span class="builtin"&gt;=&lt;/span&gt; &lt;span class="variable"&gt;r&lt;/span&gt; &lt;span class="selfeval"&gt;3&lt;/span&gt;) (&lt;span class="variable"&gt;trader-stop-func-set!&lt;/span&gt; &lt;span class="variable"&gt;t&lt;/span&gt; (&lt;span class="variable"&gt;mutate&lt;/span&gt; (&lt;span class="variable"&gt;trader-stop-func&lt;/span&gt; &lt;span class="variable"&gt;t&lt;/span&gt;))))&lt;br /&gt;((&lt;span class="builtin"&gt;=&lt;/span&gt; &lt;span class="variable"&gt;r&lt;/span&gt; &lt;span class="selfeval"&gt;4&lt;/span&gt;) (&lt;span class="variable"&gt;trader-limit-func-set!&lt;/span&gt; &lt;span class="variable"&gt;t&lt;/span&gt; (&lt;span class="variable"&gt;mutate&lt;/span&gt; (&lt;span class="variable"&gt;trader-limit-func&lt;/span&gt; &lt;span class="variable"&gt;t&lt;/span&gt;))))))&lt;br /&gt;&lt;span class="variable"&gt;t&lt;/span&gt;))&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;You can see that one (or none) of the trader functions is selected for mutation which is done with these functions :-&lt;br /&gt;&lt;br /&gt;&lt;div class="scheme"&gt;&lt;pre&gt;(&lt;span class="keyword"&gt;define&lt;/span&gt; (&lt;span class="variable"&gt;mutate-list&lt;/span&gt; &lt;span class="variable"&gt;l&lt;/span&gt;)&lt;br /&gt;(&lt;span class="variable"&gt;pick-from&lt;/span&gt; (&lt;span class="builtin"&gt;list&lt;/span&gt;&lt;br /&gt;          (&lt;span class="builtin"&gt;map&lt;/span&gt; (&lt;span class="keyword"&gt;lambda&lt;/span&gt; (&lt;span class="variable"&gt;x&lt;/span&gt;)&lt;br /&gt;                 (&lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="builtin"&gt;&amp;gt;&lt;/span&gt; (&lt;span class="variable"&gt;random-integer&lt;/span&gt; &lt;span class="selfeval"&gt;10&lt;/span&gt;) &lt;span class="selfeval"&gt;2&lt;/span&gt;) (&lt;span class="variable"&gt;mutate&lt;/span&gt; &lt;span class="variable"&gt;x&lt;/span&gt;) &lt;span class="variable"&gt;x&lt;/span&gt;))&lt;br /&gt;               &lt;span class="variable"&gt;l&lt;/span&gt;)&lt;br /&gt;          (&lt;span class="variable"&gt;simplify-list&lt;/span&gt; &lt;span class="variable"&gt;l&lt;/span&gt;))))&lt;br /&gt;&lt;br /&gt;(&lt;span class="keyword"&gt;define&lt;/span&gt; (&lt;span class="variable"&gt;get-mutated-term&lt;/span&gt; &lt;span class="variable"&gt;t&lt;/span&gt;)&lt;br /&gt;(&lt;span class="variable"&gt;pick-from&lt;/span&gt; (&lt;span class="builtin"&gt;list&lt;/span&gt;&lt;br /&gt;          (&lt;span class="variable"&gt;get-random-constant&lt;/span&gt; &lt;span class="selfeval"&gt;100&lt;/span&gt;)&lt;br /&gt;          (&lt;span class="variable"&gt;get-random-var&lt;/span&gt;)&lt;br /&gt;          &lt;span class="keyword"&gt;`&lt;/span&gt;(&lt;span class="builtin"&gt;+&lt;/span&gt; &lt;span class="keyword"&gt;,&lt;/span&gt;&lt;span class="variable"&gt;t&lt;/span&gt; &lt;span class="keyword"&gt;,&lt;/span&gt;(&lt;span class="variable"&gt;get-random-constant&lt;/span&gt; &lt;span class="selfeval"&gt;100&lt;/span&gt;))&lt;br /&gt;          &lt;span class="keyword"&gt;`&lt;/span&gt;(&lt;span class="builtin"&gt;-&lt;/span&gt; &lt;span class="keyword"&gt;,&lt;/span&gt;&lt;span class="variable"&gt;t&lt;/span&gt; &lt;span class="keyword"&gt;,&lt;/span&gt;(&lt;span class="variable"&gt;get-random-var&lt;/span&gt;))&lt;br /&gt;          &lt;span class="keyword"&gt;`&lt;/span&gt;(&lt;span class="builtin"&gt;*&lt;/span&gt; &lt;span class="keyword"&gt;,&lt;/span&gt;&lt;span class="variable"&gt;t&lt;/span&gt; &lt;span class="keyword"&gt;,&lt;/span&gt;(&lt;span class="variable"&gt;get-random-constant&lt;/span&gt; &lt;span class="selfeval"&gt;100&lt;/span&gt;))&lt;br /&gt;          &lt;span class="keyword"&gt;`&lt;/span&gt;(&lt;span class="builtin"&gt;/&lt;/span&gt; &lt;span class="keyword"&gt;,&lt;/span&gt;&lt;span class="variable"&gt;t&lt;/span&gt; &lt;span class="keyword"&gt;,&lt;/span&gt;(&lt;span class="variable"&gt;get-random-var&lt;/span&gt;))&lt;br /&gt;          &lt;span class="keyword"&gt;`&lt;/span&gt;(&lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="builtin"&gt;&amp;gt;&lt;/span&gt; &lt;span class="keyword"&gt;,&lt;/span&gt;&lt;span class="variable"&gt;t&lt;/span&gt; &lt;span class="keyword"&gt;,&lt;/span&gt;(&lt;span class="variable"&gt;get-random-constant&lt;/span&gt; &lt;span class="selfeval"&gt;100&lt;/span&gt;)) &lt;span class="keyword"&gt;,&lt;/span&gt;&lt;span class="variable"&gt;t&lt;/span&gt; &lt;span class="keyword"&gt;,&lt;/span&gt;(&lt;span class="variable"&gt;get-random-var&lt;/span&gt;)))))                  &lt;br /&gt;&lt;br /&gt;(&lt;span class="keyword"&gt;define&lt;/span&gt; (&lt;span class="variable"&gt;mutate&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt;)&lt;br /&gt;(&lt;span class="keyword"&gt;cond&lt;/span&gt;&lt;br /&gt;((&lt;span class="builtin"&gt;list?&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt;) (&lt;span class="variable"&gt;mutate-list&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt;))&lt;br /&gt;((&lt;span class="builtin"&gt;number?&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt;) (&lt;span class="variable"&gt;pick-from&lt;/span&gt; (&lt;span class="builtin"&gt;list&lt;/span&gt; (&lt;span class="variable"&gt;get-mutated-term&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt;) (&lt;span class="builtin"&gt;+&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt; (&lt;span class="variable"&gt;get-random-constant&lt;/span&gt; &lt;span class="selfeval"&gt;10&lt;/span&gt;)))))&lt;br /&gt;((&lt;span class="keyword"&gt;or&lt;/span&gt; (&lt;span class="builtin"&gt;eq?&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;&lt;span class="variable"&gt;o&lt;/span&gt;) (&lt;span class="builtin"&gt;eq?&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;&lt;span class="variable"&gt;c&lt;/span&gt;) (&lt;span class="builtin"&gt;eq?&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;&lt;span class="variable"&gt;h&lt;/span&gt;) (&lt;span class="builtin"&gt;eq?&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;&lt;span class="variable"&gt;l&lt;/span&gt;) (&lt;span class="builtin"&gt;eq?&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;&lt;span class="variable"&gt;g&lt;/span&gt;) (&lt;span class="builtin"&gt;eq?&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;&lt;span class="variable"&gt;r&lt;/span&gt;) (&lt;span class="builtin"&gt;eq?&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;&lt;span class="variable"&gt;m&lt;/span&gt;)) (&lt;span class="variable"&gt;get-mutated-term&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt;)) &lt;span class="comment"&gt;;; Variable&lt;br /&gt;&lt;/span&gt;    ((&lt;span class="keyword"&gt;or&lt;/span&gt; (&lt;span class="builtin"&gt;eq?&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;&lt;span class="builtin"&gt;+&lt;/span&gt;) (&lt;span class="builtin"&gt;eq?&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;&lt;span class="builtin"&gt;-&lt;/span&gt;)) (&lt;span class="variable"&gt;pick-from&lt;/span&gt; (&lt;span class="builtin"&gt;list&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;&lt;span class="builtin"&gt;-&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;&lt;span class="builtin"&gt;+&lt;/span&gt; &lt;span class="keyword"&gt;`&lt;/span&gt;(&lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="builtin"&gt;&amp;gt;&lt;/span&gt; &lt;span class="keyword"&gt;,&lt;/span&gt;(&lt;span class="variable"&gt;get-random-var&lt;/span&gt;) &lt;span class="keyword"&gt;,&lt;/span&gt;(&lt;span class="variable"&gt;get-random-constant&lt;/span&gt; &lt;span class="selfeval"&gt;100&lt;/span&gt;)) &lt;span class="builtin"&gt;+&lt;/span&gt; &lt;span class="builtin"&gt;-&lt;/span&gt;))))&lt;br /&gt;((&lt;span class="keyword"&gt;or&lt;/span&gt; (&lt;span class="builtin"&gt;eq?&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;&lt;span class="builtin"&gt;*&lt;/span&gt;) (&lt;span class="builtin"&gt;eq?&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;&lt;span class="builtin"&gt;/&lt;/span&gt;)) (&lt;span class="variable"&gt;pick-from&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;(&lt;span class="builtin"&gt;+&lt;/span&gt; &lt;span class="builtin"&gt;-&lt;/span&gt; &lt;span class="builtin"&gt;/&lt;/span&gt; &lt;span class="builtin"&gt;*&lt;/span&gt;))) &lt;span class="comment"&gt;;; Arithmetic operator&lt;br /&gt;&lt;/span&gt;    ((&lt;span class="keyword"&gt;or&lt;/span&gt; (&lt;span class="builtin"&gt;eq?&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;&lt;span class="builtin"&gt;&amp;gt;&lt;/span&gt;) (&lt;span class="builtin"&gt;eq?&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;&lt;span class="builtin"&gt;&amp;lt;&lt;/span&gt;) (&lt;span class="builtin"&gt;eq?&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;&lt;span class="builtin"&gt;=&lt;/span&gt;)) (&lt;span class="variable"&gt;pick-from&lt;/span&gt; &lt;span class="keyword"&gt;'&lt;/span&gt;(&lt;span class="builtin"&gt;&amp;gt;&lt;/span&gt; &lt;span class="builtin"&gt;&amp;lt;&lt;/span&gt; &lt;span class="builtin"&gt;=&lt;/span&gt;))) &lt;span class="comment"&gt;;; Logical operator&lt;br /&gt;&lt;/span&gt;    (&lt;span class="variable"&gt;else&lt;/span&gt; &lt;span class="variable"&gt;f&lt;/span&gt;))) &lt;span class="comment"&gt;;; No mutation - don't know what to do&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The key function here is mutate which takes an expression term and mutates it using get-mutated-term.&lt;br /&gt;&lt;br /&gt;The rest of the code is concerned with maintaining the population pool, evaluating the profitability of the members and then discarding the least profitable and breeding the most profitable.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Results&lt;/span&gt;&lt;br /&gt;The simple static example above achieved a total profit of 509 points over the 3 months data, the genetically bred trader achieved 1469 ! My efforts to hand optimise the simple trader resulted in a profitability of around 1100 but the genetic model has even exceeded this by 30%.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Update: I expanded the data available to the traders to include a long and short moving average and also the gain on the Dow Jones Industrial Average and re-ran the process. The winning trader had a profitability of around 1700 points but surprisingly hadn't chosen to use the Dow variable.&lt;br /&gt;&lt;br /&gt;I've now created a separate blog to document my efforts to take this study forward to fully automated forex trading, please visit &lt;a href="http://www.thegenetictrader.com"&gt;http://www.thegenetictrader.com&lt;/a&gt; to check on my progress.&lt;br /&gt;&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3887060946333002264-2191154956658111285?l=andrewwhaley.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrewwhaley.blogspot.com/feeds/2191154956658111285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andrewwhaley.blogspot.com/2009/07/spread-betting-and-genetic-algorithms.html#comment-form' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/2191154956658111285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/2191154956658111285'/><link rel='alternate' type='text/html' href='http://andrewwhaley.blogspot.com/2009/07/spread-betting-and-genetic-algorithms.html' title='Spread betting with genetic programs'/><author><name>Andrew Whaley</name><uri>http://www.blogger.com/profile/05346078852977103014</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/__-F14_sObgw/Sl3d8DtMYKI/AAAAAAAAAAs/WVpisrvYrTo/s72-c/ftse100' height='72' width='72'/><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3887060946333002264.post-2931570986749590918</id><published>2009-05-22T04:56:00.000-07:00</published><updated>2009-06-18T06:40:26.265-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Serving Gambit Web Applications behind Apache</title><content type='html'>Now that writing web applications in &lt;a href="http://dynamo.iro.umontreal.ca/~gambit/wiki/index.php/Main_Page"&gt;Gambit Scheme&lt;/a&gt; is so easy using &lt;a href="http://dynamo.iro.umontreal.ca/~gambit/wiki/index.php/Black_Hole"&gt;Black Hole&lt;/a&gt;, I thought I'd write an article on how to set everything up from scratch using Apache as a front end web server.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/__-F14_sObgw/ShaUSr5TyhI/AAAAAAAAAAU/a1-YgT73hLs/s1600-h/GambitWeb.gif"&gt;&lt;img id="BLOGGER_PHOTO_ID_5338617457035954706" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: pointer; HEIGHT: 185px; TEXT-ALIGN: center" alt="" src="http://2.bp.blogspot.com/__-F14_sObgw/ShaUSr5TyhI/AAAAAAAAAAU/a1-YgT73hLs/s400/GambitWeb.gif" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Using Apache as a front end web server isn't strictly necessary since the Black Hole web server fully supports HTTP and is capable of serving static as well as dynamic content but for robustness, SSL support and to offload the serving of static content it makes sense to place Gambit behind Apache.&lt;br /&gt;&lt;br /&gt;Gambit uses lightweight internal threads which allows it to efficiently support thousands of concurrent requests but these run in a single OS thread. This means that if you are running on a multicore or multiprocessor system, you will need to run multiple Gambit processes and load balance between them in order to fully utilise the available CPU. The load balancer would need to be 'sticky' unless you are going to serialize continuations outside of Gambit.&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;Enter Black Hole&lt;br /&gt;&lt;/span&gt;Black Hole is primarily a R5RS compatible module system for Gambit which allows you to easily import libraries into your code including macros which has previously been tricky on Gambit. Conversely you can also export your own code and create your own libraries to fully modularise your development. This is basic stuff but the lack of it has really stifled development on Gambit. For the web developer, the most interesting aspects are the bundled libraries for web serving, SXML and the 'Spork' continuations based web framework.&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;Getting Started&lt;/span&gt;&lt;br /&gt;This guide is based very much on Per Eckerdal's &lt;a href="http://mwaza.dyndns.org/apps/files/bh-tutorial.html"&gt;Black Hole Tutorial guide&lt;/a&gt; but has been extended based on my own experiences using Black Hole.&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;Installing Black Hole&lt;span style="FONT-WEIGHT: bold"&gt;&lt;span style="FONT-WEIGHT: bold"&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;&lt;span style="FONT-WEIGHT: bold"&gt;&lt;span style="FONT-WEIGHT: bold"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;Assuming that you have Gambit installed, you need to download the latest Black Hole code from the &lt;a href="http://git-scm.com/"&gt;git&lt;/a&gt; repository :-&lt;br /&gt;&lt;br /&gt;&lt;code&gt;git clone http://mwaza.dyndns.org/apps/files/modules.git &lt;/code&gt;&lt;br /&gt;&lt;br /&gt;That will clone the current code repository to 'modules' directory in your working directory, you now need to copy or symlink this directory to the Gambit lib directory e.g. C:\Gambit-C\v4.4.3\lib\ on Windows to create ~~/lib/modules.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Although not strictly necessary, now would be a good time to build all the modules :-&lt;br /&gt;&lt;br /&gt;&lt;code&gt;cd \Gambit-C\v4.4.3\lib\modules&lt;br /&gt;gsc build&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Black Hole is now installed and ready to use, simply do a &lt;strong&gt;(load "~~/lib/modules/build")&lt;/strong&gt; in Gambit to initialise. It is recommended that you use gsc rather than gsi because Black Hole uses compilation features that aren't available in gsi.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;For convenience, you can create a wrapper command that loads Black Hole at startup, e.g. on Windows :-&lt;/p&gt;&lt;br /&gt;&lt;p&gt;bsc.cmd : &lt;/p&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;&lt;br /&gt;gsc -:dar- -e "(load \"~~/lib/modules/build\")" %1 -&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Copy this to your Gambit bin directory then you can use 'bsc' in future instead of gsc or gsi.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;Setting Up Apache&lt;br /&gt;&lt;/span&gt;In this scenario we are using Apache to proxy the requests through to Gambit and to serve any static content, here's a sample Virtual Host setup from httpd.conf :&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;&amp;lt;VirtualHost *&amp;gt;&lt;br /&gt;    ServerName localhost&lt;br /&gt;    ProxyPass /spork http://localhost:8080&lt;br /&gt;    ProxyPassReverse /spork http://localhost:8080&lt;br /&gt;    DocumentRoot ${path}/www&lt;br /&gt;&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This configuration will forward any requests with a URI that starts with '/spork' to the Gambit server running on port 8080. Any other requests will be served from the 'www' directory under Apache.&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;Creating your Spork Application&lt;br /&gt;&lt;/span&gt;So you are now ready to go, fire up Eclipse (with &lt;a href="http://schemeway.sourceforge.net/schemescript.html"&gt;SchemeScript&lt;/a&gt;) or your alternative favorite development tool. Start your Gambit REPL window (with bsc or load the modules manually).&lt;br /&gt;&lt;br /&gt;Enter this into REPL :-&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;(import (std spork/core))&lt;br /&gt;&lt;br /&gt;(define c (spork-serve root: "/spork" ))&lt;br /&gt;&lt;br /&gt;(add-spork c ("one")&lt;br /&gt;  `(html&lt;br /&gt;    (head&lt;br /&gt;     (title "Hello, world!"))&lt;br /&gt;    (body&lt;br /&gt;     "This is my first web application using Spork :)")))&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And fire up your browser :-&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/__-F14_sObgw/SjoL0ILvvzI/AAAAAAAAAAk/gasI0F2h6ZQ/s1600-h/spork.GIF"&gt;&lt;img id="BLOGGER_PHOTO_ID_5348600497633738546" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 320px; CURSOR: hand; HEIGHT: 245px; TEXT-ALIGN: center" alt="" src="http://4.bp.blogspot.com/__-F14_sObgw/SjoL0ILvvzI/AAAAAAAAAAk/gasI0F2h6ZQ/s320/spork.GIF" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;OK it's not a spectacular example but you are setup now ready to do some more serious development effortlessly through REPL - just redefine the function and retest with no need for a restart.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3887060946333002264-2931570986749590918?l=andrewwhaley.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrewwhaley.blogspot.com/feeds/2931570986749590918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andrewwhaley.blogspot.com/2009/05/serving-gambit-web-applications-behind.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/2931570986749590918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/2931570986749590918'/><link rel='alternate' type='text/html' href='http://andrewwhaley.blogspot.com/2009/05/serving-gambit-web-applications-behind.html' title='Serving Gambit Web Applications behind Apache'/><author><name>Andrew Whaley</name><uri>http://www.blogger.com/profile/05346078852977103014</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/__-F14_sObgw/ShaUSr5TyhI/AAAAAAAAAAU/a1-YgT73hLs/s72-c/GambitWeb.gif' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3887060946333002264.post-6192569181697015503</id><published>2009-04-29T02:35:00.000-07:00</published><updated>2009-06-28T12:30:15.862-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Gambit MySQL client 0.2</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.mysql.com/common/logos/logo_mysql_sun_a.gif"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 114px; height: 68px;" src="http://www.mysql.com/common/logos/logo_mysql_sun_a.gif" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://dynamo.iro.umontreal.ca/%7Egambit/wiki/skins/common/images/gambit-logo.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 102px; height: 123px;" src="http://dynamo.iro.umontreal.ca/%7Egambit/wiki/skins/common/images/gambit-logo.png" alt="" border="0" /&gt;&lt;/a&gt;After a few weeks wrestling with the MySQL protocol, I've finally managed to produce a reasonable attempt at a client for Gambit (and probably other Scheme's).&lt;br /&gt;&lt;br /&gt;This is a pure Scheme implementation rather than using Gambit's C interface to glue the existing MySQL C API into Gambit. The reason for this is that Gambit's power, and in my view fantastic potential as a web platform, comes from it's lightweight threads which allows Gambit to process thousands of concurrent requests in a single OS thread. This is all acheived by an internal schedular, continuations and very careful use of non-blocking calls on all I/O functions. Using the C API effectively takes the OS thread out of Gambit and into the C code and therefore all of those lovely threads stop executing until your call is completed - seriously bad news for a web application.&lt;br /&gt;&lt;br /&gt;This library is now around 80% complete and supports the following features :-&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Multiple concurrent connections to MySQL,&lt;/li&gt;&lt;li&gt;Authentication using both the old and new authentication methods,&lt;/li&gt;&lt;li&gt;Switching Schema's,&lt;/li&gt;&lt;li&gt;Dynamic queries, updates, deletes etc.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Prepared statement creation,&lt;/li&gt;&lt;li&gt;Executing prepared statements (queries and updates) with bind variables for most datatypes,&lt;/li&gt;&lt;li&gt;Closing prepared statements,&lt;/li&gt;&lt;li&gt;Closing connections.&lt;/li&gt;&lt;/ul&gt;Additionally, I've also introduced a SQL Abstraction Layer. This is equivalent to JDBC in Java which defines a few generic SQL types and provides a common API across database vendors. The idea behind this is that if someone else provides another database client, they can use the same abstraction layer and then any programs can switch between databases without having to rewrite their code (hopefully).&lt;br /&gt;&lt;br /&gt;There are a few limitations with the driver, i.e. features that aren't implemented yet :-&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Not all datatypes are supported yet in prepared statements e.g. floats, doubles, sets, enums and one or two others. Some of these can easily be avoided e.g. by using DECIMAL instead of FLOAT or DOUBLE.&lt;/li&gt;&lt;li&gt;BLOB's and large character fields are not yet supported in either dynamic or prepared statements.&lt;/li&gt;&lt;li&gt;Large result sets requiring supplementary fetches aren't supported as I haven't implemented the additional fetch function.&lt;/li&gt;&lt;/ul&gt;Hopefully I'll add these things over the coming weeks and months. There are likely to be a few bugs in there, so if you find one or you are desperate for a feature that hasn't been implemented yet then please email me.&lt;br /&gt;&lt;br /&gt;The library is in the Gambit &lt;a href="http://dynamo.iro.umontreal.ca/%7Egambit/wiki/index.php/Dumping_Grounds"&gt;Dumping Grounds&lt;/a&gt;.  Here's an example of how you use it :-&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(load "sql")&lt;br /&gt;&lt;/code&gt;&lt;code&gt;(load "mysql")&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;(with-connection (sql-connect "localhost" 3306 "test" "fred" "fred")&lt;br /&gt;&lt;br /&gt;;;(mysql-execute "drop table test")&lt;br /&gt;(mysql-execute "create table test (id integer PRIMARY KEY AUTO_INCREMENT, name varchar(50), inserted datetime, amount decimal(10,2) DEFAULT -4.5)")&lt;br /&gt;(pp (sql-execute "select * from test"))&lt;br /&gt;      &lt;br /&gt;&lt;br /&gt;;; Prepared Statements&lt;br /&gt;(let ((stmt1 (sql-prepare-statement "insert into test (name, amount, inserted) values (?, ?, sysdate())"))&lt;br /&gt;      (stmt2 (sql-prepare-statement "select id, name, amount, inserted from test where amount &gt; ? order by id")))&lt;br /&gt;&lt;br /&gt;  (pp (sql-execute-prepared-statement stmt1 '("Fred" 10.5)))&lt;br /&gt;  (pp (sql-execute-prepared-statement stmt1 '("Joe" 5.5)))&lt;br /&gt;  (sql-close-statement stmt1)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  (pp (sql-execute-prepared-statement stmt2 '(4.5)))&lt;br /&gt;  (sql-close-statement stmt2))&lt;br /&gt;&lt;br /&gt;;; Close connection&lt;br /&gt;(sql-close-connection)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Result sets are returned as a list of lists i.e. a list of column values for each row in a list for the result set. The first row in the list is the column headings. For dynamic statements, the column data is always a string regardless of the SQL type because this is the way that MySQL sends it and I haven't implemented any type conversions yet. Prepared statements return binary types so I've mapped some of these e.g. strings and numbers into their respective Scheme types.&lt;br /&gt;&lt;br /&gt;I would strongly recommend using prepared statements rather than dynamic statements for performance reasons and also for their natural resistance to SQL injection attacks in web applications.&lt;br /&gt;&lt;br /&gt;Once the library is finished, I'll create a persistence layer that builds on top of the prepared statements to give a framework similar to ActiveRecord in Rails or Hibernate in Java.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3887060946333002264-6192569181697015503?l=andrewwhaley.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrewwhaley.blogspot.com/feeds/6192569181697015503/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andrewwhaley.blogspot.com/2009/04/gambit-mysql-client-02.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/6192569181697015503'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/6192569181697015503'/><link rel='alternate' type='text/html' href='http://andrewwhaley.blogspot.com/2009/04/gambit-mysql-client-02.html' title='Gambit MySQL client 0.2'/><author><name>Andrew Whaley</name><uri>http://www.blogger.com/profile/05346078852977103014</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3887060946333002264.post-1328869502990692854</id><published>2009-04-21T14:10:00.001-07:00</published><updated>2009-06-18T06:39:35.473-07:00</updated><title type='text'>MySQL Interface for Gambit</title><content type='html'>As you've probably already realised, I'm a huge fan of the &lt;a href="http://dynamo.iro.umontreal.ca/~gambit/wiki/index.php/Main_Page"&gt;Gambit Scheme&lt;/a&gt; implementation which is highly performant and compiles into a standalone executable.&lt;br /&gt;&lt;br /&gt;Gambit has also been proven to support tens of thousands of concurrent lightweight threads which helps make it an ideal platform for web applications. This coupled with it's rare ability to serialize continuations places it as a front runner for web applications in the 21st century.&lt;br /&gt;&lt;br /&gt;Unfortunately there is little infrastructure there at present to support web applications ... or so I thought. It turns out that a tremendous amount of effort has gone into developing a framework called '&lt;a href="http://dynamo.iro.umontreal.ca/~gambit/wiki/index.php/Black_Hole"&gt;Black Hole&lt;/a&gt;' by Per Eckerdal and Mikael More. This is a continuations based framework that is built on top of a module system for Gambit. I look forward to seeing this being released in the very near future.&lt;br /&gt;&lt;br /&gt;To support this effort, I have developed a pure Scheme MySQL interface for Gambit that is currently in the &lt;a href="http://dynamo.iro.umontreal.ca/~gambit/wiki/index.php/Dumping_Grounds"&gt;Gambit Dumping Grounds&lt;/a&gt;. The advantage of a pure Scheme implementation rather than a C binding is that it won't block your thousands of lightweight threads whilst your OS thread is stuck in C land.&lt;br /&gt;&lt;br /&gt;Currently the implementation supports logging on with new and old authentication methods, switching schema's and DML and DDL using dynamic queries. I'm currently adding support for prepared statements which I would consider essential before building a persistence layer for Black Hole or anything else.&lt;br /&gt;&lt;br /&gt;I'd love to do the same for Oracle but unfortunately Oracle don't publish the protocol for SQL*Net so this is not possible. Hopefully Gambit will devise a way to call C with an OS thread so as not to block the lightweight threads and then we can use the OCI interface.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3887060946333002264-1328869502990692854?l=andrewwhaley.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrewwhaley.blogspot.com/feeds/1328869502990692854/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andrewwhaley.blogspot.com/2009/04/mysql-interface-for-gambit.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/1328869502990692854'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/1328869502990692854'/><link rel='alternate' type='text/html' href='http://andrewwhaley.blogspot.com/2009/04/mysql-interface-for-gambit.html' title='MySQL Interface for Gambit'/><author><name>Andrew Whaley</name><uri>http://www.blogger.com/profile/05346078852977103014</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3887060946333002264.post-2976674622724714394</id><published>2009-04-21T14:06:00.000-07:00</published><updated>2009-06-18T06:39:35.473-07:00</updated><title type='text'>Functional Programming Languages</title><content type='html'>&lt;style type="text/css"&gt;  &lt;!--   @page { margin: 2cm }   H1 { margin-bottom: 0.11cm }   H1.western { font-family: "Arial", sans-serif; font-size: 16pt }   H1.cjk { font-family: "DejaVu Sans"; font-size: 16pt }   H1.ctl { font-family: "Arial", sans-serif; font-size: 16pt }   P { margin-bottom: 0.21cm }  --&gt;&lt;/style&gt;&lt;p class="western" style="margin-bottom: 0cm;"&gt;We’ve had Structured Programming, we’ve got Object Orientation, could Functional Programming be the next big thing ?&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;In the 1950’s high level programming languages were limited to Fortran, Algol, Cobol and Lisp. Most of the languages that we use today are derived from Algol, an imperative language. An imperative language is one which is built of statements that change state, named after the imperative mood in natural languages which expresses commands to take action. Our structured programming in C created structures or records containing data that we modified through functions or procedures – an example of an imperative style. With the advent of rich GUI applications in the 1990’s, this approach became untidy because although the structures were similar for different GUI components, the behaviour was different. This led to the much needed development of object orientation with C++. Object orientation is further refinement and development of the imperative style.&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;One of the most popular languages of recent times, Java, is a near perfect example of an OO language since it was primarily designed for developing portable GUI applications – Applets. It seems strangely ironic, therefore, that very few GUI applications are developed with Java and instead we use it mainly for developing server-side web applications. There are a wealth of web frameworks available in Java but despite this, Java it is still not the most productive language or the least error prone language for this purpose. Web applications are highly concurrent and shared state implicit in an imperative programming style can create many problems.  &lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;We have all seen the obvious failures where the wrong data is revealed to the wrong customer because the code has failed to do adequate checking but these are only the cases where the data has made it on to the web pages. For every one of these, there will be countless other bugs where incorrect concurrent data access causes subtle error conditions resulting in random error pages rather than such obvious failings. These failings can sometimes be difficult to recreate and may not be in your own code, these could be bugs in the web framework that you are using, the application server or even the JVM itself - all written in an imperative style. Adding controls such as synchronisation around data to prevent concurrent modification necessarily introduces performance bottlenecks. With multiple CPU’s and increasing numbers of cores per CPU these problems will get greater rather than lesser over the coming years.&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;“&lt;i&gt;In a concurrent world, imperative is the wrong default !”&lt;/i&gt; – Tim Sweeney, Epic Games&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;So if imperative programming is such a bad fit for our modern concurrent world, what’s the alternative ?  &lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;In the 1950’s, Lisp had a functional approach where there was little or no shared state and instead data is passed as arguments, often in a list, in function calls i.e. on a stack rather than a shared heap. This seemingly innocuous difference leads to some major differences in program structure and language features. Some of these features such as closures and continuations have been adopted by some of the newer dynamic but essentially imperative languages like Ruby and have been attributed with increasing productivity and expressiveness. Lisp survives on today in the form of Common Lisp and Scheme and although not widely used outside academia, both are enjoying renewed interest in recent years. Scheme, in particular, has seen an explosion of interest from developers becoming disillusioned with the mainstream commercial imperative languages. Scheme has been used as a teaching language at some of the prestige technical universities for many years but is now finding its way into niche commercial and open source applications, one example being the GIMP image manipulation software.&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;Another branch of functional languages derived from the 1970’s language ML include OCAML, Erlang and Haskell which again have seen a big growth in interest in recent years. OCAML has gained popularity in military and investment banking applications. Microsoft is about to release its own functional language based on ML called F#.&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;Lisp suffered a big drop in popularity when the AI research of the 1970’s failed to deliver on earlier promises and at around the same time people were beginning to do great things with C. C, with its simpler requirements for compiler technology, was perceived as fast and efficient and its imperative style suited the single-threaded applications being developed at the time. By comparison, Lisp was perceived as slow and bloated and difficult to work with. Nowadays, in Scheme’s case, the core language has been simplified and streamlined and compiler technology has improved enormously and the best Scheme and OCAML compilers can produce single-threaded code that runs at similar speeds or even slightly faster than C code. Parallel code often runs many times faster because there is little need for synchronisation. Similarly, large tasks can be effortlessly broken into many pieces and executed in parallel on many cores or distributed over many machines – a task that is not easy to achieve with Java or C#.&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;The benefits of a functional approach are not just increased performance and the removal of concurrency errors though; one functional language feature is particularly suited to web applications: continuations.&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;The stateless nature of the web introduces its own problems. Business processes are inherently stateful and yet the HTTP protocol is inherently stateless. This means that web frameworks have to implement ‘sessions’ either in memory or a database and track them through cookie values or rewritten URL’s. Business processes then need to be broken down into various discrete steps, each one corresponding with a HTTP request / response pair, and the application then needs to retrieve the state from the previous steps, perform the current step and then persist the data ready for the next step. This extra complexity is necessary because of the discontinuous nature imposed by the protocol.&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;Ideally, an application would start the process and then ‘call out’ to a user to grab the data needed for the next step and then continue the process within the same procedure so all the local state is still in scope i.e. turning the protocol inside out. Continuations permit this approach.&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;“&lt;i&gt;It's amazing that this single higher abstraction can make such a tremendous difference in your Web programming, but it really does. If the Java language had native support for continuations, we'd all be coding this way.”&lt;/i&gt; – Bruce Tate, IBM&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;Most languages support continuations of some form, e.g. the humble ‘return’ or ‘break’ statement present in most imperative languages is an example of an ‘escaping continuation’ that can be used to prematurely exit from a block of code. First class continuations present in Scheme allow continuations to be used not only for escapes but also for arbitrary jumps (with state) and they are reusable i.e. they can be invoked many times. Some Scheme implementations even allow continuations to be serialised to disk or a database and then can be later invoked even though the process that they once existed in has long since gone. This is only possible because all the required state existed on the local stack at the time the continuation was captured and is not reliant on other unknown data existing in the process heap space – the essence of a functional style.&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;These two reasons alone show how any functional language that supports first class continuations would be a far better choice for web applications than our current imperative languages but there is another, rarely mentioned, problem particularly with Java that could be addressed: poor productivity.&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;It seems strange that we have gone from writing business applications in dedicated and productive 4GL’s like PowerBuilder, Oracle Forms, etc a few years ago to using a general purpose 3GL like Java. It is probably no coincidence that there is now a shortage of developers and development projects often overrun on time and cost. Yet nobody in the lucrative software development industry talks about lost productivity, they merely claim that projects are more complex now.   &lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;Scheme and Common Lisp have two other rare features that makes them compelling and could help recover the lost productivity that we have seen in the move to Java and distributed systems : Homoiconicity and Metalinguistic Abstraction.&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;Homoiconicity is a word coined to describe the fact that the language source code is itself a data structure within the language or in other words, there is uniformity between code and data. Code can become data and data can become code. This means that programs can not only manipulate data (as you’d expect) but they can also manipulate code.&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;This opens up the opportunity for metalinguistic abstraction or creating abstractions above the base language that then become part of the language i.e. syntactic extension. In simple terms, this means that macros can be used to extend the syntax of the language and create meta-languages. This allows you to readily create a domain specific language (DSL) just for web applications or any other purpose. In fact most Lisp programs end up being a DSL for the problem being solved. This approach magnifies the reuse potential of language features since anywhere where syntax is repeated, an abstraction can be created and reused without the fear of introducing new bugs. Most languages allow you to extend and reuse data types but Lisp based languages are some of the very few that allow you to do the same for syntax.&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;Metalinguistic abstraction is certainly not unknown in Java applications, most web frameworks rely on XML to create the abstractions that can’t be done in Java. In fact XML has a very similar structure to the nested lists of Lisp S-expressions. The disadvantages of using XML for abstraction is that it is not integrated with the language so you can’t mix XML tags with java code and, of course, your application becomes messy because the logic spans numerous Java classes and XML files. Being able to create those abstractions in the core language would certainly improve readability, reduce defects and improve productivity. Interestingly Ruby on Rails does away with XML files by using Ruby mixins to create abstractions – few would disagree that Rails is more productive than a comparable Java framework. Macros in Scheme or Lisp go further still and produce very concise web specific code particularly when combined with a continuations based web framework. And unlike Ruby this is compiled code running at native code speeds and can safely be highly parallel in nature.&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;Functional languages are slowly emerging from niche areas but given the utter domination of imperative languages and the enormous established commercial interests around them, business adoption is likely to be slow initially. Given the advantages offered though, early adopters could gain significant commercial advantages over their competitors albeit at the probable cost of some early pain. Functional programming is a paradigm shift and requires developers to almost learn programming again from basic principles.&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;Hybrid languages like Scala for the JVM have recently emerged that allow functional programming to be mixed with imperative and build upon the existing tools and libraries already available for the Java platform. Whilst Scala pushes JVM development forward, there is still a danger that developers will continue using an imperative style and miss the benefits being offered.  &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3887060946333002264-2976674622724714394?l=andrewwhaley.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrewwhaley.blogspot.com/feeds/2976674622724714394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andrewwhaley.blogspot.com/2009/04/functional-programming-languages.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/2976674622724714394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/2976674622724714394'/><link rel='alternate' type='text/html' href='http://andrewwhaley.blogspot.com/2009/04/functional-programming-languages.html' title='Functional Programming Languages'/><author><name>Andrew Whaley</name><uri>http://www.blogger.com/profile/05346078852977103014</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3887060946333002264.post-811929513727293352</id><published>2008-12-11T03:13:00.000-08:00</published><updated>2009-06-18T06:40:26.266-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Functional Web Development with SISCWeb</title><content type='html'>Functional paradigms offer some innovative solutions to long standing Web development problems :-&lt;br /&gt;&lt;br /&gt;1. Continuations fix the inversion of control problem caused by the stateless nature of HTTP. With continuations you can start a function and define some variables you can then 'call out' to the user i.e. send them a page. When the user responds, your function continues where it left off with all the variables still in scope. This means no need for hidden variables, sessions packed with transient data etc. Imagine now that your entire business process is now captured in one easy to read function, not spread over numerous java classes with varied XML structures.&lt;br /&gt;&lt;br /&gt;2. Concurrency problems with poorly defined static variables leaking confidential data to the wrong customers are a thing of the past. Everything is passed on the stack as function arguments - there is no mutating state shared between requests. This also makes the application highly scaleable.&lt;br /&gt;&lt;br /&gt;3. Security - the continuations approach means that the only way to link one page to another is via a continuation which is unique to each user. This means that data-driven attacks i.e. manipulating keys in forms to get access to data won't work - you can only access data within your continuation.&lt;br /&gt;&lt;br /&gt;Try it with &lt;a href="http://siscweb.sourceforge.net/overview.html"&gt;SISCWeb&lt;/a&gt; - a Scheme continuations based framework that runs on top of J2EE. This allows you to reuse all of your Java libraries and business components but benefit from a functional presentation layer. Also being Scheme based, it offers an embedded 'REPL' so you can build and change your application on the fly without restarting Tomcat or losing existing application state.&lt;br /&gt;&lt;br /&gt;It's even better than Ruby on Rails but don't tell anyone - they'll all be using it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3887060946333002264-811929513727293352?l=andrewwhaley.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrewwhaley.blogspot.com/feeds/811929513727293352/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andrewwhaley.blogspot.com/2008/12/functional-web-development-with-siscweb.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/811929513727293352'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/811929513727293352'/><link rel='alternate' type='text/html' href='http://andrewwhaley.blogspot.com/2008/12/functional-web-development-with-siscweb.html' title='Functional Web Development with SISCWeb'/><author><name>Andrew Whaley</name><uri>http://www.blogger.com/profile/05346078852977103014</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3887060946333002264.post-5827440172179050656</id><published>2008-11-10T13:07:00.000-08:00</published><updated>2008-11-10T13:28:06.069-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ecology'/><title type='text'>Manchester-on-Sea</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/__-F14_sObgw/SRikX_afz6I/AAAAAAAAAAM/qxIKeDa5V3I/s1600-h/ManchesterExtract.gif"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 305px; height: 240px;" src="http://1.bp.blogspot.com/__-F14_sObgw/SRikX_afz6I/AAAAAAAAAAM/qxIKeDa5V3I/s320/ManchesterExtract.gif" alt="" id="BLOGGER_PHOTO_ID_5267140496276311970" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I read recently on the BBC news website that both the Greenland and Antarctic ice sheets are melting three times faster than previously thought. If both of these ice sheets melted completely, sea levels would rise by around 70 metres !&lt;br /&gt;&lt;br /&gt;Hopefully we are not in any immediate danger of this happening but it set me wondering what Britain would look like if sea levels rose by 70m.&lt;br /&gt;&lt;br /&gt;I dug out some old &lt;a href="http://www.trailgauge.co.uk/"&gt;Trailgauge&lt;/a&gt; code that I had and some elevation data that I had and generated a map.&lt;br /&gt;&lt;br /&gt;Surprisingly, most of Scotland and Wales escape with minimal land loss. The effect for southern England, however, would be rather more catastrophic. You can see the &lt;a href="http://www.trailgauge.co.uk/images/ManchesterOnSea.jpg"&gt;full map here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The good news for us northerners is that Manchester is transformed into an elegant seaside resort - perhaps it might be elegant if it wasn't overpopulated from all the refugees from the completely submerged Merseyside and Cheshire.&lt;br /&gt;&lt;br /&gt;If you want to see what happens to your town or you want to model different sea levels rises, you can &lt;a href="http://www.trailgauge.co.uk/uk-sea-level.zip"&gt;download the utility&lt;/a&gt; that I created and try it yourself. It's a Windows command-line utility that generates the map and lists any towns that match your search and gives you their new elevation above sea level, e.g. :-&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style=";font-family:Arial;font-size:85%;"  &gt;C:\Data\sealevel&gt;sealevel 70 manchester&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:Arial;font-size:85%;"  &gt;Rendering "sealevel.bmp" for sea level = 70m.&lt;/span&gt; &lt;/p&gt;  &lt;p&gt;&lt;span style=";font-family:Arial;font-size:85%;"  &gt;Manchester Ship Canal (13500, 8821) submerged&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:Arial;font-size:85%;"  &gt;Manchester (13856, 9004) = 5m&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:Arial;font-size:85%;"  &gt;Godmanchester (15249, 7703) submerged&lt;/span&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3887060946333002264-5827440172179050656?l=andrewwhaley.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrewwhaley.blogspot.com/feeds/5827440172179050656/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andrewwhaley.blogspot.com/2008/11/manchester-on-sea.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/5827440172179050656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/5827440172179050656'/><link rel='alternate' type='text/html' href='http://andrewwhaley.blogspot.com/2008/11/manchester-on-sea.html' title='Manchester-on-Sea'/><author><name>Andrew Whaley</name><uri>http://www.blogger.com/profile/05346078852977103014</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/__-F14_sObgw/SRikX_afz6I/AAAAAAAAAAM/qxIKeDa5V3I/s72-c/ManchesterExtract.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3887060946333002264.post-9156622651538409914</id><published>2008-11-08T14:11:00.000-08:00</published><updated>2009-06-18T06:39:35.473-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Have we lost our way ?</title><content type='html'>I've been using Java since 1995 so must be one of the most experienced Java developers around but despite years of my life invested in this technology, I'm increasingly thinking that this has been a mistake.&lt;br /&gt;&lt;br /&gt;When I first used Java, it was for writing Applets which is what it was really designed for i.e. object-oriented with a ready set of libraries for GUI widgets (AWT) and everything built-in to download and execute within a web page. Having come from C where it was very hard to build a GUI, Java was a huge step forward. How ironic, therefore, that I've never seen another decent Java GUI apart from Eclipse in all these years and instead we now use Java almost exclusively server-side for writing web applications and business components.&lt;br /&gt;&lt;br /&gt;The types of applications that we build are invariably web applications with a database backend i.e. replacements for the old client/server applications that we wrote 10 - 15 years ago using 4GL's like Oracle Forms, dBase, Ingres OpenRoad, Pick or in my case Dataflex.&lt;br /&gt;&lt;br /&gt;Java is an object-oriented general purpose 3GL and we are using it to write apps that we would have written with a 4GL ! Is it any wonder that there are so many Java jobs advertised or that organisations are having to recruit armies of programmers in India just to get their work done ? Productivity has nosedived.&lt;br /&gt;&lt;br /&gt;I used to write entire modules (say 10 use cases) in Dataflex in a couple days. Now it takes me 2 - 3 weeks in Java even using the best frameworks the world has to offer. And using these 'great' frameworks I end up with dozens of Java files all glued together with untidy XML - what great progress when I would have had one or two Dataflex source files !&lt;br /&gt;&lt;br /&gt;OK Java is a general purpose langauge and I can do things in Java that I could never have done in Dataflex but then how often do I need to do this ? In Dataflex, I could have glued some C code in to do something unusual if necessary, painful but still a possibility.&lt;br /&gt;&lt;br /&gt;I've recently completed a couple of projects in Ruby on Rails and it has really opened my eyes to this situation that we've gotton ourselves into. Rails offers a big increase in productivity over Java but partly because it's a script langauge so it saves on the edit/compile/deploy debug cycle.  One nice thing is that there is no nasty XML, all the code is in your Ruby source files. This means that it can be syntax checked by your editor and everything reads together. I don't particularly like Ruby as I find the syntax untidy and not intuitive. Java has a simpler and more regular syntax so is easier to learn, but there is no denying that Ruby on Rails is more productive partly because Rails uses mixins and symbols to create a semi-Domain Specific Langauge for web apps.&lt;br /&gt;&lt;br /&gt;So why do all these Java frameworks rely on XML ? Simple - XML is being used to supplement the language because it's not extendable. People are trying to create a Domain Specific Language DSL, a higher level language, dare I say it - a 4GL but the language won't let them. Instead they are forced to use a data structure (XML) to do this. This is bad because the data structure is not a language and can't contain any logic. So we end up with more and more convoluted and unfathomable XML and masses of disconnected Java classes e.g. Spring - nice try but wrong approach. We have lost our way.&lt;br /&gt;&lt;br /&gt;So, how do we get out of this mess and recover our productivity ?&lt;br /&gt;&lt;br /&gt;Having recently discovered Functional Programming through Scheme (a Lisp dialect), I can easily see how Scheme would readily support the creation of a high level DSL whilst offering the full power of the underlying language. There aren't many people using Scheme at the moment so not many frameworks out there but there is a growing following and it feels right.&lt;br /&gt;&lt;br /&gt;Maybe Scala is the answer ? Scala is a replacement Object Oriented language for the JVM that also supports functional programming.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3887060946333002264-9156622651538409914?l=andrewwhaley.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrewwhaley.blogspot.com/feeds/9156622651538409914/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andrewwhaley.blogspot.com/2008/11/have-we-lost-our-way.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/9156622651538409914'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/9156622651538409914'/><link rel='alternate' type='text/html' href='http://andrewwhaley.blogspot.com/2008/11/have-we-lost-our-way.html' title='Have we lost our way ?'/><author><name>Andrew Whaley</name><uri>http://www.blogger.com/profile/05346078852977103014</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3887060946333002264.post-312158897118817803</id><published>2008-11-06T04:34:00.002-08:00</published><updated>2009-06-18T06:40:26.266-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Luhn's algorithm in Scheme</title><content type='html'>I came across &lt;a href="http://en.wikipedia.org/wiki/Luhn_algorithm"&gt;Luhn's algorithm&lt;/a&gt; yesterday whilst trying to resolve a work related issue and was surprised to find an implementation in Scheme for it on &lt;a href="http://andrewdashin.com/luhn-scheme-implementation.aspx"&gt;Andrew Dashin's blog&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Looking at Andrew's implementation, it struck me as being a not very scheme-like implementation because it used an iterator (do) and mutating variables (set!). This gave me an opportunity to test my new found Scheme skills :-&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(&lt;b&gt;define&lt;/b&gt; (luhn-check account-number)&lt;br /&gt;  (&lt;b&gt;letrec&lt;/b&gt; ( &lt;br /&gt;      (digit (&lt;b&gt;lambda&lt;/b&gt; (str pos) (string-&amp;gt;number (string (string-ref str pos)))))    &lt;br /&gt;      (add-digits (&lt;b&gt;lambda&lt;/b&gt; (str)&lt;br /&gt;        (+ (digit str 0) (if (&amp;gt; (string-length str) 1)(digit str 1) 0))           &lt;br /&gt;       ))    &lt;br /&gt;      (luhn-pair (&lt;b&gt;lambda&lt;/b&gt; (x) &lt;br /&gt;        (+ (digit account-number x) &lt;br /&gt;         (&lt;b&gt;if&lt;/b&gt; (&amp;gt; x 0) (add-digits (number-&amp;gt;string (* (digit account-number (- x 1)) 2))) 0)&lt;br /&gt;         (&lt;b&gt;if&lt;/b&gt; (&amp;gt; x 1) (luhn-pair (- x 2)) 0))&lt;br /&gt;      )))    &lt;br /&gt;      (luhn-pair (- (string-length account-number) 1))&lt;br /&gt;    )&lt;br /&gt;  )&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;It takes a string and returns a number which should be a multiple of 10 for a valid mod 10 check or a multiple of 11 for a valid mod 11 check.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3887060946333002264-312158897118817803?l=andrewwhaley.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andrewwhaley.blogspot.com/feeds/312158897118817803/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://andrewwhaley.blogspot.com/2008/11/luhns-algorithm-in-scheme.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/312158897118817803'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3887060946333002264/posts/default/312158897118817803'/><link rel='alternate' type='text/html' href='http://andrewwhaley.blogspot.com/2008/11/luhns-algorithm-in-scheme.html' title='Luhn&apos;s algorithm in Scheme'/><author><name>Andrew Whaley</name><uri>http://www.blogger.com/profile/05346078852977103014</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
