From 941dd23b11ed8c5a9b91f9d92fd18626d06fe8bd Mon Sep 17 00:00:00 2001 From: Sacha Chua Date: Sun, 28 Nov 2021 13:03:22 -0500 Subject: Update --- ...rm--old-mccarthy-had-a-form--ian-eure--main.vtt | 1282 ++++++++++++++++++++ 1 file changed, 1282 insertions(+) create mode 100644 2021/captions/emacsconf-2021-form--old-mccarthy-had-a-form--ian-eure--main.vtt (limited to '2021/captions/emacsconf-2021-form--old-mccarthy-had-a-form--ian-eure--main.vtt') 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)] -- cgit v1.2.3