Merge pull request #238 from prt2121/pt/haskell-7.10.1
[jackhill/mal.git] / docs / FAQ.md
CommitLineData
3cbd2ef7 1# Mal/Make-a-Lisp FAQ
263007a8 2
8d8ca1f0
JM
3<a name="why_mal"></a>
4
81f5db50
JM
5### Why did you create mal/make-a-lisp?
6### OR Why the name "mal"?
7### OR Why?
8### OR Wat?
9
10In November of 2013, Alan Dipert gave a [lightning talk at
11Clojure/conj](https://www.youtube.com/watch?v=bmHTFo2Rf2w#t=28m55s)
12about [gherkin](https://github.com/alandipert/gherkin), a Lisp
e1ab693c 13implemented in bash. His presentation led me to ask myself the question
1e66ee3f
JM
14of whether a Lisp could be created using the GNU Make macro language.
15As you have probably guessed, the answer to that question is yes.
81f5db50
JM
16
17Interestingly, the current pedagogical/educational purpose of mal
18happened due to a semantic naming accident (naming is such a fraught
1e66ee3f
JM
19task in computer science). If I am remembering correctly, the name
20"mal" original meant "MAke Lisp". I do not remember precisely why
21I continued to create more implementations, apart from the fact that
22it was a fun challenge, but after the make implementation, many of the
23others were relatively easy. At some point during that process,
24I realized that the multiple implementations and incremental steps
25(which was originally just for my own clarity) was a useful learning
26tool and so the "mal" name became a double entendre for "Make, A Lisp"
27and "make-a-lisp" (and eventually just the latter given that the make
28implementation is now just a small part of the whole).
81f5db50
JM
29
30
8d8ca1f0
JM
31<a name="code_split"></a>
32
263007a8
JM
33### Why is some code split into steps and some code not?
34
35The split between code that goes in steps and code that goes into other files
36is not completely arbitrary (a bit arbitrary, but not completely). My rule of
37thumb is something like this: if the code is specific and necessary for
38implementing a Lisp then it belongs in the step files. If the purpose of the
39code is for implementing new dynamic data-types/objects and the functions or
40methods that operate on those types, then it goes in separate files.
41
42If the target language has types and functions that resemble mal types, then
43those files tend to be very small or non-existent. Examples:
44
45* the mal implementation has no types, reader, printer files and
46 has a trivial core file (just to hoist underlying functions)
47* the Clojure implementation has no types file and fairly trivial
48 reader and printer files (just to modify the Clojure reader/writer
49 slightly) and a fairly trivial core file
50* ruby types and the functions that operate on them are very "Lispy"
51 so the Ruby types file and core file are very small.
52
53The env file is somewhat more arbitrary, however, it is
54a self-contained module that is implemented early and changes very
55little after that, so I decided to separate it. Also, for languages
56that have hierarchical maps/dictionaries (e.g. Javascript
57objects/prototype chain), you do not necessarily need an env file.
58
59Another way of summarizing this answer is that the step files
60represent the core of what makes something a Lisp, the rest of the
61modules are just language specific details (they may be the harder
62than the Lisp part, but that is due to the nature of the target
63language not because of Lisp functionality per se).
64
8d8ca1f0
JM
65
66<a name="steps"></a>
67
263007a8
JM
68### Why are the mal/make-a-lisp steps structured the way they are?
69
70### OR Why is X functionality in step Y instead of step Z?
71
72There is no single consistent rule that I have used to determine which
73functionality goes in which step and the arrangement has changed
74numerous times since the beginning of the project. There are several
75different goals that I try and balance in determining which
76functionality goes into which step:
77
78* **Optimize Lisp learning**: I want developers who are unfamiliar with
79 Lisp to be able to use the project and guide to learn about Lisp
80 without becoming overwhelmed. In many Lisp introductions, concepts
81 like quoting and homoiconicity (i.e. a user exposed eval function)
82 are introduced early. But these are fairly foreign to most other
83 languages so they are introduced in later steps in mal. I also try
84 to not to concentrate too many Lisp concepts in a single step. So
85 many steps contain one or two Lisp concepts plus some core function
86 additions that support those concepts.
87
88* **Optimize implementation language learning (equal-ish step
89 sizing)**: I try to structure the steps so that the target
90 implementation can be learned incrementally. This goal is the one
91 that has caused me to refactor the steps the most. Different
92 languages have different areas that they optimize and make simple
93 for the developer. For example, in Java (prior to 8) and PostScript
94 creating the equivalent of anonymous functions and function closures
95 is painful. In other languages, function closures are trivial, but
96 IO and error handling are tedious when you are first learning the
97 language (I am looking at you Haskell). So this goal is really about
98 trying to balance step size across multiple languages.
99
100* **Practical results early and continuous feedback**: it is
101 a scientific fact that many small rewards are more motivating than
102 a single large reward (citation intentionally omitted, get a small
103 reward by googling it yourself). Each step in mal adds new
104 functionality that can actually be exercised by the implementor and,
105 just as importantly, easily tested.
106
107Also, the step structure of mal/make-a-lisp is not perfect. It never
108will be perfect, but there are some areas that could be improved. The
109most glaring problem is that step1 is on the heavy/large size because
110in most languages you have to implement a good portion of the
111reader/printer before you can begin using/testing the step. The
112compromise I have settled on for now is to put extra detail in the
113process guide for step1 and to be clear that many of the types are
114deferrable until later. But I am always open to suggestions.
81f5db50
JM
115
116
8d8ca1f0
JM
117<a name="add_implementation"></a>
118
81f5db50
JM
119### Will you add my new implementation?
120
121Absolutely! I want mal to have a idiomatic implementation in every
122programming language.
123
124Here are a few guidelines for getting your implementation accepted
125into the main repository:
126
127* Your implementation needs to be complete enough to self-host. This
280688b2
JM
128 means that all the mandatory tests should pass in both direct and
129 self-hosted modes:
81f5db50 130 ```bash
e5737b08
SL
131 make "test^[IMPL_NAME]"
132 make MAL_IMPL=[IMPL_NAME] "test^mal"
81f5db50
JM
133 ```
134 You do not need to pass the final optional tests for stepA that are
135 marked as optional and not needed for self-hosting.
136
137* Your implementation should follow the existing mal steps and
8d8ca1f0
JM
138 structure: Lisp-centric code (eval, eval_ast, quasiquote,
139 macroexpand) in the step files, other code in reader, printer, env,
140 and core files. See [code layout rationale](#code_split) above.
141 I encourage you to create implementations that take mal in new
142 directions for your own learning and experimentation, but for it to
143 be included in the main repository I ask that it follows the steps
144 and structure.
81f5db50
JM
145
146* Your implementation should stick as much as possible to the accepted
147 idioms and conventions in that language. Try to create an
148 implementation that will not make an expert in that language say
149 "Woah, that's a strange way of doing things". And on that topic,
150 I make no guarantees that the existing implementations are
151 particularly idiomatic in their target languages (improvements are
152 welcome). However, if it is clear to me that your implementation is
153 not idiomatic in a given language then I will probably ask you to
154 improve it first.
155
156* If you are creating a new implementation for an existing
068b8d35
JM
157 implementation (or somebody beats you to the punch while you are
158 working on it), there is still a chance I will merge your
159 implementation. If you can make a compelling argument that your
160 implementation is more idiomatic or significantly better than the
161 existing implementation then I may replace the existing one.
162 However, if your approach is different or unique from the existing
163 implementation, there is still a good chance I will merge your
164 implementation side-by-side with the existing one. In that case
165 I will add your github username as a suffix to the language
166 implementation directory. At the very least, even if I decide not to
167 merge your implementation, I am certainly willing to link to you
168 implementation once it is completed.
81f5db50
JM
169
170* You do not need to implement line editing (i.e. readline)
171 functionality for your implementation, however, it is a nice
172 convenience for users of your implementation and I personally find
173 it saves a lot of time when I am creating a new implementation to
280688b2 174 have line edit support early in the process.
c088d7cf
JM
175
176---
177
178**Good questions that either don't have answer or need more detail**
179
180### Why do some mal forms end in "\*" or "!" (swap!, def!, let\*, etc)?