
Crafting Interpreters: Superclasses - azhenley
http://craftinginterpreters.com/superclasses.html
======
kazinator
> _Now onto the new instruction:_

Adding a special VM instruction for such operations as inheriting from a class
is a strikingly bad design decision.

You want to minimize the proliferation of VM instructions as much as possible.

A rule of thumb is: is it unreasonable to compile into a function call? Or
else, is it likely to be heavily used in inner loops, requiring the fastest
possible dispatch? If no, don't add an instruction for it. Compile it into an
ordinary call of a run-time support function.

You're not going to inherit from a class hundreds of millions of times in some
hot loop where the application spends 80% of its time; and if someone
contrives such a thing, they don't necessarily deserve the language level
support for cutting their run-time down.

~~~
munificent
This is a good point. One of the things I have to balance with the book is
teaching the optimal way to do something without dragging through reader
through a large amount of verbose, grungy code. So sometimes (but not too
often) I take a simpler approach even if it's not the best one.

With this VM, we have plenty of opcode space left, so it's natural to just add
another instruction for inheritance, even if it does mean that the bytecode
dispatch loop doesn't fit in the instruction cache quite as well.

I'll think about this some more. I'm very hesitant to make sweeping changes to
the chapter (I want nothing more in life than for the book to be done), but
this would be a good place to teach readers this fundamental technique of
compiling language constructs to runtime function calls.

~~~
wool_gather
Probably sufficient to add it as a chapter footnote/challenge like you did
with flexible array members for the string implementation. Maybe with a
pointer to an example if you have time to find one.

~~~
hhas01
This. Compromises are fine: real-world solutions make them all the time.
What’s valuable to readers is displaying the reasoning behind them.

------
azhenley
For those following this series, Bob's update email said: "This is the second
to last chapter in the book, and the last chapter that adds new
functionality."

------
pansa2
As stated in the text, for `super` calls to work within a method, it’s
necessary to know the class on which the method is defined. Here, that’s easy
- it’s the class that the method is lexically defined within.

This is more difficult in a language which allows methods to be added to
classes dynamically. IIRC both Python and JavaScript are in this category, but
still calculate `super` lexically. Therefore, if a method is copied from one
class to another, `super` within that method may refer to the wrong class.

~~~
wool_gather
Interesting point. I'd have to look at my implementation to be sure, but Lox
will also have this quirk, won't it? You can freely assign values, (as I
recall) including functions, to a property on an instance.

Or does it only come up when a method is added to the _class_?

~~~
pansa2
> Lox will also have this quirk, won't it?

Possibly - I’m not sure about the details of method lookup in Lox. Does `this`
even work correctly when a method is assigned to an instance?

~~~
munificent
If you store a function or reference to a method in a field on an instance in
Lox, the function will remember its original `this` binding. That's what
Python, C#, Ruby, etc. do and is generally what you want. It's not what JS
does because JS doesn't really know what a "method" is, or at least didn't
before classes were added.

~~~
pansa2
Is it possible that there isn't a `this` binding? Does Lox allow access to
"unbound" methods directly from a class, or are methods accessible only via
instances?

~~~
munificent
Methods are only accessible from instances, so `this` is always meaningfully
bound. If you try to use `this` outside of a class body, it's a static error.

~~~
pansa2
OK, that solves the problem. The issue with unbound methods in Python is that
they don’t yet have a value for `this`, but they do have a fixed value for
`super`.

------
throwlaplace
can someone weigh in on this vs thorsten ball's series of books? to my
untrained eye they look fairly similar (at least thorsten's first book) but
I'm not sure.

edit: i should say i'm wondering which is more appropriate for me. my
experience is that i took a PL class during my MS where we implemented a small
recursive descent parser for a language (and the concomitant logic for
evaluating the language). i'm interested in getting better at writing
languages.

~~~
misternugget
Hey! Thorsten Ball here. I'd say: yes, they're similar, but still two
different perspectives on the same subject. (I actually recounted elsewhere
[0] how Bob convinced me, 4 years ago now, that it's valuable to have multiple
teachers of the same subject.)

So if you're into the topic I think you can get something out of my books
([1], [2]) even if you've read Bob's book before. And if you read mine, then
Bob's book will also show you something new.

I'm currently working through Bob's book myself (chapter 23) and I'm enjoying
it immensely: the language, Lox, shares a lot of things with the one in my
books (Monkey), like first-class functions and closures, but also has classes
which Monkey does not. So now I can read Bob's book and on one hand think
"Ohh, I wonder how he does _that_" and on the other hand "classes! let's see
how that works."

My books also use Go exclusively and Bob's uses Java and C. I enjoyed using
IntelliJ and writing Java for the first time in my life a lot and was always a
fan of C, so that was also really interesting, to see how the ideas translate
across three languages.

[0]:
[https://lobste.rs/s/43h7rz/crafting_interpreters_handbook_fo...](https://lobste.rs/s/43h7rz/crafting_interpreters_handbook_for#c_di9tng)
[1]: [https://interpreterbook.com](https://interpreterbook.com) [2]:
[https://compilerbook.com](https://compilerbook.com)

------
pansa2
Very good, as always. I spotted a couple of typos: “inheritred”, “get out
hands”.

~~~
munificent
Thanks, I'll fix those.

