Carp/core/Macros.carp

808 lines
26 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))))))
(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)))))
(doc implements? "Does `function` implement `interface`?")
(defmacro implements? [interface function]
(eval (list 'any? (list 'fn (array 'x) (list '= 'x interface)) (list 'meta function "implements"))))
(defmodule Dynamic
2019-03-13 20:49:48 +03:00
(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)))))
2019-11-09 14:52:11 +03:00
(defndynamic cxr [x pair]
(if (= (length x) 0)
(list 'quote pair)
(list
(if (= 'a (cadr x))
'car
(if (= 'd (cadr x))
'cdr
(macro-error "`cxr` expects either `a` or `d` symbols, got " (cadr x))))
(if (= 1 (car x))
(cxr (cddr x) pair)
(cxr (cons (- (car x) 1) (cdr x)) pair)))))
(defndynamic nthcdr [n pair]
(cxr (list (+ n 1) 'd) pair))
2019-11-09 14:52:11 +03:00
(defndynamic nthcar [n pair]
(cxr (list 1 'a n 'd) pair))
2019-03-13 20:49:48 +03:00
(defndynamic eval-internal [form]
(list 'do
(list 'defn 'main [] (list 'IO.println* form))
(list 'build)
(list 'run)))
2020-03-09 17:50:52 +03:00
(defmacro evaluate [form]
(eval-internal form))
(defmacro e [form]
(eval-internal form))
2019-09-17 20:34:34 +03:00
(defndynamic collect-into-internal [xs acc f]
(if (= 0 (length xs))
acc
(collect-into-internal (cdr xs) (append acc (f (car xs))) f)))
2020-04-10 17:04:44 +03:00
(doc collect-into
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
"Transforms a dynamic data literal into another, preserving order")
(defndynamic collect-into [xs f]
(collect-into-internal xs (f) f))
(doc empty?
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
"Returns true if the provided data literal is empty, false otherwise.")
(defndynamic empty? [xs]
(= 0 (length xs)))
2020-04-19 18:43:10 +03:00
(doc flip
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
"Flips the arguments of a function `f`."
"```"
"((flip Symbol.prefix) 'Bar 'Foo)"
"=> (Foo.Bar)"
"```")
(defndynamic flip [f]
(fn [x y]
(f y x)))
(doc compose
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
"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))"
"```")
(defndynamic compose [f g]
;; Recall that **unquoted** function names evaluate to their definitions in
;; dynamic contexts, e.g. f = (dyanmic f [arg] body)
;;
;; Right now, this cannot handle anonymous functions because they cannot be passed to apply.
;; and not anonymous functions.
;; commands expand to (command <name>), fns expand to a non-list.
;;
;; TODO: Support passing anonymous functions.
2020-05-05 15:04:09 +03:00
(if (not (or (list? f) (list? g)))
(macro-error "compose can only compose named dynamic functions. To
compose anonymous functions, such as curried functions,
see comp.")
(let [f-name (cadr f)
g-name (cadr g)
arguments (caddr g)]
(list 'fn arguments
;; Since we call an eval to apply g immediately, we wrap the args in an
;; extra quote, otherwise, users would need to double quote any sequence of
;; symbols such as '(p r a c)
(list f-name (list 'eval (list 'apply g-name (list 'quote arguments))))))))
2020-04-19 18:43:10 +03:00
(doc curry
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
"Returns a curried function accepting a single argument, that applies `f` to `x`"
"and then to the following argument."
""
"```"
"(map (curry Symbol.prefix 'Foo) '(bar baz))"
"=> (Foo.bar Foo.baz)"
"```")
(defndynamic curry [f x]
(fn [y]
(f x y)))
(doc curry*
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
"Curry functions of any airity."
""
"```"
"(map (curry* Dynamic.zip + '(1 2 3)) '((4 5) (6)))"
"=> (((+ 1 4) (+ 2 5)) ((+ 1 6)))"
""
"((curry Dynamic.zip cons '(1 2 3)) '((4 5) (6)))"
"=> ((cons 1 (4 5)) (cons (2 (6))))"
""
"(defndynamic add-em-up [x y z] (+ (+ x y) z))"
"(map (curry* add-em-up 1 2) '(1 2 3))"
"=> (4 5 6)"
"```")
(defndynamic curry* [f :rest args]
(let [f-name (cadr f)
all-args (caddr f)
unfilled-args (- (length all-args) (length args))
remaining (take unfilled-args all-args)
;; Quote the arguments to retain expected behavior and avoid the need
;; for double quotes in curried higher-orders, e.g. zip.
quote-args (map quoted args)]
(list 'fn remaining
;; eval to execute the curried function.
;; otherwise, this resolves to the form that will call the function, e.g. (add-three-vals 2 3 1)
(list 'eval (list 'apply f-name (list 'quote (append quote-args (collect-into
remaining list))))))))
;; Higher-order functions can't currently accept primitives
;; For now, wrapping primitives in a function allows us to pass them
;; to HOFs like map.
(defndynamic quoted [x]
(list 'quote x))
(doc reduce
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
"Reduces or 'folds' a data literal, such as a list or array, into a single"
"value through successive applications of `f`.")
(defndynamic reduce [f x xs]
(if (empty? xs)
x
(reduce f (f x (car xs)) (cdr xs))))
(hidden unreduce-internal)
(defndynamic unreduce-internal [f x lim acc counter]
;; Currently only works with anonymous functions and named functions.
;; does not work with commands.
2020-05-05 15:04:09 +03:00
(if (not (or (array? acc) (list? acc)))
(macro-error
"Unreduce requires a dynamic data structure to collect results, such as
(list) or (array).")
(if (= counter lim)
acc
(unreduce-internal f (f x) lim (append acc (cons (eval (f x)) (empty acc))) (+ counter 1)))))
(doc unreduce
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
"Applies `f` to a starting value `x`, then generates a sequence of values"
"by successively applying `f` to the result `lim-1` times."
"Collects results in the structure given by `acc`."
""
"```"
"(unreduce (curry + 1) 0 10 (list))"
"=> (1 2 3 4 5 6 7 8 9 10)"
"```")
(defndynamic unreduce [f x lim acc]
(unreduce-internal f x lim acc 0))
(doc filter
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
"Returns a list containing only the elements of `xs` that satisify"
"predicate `p`."
""
"```"
"(filter (fn [x] (= 'a x)) '(a b a b a b a b))"
"=> (a a a a)"
"```")
(defndynamic filter [p xs]
(let [filter-fn (fn [x y] (if (p y) (append x (list y)) x))]
(reduce filter-fn (list) xs)))
(doc reverse
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
"Reverses the order of elements in an array or list."
""
"```"
"(reverse [1 2 3 4])"
"=> [4 3 2 1]"
"```")
(defndynamic reverse [xs]
(if (array? xs)
(reduce (flip append) (array) (map array xs))
(reduce (flip append) (list) (map list xs))))
(doc empty
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
"Returns the empty form of `xs`."
""
"```"
"(empty '(1 2 3 4))"
"=> ()"
"(empty '[1 2 3 4])"
"=> []"
"```")
(defndynamic empty [xs]
(if (array? xs)
(array)
(list)))
(doc take
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
"Returns a list containing the first `n` elements of a list."
""
"```"
"(take 3 '(1 2 3 4 5))"
"=> (1 2 3)"
"```")
(defndynamic take [n xs]
;; A more straightforward impl is likely more efficient?
(let [indicies (unreduce (curry + 1) 0 n (list))
result (map cadr (zip list xs indicies))]
(if (array? xs)
(collect-into result array)
result)))
(doc apply
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
"Applies the function `f` to the provided argument list, passing each value"
"in the list as an argument to the function.")
(defndynamic apply [f argument-list]
;; The let clause here is a tad mysterious at first glance. When passed a
;; standalone function name (i.e. not an application (f x), carp evaluates
;; it into the function's defining form, e.g. foo becomes (defn foo [x] x),
;; commands such as + become (command +) etc. ;; The binding here accounts
;; for that case, allowing users to pass the function name to apply
;; unquoted.
;;
;; This is necessary for parity across map-internal, zip, and apply.
;; Since map calls its function directly, it takes it as is. Apply, on the
;; other hand, would have to take the quoted form, since it builds a list
;; that serves as the actual application.
;;
;; This is problematic for the user facing map function, since it makes
;; calls to map or zip (which uses apply) as appropriate--unless we support
;; the quoted function name argument in map-internal or the unquoted one in
;; apply, we can't use zip and map-internal in map.
(if (not (list? f))
(f argument-list)
(let [function-name (list (cadr f))]
(if (array? argument-list)
(append function-name (collect-into argument-list list))
(append function-name argument-list)))))
2020-05-05 16:19:43 +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 any?
"Checks whether any of the elements in `xs` conforms to the predicate"
"function `f`."
""
"```"
"(any? (fn [x] (= 'a x)) '(a b c))"
"=> true"
"(any? (fn [x] (= 'a x)) '(e f g))"
"=> false"
"```")
2020-05-05 15:04:09 +03:00
(defndynamic any? [f xs]
(reduce (fn [acc x] (or acc (f x))) false xs))
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 all?
"Checks whether all of the elements in `xs` conform to the predicate"
"function `f`."
""
"```"
"(all? (fn [x] (< 1 x)) '(2 3 4))"
"=> true"
"(all? (fn [x] (< 1 x)) '(-1 0 1))"
"=> false"
"```")
2020-05-05 15:04:09 +03:00
(defndynamic all? [f xs]
(reduce (fn [acc x] (and acc (f x))) true xs))
2020-04-19 19:00:54 +03:00
(hidden zip-internal)
(defndynamic zip-internal [f forms acc]
2020-05-05 15:04:09 +03:00
(if (any? empty? forms)
acc
(zip-internal
f
(map-internal cdr forms (list))
(let [result (list (apply f (map-internal car forms (list))))]
(append acc result)))))
2020-04-19 18:57:30 +03:00
(doc zip
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
"Returns the *form* that results from applying a function `f` to each of"
"the values supplied in `forms`."
"If the members of a single form are exhuasted, the result of the"
"applications thus far is returned, and any remaining members in the other"
"forms are ignored."
""
"```"
"(zip + '(1 2 3) '(4 5 6))"
"=> ((+ 1 4) (+ 2 5) (+ 3 6))"
"```"
""
"It's important to note that zip operates on forms, and that the form"
"returned by zip may not be evaluable by itself. For instance, to actually"
"transform the result in the example above into something Carp can"
"evaluate, we need to wrap each member of the list in a `do`:"
""
"```"
"(append (list 'do) (zip + '(1 2 3) '(4 5 6)))"
"=> (do (+ 1 4) (+ 2 5) (+ 3 6))"
"(eval (append (list 'do) (zip + '(1 2 3) '(4 5 6))))"
"=> 9 ;; do returns the value of the last form in its body"
"```")
(defndynamic zip [f :rest forms]
(zip-internal f forms (list)))
(doc map
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
"Applies a function `f` to each element in the list or array `xs` and"
"returns a list dynamic data literal containing the result of the function"
"applications."
""
"```"
"'(map symbol? '(a b c))"
"=> (true true true)"
"'(map (curry + 1) '(1 2 3))"
"=> (2 3 4)"
"```")
(defndynamic map [f xs]
(map-internal f xs (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 flatten
"Flattens a list recursively."
""
"```"
"(flatten '(1 2 (3 (4))))"
"=> '(1 2 3 4)"
"```")
(defndynamic flatten [l]
(reduce (fn [acc x]
(if (list? x)
(append acc (flatten x))
(cons-last x acc)))
'()
l))
2020-03-09 17:50:52 +03:00
)
(defndynamic implement-declaration [mod interface]
(list 'implements interface (Symbol.prefix mod interface)))
(doc implements-all
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
"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)))
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))
2018-01-17 19:08:02 +03:00
(defmacro for [settings :rest body] ;; settings = variable, from, to, <step>
(if (> (length body) 1)
(macro-error "Warning: the body of the 'for' loop can only contain one expression")
2019-07-09 01:18:38 +03:00
(let [variable (car settings)
from (cadr settings)
to (caddr settings)
step (if (> (length settings) 3) (cadddr settings) 1)
comp (if (> (length settings) 4)
(cadddr (cdr settings))
(if (< step (- step step)) '> '<))
2019-07-09 01:18:38 +03:00
]
(list
'let (array variable from)
(list
'while (list comp variable to)
2019-12-18 14:10:47 +03:00
(list
2019-07-09 01:18:38 +03:00
'do
(if (= (length body) 0)
()
(if (list? body)
(car body)
body))
(list
'set! variable
(list '+ variable step))))))))
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
2020-02-14 17:32:05 +03:00
(defmacro doall [f xs]
(list 'for ['i 0 (list 'Array.length (list 'ref xs))]
(list f (list 'Array.unsafe-nth (list 'ref xs) 'i))))
2019-03-13 20:49:48 +03:00
(defndynamic foreach-internal [var xs expr]
2020-01-29 13:55:56 +03:00
(let [xsym (gensym-with 'xs)
len (gensym-with 'len)
i (gensym-with 'i)]
2020-01-29 13:55:56 +03:00
(list 'let [xsym xs
len (list 'Array.length xsym)]
(list 'for [i 0 len]
(list 'let [var (list 'Array.unsafe-nth xsym i)]
2020-01-29 13:55:56 +03:00
expr)))))
(defmacro foreach [binding expr]
(if (array? binding)
(foreach-internal (car binding) (cadr binding) expr)
(macro-error "Binding has to be an array.")))
2017-10-18 23:44:15 +03:00
2019-03-13 20:49:48 +03:00
(defndynamic thread-first-internal [xs]
(if (= (length xs) 2)
2017-10-18 23:44:15 +03:00
(if (list? (last xs))
(cons (caadr xs)
2017-10-18 23:44:15 +03:00
(cons (car xs)
(cdadr xs)))
(list (cadr xs) (car xs)))
2017-10-18 23:44:15 +03:00
(if (list? (last xs))
(append
(list
(car (last xs))
(thread-first-internal (all-but-last xs)))
2017-10-18 23:44:15 +03:00
(cdr (last xs)))
(list (last xs) (thread-first-internal (all-but-last xs))))))
2017-10-18 23:44:15 +03:00
2019-03-13 20:49:48 +03:00
(defndynamic thread-last-internal [xs]
(if (= (length xs) 2)
2017-10-18 23:44:15 +03:00
(if (list? (last xs))
(cons-last (car xs) (last xs))
(list (cadr xs) (car xs)))
2017-10-18 23:44:15 +03:00
(if (list? (last xs))
(cons-last (thread-last-internal (all-but-last xs)) (last xs))
(list (last xs) (thread-last-internal (all-but-last xs))))))
2017-10-18 23:44:15 +03:00
(defmacro => [:rest forms]
(thread-first-internal forms))
(defmacro ==> [:rest forms]
(thread-last-internal forms))
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)))
(defmacro freebsd-only [:rest forms]
(if (= "freebsd" (os))
(eval (cons (quote do) forms))
()))
2017-12-07 16:59:55 +03:00
(defmacro mac-only [:rest forms]
(if (= "darwin" (os))
2020-04-10 18:31:51 +03:00
(eval (cons (quote do) forms))
()))
2017-12-07 16:59:55 +03:00
(defmacro linux-only [:rest forms]
(if (= "linux" (os))
2020-04-10 18:31:51 +03:00
(eval (cons (quote do) forms))
()))
2017-12-07 16:59:55 +03:00
(defmacro windows-only [:rest forms]
2020-05-05 15:04:09 +03:00
(if (or (= "windows" (os)) (= "mingw32" (os)))
2020-04-10 18:31:51 +03:00
(eval (cons (quote do) forms))
()))
2017-12-12 17:08:33 +03:00
(defmacro not-on-windows [:rest forms]
2020-05-05 15:04:09 +03:00
(if (not (or (= "windows" (os)) (= "mingw32" (os))))
2020-04-10 18:31:51 +03:00
(eval (cons (quote do) forms))
()))
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
2017-12-12 19:39:15 +03:00
(defmacro when [condition form]
(list 'if condition form (list)))
2017-12-12 20:45:29 +03:00
(defmacro unless [condition form]
(list 'if condition (list) form))
2017-12-15 11:28:14 +03:00
(defmacro let-do [bindings :rest forms]
(list 'let bindings
(cons 'do forms)))
2019-04-30 22:42:34 +03:00
(defmacro while-do [condition :rest forms]
(list 'while condition
(cons 'do forms)))
(defmacro defn-do [name arguments :rest body]
2020-04-10 17:04:44 +03:00
(eval (list 'defn name arguments (cons 'do body))))
(defmacro comment [:rest forms]
())
(defmacro forever-do [:rest forms]
(list 'while true (cons 'do forms)))
2019-03-13 20:49:48 +03:00
(defndynamic case-internal [name xs]
(if (= (length xs) 0)
(list)
(if (= (length xs) 2)
(macro-error "case has even number of branches; add an else branch")
(if (= (length xs) 1)
(car xs)
(list 'if
(list '= name (car xs))
(cadr xs)
(case-internal name (cddr xs)))))))
(defmacro case [name :rest forms]
(case-internal name 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))
2019-03-13 20:49:48 +03:00
(defndynamic build-str* [forms]
(if (= (length forms) 0)
(list "")
(if (= (length forms) 1)
2019-05-27 19:05:44 +03:00
(list 'ref (list 'str (car forms)))
(list 'ref (list 'String.append (list 'ref (list 'str (car forms))) (build-str* (cdr forms)))))))
(defmacro str* [:rest forms]
2019-05-27 19:05:44 +03:00
(list 'copy (build-str* forms)))
(defmacro println* [:rest forms]
2019-05-27 19:05:44 +03:00
(list 'IO.println (build-str* forms)))
2018-03-11 16:53:50 +03:00
(defmacro print* [:rest forms]
2019-05-27 19:05:44 +03:00
(list 'IO.print (build-str* forms)))
2018-03-11 16:53:50 +03:00
(defmacro ignore [form]
(list 'let (array '_ form) (list)))
2018-03-27 11:51:16 +03:00
(defmacro save-docs [:rest modules]
2018-03-27 10:05:58 +03:00
;; A trick to be able to send unquoted symbols to 'save-docs'
2020-04-17 13:59:22 +03:00
(eval (list 'save-docs-internal (list 'quote modules))))
2019-05-20 07:08:09 +03:00
2019-07-09 01:18:38 +03:00
(defndynamic project-config [bindings]
2019-05-20 07:08:09 +03:00
(if (< (length bindings) 2)
(list)
(cons-last (project-config (cdr (cdr bindings))) (list 'do (list 'Project.config
(car bindings) (car (cdr bindings)))))))
(doc defproject "Define a project configuration.")
2019-07-09 01:18:38 +03:00
(defmacro defproject [:rest bindings]
2019-05-20 07:08:09 +03:00
(project-config bindings))
2019-05-22 21:01: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 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 *gensym-counter* "Is a helper counter for `gensym`.")
2019-09-09 10:59:22 +03:00
(defdynamic *gensym-counter* 1000)
(defndynamic gensym-local [x]
(Symbol.concat ['gensym-generated x]))
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 gensym-with "Generates symbols dynamically, based on a symbol name.")
2019-09-09 23:33:56 +03:00
(defndynamic gensym-with [x]
2019-09-09 10:59:22 +03:00
(do
2020-03-18 00:51:00 +03:00
(set! *gensym-counter* (inc *gensym-counter*))
(Symbol.concat [x (Symbol.from *gensym-counter*)])))
2019-09-09 23:33:56 +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 gensym "Generates symbols dynamically as needed.")
2019-09-09 23:33:56 +03:00
(defndynamic gensym []
(gensym-with 'gensym-generated))
2019-11-22 15:10:36 +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 until "Executes `body` until the condition `cnd` is true.")
2019-11-22 15:10:36 +03:00
(defmacro until [cnd body]
(list 'while (list 'not cnd)
body))
2019-12-18 14:10:47 +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]
(list 'if (list 'defined? var)
()
(list 'defdynamic var expr)))
2019-11-29 17:25:27 +03:00
(defndynamic comp-internal [sym fns]
(if (= (length fns) 0)
sym
(list (car fns) (comp-internal sym (cdr fns)))))
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 comp "Composes the functions `fns` into one `fn`.")
2019-11-29 17:25:27 +03:00
(defmacro comp [:rest fns]
(let [x (gensym)]
(list 'fn [x] (comp-internal x fns))))
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 declcode]
(list 'deftemplate name (list) (eval defcode) (eval declcode)))
2020-06-23 13:19:14 +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
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 doto
"Evaluates `thing`, then calls all of the functions on it and"
"returns it. Useful for chaining mutating, imperative functions, and thus"
"similar to `->`. If you need `thing` to be passed as a `ref` into `expressions`"
"functions, use [`doto-ref`](#doto-ref) instead."
""
"```"
"(let [x @\"hi\"]"
" @(doto &x"
" (string-set! 0 \o)"
" (string-set! 1 \y)))"
"```")
2020-08-25 12:58:20 +03:00
(defmacro doto [thing :rest expressions]
(let [s (gensym)]
(list 'let [s thing]
(cons-last
s
(cons 'do (map (fn [expr] (cons (car expr) (cons s (cdr expr)))) expressions))))))
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 doto-ref
"Evaluates `thing`, then calls all of the functions on it and"
"returns it. Useful for chaining mutating, imperative functions, and thus"
"similar to `->`. If you need `thing` not to be passed as a `ref` into"
"`expressions` functions, use [`doto`](#doto) instead."
""
"```"
"(doto-ref @\"hi\""
" (string-set! 0 \o)"
" (string-set! 1 \y))"
"```")
2020-08-25 12:58:20 +03:00
(defmacro doto-ref [thing :rest expressions]
(let [s (gensym)]
(list 'let [s thing]
(cons-last
s
(cons 'do
(map (fn [expr] (cons (car expr) (cons (list 'ref s) (cdr expr))))
expressions))))))