I think programs with interactive UIs are good examples of programs
which are not functions. That is, they have essential state - there is
an actual screen, a mouse, the mouse cursor has a position, there is a
checkbox, it is checked or not and can toggle etc.
Clojure is specifically designed with the recognition that many
interesting programs are not functions, but that huge portions of them
should be functional (much, much more than in the typical Java/C#/
Python/Ruby program), and that any essential state must be manipulated
in a thread-safe manner, and gives you tools for realizing all of
this.
As has been pointed out, Clojure fns are Runnable and Callable, and
make great callbacks for UIs. Those callbacks can manipulate a
transactional model, send actions to agents etc. Because Clojure's
facilities don't require the threads they run on to be launched by
Clojure, or blessed in any way, they can interoperate with the
threading model of any GUI, including Swing's.
I know people have generated UIs with Netbeans and driven them from
Clojure. A declarative style of UI definition (a la JavaFX/XAML)
should also be easy. You can experiment with functional reactive
programming if that's your cup of tea, but I'd like to emphasize that
it's not necessary to do so.
Clojure's STM already models a system of time-coordinated worlds. You
can make decisions based on information as-of a point in time and make
coordinated changes as-of a point in time. Agents model true
asynchronicity.
What you want to do is stay clear about the role of the UI and its
mutability and keep it there. There may be good reasons for a CheckBox
object to have mutable state but there are none for an Employee object
to do the same. Make your model functional, your state transitions
functions taking and returning immutable values. Then, if you want to
associate those values with identities, put them in a ref or agent.
The single-threadedness of Swing itself should be a clear warning as
to the difficulty (impossibility?) of making a graph-of-mutable-
objects design multithreading capable. Treat the UI as IO and don't
let it infect your design.
If you stick to Clojure's data structures, refs and agents you should
be able to build a robust system with any GUI framework, and have a
lot of fun doing so.
Rich