|
290 | 290 | (defmacro js-in [key obj]
|
291 | 291 | (core/list 'js* "~{} in ~{}" key obj))
|
292 | 292 |
|
293 |
| -(defmacro js-debugger [] |
| 293 | +(defmacro js-debugger |
| 294 | + "Emit JavaScript \"debugger;\" statement." |
| 295 | + [] |
294 | 296 | (core/list 'js* "debugger;"))
|
295 | 297 |
|
296 | 298 | (defmacro true? [x]
|
|
308 | 310 | (bool-expr (core/list 'js* "typeof ~{} === 'string'" x)))
|
309 | 311 |
|
310 | 312 | ;; TODO: x must be a symbol, not an arbitrary expression
|
311 |
| -(defmacro exists? [x] |
| 313 | +(defmacro exists? |
| 314 | + "Return true if argument exists, analogous to usage of typeof operator |
| 315 | + in JavaScript." |
| 316 | + [x] |
312 | 317 | (bool-expr
|
313 | 318 | (core/list 'js* "typeof ~{} !== 'undefined'"
|
314 | 319 | (vary-meta x assoc :cljs.analyzer/no-resolve true))))
|
315 | 320 |
|
316 |
| -(defmacro undefined? [x] |
| 321 | +(defmacro undefined? |
| 322 | + "Return true if argument is identical to the JavaScript undefined value." |
| 323 | + [x] |
317 | 324 | (bool-expr (core/list 'js* "(void 0 === ~{})" x)))
|
318 | 325 |
|
319 | 326 | (defmacro identical? [a b]
|
|
610 | 617 | 'js/Number "number"
|
611 | 618 | 'js/Function "function"})
|
612 | 619 |
|
613 |
| -(defmacro reify [& impls] |
| 620 | +(defmacro reify |
| 621 | + "reify is a macro with the following structure: |
| 622 | +
|
| 623 | + (reify options* specs*) |
| 624 | +
|
| 625 | + Currently there are no options. |
| 626 | +
|
| 627 | + Each spec consists of the protocol name followed by zero |
| 628 | + or more method bodies: |
| 629 | +
|
| 630 | + protocol |
| 631 | + (methodName [args+] body)* |
| 632 | +
|
| 633 | + Methods should be supplied for all methods of the desired |
| 634 | + protocol(s). You can also define overrides for Object methods. Note that |
| 635 | + the first parameter must be supplied to correspond to the target object |
| 636 | + ('this' in JavaScript parlance). Note also that recur calls |
| 637 | + to the method head should *not* pass the target object, it will be supplied |
| 638 | + automatically and can not be substituted. |
| 639 | +
|
| 640 | + recur works to method heads The method bodies of reify are lexical |
| 641 | + closures, and can refer to the surrounding local scope: |
| 642 | +
|
| 643 | + (str (let [f \"foo\"] |
| 644 | + (reify Object |
| 645 | + (toString [this] f)))) |
| 646 | + == \"foo\" |
| 647 | +
|
| 648 | + (seq (let [f \"foo\"] |
| 649 | + (reify ISeqable |
| 650 | + (-seq [this] (-seq f))))) |
| 651 | + == (\\f \\o \\o)) |
| 652 | +
|
| 653 | + reify always implements IMeta and IWithMeta and transfers meta |
| 654 | + data of the form to the created object. |
| 655 | +
|
| 656 | + (meta ^{:k :v} (reify Object (toString [this] \"foo\"))) |
| 657 | + == {:k :v}" |
| 658 | + [& impls] |
614 | 659 | (let [t (with-meta (gensym "t") {:anonymous true})
|
615 | 660 | meta-sym (gensym "meta")
|
616 | 661 | this-sym (gensym "_")
|
|
628 | 673 | ~@impls))
|
629 | 674 | (new ~t ~@locals ~(ana/elide-reader-meta (meta &form))))))
|
630 | 675 |
|
631 |
| -(defmacro specify! [expr & impls] |
| 676 | +(defmacro specify! |
| 677 | + "Identical to reify but mutates its first argument." |
| 678 | + [expr & impls] |
632 | 679 | (let [x (with-meta (gensym "x") {:extend :instance})]
|
633 | 680 | `(let [~x ~expr]
|
634 | 681 | (extend-type ~x ~@impls)
|
635 | 682 | ~x)))
|
636 | 683 |
|
637 |
| -(defmacro specify [expr & impls] |
| 684 | +(defmacro specify |
| 685 | + "Identical to specify but does not mutate its first argument. The first |
| 686 | + argument must be an ICloneable instance." |
| 687 | + [expr & impls] |
638 | 688 | `(cljs.core/specify! (cljs.core/clone ~expr)
|
639 | 689 | ~@impls))
|
640 | 690 |
|
|
813 | 863 | (validate-impl-sigs env proto method))
|
814 | 864 | (recur (conj protos proto) impls)))))
|
815 | 865 |
|
816 |
| -(defmacro extend-type [type-sym & impls] |
| 866 | +(defmacro extend-type |
| 867 | + "Extend a type to a series of protocols. Useful when you are |
| 868 | + supplying the definitions explicitly inline. Propagates the |
| 869 | + type as a type hint on the first argument of all fns. |
| 870 | +
|
| 871 | + (extend-type MyType |
| 872 | + ICounted |
| 873 | + (-count [c] ...) |
| 874 | + Foo |
| 875 | + (bar [x y] ...) |
| 876 | + (baz ([x] ...) ([x y & zs] ...))" |
| 877 | + [type-sym & impls] |
817 | 878 | (let [env &env
|
818 | 879 | _ (validate-impls env impls)
|
819 | 880 | resolve (partial resolve-var env)
|
|
886 | 947 | [~@fields]
|
887 | 948 | (new ~rname ~@field-values))))
|
888 | 949 |
|
889 |
| -(defmacro deftype [t fields & impls] |
| 950 | +(defmacro deftype |
| 951 | + "(deftype name [fields*] options* specs*) |
| 952 | +
|
| 953 | + Currently there are no options. |
| 954 | +
|
| 955 | + Each spec consists of a protocol or interface name followed by zero |
| 956 | + or more method bodies: |
| 957 | +
|
| 958 | + protocol-or-Object |
| 959 | + (methodName [args*] body)* |
| 960 | +
|
| 961 | + The type will have the (by default, immutable) fields named by |
| 962 | + fields, which can have type hints. Protocols and methods |
| 963 | + are optional. The only methods that can be supplied are those |
| 964 | + declared in the protocols/interfaces. Note that method bodies are |
| 965 | + not closures, the local environment includes only the named fields, |
| 966 | + and those fields can be accessed directly. Fields can be qualified |
| 967 | + with the metadata :mutable true at which point (set! afield aval) will be |
| 968 | + supported in method bodies. Note well that mutable fields are extremely |
| 969 | + difficult to use correctly, and are present only to facilitate the building |
| 970 | + of higherlevel constructs, such as ClojureScript's reference types, in |
| 971 | + ClojureScript itself. They are for experts only - if the semantics and |
| 972 | + implications of :mutable are not immediately apparent to you, you should not |
| 973 | + be using them. |
| 974 | +
|
| 975 | + Method definitions take the form: |
| 976 | +
|
| 977 | + (methodname [args*] body) |
| 978 | +
|
| 979 | + The argument and return types can be hinted on the arg and |
| 980 | + methodname symbols. If not supplied, they will be inferred, so type |
| 981 | + hints should be reserved for disambiguation. |
| 982 | +
|
| 983 | + Methods should be supplied for all methods of the desired |
| 984 | + protocol(s). You can also define overrides for methods of Object. Note that |
| 985 | + a parameter must be supplied to correspond to the target object |
| 986 | + ('this' in JavaScript parlance). Note also that recur calls to the method |
| 987 | + head should *not* pass the target object, it will be supplied |
| 988 | + automatically and can not be substituted. |
| 989 | +
|
| 990 | + In the method bodies, the (unqualified) name can be used to name the |
| 991 | + class (for calls to new, instance? etc). |
| 992 | +
|
| 993 | + One constructor will be defined, taking the designated fields. Note |
| 994 | + that the field names __meta and __extmap are currently reserved and |
| 995 | + should not be used when defining your own types. |
| 996 | +
|
| 997 | + Given (deftype TypeName ...), a factory function called ->TypeName |
| 998 | + will be defined, taking positional parameters for the fields" |
| 999 | + [t fields & impls] |
890 | 1000 | (let [env &env
|
891 | 1001 | r (:name (cljs.analyzer/resolve-var (dissoc env :locals) t))
|
892 | 1002 | [fpps pmasks] (prepare-protocol-masks env impls)
|
|
992 | 1102 | `(defn ~fn-name [~ms]
|
993 | 1103 | (new ~rname ~@getters nil (dissoc ~ms ~@ks) nil))))
|
994 | 1104 |
|
995 |
| -(defmacro defrecord [rsym fields & impls] |
| 1105 | +(defmacro defrecord |
| 1106 | + "(defrecord name [fields*] options* specs*) |
| 1107 | +
|
| 1108 | + Currently there are no options. |
| 1109 | +
|
| 1110 | + Each spec consists of a protocol or interface name followed by zero |
| 1111 | + or more method bodies: |
| 1112 | +
|
| 1113 | + protocol-or-Object |
| 1114 | + (methodName [args*] body)* |
| 1115 | +
|
| 1116 | + The record will have the (immutable) fields named by |
| 1117 | + fields, which can have type hints. Protocols and methods |
| 1118 | + are optional. The only methods that can be supplied are those |
| 1119 | + declared in the protocols. Note that method bodies are |
| 1120 | + not closures, the local environment includes only the named fields, |
| 1121 | + and those fields can be accessed directly. |
| 1122 | +
|
| 1123 | + Method definitions take the form: |
| 1124 | +
|
| 1125 | + (methodname [args*] body) |
| 1126 | +
|
| 1127 | + The argument and return types can be hinted on the arg and |
| 1128 | + methodname symbols. If not supplied, they will be inferred, so type |
| 1129 | + hints should be reserved for disambiguation. |
| 1130 | +
|
| 1131 | + Methods should be supplied for all methods of the desired |
| 1132 | + protocol(s). You can also define overrides for |
| 1133 | + methods of Object. Note that a parameter must be supplied to |
| 1134 | + correspond to the target object ('this' in JavaScript parlance). Note also |
| 1135 | + that recur calls to the method head should *not* pass the target object, it |
| 1136 | + will be supplied automatically and can not be substituted. |
| 1137 | +
|
| 1138 | + In the method bodies, the (unqualified) name can be used to name the |
| 1139 | + class (for calls to new, instance? etc). |
| 1140 | +
|
| 1141 | + The type will have implementations of several ClojureScript |
| 1142 | + protocol generated automatically: IMeta/IWithMeta (metadata support) and |
| 1143 | + IMap, etc. |
| 1144 | +
|
| 1145 | + In addition, defrecord will define type-and-value-based =, |
| 1146 | + and will define ClojureScript IHash and IEquiv. |
| 1147 | +
|
| 1148 | + Two constructors will be defined, one taking the designated fields |
| 1149 | + followed by a metadata map (nil for none) and an extension field |
| 1150 | + map (nil for none), and one taking only the fields (using nil for |
| 1151 | + meta and extension fields). Note that the field names __meta |
| 1152 | + and __extmap are currently reserved and should not be used when |
| 1153 | + defining your own records. |
| 1154 | +
|
| 1155 | + Given (defrecord TypeName ...), two factory functions will be |
| 1156 | + defined: ->TypeName, taking positional parameters for the fields, |
| 1157 | + and map->TypeName, taking a map of keywords to field values." |
| 1158 | + [rsym fields & impls] |
996 | 1159 | (let [rsym (vary-meta rsym assoc :internal-ctor true)
|
997 | 1160 | r (vary-meta
|
998 | 1161 | (:name (cljs.analyzer/resolve-var (dissoc &env :locals) rsym))
|
|
1006 | 1169 | ~(build-map-factory rsym r fields)
|
1007 | 1170 | ~r)))
|
1008 | 1171 |
|
1009 |
| -(defmacro defprotocol [psym & doc+methods] |
| 1172 | +(defmacro defprotocol |
| 1173 | + "A protocol is a named set of named methods and their signatures: |
| 1174 | +
|
| 1175 | + (defprotocol AProtocolName |
| 1176 | + ;optional doc string |
| 1177 | + \"A doc string for AProtocol abstraction\" |
| 1178 | +
|
| 1179 | + ;method signatures |
| 1180 | + (bar [this a b] \"bar docs\") |
| 1181 | + (baz [this a] [this a b] [this a b c] \"baz docs\")) |
| 1182 | +
|
| 1183 | + No implementations are provided. Docs can be specified for the |
| 1184 | + protocol overall and for each method. The above yields a set of |
| 1185 | + polymorphic functions and a protocol object. All are |
| 1186 | + namespace-qualified by the ns enclosing the definition The resulting |
| 1187 | + functions dispatch on the type of their first argument, which is |
| 1188 | + required and corresponds to the implicit target object ('this' in |
| 1189 | + JavaScript parlance). defprotocol is dynamic, has no special compile-time |
| 1190 | + effect, and defines no new types. |
| 1191 | +
|
| 1192 | + (defprotocol P |
| 1193 | + (foo [this]) |
| 1194 | + (bar-me [this] [this y])) |
| 1195 | +
|
| 1196 | + (deftype Foo [a b c] |
| 1197 | + P |
| 1198 | + (foo [this] a) |
| 1199 | + (bar-me [this] b) |
| 1200 | + (bar-me [this y] (+ c y))) |
| 1201 | +
|
| 1202 | + (bar-me (Foo. 1 2 3) 42) |
| 1203 | + => 45 |
| 1204 | +
|
| 1205 | + (foo |
| 1206 | + (let [x 42] |
| 1207 | + (reify P |
| 1208 | + (foo [this] 17) |
| 1209 | + (bar-me [this] x) |
| 1210 | + (bar-me [this y] x)))) |
| 1211 | + => 17" |
| 1212 | + [psym & doc+methods] |
1010 | 1213 | (let [p (:name (cljs.analyzer/resolve-var (dissoc &env :locals) psym))
|
1011 | 1214 | psym (vary-meta psym assoc :protocol-symbol true)
|
1012 | 1215 | ns-name (-> &env :ns :name)
|
|
1091 | 1294 | false)))
|
1092 | 1295 | (cljs.core/native-satisfies? ~psym ~xsym)))))
|
1093 | 1296 |
|
1094 |
| -(defmacro lazy-seq [& body] |
| 1297 | +(defmacro lazy-seq |
| 1298 | + "Takes a body of expressions that returns an ISeq or nil, and yields |
| 1299 | + a ISeqable object that will invoke the body only the first time seq |
| 1300 | + is called, and will cache the result and return it on all subsequent |
| 1301 | + seq calls." |
| 1302 | + [& body] |
1095 | 1303 | `(new cljs.core/LazySeq nil (fn [] ~@body) nil nil))
|
1096 | 1304 |
|
1097 | 1305 | (defmacro delay [& body]
|
|
1189 | 1397 | cljs.analyzer/*cljs-file*)))))
|
1190 | 1398 | (assoc m test expr)))
|
1191 | 1399 |
|
1192 |
| -(defmacro case [e & clauses] |
| 1400 | +(defmacro case |
| 1401 | + "Takes an expression, and a set of clauses. |
| 1402 | +
|
| 1403 | + Each clause can take the form of either: |
| 1404 | +
|
| 1405 | + test-constant result-expr |
| 1406 | +
|
| 1407 | + (test-constant1 ... test-constantN) result-expr |
| 1408 | +
|
| 1409 | + The test-constants are not evaluated. They must be compile-time |
| 1410 | + literals, and need not be quoted. If the expression is equal to a |
| 1411 | + test-constant, the corresponding result-expr is returned. A single |
| 1412 | + default expression can follow the clauses, and its value will be |
| 1413 | + returned if no clause matches. If no default expression is provided |
| 1414 | + and no clause matches, an Error is thrown. |
| 1415 | +
|
| 1416 | + Unlike cond and condp, case does a constant-time dispatch, the |
| 1417 | + clauses are not considered sequentially. All manner of constant |
| 1418 | + expressions are acceptable in case, including numbers, strings, |
| 1419 | + symbols, keywords, and (ClojureScript) composites thereof. Note that since |
| 1420 | + lists are used to group multiple constants that map to the same |
| 1421 | + expression, a vector can be used to match a list if needed. The |
| 1422 | + test-constants need not be all of the same type." |
| 1423 | + [e & clauses] |
1193 | 1424 | (core/let [default (if (odd? (count clauses))
|
1194 | 1425 | (last clauses)
|
1195 | 1426 | `(throw
|
|
0 commit comments