A library for categorizing values in Clojure, ClojureScript, and Babashka.
Lasertag took shape while developing of the colorizing pretty-printing engine used by Bling and Fireworks.
The function lasertag.core/tag will return a descriptive tag:
(require '[lasertag.core :refer [tag tag-map]])
(tag "hi") ; => :string
(tag :hi) ; => :keyword
(tag "#^hi$") ; => :regex
(tag true) ; => :boolean
(tag [1 2 3]) ; => :vector
(tag '(1 2 3)) ; => :seq
(tag (range 3)) ; => :seq
(tag 1) ; => :number
(tag 1.5) ; => :number
(tag ##Inf) ; => :numberlasertag.core/tag-map returns a map with more info:
(tag-map (range 3))
=>
{:tag :seq
:type clojure.lang.LongRange
:all-tags #{:iterable :coll :seq :carries-meta :lazy}
:classname "clojure.lang.LongRange"}lasertag.core/tag vs clojure.core/type
| Input value | lasertag.core/tag |
clojure.core/type |
|---|---|---|
"hi" |
:string |
java.lang.String |
:hi |
:keyword |
clojure.lang.Keyword |
"^hi$" |
:regex |
java.util.regex.Pattern |
true |
:boolean |
java.lang.Boolean |
mysym |
:symbol |
clojure.lang.Symbol |
nil |
:nil |
nil |
[1 2 3] |
:vector |
clojure.lang.PersistentVector |
#{1 3 2} |
:set |
clojure.lang.PersistentHashSet |
{:a 2, :b 3} |
:map |
clojure.lang.PersistentArrayMap |
(map inc (range 3)) |
:seq |
clojure.lang.LazySeq |
(range 3) |
:seq |
clojure.lang.LongRange |
(:a :b :c) |
:seq |
clojure.lang.PersistentList |
Infinity |
:number |
java.lang.Double |
-Infinity |
:number |
java.lang.Double |
NaN |
:number |
java.lang.Double |
1/3 |
:number |
clojure.lang.Ratio |
(byte 0) |
:number |
java.lang.Byte |
(short 3) |
:number |
java.lang.Short |
(double 23.44) |
:number |
java.lang.Double |
1M |
:number |
java.math.BigDecimal |
1 |
:number |
java.lang.Long |
(float 1.5) |
:number |
java.lang.Float |
(char a) |
:char |
java.lang.Character |
(java.math.BigInteger. "171") |
:number |
java.math.BigInteger |
(java.util.Date.) |
:inst |
java.util.Date |
java.util.Date |
:class |
java.lang.Class |
lasertag.core/tag vs cljs.core/type
| Input value | lasertag.core/tag |
cljs.core/type |
|---|---|---|
"hi" |
:string |
#object[String] |
:hi |
:keyword |
cljs.core/Keyword |
"^hi$" |
:regex |
#object[RegExp] |
true |
:boolean |
#object[Boolean] |
mysym |
:symbol |
cljs.core/Symbol |
nil |
:nil |
nil |
[1 2 3] |
:vector |
cljs.core/PersistentVector |
#{1 3 2} |
:set |
cljs.core/PersistentHashSet |
{:a 2, :b 3} |
:map |
cljs.core/PersistentArrayMap |
(map inc (range 3)) |
:seq |
cljs.core/LazySeq |
(range 3) |
:seq |
cljs.core/IntegerRange |
(:a :b :c) |
:seq |
cljs.core/List |
Infinity |
:number |
#object[Boolean] |
-Infinity |
:number |
#object[Boolean] |
js/parseInt |
:function |
#object[Function] |
(new js/Date.)<
B61D
/code> |
:inst |
#object[Date] |
(.values #js [1 2 3]) |
:iterable |
#object[Object] |
(array "a" "b") |
:array |
#object[Array] |
(new js/Int8Array #js ["a" "b"]) |
:array |
#object[Int8Array] |
(new js/Set #js[1 2 3]) |
:set |
#object[Set] |
(js/Promise. (fn [x] x)) |
:promise |
#object[Promise] |
Requires Clojure 1.11.1 or higher
If using with Babashka, requires Babashka v1.12.210 or higher
Add as a dependency to your project:
Deps:
io.github.paintparty/lasertag {:mvn/version "0.12.0"}Leiningen:
[io.github.paintparty/lasertag "0.12.0"]Require it:
(require '[lasertag.core :refer [tag tag-map]])Or import into your namespace:
(ns myns.core
(:require
[lasertag.core :refer [tag tag-map]]))lasertag.core/tag returns a keyword describing the type of value:
(tag 1) ;; => :numberlasertag.core/tag-map will return a map with additional info.
;; string
(tag-map "hi")
=>
{:tag :string
:type java.lang.String
:all-tags #{:string :scalar}
:classname "java.lang.String"}
;; map
(tag-map {:a :foo})
=>
{:tag :map
:type clojure.lang.PersistentArrayMap
:all-tags #{:coll
:array-map
:coll-like
:map-like
:map
:carries-meta}
:classname "clojure.lang.PersistentArrayMap"}
;; range
(tag-map (range 10))
=>
{:tag :seq
:type clojure.lang.LongRange
:all-tags #{:iterable
:coll
:deferred
:coll-like
:lazy
:seq
:carries-meta}
:classname "clojure.lang.LongRange"}
;; Record
(defrecord MyRecordType [a b c d])
(tag-map (->MyRecordType 4 8 4 5))
=>
{:tag :record
:type my.ns.MyRecordType
:all-tags #{:datatype
:coll
:coll-like
:record
:map-like
:carries-meta}
:classname "my.ns.MyRecordType"}
;; Delay
(def my-delay (delay 100))
(tag-map my-delay)
=>
{:tag :delay
:type clojure.lang.Delay
:all-tags #{:deferred :delay}
:classname "clojure.lang.Delay"}
;; Multimethod definition
(defmulti different-behavior (fn [x] (:x-type x)))
(tag-map different-behavior)
=>
{:tag :defmulti
:type clojure.lang.MultiFn
:all-tags #{:defmulti}
:classname "clojure.lang.MultiFn"}
;; Var
(def bar nil)
(tag-map #'bar)
=>
{:tag :var
:type clojure.lang.Var
:all-tags #{:reference :var}
:classname "clojure.lang.Var"}
The JVM tests require leiningen to be installed.
lein testClojureScript tests:
npm run testBabashka tests:
bb test:bbAlpha, subject to change. Issues welcome, see contributing.
Issues for bugs, improvements, or features are very welcome. Please file an issue for discussion before starting or issuing a PR.
Copyright © 2024-2026 Jeremiah Coyle
This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0.
This Source Code may also be made available under the following Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version, with the GNU Classpath Exception which is available at https://www.gnu.org/software/classpath/license.html.