diff options
Diffstat (limited to 'src/jester/operators/lambdas.clj')
-rw-r--r-- | src/jester/operators/lambdas.clj | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/jester/operators/lambdas.clj b/src/jester/operators/lambdas.clj new file mode 100644 index 0000000..2243809 --- /dev/null +++ b/src/jester/operators/lambdas.clj @@ -0,0 +1,78 @@ +(ns jester.operators.lambdas + (:require [jester.types :refer [type-variable]]) + (:require [jester.expansion :refer [with-type + expand-use + define-simple-operator + define-syntax + with-temporary-parameter-type + *operators* + *syntax* + operator-type]])) + +(defn ^:private expand-fn [args body] + (let [args-vars (mapv #(do % (type-variable)) args) + body-var (type-variable)] + (letfn [(binding-params [args vars f] + (if (empty? args) + (f) + (with-temporary-parameter-type [(first args) (first vars)] + (binding-params (rest args) (rest vars) f))))] + (with-type `(fn [~@args] + ~(binding-params args args-vars #(expand-use body body-var))) + `(-> ~args-vars ~body-var))))) + +(define-syntax fn [[& args] body] + (expand-fn args body)) + +(define-syntax fn* [[& args] body] + (expand-fn args body)) + +(define-syntax var [name] + (when-not (symbol? name) + (throw (ex-info (str "Var name must be a symbol, not " (pr-str name)) + {:invalid-name name}))) + (if (contains? *operators* name) + (if-let [operator (get *operators* name)] + (with-type (:name operator) + (operator-type operator))))) + +(defmacro call [f & args] + (cons f args)) + +(define-simple-operator call + (∀ [args return] (-> [(-> args return) & args] return))) + +(define-simple-operator apply + (∀ [args return] (-> [(-> args return) args] return))) + +(define-simple-operator apply1 clojure.core/apply + (∀ [arg1 args return] (-> [(-> [arg1 & args] return) arg1 args] return))) + +(define-simple-operator apply2 clojure.core/apply + (∀ [arg1 arg2 args return] (-> [(-> [arg1 arg2 & args] return) arg1 arg2 args] return))) + +(define-simple-operator apply3 clojure.core/apply + (∀ [arg1 arg2 arg3 args return] (-> [(-> [arg1 arg2 arg3 & args] return) arg1 arg2 arg3 args] return))) + +(define-simple-operator map + (∀ [a b] (-> [(-> [a] b) (list a)] (list b)))) + +(define-simple-operator filter + (∀ [a] (-> [(-> [a] boolean) (list a)] (list a)))) + +(define-simple-operator remove + (∀ [a] (-> [(-> [a] boolean) (list a)] (list a)))) + +(define-simple-operator reduce + (∀ [item result] (-> [(-> [result item] result) result (list item)] result))) + +(defn zip [as bs] + (map vector as bs)) + +(define-simple-operator zip + (∀ [a b] (-> [(list a) (list b)] (list [a b])))) + +(define-simple-operator zip1 jester.operators.lambdas/zip + (∀ [x1 y1] (-> [[x1] [y1]] [[x1 y1]]))) +(define-simple-operator zip2 jester.operators.lambdas/zip + (∀ [x1 x2 y1 y2] (-> [[x1 x2] [y1 y2]] [[x1 y1] [x2 y2]]))) |