 (defn symbol? [x]
   (and (goog.isString x)
        (= (.charAt x 0) \uFDD1)))
+
+(defn str
+  "With no args, returns the empty string. With one arg x, returns
+  x.toString().  (str nil) returns the empty string. With more than
+  one arg, returns the concatenation of the str values of the args."
+  ([] "")
+  ([x] (if (nil? x) "" (. x (toString))))
+  ([x & ys] (reduce + (map str (cons x ys)))))
+
+(defn subs
+  "Returns the substring of s beginning at start inclusive, and ending
+  at end (defaults to length of string), exclusive."
+  ([s start] (.substring s start))
+  ([s start end] (.substring s start end)))
+
+(defn name [x]
+  "Returns the name String of a string, symbol or keyword."
+  (cond
+    (string? x) x
+    (or (keyword? x) (symbol? x))
+      (let [i (.lastIndexOf x "/")]
+        (if (< i 0)
+          (subs x 2)
+          (subs x (inc i))))
+    :else nil #_(throw (str "Doesn't support name: " x))))
+
+(defn namespace [x]
+  "Returns the namespace String of a symbol or keyword, or nil if not present."
+  (if (or (keyword? x) (symbol? x))
+    (let [i (.lastIndexOf x "/")]
+      (when (> i -1)
+        (subs x 2 i)))
+    :else nil #_(throw (str "Doesn't support namespace: " x))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Seq fns ;;;;;;;;;;;;;;;;
 

  By default, pr and prn print in a way that objects can be
  read by the reader"
  [obj]
  (pr-with-opts obj {"readably" true}))

(defn println
  "Prints the object(s) using string-print.
  print and println produce output for human consumption."
  [obj]
  (pr-with-opts obj {"readably" false})
  (newline))

(defn prn
  "Same as pr followed by (newline)."
  [obj]
  (pr-with-opts obj {"readably" true})
  (newline))

          [end]))

(extend-protocol IPrintable
  goog.global.Boolean (-pr-seq [bool opts] (list (str bool)))
  goog.global.Number (-pr-seq [n opts] (list (str n)))
  goog.global.String (-pr-seq [obj opts]
                        (cond
                          (keyword? obj)
                            (list (str ":"
                                       (when-let [nspc (namespace obj)]
                                         (str nspc "/"))
                                       (name obj)))
                          (symbol? obj)
                            (list (str (when-let [nspc (namespace obj)]
                                         (str nspc "/"))
                                       (name obj)))
                          (get opts :readably)
                            (list (goog.string.quote obj))
                          :else (list obj)))
  goog.global.Array (-pr-seq [a opts]
                      (pr-sequential pr-seq "#<Array [" ", " "]>" opts a)))

