... until the collector arrives ...

This "blog" is really just a scratchpad of mine. There is not much of general interest here. Most of the content is scribbled down "live" as I discover things I want to remember. I rarely go back to correct mistakes in older entries. You have been warned :)

2008-12-18

ImagePrinter

ImagePrinter is a Windows printer driver that prints to multiple image files (e.g PNG or JPG).

Executor

Executor is (yet another) pop-up command line tool.  It has a nifty "calculator" feature.

2008-12-01

Browsershots

browsershots.org provides a free online service that will display screenshots of a given URL on up to 60 different browsers.

2008-11-28

Product Aggregation in SQL Server

Ever wanted to write something like this in SQL Server:

SELECT PRODUCT(MYCOLUMN) FROM MYTABLE

Well, wish no more:

DECLARE @P FLOAT
SET @P = 1
SELECT @P = @P * MYCOLUMN FROM MYTABLE
SELECT @P

... provided you can use the query in a context that permits T-SQL that is (e.g. not in a view or a subquery).  Note that you can perform arbitrary aggregations using this technique (say, summing while respecting null contagion, concatenating strings... the mind boggles).

2008-11-18

How Many Agile Product Guys?

I was curious how many of the Agile Manifesto guys had a "product" background.  By that I mean that they have worked in a product shop at least more recently than they got into the "agile" game.  Here is the score:

  • Mike Beedle - don't think so, his Agile bio suggests that he has been consulting since the 90's
  • Arie van Bennekum - don't think so, from his Agile bio
  • Alistair Cockburn - no, according to the bio on his site
  • Ward Cunningham - maybe, from his Agile bio -- can't tell from other online sources
  • Martin Fowler - no, from the bio on his site
  • Jim Highsmith - no, from the bio on his site
  • Andrew Hunt - no, from the bio on his site
  • Ron Jeffries - no, from the bio on xprogramming.com
  • Joe Kern - no, despite the fact that his bio at immuexa talks of Compuware's OptimalJ "product team"
  • Brian Marick - maybe (as a tester?), from his bio at exampler
  • Robert C. Martin - no, from his bios at Object Mentor and his blog
  • Ken Schwaber - no, from his Agile bio
  • Jeff Sutherland - yes, from his Agile bio
  • Dave Thomas - don't know

So, we have 1 yes, 2 maybe yes, 2 maybe no, 8 no and 1 unknown.  Let's split the difference on the uncertain ones and say 10.5 no to 3.5 yes.

2008-11-14

JVM Heap Dump Options

On the Sun JVM, you can tell it to perform a heap dump automatically when an out-of-memory error occurs using these arguments:

-XX:-HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=c:\oomdump.hprof

There are many more Java HotSpot VM options.

2008-10-21

CodaServer

CodaServer is the beginnings of an open source middleware system that adds business rules and workflow to a SQL database.  A key feature is a form which is characterized as "tables with workflow".

2008-09-22

SQL Server 2000 vs LOG and SQRT

If you attempt to take the LOG or SQRT of a negative number in SQL Server 2000, it fails quietly but catastrophically.  Should a query attempt to perform one of these operations, the result set is empty -- all rows are discarded.  No error is reported, neither to the client nor in the SQL Server logs.

2008-09-21

OpenLaszlo

OpenLaszlo will now compile its applications down to DHTML (in addition to the Flash that it has always done).

2008-09-12

Quick Highlighter

Quick Highlighter is an on-line service that can generate pretty looking output for code in many languages.  My favourite feature of this service is that it hyperlinks built-in constructs to their reference pages -- especially for less popular languages like Haskell.

2008-09-06

Hadoop

Hadoop is Apache's Java implementation of the map-reduce concurrent programming model.

2008-09-04

Server2Go

Server2Go is an out-of-the box Apache/PHP/MySQL stack that can run off read-only media (and writable media as well).

OpenSourceCMS

OpenSourceCMS is a web site that hosts sandboxes for many of the open source CMS systems.  It provides a painless way to try out the various products.

2008-08-27

Scriba

Scriba is a Mathematica-style document-centric interface to BSF languages.  It ships with BeanShell, HTML, JRuby, and JScheme pre-installed.  Any JSR-223 compatible engine can be plugged in.  See, for example, the list of such engines in the java.net scripting project.

2008-08-20

Raphael

Raphael is a Javascript library that puts a facade over the SVG and VML object models.

2008-08-09

Excessive Hardware Interrupts

Windows recently told me it had found a bad block on my disk drive. I ran a disk check and told it to fix bad blocks. Presumably, the bad block had been spared out. However, my computer's performance was awful. I tried the usual dance -- clean up, defrag, ensure the page file was contiguous in a good spot -- but performance was still awful.

CPU usage was running at a background level of 10-20%. Process Explorer attributed this CPU to "Hardware Interrupts". A bit of Googling led me to this blog entry:

Little-Known Tweak to Boost Hard Drive Performance!

In short, after Windows has noted six I/O errors on a controller, it pins that controller to programmed I/O mode (PIO).  You can check this by looking at the properties of the disk controller in the Device Manager.  The only way to re-enable DMA mode is to perform some registry hacks under the key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E96A-E325-11CE-BFC1-08002BE10318}

Find the sub-key associated with the controller in question (e.g. the primary IDE channel). Then:

  • delete MasterIdDataCheckSum (if present)
  • delete SlavedIdDataCheckSum (if present)
  • add ResetErrorCountersOnSuccess (DWORD) = 1 (if desired)
  • set any or all of the following capability masks to 0xFFFFFFFF (if present):
    • MasterDeviceTimingMode
    • MasterDeviceTimingModeAllowed
    • SlaveDeviceTimingMode
    • SlaveDeviceTimingModeAllowed
    • UserMasterDeviceTimingModeAllowed
    • UserSlaveDeviceTimingModeAllowed
  • reboot

After rebooting, check to see whether the relevant controller has reverted to DMA mode. If so, your problem is probably solved (unless the hardware is truly gacked).

2008-08-06

SQL Server Comments vs Line Terminators

If you use the '--' comment syntax in SQL Server, the comment extends to the end of the line.  The question is: what constitutes the end of the line.  It turns out that SQL Server does not count a single return character as the end of line, so the following line(s) might be gobbled up into the comment.

It would seem that lines that end solely with a return character wouldn't happen in practice, at least on Windows.  However, if can happen if you are using the combination of HTA, DOM, Javascript and ADO.  If you extract the text content of an HTML element using DOM, then line terminators that are expressed as \r\n on disk are converted to \r in memory.  It is necessary to fix up such line endings before feeding the string to ADO if the SQL text contains any '--' comments.

2008-07-31

JUnit Gotcha

In JUnit 4, if you use the version of assertEquals that compares two objects, and those objects happen to be subclasses of Number, the framework converts them to long before comparing them.  This is broken for any non-integral type since it will neglect the fractional part.

Just to make matters worse, if you attempt to compare two floating point numbers using assertEquals and you forget to add the 'delta' argument, then once again you will get the object-version of the method and the comparison will be invalid.  This is a regression from the old JUnit which predated auto-boxing and the compiler would moan about mismatched argument types.  It is hard to believe, but this unit test passes:

@Test
public void test() {
    assertEquals(1.2, 1.3);
}

Functional Java

Functional Java is a Java library inspired by Scala and Haskell.  It anticipates the addition of first-class functions to Java 7, especially if it follows the BGGA Closure proposal.

Closures

It is increasingly bugging me how the term "closure" is becoming synonymous with "function literal", especially in the Java community now that it is just discovering functions.  People seem to forget that Pascal had closures in 1974, but it didn't support function literals.  I thought that Algol had closures first, but according to Wikipedia Scheme was the first in 1970.  Naturally it inherited function literals from LISP.  Of course, Scheme has the definitive implementation of closures which are not restricted to stack-based lifetime nesting.  This is unlike Pascal and practically every other language under the Sun which thinks that the stack is fundamental -- nobody in Java-land is talking about that.  At least BGGA has the UnmatchedNonlocalTransfer exception.  This is an improvement over Smalltalk where the VM would just crash.

I'm sure Algol had closures.  Maybe in Algol 60 but certainly by the time of Algol 68.

2008-07-21

Riena

Riena is an Eclipse initiative to develop a workbench replacement that is friendlier to business users.

2008-07-20

Joe Armstrong on Erlang

InfoQ has an interesting one hour lecture by Joe Armstrong: Erlang - software for a concurrent world.

2008-07-03

Enerjy

Enerjy is an Eclipse plug-in that computes various code metrics, along the lines of CheckStyle.

Jupiter

Jupiter is an Eclipse plug-in that supports team code review.

2008-07-01

SchemaSpy

SchemaSpy can used to generate decent off-line documentation for an SQL schema.

2008-06-30

SQL Server 2000 vs Recursive Functions

In SQL Server 2000, if you attempt to alter an existing recursive function so as to change the number of parameters, you will receive an error message complaining that you are passing the wrong number of arguments to the function.  This appears to be because SQL Server is checking against the old definition of the function being defined.

2008-06-20

Fiddler

Fiddler is a TCPMON-like web debugging proxy for the .NET ecosystem.  If you want to perform port-forwarding like TCPMON, you can either add a registry entry like this:

HKCU\SOFTWARE\Microsoft\Fiddler\ReverseProxyForPort=target port (DWORD)

or enable Tools/Fiddler Options/Allow remote clients to connect and then add an OnBeforeRequest handler in Rules/Customize Rules:

if (oSession.host.toLowerCase() == "webserver:8888") oSession.host = "webserver:80";

2008-06-19

Data Storm

Data Storm is a lightweight database browser intended to be invoked in-line in a Java unit test.  It is useful for debugging database unit tests that perform a rollback after the test.

2008-06-13

Java Bean Introspector vs Boolean

The Java bean introspector returns null for the read method for a property whose type Boolean (boxed) and whose getter follows the is... pattern.  JAXB names such properties following that pattern.

2008-06-11

Visual Studio XSD Tool vs XML Schema

The Visual Studio XSD tool cannot handle an XML Schema that uses a repeating element with the same name at two distinct places.  For example, it cannot handle this schema (in XQuery notation for brevity):

root {
  elementA {
    problemElement {
      name
    }
  },
  elementB {
    problemElement {
      name
    }
  }
}

The element named problemElement causes the problem.  If you attempt to generate C# code for this schema using the XSD tool, it all works.  But if you try to generate a dataset, you an error like:

Error: There was an error processing 'myproblematic.xsd'.
  - The same table (ProblemElement) cannot be the child table in two nested relations.

The solution is to rename one of the problematic elements to reflect the context (sigh).

I have a minimal xsd that demonstrates the issue:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    elementFormDefault="qualified"
    targetNamespace="urn:tns"
    xmlns:tns="urn:tns"
    >

  <xs:element name="Root" type="tns:Root"/>

  <xs:complexType name="Root">
    <xs:sequence>
      <xs:element name="ElementA">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="ProblemElement">
              <xs:complexType>
                <xs:sequence>
                  <xs:element name="Name" type="xs:string"/>
                </xs:sequence>
              </xs:complexType>
            </xs:element>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="ElementB">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="ProblemElement">
              <xs:complexType>
                <xs:sequence>
                  <xs:element name="Name" type="xs:string"/>
                </xs:sequence>
              </xs:complexType>
            </xs:element>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

</xs:schema>

And here is the command to process it:

C:\VS.NET2003\Common7\Tools\vsvars32.bat
xsd /d dotnet-xsd-bug.xsd

2008-05-31

Y-Combinator Explained Using Javascript

We take recursion for granted in most languages.  Consider the factorial function, in Javascript:

function f(n) {
    return (n < 2) ? 1 : n * f(n-1)
}

This implementation relies on the fact that the name f being defined is the same as the f in the definition.  If you think for a minute about how a compiler would arrange this, you are likely to come up with an imperative solution.  For example, the compiler might leave a placeholder for f in the compiled definition and then update it to point to itself once the body has been compiled.

Systems like the lambda calculus, being purely functional, do not admit of such imperative solutions.  So how do you express recursion functionally?

One answer is a technical trick called the Y-combinator.  Let's start by writing a variation of the factorial function:

function f(r) {
    return function(n) {
        return (n < 2) ? 1 : n * r(n-1)
    }
}

Instead of taking an integer and returning an integer, this new f takes a function and returns a function.  The returned function can compute the factorial of an integer -- provided r was bound to a suitable function that ensures the requisite recursion.

What is the proper argument for r?  How about f?

f(f)(10)

It looks promising, but it won't work.  Look again at the definition of f.  r must accept an integer as its argument, but we have passed f which expects a function.  This is trickier than it looks.  What we need is something like:

f(f(f(f(f(f(...))))))(10)

Enter the Y-combinator. It is used like this:

Y(f)(n)

which evaluates to:

f(Y(f))(n)

that is:

f(f(f(f(f(f(...))))))(n)

That's easy to say.  But has does one write this mythical function Y?  I can't answer that, but Alonzo Church could.  Here's the definition he somehow puzzled out, in lambda notation:

λf . (λg . f (g g)) (λg . f (g g))

Applying Y to f, the evaluation sequence is as follows:

(λf . (λg . f (g g)) (λg . f (g g))) f

(λg . f (g g)) (λg . f (g g))

f ((λg . f (g g)) (λg . f (g g)))

f (f ((λg . f (g g)) (λg . f (g g))))

f (f (f ((λg . f (g g)) (λg . f (g g)))))

f (f (f (f ((λg . f (g g)) (λg . f (g g))))))

...

This has the desired property.  Here is Y expressed in Javascript, along with the almost-recursive definition of f and a test case:

function Y(f) {
   return function(g) { return function(n) { return f(g(g))(n) }}(
     function(g) { return function(n) { return f(g(g))(n) }}
   )
}

function f(r) {
   return function(n) { return n < 2 ? 1 : r(n-1) * n } }

alert(Y(f)(10))

Nifty, huh?  For those who want to play along in Scheme:

(define Y
   (lambda (f)
     ((lambda (g)
        (lambda (n)
          ((f (g g)) n) ))
      (lambda (g)
        (lambda (n)
          ((f (g g)) n) )))))

(define f
   (lambda (r)
     (lambda (n)
       (if (< n 2) 1 (* n (r (- n 1)))) )))

((Y f) 10)

2008-05-26

Equinox HttpContextManager Bug

There is a bug in the Eclipse Equinox implementation of HttpContextManager (version 1.0.0.v20070608).  It throws an array out-of-bounds exception on line 91:

for (int j = 0; j < resourceMappingElements.length; j++) {
    IConfigurationElement resourceMappingElement = resourceMappingElements[i];

i is the wrong index variable.  It should be j.

This code will only work when there is only one context with no more than one resource mapping.

2008-05-23

eXist Redux

The eXist XML database system has come a long way.  It now supports full XQuery and lots of HTTP interfaces.  It provides two out three layers in the so-called XRX stack (REST and XQuery).  Now how about a browser that does XForms to complete the stack?

Google Visualization API

Another Google service:  Google Visualization API.

The Third Manifesto

The Third Manifesto is Darwen and Date's latest take on the relational model.  It attempts to eliminate the OO/relational impedence mismatch by fully supporting the relational model (in contrast, say, to the limited support in SQL).

2008-05-08

Google Chart API

Google provides a nifty service for generating charts, the Google Chart API.  You can get charts like this...

... just by crafting up a special URL:

http://chart.apis.google.com/chart?chs=200x100&cht=lxy&chtt=A Google Chart&chd=t:10,20,40,60,80,100|99,50,15,125,300,43

2008-05-02

Hibernate Tuple Query Debugging

If you are using a Hibernate HQL query like select new MyClass(...) and Hibernate cannot find an appropriate constructor, the exception message does not tell you  the types of arguments for which it was looking.  You can find out by setting a breakpoint in org.hibernate.util.ReflectHelper#getConstructor(...).

Hibernate cannot find tuple classes that are inner classes.

2008-05-01

Broken Hibernate Tools for Eclipse

The Hibernate Tools 3.2.1.GA running in Eclipse 3.3.2 have problems.

The worst is that when you run your second HQL query, the IDE hangs.  You can avoid the hang if you remember to close the previous result set pane first.

Also, the Hibernate Entity Diagram view is completely missing.

2008-04-30

Bug in Hibernate

In Hibernate 3.2.2, there appears to be a bug in org.hibernate.loader.custom.CustomLoader#scroll().  It calls the private method getHolderInstantiator():

static private HolderInstantiator getHolderInstantiator(ResultTransformer resultTransformer, String[] queryReturnAliases) {
    if ( resultTransformer != null ) {
        return HolderInstantiator.NOOP_INSTANTIATOR;
    }
    else {
        return new HolderInstantiator(resultTransformer, queryReturnAliases);
    }
}

The condition in the if statement appears to be reversed -- if a transformer is passed in it is ignored, otherwise it is used.  This bug turned up because I had registered a result transformer on the containing query.  It is still not fixed in the Hibernate source repository at the time of this writing.

The obvious workaround is to call the transformer yourself on each result row.  Unfortunately you must pass a list of result aliases to the transformTuple method of the transformer.  And how do you get that list?  You call Query.getReturnAliases of course.  But for an SQL query, you will get an UnsupportedOperationException, with the comforting message "SQL queries do not currently support returning aliases".

2008-04-28

Java Idioms for Hashing

It is common practice in Java for the calculation of a hash code to take every field into account, recursively descending into referenced objects.  In contexts where performance matters, this practice can be harmful.  The computation of the hash code in such fashion may actually be more expensive than a full equality check considering that hashing involves a lot of multiplications where equality testing involves only comparisons. 

Hashing is also used to divide objects into buckets.  For this purpose the extra cost is justified since one hash computation may eliminate many equality tests.  However, it is frequently not necessary to hash the entire reachable object graph to get a good hash code.  If an object's local non-reference fields show good variance in values across objects, it is adequate to hash them alone -- or even just a subset.  The most problematic case is "algebraic types", where the objects may large consist only of references to other objects.  Even in this case, one might still be able to get a decent hash by hashing only the object types a few levels into the object graph.  Limiting the depth of the traversal is also a reasonable strategy if the reachable object graph contains circular references.

Again, these observations only really matter when performance is a large consideration.  For small collections of objects from a small space, the extra think time is probably not worth the effort.  But, once again, it is shown that hashing is difficult.

2008-04-25

SQL Server vs CREATE TRIGGER

Using SQL Server 2000, a CREATE TRIGGER statement must be the first statement in a batch.  However, unlike other statements with that requirement, you cannot even put a SET XACT_ABORT ON statement in front of it.

2008-04-18

Determine File Extensions in Use

The following Mathematica code defines a function that lists all of the file extensions in use in a directory tree:

FileExtensionsInUse[directory_] := Module[{pattern="."~~Except["."|$PathnameSeparator]..~~EndOfString},
  StringCases[#, x:pattern:>x] /. {{}->"", {x_}:>x} & /@
  Select[FileNames["*", directory, Infinity], !StringFreeQ[#, pattern]&] //
  Union
]

2008-04-17

Ant vs Command Line Properties

Ant 1.7 appears to be sensitive to the order of command line options.  If you specify the build file (using -f) before specifying a property file (using -propertyfile), the build file will be loaded prior to loading the property file.  Thus, property values within the property file will not override those in the build file.  Reverse the order of the options if you want the property file to be loaded first.

2008-04-16

Mysterious Eclipse 3.3 Build Path Problems

Using Eclipse 3.3, I had a plug-in that failed to build with the error message complaining that a JAR on which it depends is missing.  The JAR was listed as an explicit, workspace-relative, library entry.  It was not listed in the plug-in manifest in any way.

I:

  •  verified that the destination resource existed
  • deleted the library entry and re-added it
  • cleaned and rebuilt the project
  • refreshed all resources in the workspace

None of these actions corrected the problem.  I eventually fixed it by temporarily adding the required JAR to the extra classpath entries in the plug-in manifest.  As soon as I did this, Eclipse tried to rebuild the project but failed complaining that there were now duplicate entries for the errant JAR.  I then removed the extra classpath entry that I had added and all was well.  Net result: no change.

I do not understand either what was broken or how it was fixed.  I can only imagine that Eclipse had some kind of cached information somewhere that finally got cleared out.

2008-04-11

Simulating Colour Blindness

Computerized simulation of color appearance for dichromats, by Hans Brettel, Francoise Vienot and John D. Mollon, is a paper that provides algorithms for transforming computer images so as to simulate the effects of various forms of colour blindness.

2008-04-05

DbFit

DbFit is a set of FIT/FitNesse fixtures for executing SQL tests.

2008-03-13

Extracting Mathematica Notebook Content

The following Mathematica expression will extract all non-input cells from a notebook and create a new notebook that contains only those cells:

NotebookWrite[CreateDocument[],
  Cases[NotebookGet@EvaluationNotebook[],Cell[_,Except["Input"],___],Infinity] ]

Iterating Through Mathematica Notebook Cells

The following snippet will iterate through the all the cells in a Mathematica notebook and close all Input cells:

Module[{nb, cell},
 nb = Notebooks["mynotebook.nb"][[1]];
 SelectionMove[nb, Before, Notebook];
 While[SelectionMove[nb, Next, Cell]; cell=NotebookRead[nb]; {}=!=cell,
  If["Input" == cell[[2]], 
   SetOptions[NotebookSelection[nb], "CellOpen" -> True] ]
  ]
 ]

2008-03-10

Scala and Haskell Combinators

In Scala, I find the syntax used in for comprehensions a bit confusing.  Specifically, the use of the keyword for.  Clearly, this is a concession to simulating looping constructs from other languages, particularly looping over collections.  The fact that for constructs compile to map, flatMap, filter and foreach reinforces this view.  However, the facility is more general.  Consider the use of for comprehensions in the Parser library.  The code style looks more like a Haskell do block.  It relies on the fact that the parser combinators return "collections" that are either empty or contain one element.  Thus, the "loops" are really a chain of expressions, the chain being broken by the first parse failure.  This is analogous to looking at an SQL inner join and realizing that the cardinality of all of the relations involved in the join have cardinality zero-or-one.

Haskell's do seems to suffer from a similar problem.  The construct is intended to be used with the celebrated Monad type.  But the word do suggests simple sequencing -- not general combinators.  It doesn't help that the monadic unit operation is named return.  No wonder people get confused by monads.

In both Scala and Haskell, I think that the mixed metaphors cause grief.  At least in my case, the supposedly helpful choices of keywords made it harder to understand the deeper truth.  In both cases, perhaps it would have been better to have two levels of abstraction: an upper level that uses only friendly keywords like for, do and return, and a lower level that only uses monadic or combinator terms.  Keep the two worlds separate.

Why Java Makes Me Stupid

My recent work in Mathematica has re-awakened some of my LISP sensibilities -- intuitions that I lost while working in Java.  What is it about Java that makes me forget about symbolic programming?  Well, I suppose it would be nice if Java had:

  • a symbol type
  • a "data" syntax
  • lightweight lists
  • less verbose collection syntax (e.g. for operations like fold/reduce)

The list could grow longer, of course.  Where are higher-order functions or even simple lambdas?

Having said all that, it is not impossible to do symbolic programming in Java.  It is just unpleasant (contrast the LISP and Java LabEngines, for example).  Also, the whole Java culture is "do this, then this, then this...", not "compose this and this and this".  Java makes the function call a significant event.  Not as significant as it was in the Fortran days, to be sure, but still way more significant than in LISP or Smalltalk or Mathematica or Haskell or Scala or ...

2008-03-08

Scala XML Book

The official Scala documentation for the XML facilities are poorly documented (just like everything else in the Scala library).  However, the Scala XML Book fills in some of the blanks.

XMF

Ceteva's XMF is a container language that glues together code fragments written in many different languages, in a style reminiscent of C ASM blocks.  It is hard to pin down the target application of XMF.  The core language contains more than glue.  "Undo" is a native concept, and there appears to be a sizable core library.  The documentation emphasizes language-oriented programming and meta-modelling.  Many language constructs are available to define DSLs.

2008-02-29

Virtual CloneDrive

Virtual CloneDrive is a convenient CD image mounter that masquerades as a permanent device.

2008-02-27

Alan Kay's Definition of OOP

From Meaning of "Object-Oriented Programming" According to Dr. Alan Kay:

OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. It can be done in Smalltalk and in LISP. There are possibly other systems in which this is possible, but I'm not aware of them.

This was written in 2003, long after the creation of C++ or Java.

2008-02-14

MACLISP

The old MACLISP manual is now available on-line in revised form as The Pitmanual.

2008-02-12

PXSL

Parsimonious XML Shorthand Language (PXSL) is interesting both for what it does (provide a shorthand syntax for XML) and for how it is implemented (in Haskell).

SQL Server 2000 Functions vs. Usefulness

The SQL Server 2000 development team have really gone out of their way to make table-valued functions less than useful.  Here, for example, is a function that will retrieve ancestors of a row in some kind of hierarchy table:

create function ancestors(@id int)
returns @t table(id int)
as begin
  while 1=1 begin
    select @id=(select parentId from hierarchyTable where id=@id)
  if @id is null break
    insert into @t values(@id)
  end
  return
end

But don't actually try to use this function:

select a.id, anc.id from hierarchyTable a
left join ancestors(a.id) anc on (1=1)

The alias 'a' is not visible in the argument to the function call.  In fact, it appears that the only way to pass a non-constant value to a table-valued function is within a stored procedure.

Apparently, this is fixed in SQL Server 2005 using the new CROSS APPLY or OUTER APPLY join operators.  Of course, SQL Server 2005 implements recursive queries using the WITH clause for SELECT statements, so such function shenanigans are less necessary:

WITH

  data AS (
    SELECT 'grandparent' AS id, CAST(NULL AS VARCHAR(MAX)) AS parent
    UNION SELECT 'parent 1', 'grandparent'
    UNION SELECT 'parent 2', 'grandparent'
    UNION SELECT 'child 1', 'parent 1'
    UNION SELECT 'child 2', 'parent 1'
    UNION SELECT 'child 3', 'parent 2'
    UNION SELECT 'child 4', 'parent 2'
  )

, hierarchy AS (
    SELECT 0 AS level, CAST(NULL AS VARCHAR(MAX)) AS parent, id
    FROM data
    WHERE parent IS NULL
    UNION ALL
    SELECT parent.level+1, child.parent, child.id
    FROM data AS child
    INNER JOIN hierarchy AS parent ON parent.id = child.parent
  )

SELECT * from hierarchy
ORDER BY 1, 2, 3

2008-02-09

Parnas on Software Engineering

In a similar vein, some of David Parnas' lectures concerning software engineering can be found at the David Parnas Lecture Series at the University of Limerick.

PDFCreator

For the record, here is a link to the PDFCreator Windows printer driver on pdfforge.

Early LISP Paper

John McCarthy has put one of his seminal LISP papers up on the web as HTML: Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I.

2008-01-31

Vital and Pivotal

Vital is a Haskell implementation that takes a document-centered approach, much like a Mathematica notebook.  Its successor, Pivotal, is a Haskell re-implementation of the Java original.  Pivotal is only in the early stages.  Both feel like incomplete implementations, but Vital in particular seems suitable for sandbox-style exploration of Haskell.

Implications of Non-Strict Functions

Here is a great little Haskell snippet that will wrench you out of imperative thinking:

notimperative x = (a,b,c,d) where
  (a,b) = incr x c
  (c,d) = incr d a
  incr i j = (i+1,j+1)

The result of evaluating notimperative 1 is (2,5,4,3).

A pithier, but more obvious, version is:

notimperative2 x = (a,b) where
  (a,b) = (b+1,x)

2008-01-29

Ivy

Ivy is the Ant group's answer to Maven.  It provides dependency management that is tightly integrated with Ant.


2008-01-26

Sandboxie

Sandboxie is a Windows virtualization application that allows you to run arbitrary programs within an isolated sandbox.  It prevents applications from making permanent changes to the true file system and registry.  Apart from the security service that it may provide, it allows you to test software installers without making any permanent changes to your system.


2008-01-22

Polyglot Blog

Luis Diego Fallas is a programming polyglot who keeps a blog, Exploring Beautiful Languages.


MIT Open CourseWare

MIT has an excellent site with lecture notes and other material available on their Open CourseWare site.


2008-01-21

XSTM

XSTM is an open source library that implements software transactional memory.

Speaking of STM, Simon Peyton Jones has written a great paper about implementing STM in Haskell, Beautiful concurrency.


2008-01-18

XSLT Root Node Problem

I am stumped by what appears to be a bug in both the IE7 and Saxon6.5.5 - which leads to wonder if it is not a bug at all but rather my misunderstanding of the way things work.  I tried to write a recursive XSLT template that worked its way up the element hierarchy, recursing until the node set '..' was empty.  To my surprise, an endless recursion occurred.  If I run Saxon in the debugger, I get the following expected results when the context has '.' bound to the top-most XML element:

local-name(.) -> test-checklist (my outermost element name)
local-name(*[1]) -> category (the element name of the first child element)
count(. | /) -> 2 (this node is not the root)
count(.. | /) -> 1 (the parent node is the root)
count(/..) -> 0 (the root has no parent)

However, if I then try <xsl:apply-templates select=".."/>, '.' is still bound to the document's outermost element (test-checklist in this case).

I tried the Xalan and .NET 1.0 transformers as well.  Everyone agrees - an endless loop occurs.  I don't understand this, and I've scoured both the XSLT and XPath specifications to find an explanation (without success).  As a workaround, I changed the termination test to 2 = count(.. | /).

Update:  I found it.  My template was matching '*'.  '*' does not match '/'.  Thus, once my code recursed up to the root, the default template rule for '*|/' kicked in.  The default rule invokes apply-templates on the context node's children.  Thus, execution would just rattle around on the top-most element.  Subtle.


2008-01-17

Prefuse

Prefuse is a nifty-looking data visualization library for Java (and soon Flash).


2008-01-11

IE7 vs Line Breaks

In IE7 (and maybe other versions of IE), line breaks are represented as carriage returns (only).  You will see this, for example, if you use DOM to extract text from a PRE element.


2008-01-09

Scala Partial Functions

In Scala, a block that contains a series of case expressions defines a partial function, thus:

val x: PartialFunction[Any,Int] = {case x: String => 1 case _: Any => 2}

Note that the type of x in the example must be specified because the input parameter to the partial function cannot be inferred.  This would not be necessary in circumstances where there is enough information to infer the type, e.g.

def doit(f: PartialFunction[Any, Int]) = f("hi")

doit({case x: String => 1 case _: Any => 2})

SQL Server Query Analyzer vs 'GO'

Be aware that Query Analyzer (and presumably OSQL) takes any line consisting solely of the word 'GO' as a batch terminator -- even if that word appears within a block comment.

SQL Server System-Generated Names

On SQL Server, the following query will list all SQL elements that have system-generated names (e.g. indexes, constraints):

select tab.name "table", obj.type "type", obj.name "name"
from (
  select null "type", null "name", null "tableId" where 1=0
  union select 'index', name, id from sysindexes where name not like '_WA_SYS%'
  union select 'primary key', name, parent_obj from sysobjects where xtype='PK'
  union select 'foreign key', name, parent_obj from sysobjects where xtype='F'
  union select 'check constraint', name, parent_obj from sysobjects where xtype='C'
  union select 'unique constraint', name, parent_obj from sysobjects where xtype='UQ'
  union select 'default constraint', name, parent_obj from sysobjects where xtype='D'
) obj
inner join sysobjects tab on (tab.id=obj.tableId)
where objectproperty(obj.tableId, 'isMsShipped')=0
and obj.name like '%\_\_%' escape '\'
order by tab.name, obj.type, obj.name

2008-01-08

Retrieving SQL Server Objects by Structure

Indexes

On SQL Server, the following SQL statement will determine the name of an index given its key columns:

select idx.name
from sysobjects tab
inner join sysindexes idx on (idx.id=tab.id and idx.name not like ''_WA_SYS%'')
where 0=(
  select sum(1)-sum(case when col.name=need.name then 1 else 0 end)
  from sysindexkeys ikey
  inner join syscolumns col on (col.id=ikey.id and col.colid=ikey.colid and ikey.id=idx.id and ikey.indid=idx.indid)
  full join (
    select null keyno, null name where 1=2
    union select 1, 'lineItemId'
    union select 2, 'projectId'
  ) need on (need.keyno=ikey.keyno)
)
and tab.name='lineItem'

Note the cryptic _WA_SYS reference.  SQL Server creates indexes that start with that prefix to support statistics operations.  It can happen in practice that there are two indexes on the same column set: one user index plus one system index.  We need to ignore the latter.

Primary Keys

In a similar vein, here is a statement to identify a primary key structurally (note that column order is not relevant):

select pk.name
from sysobjects tab
inner join sysobjects pk on (pk.parent_obj=tab.id and pk.xtype='PK')
where 0=(
  select sum(1)-sum(case when col.name=need.name then 1 else 0 end)
  from sysindexes idx
  inner join sysindexkeys ikey on (ikey.id=idx.id and ikey.indid=idx.indid)
  inner join syscolumns col on (ikey.id=col.id and col.colid=ikey.colid)
  full join (
    select null name where 1=2
    union select 'chartId'
    union select 'rowId'
    union select 'chartIndex'
  ) need on (need.name=col.name)
  where idx.name=pk.name
)
and tab.name='tbCustomChartDataSet'

Foreign Keys

To find a foreign key:

select fk.name
from sysobjects tab
inner join sysobjects fk on (fk.parent_obj=tab.id and fk.xtype='F')
where 0=(
  select sum(1)-sum(case when col.name=need.name and rcol.name=need.rname then 1 else 0 end)
  from sysforeignkeys con
  inner join sysobjects rtab on (rtab.id=con.rkeyid)
  inner join syscolumns col on (col.id=con.fkeyid and col.colid=con.fkey)
  inner join syscolumns rcol on (rcol.id=con.rkeyid and rcol.colid=con.rkey)
  full join (
    select null name, null rname where 1=2
    union select 'projectId', 'projectId'
    union select 'projectStageId', 'projectStageId'
  ) need on (need.name=col.name and need.rname=rcol.name)
  where con.constid=fk.id
  and rtab.name='tbProjectStageXref'
)
and tab.name='lineItem'

Column Constraints

To find a column constraint of some type (a 'check' constraint in the example):

select def.name from sysobjects def
inner join sysobjects tab on (tab.id=def.parent_obj)
inner join sysconstraints con on (con.id=tab.id and constid=def.id)
inner join syscolumns col on (col.id=tab.id and col.colid=con.colid)
where def.xtype='C'
and tab.name='unitConvVolume'
and col.name='qty_2'

Unique Constraints

To find a column constraint of some type (a 'check' constraint in the example):

select idx.name
from sysobjects tab
inner join sysobjects con on (con.parent_obj=tab.id)
inner join sysindexes idx on (idx.name=con.name)
where 0=(
  select sum(1)-sum(case when col.name=need.name then 1 else 0 end)
  from sysindexkeys ikey
  inner join syscolumns col on (col.id=ikey.id and col.colid=ikey.colid and ikey.id=idx.id and ikey.indid=idx.indid)
  full join (
    select null keyno, null name where 1=2
    union select 1, 'budgetId'
    union select 2, 'afeName'
  ) need on (need.keyno=ikey.keyno)
)
and tab.name='tbAfe'

Script Generation

Even more exciting, here is an SQL statement that generates an SQL script that can be run in another database to rename all indexes to match the names used in the first database (only indexes on user tables and that are not associated with a constraint or 'text' column are considered).

select text from (

select null tab, null idx, null seq, null text where 1=0

union select tab.name
, idx.name
, blk.seq
, replace(replace(blk.text, '$TABLE$', tab.name), '$INDEX$', idx.name) text
from sysindexes idx
inner join sysobjects tab on (tab.id=idx.id)
cross join (
  select null seq, null text where 1=0
  union select 1,     'declare @idx_name sysname'
  union select 2,     'select @idx_name=tab.name+''.''+idx.name '
  union select 3,     'from sysobjects tab '
  union select 4,     'inner join sysindexes idx on (idx.id=tab.id and idx.name not like ''_WA_SYS%'') '
  union select 5,     'where 0=( '
  union select 6,     '  select sum(1)-sum(case when col.name=need.name then 1 else 0 end) '
  union select 7,     '  from sysindexkeys ikey '
  union select 8,     '  inner join syscolumns col on (col.id=ikey.id and col.colid=ikey.colid and ikey.id=idx.id and ikey.indid=idx.indid) '
  union select 9,     '  full join ( '
  union select 10,    '    select null keyno, null name where 1=2 '
  /* 1000-9999 reserved for key column names */
  union select 10000, '  ) need on (need.keyno=ikey.keyno) '
  union select 10001, ') '
  union select 10002, 'and tab.name=''$TABLE$'' '
  union select 10003, 'exec sp_rename @idx_name, ''$INDEX$'', ''INDEX'''
  union select 10004, 'go'
  union select 10005, ''
) blk
where tab.xtype='U'
and idx.indid<>255
and idx.name not like '_WA_SYS%'
and not exists (select 1 from sysobjects where name=idx.name)

union select tab.name
, idx.name
, 1000+ikey.keyno
, '    union select '+cast(ikey.keyno as varchar)+', '''+col.name+''''
from sysindexes idx
inner join sysobjects tab on (tab.id=idx.id)
inner join sysindexkeys ikey on (ikey.id=idx.id and ikey.indid=idx.indid)
inner join syscolumns col on (col.id=idx.id and col.colid=ikey.colid)
where tab.xtype='U'
and idx.indid<>255
and idx.name not like '_WA_SYS%'
and not exists (select 1 from sysobjects where name=idx.name)

) data

order by tab, idx, seq

2008-01-05

LISP Survey

I stumbled across an interesting LISP article, Common Lisp Implementations: A Survey.

Mandelbrot in Mathematica

Just for laughs, a implemented a tiny Mandelbrot application in Mathematica.

mandelbrot =
  Compile[{{cx, _Real}, {cy, _Real}, {limit, _Integer}},
    Module[{count = 0, zx=cx, zy=cy, zx2=0, zy2=0, tx=0, ty=0},
      While[count <= limit && (zx2 = zx^2)+(zy2 = zy^2) < 4,
        ++count;
        tx = zx2 - zy2 + cx;
        ty = 2 zx zy + cy;
        zx = tx;
        zy = ty
      ];
    count
  ]
];

Manipulate[
  ReliefPlot[
    Table[
      mandelbrot[x, y, limit],
      {y, y0, y0 + x1 - x0, (x1 - x0) / resolution},
      {x, x0, x1, (x1 - x0) / resolution}
    ],
    ColorFunction -> colors
  ],
  {limit, 50},
  {resolution, 400},
  {x0, -2},
  {x1, 1},
  {y0, -1.5},
  {colors, Sort@ColorData["Gradients"]}
]

Wicket

Apache Wicket is yet another web framework that is getting some buzz.


2008-01-04

Scala

Scala is a programming language that seems to be largely a fusion of Haskell and Java.  As is the fad these days, it has its own web framework called lift.  I spent some time working with Scala, and it appears to be a promising successor for Java.  There is a growing, vocal community using it.

My attention was drawn back to Scala by Bruce Eckel's blog entry Java: Evolutionary Dead End.  Quite a few people in the blogosphere share the view expressed in a blog entry by n8han, The awesomeness of Scala is implicit.


Blog Archive