When I first looked at the
Arc Challenge code my reaction, like that of many people, was WTH? Here's the code:
(defop said req
(aform [w/link (pr "you said: " (arg _ "foo"))
(pr "click here")]
(input "foo")
(submit)))
Within the context of the Arc web/app server this creates a page called
/said which has a form on it:
<form method=post action="x">
<input type=hidden name="fnid" value="JtCw8ju328">
<input type=text name="foo" value="" size=10>
<input type=submit value="submit">
</form>
That form accepts a single parameter called
foo and redirects to
/x.
When clicking
submit the user is taken to a page with a single link on it:
<a href="x?fnid=bHJpJ5G1DH">click here</a>
Following that link brings up a page showing what you typed in the first; here's the output when I typed
hello in the form:
you said: hello
So, how does that work?
Firstly, the
defop defines an 'operation' (which is just a page within the web server). In this case the page is called
said and hence is bound to
/said. There's a single argument, called
req, which will contain the HTTP request when
said is called by the server.
When
said is called it uses
aform to create an HTML form. To see this more clearly I've removed the clever part (and replaced it with X):
(aform X
(input "foo")
(submit))
So
aform creates a form with an simple HTML input with the name
foo and a submit button. The clever bit is what happens when the form is submitted.
By default the form submits to the page
/x. This is hard-coded in the source of the Arc server. It makes use of a neat feature of the Arc server: fnids. When the form was generated a hidden field was inserted with a unique 'function id' (the
fnid). This fnid is used by the
/x URL to lookup a function to call when
/x is activated. (Note this example uses URLs/hidden form fields for the fnid, there's no reason why it couldn't be stored in a cookie).
The function called is actually the first argument to
aform which has been stored away to be called when necessary. Here's the function definition:
[w/link (pr "you said: " (arg _ "foo")) (pr "click here")]
[ ... _ ... ] is special Arc syntax for a function with a single argument called
_. So the first argument to
aform is a function definition, and that function is assigned a unique
fnid and that
fnid can be used to lookup that function and call it. The single argument consists of the HTTP request used to activate the function.
The
w/link macro creates a page consisting of the words
click here linked to another page. The link is, once again, done using a function and fnid. The function called when the link is clicked is:
(pr "you said: " (arg _ "foo"))
w/link's first argument is an expression that will be evaluated within the context of a function (which is entirely hidden inside the server) and used to output the page. It retrieves the
foo argument from the HTTP request at the time of the initial POST.
What's neat here is the mapping between functions and fnids so that pages are just functions and the lookup of the right page to go to is handled automatically.