Learn C and Build Your Own Lisp (2014)
buildyourownlisp.com
buildyourownlisp.com
It does make use of the author's grammar parser, which is my only minor complaint. Does anyone know a good resource in which the author handcrafts a parser? I'm aware of the various parser generators that exist. I also read the dragon book in my college's compiler design course ~12 years ago. But we also used a parser generator in that class.
http://craftinginterpreters.com/contents.html the book implements the Lox language in Java and C.
That's the algorithm for the common lisp reader. Writing a recursive descent parser based on that spec is fairly straightforward.
And once you hand write your own recursive descent parser you'll probably not want to give up the control that gives you to a parser generator. Yuck.
And, while a Haskell-style type system makes them nicer, they work really well in dynamically typed languages too. (e.g. https://github.com/drewc/smug )
I've been hacking on it here and there and almost have it r4rs compliant -- replaced the lexer with re2c and was going to do the parser in lemon but the design they already have is just too simple to mess with.
[0]https://github.com/catseye/minischeme --note: the bog stock original is floating around on the internets if you google hard enough.
Equivalent JavaScript: https://github.com/sctb/lumen/blob/master/bin/reader.js
It’s 158 lines of lisp, fully bootstrapped, and zero fanciness.
Building LISP: http://www.lwh.jp/lisp/index.html
- Parser: http://www.lwh.jp/lisp/parser.html
Full source: https://github.com/kimtg/ToyLisp
People like lisps because they are written as ASTs. So you can manipulate programs (ASTs) to create DSLs very easily.
That's a low bar. Performance wise, most languages are faster than Python.
However, CL and Scheme both blitz Python when it comes to performance.
The metaprogramming utilities of lisp are still unmatched.
Scheme (my daily driver) is a smaller language. It consists of a small set of well chosen primitives that easily compose to build higher abstractions. It is really nice to work with.
Just mentioned them, because many ignore them as they are commercial products, yet I would consider them the surviving ones from Lisp Machine days developer workflows.
So I would assume, parallel to the the graphical developer tooling, they also offer quite good compilers.
Additionally there are roughly three usage modes for the larger CL implementations:
1) interpreter, often used for development/debugging
2) safe compiled code with full error checking and full generics, often with lots of debug info
3) optimized code, with various degrees of unsafeness, with no debug information, often with limited or no generics
Often applications are a mix of 2) and 3), where often 3) is limited to the portion of the code that actually needs to be VERY fast. This means, that the large majority of the code is fully safe and fully generic code -> thus it has a lot of influence how fast the language/application feels.
For example when one uses CLOS (providing a lot of generic and extensible machinery), a CLOS implementation will use a lot of caching to make it run fast -> caches cost memory. Now, when one starts a CLOS-based application these caches need to be computed and filled - which might make the application at start up feel a bit slow or sluggish. So it makes sense when generating an application to save it with the caches pre-filled - then at application start, caches are simply already loaded and there is no performance hit at startup. That's not something one can see in a simple micro-benchmark or which depends on the 'compiler' (the part which compiles code and generates the machine code) - that's performance from the wider CL system architecture -> one needs to be able to provide that to CLOS applications to improve user acceptance.
I really want to prefer CL, but I always end up trying to write scheme which kind of works, but quickly becomes weird.
I would expect that SBCL might have an advantage in some areas where it's easier to write fast code, because of its type inference and compiler hints. That's very useful.
Some benchmarks on smaller machines like Macs and ARM-boards. http://lispm.de/lisp/benchmarks.html
People are drawn to them for various reasons, among them: strong metaprogramming facilities, real homoiconicity, DSLs, multiple paradigms, REPL development, hot-loading, and sheer elegance.
Why Lisp? For me, it gives me the freedom to get software written with the minimum of fuss in the least amount of time. I can keep my Lisp up and running, while I make changes to my code. I can type in and print out complex data structures without having to write parsers or print methods. I can experiment with data without defining new classes. If some functionality doesn't exist, I can add it: there's no distinction between the language itself and the libraries.
Maybe you should speak to more people who use Lisp, or try it yourself. If you don't know functional programming, you can still write basic Lisp until you learn it.
That's a silly thing to say, especially when two of Lisp's primitive operations, CAR and CDR, are literally named after IBM 704's registers and the first implementations were done on register-based hardware (IBM mainframes and DEC minicomputers).
There's now also more archaic Lisps that don't use a GC, and compile to very efficient machine code, that could compete with C speeds.
Most Lisps actually have too many functions. Not that its bad, but I think you got confused with they require very little primitive functions to mean there standard libs to be small.
On to why, it's hard to explain, but it's arguably the greatest syntax ever designed. In that it's simple and consistent, yet can express all things and easily be extended. You really have to try it to understand though, and give it a good 30 days. It's only once you're familiar with it and past the initial hump that you understand its appeal.
Finally, I'll explain the historical reasons people like Lisps. Its because they pioneered garbage collection, conditionals, closures, multiple inheritance, mixins, dynamic typing, macros, meta-programming, functional programming and REPLs (aka programming prompts). They were also the second OOP language, some people say to this day, only Smalltalk and some Lisps are truly OOP. So there's a lot of love due to its legacy of everything it gave us.
They're now being rediscovered, and because most software can now be successful even at Java's performance and memory usage, Lisps are making a come back. Since they no longer have any defeating drawback.
- You can use whatever paradigm you want.
- Most implementations are fast enough.
- A competent programmer with expert guidance can be effective in common lisp within a day.
- It has many functions, perhaps more than any other language
- It is tricky to implement fully and correctly (I used to contribute to ECL; Embeddable Common-Lisp)
Lisp is perhaps the most effective language.
ESR says[1]: [LISP is worth learning for] the profound enlightenment experience you will have when you finally get it. That experience will make you a better programmer for the rest of your days, even if you never actually use LISP itself a lot. (You can get some beginning experience with LISP fairly easily by writing and modifying editing modes for the Emacs text editor, or Script-Fu plugins for the GIMP.)
However RG says[2]: I just wasn't a very good programmer any more. Lisp's power had made me complacent, and the world had passed me by. Looking back, I actually don't think I was ever a very good programmer. I just happened to have the good fortune to recognize a good thing when I saw it, and used the resulting leverage to build a successful career. But I credit much of my success to the people who designed Common Lisp.
[1]: http://www.catb.org/esr/faqs/hacker-howto.html
[2]: http://coding.derkeiler.com/Archive/Lisp/comp.lang.lisp/2006...
I am looking towards following this tutorial.
[0]: https://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_...
queinnec went to some pains to make this book accessible, in particular by heavily reducing his usual reliance on denotational semantics. but its not really a good causal introduction to the topic, it requires a certain amount of work to get through.
but can't recommend this book strongly enough, maybe as the ideal followon to SICP
I worked through most of MAL with Python and am currently doing it in Haskell. It's a great experience! (I think a few of the concepts could be explained in more detail, though. Maybe I should send in a patch.)
Though I would suggest reading other sources on how pratt parsers work if you want to fully understand the pure simple genius behind them.
As someone interested in Language. I’ll definitely be giving more thought to it.
I'm self-studying and have been working through 'the Dragon book', regarding compilers. I like Lisp due to beginning my learning with HtDP and SICP, and the functional paradigm appeals to me. I'm just beginning K&R C, and Kernighan's Unix Programming Environment. Naturally I'm really excited to find this here so I'll definitely be working through it.
Were I more concerned about ticking boxes on my CV for the person in HR then I probably wouldn't bother.
It is only a matter of reading the required material and get going at it.
alternatively just write more code because tbh that sounds like you just started programming
Apart from explanations, it also contains exercises and their solutions.
I've got those in my scheme https://github.com/rain-1/scheme_interpreter but it isn't perfect
Every value has both a constructor that assigns memory, and a destructor that frees it. Every expression also reallocates it's memory as it processes. So memory is managed and doesn't leak, but it doesn't quite fit with what we know as a GC, and could trash performance in some cases.
And Tail-Call-Optimisation isn't really touched on.
Scheme 9 from Empty Space (https://www.t3x.org/s9book/index.html) explains GC, tail call elimination, continuations, macros, bignums, flonums, etc.
The author doesn't really list any viable reasons to use C over any more modern, convenient language. Just the whole "shows you how memory management really works". A lot of C programmers remind me of the die hard Gentoo/Arch Linux people who think it'll help them "show you how Linux really works".
So the author has something else in mind: building a high level language from the hardware up. C#, JavaScript, Java, and Python already contain much of the basic functionality of Lisp, most importantly a garbage collector, memory safety, and high-level data types.