> A fexpr is a function whose operands are passed to it without being evaluated. When a fexpr is called, only the body of the fexpr is evaluated; no other evaluations take place except when explicitly initiated by the fexpr.
> A fexpr is a function whose operands are passed to it without being evaluated. When a fexpr is called, only the body of the fexpr is evaluated; no other evaluations take place except when explicitly initiated by the fexpr.
If a language has fexpr semantics, you can for instance implement both macros and "normal" functions (among many other things) in very similar ways, since the only difference is that a normal function will first evaluate its arguments and then use the results of evaluation, whereas a macro may not do that (or may conditionally evaluate them!).
Hope that helps a little...
If your interpreter processes special forms by looking up the operator symbol in a table and calling a retrieved function, that's an fexpr.
If the application can wire its own entries into that table, then it can extend the language with new special forms.
The original terminology in LISP was that the FSUBR was a machine-language coded special operator. When the program wired its own interpreted funtion to create a new operator, that was a called FEXPR.
FEXPR is an extension of the interpreter which is itself an interpreted function. The name probably alludes to the FEXPR containing a body of expressions that must be evaluated. Whereas the machine language analog, the FSUBR, is a pure subroutine: the interpreter isn't required to process expressions inside it (though of course it calls the interpreter, as necessary).
Command: (zl:defun my-if zl:fexpr (form) (list :my-if form))
MY-IF
Command: (my-if (> a b) a b)
(:MY-IF ((> A B) A B))
Thus one can see that the original source of the arguments is bound to the symbol FORM as a list.A more recent language with FEXPRs seems to be the language R.
[1] http://www.lispworks.com/documentation/HyperSpec/Body/s_eval...
Macros and other special forms must appear in their own name when they are called. You can't necessarily bind them to a symbol and then use that symbol in its place with the same behavior.
Consider a symbol which could represent some abstract "binary function", which you might later call. You can bind functions like `add` and `mul` to this without trouble, but if you try to bind `and` or `or` to it, you might not be able to (depending on which lisp you are using). You could try to wrap the call to `and` in a function, like `(define (and* x y) (and x y))`, but this `and*` does not actually have the correct behavior, because `y` should not be evaluated if `x` evaluates to `#f` - but being a function, both arguments are evaluated implicitly.
If using fexprs, this issue is non-existent. `and` and `or` are simply defined as fexprs, are first-class, and their operands are not implicitly evaluated.
Yes, with fexprs, functions can serve as (runtime-evaluated) macros. REBOL used this (though they aren't call fexprs in REBOL) so that its functions could also serve the role of Lisp macros, and it was pretty awesome. It’s too bad that REBOL became such a dead end for nontechnical reasons.
(defun if (bool @then @else)
(cond (bool (eval @then)))
(t (eval @else))))e.g. if you have x and y in the environment as variables, and call your fexpr with (max x y) as the single argument called m: (myfexpr (max x y))
In haskell, m is not calculated (i.e. "max" is not run, nor x or y consulted) until "used". But the function doesn't "know" that it's max that's waiting to run, just that m is available if needed.
In a fexpr, you get something like a macro does, so you can see '(max x y) if you care to examine m, and you must call (eval m) to get the answer, but you could theoretically decide to do something else, like form a new expression if you walk m and make a decision based on the code itself (i.e. that it's a call to "max").