18 May 2009

Soft State in the PLT Web Server

posted by Jay McCarthy

Many Web applications and network protocols have values in the continuation that are necessary to complete the computation, but that may be recomputed if they are not available. This is “soft state”.

For example, a Web application may cache a user’s preferences from a database and deliver it to a Web browser as a hidden value; when the value is returned to the application in subsequent steps, it is used to customize the display. However, if the preferences were not available (or were corrupted in some way), the application could retrieve them from the database.

When using the PLT Web Server’s native continuations, this roughly corresponds to the use of a weak box: a box that the GC is allowed to erase the contents of. When using the PLT Web Server’s serializable continuations it roughly corresponds to a weak box and a weak hash table (that holds its keys weakly) to give the box a serializable value as an identifier.

This programming pattern is a bit difficult to get right. So, a library that implements it is now provided with PLT Scheme: web-server/lang/soft.

Here’s a trivial example:

#lang web-server

(provide interface-version start)
(define interface-version 'stateless)

(define softie
  (soft-state
   (printf "Doing a long computation...~n")
   (sleep 1)))

(define (start req)
  (soft-state-ref softie)
  (printf "Done~n")
  (start
   (send/suspend
    (lambda (k-url)
      `(html (body (a ([href ,k-url]) "Done")))))))
more →

18 May 2009

Scheme Workshop: deadline NOT extended!

posted by John Clements

We’re holding the line on our submission deadline; it’s still June 5, so that gives you about three weeks to write something awesome.

Re-posting the entire CfP on a blog seems a bit tacky, so instead I’ll just post the link:

http://blog.plt-scheme.org/2009/01/cfp-scheme-workshop–2009.html

We look forward to your submissions!

more →

06 May 2009

What is send/suspend?

posted by Jay McCarthy

I often ponder what send/suspend really is. It is a lot like call/cc, but has the curious property that the continuation escapes in a single way and is only called in a particular context. I often wonder if there is something weaker than call/cc that implements send/suspend.

Today I wrote a little dispatcher that uses threads to implement send/suspend. In this implementation, _send_ing truly _suspend_s the computation.

Here’s the code: http://www.copypastecode.com/codes/view/5003

The trick is to have channels for communicating responses and requests. When you run this example, you should be able to add two numbers. But, in contrast to the normal send/suspend, all the URLs are one-shots, because once the computation is resumed, it moves forward… it is never saved.

This implementation technique also precludes clever implementations of send/suspend/dispatch, like:

(define (send/suspend/dispatch mk-page)
  (let/cc k0
    (send/back
     (mk-page
      (lambda (handler)
        (let/ec k1 
          (k0 (handler (send/suspend k1)))))))))
more →

29 Mar 2009

the DrScheme repl isn’t the one in Emacs

posted by matthias

Dear old Lisper,

You have found drscheme and it is almost like your old Lisp machine. It is easy to program in it, it has things that nobody else has, and we all love parentheses. But after some initial enthusiasm you are wondering why in the world, we decided not to provide commands for sending individual definitions and expressions from the Definitions window to the Interactions window, aka, REPL.

It wasn’t an accident. It was by design after some difficult experiences. I am personally a product of the Emacs world that you are describing below, and my advisor Dan Friedman was called the “Lispman” on his door sign at Indiana.

When I first discovered the idea of sending individual expressions and definitions from a buffer to a repl, it was a near-religious revelation to me. I wanted everyone to know this trick and use it. When I started teaching the freshman course at Rice, I told our chairman so and he asked “why”. I was shocked, awed, and I failed to explain to him how it mattered. He was a mathematician and I wrote it off. They don’t know.

Then I started watching my sophomores and juniors at Rice in lab. Now that was a true disappointment. Few if any used this trick and when they did, they more often tripped up and got the repl into a state where they didn’t know what was going on.

In the mid 90s, I wrote some more Little books with Dan, and boy, time and again, I watched him stumble across the state of the repl. I even watched him re-start the repl and load the whole buffer more often than not.

Why? In the presence of macros and higher-order functions and other beasts, it is difficult for masters of the universe with 30 years of experience to keep track of things. What do you think students with 10 or 20 days worth of experience will do? Is it really such a deep principle of computing to create the objects incrementally in the repl as opposed to thinking systematically through the design of a program?

I decided not and asked Robby to make DrScheme’s repl transparent. That is, it re-starts the repl and re-loads the buffer every time. I consider this behavior a suitable compromise: have a repl but don’t confuse yourself with send-defs and send-exprs. This is especially true in an age when sending an entire buffer takes as much time as sending an individual expression or definition. Soon we’ll get “compilation behind your back” so that only the current buffer is re-interpreted. It’ll start things even faster.

Even though I had used the incremental mode for more than a decade when I switched from Emacs to DrScheme in 1998, I have hardly ever looked back. I miss a few other things but the incremental repl is one of those rituals old Lispers acquired and never questioned … but it isn’t fundamental and critical to anything. (Note there is no qualifying clauses, no when no if no but. I really mean this last sentence the way I spelled it.)

more →

22 Mar 2009

PLT Scheme v4.1.5

posted by Eli Barzilay

PLT Scheme version 4.1.5 is now available from http://plt-scheme.org/

  • Web Server:
    • new URL-based dispatching library web-server/dispatch,
    • customizable continuation serialization policies for the stateless web language web-server/stuffers,
    • abstraction of serve/servlet to build simpler dispatchers web-server/servlet-env,
    • HTTP Digest authentication support web-server/http/digest-auth,
    • built-in cookie support in web-server/http/cookie and web-server/http/cookie-parse,
    • highlighting and pretty-printing of errors in Xexpr constructions,
    • load control dispatcher for limit concurrent sessions web-server/dispatchers/limit.
  • Scribble:
    • Literate programming is now available using the new scribble/lp language.
    • A new at-exp language makes it convenient to use the scribble reader’s @-expressions for general code.
    • The scribble/text preprocessor language has been extended to deal with indentation and other formatting issues.
    • The “scribble” command-line tool accepts a --pdf flag to render PDFs (via pdflatex).
  • DrScheme now provides feedback when PLaneT downloads and installs new packages.

  • Units & Contracts:
    • Elements of unit signatures can now be associated with contracts via the contracted signature form.
    • A contract combinator for units, unit/c, has been added.
    • The new with-contract form provides a nestable submodule contract boundary, protecting a group of definitions from the surrounding code with contracts.
    • The define/contract form has been reworked and new define forms have been added: define-struct/contract and define-unit/contract.
  • Language levels and teachpacks from the DeinProgramm project for the German textbook “Die Macht der Abstraktion” by Herbert Klaeren and Michael Sperber have been added.

  • Misc:
    • Typed Scheme now comes with several more pre-wrapped libraries, found in the typed collection.
    • The xml and html collections are now contracted.
    • Binding parsing in net/cgi now interacts with net/uri-codec’s configuration parameters.
    • DrScheme captures logging output.
    • Check syntax: it is now possible to tack arrows crossing the currently selected text.
    • New bitwise-bit-field function.
  • The usual pile of bugfixes. (Notable: scheme/package works, deflate compression fixed, DrScheme language dialog issue resolved, match fixes, Windows networking, and much more.)

[Note that mirror sites can take a while to catch up with the new downloads.]

Feedback Welcome.

more →

12 Mar 2009

Maintaining self-references in Planet packages

posted by Carl Eastlund

PLaneT packages may refer to themselves (i.e. include module paths referring to some part of the same package) for a number of reasons. One module may require another. Scribble documentation traces for-label imports to construct hypertext links. DrScheme language levels may provide a module path for an initial namespace.

In each of these cases, we want the module path to refer to the same version of the same package that it occurs in. On the other hand, we do not want to have to manually search and replace the version number every time we update. Before I solved this problem I would often release some new version x.0 of a package, only to find some lingering dependency on y.0 that my search/replace had not caught. Of course, then I had to go back and replace all occurrences of both x.0 and y.0 with x.1 and release again. To avoid this headache, we need a way to express self-referential module paths with precise, implicit version numbers.

The built-in module paths don’t quite support this. The relevant forms are PLaneT paths with version numbers, PLaneT paths without version numbers, and relative paths:

(planet my/package:1:0/dir/file)
(planet my/package/dir/file)
"../dir/file.ss"

PLaneT paths with version numbers suffer from the search and replace problem: they become obsolete, and must be changed with every new release.

PLaneT paths without version numbers “upgrade” with a new release: they automatically refer to the latest version of a package. Unfortunately, this means they aren’t really “self”-references. As soon as version 2.0 is released, every version-free reference to the package refers to 2.0. Even the references in version 1.0 get implicitly updated, and become forward references rather than self-references.

Relative paths are precise, in that they always refer to the same version of the same package. However, because they implicitly refer to the directory containing the source code, they are only valid within a single file. They cannot be reliably passed to DrScheme for a language level namespace, traced for documentation links by Scribble, or used by other such external tools.

None of these options provides precise, stable, externally comprehensible, self-referential module paths.

To fill this need, I have released (planet cce/scheme:4:1/planet). This module provides PLaneT package authors with several macros that construct references to the current package in require imports, Scribble documentation, and dynamic values. The self-referential modules paths are constructed automatically at compile time based on the source location of the macro use and the local PLaneT package database. Their expanded form always includes an explicit package name and version number (both major and minor). Here I will summarize their use, with (planet my/package:1:0/dir/file) as a running example. For full details, see the online documentation or install the package.

To import a module from within a PLaneT package, use the this-package-in require transformer. To re-export bindings from a module imported this way, use the this-package-out provide transformer, or use require/provide/this-package in place of both.

For example, you might want to import and re-export bindings from dir/file:

(require (planet my/package:1:0/dir/file))
(provide (all-from-out (planet my/package:1:0/dir/file)))

You can leave out the package name and version number, thus making the code invariant across upgrades, by writing:

(require (this-package-in dir/file))
(provide (this-package-out dir/file))

Or, you can further simplify it:

(require/provide/this-package dir/file)

All three of the above are equivalent (in version 1.0).

In Scribble documentation, a module often refers to itself via defmodule, declare-exporting, or schememodname. I provide the extensions defmodule/this-package, declare-exporting/this-package, and schememodname/this-package, respectively. These macros allow the user to supply a path such as dir/file, or to omit one to refer to the package as a whole (or its main module). In positions where the original macros allow a sequence of module paths, these forms allow two sequences, one for self-referential module paths and one for other paths.

To document an entire module, one might first write:

(defmodule (planet my/package:1:0))

The automatic self-reference version is simply:

(defmodule/this-package)

In more complicated cases, one might document a sub-part of a package or present bindings from multiple sources:

(defmodule (planet my/package:1:0/dir/file)
  #:use-sources
  [(planet my/package:1:0/private/impl) somewhere/else])

These self-references can still be automated:

(defmodule/this-package dir/file
  #:use-sources
  [private/impl]
  [somewhere/else])

Finally, I provide this-package-version-symbol for constructing PLaneT package symbols as runtime values. This macro is analogous to this-package-version from the planet/util collection, but it constructs a symbol rather than an s-expression. You can use this symbol to construct a module path for a DrScheme language level, or escape it with unsyntax in Scribble’s schemeblock typesetting to create self-referential example code.

This list of utilities may not be complete. Users may need to write new macros for self-referential PLaneT packages. To that end, (planet cce/scheme:4:1/syntax) provides syntax-source-planet-package. This function is analogous to this-package-version, but operates on syntax objects and is designed to be used in macro transformers. There are also -owner, -name, -major, -minor, and -symbol versions following the same analogy.

I find these tools useful for maintaining my PLaneT packages, and I hope other authors will too. If you do give them a try, please send feedback on what does or doesn’t work, or what might be improved. I would eventually like to add a refined version to the PLT Scheme collections once we get enough experience to know that these tools are fairly complete and usable.

more →

24 Feb 2009

Call for Participation: Writing Typed Scheme wrapper modules

posted by Sam Tobin-Hochstadt

Typed Scheme is a language for writing PLT Scheme programs that are statically checked for type errors. Right now, Typed Scheme handles a large portion of the PLT Scheme language. However, to use Typed Scheme effectively, we need libraries that work with it. For this task, we’re looking for help.

We’d like volunteers for writing wrapper modules that adapt untyped libraries to Typed Scheme. This task is very easy for the smallest libraries, but can be much more complicated for larger, complex libraries.

There’s a preliminary guide for conversion here and a list of modules to adapt, and their current status is available here.

Questions about this project, and about developing with Typed Scheme in general, can be asked on [email protected] , and questions or comments can be sent directly to me.

We hope to continue making Typed Scheme into a useful tool for PLT Scheme programmers.

Thanks,

Sam, Stevie, and Matthias

more →

18 Feb 2009

Steering Scheme

posted by matthias

Election time is here again. A couple more days and the Scheme community will have a set of new steer-ers.

What should we want from a steering committee?

I have argued at this place before that good language design needs a feedback loop. Language designers write down specs; language implementers translate those specs into compilers and interpreters; programmers use these implementations to produce useful software. The loop comes in when implementers inform designers of flaws, inconsistencies, mistakes, errors, and other internal consistency problems in the specs. This is clearly happening with R6RS, and it is good. Implementers are a biased bunch, however. After all, they work on just one kind of program, and in a highly specialized domain that has been mined for a long time. How can you trust them? [*]

The loop becomes truly useful when people write large software systems (not just compilers, because they really are special cases!) and find that the language fails them in some way. Such failures can come in a number of flavors. For a document such as R6RS, we should hope that programmers can discover problems with porting systems that are apparently due to ambiguities, flaws, mistakes, roaches in the actual document (as opposed to a specific implementation).

So what does this have to do with the steering committee?

The last thing we want from a steering committee is a radical commitment to change (whatever it may be); a prejudice concerning R6RS; a closed mind about the size of “Scheme” (it’s too large, it’s too small); a willingness to steer without making observations. A steering committee of overbearing curmudgeons is not what we want.

What we do want is a committee that is willing to figure out how the listening is going to happen; how we can possibly finance a systematic way of listening (writing NSF grants, anyone?); how the feedback is best channeled into language design.

Let’s hope we get such a steering committee. The Scheme community deserves it.

[*] No I am not naive enough to think that language implementers don’t design languages, and that implementers don’t program systems other than implementations. I am just skeptical that it is easy for them to separate out their various roles in an objective manner, even if many of them are able to think at several different levels about programs.

more →

14 Feb 2009

New Contract-Related Features

posted by Stevie

In SVN I’ve added three new major features that involve contracts. One allows for more fine-grained control of contracts, and the other two allow for the use of contracts with signatures and units.

Contract Regions

Contract regions allow the programmer to protect a region of code with a contract boundary. In addition to the wrapped code, the programmer also provides a name for the region which is used in blame situations and a list of exported variables which can either be protected with contracts or unprotected. The region provides a true contract boundary, in that uses of contracted exports within the region are unprotected. Contract regions are specified with the with-contract form. The following contract region defines two mutually recursive functions:

(with-contract region1
 ([f (-> number? boolean?)]
  [g (-> number? boolean?)])
 (define (f n) (if (zero? n) #f (g (sub1 n))))
 (define (g n) (if (zero? n) #t (f (sub1 n)))))
 ```

The internal calls to `f` and `g` are uncontracted, but calls to `f`and `g` outside this region would be appropriately contracted.  First-order checks are performed at the region, so the
following region:

```racket
(with-contract region2
 ([n number?])
 (define n #t))
 ```

results in the following error:

```racket
(region region2) broke the contract number? on n; expected <number?>, given: #t

Notice that the blame not only gives the name of the region, but describes what type of contract boundary was involved.

For contracting a single definition, there is the define/contract form which has a similar syntax to define, except that it takes a contract before the body of the definition.

To compare the two forms, the following two definitions are equivalent:

(with-contract fact
 ([fact (-> number? number?)])
 (define (fact n)
   (if (zero? n) 1 (* n (fact (sub1 n))))))

(define/contract (fact n)
 (-> number? number?)
 (if (zero? n) 1 (* n (fact (sub1 n)))))

First order checks are similarly performed at the definition for define/contract, so

(define/contract (fact n)
 (-> number?)
 (if (zero? n) 1 (* n (fact (sub1 n)))))

results in

(function fact) broke the contract (-> number?) on fact; expected a procedure that accepts no arguments without any keywords, given: #<procedure:fact>

Signature Contracts

In addition to contract regions, units are also now contract boundaries. One way to use contracts with units is to add contracts to unit signatures via the contracted signature form.

(define-signature toy-factory^
 ((contracted
   [build-toys (-> integer? (listof toy?))]
   [repaint    (-> toy? symbol? toy?)]
   [toy?       (-> any/c boolean?)]
   [toy-color  (-> toy? symbol?)])))

Notice that contracts in a signature can use variables listed in the signature.Now if we take the following implementation of that signature:

(define-unit [email protected]
 (import)
 (export toy-factory^)

 (define-struct toy (color) #:transparent)

 (define (build-toys n)
   (for/list ([i (in-range n)])
     (make-toy 'blue)))

 (define (repaint t col)
   (make-toy col)))

We get the appropriate contract checks on those exports:

> (define-values/invoke-unit/infer [email protected])
> (build-toys 3)
(#(struct:toy blue) #(struct:toy blue) #(struct:toy blue))
> (build-toys #f)
top-level broke the contract (-> integer? (listof toy?))
 on build-toys; expected >, given: #f

As before, uses of contracted exports inside the unit are not checked.

Since units are contract boundaries, they can be blamed appropriately. Take the following definitions:

(define-unit [email protected]
 (import toy-factory^)
 (export)
 (let ([toys (build-toys 3)])
   (repaint 3 'blue)))

(define-compound-unit/infer [email protected]
 (import) (export)
 (link [email protected] [email protected]))
When we invoke the combined unit:> (define-values/invoke-unit/infer [email protected])
(unit [email protected]) broke the contract
 (-> toy? symbol? toy?)
on repaint; expected >, given: 3

Unit Contracts

However, we may not always be able to add contracts to signatures. For example, there are many already-existing signatures in PLT Scheme that one may want to implement, or a programmer may want to take a unit value and add contracts to it after the fact.

To do this, there is the unit/c contract combinator. It takes a list of imports and exports, where each signature is paired with a list of variables and their contracts for each signature. So if we had the uncontracted version of the toy-factory^ signature:

(define-signature toy-factory^
 (build-toys repaint toy? toy-color))

the following contracts would be appropriate for a unit that imports nothing and exports that signature:

(unit/c (import) (export))
(unit/c (import) (export toy-factory^))
(unit/c
 (import)
 (export (toy-factory^
          [toy-color (-> toy? symbol?)])))
(unit/c
 (import)
 (export (toy-factory^
          [build-toys (-> integer? (listof toy?))]
          [repaint    (-> toy? symbol? toy?)]
          [toy?       (-> any/c boolean?)]
          [toy-color  (-> toy? symbol?)])))

Unit contracts can contain a superset of the import signatures and a subset of the export signatures for a given unit value. Also, variables that are not listed for a given signature are left alone when the contracts are being added.

Since the results of applying unit/c is a new unit, then adding a contract can cause link inference to fail. For example, if we change the definition of [email protected] above to

(define/contract [email protected]
 (unit/c
  (import)
  (export (toy-factory^
           [build-toys (-> integer? (listof toy?))]
           [repaint    (-> toy? symbol? toy?)]
           [toy?       (-> any/c boolean?)]
           [toy-color  (-> toy? symbol?)])))
 (unit
   (import)
   (export toy-factory^)

   (define-struct toy (color) #:transparent)

   (define (build-toys n)
     (for/list ([i (in-range n)])
       (make-toy 'blue)))

   (define (repaint t col)
     (make-toy col))))

Then when we try to combine it with the [email protected] unit, we get:

define-compound-unit/infer: not a unit definition in: [email protected]

One way to solve this is to use define-unit-binding to set up the static information for the new contracted value. Another possibility for unit definitions is to use define-unit/contract:

(define-unit/contract [email protected]
 (import)
 (export (toy-factory^
          [build-toys (-> integer? (listof toy?))]
          [repaint    (-> toy? symbol? toy?)]
          [toy?       (-> any/c boolean?)]
          [toy-color  (-> toy? symbol?)]))

 (define-struct toy (color) #:transparent)

 (define (build-toys n)
   (for/list ([i (in-range n)])
     (make-toy 'blue)))

 (define (repaint t col)
   (make-toy col)))

More about these features can be found in the Reference, and a short section about signature and unit contracts has been added to the Guide.

more →

29 Jan 2009

CfP: Scheme Workshop 2009!

posted by John Clements

SCHEME AND FUNCTIONAL PROGRAMMING WORKSHOP 2009: Cambridge, Massachusetts: August 22, 2009: call for papers: http://www.schemeworkshop.org/2009/:

The Scheme and Functional Programming Workshop showcases research and experience related to Scheme, and more broadly to all aspects of functional programming.

Areas of interest include:

  • Language Design, Type Systems, Theory

  • Program Development Environments, Education

  • Agile Methodologies, Lightweight Software Engineering

  • Applications, Implementation, and Experience

  • SRFIs!

In addition to technical papers on matters of programming-language research, we encourage submissions that present experience or innovation with a particular project. The key criterion for any paper—technical or not—is that it makes a contribution from which other practitioners can benefit.

Dates::

Dates are firm, and will not be extended. Please plan accordingly.

  • Submission Deadline: June 5, 2009 (FIRM)

  • Author Notification: June 26, 2009

  • Final Papers Due: July 24, 2009

  • Workshop: August 22, 2009

Program Committee::

  • John Clements, Cal Poly State University (organizer & chair)

  • Dominique Boucher, Nu Echo

  • Abdulaziz Ghuloum, Indiana University

  • David Herman, Northeastern University

  • Shriram Krishnamurthi, Brown University

  • Matthew Might, University of Utah

  • David Van Horn, Northeastern University

Publication Policy::

Submitted papers must have content that has not previously been published in other conferences or refereed venues, and simultaneous submission to other conferences or refereed venues is unacceptable.

Publication of a paper at this workshop is not intended to replace conference or journal publication, and does not preclude re-publication of a more complete or finished version of the paper at some later conference or in a journal.

Submission Instructions::

Your submissions should be no longer than 12 pages, including bibliography and appendices. Papers may be shorter than this limit, and the Program Committee encourages authors to submit shorter papers where appropriate.

The conference web page (URL above) contains detailed formatting instructions and LaTeX support files.

Submit your papers using the Continue 2.0 submission server, at the URL:

http://continue2.cs.brown.edu/scheme2009/

We look forward to reading your papers!

more →

Made with Frog, a static-blog generator written in Racket.
Source code for this blog.