Lisp creates lisp

I've heard a lot that writing a function in lisp will yield a function equivalent to any of the built in operators, therefore it is entirely possible to re-create any of the built in operators using lisp code. However, this can't be done in C because of its syntax rules. But if C did use prefix notation then I don't see a reason why you couldn't re-create any of the built in operators using C code. So basically what I am wondering is if it is prefix notation alone that makes this claim true in lisp or is there something deeper going on here that I am not seeing clearly?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

The immediate point is that

The immediate point is that all Lisp function calls look the same syntactically: there is no visible difference between (+ a b) and (foo a b) corresponding to the C distinction between a + b and foo(a, b).

The deeper point is that because Lisp code is uniformly constructed, and has a one-to-one correspondence with built-in Lisp objects (namely symbols and pairs/conses), it is straightforward to (a) process code at run time, and (b) to run user-specified transformer programs (called macros, but not to be confused with C macros) at compile time. That is what makes Lisp the programmable programming language.

Lisp objects not directly representable in source code

Common Lisp at least also has self-evaluating objects that can be passed to EVAL but have no direct representation in source code (i.e. don't have a canonical way to be printed readably). Examples are readtables, structures, CLOS objects, etc. Emacs Lisp is much the same: buffers, windows, etc evaluate to themselves but can't be represented in source code.

What's the Scheme take on this? I probably need a Scheme refresher course because I honestly don't remember whether it has EVAL or not.


eval was introduced to scheme in R5RS.

(I actually found out that when reading a critique of R5RS on the MIT scheme page)

Not the Language, the Implementation

Being able to rewrite built in operators is a feature of the language implementation, not the language (or the syntax rules as you stated in your question). Most LISP systems are designed to be highly configurable and would allow for such major modifications at runtime by the program.

C systems are much less dynamic and do not allow those types of modifications at run time. Technically, you can rewrite the built ins in C, but that means hacking the compiler which is a separate program (generally written in C) and not the actual program you are writing. This is a different type of operation, although similarly equivalent and much less convenient than if the system is designed to support it.

LISP systems were designed for dynamic programming and flexibility, and although most of the time redefining + is a "bad idea", especially when working on a large project with many programmers, like the niche C eventually too over in history. But sometimes, on programs written by single developers with an extensive understanding of the complete system, such language modification abilities were a practical requirement at times.

So, syntax has nothing to do with it. :)

Implementation vs. language spec

I don't see how being able to rewrite built in operators is an implementation feature when the language spec does not give any instructions on how to include it or what the expected behaviour is.

If you wrote a C that included reflection as part of its implementation, I would argue that it isn't C anymore. It may share the same syntax and some of the behaviour, but it wouldn't conform to the C language spec exactly.

This is from the Scheme R5RS spec,

This chapter describes Scheme's built-in procedures. The initial (or ``top level'') Scheme environment starts out with a number of variables bound to locations containing useful values, most of which are primitive procedures that manipulate data. For example, the variable abs is bound to (a location initially containing) a procedure of one argument that computes the absolute value of a number, and the variable + is bound to a procedure that computes sums. Built-in procedures that can easily be written in terms of other built-in procedures are identified as ``library procedures''.

A program may use a top-level definition to bind any variable. It may subsequently alter any such binding by an assignment (see 4.1.6). These operations do not modify the behavior of Scheme's built-in procedures. Altering any top-level binding that has not been introduced by a definition has an unspecified effect on the behavior of the built-in procedures.

So it's up to the implementation to specify what will happen when you try to re-assign built-in operators but the spec is clear that it is possible to do so. While I haven't read the entire C standard, I'd bet the farm that it makes no mention of this type of thing or, if it does, it would be clear that changing the built-in operators is forbidden.

A Language is More Than It's Standard

And sometimes the standard is the implementation.

There have been other

There have been other systems (than lisp) with reflective abilities.

IIRC, Self was such a system. You actually could redefine + and the system then run several hours to recompile everything inside it which used it.