Carp/core/Macros.carp

232 lines
7.7 KiB
Plaintext
Raw Normal View History

;; Defining the meta data macros early so that they can be used by all the other code.
2020-05-05 15:04:09 +03:00
(defmacro and [x y]
(list 'if x y false))
(defmacro or [x y]
(list 'if x true y))
Make `doc` take a rest parameter of strings Carp preserves tabulation and other whitespace in strings, as it should. This sometimes results in awkward code indentation when it comes to long doc strings that exceed 80 characters. Often, one has to continue the string on a newline, but needs to avoid adding tabs to prevent Carp from rendering them in the output. This change alters the behavior of doc to take a series of strings as a rest parameter instead, allowing for neater organization in the source, for example, after this change the following long doc string for compose: ~~~ "Returns the composition of two functions `f` and `g` for functions of any arity; concretely, returns a function accepting the correct number of arguments for `g`, applies `g` to those arguments, then applies `f` to the result. If you only need to compose functions that take a single argument (unary arity) see `comp`. Comp also generates the form that corresponds to the composition, compose contrarily evaluates 'eagerly' and returns a computed symbol. For exmaple: ``` ;; a silly composition ((compose empty take) 3 [1 2 3 4 5]) ;; => [] (String.join (collect-into ((compose reverse map) Symbol.str '(p r a c)) array)) ;; => 'carp' ;; comp for comparison ((comp (curry + 1) (curry + 2)) 4) ;; => (+ 1 (+ 2 4)) ```" ~~~ becomes: ~~~ "Returns the composition of two functions `f` and `g` for functions of any" "arity; concretely, returns a function accepting the correct number of" "arguments for `g`, applies `g` to those arguments, then applies `f` to the" "result." "" "If you only need to compose functions that take a single argument (unary arity)" "see `comp`. Comp also generates the form that corresponds to the composition," "compose contrarily evaluates 'eagerly' and returns a computed symbol." "```" ";; a silly composition" "((compose empty take) 3 [1 2 3 4 5])" ";; => []" "" "(String.join (collect-into ((compose reverse map) Symbol.str '(p r a c)) array))" ";; => 'carp'" "" ";; comp for comparison" "((comp (curry + 1) (curry + 2)) 4)" ";; => (+ 1 (+ 2 4))" "```") ~~~ And the output remains the same; this just enables better alignment in the source file. The strings passed to doc are newline separated by default, but one can circumvent this behavior by passing a bool along with the string as follows: ~~~ (doc foo ("My amazing doc " false) "continues on one line." "" "And then another.") ~~~ The above doc string will result in the following output: ~~~ My amazing doc continues on one line. And then another. ~~~ Of course, the original behavior of doc also remains valid, so if one prefers to use the old indentation-mixed single string format, one still can! This change also reformats the doc strings in macro to utilize the new rest parameter and make the source a bit neater.
2020-10-01 18:41:05 +03:00
;; Defined early so that `doc` can accept a rest arg
(defndynamic map-internal [f xs acc]
(if (= 0 (length xs))
acc
(map-internal f (cdr xs) (cons-last (f (car xs)) acc))))
(defndynamic list-to-array-internal [xs acc]
(if (= 0 (length xs))
acc
(list-to-array-internal (cdr xs) (append acc (array (car xs))))))
(defmodule Dynamic
(defndynamic /= [a b] (not (= a b)))
(defndynamic caar [pair] (car (car pair)))
(defndynamic cadr [pair] (car (cdr pair)))
(defndynamic cdar [pair] (cdr (car pair)))
(defndynamic cddr [pair] (cdr (cdr pair)))
(defndynamic caaar [pair] (car (car (car pair))))
(defndynamic caadr [pair] (car (car (cdr pair))))
(defndynamic cadar [pair] (car (cdr (car pair))))
(defndynamic cdaar [pair] (cdr (car (car pair))))
(defndynamic caddr [pair] (car (cdr (cdr pair))))
(defndynamic cdadr [pair] (cdr (car (cdr pair))))
(defndynamic cddar [pair] (cdr (cdr (car pair))))
(defndynamic cdddr [pair] (cdr (cdr (cdr pair))))
(defndynamic caaaar [pair] (car (car (car (car pair)))))
(defndynamic caaadr [pair] (car (car (car (cdr pair)))))
(defndynamic caadar [pair] (car (car (cdr (car pair)))))
(defndynamic caaddr [pair] (car (car (cdr (cdr pair)))))
(defndynamic cadaar [pair] (car (cdr (car (car pair)))))
(defndynamic cadadr [pair] (car (cdr (car (cdr pair)))))
(defndynamic caddar [pair] (car (cdr (cdr (car pair)))))
(defndynamic cadddr [pair] (car (cdr (cdr (cdr pair)))))
(defndynamic cdaaar [pair] (cdr (car (car (car pair)))))
(defndynamic cdaadr [pair] (cdr (car (car (cdr pair)))))
(defndynamic cdadar [pair] (cdr (car (cdr (car pair)))))
(defndynamic cdaddr [pair] (cdr (car (cdr (cdr pair)))))
(defndynamic cddaar [pair] (cdr (cdr (car (car pair)))))
(defndynamic cddadr [pair] (cdr (cdr (car (cdr pair)))))
(defndynamic cdddar [pair] (cdr (cdr (cdr (car pair)))))
(defndynamic cddddr [pair] (cdr (cdr (cdr (cdr pair))))))
(meta-set! doc "doc" "Set documentation for a binding.")
Make `doc` take a rest parameter of strings Carp preserves tabulation and other whitespace in strings, as it should. This sometimes results in awkward code indentation when it comes to long doc strings that exceed 80 characters. Often, one has to continue the string on a newline, but needs to avoid adding tabs to prevent Carp from rendering them in the output. This change alters the behavior of doc to take a series of strings as a rest parameter instead, allowing for neater organization in the source, for example, after this change the following long doc string for compose: ~~~ "Returns the composition of two functions `f` and `g` for functions of any arity; concretely, returns a function accepting the correct number of arguments for `g`, applies `g` to those arguments, then applies `f` to the result. If you only need to compose functions that take a single argument (unary arity) see `comp`. Comp also generates the form that corresponds to the composition, compose contrarily evaluates 'eagerly' and returns a computed symbol. For exmaple: ``` ;; a silly composition ((compose empty take) 3 [1 2 3 4 5]) ;; => [] (String.join (collect-into ((compose reverse map) Symbol.str '(p r a c)) array)) ;; => 'carp' ;; comp for comparison ((comp (curry + 1) (curry + 2)) 4) ;; => (+ 1 (+ 2 4)) ```" ~~~ becomes: ~~~ "Returns the composition of two functions `f` and `g` for functions of any" "arity; concretely, returns a function accepting the correct number of" "arguments for `g`, applies `g` to those arguments, then applies `f` to the" "result." "" "If you only need to compose functions that take a single argument (unary arity)" "see `comp`. Comp also generates the form that corresponds to the composition," "compose contrarily evaluates 'eagerly' and returns a computed symbol." "```" ";; a silly composition" "((compose empty take) 3 [1 2 3 4 5])" ";; => []" "" "(String.join (collect-into ((compose reverse map) Symbol.str '(p r a c)) array))" ";; => 'carp'" "" ";; comp for comparison" "((comp (curry + 1) (curry + 2)) 4)" ";; => (+ 1 (+ 2 4))" "```") ~~~ And the output remains the same; this just enables better alignment in the source file. The strings passed to doc are newline separated by default, but one can circumvent this behavior by passing a bool along with the string as follows: ~~~ (doc foo ("My amazing doc " false) "continues on one line." "" "And then another.") ~~~ The above doc string will result in the following output: ~~~ My amazing doc continues on one line. And then another. ~~~ Of course, the original behavior of doc also remains valid, so if one prefers to use the old indentation-mixed single string format, one still can! This change also reformats the doc strings in macro to utilize the new rest parameter and make the source a bit neater.
2020-10-01 18:41:05 +03:00
(defmacro doc [name :rest strings]
(let [newline "
" ;; Looks a bit odd but the newline literal is important here! (str \newline) currently results in unwanted escapes
separated (map-internal (fn [x] (if (list? x)
(if (cadr x)
(Dynamic.String.concat [(car x) newline])
(car x))
(Dynamic.String.concat [x newline])))
strings
())]
(eval (list 'meta-set! name "doc" (Dynamic.String.concat (list-to-array-internal separated []))))))
(doc print-doc "Print the documentation for a binding.")
(defmacro print-doc [name]
2020-04-17 13:29:21 +03:00
(eval (list 'macro-log (list 'meta name "doc"))))
(doc sig "Annotate a binding with the desired signature.")
(defmacro sig [name signature]
2020-04-17 13:29:21 +03:00
(eval (list 'meta-set! name "sig" signature)))
(doc print-sig "Print the annotated signature for a binding.")
(defmacro print-sig [name]
2020-04-17 13:29:21 +03:00
(eval (list 'macro-log (list 'meta name "sig"))))
(doc hide "Mark a binding as hidden, this will make it not print with the 'info' command.")
(defmacro hidden [name]
2020-04-17 13:29:21 +03:00
(eval (list 'meta-set! name "hidden" true)))
(doc private "Mark a binding as private, this will make it inaccessible from other modules.")
2018-03-27 15:14:30 +03:00
(defmacro private [name]
2020-04-17 13:29:21 +03:00
(eval (list 'meta-set! name "private" true)))
2019-06-22 21:18:32 +03:00
(doc todo "sets the todo property for a binding.")
(defmacro todo [name value]
2020-04-17 13:29:21 +03:00
(eval (list 'meta-set! name "todo" value)))
2019-06-22 21:18:32 +03:00
2018-03-27 15:08:49 +03:00
(doc private? "Is this binding private?")
(defmacro private? [name]
(eval (list 'not (list 'list? (list 'meta name "private")))))
2018-03-27 15:08:49 +03:00
(doc hidden? "Is this binding hidden?")
(defmacro hidden? [name]
(eval (list 'not (list 'list? (list 'meta name "hidden")))))
2019-06-04 12:30:22 +03:00
(defndynamic annotate-helper [name annotation]
(list 'cons annotation (list 'meta name "annotations")))
2019-06-04 12:30:22 +03:00
(doc annotate "Add an annotation to this binding.")
(defmacro annotate [name annotation]
(eval (list 'meta-set! name "annotations" (eval (annotate-helper name annotation)))))
(defmodule Dynamic
(defndynamic quoted [x]
(list 'quote x))
2020-03-09 17:50:52 +03:00
)
2019-03-13 20:49:48 +03:00
(defndynamic cond-internal [xs]
(if (= (length xs) 0)
2017-06-26 12:15:03 +03:00
(list)
(if (= (length xs) 2)
(macro-error "cond has even number of branches; add an else branch")
(if (= (length xs) 1)
2017-06-26 12:15:03 +03:00
(car xs)
(list
2017-10-17 10:02:12 +03:00
'if
2017-06-26 12:15:03 +03:00
(car xs)
(cadr xs)
(cond-internal (cddr xs)))))))
2017-06-26 12:15:03 +03:00
Make `doc` take a rest parameter of strings Carp preserves tabulation and other whitespace in strings, as it should. This sometimes results in awkward code indentation when it comes to long doc strings that exceed 80 characters. Often, one has to continue the string on a newline, but needs to avoid adding tabs to prevent Carp from rendering them in the output. This change alters the behavior of doc to take a series of strings as a rest parameter instead, allowing for neater organization in the source, for example, after this change the following long doc string for compose: ~~~ "Returns the composition of two functions `f` and `g` for functions of any arity; concretely, returns a function accepting the correct number of arguments for `g`, applies `g` to those arguments, then applies `f` to the result. If you only need to compose functions that take a single argument (unary arity) see `comp`. Comp also generates the form that corresponds to the composition, compose contrarily evaluates 'eagerly' and returns a computed symbol. For exmaple: ``` ;; a silly composition ((compose empty take) 3 [1 2 3 4 5]) ;; => [] (String.join (collect-into ((compose reverse map) Symbol.str '(p r a c)) array)) ;; => 'carp' ;; comp for comparison ((comp (curry + 1) (curry + 2)) 4) ;; => (+ 1 (+ 2 4)) ```" ~~~ becomes: ~~~ "Returns the composition of two functions `f` and `g` for functions of any" "arity; concretely, returns a function accepting the correct number of" "arguments for `g`, applies `g` to those arguments, then applies `f` to the" "result." "" "If you only need to compose functions that take a single argument (unary arity)" "see `comp`. Comp also generates the form that corresponds to the composition," "compose contrarily evaluates 'eagerly' and returns a computed symbol." "```" ";; a silly composition" "((compose empty take) 3 [1 2 3 4 5])" ";; => []" "" "(String.join (collect-into ((compose reverse map) Symbol.str '(p r a c)) array))" ";; => 'carp'" "" ";; comp for comparison" "((comp (curry + 1) (curry + 2)) 4)" ";; => (+ 1 (+ 2 4))" "```") ~~~ And the output remains the same; this just enables better alignment in the source file. The strings passed to doc are newline separated by default, but one can circumvent this behavior by passing a bool along with the string as follows: ~~~ (doc foo ("My amazing doc " false) "continues on one line." "" "And then another.") ~~~ The above doc string will result in the following output: ~~~ My amazing doc continues on one line. And then another. ~~~ Of course, the original behavior of doc also remains valid, so if one prefers to use the old indentation-mixed single string format, one still can! This change also reformats the doc strings in macro to utilize the new rest parameter and make the source a bit neater.
2020-10-01 18:41:05 +03:00
(doc cond
"Executes a block of code if a specified condition is true. Multiple"
"such blocks can be chained."
""
"```"
"(cond"
" (< 10 1) (println \"Condition 1 is true\")"
" (> 10 1) (println \"Condition 2 is true\")"
" (println \"Else branch\"))"
"```")
2017-06-26 12:15:03 +03:00
(defmacro cond [:rest xs]
(cond-internal xs))
2017-06-29 18:05:34 +03:00
(defmacro refstr [x]
2017-10-17 10:02:12 +03:00
(list 'ref
(list 'str x)))
2017-10-13 14:48:40 +03:00
2017-11-29 17:28:21 +03:00
(defmacro swap! [x y]
(list 'let (array 'tmp y) (list 'do (list 'set! y x) (list 'set! x 'tmp))))
(defmacro update! [x f]
(list 'set! x (list f x)))
2019-03-13 20:49:48 +03:00
(defndynamic use-all-fn [names]
(if (= (length names) 0)
2017-12-12 17:08:33 +03:00
(macro-error "Trying to call use-all without arguments")
2020-04-10 18:31:51 +03:00
(do
(eval (list 'use (car names)))
(if (= (length names) 1)
()
(use-all-fn (cdr names))))))
2017-12-12 17:08:33 +03:00
(defmacro use-all [:rest names]
2020-04-10 18:31:51 +03:00
(use-all-fn names))
2017-12-12 19:39:15 +03:00
2018-03-24 12:28:19 +03:00
(defmacro load-and-use [name]
2020-04-10 18:31:51 +03:00
(do
(eval (list 'load (str name ".carp")))
(eval (list 'use name))))
2018-03-24 12:28:19 +03:00
(defmacro comment [:rest forms]
())
2019-03-13 20:49:48 +03:00
(defndynamic build-vararg [func forms]
(if (= (length forms) 0)
(macro-error "vararg macro needs at least one argument")
(if (= (length forms) 1)
(car forms)
(list func (car forms) (build-vararg func (cdr forms))))))
(defmacro and* [:rest forms]
(build-vararg 'and forms))
(defmacro or* [:rest forms]
(build-vararg 'or forms))
(defmacro ignore [form]
(list 'let (array '_ form) (list)))
Make `doc` take a rest parameter of strings Carp preserves tabulation and other whitespace in strings, as it should. This sometimes results in awkward code indentation when it comes to long doc strings that exceed 80 characters. Often, one has to continue the string on a newline, but needs to avoid adding tabs to prevent Carp from rendering them in the output. This change alters the behavior of doc to take a series of strings as a rest parameter instead, allowing for neater organization in the source, for example, after this change the following long doc string for compose: ~~~ "Returns the composition of two functions `f` and `g` for functions of any arity; concretely, returns a function accepting the correct number of arguments for `g`, applies `g` to those arguments, then applies `f` to the result. If you only need to compose functions that take a single argument (unary arity) see `comp`. Comp also generates the form that corresponds to the composition, compose contrarily evaluates 'eagerly' and returns a computed symbol. For exmaple: ``` ;; a silly composition ((compose empty take) 3 [1 2 3 4 5]) ;; => [] (String.join (collect-into ((compose reverse map) Symbol.str '(p r a c)) array)) ;; => 'carp' ;; comp for comparison ((comp (curry + 1) (curry + 2)) 4) ;; => (+ 1 (+ 2 4)) ```" ~~~ becomes: ~~~ "Returns the composition of two functions `f` and `g` for functions of any" "arity; concretely, returns a function accepting the correct number of" "arguments for `g`, applies `g` to those arguments, then applies `f` to the" "result." "" "If you only need to compose functions that take a single argument (unary arity)" "see `comp`. Comp also generates the form that corresponds to the composition," "compose contrarily evaluates 'eagerly' and returns a computed symbol." "```" ";; a silly composition" "((compose empty take) 3 [1 2 3 4 5])" ";; => []" "" "(String.join (collect-into ((compose reverse map) Symbol.str '(p r a c)) array))" ";; => 'carp'" "" ";; comp for comparison" "((comp (curry + 1) (curry + 2)) 4)" ";; => (+ 1 (+ 2 4))" "```") ~~~ And the output remains the same; this just enables better alignment in the source file. The strings passed to doc are newline separated by default, but one can circumvent this behavior by passing a bool along with the string as follows: ~~~ (doc foo ("My amazing doc " false) "continues on one line." "" "And then another.") ~~~ The above doc string will result in the following output: ~~~ My amazing doc continues on one line. And then another. ~~~ Of course, the original behavior of doc also remains valid, so if one prefers to use the old indentation-mixed single string format, one still can! This change also reformats the doc strings in macro to utilize the new rest parameter and make the source a bit neater.
2020-10-01 18:41:05 +03:00
(doc const-assert
"Asserts that the expression `expr` is true at compile time."
"Otherwise it will fail with the message `msg`."
""
"The expression must be evaluable at compile time.")
2019-05-22 21:01:03 +03:00
(defndynamic const-assert [expr msg]
(if expr () (macro-error msg)))
2019-09-09 10:59:22 +03:00
Make `doc` take a rest parameter of strings Carp preserves tabulation and other whitespace in strings, as it should. This sometimes results in awkward code indentation when it comes to long doc strings that exceed 80 characters. Often, one has to continue the string on a newline, but needs to avoid adding tabs to prevent Carp from rendering them in the output. This change alters the behavior of doc to take a series of strings as a rest parameter instead, allowing for neater organization in the source, for example, after this change the following long doc string for compose: ~~~ "Returns the composition of two functions `f` and `g` for functions of any arity; concretely, returns a function accepting the correct number of arguments for `g`, applies `g` to those arguments, then applies `f` to the result. If you only need to compose functions that take a single argument (unary arity) see `comp`. Comp also generates the form that corresponds to the composition, compose contrarily evaluates 'eagerly' and returns a computed symbol. For exmaple: ``` ;; a silly composition ((compose empty take) 3 [1 2 3 4 5]) ;; => [] (String.join (collect-into ((compose reverse map) Symbol.str '(p r a c)) array)) ;; => 'carp' ;; comp for comparison ((comp (curry + 1) (curry + 2)) 4) ;; => (+ 1 (+ 2 4)) ```" ~~~ becomes: ~~~ "Returns the composition of two functions `f` and `g` for functions of any" "arity; concretely, returns a function accepting the correct number of" "arguments for `g`, applies `g` to those arguments, then applies `f` to the" "result." "" "If you only need to compose functions that take a single argument (unary arity)" "see `comp`. Comp also generates the form that corresponds to the composition," "compose contrarily evaluates 'eagerly' and returns a computed symbol." "```" ";; a silly composition" "((compose empty take) 3 [1 2 3 4 5])" ";; => []" "" "(String.join (collect-into ((compose reverse map) Symbol.str '(p r a c)) array))" ";; => 'carp'" "" ";; comp for comparison" "((comp (curry + 1) (curry + 2)) 4)" ";; => (+ 1 (+ 2 4))" "```") ~~~ And the output remains the same; this just enables better alignment in the source file. The strings passed to doc are newline separated by default, but one can circumvent this behavior by passing a bool along with the string as follows: ~~~ (doc foo ("My amazing doc " false) "continues on one line." "" "And then another.") ~~~ The above doc string will result in the following output: ~~~ My amazing doc continues on one line. And then another. ~~~ Of course, the original behavior of doc also remains valid, so if one prefers to use the old indentation-mixed single string format, one still can! This change also reformats the doc strings in macro to utilize the new rest parameter and make the source a bit neater.
2020-10-01 18:41:05 +03:00
(doc defdynamic-once "Creates a dynamic variable and sets its value if it's not already defined.")
2019-12-18 14:10:47 +03:00
(defmacro defdynamic-once [var expr]
2021-01-11 15:21:29 +03:00
(eval
(list 'if (list 'defined? var)
()
(list 'defdynamic var expr))))
2019-11-29 17:25:27 +03:00
Make `doc` take a rest parameter of strings Carp preserves tabulation and other whitespace in strings, as it should. This sometimes results in awkward code indentation when it comes to long doc strings that exceed 80 characters. Often, one has to continue the string on a newline, but needs to avoid adding tabs to prevent Carp from rendering them in the output. This change alters the behavior of doc to take a series of strings as a rest parameter instead, allowing for neater organization in the source, for example, after this change the following long doc string for compose: ~~~ "Returns the composition of two functions `f` and `g` for functions of any arity; concretely, returns a function accepting the correct number of arguments for `g`, applies `g` to those arguments, then applies `f` to the result. If you only need to compose functions that take a single argument (unary arity) see `comp`. Comp also generates the form that corresponds to the composition, compose contrarily evaluates 'eagerly' and returns a computed symbol. For exmaple: ``` ;; a silly composition ((compose empty take) 3 [1 2 3 4 5]) ;; => [] (String.join (collect-into ((compose reverse map) Symbol.str '(p r a c)) array)) ;; => 'carp' ;; comp for comparison ((comp (curry + 1) (curry + 2)) 4) ;; => (+ 1 (+ 2 4)) ```" ~~~ becomes: ~~~ "Returns the composition of two functions `f` and `g` for functions of any" "arity; concretely, returns a function accepting the correct number of" "arguments for `g`, applies `g` to those arguments, then applies `f` to the" "result." "" "If you only need to compose functions that take a single argument (unary arity)" "see `comp`. Comp also generates the form that corresponds to the composition," "compose contrarily evaluates 'eagerly' and returns a computed symbol." "```" ";; a silly composition" "((compose empty take) 3 [1 2 3 4 5])" ";; => []" "" "(String.join (collect-into ((compose reverse map) Symbol.str '(p r a c)) array))" ";; => 'carp'" "" ";; comp for comparison" "((comp (curry + 1) (curry + 2)) 4)" ";; => (+ 1 (+ 2 4))" "```") ~~~ And the output remains the same; this just enables better alignment in the source file. The strings passed to doc are newline separated by default, but one can circumvent this behavior by passing a bool along with the string as follows: ~~~ (doc foo ("My amazing doc " false) "continues on one line." "" "And then another.") ~~~ The above doc string will result in the following output: ~~~ My amazing doc continues on one line. And then another. ~~~ Of course, the original behavior of doc also remains valid, so if one prefers to use the old indentation-mixed single string format, one still can! This change also reformats the doc strings in macro to utilize the new rest parameter and make the source a bit neater.
2020-10-01 18:41:05 +03:00
(doc inline-c "Inlines some custom C code.")
(defmacro inline-c [name defcode :rest declcode]
(eval (list 'deftemplate name (list) defcode (if (empty? declcode) "" (car declcode)))))
2020-05-12 21:24:40 +03:00
2020-06-26 19:57:06 +03:00
(deftemplate bottom (Fn [] a) "$a $NAME()" "$DECL { abort(); }")
Make `doc` take a rest parameter of strings Carp preserves tabulation and other whitespace in strings, as it should. This sometimes results in awkward code indentation when it comes to long doc strings that exceed 80 characters. Often, one has to continue the string on a newline, but needs to avoid adding tabs to prevent Carp from rendering them in the output. This change alters the behavior of doc to take a series of strings as a rest parameter instead, allowing for neater organization in the source, for example, after this change the following long doc string for compose: ~~~ "Returns the composition of two functions `f` and `g` for functions of any arity; concretely, returns a function accepting the correct number of arguments for `g`, applies `g` to those arguments, then applies `f` to the result. If you only need to compose functions that take a single argument (unary arity) see `comp`. Comp also generates the form that corresponds to the composition, compose contrarily evaluates 'eagerly' and returns a computed symbol. For exmaple: ``` ;; a silly composition ((compose empty take) 3 [1 2 3 4 5]) ;; => [] (String.join (collect-into ((compose reverse map) Symbol.str '(p r a c)) array)) ;; => 'carp' ;; comp for comparison ((comp (curry + 1) (curry + 2)) 4) ;; => (+ 1 (+ 2 4)) ```" ~~~ becomes: ~~~ "Returns the composition of two functions `f` and `g` for functions of any" "arity; concretely, returns a function accepting the correct number of" "arguments for `g`, applies `g` to those arguments, then applies `f` to the" "result." "" "If you only need to compose functions that take a single argument (unary arity)" "see `comp`. Comp also generates the form that corresponds to the composition," "compose contrarily evaluates 'eagerly' and returns a computed symbol." "```" ";; a silly composition" "((compose empty take) 3 [1 2 3 4 5])" ";; => []" "" "(String.join (collect-into ((compose reverse map) Symbol.str '(p r a c)) array))" ";; => 'carp'" "" ";; comp for comparison" "((comp (curry + 1) (curry + 2)) 4)" ";; => (+ 1 (+ 2 4))" "```") ~~~ And the output remains the same; this just enables better alignment in the source file. The strings passed to doc are newline separated by default, but one can circumvent this behavior by passing a bool along with the string as follows: ~~~ (doc foo ("My amazing doc " false) "continues on one line." "" "And then another.") ~~~ The above doc string will result in the following output: ~~~ My amazing doc continues on one line. And then another. ~~~ Of course, the original behavior of doc also remains valid, so if one prefers to use the old indentation-mixed single string format, one still can! This change also reformats the doc strings in macro to utilize the new rest parameter and make the source a bit neater.
2020-10-01 18:41:05 +03:00
(doc unreachable
"Asserts that a block of code will never be reached. If it is"
"the program will be aborted with an error message.")
2020-06-23 13:19:14 +03:00
(defmacro unreachable [msg]
(list 'do
(list 'IO.println
(list 'ref
(list 'fmt "%s:%d:%d: %s"
(eval (list 'file msg))
(eval (list 'line msg))
(eval (list 'column msg))
msg)))
2020-06-23 13:26:53 +03:00
(list 'System.abort)
2020-06-26 19:57:06 +03:00
(list 'bottom)))
2020-08-25 12:58:20 +03:00
(defmacro save-docs [:rest modules]
;; A trick to be able to send unquoted symbols to 'save-docs'
(eval (list 'save-docs-internal (list 'quote modules))))
2020-05-12 21:24:40 +03:00
(defndynamic implement-declaration [mod interface]
(list 'implements interface (Symbol.prefix mod interface)))
2020-05-12 21:24:40 +03:00
(doc implements-all
"Declares functions in mod with names matching `interfaces` as implementations"
"of those interfaces.")
(defmacro implements-all [mod :rest interfaces]
(cons 'do (map (curry implement-declaration mod) interfaces)))