Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replacement require-macros form #37

Merged
merged 1 commit into from
Mar 15, 2018
Merged

Replacement require-macros form #37

merged 1 commit into from
Mar 15, 2018

Conversation

technomancy
Copy link
Collaborator

After some discussion on the #fennel freenode channel it was
observed that the current macro and special calls could be
problematic on larger codebases because they are global.

I started thinking about what a macro system would look like which
used the existing module system and didn't affect global compiler
state, and I came up with the require-macros form.

;; main.fnl
(require-macros "mymacros")

(defn add-seven-then-multiply-by-a-hundred [x]
  (-> x (+ 7) (* 100)))

(print add-seven-then-multiply-by-a-hundred 93)
;; mymacros.fnl
{"->" (fn [val ...]
        (each [_ elt (pairs [...])]
          (table.insert elt 2 val)
          (set elt.n (+ 1 elt.n))
          (set val elt))
        val)
 "defn" (fn [name args ...]
          (list (sym "set") name
                (list (sym "fn") args ...)))}

This allows you to import macros just for the scope of a single file
(or if you really want to, for the scope of a single function). The
mymacros.fnl file would be loaded in the same kind context as
eval-compiler currently works.

I think it's comprehensive enough that it could replace the existing
macro, special, and eval-compiler forms, but I'll admit I
haven't thought thru the implications of that fully. Maybe special
and eval-compiler are still needed in some contexts?

What do you think?

@technomancy technomancy mentioned this pull request Mar 15, 2018
@bakpakin
Copy link
Owner

I think this a good start. I have never liked the clojurescript idea of require-macros, but it does keep macros modular. I would eventually like require-macros to look more like normal fennel.

I think that the macro/extension system is overly complicated, but I think I would like to keep eval-compiler no matter what. While not often needed, it can be used to extend the compiler in pretty much arbitrary ways.

Perhaps the special special form could be dropped though.

@bakpakin bakpakin merged commit 76dd2f7 into master Mar 15, 2018
@technomancy technomancy deleted the require-macros branch March 15, 2018 21:45
@technomancy
Copy link
Collaborator Author

technomancy commented Mar 16, 2018 via email

@bakpakin
Copy link
Owner

Can you go into more detail here? As far as I'm concerned the modules
loaded by require-macros are normal Fennel; the only difference is a
few extra entries in the environment, which is the same as how
eval-compiler works.

I was thinking more along the lines of looking like common lisp, with a defmacro kind of syntax, but with lexical scoping. I guess originally I had envisioned macros and functions living along side one another in the same file, but that was never set in stone.

Something like:

(do
  (defmacro mymac [x] (list (sym "if") x x))
  (mymac :hi))

Which would expand to

(do
  (if :hi :hi))

Without modifying the environment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants