Web authoring with higher-order functions

Kurt Nørmark ©    normark@cs.auc.dk    Department of Computer Science, Aalborg University    

Abstract.

In the earlier parts of this tutorial we have described the fundamental aspects of the HTML mirror in Scheme. We will now take a look at a more advanced aspect, namely authoring with use of higher-order functions. This particular aspect pays tribute to the fact that in LAML, HTML is available as Scheme functions (not macros or just list structures).

The topic of 'higher-order functions' is a key area in functional programming. Therefore we find it important to cover higher-order functions in this tutorial. It should be noticed that LAML has been defined with particular emphasis on 'a good fit' between higher-order functions that work on lists, and the HTML/XML mirror functions.

 

  Higher-order functions curlev-sec
1  Summing up
In this section we will briefly summarize our current knowledge about the HTML mirror functions in Scheme.
1.1  Summing up
 

Summing up   curlev
1.1  Summing up

Until now in this tutorial we have seen how to use the HTML mirror functions to produce relatively straightforward web pages. We have also seen how to make pages which includes pieces of Scheme programs, such as the factorial function, or functions for managing lists of bookmarks. In addition we have studied the details of HTML mirror functions, in particular the interpretation of different kinds of parameters of these.

 

 

 Summing up Element Modification hio-sec
2  Higher-order functions
We start with a very brief account on higher-order functions. It is really just a few words with a reference to a LAML related teaching material, in which there are many more details.
2.1  Higher-order functions
 

Higher-order functions   hio
2.1  Higher-order functions

Higher-order functions accept functions as parameters. In addition, a higher-order function can return a function as the result. Finally, functions can be organized in data structures, such as in lists (lists of functions).

I will not here go deeper the general subject of higher-order functions here. I have written a teaching material about functional programming in Scheme. Please take a look at the chapters that cover higher-order functions. I will recommend that you read the thematic view of this material, chapter 13 - 17. The direct link to the thematic view of chapter 13 is here.

 

 

 Higher-order functions Using higher-order list functions element-mod-sec
3  Element Modification
Using element modification it is possible to generate specialized versions of a particular element, which binds attributes or part of the content to particular values
3.1  Element Modification
 

Element Modification   element-mod
3.1  Element Modification

The function xml-modify-element allows us to bind attributes to constant values in a mirror function, before the mirror function is applied. To illustrate this idea, take a look at element-mod which uses the XHTML1.0 transitional mirror. The resulting page is also available.

The name ol-alpha is bound to a modified version of the HTML mirror function ol, in which the type attribute is pre-bound to the value "A". By using ol-alpha you will 'automatically' add the type attribute to the instance of ol with the value "A".

The function a-target is defined to be a modification of the a HTML mirror function, in which the target attribute is pre-bound to the parameter t of a-target.

ol-roman-3 is a modified version of ol, in which we apply the attributes in ol-attributes. Notice the way we can pass a list (more precisely, a property list) of attributes to xml-modify-element.

The function named sli is a modified version of the mirror of the li element, in which we append the value of the (p) expression. Thus, we see that we can use xml-modify-element for 'modification' of the element contents as well as the attributes of the element.

When we use xml-modify-element to 'modify' the element contents, it is relevant to have a version wich prepends the contents instead of appending it. The function xml-modify-element-prepend does that. See !!-li for an example. Again, it is instructive to see the effect on the generated HTML page.

 

 

 Element Modification XML-in-LAML parameterization and abstraction hio-list-sec
4  Using higher-order list functions
In Lisp and Scheme, structured data is typically organized in list structures. In this section we will illustrate how to make use of mapping and filtering together with the HTML mirror functions.
4.1  Ordered and unordered lists
4.2  Tables
4.3  More Tables
 

Using higher-order list functions  Tables ol-ul
4.1  Ordered and unordered lists

It may be tempting to pass a list of items to the ol or ul mirror functions. This can be done as in the second ul clause of the lists document. However, it is hardly attractive to use this form compared to the first one, in which we embed li elements in the ul form.

Things is a little different if we already have our data in a list, such as my-list. In that case it more reasonable to use the third form in lists, namely this one:

  (ul (li-map my-list))

Recall that li-map is defined explicitly in the document, by use of a curry-generalized map.

Let us also illustrate the use of filtering. In the list my-second-list some of the items are marked with a star. We want to eliminate the unstared items in the rendered list. The fourth example shows how it can be done by use of filtering.

The resulting web page is available such that you can see the actual presentation of the lists from this section.

 

 

Using higher-order list functions Ordered and unordered lists More Tables tables
4.2  Tables

Tables can in a natural way be organized as lists of rows or lists of columns. In HTML, a table is basically a list of rows. Using Scheme, it is attractive to represent tables as lists of lists (list of rows, where a row is a list of elements).

As the first example, let us look at the factorial table example from the getting started section.The original example is shown in fac-2, which already makes use of mapping.

We have refined the factorial example to that of fac-3. Let us go over the details.

We first redefine map to be curry generalized. The function curry-generalized makes it possible to use map in a curried way. Thus,

 (map td)

returns a td mapper. Without curry generalization, (map td) would cause an error, because map requires at least two parameters: a mapping function and a list.

After map and fac comes a specialization of the table mirror function table-with-border with the border bound to 1. The function make-n-fac-n makes a list of numbers, say (n (fac n)) with n running from 1 to an upper limit h.

Finally we see the write-html clause, in which we meet the crucial expression

  (map 
    (compose tr (map (compose td as-string)))
    (make-n-fac-n 55))

The inner composition aggregates the td mirror function with the string converter function as-string. The outer composition aggregates the tr mirror function and the 'extended td mapper'. This composed function is mapped on a list like

  ((1 1)
   (2 2)
   (3 6)
   (4 24)
   ...
  )

as formed by make-n-fac-n. The resulting page is similar to the pages from the earlier chapter.

 

 

Using higher-order list functions Tables  more-tables
4.3  More Tables

We will now take a look at another and more advanced table example, which can be seen here. The source document is more-tables.

We define sample-table as a list of rows. In write-html-clause we first render the table in a straightforward way.

Next we show a rendering of the table in which we compose the function switch with tr and (map td). The function switch switches the first and second element in a list. When applied via map on rows in a table, the effect is a switching the first and second column. See again the resulting HTML document for the effect of applying switch.

The final table made in the example is interesting because we apply an attribute in one of the table cells - the upper left one. We use the cell function, which is just an alias of list. In addition, we colorize all numeric cells (the third column) with a grey background. This is done by grey-numeric. Please study both the result and the generating expression carefully.

 

 

 Using higher-order list functions Postscript par-sec
5  XML-in-LAML parameterization and abstraction
In this section we will discuss how to generate functions which obey the XML-in-LAML mirror function parameter passing rules. In the first variant, xml-in-laml-parametrization, we provide for a XML-in-LAML parametrization of an existing XML related function which uses straightforward positional parameters. In the second variant, xml-in-laml-abstraciton, we provide for abstractions on top of existing mirror functions.
5.1  XML-in-LAML parametrizations
5.2  XML-in-LAML abstractions
5.3  More XML-in-LAML abstractions
 

XML-in-LAML parameterization and abstraction  XML-in-LAML abstractions par
5.1  XML-in-LAML parametrizations

Now take a look at color-frames, more specifically at the write-html clause at write-html-clause-color-frame. We will start by using the XHTML convenience function color-frame-width (A link to a program source marker in write-html-clause-color-frame) to produce a color framed text, see here (original color frame).

We wish to use the XML-in-LAML parameter passing techniques for color-frame-width. That is, instead of the call

  (color-frame-width "Some text" red 100)

we prefer the following call

  (new-color-frame-width "Some text" 'color red 'width "100")

or equivalently for instance

  (new-color-frame-width 'width "100" 'color red  "Some text" )

or perhaps something like

  (new-color-frame-width "Some" 'width "100" 'color red  "text" )

which more profoundly uses the merits of the mirror rules. In write-html-clause-color-frame we focus on the call of new-color-frame-width at A link to a program source marker in write-html-clause-color-frame.

Let us now develop new-color-frame-width using the XML-in-LAML library higher-order function xml-in-laml-parametrization.When we use xml-in-laml-parametrization we can - most importantly - carry out a transformation from the new XML-in-LAML parameter format to the old one. The local function med (for mediator) does that, just by accessing the attributes property list. The local val! procedure validates the new parameter list, using the generally useful functions color-string? and hex-numeric-string?. As prescribed in xml-in-laml-parametrization errors are reported using the function xml-check-error.

Notice the use of get-prop and defaulted-get-prop, which both work on property lists. These functions correspond to the functions get and defaulted-get, which work on association lists. All four functions are located in the library of generally useful Scheme functions.

Again, take a look at the resulting HTML page to assure yourself, that it works (see new color frame).

 

 

XML-in-LAML parameterization and abstraction XML-in-LAML parametrizations More XML-in-LAML abstractions abstractions
5.2  XML-in-LAML abstractions

It is often convenient to introduce ad hoc abstractions, when you write a new web document. This is very easy in Scheme, because we can just write a simple function.

Things become a little more difficult if we want the new abstraction to obey the mirror function rules of LAML - see the section about HTML mirror rules. We will now see how to use xml-in-laml-abstraction in such situations. We switch our interest to a new example web document, li-extensions.

The functions spacy-li and question-li are both generated by xml-in-laml-abstraction. The function xml-in-laml-abstraction is similar to xml-in-laml-parametrization. But the function xml-in-laml-abstraction is intended to carry out abtractions on top of an XML-in-LAML mirror function. In other words, the lambda expressions passed to xml-in-laml-abstraction should ultimately pass the content to a 'terminal' XML-in-LAML mirror function.

spacy-li is a variation of the HTML mirror function li, which embeds the list item in a p element (presumably to make a little white space before the next list item). In write-html-clause-li we see an example use of spacy-li (A link to a program source marker in write-html-clause-li). In spacy-li notice that we pass the attribute property list to the li element and the contents to the nested p element. Also notice the general and characteristic 'LAML parameter profile' is now made available to the spacy-li function.

The funciton question-li introduces an ad hoc abstraction, which takes a keywords attribute. We use various HTML elements, such as p, b, br, and font to render a question-li Notice that we use spacy-li in the body of question-li. Notice again the versatility of the actual parameters in write-html-clause-li (A link to a program source marker in write-html-clause-li).

The question-li function passes an attribute validator, generated by required-implied-attributes. The higher-order function required-implied-attributes is convenient for creation of functions that check attribtutes. Its first parameter is the list of required attributes, and the second parameter is the list of other possible attributes (called implied attributes in a DTD). - Notice that x attribute passed to the second and third list is not valid according to the generated checking procedure. Try process li-extensions to see the effect.

The HTML page generated by li-extensions is here.

 

 

XML-in-LAML parameterization and abstraction XML-in-LAML abstractions  more-astractions
5.3  More XML-in-LAML abstractions

We will show yet another example of the use of xml-in-laml-abstraction in the document more-li-extensions. The generated HTML document can be seen here. The example is made to illustrate the full generality and power of xml-in-laml-abstraction. Notice, however, that we still recommend the use of the XML in LAML framework, instead of programming several XML in LAML abstractions.

We program an abstraction question-item with the attributes exercise and eref. A question-item can contain a keywords clause (plural) which, in turn, can contain a number of keyword clauses. In write-html-clause-more-li we see a couple of examples (A link to a program source marker in write-html-clause-more-li A link to a program source marker in write-html-clause-more-li).

Both keywords and keyword return AST's in a designated adhoc language. The AST constructor make-ast is used for the construction. The second lambda expression parameters of xml-in-laml-abstraction of keywords (A link to a program source marker in keywords) and keyword (A link to a program source marker in keyword) check the validity of the new elements. In question-item we use traverse-and-collect-first-from-ast and traverse-and-collect-all-from-ast to decompose the constructed AST. The pieces are put together at A link to a program source marker in question-item.

Again - this example is probably too complex relative to the task at hand. But it shows that XML-in-LAML abstractions, made by xml-in-laml-abstraction, can play together in the way it is intended.

 

 

 XML-in-LAML parameterization and abstraction  ps
6  Postscript
For additional information about the use of higher-order function for web authoring you can consult lecture 4 of the teaching material Functional Programming in Scheme - a web-oriented approach.