summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--2021/captions/emacsconf-2021-form--old-mccarthy-had-a-form--ian-eure--main.vtt1282
-rw-r--r--2021/captions/form.md430
-rw-r--r--2021/info/form-schedule.md12
-rw-r--r--2021/info/native-schedule.md2
-rw-r--r--2021/schedule-details.md4
5 files changed, 1723 insertions, 7 deletions
diff --git a/2021/captions/emacsconf-2021-form--old-mccarthy-had-a-form--ian-eure--main.vtt b/2021/captions/emacsconf-2021-form--old-mccarthy-had-a-form--ian-eure--main.vtt
new file mode 100644
index 00000000..4f95164f
--- /dev/null
+++ b/2021/captions/emacsconf-2021-form--old-mccarthy-had-a-form--ian-eure--main.vtt
@@ -0,0 +1,1282 @@
+WEBVTT
+
+00:01.199 --> 00:00:02.320
+My name is Ian Eure,
+
+00:00:02.320 --> 00:00:03.199
+and welcome to my talk
+
+00:00:03.199 --> 00:00:05.120
+"Old McCarthy Had a Form".
+
+00:00:05.120 --> 00:00:05.759
+In this talk,
+
+00:00:05.759 --> 00:00:07.759
+I'm going to be discussing EIEIO,
+
+00:00:07.759 --> 00:00:09.920
+which is an Emacs Lisp implementation
+
+00:00:09.920 --> 00:00:12.320
+of the Common Lisp object system.
+
+00:12.320 --> 00:00:13.519
+CLOS is a way of writing
+
+00:13.519 --> 00:00:15.360
+object-oriented Common Lisp code,
+
+00:00:15.360 --> 00:00:17.920
+and with EIEIO you have much of that same
+
+00:17.920 --> 00:00:19.920
+power but inside Emacs.
+
+00:00:19.920 --> 00:00:21.359
+I'm going to be using those two names
+
+00:00:21.359 --> 00:00:22.988
+interchangeably throughout this talk,
+
+00:00:22.988 --> 00:00:26.640
+since they're nearly equivalent.
+
+00:26.640 --> 00:00:27.534
+You might wonder,
+
+00:00:27.534 --> 00:00:28.880
+"Why would I want to write
+
+00:00:28.880 --> 00:00:31.439
+object Emacs Lisp code?".
+
+00:00:31.439 --> 00:00:33.440
+I like it because I like writing
+
+00:00:33.440 --> 00:00:34.960
+in a functional programming style,
+
+00:00:34.960 --> 00:00:36.896
+or I like to do an imperative style
+
+00:00:36.896 --> 00:00:39.040
+that captures interactive key sequences
+
+00:00:39.040 --> 00:00:41.200
+that I might enter manually.
+
+00:41.200 --> 00:00:42.800
+Well, I think, different kinds of programs
+
+00:42.800 --> 00:00:45.120
+need different kind of programming paradigms,
+
+00:00:45.120 --> 00:00:47.760
+and sometimes OOP is the one that fits.
+
+00:00:47.760 --> 00:00:49.708
+Also, if you've done much OOP before,
+
+00:00:49.708 --> 00:00:50.655
+you might be surprised by
+
+00:00:50.655 --> 00:00:52.879
+how EIEIO works and the sorts of power
+
+00:00:52.879 --> 00:00:55.039
+that it brings to your programs.
+
+00:55.039 --> 00:00:58.480
+So, let's talk about that model now.
+
+00:58.480 --> 00:01:00.000
+Classes are pretty much what
+
+00:01:00.000 --> 00:01:01.120
+you would expect if you've done
+
+00:01:01.120 --> 00:01:02.879
+OOP programming before.
+
+01:02.879 --> 00:01:04.400
+In the CLOS model,
+
+00:01:04.400 --> 00:01:06.400
+they only have fields,
+
+00:01:06.400 --> 00:01:08.000
+they only encapsulate values,
+
+00:01:08.000 --> 00:01:10.720
+they don't have anything to do with methods.
+
+01:10.720 --> 00:01:13.040
+So, in this case, we have a base class for
+
+01:13.040 --> 00:01:15.040
+an EMMS player backend,
+
+00:01:15.040 --> 00:01:18.159
+and it has one field (a slot is what
+
+00:01:18.159 --> 00:01:20.000
+it's called in CLOS terminology),
+
+00:01:20.000 --> 00:01:22.720
+which indicates whether it's playing or not,
+
+00:01:22.720 --> 00:01:24.080
+and it's declared abstract,
+
+00:01:24.080 --> 00:01:25.439
+so you can't create an instance
+
+00:01:25.439 --> 00:01:27.040
+of an object based on this class,
+
+00:01:27.040 --> 00:01:29.280
+you can only extend it with another class,
+
+00:01:29.280 --> 00:01:31.119
+that's an EIEIO extension,
+
+00:01:31.119 --> 00:01:33.439
+but I think it's a pretty good one.
+
+01:33.439 --> 00:01:34.640
+You can also see there's a class
+
+00:01:34.640 --> 00:01:37.119
+that implements an mpv player back-end,
+
+00:01:37.119 --> 00:01:39.680
+and it extends the base class,
+
+00:01:39.680 --> 00:01:40.960
+it doesn't add any slots,
+
+00:01:40.960 --> 00:01:44.479
+and those get inherited from the base class.
+
+01:44.479 --> 00:01:45.936
+If you want these to do much more
+
+00:01:45.936 --> 00:01:46.960
+than encapsulate data,
+
+00:01:46.960 --> 00:01:48.880
+you need to start writing methods.
+
+00:01:48.880 --> 00:01:50.324
+The CLOS model is to have
+
+00:01:50.324 --> 00:01:51.439
+a generic function.
+
+00:01:51.439 --> 00:01:52.399
+A generic function is
+
+00:01:52.399 --> 00:01:53.680
+kind of like an interface,
+
+00:01:53.680 --> 00:01:55.600
+it's just a name and an argument list,
+
+01:55.600 --> 00:01:57.280
+and there's no implementation,
+
+00:01:57.280 --> 00:01:58.560
+you have to write a method
+
+00:01:58.560 --> 00:02:00.960
+in order to have an actual implementation.
+
+00:02:00.960 --> 00:02:02.880
+When you call the generic function,
+
+00:02:02.880 --> 00:02:04.960
+the system will do a dynamic dispatch
+
+00:02:04.960 --> 00:02:06.560
+to a method that matches based on
+
+00:02:06.560 --> 00:02:08.319
+its argument types and how the method
+
+00:02:08.319 --> 00:02:12.239
+has declared that it should be invoked.
+
+02:12.239 --> 00:02:14.239
+Here's an example of some methods
+
+00:02:14.239 --> 00:02:16.480
+for our mpv player backend,
+
+00:02:16.480 --> 00:02:19.599
+you can see that it'll play anything
+
+00:02:19.599 --> 00:02:21.200
+other than something
+
+00:02:21.200 --> 00:02:23.200
+with a keyword of `unplayable`,
+
+00:02:23.200 --> 00:02:25.328
+and it just has dummy start and stop methods
+
+00:02:25.328 --> 00:02:27.680
+that return "Started" and "Stopped" text.
+
+00:02:27.680 --> 00:02:29.599
+A method is just one implementation
+
+00:02:29.599 --> 00:02:30.552
+of a generic function,
+
+00:02:30.552 --> 00:02:32.640
+and you can have as many as you need.
+
+02:32.640 --> 00:02:33.920
+In order to determine
+
+00:02:33.920 --> 00:02:35.519
+which method gets dispatched
+
+00:02:35.519 --> 00:02:36.879
+when you call a generic function,
+
+00:02:36.879 --> 00:02:38.080
+they're specialized based on
+
+02:38.080 --> 00:02:39.360
+their argument type.
+
+00:02:39.360 --> 00:02:40.640
+In this case, you can see that
+
+00:02:40.640 --> 00:02:41.680
+first argument says
+
+00:02:41.680 --> 00:02:44.480
+`player talk/emms-player-mpv`,
+
+00:02:44.480 --> 00:02:46.239
+that means that if that first argument
+
+00:02:46.239 --> 00:02:48.480
+is an instance of the mpv player
+
+00:02:48.480 --> 00:02:50.080
+or a subclass of it,
+
+00:02:50.080 --> 00:02:52.000
+then those methods will be invoked,
+
+00:02:52.000 --> 00:02:53.560
+unless there's a more specific one
+
+00:02:53.560 --> 00:02:55.440
+based on that argument type.
+
+02:55.440 --> 00:02:56.656
+You don't have to define
+
+00:02:56.656 --> 00:02:57.760
+the generic functions.
+
+00:02:57.760 --> 00:02:59.040
+If you define a method,
+
+00:02:59.040 --> 00:03:00.451
+then it'll implicitly define
+
+00:03:00.451 --> 00:03:03.599
+the generic function for you.
+
+03:03.599 --> 00:03:05.440
+Specialization is really powerful.
+
+00:03:05.440 --> 00:03:06.939
+It lets the methods define
+
+00:03:06.939 --> 00:03:08.400
+how they get invoked
+
+00:03:08.400 --> 00:03:10.472
+If you've done much programming in Clojure,
+
+00:03:10.472 --> 00:03:12.959
+this sounds a little bit like multi-methods,
+
+00:03:12.959 --> 00:03:16.319
+but with multi-methods, only the main method,
+
+00:03:16.319 --> 00:03:18.000
+the equivalent of the generic function,
+
+00:03:18.000 --> 00:03:19.920
+can determine how they're dispatched.
+
+00:03:19.920 --> 00:03:21.519
+So, as the writer of an interface,
+
+00:03:21.519 --> 00:03:23.120
+you might not be able to foresee
+
+00:03:23.120 --> 00:03:25.519
+every way that someone who's implementing
+
+00:03:25.519 --> 00:03:26.959
+a version of that interface
+
+03:26.959 --> 00:03:28.400
+would like to dispatch.
+
+00:03:28.400 --> 00:03:29.920
+CLOS doesn't have that problem,
+
+00:03:29.920 --> 00:03:31.200
+you get to define your
+
+03:31.200 --> 00:03:34.080
+own invocation semantics.
+
+03:34.080 --> 00:03:35.360
+You're also not limited to
+
+00:03:35.360 --> 00:03:37.200
+dispatching based on the value
+
+00:03:37.200 --> 00:03:39.920
+being a subclass of an EIEIO type.
+
+00:03:39.920 --> 00:03:41.280
+You can dispatch based on
+
+03:41.280 --> 00:03:42.879
+a primitive type like integer,
+
+00:03:42.879 --> 00:03:45.360
+you can dispatch based on the value,
+
+03:45.360 --> 00:03:47.599
+you can dispatch on multiple arguments,
+
+03:47.599 --> 00:03:49.599
+and there's also a default dispatch
+
+00:03:49.599 --> 00:03:50.688
+that will get applied
+
+00:03:50.688 --> 00:03:53.200
+if there's no others that are defined.
+
+00:03:53.200 --> 00:03:54.319
+If you don't have a default,
+
+00:03:54.319 --> 00:03:55.439
+then you'll just get an error
+
+03:55.439 --> 00:03:56.480
+from the system,
+
+00:03:56.480 --> 00:03:57.439
+and if that doesn't cover it,
+
+00:03:57.439 --> 00:03:59.040
+you can even define your own.
+
+03:59.040 --> 00:04:00.239
+Definition is with the
+
+00:04:00.239 --> 00:04:01.760
+`cl-generic-generalizers`,
+
+00:04:01.760 --> 00:04:03.680
+which is itself a generic function.
+
+00:04:03.680 --> 00:04:05.680
+Much of CLOS is built in CLOS,
+
+00:04:05.680 --> 00:04:08.319
+which I think is really cool.
+
+04:08.319 --> 00:04:09.599
+In addition to all that,
+
+00:04:09.599 --> 00:04:12.319
+you have four different types of methods,
+
+04:12.319 --> 00:04:13.680
+and those are distinguished by
+
+00:04:13.680 --> 00:04:16.000
+what's called a qualifier.
+
+04:16.000 --> 00:04:18.400
+Every function can have methods
+
+00:04:18.400 --> 00:04:20.239
+that have all four different
+
+00:04:20.239 --> 00:04:21.280
+types of qualifiers,
+
+00:04:21.280 --> 00:04:22.960
+and based on your class inheritance,
+
+00:04:22.960 --> 00:04:25.680
+you might have multiple of each type.
+
+04:25.680 --> 00:04:26.800
+There's the primary method,
+
+00:04:26.800 --> 00:04:28.560
+which is equivalent to the method
+
+00:04:28.560 --> 00:04:29.919
+in any other OOP system,
+
+00:04:29.919 --> 00:04:32.160
+so we're not going to cover that too much.
+
+04:32.160 --> 00:04:33.759
+Then there's a `before` method.
+
+00:04:33.759 --> 00:04:35.600
+This is evaluated before
+
+00:04:35.600 --> 00:04:37.440
+the primary method for side effects,
+
+00:04:37.440 --> 00:04:40.080
+and its return value is discarded.
+
+00:04:40.080 --> 00:04:41.120
+There's an `after` method,
+
+00:04:41.120 --> 00:04:42.560
+which is the same but happens after
+
+00:04:42.560 --> 00:04:44.479
+the method has finished evaluating.
+
+04:44.479 --> 00:04:46.639
+And then there's an `around` method
+
+00:04:46.639 --> 00:04:49.199
+that happens around all the other three.
+
+04:49.199 --> 00:04:51.120
+And by using these types of methods
+
+00:04:51.120 --> 00:04:52.560
+and using class inheritance
+
+00:04:52.560 --> 00:04:54.560
+to compose them into your classes,
+
+00:04:54.560 --> 00:04:56.479
+you can add some really powerful
+
+00:04:56.479 --> 00:04:58.240
+mixin type functionality.
+
+00:04:58.240 --> 00:04:59.764
+You can use before and after
+
+00:04:59.764 --> 00:05:01.280
+to build things like logging,
+
+00:05:01.280 --> 00:05:02.479
+and you can use around
+
+00:05:02.479 --> 00:05:04.880
+to implement things like memoization.
+
+05:04.880 --> 00:05:06.720
+If you've done much Emacs Lisp programming,
+
+00:05:06.720 --> 00:05:08.160
+those before after and around
+
+00:05:08.160 --> 00:05:09.919
+might jog your memory because
+
+05:09.919 --> 00:05:11.440
+they're the same features you get
+
+00:05:11.440 --> 00:05:14.160
+with Emacs's built-in function advice.
+
+05:14.160 --> 00:05:15.680
+The thing with function advice is that
+
+05:15.680 --> 00:05:17.199
+it only works on functions
+
+00:05:17.199 --> 00:05:18.240
+in the global namespace,
+
+00:05:18.240 --> 00:05:20.360
+and there's no kind of conditionality,
+
+00:05:20.360 --> 00:05:21.840
+they always get dispatched
+
+00:05:21.840 --> 00:05:23.440
+when that function is invoked.
+
+05:23.440 --> 00:05:25.600
+The nice thing about the CLOS system is that
+
+00:05:25.600 --> 00:05:27.039
+whether they get invoked or not
+
+05:27.039 --> 00:05:28.872
+depends on whether they exist in
+
+00:05:28.872 --> 00:05:30.160
+the class hierarchy,
+
+00:05:30.160 --> 00:05:31.520
+so you can add them to your
+
+00:05:31.520 --> 00:05:32.880
+class hierarchy if you want
+
+00:05:32.880 --> 00:05:34.000
+that extra functionality
+
+00:05:34.000 --> 00:05:35.440
+like logging or memoization,
+
+00:05:35.440 --> 00:05:37.120
+and you can exclude it if you don't.
+
+00:05:37.120 --> 00:05:38.320
+I think that's really powerful
+
+05:38.320 --> 00:05:42.639
+and a very interesting way of doing it.
+
+05:42.639 --> 00:05:44.639
+It also supports multiple inheritance,
+
+05:44.639 --> 00:05:46.639
+which is the mechanism that you can use
+
+05:46.639 --> 00:05:48.560
+to compose all these different kinds of
+
+05:48.560 --> 00:05:50.479
+behaviors into a single object that does
+
+05:50.479 --> 00:05:52.240
+all the things that you want.
+
+00:05:52.240 --> 00:05:54.720
+Here's a quick example of a logger.
+
+00:05:54.720 --> 00:05:56.240
+So, you can see the class just has
+
+00:05:56.240 --> 00:05:58.319
+a single slot called `messages`,
+
+00:05:58.319 --> 00:05:59.840
+it has a `log` method
+
+00:05:59.840 --> 00:06:01.440
+that pushes a new message,
+
+00:06:01.440 --> 00:06:03.840
+which is a format string, into that,
+
+00:06:03.840 --> 00:06:05.520
+and then it will return them back out,
+
+00:06:05.520 --> 00:06:07.280
+or it'll just return the latest.
+
+06:07.280 --> 00:06:08.479
+And there's a simple example
+
+00:06:08.479 --> 00:06:09.600
+that shows it logging,
+
+00:06:09.600 --> 00:06:11.280
+and then shows it coming back out,
+
+00:06:11.280 --> 00:06:14.080
+pretty much what you would expect.
+
+06:14.080 --> 00:06:16.400
+Here's another class that adapts
+
+00:06:16.400 --> 00:06:19.039
+the `emms-player` to the `logger` class.
+
+00:06:19.039 --> 00:06:20.560
+It only extends the logger
+
+00:06:20.560 --> 00:06:22.400
+because it doesn't need any features
+
+00:06:22.400 --> 00:06:25.039
+of the `emms-player` class itself.
+
+00:06:25.039 --> 00:06:27.440
+It just implements methods that dispatch
+
+00:06:27.440 --> 00:06:30.240
+based on it being that logging player class,
+
+00:06:30.240 --> 00:06:31.759
+and you can see it logs whenever
+
+00:06:31.759 --> 00:06:34.240
+a track is started or stopped,
+
+00:06:34.240 --> 00:06:36.240
+and it also adds some track
+
+00:06:36.240 --> 00:06:37.520
+to tell you whether or not
+
+00:06:37.520 --> 00:06:38.560
+the track was playable,
+
+00:06:38.560 --> 00:06:41.199
+that is using the around method.
+
+00:06:41.199 --> 00:06:43.199
+So, you can see we have all three methods
+
+00:06:43.199 --> 00:06:45.280
+before, after, and around in this class,
+
+00:06:45.280 --> 00:06:48.160
+so you can see how those work.
+
+00:06:48.160 --> 00:06:49.440
+Then you need one more,
+
+00:06:49.440 --> 00:06:50.184
+which is the class
+
+00:06:50.184 --> 00:06:51.759
+that mixes it all together,
+
+00:06:51.759 --> 00:06:54.080
+So, that's the `logging-player-mpv`,
+
+00:06:54.080 --> 00:06:56.639
+and it extends both the `logging-player` class
+
+06:56.639 --> 00:06:59.680
+and the `emms-player-mpv` class.
+
+06:59.680 --> 00:07:01.440
+What's really interesting about this is
+
+07:01.440 --> 00:07:03.360
+that even though the logging player is
+
+07:03.360 --> 00:07:05.520
+part of the `emms-player` hierarchy,
+
+00:07:05.520 --> 00:07:06.472
+it doesn't depend on
+
+00:07:06.472 --> 00:07:08.240
+a specific implementation,
+
+00:07:08.240 --> 00:07:10.400
+so you can combine the two different
+
+00:07:10.400 --> 00:07:12.639
+classes that lets the logging class
+
+00:07:12.639 --> 00:07:13.919
+only care about logging,
+
+07:13.919 --> 00:07:15.440
+and the `emms-player` class
+
+00:07:15.440 --> 00:07:17.039
+only care about playing,
+
+00:07:17.039 --> 00:07:18.240
+and that is a really nice
+
+07:18.240 --> 00:07:19.599
+way of separating your concerns
+
+00:07:19.599 --> 00:07:21.440
+that I think is very powerful.
+
+07:21.440 --> 00:07:22.515
+Here's a quick example of
+
+00:07:22.515 --> 00:07:23.599
+just how that works,
+
+00:07:23.599 --> 00:07:25.199
+and you can see the `unplayable`
+
+07:25.199 --> 00:07:26.160
+track is not playable,
+
+00:07:26.160 --> 00:07:27.840
+and it gets logged as such,
+
+00:07:27.840 --> 00:07:29.360
+`foo` is playable, and you can see
+
+07:29.360 --> 00:07:31.120
+the logs in started and stopped.
+
+00:07:31.120 --> 00:07:32.560
+So, you can see it's having
+
+00:07:32.560 --> 00:07:34.000
+the side effects from those methods,
+
+00:07:34.000 --> 00:07:36.960
+and it's also returning
+
+00:07:36.960 --> 00:07:40.319
+the value off the player as well.
+
+07:40.319 --> 00:07:41.599
+I think this system has a bunch of
+
+07:41.599 --> 00:07:43.120
+really nice properties.
+
+07:43.120 --> 00:07:44.080
+First and foremost,
+
+00:07:44.080 --> 00:07:45.840
+it feels like a normal Lisp,
+
+00:07:45.840 --> 00:07:47.360
+all you're doing is calling functions,
+
+00:07:47.360 --> 00:07:49.840
+there's no magic involved.
+
+07:49.840 --> 00:07:51.919
+Also, you can use either or both of the
+
+07:51.919 --> 00:07:53.840
+classes or generic functions.
+
+00:07:53.840 --> 00:07:55.120
+If you only need to
+
+00:07:55.120 --> 00:07:56.960
+encapsulate data into a structure,
+
+00:07:56.960 --> 00:07:58.479
+then you can only use classes,
+
+07:58.479 --> 00:08:00.400
+you don't have to use generic functions.
+
+08:00.400 --> 00:08:02.080
+And if you only need dynamic dispatch,
+
+08:02.080 --> 00:08:03.068
+you can only implement
+
+00:08:03.068 --> 00:08:04.720
+a generic function and methods.
+
+00:08:04.720 --> 00:08:06.560
+You don't get forced into a model
+
+00:08:06.560 --> 00:08:08.000
+where you have to use both.
+
+00:08:08.000 --> 00:08:09.247
+You can mix and match for
+
+00:08:09.247 --> 00:08:10.800
+whatever needs your program has,
+
+00:08:10.800 --> 00:08:13.039
+which I think is really amazing.
+
+08:13.039 --> 00:08:15.440
+Any value can conform to an interface,
+
+08:15.440 --> 00:08:17.039
+meaning a generic function.
+
+00:08:17.039 --> 00:08:19.520
+So, you don't have to use those classes.
+
+00:08:19.520 --> 00:08:20.479
+You can even implement
+
+00:08:20.479 --> 00:08:22.240
+a generic function over `nil`,
+
+00:08:22.240 --> 00:08:23.599
+which gives you those really nice
+
+08:23.599 --> 00:08:24.800
+properties of Lisp,
+
+00:08:24.800 --> 00:08:26.460
+where you have nil-punning, you know,
+
+00:08:26.460 --> 00:08:28.800
+if you take the head of a nil list,
+
+00:08:28.800 --> 00:08:30.479
+then the output is `nil`,
+
+00:08:30.479 --> 00:08:31.283
+but you can do that
+
+00:08:31.283 --> 00:08:32.880
+with your object system too.
+
+00:08:32.880 --> 00:08:34.320
+And a really nice feature of that is
+
+08:34.320 --> 00:08:35.919
+that you have no possibility of
+
+00:08:35.919 --> 00:08:36.959
+null pointer exceptions
+
+00:08:36.959 --> 00:08:38.719
+like you do in other languages.
+
+00:08:38.719 --> 00:08:39.919
+They have a calling convention
+
+00:08:39.919 --> 00:08:42.880
+where you call object dot method,
+
+08:42.880 --> 00:08:45.600
+but in CLOS, you call a generic function,
+
+00:08:45.600 --> 00:08:47.279
+and you just give it some arguments.
+
+00:08:47.279 --> 00:08:48.959
+Typically, the first one is going to be
+
+00:08:48.959 --> 00:08:51.680
+an EIEIO class object,
+
+00:08:51.680 --> 00:08:53.200
+but it doesn't have to be,
+
+00:08:53.200 --> 00:08:54.640
+but because you're not calling that
+
+00:08:54.640 --> 00:08:55.519
+instance of an object,
+
+00:08:55.519 --> 00:08:57.279
+there's nothing to be nil in the first place,
+
+00:08:57.279 --> 00:08:58.320
+so there's no possibility of
+
+00:08:58.320 --> 00:09:00.080
+a nil pointer exception.
+
+09:00.080 --> 00:09:01.376
+And then the ability to
+
+00:09:01.376 --> 00:09:02.480
+have multiple inheritance
+
+00:09:02.480 --> 00:09:04.000
+and mix in all of these different
+
+00:09:04.000 --> 00:09:05.760
+functionalities into your final object
+
+00:09:05.760 --> 00:09:07.279
+is very powerful.
+
+09:07.279 --> 00:09:09.839
+Because you have multiple inheritance,
+
+00:09:09.839 --> 00:09:11.120
+your final object that
+
+00:09:11.120 --> 00:09:12.560
+composes all of those things
+
+00:09:12.560 --> 00:09:14.080
+is both a player and a logger,
+
+00:09:14.080 --> 00:09:15.600
+and it can be substituted into code
+
+00:09:15.600 --> 00:09:17.279
+that expects either of them.
+
+00:09:17.279 --> 00:09:19.040
+It's not an adapter class
+
+09:19.040 --> 00:09:21.360
+that only allows you to do one thing,
+
+00:09:21.360 --> 00:09:22.560
+it does both of them.
+
+00:09:22.560 --> 00:09:24.800
+I think that's amazing.
+
+09:24.800 --> 00:09:26.320
+So, here are some practical examples
+
+09:26.320 --> 00:09:27.387
+where I think maybe this
+
+00:09:27.387 --> 00:09:28.720
+could be a good idea.
+
+00:09:28.720 --> 00:09:30.399
+And I like to think about,
+
+09:30.399 --> 00:09:32.320
+"What is OOP actually good for?".
+
+00:09:32.320 --> 00:09:34.640
+I think it has three really amazing powers,
+
+09:34.640 --> 00:09:36.399
+encapsulation, abstraction,
+
+00:09:36.399 --> 00:09:37.279
+and extensibility,
+
+00:09:37.279 --> 00:09:39.200
+so let's look at those.
+
+09:39.200 --> 00:09:40.959
+Encapsulation is just keeping
+
+00:09:40.959 --> 00:09:42.480
+related data together.
+
+00:09:42.480 --> 00:09:43.680
+Here's an example from the
+
+09:43.680 --> 00:09:45.360
+transmission Torrent client.
+
+00:09:45.360 --> 00:09:46.399
+In order for it to work,
+
+00:09:46.399 --> 00:09:47.600
+it needs to have all four of
+
+09:47.600 --> 00:09:49.920
+these variables set consistently,
+
+00:09:49.920 --> 00:09:52.240
+but if you use the customization interface,
+
+09:52.240 --> 00:09:53.920
+they're kind of strewn all over the buffer
+
+00:09:53.920 --> 00:09:55.760
+because that shows them alphabetically
+
+00:09:55.760 --> 00:09:57.040
+by variable name instead of
+
+00:09:57.040 --> 00:09:59.920
+grouping them logically by function.
+
+09:59.920 --> 00:10:01.327
+You also have all these
+
+00:10:01.327 --> 00:10:02.480
+in the global namespace,
+
+00:10:02.480 --> 00:10:04.720
+so you need this disambiguation in front,
+
+00:10:04.720 --> 00:10:06.800
+you have to have a transmission prefix,
+
+00:10:06.800 --> 00:10:08.720
+so it's kind of ugly.
+
+10:08.720 --> 00:10:10.240
+An alternative example would be to
+
+10:10.240 --> 00:10:11.760
+encapsulate all of that
+
+00:10:11.760 --> 00:10:13.360
+in a single class.
+
+10:13.360 --> 00:10:16.160
+This has one slot for each of those values,
+
+00:10:16.160 --> 00:10:17.040
+except the username
+
+00:10:17.040 --> 00:10:18.000
+and password is broken out,
+
+00:10:18.000 --> 00:10:20.240
+there was only one in the previous example,
+
+00:10:20.240 --> 00:10:23.120
+but it works pretty much the same.
+
+10:23.120 --> 00:10:25.200
+The really neat thing about this is that
+
+10:25.200 --> 00:10:27.279
+the customization interface understands
+
+10:27.279 --> 00:10:29.920
+how to customize EIEIO objects,
+
+00:10:29.920 --> 00:10:32.640
+so you can set your custom variable
+
+00:10:32.640 --> 00:10:34.000
+to the value of an object,
+
+00:10:34.000 --> 00:10:35.760
+and in the customization interface,
+
+00:10:35.760 --> 00:10:37.040
+it shows you all of the fields,
+
+00:10:37.040 --> 00:10:38.399
+and it lets you edit the values
+
+00:10:38.399 --> 00:10:40.079
+of those slots directly.
+
+00:10:40.079 --> 00:10:41.760
+So, that keeps that logical grouping
+
+00:10:41.760 --> 00:10:44.800
+that I think makes things really easy to use.
+
+10:44.800 --> 00:10:46.160
+Another thing it's really good at is
+
+10:46.160 --> 00:10:48.268
+abstraction, and this is really core to
+
+00:10:48.268 --> 00:10:49.408
+a lot of what Emacs does
+
+00:10:49.408 --> 00:10:51.200
+because it runs on so many different systems,
+
+00:10:51.200 --> 00:10:53.308
+and it works with so many different
+
+00:10:53.308 --> 00:10:55.120
+kinds of similar tools.
+
+10:55.120 --> 00:10:56.109
+Here's an example from
+
+00:10:56.109 --> 00:10:58.079
+the built-in SQL implementation.
+
+00:10:58.079 --> 00:10:59.360
+This is the definition of
+
+00:10:59.360 --> 00:11:01.040
+the postgres backend,
+
+00:11:01.040 --> 00:11:02.160
+there's one of these for
+
+00:11:02.160 --> 00:11:04.000
+every supported database backend.
+
+00:11:04.000 --> 00:11:05.440
+And you can see, this is a pretty
+
+11:05.440 --> 00:11:08.480
+classic interface abstraction pattern.
+
+11:08.480 --> 00:11:09.680
+On the left-hand side,
+
+00:11:09.680 --> 00:11:10.880
+you have a symbol that's common
+
+00:11:10.880 --> 00:11:12.399
+among all the database backends,
+
+00:11:12.399 --> 00:11:14.160
+and the code that doesn't
+
+00:11:14.160 --> 00:11:16.240
+know about the implementation can use,
+
+00:11:16.240 --> 00:11:17.519
+no matter what implementation
+
+00:11:17.519 --> 00:11:19.040
+is being specified.
+
+00:11:19.040 --> 00:11:20.000
+On the right-hand side,
+
+00:11:20.000 --> 00:11:21.120
+you have the implementation
+
+00:11:21.120 --> 00:11:22.560
+specific values,
+
+00:11:22.560 --> 00:11:24.399
+in some cases these are just strings,
+
+00:11:24.399 --> 00:11:25.760
+or regexes, and in others
+
+00:11:25.760 --> 00:11:27.519
+those are actual functions.
+
+11:27.519 --> 00:11:29.440
+So, really this already is
+
+00:11:29.440 --> 00:11:30.720
+object orientation,
+
+00:11:30.720 --> 00:11:32.959
+it's just an ad-hoc system for it,
+
+00:11:32.959 --> 00:11:34.880
+but you don't have to use an ad-hoc system
+
+00:11:34.880 --> 00:11:35.519
+because there's this
+
+00:11:35.519 --> 00:11:38.000
+nice formal one instead.
+
+11:38.000 --> 00:11:38.880
+Another thing that it's
+
+00:11:38.880 --> 00:11:40.959
+really good at is extensibility,
+
+00:11:40.959 --> 00:11:42.160
+we saw some of that with
+
+00:11:42.160 --> 00:11:44.800
+the emms-player example earlier.
+
+00:11:44.800 --> 00:11:46.160
+But here's another thing I think
+
+00:11:46.160 --> 00:11:48.720
+it would be interesting to explore.
+
+11:48.720 --> 00:11:51.279
+Emacs has this idea of derived modes
+
+11:51.279 --> 00:11:52.639
+where you have a mode that's based on
+
+11:52.639 --> 00:11:54.639
+another, and that's a pretty clear
+
+11:54.639 --> 00:11:57.040
+inheritance pattern straight out of OOP
+
+11:57.040 --> 00:11:58.560
+as far as I'm concerned.
+
+00:11:58.560 --> 00:12:00.079
+What would it look like
+
+00:12:00.079 --> 00:12:02.959
+if major modes were EIEIO classes,
+
+00:12:02.959 --> 00:12:04.800
+and you could extend your mode
+
+12:04.800 --> 00:12:06.399
+by extending the class.
+
+00:12:06.399 --> 00:12:08.240
+I think that's a really interesting idea,
+
+00:12:08.240 --> 00:12:10.880
+and I'd like to explore that more.
+
+12:10.880 --> 00:12:14.079
+In conclusion, I think EIEIO is amazing,
+
+12:14.079 --> 00:12:16.079
+and I had no idea that such a powerful
+
+12:16.079 --> 00:12:18.079
+object orientation system
+
+00:12:18.079 --> 00:12:20.160
+was available in the Emacs.
+
+12:20.160 --> 00:12:21.519
+My goal with this talk
+
+00:12:21.519 --> 00:12:23.519
+is for anyone who writes Emacs Lisp,
+
+00:12:23.519 --> 00:12:25.360
+to look at these classes of problems,
+
+00:12:25.360 --> 00:12:27.360
+encapsulation, abstraction,
+
+00:12:27.360 --> 00:12:28.639
+and extensibility,
+
+00:12:28.639 --> 00:12:29.600
+and if you run into
+
+00:12:29.600 --> 00:12:31.279
+those problems in your code,
+
+12:31.279 --> 00:12:33.279
+instead of immediately reaching
+
+00:12:33.279 --> 00:12:34.959
+and building your own system,
+
+00:12:34.959 --> 00:12:35.760
+I want you to think:
+
+00:12:35.760 --> 00:12:37.279
+"Oh there's a thing for that,
+
+00:12:37.279 --> 00:12:39.040
+and I can just use it."
+
+12:39.040 --> 00:12:40.560
+That's my talk, thanks.
+
+00:12:40.560 --> 00:12:41.560
+Hack on!
+
+00:12:41.560 --> 00:12:43.880
+[captions by bhavin192 (Bhavin Gandhi)]
diff --git a/2021/captions/form.md b/2021/captions/form.md
new file mode 100644
index 00000000..76984b28
--- /dev/null
+++ b/2021/captions/form.md
@@ -0,0 +1,430 @@
+<a name="transcript"></a>
+# Transcript
+
+[[!template text="My name is Ian Eure," start="00:00:01.199" video="mainVideo" id=subtitle]]
+[[!template text="and welcome to my talk" start="00:00:02.320" video="mainVideo" id=subtitle]]
+[[!template text="&quot;Old McCarthy Had a Form&quot;." start="00:00:03.199" video="mainVideo" id=subtitle]]
+[[!template text="In this talk," start="00:00:05.120" video="mainVideo" id=subtitle]]
+[[!template text="I'm going to be discussing EIEIO," start="00:00:05.759" video="mainVideo" id=subtitle]]
+[[!template text="which is an Emacs Lisp implementation" start="00:00:07.759" video="mainVideo" id=subtitle]]
+[[!template text="of the Common Lisp object system." start="00:00:09.920" video="mainVideo" id=subtitle]]
+[[!template text="CLOS is a way of writing" start="00:00:12.320" video="mainVideo" id=subtitle]]
+[[!template text="object-oriented Common Lisp code," start="00:00:13.519" video="mainVideo" id=subtitle]]
+[[!template text="and with EIEIO you have much of that same" start="00:00:15.360" video="mainVideo" id=subtitle]]
+[[!template text="power but inside Emacs." start="00:00:17.920" video="mainVideo" id=subtitle]]
+[[!template text="I'm going to be using those two names" start="00:00:19.920" video="mainVideo" id=subtitle]]
+[[!template text="interchangeably throughout this talk," start="00:00:21.359" video="mainVideo" id=subtitle]]
+[[!template text="since they're nearly equivalent." start="00:00:22.988" video="mainVideo" id=subtitle]]
+[[!template text="You might wonder," start="00:00:26.640" video="mainVideo" id=subtitle]]
+[[!template text="&quot;Why would I want to write" start="00:00:27.534" video="mainVideo" id=subtitle]]
+[[!template text="object Emacs Lisp code?&quot;." start="00:00:28.880" video="mainVideo" id=subtitle]]
+[[!template text="I like it because I like writing" start="00:00:31.439" video="mainVideo" id=subtitle]]
+[[!template text="in a functional programming style," start="00:00:33.440" video="mainVideo" id=subtitle]]
+[[!template text="or I like to do an imperative style" start="00:00:34.960" video="mainVideo" id=subtitle]]
+[[!template text="that captures interactive key sequences" start="00:00:36.896" video="mainVideo" id=subtitle]]
+[[!template text="that I might enter manually." start="00:00:39.040" video="mainVideo" id=subtitle]]
+[[!template text="Well, I think, different kinds of programs" start="00:00:41.200" video="mainVideo" id=subtitle]]
+[[!template text="need different kind of programming paradigms," start="00:00:42.800" video="mainVideo" id=subtitle]]
+[[!template text="and sometimes OOP is the one that fits." start="00:00:45.120" video="mainVideo" id=subtitle]]
+[[!template text="Also, if you've done much OOP before," start="00:00:47.760" video="mainVideo" id=subtitle]]
+[[!template text="you might be surprised by" start="00:00:49.708" video="mainVideo" id=subtitle]]
+[[!template text="how EIEIO works and the sorts of power" start="00:00:50.655" video="mainVideo" id=subtitle]]
+[[!template text="that it brings to your programs." start="00:00:52.879" video="mainVideo" id=subtitle]]
+[[!template text="So, let's talk about that model now." start="00:00:55.039" video="mainVideo" id=subtitle]]
+[[!template text="Classes are pretty much what" start="00:00:58.480" video="mainVideo" id=subtitle]]
+[[!template text="you would expect if you've done" start="00:01:00.000" video="mainVideo" id=subtitle]]
+[[!template text="OOP programming before." start="00:01:01.120" video="mainVideo" id=subtitle]]
+[[!template text="In the CLOS model," start="00:01:02.879" video="mainVideo" id=subtitle]]
+[[!template text="they only have fields," start="00:01:04.400" video="mainVideo" id=subtitle]]
+[[!template text="they only encapsulate values," start="00:01:06.400" video="mainVideo" id=subtitle]]
+[[!template text="they don't have anything to do with methods." start="00:01:08.000" video="mainVideo" id=subtitle]]
+[[!template text="So, in this case, we have a base class for" start="00:01:10.720" video="mainVideo" id=subtitle]]
+[[!template text="an EMMS player backend," start="00:01:13.040" video="mainVideo" id=subtitle]]
+[[!template text="and it has one field (a slot is what" start="00:01:15.040" video="mainVideo" id=subtitle]]
+[[!template text="it's called in CLOS terminology)," start="00:01:18.159" video="mainVideo" id=subtitle]]
+[[!template text="which indicates whether it's playing or not," start="00:01:20.000" video="mainVideo" id=subtitle]]
+[[!template text="and it's declared abstract," start="00:01:22.720" video="mainVideo" id=subtitle]]
+[[!template text="so you can't create an instance" start="00:01:24.080" video="mainVideo" id=subtitle]]
+[[!template text="of an object based on this class," start="00:01:25.439" video="mainVideo" id=subtitle]]
+[[!template text="you can only extend it with another class," start="00:01:27.040" video="mainVideo" id=subtitle]]
+[[!template text="that's an EIEIO extension," start="00:01:29.280" video="mainVideo" id=subtitle]]
+[[!template text="but I think it's a pretty good one." start="00:01:31.119" video="mainVideo" id=subtitle]]
+[[!template text="You can also see there's a class" start="00:01:33.439" video="mainVideo" id=subtitle]]
+[[!template text="that implements an mpv player back-end," start="00:01:34.640" video="mainVideo" id=subtitle]]
+[[!template text="and it extends the base class," start="00:01:37.119" video="mainVideo" id=subtitle]]
+[[!template text="it doesn't add any slots," start="00:01:39.680" video="mainVideo" id=subtitle]]
+[[!template text="and those get inherited from the base class." start="00:01:40.960" video="mainVideo" id=subtitle]]
+[[!template text="If you want these to do much more" start="00:01:44.479" video="mainVideo" id=subtitle]]
+[[!template text="than encapsulate data," start="00:01:45.936" video="mainVideo" id=subtitle]]
+[[!template text="you need to start writing methods." start="00:01:46.960" video="mainVideo" id=subtitle]]
+[[!template text="The CLOS model is to have" start="00:01:48.880" video="mainVideo" id=subtitle]]
+[[!template text="a generic function." start="00:01:50.324" video="mainVideo" id=subtitle]]
+[[!template text="A generic function is" start="00:01:51.439" video="mainVideo" id=subtitle]]
+[[!template text="kind of like an interface," start="00:01:52.399" video="mainVideo" id=subtitle]]
+[[!template text="it's just a name and an argument list," start="00:01:53.680" video="mainVideo" id=subtitle]]
+[[!template text="and there's no implementation," start="00:01:55.600" video="mainVideo" id=subtitle]]
+[[!template text="you have to write a method" start="00:01:57.280" video="mainVideo" id=subtitle]]
+[[!template text="in order to have an actual implementation." start="00:01:58.560" video="mainVideo" id=subtitle]]
+[[!template text="When you call the generic function," start="00:02:00.960" video="mainVideo" id=subtitle]]
+[[!template text="the system will do a dynamic dispatch" start="00:02:02.880" video="mainVideo" id=subtitle]]
+[[!template text="to a method that matches based on" start="00:02:04.960" video="mainVideo" id=subtitle]]
+[[!template text="its argument types and how the method" start="00:02:06.560" video="mainVideo" id=subtitle]]
+[[!template text="has declared that it should be invoked." start="00:02:08.319" video="mainVideo" id=subtitle]]
+[[!template text="Here's an example of some methods" start="00:02:12.239" video="mainVideo" id=subtitle]]
+[[!template text="for our mpv player backend," start="00:02:14.239" video="mainVideo" id=subtitle]]
+[[!template text="you can see that it'll play anything" start="00:02:16.480" video="mainVideo" id=subtitle]]
+[[!template text="other than something" start="00:02:19.599" video="mainVideo" id=subtitle]]
+[[!template text="with a keyword of `unplayable`," start="00:02:21.200" video="mainVideo" id=subtitle]]
+[[!template text="and it just has dummy start and stop methods" start="00:02:23.200" video="mainVideo" id=subtitle]]
+[[!template text="that return &quot;Started&quot; and &quot;Stopped&quot; text." start="00:02:25.328" video="mainVideo" id=subtitle]]
+[[!template text="A method is just one implementation" start="00:02:27.680" video="mainVideo" id=subtitle]]
+[[!template text="of a generic function," start="00:02:29.599" video="mainVideo" id=subtitle]]
+[[!template text="and you can have as many as you need." start="00:02:30.552" video="mainVideo" id=subtitle]]
+[[!template text="In order to determine" start="00:02:32.640" video="mainVideo" id=subtitle]]
+[[!template text="which method gets dispatched" start="00:02:33.920" video="mainVideo" id=subtitle]]
+[[!template text="when you call a generic function," start="00:02:35.519" video="mainVideo" id=subtitle]]
+[[!template text="they're specialized based on" start="00:02:36.879" video="mainVideo" id=subtitle]]
+[[!template text="their argument type." start="00:02:38.080" video="mainVideo" id=subtitle]]
+[[!template text="In this case, you can see that" start="00:02:39.360" video="mainVideo" id=subtitle]]
+[[!template text="first argument says" start="00:02:40.640" video="mainVideo" id=subtitle]]
+[[!template text="`player talk/emms-player-mpv`," start="00:02:41.680" video="mainVideo" id=subtitle]]
+[[!template text="that means that if that first argument" start="00:02:44.480" video="mainVideo" id=subtitle]]
+[[!template text="is an instance of the mpv player" start="00:02:46.239" video="mainVideo" id=subtitle]]
+[[!template text="or a subclass of it," start="00:02:48.480" video="mainVideo" id=subtitle]]
+[[!template text="then those methods will be invoked," start="00:02:50.080" video="mainVideo" id=subtitle]]
+[[!template text="unless there's a more specific one" start="00:02:52.000" video="mainVideo" id=subtitle]]
+[[!template text="based on that argument type." start="00:02:53.560" video="mainVideo" id=subtitle]]
+[[!template text="You don't have to define" start="00:02:55.440" video="mainVideo" id=subtitle]]
+[[!template text="the generic functions." start="00:02:56.656" video="mainVideo" id=subtitle]]
+[[!template text="If you define a method," start="00:02:57.760" video="mainVideo" id=subtitle]]
+[[!template text="then it'll implicitly define" start="00:02:59.040" video="mainVideo" id=subtitle]]
+[[!template text="the generic function for you." start="00:03:00.451" video="mainVideo" id=subtitle]]
+[[!template text="Specialization is really powerful." start="00:03:03.599" video="mainVideo" id=subtitle]]
+[[!template text="It lets the methods define" start="00:03:05.440" video="mainVideo" id=subtitle]]
+[[!template text="how they get invoked" start="00:03:06.939" video="mainVideo" id=subtitle]]
+[[!template text="If you've done much programming in Clojure," start="00:03:08.400" video="mainVideo" id=subtitle]]
+[[!template text="this sounds a little bit like multi-methods," start="00:03:10.472" video="mainVideo" id=subtitle]]
+[[!template text="but with multi-methods, only the main method," start="00:03:12.959" video="mainVideo" id=subtitle]]
+[[!template text="the equivalent of the generic function," start="00:03:16.319" video="mainVideo" id=subtitle]]
+[[!template text="can determine how they're dispatched." start="00:03:18.000" video="mainVideo" id=subtitle]]
+[[!template text="So, as the writer of an interface," start="00:03:19.920" video="mainVideo" id=subtitle]]
+[[!template text="you might not be able to foresee" start="00:03:21.519" video="mainVideo" id=subtitle]]
+[[!template text="every way that someone who's implementing" start="00:03:23.120" video="mainVideo" id=subtitle]]
+[[!template text="a version of that interface" start="00:03:25.519" video="mainVideo" id=subtitle]]
+[[!template text="would like to dispatch." start="00:03:26.959" video="mainVideo" id=subtitle]]
+[[!template text="CLOS doesn't have that problem," start="00:03:28.400" video="mainVideo" id=subtitle]]
+[[!template text="you get to define your" start="00:03:29.920" video="mainVideo" id=subtitle]]
+[[!template text="own invocation semantics." start="00:03:31.200" video="mainVideo" id=subtitle]]
+[[!template text="You're also not limited to" start="00:03:34.080" video="mainVideo" id=subtitle]]
+[[!template text="dispatching based on the value" start="00:03:35.360" video="mainVideo" id=subtitle]]
+[[!template text="being a subclass of an EIEIO type." start="00:03:37.200" video="mainVideo" id=subtitle]]
+[[!template text="You can dispatch based on" start="00:03:39.920" video="mainVideo" id=subtitle]]
+[[!template text="a primitive type like integer," start="00:03:41.280" video="mainVideo" id=subtitle]]
+[[!template text="you can dispatch based on the value," start="00:03:42.879" video="mainVideo" id=subtitle]]
+[[!template text="you can dispatch on multiple arguments," start="00:03:45.360" video="mainVideo" id=subtitle]]
+[[!template text="and there's also a default dispatch" start="00:03:47.599" video="mainVideo" id=subtitle]]
+[[!template text="that will get applied" start="00:03:49.599" video="mainVideo" id=subtitle]]
+[[!template text="if there's no others that are defined." start="00:03:50.688" video="mainVideo" id=subtitle]]
+[[!template text="If you don't have a default," start="00:03:53.200" video="mainVideo" id=subtitle]]
+[[!template text="then you'll just get an error" start="00:03:54.319" video="mainVideo" id=subtitle]]
+[[!template text="from the system," start="00:03:55.439" video="mainVideo" id=subtitle]]
+[[!template text="and if that doesn't cover it," start="00:03:56.480" video="mainVideo" id=subtitle]]
+[[!template text="you can even define your own." start="00:03:57.439" video="mainVideo" id=subtitle]]
+[[!template text="Definition is with the" start="00:03:59.040" video="mainVideo" id=subtitle]]
+[[!template text="`cl-generic-generalizers`," start="00:04:00.239" video="mainVideo" id=subtitle]]
+[[!template text="which is itself a generic function." start="00:04:01.760" video="mainVideo" id=subtitle]]
+[[!template text="Much of CLOS is built in CLOS," start="00:04:03.680" video="mainVideo" id=subtitle]]
+[[!template text="which I think is really cool." start="00:04:05.680" video="mainVideo" id=subtitle]]
+[[!template text="In addition to all that," start="00:04:08.319" video="mainVideo" id=subtitle]]
+[[!template text="you have four different types of methods," start="00:04:09.599" video="mainVideo" id=subtitle]]
+[[!template text="and those are distinguished by" start="00:04:12.319" video="mainVideo" id=subtitle]]
+[[!template text="what's called a qualifier." start="00:04:13.680" video="mainVideo" id=subtitle]]
+[[!template text="Every function can have methods" start="00:04:16.000" video="mainVideo" id=subtitle]]
+[[!template text="that have all four different" start="00:04:18.400" video="mainVideo" id=subtitle]]
+[[!template text="types of qualifiers," start="00:04:20.239" video="mainVideo" id=subtitle]]
+[[!template text="and based on your class inheritance," start="00:04:21.280" video="mainVideo" id=subtitle]]
+[[!template text="you might have multiple of each type." start="00:04:22.960" video="mainVideo" id=subtitle]]
+[[!template text="There's the primary method," start="00:04:25.680" video="mainVideo" id=subtitle]]
+[[!template text="which is equivalent to the method" start="00:04:26.800" video="mainVideo" id=subtitle]]
+[[!template text="in any other OOP system," start="00:04:28.560" video="mainVideo" id=subtitle]]
+[[!template text="so we're not going to cover that too much." start="00:04:29.919" video="mainVideo" id=subtitle]]
+[[!template text="Then there's a `before` method." start="00:04:32.160" video="mainVideo" id=subtitle]]
+[[!template text="This is evaluated before" start="00:04:33.759" video="mainVideo" id=subtitle]]
+[[!template text="the primary method for side effects," start="00:04:35.600" video="mainVideo" id=subtitle]]
+[[!template text="and its return value is discarded." start="00:04:37.440" video="mainVideo" id=subtitle]]
+[[!template text="There's an `after` method," start="00:04:40.080" video="mainVideo" id=subtitle]]
+[[!template text="which is the same but happens after" start="00:04:41.120" video="mainVideo" id=subtitle]]
+[[!template text="the method has finished evaluating." start="00:04:42.560" video="mainVideo" id=subtitle]]
+[[!template text="And then there's an `around` method" start="00:04:44.479" video="mainVideo" id=subtitle]]
+[[!template text="that happens around all the other three." start="00:04:46.639" video="mainVideo" id=subtitle]]
+[[!template text="And by using these types of methods" start="00:04:49.199" video="mainVideo" id=subtitle]]
+[[!template text="and using class inheritance" start="00:04:51.120" video="mainVideo" id=subtitle]]
+[[!template text="to compose them into your classes," start="00:04:52.560" video="mainVideo" id=subtitle]]
+[[!template text="you can add some really powerful" start="00:04:54.560" video="mainVideo" id=subtitle]]
+[[!template text="mixin type functionality." start="00:04:56.479" video="mainVideo" id=subtitle]]
+[[!template text="You can use before and after" start="00:04:58.240" video="mainVideo" id=subtitle]]
+[[!template text="to build things like logging," start="00:04:59.764" video="mainVideo" id=subtitle]]
+[[!template text="and you can use around" start="00:05:01.280" video="mainVideo" id=subtitle]]
+[[!template text="to implement things like memoization." start="00:05:02.479" video="mainVideo" id=subtitle]]
+[[!template text="If you've done much Emacs Lisp programming," start="00:05:04.880" video="mainVideo" id=subtitle]]
+[[!template text="those before after and around" start="00:05:06.720" video="mainVideo" id=subtitle]]
+[[!template text="might jog your memory because" start="00:05:08.160" video="mainVideo" id=subtitle]]
+[[!template text="they're the same features you get" start="00:05:09.919" video="mainVideo" id=subtitle]]
+[[!template text="with Emacs's built-in function advice." start="00:05:11.440" video="mainVideo" id=subtitle]]
+[[!template text="The thing with function advice is that" start="00:05:14.160" video="mainVideo" id=subtitle]]
+[[!template text="it only works on functions" start="00:05:15.680" video="mainVideo" id=subtitle]]
+[[!template text="in the global namespace," start="00:05:17.199" video="mainVideo" id=subtitle]]
+[[!template text="and there's no kind of conditionality," start="00:05:18.240" video="mainVideo" id=subtitle]]
+[[!template text="they always get dispatched" start="00:05:20.360" video="mainVideo" id=subtitle]]
+[[!template text="when that function is invoked." start="00:05:21.840" video="mainVideo" id=subtitle]]
+[[!template text="The nice thing about the CLOS system is that" start="00:05:23.440" video="mainVideo" id=subtitle]]
+[[!template text="whether they get invoked or not" start="00:05:25.600" video="mainVideo" id=subtitle]]
+[[!template text="depends on whether they exist in" start="00:05:27.039" video="mainVideo" id=subtitle]]
+[[!template text="the class hierarchy," start="00:05:28.872" video="mainVideo" id=subtitle]]
+[[!template text="so you can add them to your" start="00:05:30.160" video="mainVideo" id=subtitle]]
+[[!template text="class hierarchy if you want" start="00:05:31.520" video="mainVideo" id=subtitle]]
+[[!template text="that extra functionality" start="00:05:32.880" video="mainVideo" id=subtitle]]
+[[!template text="like logging or memoization," start="00:05:34.000" video="mainVideo" id=subtitle]]
+[[!template text="and you can exclude it if you don't." start="00:05:35.440" video="mainVideo" id=subtitle]]
+[[!template text="I think that's really powerful" start="00:05:37.120" video="mainVideo" id=subtitle]]
+[[!template text="and a very interesting way of doing it." start="00:05:38.320" video="mainVideo" id=subtitle]]
+[[!template text="It also supports multiple inheritance," start="00:05:42.639" video="mainVideo" id=subtitle]]
+[[!template text="which is the mechanism that you can use" start="00:05:44.639" video="mainVideo" id=subtitle]]
+[[!template text="to compose all these different kinds of" start="00:05:46.639" video="mainVideo" id=subtitle]]
+[[!template text="behaviors into a single object that does" start="00:05:48.560" video="mainVideo" id=subtitle]]
+[[!template text="all the things that you want." start="00:05:50.479" video="mainVideo" id=subtitle]]
+[[!template text="Here's a quick example of a logger." start="00:05:52.240" video="mainVideo" id=subtitle]]
+[[!template text="So, you can see the class just has" start="00:05:54.720" video="mainVideo" id=subtitle]]
+[[!template text="a single slot called `messages`," start="00:05:56.240" video="mainVideo" id=subtitle]]
+[[!template text="it has a `log` method" start="00:05:58.319" video="mainVideo" id=subtitle]]
+[[!template text="that pushes a new message," start="00:05:59.840" video="mainVideo" id=subtitle]]
+[[!template text="which is a format string, into that," start="00:06:01.440" video="mainVideo" id=subtitle]]
+[[!template text="and then it will return them back out," start="00:06:03.840" video="mainVideo" id=subtitle]]
+[[!template text="or it'll just return the latest." start="00:06:05.520" video="mainVideo" id=subtitle]]
+[[!template text="And there's a simple example" start="00:06:07.280" video="mainVideo" id=subtitle]]
+[[!template text="that shows it logging," start="00:06:08.479" video="mainVideo" id=subtitle]]
+[[!template text="and then shows it coming back out," start="00:06:09.600" video="mainVideo" id=subtitle]]
+[[!template text="pretty much what you would expect." start="00:06:11.280" video="mainVideo" id=subtitle]]
+[[!template text="Here's another class that adapts" start="00:06:14.080" video="mainVideo" id=subtitle]]
+[[!template text="the `emms-player` to the `logger` class." start="00:06:16.400" video="mainVideo" id=subtitle]]
+[[!template text="It only extends the logger" start="00:06:19.039" video="mainVideo" id=subtitle]]
+[[!template text="because it doesn't need any features" start="00:06:20.560" video="mainVideo" id=subtitle]]
+[[!template text="of the `emms-player` class itself." start="00:06:22.400" video="mainVideo" id=subtitle]]
+[[!template text="It just implements methods that dispatch" start="00:06:25.039" video="mainVideo" id=subtitle]]
+[[!template text="based on it being that logging player class," start="00:06:27.440" video="mainVideo" id=subtitle]]
+[[!template text="and you can see it logs whenever" start="00:06:30.240" video="mainVideo" id=subtitle]]
+[[!template text="a track is started or stopped," start="00:06:31.759" video="mainVideo" id=subtitle]]
+[[!template text="and it also adds some track" start="00:06:34.240" video="mainVideo" id=subtitle]]
+[[!template text="to tell you whether or not" start="00:06:36.240" video="mainVideo" id=subtitle]]
+[[!template text="the track was playable," start="00:06:37.520" video="mainVideo" id=subtitle]]
+[[!template text="that is using the around method." start="00:06:38.560" video="mainVideo" id=subtitle]]
+[[!template text="So, you can see we have all three methods" start="00:06:41.199" video="mainVideo" id=subtitle]]
+[[!template text="before, after, and around in this class," start="00:06:43.199" video="mainVideo" id=subtitle]]
+[[!template text="so you can see how those work." start="00:06:45.280" video="mainVideo" id=subtitle]]
+[[!template text="Then you need one more," start="00:06:48.160" video="mainVideo" id=subtitle]]
+[[!template text="which is the class" start="00:06:49.440" video="mainVideo" id=subtitle]]
+[[!template text="that mixes it all together," start="00:06:50.184" video="mainVideo" id=subtitle]]
+[[!template text="So, that's the `logging-player-mpv`," start="00:06:51.759" video="mainVideo" id=subtitle]]
+[[!template text="and it extends both the `logging-player` class" start="00:06:54.080" video="mainVideo" id=subtitle]]
+[[!template text="and the `emms-player-mpv` class." start="00:06:56.639" video="mainVideo" id=subtitle]]
+[[!template text="What's really interesting about this is" start="00:06:59.680" video="mainVideo" id=subtitle]]
+[[!template text="that even though the logging player is" start="00:07:01.440" video="mainVideo" id=subtitle]]
+[[!template text="part of the `emms-player` hierarchy," start="00:07:03.360" video="mainVideo" id=subtitle]]
+[[!template text="it doesn't depend on" start="00:07:05.520" video="mainVideo" id=subtitle]]
+[[!template text="a specific implementation," start="00:07:06.472" video="mainVideo" id=subtitle]]
+[[!template text="so you can combine the two different" start="00:07:08.240" video="mainVideo" id=subtitle]]
+[[!template text="classes that lets the logging class" start="00:07:10.400" video="mainVideo" id=subtitle]]
+[[!template text="only care about logging," start="00:07:12.639" video="mainVideo" id=subtitle]]
+[[!template text="and the `emms-player` class" start="00:07:13.919" video="mainVideo" id=subtitle]]
+[[!template text="only care about playing," start="00:07:15.440" video="mainVideo" id=subtitle]]
+[[!template text="and that is a really nice" start="00:07:17.039" video="mainVideo" id=subtitle]]
+[[!template text="way of separating your concerns" start="00:07:18.240" video="mainVideo" id=subtitle]]
+[[!template text="that I think is very powerful." start="00:07:19.599" video="mainVideo" id=subtitle]]
+[[!template text="Here's a quick example of" start="00:07:21.440" video="mainVideo" id=subtitle]]
+[[!template text="just how that works," start="00:07:22.515" video="mainVideo" id=subtitle]]
+[[!template text="and you can see the `unplayable`" start="00:07:23.599" video="mainVideo" id=subtitle]]
+[[!template text="track is not playable," start="00:07:25.199" video="mainVideo" id=subtitle]]
+[[!template text="and it gets logged as such," start="00:07:26.160" video="mainVideo" id=subtitle]]
+[[!template text="`foo` is playable, and you can see" start="00:07:27.840" video="mainVideo" id=subtitle]]
+[[!template text="the logs in started and stopped." start="00:07:29.360" video="mainVideo" id=subtitle]]
+[[!template text="So, you can see it's having" start="00:07:31.120" video="mainVideo" id=subtitle]]
+[[!template text="the side effects from those methods," start="00:07:32.560" video="mainVideo" id=subtitle]]
+[[!template text="and it's also returning" start="00:07:34.000" video="mainVideo" id=subtitle]]
+[[!template text="the value off the player as well." start="00:07:36.960" video="mainVideo" id=subtitle]]
+[[!template text="I think this system has a bunch of" start="00:07:40.319" video="mainVideo" id=subtitle]]
+[[!template text="really nice properties." start="00:07:41.599" video="mainVideo" id=subtitle]]
+[[!template text="First and foremost," start="00:07:43.120" video="mainVideo" id=subtitle]]
+[[!template text="it feels like a normal Lisp," start="00:07:44.080" video="mainVideo" id=subtitle]]
+[[!template text="all you're doing is calling functions," start="00:07:45.840" video="mainVideo" id=subtitle]]
+[[!template text="there's no magic involved." start="00:07:47.360" video="mainVideo" id=subtitle]]
+[[!template text="Also, you can use either or both of the" start="00:07:49.840" video="mainVideo" id=subtitle]]
+[[!template text="classes or generic functions." start="00:07:51.919" video="mainVideo" id=subtitle]]
+[[!template text="If you only need to" start="00:07:53.840" video="mainVideo" id=subtitle]]
+[[!template text="encapsulate data into a structure," start="00:07:55.120" video="mainVideo" id=subtitle]]
+[[!template text="then you can only use classes," start="00:07:56.960" video="mainVideo" id=subtitle]]
+[[!template text="you don't have to use generic functions." start="00:07:58.479" video="mainVideo" id=subtitle]]
+[[!template text="And if you only need dynamic dispatch," start="00:08:00.400" video="mainVideo" id=subtitle]]
+[[!template text="you can only implement" start="00:08:02.080" video="mainVideo" id=subtitle]]
+[[!template text="a generic function and methods." start="00:08:03.068" video="mainVideo" id=subtitle]]
+[[!template text="You don't get forced into a model" start="00:08:04.720" video="mainVideo" id=subtitle]]
+[[!template text="where you have to use both." start="00:08:06.560" video="mainVideo" id=subtitle]]
+[[!template text="You can mix and match for" start="00:08:08.000" video="mainVideo" id=subtitle]]
+[[!template text="whatever needs your program has," start="00:08:09.247" video="mainVideo" id=subtitle]]
+[[!template text="which I think is really amazing." start="00:08:10.800" video="mainVideo" id=subtitle]]
+[[!template text="Any value can conform to an interface," start="00:08:13.039" video="mainVideo" id=subtitle]]
+[[!template text="meaning a generic function." start="00:08:15.440" video="mainVideo" id=subtitle]]
+[[!template text="So, you don't have to use those classes." start="00:08:17.039" video="mainVideo" id=subtitle]]
+[[!template text="You can even implement" start="00:08:19.520" video="mainVideo" id=subtitle]]
+[[!template text="a generic function over `nil`," start="00:08:20.479" video="mainVideo" id=subtitle]]
+[[!template text="which gives you those really nice" start="00:08:22.240" video="mainVideo" id=subtitle]]
+[[!template text="properties of Lisp," start="00:08:23.599" video="mainVideo" id=subtitle]]
+[[!template text="where you have nil-punning, you know," start="00:08:24.800" video="mainVideo" id=subtitle]]
+[[!template text="if you take the head of a nil list," start="00:08:26.460" video="mainVideo" id=subtitle]]
+[[!template text="then the output is `nil`," start="00:08:28.800" video="mainVideo" id=subtitle]]
+[[!template text="but you can do that" start="00:08:30.479" video="mainVideo" id=subtitle]]
+[[!template text="with your object system too." start="00:08:31.283" video="mainVideo" id=subtitle]]
+[[!template text="And a really nice feature of that is" start="00:08:32.880" video="mainVideo" id=subtitle]]
+[[!template text="that you have no possibility of" start="00:08:34.320" video="mainVideo" id=subtitle]]
+[[!template text="null pointer exceptions" start="00:08:35.919" video="mainVideo" id=subtitle]]
+[[!template text="like you do in other languages." start="00:08:36.959" video="mainVideo" id=subtitle]]
+[[!template text="They have a calling convention" start="00:08:38.719" video="mainVideo" id=subtitle]]
+[[!template text="where you call object dot method," start="00:08:39.919" video="mainVideo" id=subtitle]]
+[[!template text="but in CLOS, you call a generic function," start="00:08:42.880" video="mainVideo" id=subtitle]]
+[[!template text="and you just give it some arguments." start="00:08:45.600" video="mainVideo" id=subtitle]]
+[[!template text="Typically, the first one is going to be" start="00:08:47.279" video="mainVideo" id=subtitle]]
+[[!template text="an EIEIO class object," start="00:08:48.959" video="mainVideo" id=subtitle]]
+[[!template text="but it doesn't have to be," start="00:08:51.680" video="mainVideo" id=subtitle]]
+[[!template text="but because you're not calling that" start="00:08:53.200" video="mainVideo" id=subtitle]]
+[[!template text="instance of an object," start="00:08:54.640" video="mainVideo" id=subtitle]]
+[[!template text="there's nothing to be nil in the first place," start="00:08:55.519" video="mainVideo" id=subtitle]]
+[[!template text="so there's no possibility of" start="00:08:57.279" video="mainVideo" id=subtitle]]
+[[!template text="a nil pointer exception." start="00:08:58.320" video="mainVideo" id=subtitle]]
+[[!template text="And then the ability to" start="00:09:00.080" video="mainVideo" id=subtitle]]
+[[!template text="have multiple inheritance" start="00:09:01.376" video="mainVideo" id=subtitle]]
+[[!template text="and mix in all of these different" start="00:09:02.480" video="mainVideo" id=subtitle]]
+[[!template text="functionalities into your final object" start="00:09:04.000" video="mainVideo" id=subtitle]]
+[[!template text="is very powerful." start="00:09:05.760" video="mainVideo" id=subtitle]]
+[[!template text="Because you have multiple inheritance," start="00:09:07.279" video="mainVideo" id=subtitle]]
+[[!template text="your final object that" start="00:09:09.839" video="mainVideo" id=subtitle]]
+[[!template text="composes all of those things" start="00:09:11.120" video="mainVideo" id=subtitle]]
+[[!template text="is both a player and a logger," start="00:09:12.560" video="mainVideo" id=subtitle]]
+[[!template text="and it can be substituted into code" start="00:09:14.080" video="mainVideo" id=subtitle]]
+[[!template text="that expects either of them." start="00:09:15.600" video="mainVideo" id=subtitle]]
+[[!template text="It's not an adapter class" start="00:09:17.279" video="mainVideo" id=subtitle]]
+[[!template text="that only allows you to do one thing," start="00:09:19.040" video="mainVideo" id=subtitle]]
+[[!template text="it does both of them." start="00:09:21.360" video="mainVideo" id=subtitle]]
+[[!template text="I think that's amazing." start="00:09:22.560" video="mainVideo" id=subtitle]]
+[[!template text="So, here are some practical examples" start="00:09:24.800" video="mainVideo" id=subtitle]]
+[[!template text="where I think maybe this" start="00:09:26.320" video="mainVideo" id=subtitle]]
+[[!template text="could be a good idea." start="00:09:27.387" video="mainVideo" id=subtitle]]
+[[!template text="And I like to think about," start="00:09:28.720" video="mainVideo" id=subtitle]]
+[[!template text="&quot;What is OOP actually good for?&quot;." start="00:09:30.399" video="mainVideo" id=subtitle]]
+[[!template text="I think it has three really amazing powers," start="00:09:32.320" video="mainVideo" id=subtitle]]
+[[!template text="encapsulation, abstraction," start="00:09:34.640" video="mainVideo" id=subtitle]]
+[[!template text="and extensibility," start="00:09:36.399" video="mainVideo" id=subtitle]]
+[[!template text="so let's look at those." start="00:09:37.279" video="mainVideo" id=subtitle]]
+[[!template text="Encapsulation is just keeping" start="00:09:39.200" video="mainVideo" id=subtitle]]
+[[!template text="related data together." start="00:09:40.959" video="mainVideo" id=subtitle]]
+[[!template text="Here's an example from the" start="00:09:42.480" video="mainVideo" id=subtitle]]
+[[!template text="transmission Torrent client." start="00:09:43.680" video="mainVideo" id=subtitle]]
+[[!template text="In order for it to work," start="00:09:45.360" video="mainVideo" id=subtitle]]
+[[!template text="it needs to have all four of" start="00:09:46.399" video="mainVideo" id=subtitle]]
+[[!template text="these variables set consistently," start="00:09:47.600" video="mainVideo" id=subtitle]]
+[[!template text="but if you use the customization interface," start="00:09:49.920" video="mainVideo" id=subtitle]]
+[[!template text="they're kind of strewn all over the buffer" start="00:09:52.240" video="mainVideo" id=subtitle]]
+[[!template text="because that shows them alphabetically" start="00:09:53.920" video="mainVideo" id=subtitle]]
+[[!template text="by variable name instead of" start="00:09:55.760" video="mainVideo" id=subtitle]]
+[[!template text="grouping them logically by function." start="00:09:57.040" video="mainVideo" id=subtitle]]
+[[!template text="You also have all these" start="00:09:59.920" video="mainVideo" id=subtitle]]
+[[!template text="in the global namespace," start="00:10:01.327" video="mainVideo" id=subtitle]]
+[[!template text="so you need this disambiguation in front," start="00:10:02.480" video="mainVideo" id=subtitle]]
+[[!template text="you have to have a transmission prefix," start="00:10:04.720" video="mainVideo" id=subtitle]]
+[[!template text="so it's kind of ugly." start="00:10:06.800" video="mainVideo" id=subtitle]]
+[[!template text="An alternative example would be to" start="00:10:08.720" video="mainVideo" id=subtitle]]
+[[!template text="encapsulate all of that" start="00:10:10.240" video="mainVideo" id=subtitle]]
+[[!template text="in a single class." start="00:10:11.760" video="mainVideo" id=subtitle]]
+[[!template text="This has one slot for each of those values," start="00:10:13.360" video="mainVideo" id=subtitle]]
+[[!template text="except the username" start="00:10:16.160" video="mainVideo" id=subtitle]]
+[[!template text="and password is broken out," start="00:10:17.040" video="mainVideo" id=subtitle]]
+[[!template text="there was only one in the previous example," start="00:10:18.000" video="mainVideo" id=subtitle]]
+[[!template text="but it works pretty much the same." start="00:10:20.240" video="mainVideo" id=subtitle]]
+[[!template text="The really neat thing about this is that" start="00:10:23.120" video="mainVideo" id=subtitle]]
+[[!template text="the customization interface understands" start="00:10:25.200" video="mainVideo" id=subtitle]]
+[[!template text="how to customize EIEIO objects," start="00:10:27.279" video="mainVideo" id=subtitle]]
+[[!template text="so you can set your custom variable" start="00:10:29.920" video="mainVideo" id=subtitle]]
+[[!template text="to the value of an object," start="00:10:32.640" video="mainVideo" id=subtitle]]
+[[!template text="and in the customization interface," start="00:10:34.000" video="mainVideo" id=subtitle]]
+[[!template text="it shows you all of the fields," start="00:10:35.760" video="mainVideo" id=subtitle]]
+[[!template text="and it lets you edit the values" start="00:10:37.040" video="mainVideo" id=subtitle]]
+[[!template text="of those slots directly." start="00:10:38.399" video="mainVideo" id=subtitle]]
+[[!template text="So, that keeps that logical grouping" start="00:10:40.079" video="mainVideo" id=subtitle]]
+[[!template text="that I think makes things really easy to use." start="00:10:41.760" video="mainVideo" id=subtitle]]
+[[!template text="Another thing it's really good at is" start="00:10:44.800" video="mainVideo" id=subtitle]]
+[[!template text="abstraction, and this is really core to" start="00:10:46.160" video="mainVideo" id=subtitle]]
+[[!template text="a lot of what Emacs does" start="00:10:48.268" video="mainVideo" id=subtitle]]
+[[!template text="because it runs on so many different systems," start="00:10:49.408" video="mainVideo" id=subtitle]]
+[[!template text="and it works with so many different" start="00:10:51.200" video="mainVideo" id=subtitle]]
+[[!template text="kinds of similar tools." start="00:10:53.308" video="mainVideo" id=subtitle]]
+[[!template text="Here's an example from" start="00:10:55.120" video="mainVideo" id=subtitle]]
+[[!template text="the built-in SQL implementation." start="00:10:56.109" video="mainVideo" id=subtitle]]
+[[!template text="This is the definition of" start="00:10:58.079" video="mainVideo" id=subtitle]]
+[[!template text="the postgres backend," start="00:10:59.360" video="mainVideo" id=subtitle]]
+[[!template text="there's one of these for" start="00:11:01.040" video="mainVideo" id=subtitle]]
+[[!template text="every supported database backend." start="00:11:02.160" video="mainVideo" id=subtitle]]
+[[!template text="And you can see, this is a pretty" start="00:11:04.000" video="mainVideo" id=subtitle]]
+[[!template text="classic interface abstraction pattern." start="00:11:05.440" video="mainVideo" id=subtitle]]
+[[!template text="On the left-hand side," start="00:11:08.480" video="mainVideo" id=subtitle]]
+[[!template text="you have a symbol that's common" start="00:11:09.680" video="mainVideo" id=subtitle]]
+[[!template text="among all the database backends," start="00:11:10.880" video="mainVideo" id=subtitle]]
+[[!template text="and the code that doesn't" start="00:11:12.399" video="mainVideo" id=subtitle]]
+[[!template text="know about the implementation can use," start="00:11:14.160" video="mainVideo" id=subtitle]]
+[[!template text="no matter what implementation" start="00:11:16.240" video="mainVideo" id=subtitle]]
+[[!template text="is being specified." start="00:11:17.519" video="mainVideo" id=subtitle]]
+[[!template text="On the right-hand side," start="00:11:19.040" video="mainVideo" id=subtitle]]
+[[!template text="you have the implementation" start="00:11:20.000" video="mainVideo" id=subtitle]]
+[[!template text="specific values," start="00:11:21.120" video="mainVideo" id=subtitle]]
+[[!template text="in some cases these are just strings," start="00:11:22.560" video="mainVideo" id=subtitle]]
+[[!template text="or regexes, and in others" start="00:11:24.399" video="mainVideo" id=subtitle]]
+[[!template text="those are actual functions." start="00:11:25.760" video="mainVideo" id=subtitle]]
+[[!template text="So, really this already is" start="00:11:27.519" video="mainVideo" id=subtitle]]
+[[!template text="object orientation," start="00:11:29.440" video="mainVideo" id=subtitle]]
+[[!template text="it's just an ad-hoc system for it," start="00:11:30.720" video="mainVideo" id=subtitle]]
+[[!template text="but you don't have to use an ad-hoc system" start="00:11:32.959" video="mainVideo" id=subtitle]]
+[[!template text="because there's this" start="00:11:34.880" video="mainVideo" id=subtitle]]
+[[!template text="nice formal one instead." start="00:11:35.519" video="mainVideo" id=subtitle]]
+[[!template text="Another thing that it's" start="00:11:38.000" video="mainVideo" id=subtitle]]
+[[!template text="really good at is extensibility," start="00:11:38.880" video="mainVideo" id=subtitle]]
+[[!template text="we saw some of that with" start="00:11:40.959" video="mainVideo" id=subtitle]]
+[[!template text="the emms-player example earlier." start="00:11:42.160" video="mainVideo" id=subtitle]]
+[[!template text="But here's another thing I think" start="00:11:44.800" video="mainVideo" id=subtitle]]
+[[!template text="it would be interesting to explore." start="00:11:46.160" video="mainVideo" id=subtitle]]
+[[!template text="Emacs has this idea of derived modes" start="00:11:48.720" video="mainVideo" id=subtitle]]
+[[!template text="where you have a mode that's based on" start="00:11:51.279" video="mainVideo" id=subtitle]]
+[[!template text="another, and that's a pretty clear" start="00:11:52.639" video="mainVideo" id=subtitle]]
+[[!template text="inheritance pattern straight out of OOP" start="00:11:54.639" video="mainVideo" id=subtitle]]
+[[!template text="as far as I'm concerned." start="00:11:57.040" video="mainVideo" id=subtitle]]
+[[!template text="What would it look like" start="00:11:58.560" video="mainVideo" id=subtitle]]
+[[!template text="if major modes were EIEIO classes," start="00:12:00.079" video="mainVideo" id=subtitle]]
+[[!template text="and you could extend your mode" start="00:12:02.959" video="mainVideo" id=subtitle]]
+[[!template text="by extending the class." start="00:12:04.800" video="mainVideo" id=subtitle]]
+[[!template text="I think that's a really interesting idea," start="00:12:06.399" video="mainVideo" id=subtitle]]
+[[!template text="and I'd like to explore that more." start="00:12:08.240" video="mainVideo" id=subtitle]]
+[[!template text="In conclusion, I think EIEIO is amazing," start="00:12:10.880" video="mainVideo" id=subtitle]]
+[[!template text="and I had no idea that such a powerful" start="00:12:14.079" video="mainVideo" id=subtitle]]
+[[!template text="object orientation system" start="00:12:16.079" video="mainVideo" id=subtitle]]
+[[!template text="was available in the Emacs." start="00:12:18.079" video="mainVideo" id=subtitle]]
+[[!template text="My goal with this talk" start="00:12:20.160" video="mainVideo" id=subtitle]]
+[[!template text="is for anyone who writes Emacs Lisp," start="00:12:21.519" video="mainVideo" id=subtitle]]
+[[!template text="to look at these classes of problems," start="00:12:23.519" video="mainVideo" id=subtitle]]
+[[!template text="encapsulation, abstraction," start="00:12:25.360" video="mainVideo" id=subtitle]]
+[[!template text="and extensibility," start="00:12:27.360" video="mainVideo" id=subtitle]]
+[[!template text="and if you run into" start="00:12:28.639" video="mainVideo" id=subtitle]]
+[[!template text="those problems in your code," start="00:12:29.600" video="mainVideo" id=subtitle]]
+[[!template text="instead of immediately reaching" start="00:12:31.279" video="mainVideo" id=subtitle]]
+[[!template text="and building your own system," start="00:12:33.279" video="mainVideo" id=subtitle]]
+[[!template text="I want you to think:" start="00:12:34.959" video="mainVideo" id=subtitle]]
+[[!template text="&quot;Oh there's a thing for that," start="00:12:35.760" video="mainVideo" id=subtitle]]
+[[!template text="and I can just use it.&quot;" start="00:12:37.279" video="mainVideo" id=subtitle]]
+[[!template text="That's my talk, thanks." start="00:12:39.040" video="mainVideo" id=subtitle]]
+[[!template text="Hack on!" start="00:12:40.560" video="mainVideo" id=subtitle]]
+[[!template text="captions by bhavin192 (Bhavin Gandhi)" start="00:12:41.560" video="mainVideo" id=subtitle]]
diff --git a/2021/info/form-schedule.md b/2021/info/form-schedule.md
index 5bc54e69..5eed89de 100644
--- a/2021/info/form-schedule.md
+++ b/2021/info/form-schedule.md
@@ -1,10 +1,14 @@
<!-- Automatically generated by conf-create-info-pages -->
Q&A: IRC
-Status: Captions added to video
-Duration: 12:43
-<div class="times" start="2021-11-28T18:00:00Z" end="2021-11-28T18:13:00Z">Sunday, Nov 28 2021, ~ 1:00 PM - 1:13 PM EST<br />Sunday, Nov 28 2021, ~10:00 AM - 10:13 AM PST<br />Sunday, Nov 28 2021, ~ 6:00 PM - 6:13 PM UTC<br />Sunday, Nov 28 2021, ~ 7:00 PM - 7:13 PM CET<br />Sunday, Nov 28 2021, ~ 8:00 PM - 8:13 PM EET<br />Sunday, Nov 28 2021, ~11:30 PM - 11:43 PM IST<br />Monday, Nov 29 2021, ~ 2:00 AM - 2:13 AM +08<br />Monday, Nov 29 2021, ~ 3:00 AM - 3:13 AM JST<br /><a href="/2021/">Find out how to watch and participate</a></div>
+Status: Now playing
+Duration: 12:44
-If you have questions and the speaker has not indicated public contact information on this page, please feel free to e-mail us at <emacsconf-submit@gnu.org> and we'll forward your question to the speaker.# Description
+
+If you have questions and the speaker has not indicated public contact information on this page, please feel free to e-mail us at <emacsconf-submit@gnu.org> and we'll forward your question to the speaker.<div class="mainVideo"><div class="video-card vid" data-id="mainVideo"><figure><video controls preload="metadata" id="mainVideo">
+<source src="https://media.emacsconf.org/2021/emacsconf-2021-form--old-mccarthy-had-a-form--ian-eure--main.webm"><track label="English" kind="captions" srclang="en" src="/2021/captions/emacsconf-2021-form--old-mccarthy-had-a-form--ian-eure--main.vtt" default>
+</video></figure>
+<div class="files resources"><ul><li><a href="https://media.emacsconf.org/2021/emacsconf-2021-form--old-mccarthy-had-a-form--ian-eure--main.webm">Download .webm video (12:44, 13.8MB)</a></li><li><a href="https://media.emacsconf.org/2021/emacsconf-2021-form--old-mccarthy-had-a-form--ian-eure--main.vtt">Download --main.vtt</a></li><li><a href="https://toobnix.org/w/mcyaNMBE1QpjvQa2qDayvi">View on Toobnix</a></li></ul></div></div>
+</div># Description
diff --git a/2021/info/native-schedule.md b/2021/info/native-schedule.md
index 081f25e5..257d85a0 100644
--- a/2021/info/native-schedule.md
+++ b/2021/info/native-schedule.md
@@ -1,7 +1,7 @@
<!-- Automatically generated by conf-create-info-pages -->
Q&A: live
-Status: Now playing
+Status: Finished
Duration: 39:08
diff --git a/2021/schedule-details.md b/2021/schedule-details.md
index 5ea8fb26..a483e2bf 100644
--- a/2021/schedule-details.md
+++ b/2021/schedule-details.md
@@ -40,9 +40,9 @@
<tr><td>done</td><td width=100>~10:19 AM</td><td><a href="/2021/talks/ui">Yak-shaving to a UI framework</a></td><td>Erik Anderson</td></tr>
<tr><td>done</td><td width=100>~10:38 AM</td><td><a href="/2021/talks/mold">Moldable Emacs, a step towards sustainable software</a></td><td>Andrea</td></tr>
<tr><td>done</td><td width=100>~10:49 AM</td><td><a href="/2021/talks/model">Extending the "model" of Emacs to other applications</a></td><td>Laszlo Krajnikovszkij</td></tr>
-<tr><td>now playing</td><td width=100>~11:00 AM</td><td><a href="/2021/talks/native">Emacs Lisp native compiler, current status and future developments</a></td><td>Andrea Corallo</td></tr>
+<tr><td>done</td><td width=100>~11:00 AM</td><td><a href="/2021/talks/native">Emacs Lisp native compiler, current status and future developments</a></td><td>Andrea Corallo</td></tr>
<tr><td colspan="4"><strong>Sunday afternoon<strong></td></tr>
-<tr><td>captioned</td><td width=100>~ 1:00 PM</td><td><a href="/2021/talks/form">Old McCarthy Had a Form</a></td><td>Ian Eure</td></tr>
+<tr><td>now playing</td><td width=100>~ 1:01 PM</td><td><a href="/2021/talks/form">Old McCarthy Had a Form</a></td><td>Ian Eure</td></tr>
<tr><td>received</td><td width=100>~ 1:16 PM</td><td><a href="/2021/talks/bindat">Turbo Bindat</a></td><td>Stefan Monnier</td></tr>
<tr><td>captioned</td><td width=100>~ 1:53 PM</td><td><a href="/2021/talks/test">Test blocks</a></td><td>Eduardo Ochs</td></tr>
<tr><td>captioned</td><td width=100>~ 2:02 PM</td><td><a href="/2021/talks/bidi">Perso-Arabic Input Methods And Making More Emacs Apps BIDI Aware</a></td><td>Mohsen BANAN</td></tr>