<?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-6102611449527699173</id><updated>2011-12-13T14:18:51.160-08:00</updated><category term='negatives'/><category term='handsets'/><category term='xecute'/><category term='me'/><category term='wiki'/><category term='introduction'/><category term='documentation'/><category term='enterprise 2.0'/><category term='relational'/><category term='scope'/><category term='Caché Objects'/><category term='front-end'/><category term='legacy systems'/><category term='gotchas'/><category term='ESME'/><category term='medical records'/><category term='method generators'/><category term='rob tweed'/><category term='life'/><category term='database structures'/><category term='positives'/><category term='regex'/><category term='VistA'/><category term='SAP'/><category term='applications'/><category term='android'/><category term='caché community'/><category term='iterator'/><category term='tablets'/><category term='csp'/><category term='Cache ObjectScript'/><category term='twistah'/><category term='ehr'/><category term='zen'/><category term='eiffel'/><category term='nosql'/><category term='patient records'/><category term='code'/><category term='open standards'/><category term='health'/><category term='mumps'/><category term='iterator quest'/><title type='text'>How I Learned To Stop Worrying And ... er ... Accept Caché ObjectScript</title><subtitle type='html'>Caché ObjectScript with a 2.0 attitude</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>35</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-3169696936135712112</id><published>2011-04-21T02:12:00.000-07:00</published><updated>2011-04-21T02:13:17.860-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='handsets'/><category scheme='http://www.blogger.com/atom/ns#' term='mumps'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'></title><content type='html'>Wow. &lt;a href="http://omahadave.com/MumpsBlog.html"&gt;This guy has ported Mumps to Android&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Nice.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-3169696936135712112?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/3169696936135712112/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=3169696936135712112' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/3169696936135712112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/3169696936135712112'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2011/04/wow.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-8564862270325459025</id><published>2010-09-28T22:22:00.000-07:00</published><updated>2010-09-28T22:25:41.679-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scope'/><category scheme='http://www.blogger.com/atom/ns#' term='rob tweed'/><title type='text'></title><content type='html'>I'm still &lt;a href="http://groups.google.co.uk/group/comp.lang.mumps/browse_thread/thread/f55f57bbedcc8c41#"&gt;sparring &lt;/a&gt;with Rob Tweed over MUMPS's dynamic scoping.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-8564862270325459025?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/8564862270325459025/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=8564862270325459025' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/8564862270325459025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/8564862270325459025'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2010/09/im-still-sparring-with-rob-tweed-over.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-5543460607241716791</id><published>2010-09-26T10:15:00.000-07:00</published><updated>2010-09-26T10:18:20.125-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scope'/><category scheme='http://www.blogger.com/atom/ns#' term='Cache ObjectScript'/><category scheme='http://www.blogger.com/atom/ns#' term='mumps'/><title type='text'></title><content type='html'>The Mumps scope conversation is hotting up (see &lt;a href="http://programmers.stackexchange.com/questions/5490/is-mumps-alive/"&gt;Rob's answer&lt;/a&gt; and comments). And he leads me to a &lt;a href="http://carlo-hamalainen.net/blog/?p=580"&gt;new MUMPS blog&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-5543460607241716791?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/5543460607241716791/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=5543460607241716791' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/5543460607241716791'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/5543460607241716791'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2010/09/mumps-scope-conversation-is-hotting-up.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-455724726583340328</id><published>2010-09-20T12:53:00.001-07:00</published><updated>2010-09-20T12:54:59.601-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='nosql'/><category scheme='http://www.blogger.com/atom/ns#' term='mumps'/><title type='text'></title><content type='html'>I just &lt;a href="http://programmers.stackexchange.com/questions/5490/is-mumps-alive"&gt;answered a question&lt;/a&gt; about MUMPS on programmers.stackexchange.com&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Having been out of that world for a couple of years, my thinking is that the NoSQL movement is probably the best and worst thing to happen to MUMPS. Ultimately it's likely to both vindicate and kill it. Because somebody, at some point, is going to reinvent MUMPS's database and query structure almost identically, but with no connection to the MUMPS tradition. Then people will rave about this new storage system. But no-one will ever choose a MUMPS derivative again.&lt;br /&gt;&lt;br /&gt;For example, a month or two ago, I was talking with a colleague about using redis to cache a look-up of something in our Django application. We had a large number of records addressed by a triple of three keys, and needed to quickly get subsets matching one or two of these keys (but different combinations at different times).&lt;br /&gt;&lt;br /&gt;This is the kind of thing that MUMPS eats for breakfast. But we were finding it hard to squash into redis's key,val pair structure. Even with dictionaries. (Same would be true of memcached etc.) For the first time in my life, I found myself actually regretting that I couldn't write this module in Cache ObjectScript.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-455724726583340328?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/455724726583340328/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=455724726583340328' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/455724726583340328'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/455724726583340328'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2010/09/i-just-answered-question-about-mumps-on.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-425075553102214077</id><published>2010-09-15T10:07:00.000-07:00</published><updated>2010-09-15T10:08:49.716-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tablets'/><category scheme='http://www.blogger.com/atom/ns#' term='health'/><category scheme='http://www.blogger.com/atom/ns#' term='front-end'/><title type='text'></title><content type='html'>Dell Streak tablets &lt;a href="http://www.zdnet.com/blog/btl/dells-enterprise-streak-plan-target-verticals-like-healthcare/39121?tag=nl.e589"&gt;part of&lt;/a&gt; their health-care strategy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-425075553102214077?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/425075553102214077/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=425075553102214077' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/425075553102214077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/425075553102214077'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2010/09/dell-streak-tablets-part-of-their.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-2145984933716060514</id><published>2010-07-23T03:05:00.001-07:00</published><updated>2010-07-23T03:07:55.143-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VistA'/><category scheme='http://www.blogger.com/atom/ns#' term='medical records'/><category scheme='http://www.blogger.com/atom/ns#' term='health'/><category scheme='http://www.blogger.com/atom/ns#' term='mumps'/><title type='text'></title><content type='html'>Andy Oram at O'Reilly &lt;a href="http://radar.oreilly.com/2010/07/vista-scenarios-and-other-cont.html"&gt;on VistA.&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;I wouldn't dare guess whether VistA will continue as a niche product or will suddenly emerge to eat up the U.S. market for electronic medical systems. But I think it's definitely something to watch.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-2145984933716060514?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/2145984933716060514/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=2145984933716060514' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/2145984933716060514'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/2145984933716060514'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2010/07/andy-oram-at-oreilly-on-vista.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-7955770032099578684</id><published>2010-06-21T11:17:00.000-07:00</published><updated>2010-06-21T11:21:58.414-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='patient records'/><title type='text'></title><content type='html'>Philip Greenspun's &lt;a href="http://philip.greenspun.com/politics/health-care-reform"&gt;suggestions&lt;/a&gt; for reform of the US Health system.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-7955770032099578684?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/7955770032099578684/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=7955770032099578684' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/7955770032099578684'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/7955770032099578684'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2010/06/philip-greenspuns-suggestions-for.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-6926941773230637129</id><published>2010-06-11T08:05:00.001-07:00</published><updated>2010-06-11T08:05:56.643-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='health'/><title type='text'></title><content type='html'>&lt;a href="http://radar.oreilly.com/2010/06/here-come-healthcare-apps.html"&gt;Here come the healthcare apps.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-6926941773230637129?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/6926941773230637129/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=6926941773230637129' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/6926941773230637129'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/6926941773230637129'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2010/06/here-come-healthcare-apps.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-439223263703401589</id><published>2010-03-12T02:09:00.000-08:00</published><updated>2010-03-12T02:11:20.235-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='patient records'/><category scheme='http://www.blogger.com/atom/ns#' term='health'/><category scheme='http://www.blogger.com/atom/ns#' term='open standards'/><title type='text'></title><content type='html'>Tim O'Reilly &lt;a href="http://radar.oreilly.com/2010/03/nhin-direct-open-healthcare-an.html"&gt;on open patient record initiatives&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-439223263703401589?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/439223263703401589/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=439223263703401589' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/439223263703401589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/439223263703401589'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2010/03/tim-oreilly-on-open-patient-record.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-3938798969929138412</id><published>2009-06-30T16:28:00.000-07:00</published><updated>2009-06-30T16:56:38.154-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='me'/><title type='text'></title><content type='html'>OK. It's been six months or more since I last updated this blog.&lt;br /&gt;&lt;br /&gt;Astute readers will probably have realized that I've fallen out of the Cache world. My day-job is now working with Python and Django which, of course, makes me very happy.&lt;br /&gt;&lt;br /&gt;But I have a bit of sadness too. I learned a LOT from working with Cache and ObjectScript. Some of it was painful. Some of it was weird. But much was enlightening. I often found myself realizing how &lt;span style="font-style:italic;"&gt;different&lt;/span&gt; a programmer's world could be from that which I considered mainstream. I'm grateful that I had the chance to experience that. It made me a better (and humbler) programmer. Humbler because it doesn't matter how bad something looks, chances are it may have seemed, or even been, the right solution to some problem, somewhere, somewhen. Seeing that, teaches &lt;span style="font-style:italic;"&gt;perspective&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Furthermore, I stand by the things I've &lt;a href="http://cachetastic.blogspot.com/2008/06/hi-my-name-is-phil-and-im.html"&gt;written&lt;/a&gt; &lt;a href="http://cachetastic.blogspot.com/2008/07/ok-after-mentioning-some-bad-things.html"&gt;before&lt;/a&gt;. I still believe that both the theme of old-skool legacy medical systems coming to terms with the modern web 2.0 environment, and Intersystems' platform's potential for reinventing itself, are interesting.&lt;br /&gt;&lt;br /&gt;I'd like to know more and follow both. OTOH, my new day-job and new set of concerns are taking up way too much time. If I could, I'd have attended the &lt;a href="http://www.outoftheslipstream.com/node/167"&gt;Slipstream Workshop&lt;/a&gt; this coming week, but as it's a work-day, I won't be able to. Good luck for everyone who's attending, anyway.&lt;br /&gt;&lt;br /&gt;Finally, this is not goodbye. If any MUMPS related thoughts or news comes my way, I'll still pass them on. And if anyone else out there in the Cache or MUMPS communities would like to take over and continue this blog, I'd be happy to add you as a co-author. Just drop me a note in the comments here.&lt;br /&gt;&lt;br /&gt;L8r peeps ...&lt;br /&gt;&lt;br /&gt;PS : I'm extremely impressed with GitHub at the moment. So much so that I've decided that it's worth moving Twistah across to it from the rather unexciting Google Code. The new repository is &lt;a href="http://github.com/interstar/Twistah/tree/master"&gt;http://github.com/interstar/Twistah/tree/master&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-3938798969929138412?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/3938798969929138412/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=3938798969929138412' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/3938798969929138412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/3938798969929138412'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2009/06/ok.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-5291238706758917565</id><published>2008-11-12T11:58:00.000-08:00</published><updated>2008-11-12T12:00:33.909-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='negatives'/><category scheme='http://www.blogger.com/atom/ns#' term='mumps'/><title type='text'></title><content type='html'>The anti-MUMPS troll at the Daily WTF? (admittedly, we've all been there) has &lt;a href="http://thedailywtf.com/Articles/MUMPS-Madness.aspx"&gt;another anti-MUMPS story.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-5291238706758917565?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/5291238706758917565/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=5291238706758917565' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/5291238706758917565'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/5291238706758917565'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/11/anti-mumps-troll-at-daily-wtf.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-8495224968795339159</id><published>2008-10-20T07:27:00.000-07:00</published><updated>2008-10-31T05:29:31.372-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='database structures'/><category scheme='http://www.blogger.com/atom/ns#' term='relational'/><category scheme='http://www.blogger.com/atom/ns#' term='mumps'/><title type='text'></title><content type='html'>If you've been following the discussion over &lt;a href="http://groups.google.com/group/comp.lang.mumps/browse_thread/thread/071ef99948eb9ef3"&gt;Mumps : the IT world's best kept secret?&lt;/a&gt; you'll have noticed that one thing that stands out about Caché / MUMPS is its unusually structured data-store of persistent, multi-dimensional ragged-arrays. And Rob Tweed makes a case that this is a better fit than a relational database for internet scale applications. He cites Google's BigTable and Amazon's S3 as examples of a trend away from relational dbs in favour of key value pairs.&lt;br /&gt;&lt;br /&gt;Today Steve Yegge has &lt;a href="http://steve-yegge.blogspot.com/2008/10/universal-design-pattern.html"&gt;an interesting meditation&lt;/a&gt; on a similar theme, about "domain modelling schools" and the need for programmers to have experience of multiple tools and organizing principles. (And while he doesn't note the MUMPS model, it would be another interesting one to add to the list.)&lt;br /&gt;&lt;br /&gt;Worth reading, also, &lt;a href="http://www.pbs.org/cringely/pulpit/2008/pulpit_20081003_005424.html"&gt;this Cringely piece&lt;/a&gt; on how relational databases don't work so well in a parallel cloud where disk-access is often a bottleneck so more of the live database is moved into memory. (Killer quote : "&lt;em&gt;Google has THE ENTIRE INTERNET IN MEMORY AT ONCE&lt;/em&gt;.") Disk is just used for backup / persistence."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-8495224968795339159?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/8495224968795339159/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=8495224968795339159' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/8495224968795339159'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/8495224968795339159'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/10/if-youve-been-following-discussion-over.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-3615883613162434263</id><published>2008-09-16T06:25:00.001-07:00</published><updated>2008-09-16T06:26:32.768-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mumps'/><title type='text'></title><content type='html'>More discussion of Rob's future of Mumps is &lt;a href="http://groups.google.com/group/comp.lang.mumps/browse_thread/thread/071ef99948eb9ef3"&gt;going on&lt;/a&gt; on the mailing list and in comments to his &lt;a href="http://www.outoftheslipstream.com/node/125"&gt;original post&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-3615883613162434263?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/3615883613162434263/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=3615883613162434263' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/3615883613162434263'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/3615883613162434263'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/09/more-discussion-of-robs-future-of-mumps.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-8336276762082985499</id><published>2008-09-12T14:34:00.001-07:00</published><updated>2008-09-12T14:49:05.791-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='legacy systems'/><category scheme='http://www.blogger.com/atom/ns#' term='mumps'/><title type='text'></title><content type='html'>Rob Tweed asks &lt;a href="http://www.outoftheslipstream.com/node/125"&gt;if MUMPS is dead&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Worth reading his thoughts. Some intriguing ideas, such as his own work making the MUMPS db accessible from Python and other scripting languages, and the parallels between the MUMPS db and Google Application Engine and Amazon's AWS.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-8336276762082985499?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/8336276762082985499/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=8336276762082985499' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/8336276762082985499'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/8336276762082985499'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/09/rob-tweed-asks-if-mumps-is-dead-worth.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-8551360436882120525</id><published>2008-08-07T18:56:00.000-07:00</published><updated>2008-08-07T19:12:12.340-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gotchas'/><title type='text'>Workaround for the Scoping Gotcha</title><content type='html'>My colleague pointed out to me today that you can get around the &lt;a href="http://cachetastic.blogspot.com/2008/08/xecute-scoping.html"&gt;scoping issue&lt;/a&gt; I mentioned by writing your method like this :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; &lt;br /&gt;  Method f() {&lt;br /&gt;    set x = 6&lt;br /&gt;    set m = "write !,"_x ; difference&lt;br /&gt;    xecute m&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;What's the difference? Instead of including the name of the variable x inside the string, you concatenate the value of the local variable x with the string at run-time, before the string is finally evaluated. Because the value of x is resolved &lt;span style="font-style:italic;"&gt;before&lt;/span&gt; the xecute, things work as you'd expect.&lt;br /&gt;&lt;br /&gt;That's true. But I still regard this as a serious bug. An equivalent python program : &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; &lt;br /&gt;class A :&lt;br /&gt;    def f(self) :&lt;br /&gt;        x = 6&lt;br /&gt;        m = "print x"&lt;br /&gt;        exec m&lt;br /&gt;&lt;br /&gt;x = 9&lt;br /&gt;a = A()&lt;br /&gt;a.f()&lt;br /&gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;prints what you'd expect : the number 6.&lt;br /&gt;&lt;br /&gt;What's really going on to cause this issue in Caché? My guess is that the OO layer in Caché is compiled down to plain Caché .int routines which don't have a significantly different semantics or scoping rules to Caché ObjectScript. In order to get the effect of the private world inside the object, at compile time the variable x is renamed to some object-specific equivalent. Of course, this renaming affects the real references to x, but not the string assigned to m. &lt;br /&gt;&lt;br /&gt;When the VM then tries to xecute the string, it encounters the name x but finds no binding in the local execution frame and so, according to COS's dynamic scoping rules, has to look down the stack for a frame which does have a binding, the place from which we call y.f(), where x is bound to 9.&lt;br /&gt;&lt;br /&gt;Of course, this hypothesis might be completely wrong. Expert correction is welcome.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-8551360436882120525?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/8551360436882120525/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=8551360436882120525' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/8551360436882120525'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/8551360436882120525'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/08/workaround-for-scoping-gotcha.html' title='Workaround for the Scoping Gotcha'/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-6635869761288271871</id><published>2008-08-07T07:46:00.000-07:00</published><updated>2008-08-07T07:47:27.761-07:00</updated><title type='text'></title><content type='html'>Don't be confused. &lt;a href="http://objectscript.sourceforge.net/"&gt;This&lt;/a&gt; is NOT Caché ObjectScript. :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-6635869761288271871?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/6635869761288271871/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=6635869761288271871' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/6635869761288271871'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/6635869761288271871'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/08/dont-be-confused.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-1261288563094889722</id><published>2008-08-06T13:05:00.000-07:00</published><updated>2008-08-06T13:41:38.958-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Caché Objects'/><category scheme='http://www.blogger.com/atom/ns#' term='scope'/><category scheme='http://www.blogger.com/atom/ns#' term='Cache ObjectScript'/><category scheme='http://www.blogger.com/atom/ns#' term='xecute'/><title type='text'>Xecute Scoping</title><content type='html'>A nasty gotcha in scoping when you try to use Caché's "interpret a string containing code" command &lt;em&gt;xecute&lt;/em&gt; inside an object.&lt;br /&gt;&lt;br /&gt;You can execute (ie. eval) a string containing a piece of Caché ObjectScript with xecute like this :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;set m = "write 2+2"&lt;br /&gt;xecute m&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;xecute only works on statements, not expressions. But you can use the alternative @ for that. Eg.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;set m = "2+2"&lt;br /&gt;write @m&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;However, if you try to use this inside a class definition, something odd happens.&lt;br /&gt;&lt;br /&gt;When a class is compiled, the string which contains code is obviously not affected by the pre-processor. But it seems that when the method is run and the string xecuted, the &lt;em&gt;variable names&lt;/em&gt; in the string don't get bound to the scope within the method. Instead they get their values from the global frame or somewhere else entirely.&lt;br /&gt;&lt;br /&gt;Look at the following example.&lt;br /&gt;&lt;br /&gt;A class :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Class MY.ScopeGotcha Extends %Persistent [ ClassType = persistent, ProcedureBlock ]&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;  Method f() {&lt;br /&gt;    set x = 6&lt;br /&gt;    set m = "write !,x"&lt;br /&gt;    xecute m&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now try running it from the terminal like this :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; set x = 9&lt;br /&gt; set y = ##class(MY.ScopeGotcha).%New()&lt;br /&gt; do y.f()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Guess what it prints ... :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-1261288563094889722?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/1261288563094889722/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=1261288563094889722' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/1261288563094889722'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/1261288563094889722'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/08/xecute-scoping.html' title='Xecute Scoping'/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-6809007642669335608</id><published>2008-07-29T22:01:00.000-07:00</published><updated>2008-07-29T22:33:32.195-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cache ObjectScript'/><category scheme='http://www.blogger.com/atom/ns#' term='regex'/><title type='text'></title><content type='html'>You know what I really wish? &lt;br /&gt;&lt;br /&gt;I wish Caché had decent regular expressions. The same ones that Perl made ubiquitous and are supported in C++, Java, Python, Ruby, PHP, Javascript and every other language you can think of. &lt;br /&gt;&lt;br /&gt;It's hard to write a &lt;a href="http://code.google.com/p/twistah/"&gt;wiki&lt;/a&gt; without good string processing and regexes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-6809007642669335608?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/6809007642669335608/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=6809007642669335608' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/6809007642669335608'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/6809007642669335608'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/07/you-know-what-i-really-wish-i-wish-cach.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-2725609183884010648</id><published>2008-07-27T08:44:00.000-07:00</published><updated>2008-07-29T22:06:12.021-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Caché Objects'/><category scheme='http://www.blogger.com/atom/ns#' term='documentation'/><title type='text'></title><content type='html'>Intersystems's documentation for Caché is notoriously bad.&lt;br /&gt;&lt;br /&gt;Here's a &lt;a href="http://docs.intersystems.com/csp/docbook/DocBook.UI.Page.cls?KEY=ROBJ_class_super"&gt;classic example&lt;/a&gt; I found today for the "super" keyword. &lt;br /&gt;&lt;br /&gt;Yes, I realize "super" has something to do with super-classes and inheritance and so the "extends" keyword is relevant ... but ... er ... wouldn't you expect the "super" example to actually *use* the "super" keyword? Somewhere?&lt;br /&gt;&lt;br /&gt;Or if there is no "super" keyword, because "extends" is how you declare inheritance relationships, what on earth is this page doing here?&lt;br /&gt;&lt;br /&gt;Update : after further consideration, the only way I can decode this is that "super" is the &lt;a href="http://homepages.tcp.co.uk/~nicholson/alice.html"&gt;name of the list of super-classes.&lt;/a&gt; That's why the super "keyword" can "have a value".&lt;br /&gt;&lt;br /&gt;This is typical of Intersystems' often garbled approach to documentation. Don't they know what the word "&lt;a href="http://en.wikipedia.org/wiki/Keyword_%28computer_programming%29"&gt;keyword&lt;/a&gt;" actually means???&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-2725609183884010648?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/2725609183884010648/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=2725609183884010648' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/2725609183884010648'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/2725609183884010648'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/07/intersystems-documentation-for-cach-is.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-395625123821851521</id><published>2008-07-16T22:51:00.000-07:00</published><updated>2008-07-16T23:13:03.985-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='caché community'/><title type='text'></title><content type='html'>Cool. Someone at George James (who make Caché source-control software) has &lt;a href="http://www.outoftheslipstream.com/node/122"&gt;noticed&lt;/a&gt; this blog. :-)&lt;br /&gt;&lt;br /&gt;When I first started using Caché I went looking on the web and found ... well, not what I was looking for. &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Where are all the Caché blogs?&lt;/blockquote&gt; &lt;br /&gt;&lt;br /&gt;I thought. &lt;br /&gt;&lt;br /&gt;Coming from a world of Python and Erlang and other scripting languages, which are also usually associated with web-applications and often the free-software / open-source movement, I'm used to a very loud bustling chatter as people ask for and offer help, create new applications, celebrate and criticise language features etc.&lt;br /&gt;&lt;br /&gt;Arriving in the Caché ecosystem was, frankly, a bit weird. Like arriving in a ghost-town. Where are all the &lt;em&gt;people&lt;/em&gt;?&lt;br /&gt;&lt;br /&gt;George James was one of the few (well, actually, now I think of it) the only specifically Caché blog I found.&lt;br /&gt;&lt;br /&gt;So where &lt;em&gt;is&lt;/em&gt; everybody? There must be more of us out there? If you have a Caché related blog or wiki or site, drop me a comment and I'll be delighted to add it to my blogroll on the right.&lt;br /&gt;&lt;br /&gt;Update : and of course, if someone from the community wants to point out that I've got it all completely wrong about iterators etc. then that's welcome too.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-395625123821851521?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/395625123821851521/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=395625123821851521' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/395625123821851521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/395625123821851521'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/07/cool.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-1673133425371641034</id><published>2008-07-16T22:34:00.000-07:00</published><updated>2008-07-17T05:30:38.311-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Caché Objects'/><category scheme='http://www.blogger.com/atom/ns#' term='iterator quest'/><category scheme='http://www.blogger.com/atom/ns#' term='iterator'/><category scheme='http://www.blogger.com/atom/ns#' term='Cache ObjectScript'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>The Quest for an ObjectScript Iterator (part 5)</title><content type='html'>In which we take the last post's iterator and simply wrap it inside a Caché Objects class.&lt;br /&gt;&lt;br /&gt;Define a class User.MultiIterator&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;Class User.MultiIterator Extends %Persistent&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;Property i As %String;&lt;br /&gt;Property j As %String;&lt;br /&gt;Property k As %String;&lt;br /&gt;Property val As %String;&lt;br /&gt;&lt;br /&gt;Method startIterator()&lt;br /&gt;{&lt;br /&gt;  set ..i=""&lt;br /&gt;  set ..j=""&lt;br /&gt;  set ..k=""&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Method next()&lt;br /&gt;{&lt;br /&gt;  if (..i="") {&lt;br /&gt;    set ..i=$order(^multi(..i))&lt;br /&gt;    quit ..next()&lt;br /&gt;  }&lt;br /&gt;  if (..j="") {&lt;br /&gt;    set ..j=$order(^multi(..i,..j))&lt;br /&gt;    quit ..next()&lt;br /&gt;  }&lt;br /&gt;  set ..k=$order(^multi(..i,..j,..k))&lt;br /&gt;  if ..k'="" {&lt;br /&gt;    set ..val = $get(^multi(..i,..j,..k))&lt;br /&gt;    quit 1&lt;br /&gt;  }&lt;br /&gt;  set ..j=$order(^multi(..i,..j))&lt;br /&gt;  if ..j'="" {&lt;br /&gt;    quit ..next()&lt;br /&gt;  }&lt;br /&gt;  set ..i=$order(^multi(..i))&lt;br /&gt;  if ..i'="" {&lt;br /&gt;    quit ..next()&lt;br /&gt;  }&lt;br /&gt;  quit 0&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Using it (in another file) is now :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;new it&lt;br /&gt;set it= ##class(User.MultiIterator).%New()&lt;br /&gt;do it.startIterator()&lt;br /&gt;while it.next() {&lt;br /&gt;  write !,it.i_","_it.j_","_it.k_" : "_it.val&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The logic is identical. The only difference, now I've made the i,j and k indices and the val properties of the iterator object rather than local variables passed by reference. It looks perhaps a little cleaner from the user's perspective. OTOH you  have to create an extra class definition routine.&lt;br /&gt;&lt;br /&gt;In the next post I think it's time to start thinking how we can add some filtering to the iterator.&lt;br /&gt;&lt;br /&gt;Update : thanks to 80N for the correct. (Read comments)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-1673133425371641034?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/1673133425371641034/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=1673133425371641034' title='3 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/1673133425371641034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/1673133425371641034'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/07/quest-for-objectscript-iterator-part-5.html' title='The Quest for an ObjectScript Iterator (part 5)'/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-248282744087142464</id><published>2008-07-15T20:20:00.000-07:00</published><updated>2008-08-07T07:41:04.707-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iterator quest'/><category scheme='http://www.blogger.com/atom/ns#' term='iterator'/><category scheme='http://www.blogger.com/atom/ns#' term='Cache ObjectScript'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>The Quest for an ObjectScript Iterator (part 4)</title><content type='html'>Here's a three key iterator that runs through a global called ^multi  :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;StartIterator(&amp;i,&amp;j,&amp;k)&lt;br /&gt;  set i = ""&lt;br /&gt;  set j = ""&lt;br /&gt;  set k = ""&lt;br /&gt;  quit&lt;br /&gt; &lt;br /&gt;Next(&amp;i,&amp;j,&amp;k,&amp;val)&lt;br /&gt;  if (i="") {&lt;br /&gt;    set i=$order(^multi(i))&lt;br /&gt;    quit $$Next(.i,.j,.k,.val)&lt;br /&gt;  }&lt;br /&gt;  if (j="") {&lt;br /&gt;    set j=$order(^multi(i,j))&lt;br /&gt;    quit $$Next(.i,.j,.k,.val)&lt;br /&gt;  }&lt;br /&gt;  set k=$order(^multi(i,j,k))&lt;br /&gt;  if k'="" {&lt;br /&gt;    set val = $get(^multi(i,j,k))&lt;br /&gt;    quit 1&lt;br /&gt;  }&lt;br /&gt;  set j=$order(^multi(i,j))&lt;br /&gt;  if j'="" {&lt;br /&gt;    quit $$Next(.i,.j,.k,.val)&lt;br /&gt;  }&lt;br /&gt;  set i=$order(^multi(i))&lt;br /&gt;  if i'="" {&lt;br /&gt;    quit $$Next(.i,.j,.k,.val)&lt;br /&gt;  }&lt;br /&gt;  quit 0&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;test() &lt;br /&gt;  new i,j,k,val&lt;br /&gt;  do StartIterator(.i,.j,.k)&lt;br /&gt;  while $$Next(.i,.j,.k,.val) {&lt;br /&gt;    write !, i_","_j_","_k_" = "_val&lt;br /&gt;  }&lt;br /&gt;  quit&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see $$Next() starts getting somewhat complicated. Not only long but with various recursive calls to itself. Why is this?&lt;br /&gt;&lt;br /&gt;Well, first, compare what the ordinary nested loop version of this would look like : &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;order()&lt;br /&gt;  new i,j,k&lt;br /&gt;  set i=""&lt;br /&gt;  for { &lt;br /&gt;    set i=$order(^multi(i))   &lt;br /&gt;    quit:i=""&lt;br /&gt;    set j=""&lt;br /&gt;    for { &lt;br /&gt;      set j=$order(^multi(i,j))  &lt;br /&gt;      quit:j=""&lt;br /&gt;      set k=""&lt;br /&gt;      for {&lt;br /&gt;        set k=$order(^multi(i,j,k))&lt;br /&gt;        quit:k=""&lt;br /&gt;        write !,i_","_j_","_k_" = "_^multi(i,j,k)&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  quit&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;For the iterator version, we have to find a way to flatten out that nested structure of $order statements. We also have to cope with the fact that inside our $$Next we don't have any state information except the values of i, j and k. We don't know if j="" because we haven't started looping yet, or because we just reached the end of the js under the current i.  (This is something we do have, for free, in the nested loop version.)&lt;br /&gt;&lt;br /&gt;And when we do do an $order on i, we have to go round and test the j again ... etc. I'm using recursion to do these tests multiple times because it makes the code shorter. &lt;br /&gt;&lt;br /&gt;So why would we prefer the iterator version to the nested loops? Mainly because it decouples the business logic from the details of the data-structure. test() knows nothing of the name or shape of the global. Also, the iterator is reusable many times, but the nested loops will have to be reconstructed whenever we need to run through the global.&lt;br /&gt;&lt;br /&gt;The same principles can be applied to create iterators for globals with more keys, although as the number of keys increases, the size and complexity of the $$Next() function also increases. The pattern remains the same though.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-248282744087142464?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/248282744087142464/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=248282744087142464' title='3 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/248282744087142464'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/248282744087142464'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/07/quest-for-objectscript-iterator-part-4.html' title='The Quest for an ObjectScript Iterator (part 4)'/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-5863709180126701388</id><published>2008-07-14T21:56:00.000-07:00</published><updated>2008-07-14T22:06:03.715-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iterator quest'/><category scheme='http://www.blogger.com/atom/ns#' term='iterator'/><category scheme='http://www.blogger.com/atom/ns#' term='Cache ObjectScript'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>The Quest for an ObjectScript Iterator (part 3)</title><content type='html'>This is the third part of the &lt;a href="http://cachetastic.blogspot.com/search/label/iterator%20quest"&gt;series&lt;/a&gt; on writing "iterators" in Caché ObjectScript that began with an &lt;a href="http://cachetastic.blogspot.com/2008/07/quest-for-objectscript-iterator-part-1.html"&gt;introduction&lt;/a&gt;, and went on to &lt;a href="http://cachetastic.blogspot.com/2008/07/quest-for-objectscript-iterator-part-2.html"&gt;describe Caché's database structure&lt;/a&gt;. The aim is to invent abstractions that lets us loop through a global without knowing anything about its structure.&lt;br /&gt;&lt;br /&gt;This time, I'll keep it short, and just show the simplest COS iterator. Because in these examples, I am using Caché ObjectScript and &lt;em&gt;not&lt;/em&gt; Caché Objects I have no objects to encapsulate index state. So I will use call-by-reference to allow a single Next() function to return both the index and the value of each record which are declared in the caller.&lt;br /&gt;&lt;br /&gt;For a simple single key global (here called ^xs) the definition of the iterator is this :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;StartIterator(&amp;i)&lt;br /&gt;  set i = ""&lt;br /&gt;  quit&lt;br /&gt; &lt;br /&gt;Next(&amp;i,&amp;val)&lt;br /&gt;  set i=$order(^xs(i))&lt;br /&gt;  if i="" { quit 0 }&lt;br /&gt;  set val=$get(^xs(i))&lt;br /&gt;  quit 1&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;And we can use it like so :&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;test()&lt;br /&gt;  new i,val &lt;br /&gt;  do StartIterator(.i)&lt;br /&gt;  while $$Next(.i,.val) {&lt;br /&gt;    write !, i_" : "_val ; example "do something"&lt;br /&gt;  }&lt;br /&gt;  quit&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You'll see that test(), which represents some kind of business logic, has no direct mention of ^xs and no commitment to its structure (except that there is a single index, i which steps through it). &lt;br /&gt;&lt;br /&gt;OK, that's the basic idea. It should be reasonably self-evident if you've even started working with Caché. Next episode, I'll delve into the uglier problems of multi-key globals.&lt;br /&gt;&lt;br /&gt;See? Told you this would be a quick one. :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-5863709180126701388?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/5863709180126701388/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=5863709180126701388' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/5863709180126701388'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/5863709180126701388'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/07/quest-for-objectscript-iterator-part-2_14.html' title='The Quest for an ObjectScript Iterator (part 3)'/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-4755726244792373910</id><published>2008-07-14T08:39:00.000-07:00</published><updated>2008-07-14T08:52:29.983-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='method generators'/><category scheme='http://www.blogger.com/atom/ns#' term='Caché Objects'/><title type='text'>Method Generators</title><content type='html'>Just noticed that you can do interesting compile-time code generation in Caché Objects using &lt;a href="http://docs.intersystems.com/cache20081/csp/docbook/DocBook.UI.Page.cls?KEY=GOBJ_methodgen"&gt;compile-time Method Generators&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Something I'll be investigating shortly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-4755726244792373910?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/4755726244792373910/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=4755726244792373910' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/4755726244792373910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/4755726244792373910'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/07/method-generators.html' title='Method Generators'/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-1541482315148344133</id><published>2008-07-13T16:42:00.000-07:00</published><updated>2008-07-13T19:48:02.066-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iterator quest'/><category scheme='http://www.blogger.com/atom/ns#' term='iterator'/><category scheme='http://www.blogger.com/atom/ns#' term='Cache ObjectScript'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>The Quest for an ObjectScript Iterator (part 2)</title><content type='html'>In this &lt;a href="http://cachetastic.blogspot.com/search/label/iterator%20quest"&gt;series&lt;/a&gt; of blog-posts (starting &lt;a href="http://cachetastic.blogspot.com/2008/07/quest-for-objectscript-iterator-part-1.html"&gt;here&lt;/a&gt;) I'm exploring the issues of maintaining an abstraction layer between Caché database and your business logic. Caché's tight integration of database and program environment tempts away from this. And, in particular, the functions for accessing and looping through tables pull against it.&lt;br /&gt;&lt;br /&gt;In this post, I'll give some background and explanations of how Caché ObjectScript programs see the database. Experienced Caché and MUMPS programmers probably know this already, but new arrivals from other worlds might find it informative.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The Caché database is structured as sparse, multi-dimensional arrays (known as "globals") containing chunks of data in strings. Because the arrays can use strings as indexes (ie. the keys can be strings) meaningful information in a record is usually spread across both the keys and the actual value. &lt;span style="font-style:italic;"&gt;But only keys are easy to search on. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is different from a relational database where all fields are (at least from the SQL writer's perspective) more or less equal.&lt;br /&gt;&lt;br /&gt;Let's create an example. A rather simplistic patient record might be stored something like this : &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;^Patient("general hospital",324542)=john~smith~malaria&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;where the hospital name is the first key, patient id is the second, and the actual data (first name, last name and disease) is encoded as sub-strings (known as "pieces" in Caché terminology) separated by the ~ character.&lt;br /&gt;&lt;br /&gt;Such a database structure makes it easy and very fast, to pull out data if you have all the necessary keys. To get this record from the database into a variable p :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;set p = ^Patient("general hospital",324542)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It's also pretty simple to manipulate a subtree. For example there are operations which can copy an entire subtree to another variable.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;merge gh = ^Patient("general hospital") &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;will grab all general hospital patients and put them into a subtree in the variable gh. &lt;br /&gt;&lt;br /&gt;You can delete subtrees with &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;kill ^Patient("old hospital")&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;etc.&lt;br /&gt;&lt;br /&gt;On the other hand, if you want to find all patients who have malaria, you have a slog. You either have to manually run through all the records checking which contain "malaria" in the disease field of the string. Or, if looking-up patients by disease is a common requirement that needs to be fast, you make a second array as a fast, searchable index, that is structured like this.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;^PatientDiseaseIndex("malaria","general hospital",324542)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And make sure you keep it in sync.&lt;br /&gt;&lt;br /&gt;Iterating through these multi-dimensional arrays is "baroque" to say the least. Caché ObjectScript provides two commands : &lt;span style="font-weight:bold;"&gt;$order&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;$query&lt;/span&gt; for looping through tables.&lt;br /&gt;&lt;br /&gt;$order takes as argument an array descriptor (name and keys), and returns the &lt;em&gt;next&lt;/em&gt; key at the same level of hierarchy as the right-most key listed in the array expression. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Huh?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To make that last sentence clearer, here's an example.&lt;br /&gt;&lt;br /&gt;Let's suppose we have three patient records :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;^Patient("general hospital",324542)=john~smith~malaria&lt;br /&gt;^Patient("general hospital",324549)=martha~jones~measles&lt;br /&gt;^Patient("local clinic",2323)=donna~noble~flu&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Calling the $order function like this : &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$order(^Patient("general hospital",324542)) &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;will return the value 324549. Why? Because 324549 is the &lt;span style="font-style:italic;"&gt;next key&lt;/span&gt; at the "patient id" level of the key indexes.&lt;br /&gt;&lt;br /&gt;Similarly&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$order(^Patient("general hospital")) &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;will return the string "local clinic", because here we're only giving the top-level key of ^Patient. And the next key after "general hospital" is "local clinic".&lt;br /&gt;&lt;br /&gt;Using $order, then, it's possible to loop through each key at a particular level of the hierarchy. It also knows how to find the first key at any level; you simply pass it an empty string. So &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$order(^Patient("")) &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;returns "general hospital", the first top level key. And &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$order(^Patient("general hospital",""))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;returns 324542, the first second level key below "general hospital".&lt;br /&gt;&lt;br /&gt;When the $order runs out of keys at any particular level of a subtree, it returns an empty string.&lt;br /&gt;&lt;br /&gt;For example, &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$order(^Patient("general hospital",324549)) &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;returns "", which signals to us that there are no patient ids after 324549 in the "general hospital" subtree.&lt;br /&gt;&lt;br /&gt;To loop through &lt;em&gt;all&lt;/em&gt; records in the table we have to use nested loops. Typically something like this.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;set hospital=""&lt;br /&gt;for {&lt;br /&gt;  set hospital=$order(^Patient(hospital))&lt;br /&gt;  quit:hospital=""&lt;br /&gt;  set id=""&lt;br /&gt;  for {&lt;br /&gt;    set id=$order(^Patient(hospital,id))&lt;br /&gt;    quit:id=""&lt;br /&gt;    set p = $get(^Patient(hospital,id))&lt;br /&gt;    ... do something with patient p&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In other words, &lt;b&gt;it's a bloody performance!&lt;/b&gt; Especially when you come from the sort of language where you're used to being able to write something like this :&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;for p in Patient {&lt;br /&gt;  ... do something with patient p&lt;br /&gt;} &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;But the problem is far more pernicious than simple verbosity. This code hardwires a great deal of commitment to the particular database structure. Let's suppose we realize at a later date that we really need to add a third key to Patients. For example, our hospital network expands into a neighbouring state and we now need to support a new structure :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;^NewPatient(region,hospital,id)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Migrating the existing data is a bit of work. &lt;span style="font-weight:bold;"&gt;But now every single place in the code that loops through patients looking for records that match some criteria will have to be rewritten as well!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The alternative iterating function $query offers some help. But has its own bizarre qualities.&lt;br /&gt;&lt;br /&gt;Like $order, the $query function takes an array name and keys. But it returns a &lt;span style="font-style:italic;"&gt;string&lt;/span&gt; which contains the full array access expression of the next item regardless of the level of hierarchy. So&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$query(^Patient("general hospital",324542)) &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;will return a string containing "^Patient("general hospital",324549)"&lt;br /&gt;&lt;br /&gt;This can then be &lt;em&gt;eval&lt;/em&gt;ed in the next statement. ObjectScript has an @ operator for eval, so we loop through the array like this.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  set q=$query(^Patient)&lt;br /&gt;  for {&lt;br /&gt;    if q '= "" {&lt;br /&gt;      set p = @q&lt;br /&gt;      ... do something with patient p&lt;br /&gt;    }&lt;br /&gt;    set q=$query(@q)&lt;br /&gt;    quit:q=""&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As before, there's a way to get at the first record - the $query(^Patient), and when $query returns "" we've reached the end. &lt;br /&gt;&lt;br /&gt;This is somewhat of an improvement in that we're back to one loop. And it would still work if we moved to a new structure for ^Patient. It's a minor inconvenience that we've got ourselves into a "for" which only tests for the exit condition at the end of the loop body so we need an extra test that q isn't "" for the actual "do something" part.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;The bigger concern is that we've now lost our keys.&lt;/span&gt; The value of q is going to be something like "^Patient("general hospital",324549)" while the value of p is "martha~jones~measles". If, in the "do something", I want to know what hospital we're talking about I'm going to have to cut up the string q to extract it. That's a bit painful.&lt;br /&gt;&lt;br /&gt;In the next part of this series, I'll start showing some "iterator" routines which do successfully hide the structure of a table and yet give access to necessary key information.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-1541482315148344133?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/1541482315148344133/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=1541482315148344133' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/1541482315148344133'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/1541482315148344133'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/07/quest-for-objectscript-iterator-part-2.html' title='The Quest for an ObjectScript Iterator (part 2)'/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-5921573484927820478</id><published>2008-07-12T18:35:00.000-07:00</published><updated>2008-07-13T13:32:15.902-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iterator quest'/><category scheme='http://www.blogger.com/atom/ns#' term='iterator'/><category scheme='http://www.blogger.com/atom/ns#' term='Cache ObjectScript'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>The Quest for an ObjectScript Iterator (part 1)</title><content type='html'>One of the advantages of Caché is the close integration of programming language and database. It's trivially easy to read and write directly to and from the db in Cache ObjectScript code.&lt;br /&gt;&lt;br /&gt;But that ease has a downside : it's so tempting to shunt stuff in and out at a moment's notice, that if not careful, you can suddenly find yourself with an extremely tight inter-dependency between the database structure and your business logic. Hard commitments to the details of your data-base schema are scattered in hundreds of places throughout the code, making any change expensive.&lt;br /&gt;&lt;br /&gt;The conscientious programmer will want to put some kind of abstraction layer or API between direct database calls and the rest of the business logic. Such a layer comes in handy if you find you need to add extra logging or transaction protection during record saves, for example.&lt;br /&gt; &lt;br /&gt;But the nature of the database makes this a challenge for those used to other languages and ways of doing things. There are particular difficulties when it comes to looping through the tables, as ObjectScript's commands for this make direct reference to the the schema.&lt;br /&gt;&lt;br /&gt;In this series of blog-posts I'll describe my own ongoing quest for a decent way to abstract away from direct db access and for some sort of &lt;a href="http://en.wikipedia.org/wiki/Iterator"&gt;Iterator&lt;/a&gt; to let business logic run through collections of records without (much) knowledge of how they're stored.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-5921573484927820478?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/5921573484927820478/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=5921573484927820478' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/5921573484927820478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/5921573484927820478'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/07/quest-for-objectscript-iterator-part-1.html' title='The Quest for an ObjectScript Iterator (part 1)'/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-5166437649386589891</id><published>2008-07-05T11:12:00.001-07:00</published><updated>2008-07-05T11:14:23.814-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='enterprise 2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='SAP'/><category scheme='http://www.blogger.com/atom/ns#' term='ESME'/><title type='text'></title><content type='html'>Here's an &lt;a href="http://blog.abesh.net/2008/07/05/esme-the-demo/"&gt;interesting example&lt;/a&gt; (watch the video) of bringing social-software ideas into the traditional  enterprise : ESME on SAP.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-5166437649386589891?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/5166437649386589891/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=5166437649386589891' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/5166437649386589891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/5166437649386589891'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/07/heres-interesting-example-watch-video.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-1541710231387033646</id><published>2008-07-05T09:11:00.001-07:00</published><updated>2008-07-05T09:35:38.723-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='zen'/><title type='text'></title><content type='html'>Need to start looking into &lt;a href="http://docs.intersystems.com/cache20081/csp/docbook/DocBook.UI.Page.cls?KEY=GZEN"&gt;Zen&lt;/a&gt; .&lt;br /&gt;&lt;br /&gt;On first glance it has some impressive widgets. Especially taking advantage of SVG for cute vector graphs etc.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-1541710231387033646?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/1541710231387033646/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=1541710231387033646' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/1541710231387033646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/1541710231387033646'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/07/need-to-start-looking-into-zen-yet.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-1285268495935054652</id><published>2008-07-03T23:07:00.000-07:00</published><updated>2008-07-03T23:27:56.768-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wiki'/><category scheme='http://www.blogger.com/atom/ns#' term='Cache ObjectScript'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='twistah'/><title type='text'></title><content type='html'>Just want to drive a spike through a development and code release process I will be following on this blog.&lt;br /&gt;&lt;br /&gt;Last weekend I started writing a simple wiki in Cache ObjectScript and CSP, and tonight I polished off a couple of odds and ends.&lt;br /&gt;&lt;br /&gt;Wiki is one of the simplest web-apps you can imagine and is often used to demonstrate new web-frameworks. So it was an obvious experiment to try in Caché. I was also surprised when I went googling for Intersystems Caché wiki that I only found Wikipedia entries but no wiki software for the platform.&lt;br /&gt;&lt;br /&gt;So I rectified that. Altogether development has taken around three hours. Not too bad if not quite up with the 10 minute examples boasted by Django / Ruby on Rails etc. &lt;br /&gt;&lt;br /&gt;I'll have more to say about this code in the next few blog-posts, both to explain how to use it, and some of the implementation decisions behind it. I'll also, I'm sure, be adding further features.&lt;br /&gt;&lt;br /&gt;However, that can wait. For the impatient, here's the &lt;a href="http://code.google.com/p/twistah/source/browse"&gt;project on Google Code&lt;/a&gt; codenamed "Twistah". The software comes in one XML file (NooRanchWiki.xml), an exported COS "project". Once you download the file You can import it into any namespace using Studio's "Tools &gt; Import Local" menu.&lt;br /&gt;&lt;br /&gt;Then go to http://webserver/csp/namespace/view.csp for the HelloWorld page.&lt;br /&gt;&lt;br /&gt;At the moment, it doesn't do much wiki markup. Only creating links is supported (for which you must use a [[PageName]] notation (double-square brackets and no spaces allowed at the moment)&lt;br /&gt;&lt;br /&gt;It does have an overview of all pages (surprisingly easy) and RecentChanges which has been implemented in a slightly unusual way that I'll explain later.&lt;br /&gt;&lt;br /&gt;OK, enjoy what's possibly Intersystem Caché and COS's only open-source wiki package. (BSD license for all you Gnuophobes)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-1285268495935054652?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/1285268495935054652/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=1285268495935054652' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/1285268495935054652'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/1285268495935054652'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/07/just-want-to-drive-spike-through.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-4077134138202544389</id><published>2008-07-02T09:10:00.001-07:00</published><updated>2008-07-03T06:50:32.819-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='life'/><category scheme='http://www.blogger.com/atom/ns#' term='Cache ObjectScript'/><category scheme='http://www.blogger.com/atom/ns#' term='zen'/><category scheme='http://www.blogger.com/atom/ns#' term='positives'/><category scheme='http://www.blogger.com/atom/ns#' term='csp'/><title type='text'></title><content type='html'>OK, after mentioning some &lt;a href="http://cachetastic.blogspot.com/2008/07/some-mumps-dissing-and-more-positive.html"&gt;bad&lt;/a&gt; things about Caché ObjectScript, here are a couple of &lt;em&gt;good&lt;/em&gt; things about Caché in general.&lt;br /&gt;&lt;br /&gt;(That's not to say all the suckage is just the COS language, but we can come to other negatives later. This is a "positives" post.)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;It's "alive"&lt;/b&gt; I'm starting to think that, possibly, the BEST thing about Caché is that it's a living platform in the sense that Steve Yegge &lt;a href="http://steve-yegge.blogspot.com/2007/01/pinocchio-problem.html"&gt;talks about here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;What makes it "alive" is that the code is kept in the data-base and is interpreted (or rather, compiled on a routine-by-routine basis) so that it can be changed without the whole stop-recompile-restart cycle for the server. There is a terminal shell through which you can inspect and interact with the database and code. (Create objects, call functions etc.) It's not a great one in the Yegge sense, but it's there and useful.&lt;br /&gt;&lt;br /&gt;Caché does not obviously have "advice" as Yegge calls it, but the system I work on does have dozens of hooks, and I think the developers must have got the idea from somewhere. Does Caché have plugins and other ways to extend it? Well, quite a lot of the innards seem to be visible (introspection) and new features like the OO language and the JSP-like CSP-pages ultimately compile down into the core language, so it &lt;em&gt;is&lt;/em&gt; extensible.&lt;br /&gt;&lt;br /&gt;Keeping the source-code in the database gives rise to one obvious and infuriating problem. You can't use all the ordinary file-based tools that you're used to for things like source-management, difference comparisons, backups and deployment. This is a problem that Caché shares with (comparing the sublime with the ridiculous) Smalltalk. Like Smalltalk, the whole "environment" of code and database is kept in a single large file.&lt;br /&gt;&lt;br /&gt;Perhaps the resemblance is not wholly accidental. Caché might, in some ways, be moving to occupy a similar niche to something like &lt;a href="http://gemstone.com/products/smalltalk/"&gt;Gemstone&lt;/a&gt; - a kind of self-contained persistent-object world. And as it does so, it may acquire further similarities to Smalltalk environments. Certainly had Intersystems taken Smalltalk as their model for an OO layer, rather than the stereotypical Visual C++ / Java development environments of the 90s, a great deal of pain might have been ameliorated. (That's something I want to come back to, here I'll just note that it is a good thing about Caché that it's a living platform and with some resemblance to Smalltalk.)&lt;br /&gt; &lt;br /&gt;&lt;b&gt;Batteries included&lt;/b&gt; : The environment includes, in a single standard installation, the database (obviously), the development tools, runtime environment and web-server.&lt;br /&gt;&lt;br /&gt;That's quite handy to set up. It doesn't mean it's easy to deploy the environment, but once the environment is deployed, you have most of what you need for a web front-end and a database backend. &lt;br /&gt;&lt;br /&gt;CSP is more or less like every other *SP (JSP, ASP, PHP etc.) You write HTML, can call out to COS on the server (interestingly at both compile-time and run-time, so I guess it's possible to do metaprogramming at compile-time, though need to try this.) and has some special tags.&lt;br /&gt;&lt;br /&gt;There's also now a new browser-side component library called Zen, and AJAXy XMLHttpRequest communication behind the scenes. (Another thing I still need to play with.)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;It's fast.&lt;/b&gt; Allegedly. But that's a plausible claim given how low level the data-access is. Compared to say a multi-layer system with Object-Relation Mapping library over ODBC to relational database.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;It's simple.&lt;/b&gt; It is, actually. It's pretty simple to make stuff happen. You tend to have direct access to things rather than have to learn sophisticated frameworks, go through multiple abstraction layers etc. There's a downside to that, of course, (in flexibility and maintainability) but the value of simplicity of getting started, and building incrementally from simple prototypes shouldn't be discounted.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-4077134138202544389?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/4077134138202544389/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=4077134138202544389' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/4077134138202544389'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/4077134138202544389'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/07/ok-after-mentioning-some-bad-things.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-9121438835752772972</id><published>2008-07-01T18:58:00.000-07:00</published><updated>2008-07-01T19:04:21.386-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ehr'/><category scheme='http://www.blogger.com/atom/ns#' term='health'/><category scheme='http://www.blogger.com/atom/ns#' term='eiffel'/><title type='text'></title><content type='html'>Here's something interesting : &lt;a href="http://www.openehr.org/home.html"&gt;OpenEHR&lt;/a&gt; is an open electronic health-record standard.&lt;br /&gt;&lt;br /&gt;Seems to be in &lt;a href="http://eiffel.com/"&gt;Eiffel&lt;/a&gt; of all things?! Gosh!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-9121438835752772972?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/9121438835752772972/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=9121438835752772972' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/9121438835752772972'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/9121438835752772972'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/07/heres-something-interesting-openehr-is.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-1282792565143137230</id><published>2008-07-01T06:36:00.000-07:00</published><updated>2008-07-02T08:10:57.139-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cache ObjectScript'/><title type='text'></title><content type='html'>Some &lt;a href="http://thedailywtf.com/Articles/A_Case_of_the_MUMPS.aspx"&gt;MUMPS dissing&lt;/a&gt; and &lt;a href="http://robert.hurst-ri.us/2008/03/22/cache-ftw/"&gt;a more positive respost&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I'm going to blog about what sucks, and what's good (enough) in Caché, although finally my focus will be on how I think it can be used well, rather than judging it.&lt;br /&gt;&lt;br /&gt;But let's start with some negatives. From my perspective, after a year or so ObjectScript programming, here are the most disturbing parts : &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Dynamic Scope.&lt;/b&gt; Yep, this is truly, awesomely fearful. Dynamic scope means that this :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;f() &lt;br /&gt;  new x&lt;br /&gt;  do g()&lt;br /&gt;  write x&lt;br /&gt;  quit&lt;br /&gt;&lt;br /&gt;g()&lt;br /&gt;  set x = 5&lt;br /&gt;  quit&lt;br /&gt;&lt;br /&gt;do f()&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;will write the number 5 to the terminal.&lt;br /&gt;&lt;br /&gt;Why? Although x is defined within the scope of f, it's visible (and writable) within g. Note, not because g() is within the lexical scope of f() but merely because it is called from it.&lt;br /&gt;&lt;br /&gt;The potential for weird interdependencies abounds.&lt;br /&gt;&lt;br /&gt;The "new x" at the beginning of f() can shadow (hide any x that was defined previously on the stack). So it's possible to use this mechanism to *avoid* having the effects of dynamic scoping. Unfortunately, legacy code is often FULL of the stuff. Old MUMPS coders seem to be happy to rely on it to pass values into and out of functions.&lt;br /&gt;&lt;br /&gt;Dynamic Scoping in large systems is absolutely the number one cause of Caché hell. Especially as it prevents you even *trying* to reduce interdependency. When encountering legacy code with references to unlocalized variables, you might be tempted to add the "new" statement to make them local. However this can break entirely different parts of the code which were relying on the value of the variable being set as a side-effect of the call. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Left to right operator precedence&lt;/b&gt; : This is not so evil in principle. There's no reason that it's better for 2+3*6 to be 20 rather than 30. But it sure as hell catches you out if you are experienced in (and plan to stay habituated to) the way most languages do it. It's nastiest in boolean expressions, of course, where &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;if x = 1 &amp;&amp; y = 2 { &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;is evaluated as &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;if (((x=1)&amp;&amp;y)=2) {&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Significant Whitespace&lt;/b&gt; And I don't mean like Python, I mean in the middle or at the end of lines.&lt;br /&gt;&lt;br /&gt;For example &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;kill  for { quit:'$data(x) }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;is OK code (bit pointless but syntactically OK, and has understandable semantics).&lt;br /&gt;&lt;br /&gt;Whereas &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;kill for { quit:'$data(x) }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Is a syntax error.&lt;br /&gt;&lt;br /&gt;Obviously.&lt;br /&gt;&lt;br /&gt;Aaaarrrgghhhh!&lt;br /&gt;&lt;br /&gt;OK ... more soon ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-1282792565143137230?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/1282792565143137230/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=1282792565143137230' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/1282792565143137230'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/1282792565143137230'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/07/some-mumps-dissing-and-more-positive.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-4129639361520216750</id><published>2008-07-01T06:16:00.000-07:00</published><updated>2008-07-01T06:22:17.011-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='applications'/><title type='text'></title><content type='html'>So what do people do with Caché? &lt;br /&gt;&lt;br /&gt;A brief glimpse can perhaps be seen in Intersystems' &lt;a href="http://www.zibb.com/article/3137190/InterSystems+Honors+Winners+Of+2008+Innovator+Awards"&gt;Innovation Awards for 2008&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-4129639361520216750?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/4129639361520216750/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=4129639361520216750' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/4129639361520216750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/4129639361520216750'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/07/so-what-what-do-people-do-with-cach.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-5862393962079828533</id><published>2008-06-30T19:31:00.000-07:00</published><updated>2008-07-01T08:11:03.634-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'></title><content type='html'>To check out how awesomely obfusticated Mumps style coding can get, see the example at the end of &lt;a href="http://en.wikipedia.org/wiki/MUMPS"&gt;this wikipedia article&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-5862393962079828533?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/5862393962079828533/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=5862393962079828533' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/5862393962079828533'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/5862393962079828533'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/06/to-check-out-how-awesomely-obfusticated.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6102611449527699173.post-996976580471127717</id><published>2008-06-30T17:27:00.000-07:00</published><updated>2008-07-01T11:49:28.193-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='introduction'/><title type='text'></title><content type='html'>Hi, my name is Phil and I'm a ... modern programmer. I mean, you can usually find me over on my &lt;a href="http://smartdisorganized.blogspot.com/"&gt;other blogs&lt;/a&gt; &lt;a href="http://blahsploitation.blogspot.com/"&gt;raving about&lt;/a&gt; exciting &lt;a href="http://platformwars.blogspot.com/"&gt;new developments&lt;/a&gt; in programming platforms and languages.&lt;br /&gt;&lt;br /&gt;I love Python. I'm a keen student of Erlang. I think functional programming is cool. As are Lisp and Smalltalk ... and I need to learn about Monads.&lt;br /&gt;&lt;br /&gt;When new stuff is going on, I'm down with it. (I mean, maybe Lisp and Smalltalk are not exactly new, but they're very contemporary and hip)&lt;br /&gt;&lt;br /&gt;But I have a confession to make, ... you won't find it on my homepage or my CV.&lt;br /&gt;&lt;br /&gt;I am, by day, &lt;span style="font-weight:bold;"&gt;a Caché programmer!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The reaction to such an admission usually ranges from incomprehension (you what?) to that of my ex-colleagues from the University of Brasilia computer science department  : outright ROFL hilarity.&lt;br /&gt;&lt;br /&gt;"You're writing MUMPS??!!!" they cackled. And, more or less, I am. Yes.&lt;br /&gt;&lt;br /&gt;Er ... you what?&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.intersystems.com/cache/index.html"&gt;&lt;br /&gt;Intersystems Caché&lt;/a&gt; is the latest in a long line of MUMPS based integrated database+programming environments. It styles itself a "post-relational" database but this is really a fancy name for saying it's a good old fashioned hierarchical database of the kind that Codd and Date did battle with in the 70s. At heart the programming language is tightly integrated with the database access so that reading and writing to it is more or less the same as reading and writing in-memory arrays.&lt;br /&gt;&lt;br /&gt;Cache has layered over this, an SQL-like view, and an object-oriented language with built-in persistence. In fact, although most people, me among them, would agree that Codd and Date won their argument with the hierarchical database people (essentially by showing that forcing programmers to explicitly recognise the database structure and to traverse pointers was an unnecessary encumbrance when compared to the relational model), when your data is already hierarchically structured (as are nested objects) reading and writing them in a hierarchical database can be pretty fast. And Caché is increasingly selling itself as a fast, object database.&lt;br /&gt;&lt;br /&gt;In forthcoming posts I'll explore this further. &lt;br /&gt;&lt;br /&gt;But, in general, why blog about this? It's dull day-job stuff. &lt;br /&gt;&lt;br /&gt;Or so I thought.&lt;br /&gt;&lt;br /&gt;But I'm starting to wonder. &lt;br /&gt;&lt;br /&gt;Firstly; despite my original impression of Caché's built in language - called, confusingly, ObjectScript, even though it *isn't* object-oriented - which was more or less along the lines of &lt;span style="font-weight:bold; size=larger;"&gt;OMFG! Get me OUT of here!!!&lt;/span&gt; I have started to, grudgingly, respect some of its features as I've become more familiar with them.&lt;br /&gt;&lt;br /&gt;Secondly, more importantly, a good programmer should be able to discover the patterns that make for "beautiful code" in any programming language.&lt;br /&gt;&lt;br /&gt;And thirdly, most importantly, because there's a challenge here. This world of Caché is decidedly unhip. It's as far as possible from the excitement of web 2.0 as one can imagine. It's old-skool, conservative, enterprisey, &lt;em&gt;legacy&lt;/em&gt; (the original MUMPS hails from the early 70s and a lot of the code you see looks like it!), proprietary. There are few companies who sell expensive systems to governments and health-services and hospitals. (MUMPS's stronghold is medical, patient records, management of warehouses of medicines etc.) Such companies (my own employer among them) look at you bewildered when you ask their policy on blogging. They shudder at the thought of open-source software. &lt;br /&gt;&lt;br /&gt;And yet, if things are going the way that I assume they are, even this world must change. It will be challenged by SaaS and commodity, free-software. The patient (&lt;a href="https://www.google.com/health/p/"&gt;read Google&lt;/a&gt;) will take responsibility for their own medical records and hospitals will learn to speak to the outside world. There will be Caché blogs and wikis and twitters ... at least, I imagine there must be, if there is to be any ecosystem at all. But how will this good-old-fashioned, staidest of the staid, enterprise deal with the rise of "Enterprise 2.0"?&lt;br /&gt;&lt;br /&gt;All fascinating topics to be explored on this blog.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6102611449527699173-996976580471127717?l=cachetastic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cachetastic.blogspot.com/feeds/996976580471127717/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6102611449527699173&amp;postID=996976580471127717' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/996976580471127717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6102611449527699173/posts/default/996976580471127717'/><link rel='alternate' type='text/html' href='http://cachetastic.blogspot.com/2008/06/hi-my-name-is-phil-and-im.html' title=''/><author><name>phil jones</name><uri>https://profiles.google.com/109547101047038671387</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-pEhlkzMvQ3U/AAAAAAAAAAI/AAAAAAAAAJg/jt79shkgF6k/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry></feed>
