Hacker News new | ask | show | jobs
by lispm 2553 days ago
> One strange Lisp variant is Mathematica

I wouldn't call Mathematica a Lisp, given that it is a runtime rewrite system and not based on a defined evaluator (which also makes Lisp relatively easy to compile and also compilable to relatively efficient code).

> That way you could define both a macro and function version of a symbol if they both make sense.

There is a variant of that in CL called 'compiler macro'.

> The utility of two namespaces seems to be than when Lisps were dynamically scoped

One still has the same problems with global symbols in Scheme.

   (define (foo list) (list list))
Here the parameter variable LIST shadows the global function LIST.
2 comments

> Mathematica

It's derived from Wolfram's conception of Macsyma, and it is designed so that all code is made out of numbers, strings, symbols, and arrays (sure, not cons cells). I guess it's nice to know you wouldn't call Mathematica a Lisp, but I didn't say it was strictly in the Lisp family, just a strange variant. (Does this mean you do not consider PicoLisp a Lisp either, since it is not really compilable, as far as I can see? Or is it fine to you because it has a defined evaluator?)

Mathematica does have a built-in compiler, but granted it is unclear exactly what subset of the language it is compiling.

> There is a variant of that in CL called 'compiler macro'.

I am aware, but that certainly does not have the same effect because CL is not required to invoke your compiler macro. This means you cannot rely on compiler macros for control flow manipulations, like what 'and' requires. (I know you said "variant," but they are more of an optimization than what I was talking about.)

> (define (foo list) (list list))

As I said, with lexical scoping "this became a bit less of an issue." What I had in mind is that at least any of these kinds of shadowing errors will be entirely local. You won't have the problem that by using 'list' as the name of an argument, if it were dynamically bound in a Lisp-1 it would mess up any function you might call that itself uses 'list'. Lexical scoping at least prevents this spooky action at a distance that you would need a Lisp-2 to prevent under dynamic scoping.

> I guess it's nice to know you wouldn't call Mathematica a Lisp,

Thanks!

> but I didn't say it was strictly in the Lisp family, just a strange variant.

Right, that was my point, I don't consider term rewriting systems as Lisp variants, even though they may have numbers and strings as data types. The actual execution engine is too different.

Fexprs had the interesting property that it sees the actual source at runtime (which makes it very different from lazy evaluation or wrapping things in lambdas), which appeals especially to users/implementors of computer algebra systems (see Reduce written in Portable Standard Lisp, which provides Fexprs) or other math software dealing with formulas (like R, which has a feature similar to fexprs).

> Mathematica does have a built-in compiler, but granted it is unclear exactly what subset of the language it is compiling.

From what I read of its very unspecific documentation, I doubt that it does the term rewriting at compile time (like Lisp does macro expansion at compile time) - does it? To me it looks like the compiler targets numeric code and basic control flow...

They probably have better documentation of their language implementation, internally. Or is there an externally available document, which actually describes their implementation?

Mathematica as a rewrite language

https://www3.risc.jku.at/publications/download/risc_342/1996...

I fixed that in TXR Lisp. Macro bindings and function bindings in the global namespace are separate and coexist. The mboundp predicate is provided for testing for a macro binding, which can be undone with mmakunbound, analogous to fmakunbound

https://www.nongnu.org/txr/txr-manpage.html#N-0384A294

TXR comes with function complements of if and and and some others.

  1> (and (prinl 'foo) nil (prinl 'bar))
  foo
  nil
  2> (mapcar 'and '(nil t nil t) '(nil nil t t ))
  (nil nil nil t)
Unsurprisingly, TXR Lisp has no compiler macros. If you want to speed up a function using a macro, then just write a same-named macro.

TXR Lisp macros can decline to expand by returning an output that is eq to their input. If a macro declines to expand, and a function exists, then that form will be treated as a call to that function, naturally.

When a TXR Lisp lexical macro declines to expand, then a same-named macro in an outer scope (or else the global environment) is thereby effectively unshadowed and gets an opportunity to expand the input. This is very useful and exploited in the implementation of tagbody, which it simplifies. http://www.kylheku.com/cgit/txr/commit/share/txr/stdlib/tagb...