Guile (http://www.gnu.org/software/guile/guile.html) is trying to become a universal extension language - one can (in theory) write parsers for other languages in it; that way, a program that uses Guile as its extension language can also be programmed in those other languages.
It is almost a travesty that there's no readily-available CGI library that'll run as-is on Guile. There's not even a downloadable block of code to insert in your Guile/CGI scripts.
Oh well, a perl script that outputs an associative array from form input, and a bash script to pipe them together is a decent workaround, but I hate having to use two non-reusable scripts when one will do.
I guess this should eventually go to GuileCgiScripting.
Guile 2.0 includes an HTTP server: http://www.gnu.org/software/guile/manual/html_node/Web-Server.html
The problem with the original vision of Guile as the ultimate protean scripting language is that this problem has been solved, and arguably much better, by MicrosoftDotNet and the MonoProject.
It may be "better" but there's the big problem of Microsoft's IP all over it. Also, it has been alleged that DotNet's VM design doesn't work well for dynamically typed languages; although the IronPython guys say that's false. A bigger problem with Guile is that not many people like to work in Lisp/Scheme.
I still use Guile often because the SchemeLanguage is, to me, much easier to work in for quick jobs than the alternatives (Perl, Python, Ruby, etc.) and because Guile is a "workhorse Scheme" with strong ties to the underlying Unix environment. -- JeffRead
Old versions of Guile had two interesting features which I didn't see in other Scheme implementations. First, macros are first class objects. (This is quite a unique thing not only within the Scheme club, but within the whole Lisp family, I'd guess.) So, for example, a function can return a macro, or (given that you define "unless" as a macro) you can write code like
(for-each (lambda (macro) (macro condition (branch1) (branch2))) (list if unless))- this would execute both of "branch1" and "branch2", such that the order of execution is determined by "condition". You can create anonymous macros as well. Second, in Guile you can create local binding objects at any point, and use them with "eval". -- CsabaHenk?
I don't think the behavior you are describing is specific to Guile. In CommonLisp, one can access the macro expansion function of a macro using the macro-function accessor; e.g., (macro-function 'unless). A macro expansion function is just a plain old function that, when applied to a form and an environment, computes the macro expansion of the form in the environment. So you can pass around this function and apply it to forms to compute their expansions; one can then, of course, use eval to evaluate these expansions. Thus, since functions are FirstClass in CommonLisp, macros are as well. One can create "anonymous macros" just by using lambda to create macro expansion functions. I don't know what a "local binding object" is though.
By a "binding object" I mean an object which represents a binding, or as you say, environment (I think we can use here binding and environment as synonyms here). By "local" I mean that it captures the current lexical environment. In Guile you can do the following:
(define x 0) (define clo (let ((x 1)) (lambda () '()))) (local-eval 'x (procedure-environment clo)) => 1You can use (define env (let ((x 1)) (the-environment))) and (local-eval 'x env) here. And when you are really, really crazy, you can define them as
(define (my-local-eval form env) (call-with-current-continuation (lambda (x) (env (list x form))))) (define-macro (my-the-environment) (call-with-current-continuation (lambda (x) x)))In this case, my-the-environment provides a hop back into the macro expander in the lexical scope of its call, and when the evaluation commences, it hops back out after getting the form evaluated. Your mileage when using this gotesque contraption may vary. As a rather surprising data point, GuileV1 works with basic use cases. -- dak
By R5RS, the stock "eval" also has an optional second environment argument, but it doesn't require that there should be a way for capturing lexical environments in objects. You could be fooled by the optional procedure "interaction-environment", but in all Schemes I've seen it behaves as follows:
(define x 0) (define env (let ((x 1)) (interaction-environment))) (eval 'x env) => 0To be able to do the trick you've mentioned you can do in CommonLisp, you not only need to have a way to get the expander of a macro, but also you need to have local environments. See the CommonLisp example:
(defmacro foom () 'x) (setq x 0) (foom) => 0 (let ((x 1)) (foom)) => 1 (let ((x 1)) (eval 'x)) => 0That is, the expander is evaluated in the current lexical context. So, to be able to make use of the expander, you need to have a way to evaluate in an arbitrary environment, and also a way to capture lexical environments. But the R5RS spec doesn't give you a way to do this, and I haven't seen a Scheme other than Guile which implements such a thing (I haven't seem all Schemes, though).
Common Lisp doesn't capture lexical environments, either. EVAL only has access to the dynamic environment; CL doesn't have lexical global variables, so LET is creating a dynamic binding for the global variable X, which is implicitly declared special.
So, considering CommonLisp: if you have local binding objects there, yes, you can use macros as first-order objects, along the lines you've shown. (Although you must admit the Guile way is much more sugared. Yes, I know you can sugar it in CommonLisp if you want.)
I'd be happy to see an example how to create and use local binding objects in CommonLisp, because I'm not familiar with that language. -- CsabaHenk?