- I don't get lisp's (lisp-2) dynamic scoping (a big reason I haven't switched from vim to emacs). I'm much more comfortable with the lexical scoping of scheme (lisp-1).
- I don't get big schemes (like R6RS). For a while, I thought of my own implementation of R5RS. But I've heard R7RS is pretty much R5RS with improvements. So R7RS it is.
- But I'd like to have macros. I wonder if R7RS has macros.
- Mainly interested in crazy metaprogramming and logic/relational experiments using Friedman/Byrd school of thought (reasoned schemer, minikanren, constraint kanren, that sort of stuff).
- Finally instead of rolling my own from scratch, I've heard I could use something like chibi as a starting point (additional points since chibi is implemented in C).
> - I don't get lisp's (lisp-2) dynamic scoping (a big reason I haven't switched from vim to emacs). I'm much more comfortable with the lexical scoping of scheme (lisp-1).
Lisp-1/2 has to do with functions and other identifiers living in separate namespaces. So in a Lisp 2 requires special functions that live in the function namespace to call functions that exist as a local variable, (i.e. funcall or apply in Common Lisp)
If you're having a hard time coming to terms with dynamic scoping (and I think most Lispers don't like it) and you're interested in metaprogramming, try writing a macro in a dynamically-scoped lisp that lets you use lexical scoping. This is kind of a fun exercise and you can do it in Elisp.
I used to be interested in Lisp - in particular Clojure - for metaprogramming and mini-kanren mostly - so you're mindset reminds me of my own. But I realized I could get much the same thing as metaprogramming with data-oriented programming, or making an interpreted language to do what I needed. The performance of raw native code is comparable in some cases. Where that fails, you could theoretically use Perl or Python to generate C code that just has to be performant but is very repetitive. The benefit of that is that mere mortals will understand what you're doing better, and you're not forced to bear the burden of a garbage collected runtime.
> - I don't get lisp's (lisp-2) dynamic scoping (a big reason I haven't switched from vim to emacs). I'm much more comfortable with the lexical scoping of scheme (lisp-1).
"Dynamic vs lexical scope" doesn't have anything to do with "Lisp-1 vs Lisp-2". "Lisp-1 vs Lisp-2" is about whether function values are distinguishable from "defun"-defined functions. "Dynamic vs lexical scope" is about whether variable name-resolution is done based on the lexical scope stack, or the call stack.
You can enable lexical scoping in Elisp files by starting them with:
I think you might really like s7 Scheme. Full TCO, mostly R5RS, and full Common Lisp style macros with keywords, gensyms and first class environments. And it embeds in C in a snap. I'm using it for Scheme For Max and loving it. Based on what you're saying I think it might hit the sweet spot for you.
I don't know about elisp, but common lisp uses primarily lexical scoping. If you ignore ‘defparameter’/‘defvar’, then you'll be living exclusively in lexical scoping land.
> I'd like to have macros. I wonder if R7RS has macros
R7RS only specifies hygienic macros, but unhygienic macros are a commonly implemented extension. They aren't present in chibi scheme, but you find chicken scheme[0] or s7 scheme[1] interesting.
Chibi has explicit renaming macros. If you really want less hygiene than that, you can implement defmacro on top of er-macro-transformer.
Edit: er-macro-transformer IS unhygienic unless you tell it otherwise, much like gensym, except all renamed bindings introduced in the same macro invocation are the same. Gensym is of course available as well
Dynamic scope in Clojure is a key way to model supervised local side effects (side reads and side mutations) in a tightly controlled way while ensuring that the expression as a whole remains referentially transparent and the effect behaviors are late bound. If you are into crazy metaprogramming, this is pretty important imo. The only other way to model effects that I know of is monads which involve lots of opaque closures, which block metaprogramming. Code-as-data captures a lot of static information about your program which monads lose.
I have very little interest in the ML family (well, let's just say that my interest in ML is in a different part of my brain that I don't want interfering with my thinking/exploration about systems like lisp/scheme and what kind of metaprogramming can be done with them).
I guess I'll have to think about dynamic-scoping a little more.
I mean once you have a function object instance, you've lost the source code, you can't know anything about what it does (beyond the type) except what you can glean by running it.
Emacs Lisp is a rare case of being in certain ways older than Scheme.
Common Lisp, which is the main representative of Lisp-2 family, is firmly in lexical scoping, which is what enabled the example in the linked article. It also has wild unrestricted macros, and much more stable language (less redoing work when moving from implementation to implementation, especially if you use wrapper libs around stuff outside standard library)
- I don't get big schemes (like R6RS). For a while, I thought of my own implementation of R5RS. But I've heard R7RS is pretty much R5RS with improvements. So R7RS it is.
- But I'd like to have macros. I wonder if R7RS has macros.
- Mainly interested in crazy metaprogramming and logic/relational experiments using Friedman/Byrd school of thought (reasoned schemer, minikanren, constraint kanren, that sort of stuff).
- Finally instead of rolling my own from scratch, I've heard I could use something like chibi as a starting point (additional points since chibi is implemented in C).
Comments?