Does the world need yet another programming language? After reviewing Curl, I'm still not sure. Most languages start out as an attempt to simplify overly complex and cruft-filled older languages. But as they develop, these new kids on the block are beset by many of the same ills that plague their older siblings.
Curl began optimistically in 1995. The language was devised as a way of addressing vexing client-side problems that were troublesome after many years of browser development. These problems were mainly due to disparate development directions with limited standardization for two and three dimensional graphics, file access, multimedia support, and XML, for example.
pros |
cons |
Curl is enabled via a plug-in that works with either Internet Explorer or Netscape Navigator 4.x (and is mostly compatible with Netscape 6/Mozilla). Curl currently supports Windows only. Both Mac and Linux ports, and a server version are planned.
The language is noteworthy for its license. While the development licenses are free, Curl supports itself by charging on a per-use basis in full production environments, making it an early contender in the subscriber space that initiatives like Microsoft .Net are striving to fill. Licensing fees are set by usage ($0.0005/KB of data transferred).
The goal of Curl is simplicity, although I'm leery of any languages that are supposedly designed for non-programmers. The basic code examples look like slightly twisted LISP after a few run-ins with XML. I wrote Listing 1 as a routine that converts between miles and kilometers. This routine is fairly easy to follow if you're familiar with programming, but Curl isn't that much friendlier than JavaScript. And a strong data typing structure can make for very efficient code, but at the expense of more complex developmenta questionable trade-off in scripting.
However, Curl does exhibit some interesting concepts. The structure of the language in general follows the convention:
{operation [parameterName = ] expression[:type] [,[parameterName = ] expression[:type]]}
Operation
is the action (let
, set
, define-proc
, paragraph
, and so
on), expression
is a contained operation/expression/type triplet (or the result of same), parameterName
is the name of the parameter that's being operated on, and type
gives the expression data type. The elements within square brackets indicate optional elements (the bracket itself isn't included), while the integral curly braces group expressions.
Curl also distinguishes between declaration and assignment of a scalar value, which can make your code more efficient, but adds the complexity of deciding whether a given expression is a constant, a parameter, or a functionmuch more challenging than loosely typed languages like JavaScript.
Functions in Curl are relatively straightforward once you get used to the stack-like order of operations. For instance, consider Listing 2, the converter from Listing 1. The function defines an input parameter, miles_in
, as a floating point number, and specifies that the output type should also be a float. It then defines an expression as a float that performs the actual conversion to a temporary variable (called k
). The final line returns the variable's contents to the calling function. The line delimiter is a carriage return.
An additional aspect of this approach is that you use Curl to create HTML-like output functionally, rather than through markup. For instance, this code creates a paragraph that's sent to the display:
{paragraph {value myMiles & " miles = " & {m2k myMiles} & " kilometers"}}
It's worth noting that there isn't any HTML in this code. Curl creates its own display region and outputs its content to that region, rather than creating content for a browser. This gives you much finer control over the output, but at the expense of the very real benefits provided by the massive HTML infrastructure (more on this later).
The event-handling mechanism follows a model similar to that of DHTML. Each Curl object can add one or more event handlers that can be used to either invoke specific method calls or to set properties for the handler or other objects. To test this, I wrote the code in Listing 3, which creates two rectangles and adds them to a flow container (much like a layout container in Java). The code then attaches event handlers to each rectangle that set different colors when the mouse enters or leaves it. (Note that Curl uses ||
to delineate comments, rather than //
or #
.) The add-event-handler method takes an event object
(the PointerEnter
or PointerLeave
objects) and performs the commands given after the do
keyword. This model of treating the events themselves as distinct objects, which can then be caught by the appropriate event handlers, is gaining currency with most languages.
Surge Lab, the Curl IDE, is adequate. However, it isn't Curl's strongest feature by any stretch. Curl, like most compiled languages, supports the idea of packages. These are compiled sets of Curl programs that together provide a unified set of functionality. Unlike more sophisticated IDEs, Surge Lab doesn't let you see packages through an object viewer or via pop-ups while you're typing. Nor can you select a specific object and see its definition. Thus, you're reliant upon the Help system, which is also written in Curl. It's a surprisingly good resource for showcasing Curl's capabilities. Clearly, Surge Lab's strength is the ability to produce document-oriented code. The resulting code flows in a way that's reminiscent of HTML, and it doesn't rely upon absolute positioning as you'd expect with C++ (even though this is possible if needed). The Help system is broken into an API document that makes the packages and their enclosed objects, methods, and properties somewhat reminiscent of the Javadoc system.
working with text, graphics, sound, and 3d
Many of the critical packages (like graphics handling) are implicitly loaded by the environment itself, but you can add your own or third-party packages using the import
command from within your scripts. The graphics model that Curl uses is built upon the creation of graphical objects rather than simply rendering content to a graphical space. This feature makes Curl useful for developing interfaces, because it lets you create complex objects out of simple ones through inheritance and aggregation. This also applies to text. Many of the properties for specifying text follow the CSS conventions, as Listing 4 demonstrates. You can also create sophisticated custom flow output (as in Listing 5).
Curl supports a fairly impressive set of libraries. Beyond the basic two-dimensional features, Curl has a rich 3D-rendering environment, including the ability to animate 3D scenes, create scene graphs, and work with basic renderers, 3D text, and particle systems. The language also supports one of my favorite features: filters. These let you apply precise effects onto a graphic image, such as introducing blur effects, posterizing and embossing graphics on the fly, and twirling content. In addition, Curl supports both external .WAV files and generated sounds (via frequency envelopes), and includes image loading and manipulation capabilities.
file systems and networkingCurl was intended as a client language for working with external Web services and HTTP. You can read files (and HTTP file headers) from remote Web servers, although currently there's limited support for writing to external files. The code in Listing 6 retrieves the headers from a specific Web page (initially, www.curl.com). The routine creates a Web-stream object, which can then receive Web content and extract the relevant headers.
Curl also works explicitly with Web services that use SOAP. It currently supports the (latest) version 1.1 SOAP specification. Understanding this spec itself isn't necessary. However, you do need to know enough to set up the requisite data types in your argument calls. Once you set up these services, you can call them transparently as remote procedure calls.
The Curl packages also include an XML SAX parser for handling simple XML work. The parser is useful for evaluating commands based upon specific XML elements, but it has several limitations when querying XML or retaining a DOM object in memory. It doesn't support XSLT or XPath, so you can't do any native transformations upon it. As an ardent XML practitioner, this omission disappointed me.
Finally, Curl has a full complement of file and directory routines, but this is a mixed blessing. These capabilities work well when the client is used locally (for example, looking at a Curl file located on your hard drive rather than on a server). However, they don't work when the Curl application is talking to a server, for sandbox security reasons.
swimming back
Some aspects of Curl, like the 2D and 3D graphics integration, offer some interesting potential for development, especially with XML. The Curl language can be a bit cryptic at first, but once you get a feel for it, it's internally consistent and supports object-oriented development among its many design features.
However, Curl has its fair share of negatives. It's especially frustrating as a client language. The type system that Curl uses seems curiously antiquated in an age when Python, Perl, and JavaScript all demonstrate that weakly typed languages offer many advantages in client systems.
Curl also doesn't provide much in the way of interoperability with other environments, even as a component embedded in an HTML Web page. The IDE needs to be radically improved before it can be taken seriously as a development environment. It's stable (which isn't something you can take for granted), but the bar has been raised on IDEs: after several years of working with IDEs such as Microsoft Visual Studio, Sun Forte, Borland JBuilder, and so on, the expectations of developers for such features as dropdown APIs, good project management tools, and context-sensitive help mean that anything less will be seen as substandard.
Curl has the potential to be very powerful. Its ability to work with interpreted, instead of compiled languages means that Curl can be used for sophisticated applications in response to just-in-time changes on the server and access privileges. Curl's LISP-like structure is also making a comeback in the computing world as systems become more complex and distributed. With future SVG support, Curl's graphic generation abilities will provide an alternative to developing interactive SVG graphics on Internet Explorer.
Curl has cool features and it could very well become important over time. Curl may be the next Java, especially because its designers have solved one of the big headaches that Java hasn't: they've developed a good client-side programming language.
Kurt is an author and a developer who specializes in Web technologies and XML. You can contact Kurt at [email protected].
{curl 1.7 applet} {applet license="development"} {let miles : float, kilometers:float} {define-proc {m2k miles_in:float}:float let k:float = (miles_in * 1.6) asa float {return k} } {set kilometers={m2k 100}} {title "Miles To Kilometers"} {paragraph {value "100 miles = " & kilometers & " kilometers"}} {paragraph {value "200 miles = " & {m2k 200} & " kilometers"}} {let myMiles :float = 300} {paragraph {value myMiles & " miles = " & {m2k myMiles} & " kilometers"}}
</code> {define-proc {m2k miles_in:float}:float let k:float = (miles_in * 1.6) asa float {return k} }
{curl 1.7 applet} {applet license="development"} {value let left = {RectangleGraphic width=100pt, height=50pt} let right = {RectangleGraphic width=100pt, height=50pt} let my-hbox = {HBox left, right} || attach first event handler to left rectangle {left.add-event-handler {on PointerEnter do set right.fill-color = "green" } } || attach second event handler to left rectangle {left.add-event-handler {on PointerLeave do set right.fill-color = "red" } } my-hbox }
{paragraph font-size=24pt,font-family="san-serif",font-weight="bold", font-style="italic", The Curl Help System}
Listing 5
{curl 1.7 applet} {applet license = "development"} {define-text-proc {blink ...}:any let color-str:String = "blue" let flash:TextFlowBox = {TextFlowBox font-weight = "bold", color = color-str, {value ...} } {Timer interval = 0.25s, {on TimerEvent do {if color-str == "white" then set color-str = "blue" else set color-str = "white" } set flash.color = color-str } } {return {text {value flash}}} } {paragraph font-size=24pt,font-family="san-serif",font-weight="bold", font-style="italic",
> {value let url-text:TextField = {TextField width=3in, value="http://www.curl.com/"} let web-buffer:VBox = {VBox} let connect-button:CommandButton = {CommandButton label = "Get it!", || when button is clicked ... {on Action do || convert string to Url let web-url:Url = {url url-text.value} let http-file:HttpFile = {web-url.instantiate-File} asa HttpFile || open the Url let web-stream:HttpTextInputStream = {http-file.http-read-open || don't redirect auto-redirect? = false, || return response headers even if error status always-return-response-headers? = true} || display status {web-buffer.add "Status: " & web-stream.response-headers.status} || display response headers {for value:String key name:String in web-stream.response-headers do {web-buffer.add name & {if value == "" then "" else ": " & value} } } {web-stream.close} web-buffer } } {spaced-vbox {spaced-hbox {text URI to get:}, url-text, connect-button}, {HBox {text {bold Response Headers:}}}, {HBox width=5in, web-buffer} } }