diff --git a/content/blog/12_compiler_let_in_lambda/fig_colored.png b/content/blog/12_compiler_let_in_lambda/fig_colored.png new file mode 100755 index 0000000..08a0a6f Binary files /dev/null and b/content/blog/12_compiler_let_in_lambda/fig_colored.png differ diff --git a/content/blog/12_compiler_let_in_lambda/fig_colored_ordered.png b/content/blog/12_compiler_let_in_lambda/fig_colored_ordered.png new file mode 100755 index 0000000..addbddd Binary files /dev/null and b/content/blog/12_compiler_let_in_lambda/fig_colored_ordered.png differ diff --git a/content/blog/12_compiler_let_in_lambda/fig_graph.png b/content/blog/12_compiler_let_in_lambda/fig_graph.png new file mode 100755 index 0000000..3a022c5 Binary files /dev/null and b/content/blog/12_compiler_let_in_lambda/fig_graph.png differ diff --git a/content/blog/12_compiler_let_in_lambda/fig_subgraphs.png b/content/blog/12_compiler_let_in_lambda/fig_subgraphs.png new file mode 100755 index 0000000..8d37338 Binary files /dev/null and b/content/blog/12_compiler_let_in_lambda/fig_subgraphs.png differ diff --git a/content/blog/12_compiler_let_in_lambda/fig_subgraphs_colored.png b/content/blog/12_compiler_let_in_lambda/fig_subgraphs_colored.png new file mode 100755 index 0000000..d75aa25 Binary files /dev/null and b/content/blog/12_compiler_let_in_lambda/fig_subgraphs_colored.png differ diff --git a/content/blog/12_compiler_let_in_lambda/fig_subgraphs_colored_all.png b/content/blog/12_compiler_let_in_lambda/fig_subgraphs_colored_all.png new file mode 100755 index 0000000..a65b951 Binary files /dev/null and b/content/blog/12_compiler_let_in_lambda/fig_subgraphs_colored_all.png differ diff --git a/content/blog/12_compiler_let_in_lambda/fig_subgraphs_colored_ordered.png b/content/blog/12_compiler_let_in_lambda/fig_subgraphs_colored_ordered.png new file mode 100755 index 0000000..4ac6615 Binary files /dev/null and b/content/blog/12_compiler_let_in_lambda/fig_subgraphs_colored_ordered.png differ diff --git a/content/blog/12_compiler_let_in_lambda/index.md b/content/blog/12_compiler_let_in_lambda/index.md new file mode 100644 index 0000000..2541f53 --- /dev/null +++ b/content/blog/12_compiler_let_in_lambda/index.md @@ -0,0 +1,85 @@ +--- +title: Compiling a Functional Language Using C++, Part 12 - Let/In and Lambdas +date: 2020-04-20T20:15:16-07:00 +tags: ["C and C++", "Functional Languages", "Compilers"] +draft: true +--- + +Now that our language's type system is more fleshed out and pleasant to use, +it's time to shift our focus to the ergonomics of the language itself. I've been +mentioning `let/in` expressions and __lambda expressions__ for a while now. +The former will let us create names for expressions that are limited to +a certain scope (without having to create global variable bindings), while +the latter will allow us to create functions without giving them any name at +all. + +Let's take a look at `let/in` expressions first, to make sure we're all on +the same page about what it is we're trying to implement. Let's +start with some rather basic examples, and then move on to more +complex examples. The most basic use of a `let/in` expression is, in Haskell: + +```Haskell +let x = 5 in x + x +``` + +In the above example, we bind the variable `x` to the value `5`, and then +refer to `x` twice in the expression after the `in`. The whole snippet is one +expression, evaluating to what the `in` part evaluates to. Additionally, +the variable `x` does not escape the expression - +{{< sidenote "right" "used-note" "it cannot be used anywhere else." >}} +Unless, of course, you bind it elsewhere; naturally, using x +here does not forbid you from re-using the variable. +{{< /sidenote >}} + +Now, consider a slightly more complicated example: + +```Haskell +let sum xs = foldl (+) 0 xs in sum [1,2,3] +``` + +Here, we're defining a _function_ `sum`, +{{< sidenote "right" "eta-note" "which takes a single argument:" >}} +Those who favor the +point-free +programming style may be slightly twitching right now, the words +eta reduction swirling in their mind. What do you know, +fold-based sum is even one of the examples +on the Wikipedia page! I assure you, I left the code as you see it +deliberately, to demonstrate a principle. +{{< /sidenote >}} the list to be summed. We will want this to be valid +in our language, as well. We will soon see how this particular feature +is related to lambda functions, and why I'm covering these two features +in the same post. + +Let's step up the difficulty a bit more, with an example that, +{{< sidenote "left" "translate-note" "though it does not immediately translate to our language," >}} +The part that doesn't translate well is the whole deal with patterns in +function arguments, as well as the notion of having more than one equation +for a single function, as is the case with safeTail. +

+It's not that these things are impossible to translate; it's just +that translating them may be worthy of a post in and of itself, and would only +serve to bloat and complicate this part. What can be implemented with +pattern arguments can just as well be implemented using regular case expressions; +I dare say most "big" functional languages actually just convert from the +former to the latter as part of the compillation process. +{{< /sidenote >}} illustrates another important principle: + +```Haskell +let + safeTail [] = Nothing + safeTail [x] = Just x + safeTail (_:xs) = safeTail xs + myTail = safeTail [1,2,3,4] +in + myTail +``` + +The principle here is that definitions in `let/in` can be __recursive and +polymorphic__. Remember the note in +[part 10]({{< relref "10_compiler_polymorphism.md" >}}) about +[let-polymorphism](https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system#Let-polymorphism)? This is it: we're allowing polymorphic variable bindings, +but only when they're bound in a `let/in` expression (or at the top level). + +The principles demonstrated by the last two snippets mean that compiling `let/in` +expressions, at least with the power we want to give them