4 ms·
I don't think the grandparent wants all of these features at once necessarily in a single tutorial, but an introduction to them in a language that they already
by mkehrt 11y ago
I don't think the grandparent wants all of these features at once necessarily in a single tutorial, but an introduction to them in a language that they already know.
Also, the things you say that function pointers don't have are exactly the things that make lambdas interesting. Lambdas are anonymous and, crucially, can be nested. It's the very nesting that is what makes them difficult to get right, as they close over their containing scope. Variables mentioned in lambda bodies that are not parameters get their values from the definition scope, not the scope where they are used. In C function pointers, this issue doesn't even come up.
- mafribe 11y agoI did point out the nesting and the requirement to name in C. The scoping follows immediately from beta-reduction (lambda x.M)N --> M[N/x] which I find very intuitive. I never had trouble understanding this, but maybe I'm overgeneralising from my own learning process. The real difficulty, or rather the real subtlety, is not nesting but name binding and the automatic renaming of bound variables where necessary. Having taught lambda-calculus to generations of students, that causes confusion with some students. And I think implementing a type-inferencer in C is going to be confusing because beauty of e.g. the W type-inference algorithm is drowned by orthogonal issues that C forces on you like memory management. Interpreters are best written in languages with pattern matching. So I prefer to bootstrap one's learning: get the basics of lambda-calculus, then implement a lambda-calculus interpreter and type-inferencer in a modern FP language. (As an aside, that's what SICP also does.)
- Silhouette 11y agoThe real difficulty, or rather the real subtlety, is not nesting but name binding and the automatic renaming of bound variables where necessary. If you're trying to understand what a closure does, perhaps that's true. If you're trying to understand how it does it, and you come from an imperative programming background where you know the ABIs for your languages like the back of your hand and are used to the kind of function set-up that always allocates space for local variables on the stack, there is a huge question of how all that lovely, neat theory is actually implemented in practice. Some of this discussion reminds me of the jokes about professors who prove that a solution to some elegantly expressed problem must exist, but then lead it to the grad students to actually find it...
- igravious 11y agoGrandparent here :) Indeed, you have put it more succinctly and cogently that I ever could. I would like an introduction to these advanced topics in the language that I already now. For instance, for a Haskell module I was studying we used a teeny tiny interpreter that had been created just for the task of learning the basics of Haskell. This interpreter was written in Lua. It was small, and I could follow the logic of it. It lacked type inference though, and if I had seen a tutorial _in C_ about how to bolt on a Hindley Milner type inference engine to a lambda calc core I bet I could have made a stab at improving this toy project. Even with Ruby now I bet I code Ruby as if it were a really dynamic C. I hardly ever use map() or collect(), for instance. I just don't have it in my mental toolbox. I'm not total loser though, I do like my {|o| blocks!} I need to emphasize this. I am fluent in C, and can think in it. When I open Pierce TaPL and see immediately ML my heart sinks.
- mafribe 11y agoWhen I open Pierce TaPL and see immediately ML my heart sinks. I strongly recommend that you ignore this feeling and learn a modicum of ML coding. If you want to learn TAPL, just learn a bit of Ocaml. You don't need much. If you already speak C, a bit of Haskell and Ruby, you should be able to pick up enough Ocaml in a few hours/days. Programming in Ocaml is way easier than in Haskell or C. The only two things that are a bit difficult in Ocaml are modules and the object system. You can completely ignore objects. Nobody ever uses them, and for TAPL you can also ignore modules (although you occasionally have to open a module, which is trival, something like: open Support.Pervasive).
- vezzy-fnord 11y agoYou can completely ignore objects. Nobody ever uses them This is an oft-made statement about OCaml, but it simply isn't true. 0install and Opa are two major projects that use the object system, for instance.
- igravious 11y agoReally? I feel like C fits my brain, know what I mean? I don't even think that it was because I learnt it early on. It's a simple language, I feel. Why is programming way easier in Ocaml than in C? Setting aside that for me programming is way easier in C than in Ocaml because I know C and don't know Ocaml, what is it about Ocaml that is way easier than C? Anyway, my original point is that it is _cheating_ to explain how to build a Lisp by saying, "First reach for your nearest functional programming language". Useless car analogy. Today I'm going to learn how to build a car. First, take the engine from my Toyata... oh... um...