a thoughtful web.
Good ideas and conversation. No ads, no tracking.   Login or Take a Tour!
comment
bhrgunatha  ·  1551 days ago  ·  link  ·    ·  parent  ·  post: GNU Guile 3.0.0 released

Sorry in advance, I'm verbose as fuck and don't know your background.

    Why do people like lisp so much?

I think it boils down to two things but everyone has their own point of view.

1. Homoiconicity (see later)

2. The ability to change both the way the program is read and evaluated.

It might be apocryphal but people say Lisp is named due to List Processing.

At its heart what seems to most annoy people about it - all those parentheses - turns out to be one of its killer features. As bfv pointed out the programs you write are exactly the same representation as the lists used by the language. This is called homoiconicity. Since bfv already highlighted the REPL - Read , Eval, Print, Loop - I want to expand a bit on what I think is the heart of Lisp the read and eval parts.

This is only conceptual,high level and very handwavy so the actual details vary wildly and factually.

Most languages - whether compiled or interpreted - need a pre-processing step - called parsing (READ!) - that turns the text representation (your program) into an internal representation called an AST (abstract syntax tree). An interpreted language will take the AST and run it by interpreting it (EVAL!). That is convert the into the actions of the program you wrote. It might have to interpret parts of the AST over and over again and each time has to figure out what to do.

A compiled language analyses the AST much more deeply and converts it into a representation the machine itself can execute - the computer's own binary machine code. Since this is only done once (at the time of compilation) there is no need to keep or interpret the AST over and over again to take the actions as the program runs - the computer does that itself. That is why compiled languages are generally faster than interpreted languages - because the compiler takes more time analysing the AST to see how best to convert it into the binary instructions the computer itself executes. . Also the interpreter is a program itself which the actual machine is executing and that extra layer has a toll. Note there are 2 phases for both interpreted and compiled - I like the diagram's use of pre-processing and processing to represent that.

Back to Lisp.

Lisp also has separate pre-processing and processing phases. BUT (and this is one of those killer features) your program can hook into the pre-processing phase using Lisp's infamous macros. The pre-processing phase of Lisp transforms your program (which thanks to homoiconicity is a just a bunch of Lists) and converts them according to both the macros provided by whatever flavour of Lisp your using and the macros you wrote as part of your program. These transformation use the full power of language too and because your program is just a bunch of lists, it's really straightforward to transform them. Yes, the full power of the language means your macros can also use the other macros at the pre-processing phase too.

What's more you can hook into the parsing part of pre-processing which basically means you can invent your own syntax - even if it's not based on lists - as long as the end result of that is in the format (lists!) the rest of the language understands.

The processing phase then takes the transformed code (which are now legitimate lists your favourite Lisp flavour can understand) and executes it.

For example this cheeky monkey takes C source code during the pre-processing phase and transforms it into a list - (run-c-program <c source code>) then during the processing phase "run-c-program" shells out to compile and execute the C-program.

You might cry foul about now and say "but then lisp is interpreted" but actually the choice of compiled or interpreted is truly and deeply an implementation detail and some exceptional computer scientists have converted the whole process into one that uses the compiled model.

I'm not going to waste more time to cover what a JIT compiler is but this announcement is notable because Guile now has a JIT compiler.

    And what does it mean for a language to be a dialect of lisp (scheme)?

I think if it conforms to the above model then it's in the lisp family.

There are many decisions and tradeoffs when you design a language. I think perhaps the 4 most interesting lisp languages are Common Lisp, Racket, Clojure and Emacs Lisp.

A big difference between Scheme and most other Lisps is the macro system and Racket has extended the Scheme model to the point where the designers call it a language laboratory rather than a language. For example when you install racket - it includes Scheme (both standards R5RS and R6RS), Datalog (logic programming), Typed Racket (static type checking), Lazy Racket (lazy evaluation), Algol 60 - no seriously!, Scribble (a language for making documentation), Slideshow, and many others.