1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-11 21:57:38 +03:00
mal/impls/chuck/notes.md

156 lines
6.9 KiB
Markdown
Raw Permalink Normal View History

2016-04-28 11:17:59 +03:00
# Step 1
- What if I don't have an OOP language?
- types.qx could be more prominently mentioned...
2016-04-28 11:17:59 +03:00
- A table with all types and suggested object names would be hugely
useful
- Same for a list of all errors and their messages
- Mention return types and argument types consistently
- More on int/float and their grammar (int is mentioned implicitly in
the ASCII art, nothing on signs or bases or their lack of)
- Note that a string must be parsed for the `print_readably` thing to
work and mention how one could do that (like, by using a `read` or
`eval`-like thing or alternatively, chopping off the surrounding
quotes and doing the inverse transformation of the printing)
- How is an atom printed?
2016-04-29 21:40:11 +03:00
# Step 2
- What if my language doesn't support lambdas, let alone passing
around named functions? Ideally write something about
implementing/using functors/delegates or replacing that namespace
with a big switch as with VHDL. Another problem is that if you
choose a different solution in step 4, step 2 could end up no longer
functional...
- What kind of error (read: what message?) is raised when no value can
be looked up for the symbol? Is it arbitrary? Do I need to extend
my error handling to allow for format strings?
- It would be worth a mention that you should extend the printer to
handle "native" functions (or in oldtimey terms, subrs)
2016-04-30 21:12:07 +03:00
# Step 3
- You should modify both eval_ast *and* EVAL
- Suggest the trick with destructuring the AST into `a0`, `a1`,
etc. variables for easier access. Perhaps this can be used to clear
up the general language used with AST manipulation (like, first
parameter and second list element)?
- What does def! return? Emacs Lisp for instance returns the symbol
whereas the tests suggest the value should be returned instead...
2016-05-12 11:01:09 +03:00
# Step 4
- "Implement the strings functions"
- The "no closures" paragraph isn't quite clear. Asides from that, do
native functions don't really need to be wrapped the same way as the
`fn*` objects, just introduce another type (like, a Subr and a Func
type) and do a check before applying the arguments to it
- Why does the guide say that the first argument of `count` can be
treated as list, yet there's a test performing `(count nil)` and
expecting zero as result?
- Does it make sense to compare, say, atoms in `=`?
2016-05-14 04:02:07 +03:00
# Step 5
- "This is especially important in Lisp languages because they tend to
prefer using recursion instead of iteration for control structures."
<- I'd argue it's less of a lisp thing (see everything else related
to CL) and more a thing functional programming proponents have
considered more elegant than introducing iteration constructs (see
haskell, ocaml, erlang)
- It's not really clear that the TCO change for `let*` involves the
form you'd normally pass to `EVAL` to become the new `ast`. I had to
reread this a few more times to understand that the "second `ast`"
is actually its third argument...
- Where did the check for `do` not being broken by TCO go?
- What's the deal with the `quux/tests/step5_tco.qx` file?
2016-07-30 01:50:12 +03:00
# Step 6
- "The closure calls the your EVAL function […]."
- I still don't have any closures. How the heck do I implement
`eval`? What about `swap!`?
- It would be useful to mention that `swap!` sort of requires
implementing `apply` first...
2016-07-30 22:53:24 +03:00
# Step 7
- Why the scare quotes for splicing?
- "Before implementing the quoting forms, you will need to implement
some supporting functions in the core namespace:" should be one list
item
- "this function takes a list as its second parameter and returns a
new list that has the first argument prepended to it." reads backwards
- The quasiquote paragraph is hard to read
- It's rather confusing to refer to the argument of `ast` and to an
`ast` parameter, perhaps name the latter a form?
- What could also help would be a visualization of the four
conditionals:
- \`42, \`()
- \`~foo
- \`(~@foo) and more
- \`(42 ~@foo) and everything else
- Mal/mal is inconsistently capitalized
- "Expand the conditional with reader `read_form` function to add the
following four cases" is again weird, better refer to the
`read_form` function in reader.qx
- "concat should support concatenation of lists, vectors, or a mix or
both." <- "or a mix or both" is redundant
2016-08-01 11:40:32 +03:00
# Step 8
- "In the previous step, quoting enabled some simple manipulation [of]
data structures"
- The macroexpand function step refers to call/apply, it's unclear how
to proceed if you don't have such a thing
- How should the exception for invalid `nth` access look like? Also,
why is it an exception and not an error like with the reader?
- How can `first` take a list (or vector), but work on `nil`?
- The description of `rest` is inconsistent with the tests
- "In the main program, use the rep function to define two new control
structures macros."
- Why does the definition of `cond` use `throw` although it's only
introduced in the next chapter?
2016-08-06 01:34:18 +03:00
# Step 9
- It's not really clear that you really just have a `try*` special
form, with `catch*` merely existing inside it...
- Another thing to clarify is that the exception value is a string
containing the message you'd see (unless you're using `throw`)
- Generally, it would be better to explain the general exception
handling mechanism (with some examples), then showing how one
implements it for both languages with and without exceptions
- Another way than using a global variable is introducing an error
type next to the other MAL types and checking whether something a
function returned is one, although the hint about returning one at
each use of `EVAL` still stands...
- Shouldn't either trick be mentioned at the beginning, simply because
you'll need it in a language without exceptions to do error handling?
- Why this bizarre treatment for `keyword`? Why is there no test for
it?
- Is there a test for whether hash maps deduplicate identical keys
when using `hash-map` or `assoc`?
- What exactly are keys the specification for `dissoc`, `get` and
`contains?` are speaking of? Can I assume these are either strings
or keywords?
- Why is it not documented that `get` may take `nil` instead of a map?
- Perhaps it's worth adding more tests involving symbols to ensure
that functions using apply internally don't evaluate their args?
2016-08-06 22:25:56 +03:00
# Step A
- "Add meta-data support to mal functions." <- Shouldn't you mention
that this involves implementing `with-meta` and `meta`?
- "TODO. Should be separate from the function macro flag." <- Why is
this even related?
- It would be worth to mention that `with-meta` shall clone its
argument to avoid one of the more sneaky test failure reasons
- "The value of this entry should be a mal string containing the name
2016-08-06 22:25:56 +03:00
of the current implementation."
- "When the REPL starts up (as opposed to when it is called with a
script and/or arguments), call the rep function with this string to
print a startup header: `"(println (str \"Mal
[\" *host-language* \"]\"))".`" <- proof that you better quote these
because the asterisks just disappear...