Monday, October 31, 2011

Monadic Predicate Logic with Some Modal Operators

I have a new version of the monadic predicate logic program that I posted a while ago.  It has operators for possibility and necessity (<> and [], respectively).  They bind to sub-expressions the same way negation (~) does; they bind to the nearest existential or universal quantifier to the right, or, failing that, the nearest predication to the right, so <>Px&Py is equivalent to (<>Px)&(Py) but not <>(Px&Py)<>x,Px&Py is equivalent to <>(x,Px&Py) but not (<>x,Px)&Py.  I'm posting it and its source code, now that I have written a parser that I'm not ashamed of.  The one downside is that it no longer supports the "old school" dot grouping.  If any one wants to use it, tell me and I'll add it back in.  If anyone uses this program at all, tell me!

Wednesday, October 26, 2011

Setting Local Variables in Visual Studio

Have you ever wanted to change the value of a local variable inside of a method?  Without changing its code or pausing it in the debugger, that is?  Maybe not, but I did, while writing a unit test this week.  I figured out how to do it in Visual Studio, using Visual Studio's DTE object.  The DTE object provides a programmatic interface to Visual Studio's debugger.  With it, breakpoints can be set and deleted programmatically.  But what about changing the variable?  Breakpoints can have conditions, so...


using EnvDTE;
using System.Runtime.InteropServices;

...

// Get the DTE object.
DTE lDTE =
  Marshal.GetActiveObject( "VisualStudio.DTE" ) as DTE;

// Set a conditional breakpoint.  In this example, the
// break is in file.cs, line 422.
lDTE.Debugger.Breakpoints.Add(
  null,
  "file.cs", 
  422,
  1,
  // Use the break condition to set the local variable
  // you want changed.  Note that the expression always
  // returns false; the debugger will assign 1 to
  // lVariable every time the condition is evaluated,
  // but never pause the unit test.
  "(lVariable = 1.0f).ToString() == null",
  dbgBreakpointConditionType
    .dbgBreakpointConditionTypeWhenTrue,
  null,
  null,
  0,
  null,
  0,
  dbgHitCountType.dbgHitCountTypeNone );

// Call that method...
...

// Delete the breakpoint if you don't want it
// to affect later code.
lDTE.Debugger.Breakpoints.Item( 1 ).Delete();

Tuesday, October 25, 2011

John McCarthy

John McCarthy died yesterday.  It's funny, I looked at his website yesterday and later thought about how old he must be, not knowing he had passed.  He invented the LISP programming language back in the late 1950s. Even though I don't program in LISP - I wrote a Scheme plugin for GIMP a few years ago; that's about all - I admire it a lot.  Thinking about how simple its syntax is and how simple its runtime is, yet how powerful it is just makes me feel good inside.  It's like a work of art.

So, those of you who are programmers: to commemorate, read McCarthy's original specification for LISP, which is an excellent read for any computer scientist.  And then write a program in the functional style.


John McCarthy, 1927-2011

Tuesday, September 27, 2011

Golf This!

Here's something for all you programmers out there:

print((@ARGV=map glob,@ARGV)?do{0 while(<>);$.}:0)
  1. Easy: What language is it?
  2. Moderate: What does it do?
  3. Difficult: Can you golf it?  That is, can you write a script that's even shorter but does the same thing?

Sunday, June 12, 2011

A Lambda Calculus Evaluator

Here's an application I created back in 2007 that evaluates Lambda Calculus expressions.  I doubt it will be of use to anyone; if you know what Lambda Calculus is, and you actually care about it, you might decide to write your own evaluator, like I did.  This one has a nice, friendly graphical user interface, though.
If you want to run it, download LambdaCalculus.zip, unzip it and run LambdaCalculusGUI.exe.  You'll need .NET or Mono installed on you computer, and you'll need LambdaCalculus.dll (included in LambdaCalculus.zip) to be in the execution directory (probably the same directory that LambdaCalculusGUI.exe is in).

The application is written for .NET 2.0.  That's before LINQ, but after generics.  Nevertheless, I was using ArrayList where I could have used List<Type>.  And I was using Hungarian notation.  Boo. Programmers: do you ever look at your old code and squirm a little because of something you did that you would never do now?

    Sunday, May 08, 2011

    Hours of Sunshine Annually in USA

    I made a Google Earth map of hours of sunshine per year for various places in the U.S. I got the data from "Historical Sunshine and Cloud Data in the United States, CDIAC NDP-021/R1", a database from the Global Change Master Directory - a government website.  I matched the place names in the database with locations I found in another database published by the USGS.



    I constructed the document with two Perl scripts: one to match place names with locations and another to write the KML.  I had to match some places names with locations by hand.

    Sunday, April 10, 2011

    Language Recognition with gzip

    So I'm watching a lecture in CS221, and Prof. Norvig shows a slide with this Unix command on it:
      cat | gzip | wc
    and informs us that it can be used to identify what language a text is written in.  Basically the command is "combine some files, zip them up, then measure the size of the resulting zip file.  Jiggawhat?  Yes, there is a thing called "compression-based classification", and it's actually pretty effective.  What happens when you zip a file?  A compression algorithm finds repeated patterns in the file and replaces instances of them with shorter patterns.  The more and longer the repeated patterns, the more the file can be compressed.  What happens when you zip two files together?  If they have similar content, they will compress well.  If they have different content, they won't compress as well.  So, if you have some text and you want to find out what language it is, zip it with example texts for any language it might be.  The language it compresses best with is the language it is mostly likely to be.  If the languages you are considering aren't too similar (e.g. Dutch & German, not Norwegian & Swedish), this technique is actually very reliable.

    People have made serious studies of this.  I tried it out informally, and it actually works.  Here's a Perl script that does compression-based classification:
    Note the system call in size_when_zipped.  I threw together a "corpus" for each of several languages by picking text from books on Project Gutenberg; English, French, German and Dutch and found the script to work consistently for various texts.

    Changing the topic: I rewrote the script in Python and Haskell, just to see how the code would compare.  The translation from Perl to Python was pretty direct.  Again, I use Unix utilities to zip the files together and measure their length.  The Python version is both fewer lines and fewer characters, but only because I used less whitespace and no lines were devoted beginnings and endings of code blocks.  The translation to Haskell was less direct.  I don't have a Unix or GNU system to run Haskell programs on, so, when I wrote the Haskell version,  I had to write functions to perform the globbing and concatenation done by cat and the zipping done by gzip.  It it weren't for that, the Haskell code would have been the smallest.  Haskell blows both Python and Perl away in terms of terseness, without being (IMO) less readable.
    I must say that Python is ridiculously easy to code with.  I've only written a few hundred lines of Python, and I already feel like I've got the language figured out.  Still, Perl is more fun.  Probably because in Perl "There's more than one way to do it", and using the ins and outs of the language to find a way to do that is both elegant and readable is an interesting challenge.  With Python "There should be one—and preferably only one—obvious way to do it"  and there are no challenges if you already know how to write conventional C#/Java code.

    Thanks to Job Vranish for the lovely definition of bestOf in the Haskell version. The version I wrote was several lines longer.  With Haskell "There is more than one way to do it, the obvious way to do it is with recursion, but you should never use recursion because somebody already wrote higher-order function to do it".