Wednesday, November 18, 2009

Learning Curl: {value expr} and Curl as an expression-based language

One thing that I have noticed in C# and Java programmers learning Curl is that if they rely on one of the available books (and even to some extent if they use the on-line Curl resources) there is a puzzle about {value some-expression} code blocks.

Here is an example from a book on Curl:
{value 2fortnights + 1day}
This an example of a Curl expression in which quantities are added (note the optional use of the plural for the user-defined quantity.)

{curl 7.0 applet}
{let public constant fortnight:Type = {type-of 14days}}
time in seconds is {value 2fortnights + 1day}
 
In keeping with the Gentle Slope approach to reduce the steepness of the Curl learning-curve, the text
time in seconds is
appears in the browser as text.
We say that this bit of text is at the top-level.
What follows, however, is an expression within curly braces and what we want to display is the result of that addition of the two Time quantities. We could have written this expression using optional parentheses as
{value (2fortnights + 1day) }
The {value } macro has been used to return a value: that is all.
To show that this is so, consider this alternative:
{String (2fortnights + 1day) }
The default constructor for the String class also returns a value (an instance of a String.)
Here is another alternative using assignment to a variable named tos:

{let tos:Time = 2fortnights + 1day}
The Time value held in the variable is {String tos}

And finally a complete alternative applet:

{curl 7.0 applet}
{let public constant fortnight:Type = {type-of 14days}}
{let tos:Time = 2fortnights + 1day}

The time in seconds equals {value 2fortnights + 1day}

Time quantity in the variable is {String tos}

Number of days: {format "%.0f", (tos / 1day)}

which displays in the browser as follows:

The time in seconds equals 2.5056e+006s

Time quantity in the variable is 2.5056e+006s

Number of days: 29

A more compact version of the applet using explicit {br} line formatting rather than relying on Curl to display the extra new lines might have been:

{curl 7.0 applet}
{let public constant fortnight:Type = {type-of 14days}}
{let tos:Time = 2fortnights + 1day}
The time in seconds equals {value 2fortnights + 1day} {br}
Time quantity in the variable is {String tos} {br}
Number of days: {format "%.0f", (tos / 1day)}

And so we proceed to wend our way up the 'Gentle Slope' of Curl.

Wednesday, November 4, 2009

What's new in what was once Borland Turbo Prolog?

PDC Visual Prolog has a page on what's new in 7.2

What stood out for me was anonymous predicates or "nameless clauses" as the Prolog response to "anonymous functions".

If you are interested in Tokyo Cabinet, you might want to glance back at PDC over the years and their features offering internal and external databases.  While I have been more excited about XSB and Logtalk in recent years, I have always enjoyed working in PDC.

There is something of an equivalent PROLOG in the Mercury project: both are distinctive in having a type system and in how they track determinism.  Both PDC and Mercury would like to appeal to programmers with a hankering for a functional style.

There are many active Prolog projects: the SWI-Prolog project is likely the most active in opensource and offers RDF parsing - somewhat different from that offered by XSB.

It is odd that with all the interest in Joe Armstrong and Erlang that there seems to be no up-tick in interest in Prolog and Constraint Logic Programming: the acquisition of ILog by IBM and the move of Drools into JBoss seem not to float any other boats.

Like Prologia (Prolog IV) in France, PDC now focuses on their software application offerings and not the language - but you wonder what would have happened if Apple or Microsoft had offered a Prolog to compete with Borland back in the late 80's ... but you could say the same of Smalltalk (in fairness, Apple's Objective-C is like Smalltalk and for some time Apple was home to some Smalltalk researchers.)  At least PROLOG never suffered the fate of Self and Strongtalk at the hands of SUN.

PDC was an early advocate of DSL's (Domain Specific Languages) but I do not know if these feature prominently in their own commercial packages.

Meanwhile, over at Strawberry Prolog a Windows prolog has been in a Beta for version 3.0 for almost a year: it was to contain a major innovation in the design of Prolog compilers, but I am still back at 2.9.2

If you like Eclipse, you might like AMZI Prolog 8 which comes as an Eclipse environment.  Amzi! is a pleasure to use and has great documentation if you have been away from logic programming for awhile.  But there are other options for Prologs which interface with Java and many "small" prolog interpreters about. 

One way to glimpse which Prolog implementations are active is to see which are supported by Logtalk - but that would exclude some of those which come with their own OOP frameworks .. such as PDC.

For other recent changes in PROLOG, see xsb.com and XSB at sourceforge.

If you are tracking any other PROLOG innovations, please add a comment and a link.  I have a note on Distributed Oz 1.4.0 elsewhere ...

Friday, October 23, 2009

ObjectIcon 2.0 UNICODE ICON programming language

The latest release of ObjectIcon is now at code.google which brings oit and oix up to 2.0

This release built without incident on my Ubuntu box and is running behind some scripts on my shared host site.

I have posted a request to Robert Parlett to comment on what features distinguish 2.0 from 1.4

The ICON language itself remains at 9.4.3

Other ICON variants include OOP UNICON and the more-pythonic Converge with its meta-programming features (Converge implements a complete Compile-Time Meta-Programming facility.)

Ralph Griswold and other ICON originators brought us iterators, generators, associative arrays and an alterntive logic-programming facility (Erlang is another language with a restricted or limited logic programming feature set.)  ICON language features are now common in Python and Ruby but its style of logic as success-or-failure rather than true and false goes far beyond non-zero evaluating to a Boolean value as found in many other programming languages.  ICON is an expression-based language (other such languages include Curl and REBOL) which leads to idioms unlike those typical of procedural languages working with a command/statement paradigm in which expression evaluation is secondary.  ICON is nonetheless procedural: each program begins with
   procedure main()

ICON and its follow-on variants are arguably the most neglected languages which were ever aimed to interest non-programmers.  

Saturday, October 17, 2009

4 Windows Browsers

I use Opera 10, Safari or Chrome or IE8 or Prism when I am not in a browser from those I am working on at aule-browsers.com

Opera has the smallest footprint at startup on my XP box ( I use Epiphany on linux) and I stopped using Firefox when it began to choke and bloat on my large set of bookmarks.  Opera behaves well on a few sites where IE8 misbehaves and vice-versa.  When all else fails I turn to Chrome or Safari (Opera is also the only one that passes w3c Acid3 on this box - but Safari does warm the room with its updates.)

Here are 4 other Windows browsers that you might want to consider:

Avant at http://www.avantbrowser.com/

TheWorld at http://www.ioage.com/en/index.htm

Wyzo 3 at http://www.wyzo.com/

SlimBrowser at http://www.flashpeak.com/sbrowser/

The latter offers to build your site-specific browser, so I will be happy to submit a competitive bid if that is your need!

Concept Application Server

While looking at alternatives to Jetty and Geronimo with Jetty, I chanced upon the Concept Application Server.  I will make an effort not to take the wrong tone.

A few tips: they offer the server and the client.  Take the server. It comes with the client and you want them co-installed or no end of test scripts break (expect paths to be hard-coded and they will be the physical paths.)

The web site is in English but is in need of work.  If you find the help CHM file, you will find that it even more in need of help.

The server and client are said to be RC (release candidates) but their own simplest examples crash the client on my XP desktop.  Those examples were a mix of broken English and garish odd dialogs with senseless layout or radiobuttons which are not etc. etc.  They say their current focus of effort is on their IDE, which I have not seen (it will not run.)

The choice of the name 'Concept' is so regrettable.  It is the name of their alternative programming language. The architecture is something like client server for the web: applications reside on the server but execute in a client.  So how to see this in action?

The server bin has options to install as an NT service.  Once that is done, you can try
     concept://localhost/Samples/test.con
in your browser.

You may do better than I did in Opera and IE 8 on XP if you are running Vista or Seven.

What was sad to see was the immense install: the server arrives with an immense pile of DLL's.  The download was very slow in my case (they may be serving the file themselves) and I had already waited for the Client (my mistake, I guess.)

It remains unclear why anyone would adopt the Concept programming language unless they believe that programmers are what is needed: this looks like life without the web designers.  But they also appear to be without UI designers.  Perhaps they have an alternative to HTTP, but I cannot see it after a few hours.

Their blog has seen no addition in the past year (last entry Oct 2008) but it is tell-tale, quote
The Linux distribution is now up-to-date (or almost up-to-date).

The worst is the commendation from a Romanian academic: the author of Concept is working to write the demo chat program in less that 1 minute - indeed, he will soon be able to write those few lines of code in less than 30 sec's.  This feat may impress some CIO somewhere.  And the team is brilliant and the team is dedicated.  But a former president's wife was an all-but illiterate peasant who was awarded a PhD and headed chemical research.  This is Romania.  Not Montenegro, but still, caveat emptor.  I follow a promising project in Sofia, Bulgaria.  But things are not always what they seem in countries where for years saying made it so.  Even in academic life.

If this server and client are 'release candidates' then I might also be the pope.

And if the documentation were not a big enough concern, I cannot find a test framework.  A search in the CHM reveals an assert but no hint of Test, UnitTest, Builder, Factory.

The one large coding effort, GyroGears, is included in compiled form as is the PDFViewer.  And this is open-source of some sort.  The SOAP code that I looked at had no header for copyright or copy-left.  A submarine patent nightmare, I assume.

The author's one PDF tells us that Concept is faster than Python.  Which Python?  Faster than PHP.  Bare-bones open-source PHP?  And why with Scala available, would we choose this form of DLL-hell on a Windows platform?  And if so much like PHP in practice, why not opt for haXe?

Concept most often means "abstraction", an important CS notion.  But today that means such things as the use of interfaces in the implementation of inversion of control.  Patterns.  Web containers.  Geronimo.  But what I find here is very unclear:  the two documents offered are unencumbered by references.

At first I thought that Concept was like client-side Curl (http://www.curl.com/ and not haxx.se cURL) but shifted to the server-side with a focus on the delegate pattern.  There is talk of an interface builder, but I see no sign of it yet in the code.  I may dig a bit more, but the game appears not to be worth the candle.

For developers most at home with GTk, this may be of interest for a project in Romania with funding for 'made in Romania' systems.  Perhaps someone at LtU would take a look at the merits of Concept as a programming language and the use of delegates in the CAS framework.  Maybe someone can see more clearly which architectural challenges are being addressed and how to judge how effectively.  Maybe this is a place for a cyclic dependency metric to be applied.  Perhaps there is some research published in Romania or some tangible data on the one HR system which has been implemented (gone into production?) in CAS or using their GyroGears.

Someone may be unkind enough to notice the file extension; perhaps another unfortuate choice.  What I suspect, is that CAS is a project solving a non-problem or another problem: the focus is on keeping the software on the server to prevent piracy and preclude updates while being performant to reduce server load.  But the trips to the database are the usual issue, and I see nothing to address that in what I can tease out of the code and the limited docs.

Thursday, October 15, 2009

curlgen with Groovy BuilderSupport: CurlBuilder for Curl web content markup

Because the Groovy MarkupBuilder has a private method which hardcodes the markup delimiters, a CurlBuilder must extend BuilderSupport just as does MarkupBuilder itself.

What follows looks to be roughly a builder candidate for Curl web content markup using "{" and "}" as the delimiters.  As with XHTML, the Curl content may require a 'prolog' and a few non-hierarchical items comparable to the !DOCTYPE of XML.  Web markup is often more than simply a hierarchy of nested nodes.
/**
* A helper class for creating Curl markup
* borrowed from http://docs.codehaus.org/display/GROOVY/Make+a+builder
* original MarkupBuilder by James Strathan
* mods by RS
*/
public class CurlBuilder extends BuilderSupport {

private IndentPrinter out;
private boolean nospace;
private int state;
private boolean nodeIsEmpty = true;

public CurlBuilder() {
  this(new IndentPrinter());
}

public CurlBuilder(PrintWriter writer) {
  this(new IndentPrinter(writer));
}

public CurlBuilder(Writer writer) {
  this(new IndentPrinter(new PrintWriter(writer)));
}

public CurlBuilder(IndentPrinter out) {
  this.out = out;
}

protected void setParent(Object parent, Object child) {
}

protected Object createNode(Object name) {
  toState(1, name);
  return name;
}

protected Object createNode(Object name, Object value) {
  toState(2, name);
// out.print(">");
  out.print(value.toString());
  return name;
}

protected Object createNode(Object name, Map attributes, Object value) {
  toState(1, name);
  for (Iterator iter = attributes.entrySet().iterator(); iter.hasNext();) {
    Map.Entry entry = (Map.Entry) iter.next();
    out.print(" ");
    print(transformName(entry.getKey().toString()));
    out.print("='");
    print(transformValue(entry.getValue().toString()));
    out.print("'");
  }
  if (value != null)
  {
    nodeIsEmpty = false;
    out.print(" " + value + "}");
  }
  return name;
}

protected Object createNode(Object name, Map attributes) {
  return createNode(name, attributes, null);
}

protected void nodeCompleted(Object parent, Object node) {
  toState(3, node);
  out.flush();
}

protected void print(Object node) {
  out.print(node == null ? "null" : node.toString());
}

protected Object getName(String methodName) {
  return super.getName(transformName(methodName));
}

protected String transformName(String name) {
  if (name.startsWith("_")) name = name.substring(1);
    return name.replace('_', '-');
}

protected String transformValue(String value) {
  return value.replaceAll("\\'", """); }

protected void toState(int next, Object name) {
  switch (state) {
    case 0:
      switch (next) {
        case 1:
        case 2:
          out.print("{");
          print(name);
          break;
        case 3:
         throw new Error();
      }
      break;
    case 1:
      switch (next) {
        case 1:
        case 2:
          out.print(" ");
          if (nospace) {
            nospace = false;
          } else {
            out.println();
            out.incrementIndent();
            out.printIndent();
          }
          out.print("{");
          print(name);
          break;
        case 3:
          if (nodeIsEmpty) {
            out.print(" }");
          }
          break;
        }
        break;
      case 2:
        switch (next) {
          case 1:
          case 2:
            throw new Error();
          case 3:
            out.print(" }");
            break;
        }
        break;
      case 3:
        switch (next) {
          case 1:
          case 2:
            if (nospace) {
              nospace = false;
            } else {
              out.println();
              out.printIndent();
            }
            out.print("{");
            print(name);
            break;
          case 3:
            if (nospace) {
              nospace = false;
            } else {
              out.println();
              out.decrementIndent();
              out.printIndent();
            }
            out.print(" }");
            break;
        }
        break;
     }
     state = next;
   }
}
That could have been so elegant if the MarkupBuilder class had understood markup itself as a pattern rather than hard-coding the SGML-style tag delimiters and assuming the tagging style (close before content, reopen after content.)

The ability to inject a markup builder for non-SGML markup for an entire site is lost: we still have to look into such things as 404 and 500 errors because we have only covered where we explicitly instantiate a builder.  DI should have solved that web container-wide.

As I never tire of saying, when we get beyond HTML5 and the mere browser, this SGML-bias will look like an unquestioned assumption as curious as any other in the history of data format oddities and over-sights.

To get from   <br/>  to {br} should not be a coding intervention task of this magnitude or this nature.

Wednesday, October 14, 2009

curlgen with Ruby Rails: Mime::Type.register and response.rb

I took some time today to try to see what is happening with default MIME content_type over at lighthouseapp.com

But I am still at sea ...

In the meantime, the Rails code states that we must not use the Response class itself. So what to do if you want to change a default MIME type across a site. For example, the default in the Mailer is 'text/plain'. And in the Response class there is a method

   def assign_default_content_type_and_charset!
      self.content_type ||= Mime::HTML

which is immediately called by

  def prepare!
    assign_default_content_type_and_charset!
    handle_conditional_get!
    set_content_length!

The first thing was to track down the Mime module in action_controller where you can see that your type may be missing (mine was.)

So now I might start the effort to convert to non-HTML web content as site output with

    Mime::Type.register "text/vnd.curl", :curl

The Mime module has a class Type (yes, I know, but so it is) and that has a static
   @@html_types = Set.new [:html, :all]
Note that it is not
  @@markup_types

Of course, it might be easier just to go into the Response class and have it set its default to the Mime::Type class static default.

But should it really be necessary to repair and modify these classes to achieve something so obvious as the default MIME Content-Type for an HTTP web framework?

That's where the hope lies with Rails 3.  But Rails 3 will be a marriage with merb and there will have to be compromises. But we should be able to hope that hard-coding the MIME defaults will be a thing of the past.

Of course for individual controllers you can go piecemeal with

  class MyApplicationController < ActionController::Base



    before_filter :set_content_type
    def set_content_type
     @headers["Content-Type"] = "text/vnd.curl; charset=utf-8"
    end
  end
 
but then you are faced with tracking down just how much of ApplicationController you must override. For example,
 
  def record_not_found
    render :text => "404 Not Found", :status => 404
  end
 
must become something like
 
  def record_not_found
    render :text => myApp.msg_404, :content_type => 'text/vnd.curl' :status => 404
  end

If you are aware of how Rails on ruby 1.8.6 can globally alter the Response content_type, please add a comment.  I don't see the answer over in the Rack module where you will find hard-coded

      @header = Utils::HeaderHash.new({"Content-Type" => "text/html"}.merge(header))

Oops.