First, a disclaimer: I'm not deeply familiar with the uniform access principle so you may want to take this with a grain of salt. That said, I would argue that Clojure does observe a uniform access principle: function calls.

The key quote on Wikipedia seems to be that "all services offered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation", and that's exactly the case with function calls in Clojure. In fact, *everything* in Clojure (and other Lisps) is a function call except for [special forms]( and [macros]( - and macros actually are functions, with the distinction that they operate on source code. You can even specify function call behavior for your own types by implementing `clojure.lang.IFn`:

    (deftype Invokable []
      (invoke [this]

    (def invokable (Invokable.))
    (invokable)                  ;=> :was-invoked

You may have in mind the use of keywords as functions, which are most specifically associated with hash-maps, but you can actually implement that behavior for different types as well. Here's a silly example where keyword access reads a file (with the same name as the keyword) from your home directory, or returns a default value if such a file doesn't exist:

    (ns weird.example
      (:require [ :as io]))

    (deftype WeirdKlass []
      (valAt [this k not-found]
        (let [home (System/getProperty "user.home")
              file (io/file home (name k))]
         (if (.isFile file)
           (slurp file)
      (valAt [this k]
        (.valAt this k nil)))

    (def klass (WeirdKlass.))

    ;; assuming you have a file at $HOME/testfile
    (:testfile klass)        ;=> "test content!"
    (:blah klass)            ;=> nil
    (:blah klass :not-found) ;=> :not-found