Thursday, June 23, 2022

Distinguishing features of Clojure

By now it should be readily apparent that Clojure is not like most programming languages. In this post I will attempt to pin down what I think makes Clojure so different, focusing more on the philosophical aspects rather then the implementation details. Clojure is distinguished from most other languages from how tightly it is integrated into the JVM, and by its excellent Java interop - but this is an implementation detail and not the philosophical core of the language.

Clojure is sometimes called a functional language, but it is not too particular about it. Functional programming is just one paradigm under the larger multi-paradigm umbrella. The emphasis on functional programming in particular gets to something deeper about the language, which is its emphasis on concurrency. In Clojure you can have side effects, but they ought to be concurrent.

Code as data

Clojure is a Lisp which means it treats code as data. In the customary manner of Lisp dialects, code is represented by collection data structures. Consequently, like most Lisp dialects the language is optimized around the manipulation of collection data structures like lists and sets. This combination of an emphasis on collection processing and code as data enables the Clojure macro system.

It should be mentioned that code as data is a philosophy rather then a specification. Like so many things it is a work in progress. Clojure did well to extend the simple S-expressions of earlier Lisp dialects with new syntax to create the extensible data notation. As a work in progress, you could further extend the extensible data notation, to add improvements to it. Future language designers may then improve it further.

Separating identity and values

The second most important aspect of Clojure is its emphasis on concurrency and immutability. Clojure has a state model that separates values from identities. Values are immutable but identities are associated with a series of values over time. Clojure doesn't prevent side effects, but it does say that you ought to log them to model changes over time. This enables STM concurrency.

Most of Clojure's constructs: its persistent data structures, its very strong emphasis on immutability and explicit modeling of state, are explained by the overarching goal of supporting concurrency. Immutability aids concurrency because immutable values can be safely shared between threads. Clojure doesn't eschew side effects, but it does emphasize that they ought to be concurrent.

Clojure certainly wouldn't appear in the shape it does now if it was created for any other purpose then its support for concurrency. If for example Clojure was designed with functional programming as an end in itself, it might have been a purely functional language. Instead, it was designed with concurrency in mind, so it doesn't appear like that. Functional programming is a means to an end. It is the currently acceptable means of implementing Clojure's goals of concurrency and explicit progression of time constructs.

Clojure's role in history is that it is a concurrent homoiconic language. There is nothing else in existence like it. It represents a truly unique programming philosophy. I think any other property of the language could be changed if it respected this core philosophy. The properties of being dynamic, functional, hosted, etc are more like implementation details then distinguishing characteristics of the language.

After all, Clojure is nothing like almost any dynamic language you have heard of. Dynamic languages almost never model state like Clojure does. Besides, Clojure developers make frequent use of type hints so that it can often appear like a statically typed language anyways. The typing discipline, the use of type hints, etc is just an implementation detail like any other. Hosting on the JVM is the logical thing to do when implementing a programming language.

These are all implementation details. Even the use of functional programming is mainly because it is more convenient when dealing with state management and concurrency, but as always functional programming must be part of a larger multi-paradigm umbrella. So functional programming is just another implementation detail. The main point is the code is data philosophy and the explicit modeling of time.

Wednesday, June 22, 2022

State management and user interface design

In this post, I will address Clojure's management of state. The importance of persistent data structures, state models, temporal databases, etc will be considered in both the fields of human-computer interaction and concurrency.

Clojure's handling of state

Clojure handles state differently from most other programming languages. Clojure divides logical entities into two types, values and identities.
  • Values: immutable data
  • Identity: an entity associated with a series of values over time
Values do not have state and are therefore immutable. Identities have states, which are their values at certain points in time.

Principles of user interface design

The first principle of user interface design is to always respect a user's decisions. After the user does something, you should never open a modal dialog box saying "Are you sure?." Modal dialogs always take away attention from the user. At the same time, a user may actually change his mind or make a mistake, and need to go back.

The means of supporting this is universal undo. Every major graphical user interface application has some sort of undo functionality. Take web browsers as an example. The key feature of HTML is its support for hyperlinks, which let you browse from one web page to another. Browser's enable the handling of a user's browsing history with forwards and back buttons.

Another example is text editors. They always support undo/redo functionality so that as a user types he/she always has the option of going back to a previous time in his/her typing history. Paint programs, video editors, or basically anything else that supports changing an entity over time supports undo. Undo is already vital to a wide variety of graphical user interface applications.

The key to supporting undo is the temporal management of the state of an application over time. In order to support universal undo we need to move away from the naive view of state, and instead view it a series of values over time. A user may change his mind at any time, which necessitates that we need move the value of our identity back to what it was at an earlier point in time. Furthermore, state managament like this should always be the default in all kinds of graphical user interface applications.

Temporal databases

The implementation of changes in values over time can be provided by temporal databases. A temporal database is like an ordinary database, except it also records changes over time. This is like what we need for graphical user interface applications, as it can be used to model the change's in an application's state over a time provided by the user. These temporal databases will then be the means by which we implement undo.

Interactivity in general

We see that the reason we need to explicitly model state in human-computer interaction is that it involves two different entities interacting with one another. When a human and a computer come together, it necessitates the management of identity so that a common understanding of the state of a program can be reached. This is actually analogous to the situation with concurrency, which involves different processors interacting with one another.
  • Concurrency: the interaction of different processors with one another
  • User interface design: the interaction of humans and computers
The issues in concurrency are somewhat similar: we need to reach agreement about the changes in shared state over time. Clojure's state management mechanisms like software transactional memory will make this easier for you. Concurrency is much easier if you explicity manage identity and state, just like user interface design. The only time when the naive model of state is sufficient is when creating single core programs that don't interact with the user at all.

External links:
Values and Change: Clojure’s approach to Identity and State

Swing HTML gallery

Swing and HTML are alike in a number of ways. Both are used to create graphical programs. Swing is based upon the Java beans component model, whilst HTML is based upon standard markup. Java beans encapsulate Java objects that are like nodes in an XML document. This is formalized by the XMLEncoder class of Java SE. Java beans properties are like HTML attributes. Swing's pluggable look and feel is like CSS.

The two frameworks differ in their original purpose, however. HTML emerged to extend text documents with hyperlinks, while Swing from the start was created as a full fledged graphical application framework. HTML's strength is in its hyperlinks and in creating rich text documents, so it has its own role to play. With the Swing HTML technology of Java SE you can get the strengths and benefits of HTML in your Swing applications.

To add HTML to Swing applications simply create a JEditorPane and set it to uneditable. Then set its editor kit to a HTMLEditorKit from the Swing HTML package. Editor panes are mainly used to view HTML rather then interact with it. There are two exceptions though, as you can use Swing to listen for hyperlink events and form submit events. Otherwise, your interactive components should not be part of an editor pane. Ten simple examples will be provided to demonstrate the cool things you can do with HTML in Swing.

1. An unordered list

(def unordered-list
  [:html
   [:body
    [:ul
     [:li "This is " [:b "bold"] " text"]
     [:li "This is " [:i "italic"] " text"]
     [:li "This is " [:u "underlined"] " text"]
     [:li "This is " [:strike "striked"] " text"]
     [:li "This is a " [:sub "subscript"]]
     [:li "This is a " [:sup "superscript"]]
     [:li
      [:font {:size 9} "This is "]
      [:font {:color "#00FF00", :size 9} "green text"]]
     [:li
      [:font {:size 6} "This is "]
      [:font {:color "#FF0000", :size 6} "red text"]]
     [:li
      [:font {:size 3} "This is "]
      [:font {:color "#0000FF", :size 3} "blue text"]]]]])

An ordered list

(def ordered-list
  [:html
   [:body
    [:h2 "Java history"]
    [:ol
     [:li
      "Java 1.0"
      [:ul
       [:li "AWT"]
       [:li "Base"]]]
     [:li "Java 1.1"
      [:ul
       [:li "Java beans"]
       [:li "SQL"]
       [:li "RMI"]]]
     [:li "Java 1.2"
      [:ul
       [:li "Swing"]
       [:li "CORBA"]]]
     [:li "Java 1.3"
      [:ul
       [:li "Java sound"]
       [:li "JDNI"]]]]]])

A description list

(def description-list
  [:html
   [:body
    [:dl
     [:dt "AWT"]
     [:dd "The original Java GUI toolkit."]
     [:dt "Swing"]
     [:dd "A GUI framework with its own pluggable look and feel."]
     [:dt "JavaFX"]
     [:dd "A modern replacement for Swing."]]]])

Java

(def java-image
   [:html
    [:body
     [:img {:src "https://upload.wikimedia.org/wikipedia/en/thumb/3/30/Java_programming_language_logo.svg/262px-Java_programming_language_logo.svg.png"}]]])

Clojure

(def clojure-image
  [:html
   [:body
    [:img {:src "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5d/Clojure_logo.svg/240px-Clojure_logo.svg.png"}]]])

Code

(def hello-world
  [:html
   [:body
    [:h1 "JVM programming"]
    [:h2 "Java programming"]
    [:pre
 "class HelloWorld {
   public static void main(String[] args) {
     System.out.println(\"Hello world\");
   }
 }"]
    [:hr]
    [:h2 "Clojure programming"]
    [:pre
 "(prn \"Hello world\")"]]])

Blockquotes

(def quote-example
  [:html
   [:body
    [:h2 "Famous programming quotes"]
    "Alan Kay speaking on Lisp"
    [:blockquote "Lisp isn't a language, it's a building material"]
    "Rich Hickey on persistent data structures"
    [:blockquote "If you write a program that uses persistent data structures, you'll be able to sleep at night. You're gonna be happier. Your life is gonna be better."]]])

Swing HTML comparison

(def swing-html-comparison
  [:html
   [:body
    [:table
     [:tr
      [:td]
      [:th "Swing"]
      [:th "HTML"]]
     [:tr
      [:th "Component model"]
      [:td "Java beans"]
      [:td "Markup"]]
     [:tr
      [:th "Styling mechanism"]
      [:td "PLAF"]
      [:td "CSS"]]]]])

Buttons

(def html-buttons
  [:html
   [:body
    [:h1 "Buttons"]
    [:h2 "Ordinary buttons"]
    [:input {:type "submit" :value "Button"} ]
    [:br]
    [:br]
    [:h2 "Toggle buttons"]
    "Checkbox" [:input {:type "checkbox"}]
    [:br]
    [:br]
    [:h3 "GUI toolkit"]
    [:form
     "AWT"
     [:input {:type "radio"}]
     "Swing"
     [:input {:type "radio"}]]

    [:h3 "JSON library"]
    [:form
     "Jackson"
     [:input {:type "radio"}]
     "GSON"
     [:input {:type "radio"}]]]])

Forms

(def forms-example
  [:html
   [:body
    [:table
     [:tr
      [:td "Name: "]
      [:td
       [:input {:type "text"}]]]
     [:tr
      [:td "Password: "]
      [:td [:input {:type "password"}]]]
     [:tr
      [:td "Send to:"]
      [:td
       [:select
        [:option "Oracle"]
        [:option "Microsoft"]]]]]
    [:br ]
    "Message:"
    [:br ]
    [:textarea {:rows "6" :cols "25"}]]])
External links:
Swing HTML package

Saturday, June 18, 2022

A circle is the limit of polygons

As the number of sides in a polygon tends to infinity, that polygon gets closer and closer to a circle. Here is how you can demonstrate this geometric reality by video using Clojure:
(ns video.core
  (:import (java.io File)
           (org.jcodec.api.awt AWTSequenceEncoder)
           (java.awt.image BufferedImage)
           (java.awt Color Polygon Rectangle RenderingHints)))

(defn create-polygon
  [vertices offset rect]

  (let [step (/ (* 2 Math/PI)
                vertices)
        x (int-array vertices)
        y (int-array vertices)
        xradius (/ (.-width rect) 2)
        yradius (/ (.-height rect) 2)]
    (dotimes [i vertices]
      (let [current-x (+ (.-x rect) xradius (int (* (Math/cos (+ offset (* i step))) xradius)))
            current-y (+ (.-y rect) yradius (int (* (Math/sin (+ offset (* i step))) yradius)))]
        (aset x i current-x)
        (aset y i current-y)))
    (Polygon. x y vertices)))

(defn main
  []

  (let [file (File.
               (str
                 (System/getProperty "user.home")
                 "/Media/out.mp4"))
        encoder (AWTSequenceEncoder/createSequenceEncoder file 5)
        img (BufferedImage. 600 600 BufferedImage/TYPE_INT_RGB)
        g (.createGraphics img)]
    (.setRenderingHint g RenderingHints/KEY_ANTIALIASING RenderingHints/VALUE_ANTIALIAS_ON)

    (dotimes [i 80]
      (.setColor g Color/WHITE)
      (.fillRect g 0 0 600 600)

      (.setColor g Color/BLACK)
      (let [polygon (create-polygon (+ i 3) 0 (Rectangle. 2 2 596 596))]
        (doto g
          (.draw polygon)))

      (.encodeImage encoder img))

    (.finish encoder)))
Here is the resulting video, which visually demonstrates this tendency:

Friday, June 17, 2022

Creating videos with Clojure

After looking through the Java SE API we can safely say that it doesn't contain any support for creating videos. To do that we need an external library like JCodec. It has APIs for the two main Java client platforms: Java SE and Android. In order to demonstrate the building of videos in Clojure, I will be using the JCodec Java SE API, which allows us to make use of our existing Java 2D functions to easily create videos. By itself, the Java SE doesn't let us do that much so to do interesting things like creating videos we need to look to external APIs. JCodec is one such API that is readily available.
(ns video.core
  (:import (java.io File)
           (org.jcodec.api.awt AWTSequenceEncoder)
           (java.awt.image BufferedImage)
           (java.awt RenderingHints Color)))

(defn main
  []

  (let [file (File.
               (str
                 (System/getProperty "user.home")
                 "/Media/out.mp4"))
        encoder (AWTSequenceEncoder/createSequenceEncoder file 30)
        img (BufferedImage. 600 600 BufferedImage/TYPE_INT_RGB)
        g (.createGraphics img)]
    (.setRenderingHint g RenderingHints/KEY_ANTIALIASING RenderingHints/VALUE_ANTIALIAS_ON)

    (dotimes [i 300]
      (.setColor g Color/WHITE)
      (.fillRect g 0 0 600 600)

      (.setColor g Color/BLACK)
      (let [center 300
            size (* i 2)]
        (.drawOval g (- center (/ size 2)) (- center (/ size 2)) size size))

      (.encodeImage encoder img))

    (.finish encoder)))
This produces the following video:

Thursday, June 16, 2022

Java SE and Android comparison

The Java SE and Android APIs address different hardware concerns and so they need to be different from one another. Even so there is a lot of overlap in the base and XML APIs, just as there is quite a lot that is different between them. The diagram presented below can be used as a quick guide if you want to compare the two of them. There is a lot of overlap between Swing and the Android user interface libraries, but they are presented in a different form on Android which is more appropriate for mobile devices. Much like Swing, Android has support for graphics, accessibility, input methods, widgets, media, etc. Emphasized instead is the special hardware support of the Android API like the telephony API which certainly don't have counterparts in Java SE. In order to discover more of the technical details, consult the API documentation.

External links
Android API

Wednesday, June 15, 2022

Java mobile applications

Computer programs are determined by the hardware they are built with. If you are building a rich client application with the JVM then you are probably targeting two types of hardware (1) desktop hardware and (2) mobile and embedded hardware. Different types of hardware necessitate different types of software, and so lets explore these distinctions in more detail.

Size matters

When computers were first created they were the size of an entire room. There was a large period of computing history when there were no personal computers because they were too cumbersome, large, and didn't have any graphical user interface capabilities. A long standing trend in the history of computing has been that they have been getting smaller so they take up less space.

A phase transition in this continuous process occurred in the past decade and a half or so, when computers became so small they could fit in your hand. They even became smaller then your keyboards. This radical change in hardware necessitated a different user interface paradigm based upon technologies like touch and speech.

This produced the most significant change in human-computer interaction technology in the last decade and a half. Now graphical user interface applications (GUIs) need to made to adapt to either desktop devices or mobile devices. A lot is shared in common between the two kinds of devices, but other things like differences in input devices pose a challenge for graphical user interface designers.

Every single GUI application has to ask itself it is targeting a mobile device or a desktop one. These hardware differences change the APIs that we have to look in to. Fortunately, as JVM language developers we have a pick of APIs including Swing for desktop applications and Android for mobile applications. With these, we can build graphical user interface applications for any device. Beyond these two, there are a couple of specialized client application frameworks with more advanced graphical capabilities.

Mobile devices

Mobile devices have specialized hardware which distinguishes them from desktop devices. Firstly, in mobile devices energy usage and heat dissipitation are significant factors. As mobile devices are not typically hooked up to a power supply, every piece of energy used by them is significant. At the same time, since they are held in our hands if they heat up too much that will effect the user. This is one reason why mobile processors tend to use ARM.

Secondly, mobile devices have different input and output devices configurations. Mobile devices lack the keyboards and mouses of standard hardware devices, both of them being replaced by touch screens. Further, the screens of phones and other mobile devices are too small to fit many standard applications.

Java SE provides means of handling printers, monitors, keyboards, mouses, processors, storage devices, etc in APIs distributed through a number of different packages, but it doesn't provide us with the means of handling mobile devices like phones. These distinction hardware configurations are handled by the Android APIs, which contain a number of Java SE packages but not Swing which is specifically for desktop applications.

Virtual mobile devices


You certainly wouldn't want to program on a mobile device when it doesn't have a keyboard. This produces a distinction between the devices you program on and the devices your programs run on. Fortunately, Android Studio provides the means to solve this by allowing you to create virtual mobile devices. That way you can run your Android programs right from your desktop.

To begin with, download Android Studio. Then open the device manager and select create device. As all Android applications are dependent upon the hardware they run on, you next select the hardware you want to emulate. Then select a system image for the Android API and click next change the virtual device as you needed and finish. With that you can get around the hardware differences between desktop and mobile applications and get to developing.

Android API

As mobile devices are a different sort of hardware then desktop devices they require their own API, but this by no means implies that there is no overlap between Java SE and Android. Most of the classes in the base, logging, preferences and SQL modules are available for use in Android applications.

As Android is based upon a different interaction paradigm then Swing, the desktop module is noticeably absent. Swing is suitable for the sort of hardware devices in desktop computers, while Android is more suitable for the sort of hardware configurations in mobile devices. Both serve their own purposes by targeting different types of hardware. Swing still has its use cases and a set of hardware that it targets.

A Java virtual machine for every device

The JVM is the best developer platform in the world. In order for it to maintain its status as the best developer platform into the future, it must have APIs for all kinds of hardware devices. With the different Java APIs like Android and Java SE that is now possible. Each different type of hardware has its own API.

Separately, Java ME provides support for embedded and mobile devices programmed with Java. It should be noted that Java ME is not the same thing as Android. Java ME is the historical API developed by Sun microsystems, while the Android API is used on most modern mobile devices. Both of them use a subset of Java SE.

External links:
Android Studio

Android API