WEBVTT 00:00:01.839 --> 00:00:04.160 hello EmacsConf 00:00:04.160 --> 00:00:05.759 thanks very much first of all to the 00:00:05.759 --> 00:00:07.200 organizers of the conference 00:00:07.200 --> 00:00:09.440 and to the audience who I hope is out 00:00:09.440 --> 00:00:10.480 there somewhere 00:00:10.480 --> 00:00:12.080 uh for giving me this chance to talk 00:00:12.080 --> 00:00:14.240 about Emacs and some of my uh 00:00:14.240 --> 00:00:16.560 my poking around with Emacs lisp my name 00:00:16.560 --> 00:00:18.480 is eric abrahamson I'm not 00:00:18.480 --> 00:00:20.960 a professional programmer but I use 00:00:20.960 --> 00:00:21.920 Emacs all day 00:00:21.920 --> 00:00:24.800 every day for writing for translating 00:00:24.800 --> 00:00:26.160 for project management 00:00:26.160 --> 00:00:28.160 and most importantly for email which 00:00:28.160 --> 00:00:29.199 will be the 00:00:29.199 --> 00:00:32.480 subject of my talk today so I'm talking 00:00:32.480 --> 00:00:35.440 about object-oriented code in Emacs 00:00:35.440 --> 00:00:38.320 uh most famous possibly oldest 00:00:38.320 --> 00:00:40.160 definitely most notorious news reader 00:00:40.160 --> 00:00:41.760 slash Emacs client 00:00:41.760 --> 00:00:44.320 email client so in particular object 00:00:44.320 --> 00:00:45.440 oriented code 00:00:45.440 --> 00:00:50.239 in news why object-oriented code 00:00:50.239 --> 00:00:51.920 the way news works is it started off as 00:00:51.920 --> 00:00:53.600 a news reader so for access 00:00:53.600 --> 00:00:57.039 accessing nntp servers and later on grew 00:00:57.039 --> 00:00:59.120 a whole bunch of new functionality as a 00:00:59.120 --> 00:01:01.039 mail client so it can talk to imap 00:01:01.039 --> 00:01:02.079 servers 00:01:02.079 --> 00:01:04.799 mail dealer directories uh folders on 00:01:04.799 --> 00:01:06.640 your file system all kinds of stuff 00:01:06.640 --> 00:01:08.400 but it presents a unified interface to 00:01:08.400 --> 00:01:09.760 all those things so it's basically 00:01:09.760 --> 00:01:11.040 polymorphism 00:01:11.040 --> 00:01:14.000 one of the the basic fundamental 00:01:14.000 --> 00:01:16.400 principles of object oriented code so 00:01:16.400 --> 00:01:18.720 it's a good fit second reason is it 00:01:18.720 --> 00:01:19.920 already is 00:01:19.920 --> 00:01:22.880 object oriented and I'll get into what 00:01:22.880 --> 00:01:23.759 that means 00:01:23.759 --> 00:01:27.280 in a second so 00:01:27.280 --> 00:01:28.640 the background that you should know is 00:01:28.640 --> 00:01:30.640 that most of this code was written in 00:01:30.640 --> 00:01:32.560 the 90s 00:01:32.560 --> 00:01:34.880 Emacs lisp has only grown sort of 00:01:34.880 --> 00:01:36.159 official 00:01:36.159 --> 00:01:38.640 object orientation support libraries 00:01:38.640 --> 00:01:41.200 over the past 10 years or so 00:01:41.200 --> 00:01:43.840 from about 2010 to the present so what 00:01:43.840 --> 00:01:44.799 does 00:01:44.799 --> 00:01:48.640 news do so the basics of 00:01:48.640 --> 00:01:50.560 object orientation in most languages are 00:01:50.560 --> 00:01:52.240 you you define 00:01:52.240 --> 00:01:53.759 a class of some sort and then you 00:01:53.759 --> 00:01:55.840 instantiate that class and these 00:01:55.840 --> 00:01:58.079 class instances have two things they 00:01:58.079 --> 00:02:00.320 have data attributes or 00:02:00.320 --> 00:02:01.759 slots or members or whatever you're 00:02:01.759 --> 00:02:04.799 going to call them and they have 00:02:04.799 --> 00:02:07.280 methods which operate on individual 00:02:07.280 --> 00:02:08.399 instances 00:02:08.399 --> 00:02:11.120 so you could say that you create or 00:02:11.120 --> 00:02:12.879 instantiate an instance of a class in 00:02:12.879 --> 00:02:13.920 that instance 00:02:13.920 --> 00:02:16.239 owns two things that owns its set of 00:02:16.239 --> 00:02:17.120 attributes 00:02:17.120 --> 00:02:20.239 and it owns some methods which 00:02:20.239 --> 00:02:23.280 also work on the on the instance 00:02:23.280 --> 00:02:26.720 so both in nurse's existing code and in 00:02:26.720 --> 00:02:29.040 the more standard object oriented Emacs 00:02:29.040 --> 00:02:30.080 lisp libraries 00:02:30.080 --> 00:02:32.480 this relationship is turned on its head 00:02:32.480 --> 00:02:34.080 a little bit 00:02:34.080 --> 00:02:37.599 in that data slots and 00:02:37.599 --> 00:02:40.239 uh and instance methods are defined 00:02:40.239 --> 00:02:41.360 outside of the 00:02:41.360 --> 00:02:42.959 class or the instances themselves so 00:02:42.959 --> 00:02:45.040 they are top level definitions 00:02:45.040 --> 00:02:46.879 so we'll get to what that means in the 00:02:46.879 --> 00:02:48.319 in the newer libraries um 00:02:48.319 --> 00:02:49.840 in a bit but uh first I want to talk 00:02:49.840 --> 00:02:51.760 about how news does this and in order to 00:02:51.760 --> 00:02:54.319 do that we are going to go deep into 00:02:54.319 --> 00:02:57.440 the darkest corner of the new co source 00:02:57.440 --> 00:02:59.879 code tree to a library called 00:02:59.879 --> 00:03:02.879 nno.l very cryptically 00:03:02.879 --> 00:03:05.040 titled uh library and when we open it up 00:03:05.040 --> 00:03:06.800 we find 00:03:06.800 --> 00:03:09.519 a library with no code comments and 00:03:09.519 --> 00:03:11.040 almost no doc strings 00:03:11.040 --> 00:03:12.800 almost as if lars was a little ashamed 00:03:12.800 --> 00:03:14.159 not ashamed but knew he was doing 00:03:14.159 --> 00:03:16.000 something a little bit crazy 00:03:16.000 --> 00:03:19.040 and didn't want anyone to see so 00:03:19.040 --> 00:03:21.040 this file contains the the object 00:03:21.040 --> 00:03:22.400 oriented mechanism 00:03:22.400 --> 00:03:24.480 whereby you can define different kinds 00:03:24.480 --> 00:03:25.760 of back ends for news 00:03:25.760 --> 00:03:27.280 and then those back ends can be 00:03:27.280 --> 00:03:29.760 instantiated as individual 00:03:29.760 --> 00:03:32.480 servers and as you define these backends 00:03:32.480 --> 00:03:33.360 you're supposed to use 00:03:33.360 --> 00:03:36.000 two macros which you can see here one is 00:03:36.000 --> 00:03:36.640 called def 00:03:36.640 --> 00:03:39.599 vu and one is called defu and if you 00:03:39.599 --> 00:03:41.280 look at the definitions the definitions 00:03:41.280 --> 00:03:43.280 look pretty simple here def vu basically 00:03:43.280 --> 00:03:45.440 turns into a def var 00:03:45.440 --> 00:03:49.040 and foo turns into a defund 00:03:49.040 --> 00:03:52.239 and along with those basic definitions 00:03:52.239 --> 00:03:55.760 the library also does some registration 00:03:55.760 --> 00:03:58.720 memoization caching of those variables 00:03:58.720 --> 00:04:00.080 it saves them in the structure 00:04:00.080 --> 00:04:01.840 for later use so that we know that those 00:04:01.840 --> 00:04:03.360 are meant to be 00:04:03.360 --> 00:04:05.280 uh attributes and methods that are used 00:04:05.280 --> 00:04:06.640 with instances 00:04:06.640 --> 00:04:08.000 with server instances but you can see 00:04:08.000 --> 00:04:09.280 that there's no server instance 00:04:09.280 --> 00:04:10.560 definition here there's no 00:04:10.560 --> 00:04:13.200 like no nothing these are top level 00:04:13.200 --> 00:04:14.239 these are top level 00:04:14.239 --> 00:04:18.160 definitions so really data attributes 00:04:18.160 --> 00:04:18.639 for 00:04:18.639 --> 00:04:22.000 new servers and 00:04:22.000 --> 00:04:23.840 methods or functions that operate on 00:04:23.840 --> 00:04:25.440 those instances are completely 00:04:25.440 --> 00:04:28.400 separate mechanisms they don't really 00:04:28.400 --> 00:04:29.600 have anything to do with each other they 00:04:29.600 --> 00:04:31.680 don't belong to the same data structures 00:04:31.680 --> 00:04:37.120 so how do they work follow me 00:04:37.120 --> 00:04:39.520 aka methods and attributes these are all 00:04:39.520 --> 00:04:41.360 the things I just said 00:04:41.360 --> 00:04:44.479 so when you define a 00:04:44.479 --> 00:04:48.560 a backend type 00:04:48.560 --> 00:04:51.199 in noose what you get is this a 00:04:51.199 --> 00:04:52.400 definition a list 00:04:52.400 --> 00:04:54.080 and it'll say there is such a back end 00:04:54.080 --> 00:04:55.520 as nnml 00:04:55.520 --> 00:04:58.880 and these are its uh data attributes 00:04:58.880 --> 00:04:59.520 that any 00:04:59.520 --> 00:05:01.840 given instance can have and then these 00:05:01.840 --> 00:05:02.960 are 00:05:02.960 --> 00:05:04.960 the functions or methods that are 00:05:04.960 --> 00:05:06.880 defined to operate on 00:05:06.880 --> 00:05:08.960 an instance of this backend so a server 00:05:08.960 --> 00:05:11.440 that belongs to the nnml 00:05:11.440 --> 00:05:13.360 backend so at least we have this data 00:05:13.360 --> 00:05:15.120 here so that's that's handy we don't you 00:05:15.120 --> 00:05:16.880 don't really touch that that's like very 00:05:16.880 --> 00:05:18.000 very very deep 00:05:18.000 --> 00:05:20.560 um use code that doesn't really come up 00:05:20.560 --> 00:05:22.560 even as a 00:05:22.560 --> 00:05:25.280 even as a bug squasher or whatever we 00:05:25.280 --> 00:05:26.479 don't touch that very often but there 00:05:26.479 --> 00:05:27.280 they are and that's 00:05:27.280 --> 00:05:30.400 that's how they work now the next thing 00:05:30.400 --> 00:05:32.080 that obviously you want to know is okay 00:05:32.080 --> 00:05:34.000 where are if I've started up news where 00:05:34.000 --> 00:05:35.039 are my servers 00:05:35.039 --> 00:05:37.199 uh where are these server objects since 00:05:37.199 --> 00:05:39.199 this is object oriented 00:05:39.199 --> 00:05:41.840 programming and the weird thing that you 00:05:41.840 --> 00:05:43.199 will eventually 00:05:43.199 --> 00:05:45.199 figure out in some cases after years of 00:05:45.199 --> 00:05:46.880 poking around in the new source code 00:05:46.880 --> 00:05:49.199 is that servers do not exist in an 00:05:49.199 --> 00:05:50.320 ontological 00:05:50.320 --> 00:05:53.440 philosophical sense as objects the 00:05:53.440 --> 00:05:55.440 primary data structures of noose are 00:05:55.440 --> 00:05:57.039 groups 00:05:57.039 --> 00:05:58.960 and in sort of an object-oriented 00:05:58.960 --> 00:06:00.720 hierarchical you know mindset you'd 00:06:00.720 --> 00:06:01.759 think well 00:06:01.759 --> 00:06:03.759 groups belong to servers so servers must 00:06:03.759 --> 00:06:05.759 exist but they don't 00:06:05.759 --> 00:06:08.000 each group and here you can see some 00:06:08.000 --> 00:06:09.360 examples of groups 00:06:09.360 --> 00:06:11.199 these are basically the data structures 00:06:11.199 --> 00:06:13.039 that represent a group each group also 00:06:13.039 --> 00:06:14.960 has a little entry here that 00:06:14.960 --> 00:06:17.039 that tells you what server it belongs to 00:06:17.039 --> 00:06:18.000 and each group 00:06:18.000 --> 00:06:20.479 replicates that data uh saying which 00:06:20.479 --> 00:06:23.120 server it belongs to and so when 00:06:23.120 --> 00:06:24.479 nurse is going through doing its 00:06:24.479 --> 00:06:26.160 business uh trying to figure out what's 00:06:26.160 --> 00:06:27.680 like updating mail from the groups or 00:06:27.680 --> 00:06:29.840 whatever almost every time 00:06:29.840 --> 00:06:31.600 it will cycle through all the list of 00:06:31.600 --> 00:06:32.960 groups it'll 00:06:32.960 --> 00:06:34.960 it'll look at all the server definitions 00:06:34.960 --> 00:06:36.720 and it will categorize the groups by 00:06:36.720 --> 00:06:38.160 server 00:06:38.160 --> 00:06:41.120 which which is just weird because you're 00:06:41.120 --> 00:06:42.160 sort of looking for okay where does the 00:06:42.160 --> 00:06:43.840 server exist it doesn't exist it's put 00:06:43.840 --> 00:06:44.479 together 00:06:44.479 --> 00:06:48.319 every time uh out of out of code 00:06:48.319 --> 00:06:50.400 elsewhere in the news code base 00:06:50.400 --> 00:06:51.840 specifically from these group 00:06:51.840 --> 00:06:54.080 these group definitions and so this is 00:06:54.080 --> 00:06:55.199 very odd because 00:06:55.199 --> 00:06:58.080 in in some sense like here this one its 00:06:58.080 --> 00:06:58.720 server is 00:06:58.720 --> 00:07:02.240 nnml and an empty string so there's a 00:07:02.240 --> 00:07:03.919 certain sense here in which this server 00:07:03.919 --> 00:07:04.479 is not 00:07:04.479 --> 00:07:06.400 really an object at all what it is is a 00:07:06.400 --> 00:07:07.759 set of instructions for how to find 00:07:07.759 --> 00:07:08.560 messages 00:07:08.560 --> 00:07:11.199 and this set of instructions is go to 00:07:11.199 --> 00:07:12.800 the default place where the user 00:07:12.800 --> 00:07:15.440 might have their mail and expect to find 00:07:15.440 --> 00:07:16.000 messages 00:07:16.000 --> 00:07:18.080 there in an nml format which is 00:07:18.080 --> 00:07:19.840 basically just one message per 00:07:19.840 --> 00:07:22.479 um per file and any number of groups 00:07:22.479 --> 00:07:23.840 could have those same instructions uh 00:07:23.840 --> 00:07:25.440 but they're not it's not really a thing 00:07:25.440 --> 00:07:26.720 it's really just a 00:07:26.720 --> 00:07:28.639 it's more of a procedural instruction 00:07:28.639 --> 00:07:30.240 and on the other end of the spectrum you 00:07:30.240 --> 00:07:31.919 might have an nni map 00:07:31.919 --> 00:07:33.599 server which very much is a thing it has 00:07:33.599 --> 00:07:35.840 its own it has its own server its own 00:07:35.840 --> 00:07:37.759 port its own authentication 00:07:37.759 --> 00:07:40.240 system so some of the servers are more 00:07:40.240 --> 00:07:41.360 like things some of the servers are more 00:07:41.360 --> 00:07:42.400 like instructions 00:07:42.400 --> 00:07:45.520 as news works right now um these 00:07:45.520 --> 00:07:47.280 most of the servers are treated like 00:07:47.280 --> 00:07:48.879 just instruction sets 00:07:48.879 --> 00:07:50.879 and and there's no place where you can 00:07:50.879 --> 00:07:53.120 go and find them there's no one central 00:07:53.120 --> 00:07:55.360 uh variable that defines them all so how 00:07:55.360 --> 00:07:56.160 do the 00:07:56.160 --> 00:07:57.520 um so we'll talk about the methods in a 00:07:57.520 --> 00:07:59.520 second how do the data attributes work 00:07:59.520 --> 00:08:02.639 uh put very crudely um 00:08:02.639 --> 00:08:04.479 your servers when they're put together 00:08:04.479 --> 00:08:05.919 uh they are okay they are 00:08:05.919 --> 00:08:08.080 kept in a variable and it's called nno 00:08:08.080 --> 00:08:08.960 nno 00:08:08.960 --> 00:08:11.120 state a list and there's a concept to 00:08:11.120 --> 00:08:12.960 this of the current server 00:08:12.960 --> 00:08:16.560 so when we go here let's go back to 00:08:16.560 --> 00:08:19.039 our nnno definition a list so when we 00:08:19.039 --> 00:08:20.560 have an nnml 00:08:20.560 --> 00:08:22.240 server say we have one here and it's 00:08:22.240 --> 00:08:24.400 just this blank string 00:08:24.400 --> 00:08:26.639 these are all when you define that in 00:08:26.639 --> 00:08:28.879 your own uh server definition code 00:08:28.879 --> 00:08:31.919 you can put in different values for all 00:08:31.919 --> 00:08:32.399 of these 00:08:32.399 --> 00:08:35.760 various attributes and when noose comes 00:08:35.760 --> 00:08:37.039 when it comes time for news to operate 00:08:37.039 --> 00:08:38.959 on this server in particular ask it to 00:08:38.959 --> 00:08:40.640 you know open a group or get new mail 00:08:40.640 --> 00:08:42.080 what it will do is it will take 00:08:42.080 --> 00:08:45.360 that particular server's data from these 00:08:45.360 --> 00:08:45.920 symbols 00:08:45.920 --> 00:08:47.600 and it will copy all that information 00:08:47.600 --> 00:08:49.600 into the global devfars 00:08:49.600 --> 00:08:51.760 so for the time that you are operating 00:08:51.760 --> 00:08:53.120 on this particular server 00:08:53.120 --> 00:08:55.920 its individual data becomes the values 00:08:55.920 --> 00:08:56.800 of these global 00:08:56.800 --> 00:08:59.360 variables which when you realize what's 00:08:59.360 --> 00:09:00.560 happening is sort of terrifying you 00:09:00.560 --> 00:09:02.080 think oh my god 00:09:02.080 --> 00:09:04.480 but at the same time it's actually kind 00:09:04.480 --> 00:09:05.760 of impressive and it's amazing that it 00:09:05.760 --> 00:09:07.279 works as well as it does 00:09:07.279 --> 00:09:09.120 I'm actually a little bit in awe of the 00:09:09.120 --> 00:09:10.880 of the code in this in this library I 00:09:10.880 --> 00:09:12.560 think it's pretty impressive 00:09:12.560 --> 00:09:15.760 so as you nno change server 00:09:15.760 --> 00:09:18.320 uh this function here these values get 00:09:18.320 --> 00:09:20.080 copied into the global value into the 00:09:20.080 --> 00:09:21.440 global variables and then as you go on 00:09:21.440 --> 00:09:22.399 the next server 00:09:22.399 --> 00:09:24.000 that gets you know cleaned out and 00:09:24.000 --> 00:09:26.399 recopied there are a few 00:09:26.399 --> 00:09:29.680 um a few other slot types 00:09:29.680 --> 00:09:32.000 or attribute types which do because all 00:09:32.000 --> 00:09:33.440 of these attributes see they all start 00:09:33.440 --> 00:09:34.720 with the nml 00:09:34.720 --> 00:09:37.920 or in this case and in folder prefix 00:09:37.920 --> 00:09:40.560 but there are a few slot types that all 00:09:40.560 --> 00:09:41.760 servers need for 00:09:41.760 --> 00:09:43.279 for instance their most recent status 00:09:43.279 --> 00:09:45.920 message a status symbol like open denied 00:09:45.920 --> 00:09:46.640 whatever 00:09:46.640 --> 00:09:48.080 and that data is sort of scattered 00:09:48.080 --> 00:09:49.680 around the rest of the news 00:09:49.680 --> 00:09:51.200 code base in various variables or 00:09:51.200 --> 00:09:53.440 various places 00:09:53.440 --> 00:09:55.440 so that's that sort of just contributes 00:09:55.440 --> 00:09:56.560 to the confusion when you're trying to 00:09:56.560 --> 00:09:57.360 figure out why 00:09:57.360 --> 00:10:00.720 things are going wrong so that is our 00:10:00.720 --> 00:10:03.839 um nnoo which is and 00:10:03.839 --> 00:10:05.440 sort of how the attributes and these 00:10:05.440 --> 00:10:07.360 global variables work 00:10:07.360 --> 00:10:09.120 if we want to talk about defu and the 00:10:09.120 --> 00:10:10.480 methods we 00:10:10.480 --> 00:10:20.800 go to 00:10:20.800 --> 00:10:23.200 and so this is the place where all the 00:10:23.200 --> 00:10:25.600 server level methods are defined 00:10:25.600 --> 00:10:27.200 and what we have here are things like 00:10:27.200 --> 00:10:29.279 here's an example there's closed server 00:10:29.279 --> 00:10:32.640 this closed server is given a 00:10:32.640 --> 00:10:36.320 a server as a an argument 00:10:36.320 --> 00:10:38.079 it looks at the server and basically it 00:10:38.079 --> 00:10:40.560 finds the proper function to call on 00:10:40.560 --> 00:10:42.079 this particular server 00:10:42.079 --> 00:10:45.120 using the function new skip function by 00:10:45.120 --> 00:10:45.600 taking 00:10:45.600 --> 00:10:48.959 the sort of latter half of this function 00:10:48.959 --> 00:10:49.760 symbol 00:10:49.760 --> 00:10:52.079 and pasting it together with the symbol 00:10:52.079 --> 00:10:53.440 that represents the back end so 00:10:53.440 --> 00:10:56.800 if you were calling this on an nni map 00:10:56.800 --> 00:10:59.600 server your skip function would look at 00:10:59.600 --> 00:11:01.279 your imap server look at closed server I 00:11:01.279 --> 00:11:02.240 knew what 00:11:02.240 --> 00:11:07.839 it would come up with 00:11:07.839 --> 00:11:10.240 server sure enough there's an imac close 00:11:10.240 --> 00:11:11.920 server and it'll call this code and then 00:11:11.920 --> 00:11:12.240 it'll 00:11:12.240 --> 00:11:14.000 it'll go and do its other bookkeeping 00:11:14.000 --> 00:11:15.279 another sort of 00:11:15.279 --> 00:11:18.320 surrounding code and so that's not that 00:11:18.320 --> 00:11:19.279 actually works pretty well 00:11:19.279 --> 00:11:22.640 uh as as things go uh defu 00:11:22.640 --> 00:11:24.959 makes a record that this this function 00:11:24.959 --> 00:11:26.800 exists and nus gets function get 00:11:26.800 --> 00:11:28.320 function looks on that cache finds the 00:11:28.320 --> 00:11:29.600 function and calls it 00:11:29.600 --> 00:11:30.959 now what's particularly confusing is 00:11:30.959 --> 00:11:32.560 that you don't actually even have to use 00:11:32.560 --> 00:11:33.360 defu 00:11:33.360 --> 00:11:35.519 so whoever wrote and then mail gear 00:11:35.519 --> 00:11:38.399 which is a weird library 00:11:38.399 --> 00:11:39.920 said to heck with you I'm not using any 00:11:39.920 --> 00:11:41.600 of these 00:11:41.600 --> 00:11:43.120 any of this machinery I'm going to do it 00:11:43.120 --> 00:11:45.839 myself so we have 00:11:45.839 --> 00:11:49.680 def structs to hold uh the instance 00:11:49.680 --> 00:11:52.320 data and then we have just plain old 00:11:52.320 --> 00:11:53.040 defense 00:11:53.040 --> 00:11:55.680 for things like animal your close server 00:11:55.680 --> 00:11:57.279 request close all of these 00:11:57.279 --> 00:11:59.279 these server level uh variables and it 00:11:59.279 --> 00:12:00.320 just turns out that 00:12:00.320 --> 00:12:03.360 news in its belt and suspenders 00:12:03.360 --> 00:12:05.839 approach to uh to coding it'll actually 00:12:05.839 --> 00:12:07.279 just go out if it can't find 00:12:07.279 --> 00:12:10.320 the memoized function it'll just go out 00:12:10.320 --> 00:12:12.160 and say has anybody defined a function 00:12:12.160 --> 00:12:14.240 that looks like this pattern and then 00:12:14.240 --> 00:12:16.000 and then melder says yes I did and then 00:12:16.000 --> 00:12:17.920 we call it and then we go so it's just 00:12:17.920 --> 00:12:19.920 it's fine it works it just adds to the 00:12:19.920 --> 00:12:21.440 confusion why 00:12:21.440 --> 00:12:24.240 why does it work we don't know sometimes 00:12:24.240 --> 00:12:25.440 the only thing worse than not knowing 00:12:25.440 --> 00:12:26.880 why something doesn't work is 00:12:26.880 --> 00:12:30.000 not knowing why something does work um 00:12:30.000 --> 00:12:30.560 and then 00:12:30.560 --> 00:12:31.920 a last little bit I want to touch on 00:12:31.920 --> 00:12:33.680 here is inheritance which is another 00:12:33.680 --> 00:12:35.440 sort of cornerstone of object-oriented 00:12:35.440 --> 00:12:38.480 coding as far as I can tell only uh 00:12:38.480 --> 00:12:40.160 the only inheritance that goes on is in 00:12:40.160 --> 00:12:41.920 something called nn male 00:12:41.920 --> 00:12:45.519 which provides sort of common functions 00:12:45.519 --> 00:12:48.399 for back ends that keep their mail on 00:12:48.399 --> 00:12:49.360 your 00:12:49.360 --> 00:12:52.000 local machine and you can spool it you 00:12:52.000 --> 00:12:53.680 can delete it you can you know you own 00:12:53.680 --> 00:12:55.440 the messages it's not like an nntp 00:12:55.440 --> 00:12:56.160 server 00:12:56.160 --> 00:12:59.040 and so a lot of those male deer nnml 00:12:59.040 --> 00:13:00.160 whatever 00:13:00.160 --> 00:13:02.959 a lot of those have sort of similar code 00:13:02.959 --> 00:13:04.079 which they 00:13:04.079 --> 00:13:07.600 which they share via this nn mail 00:13:07.600 --> 00:13:09.600 you call it an abstract parent class I 00:13:09.600 --> 00:13:12.959 guess so if you have something like nnml 00:13:12.959 --> 00:13:15.440 it has a request scan uh when it goes 00:13:15.440 --> 00:13:16.720 into request scan 00:13:16.720 --> 00:13:18.800 it ends up calling nnmail.newmail and it 00:13:18.800 --> 00:13:21.760 says I am calling this as an nml server 00:13:21.760 --> 00:13:23.279 and here are some of my callback 00:13:23.279 --> 00:13:24.959 functions and my variables that I would 00:13:24.959 --> 00:13:26.000 like you to use 00:13:26.000 --> 00:13:28.000 when you are getting your email so in 00:13:28.000 --> 00:13:30.120 this way the code is sort of you know 00:13:30.120 --> 00:13:33.120 inter-interleaved between the the child 00:13:33.120 --> 00:13:35.680 class and the parent class even though 00:13:35.680 --> 00:13:37.120 we're not talking in terms of classes 00:13:37.120 --> 00:13:39.440 here at all really 00:13:39.440 --> 00:13:42.160 so that's how noose works right now I 00:13:42.160 --> 00:13:42.959 hope that's clear 00:13:42.959 --> 00:13:45.519 it certainly wasn't to me and I still 00:13:45.519 --> 00:13:46.560 have to go refresh my 00:13:46.560 --> 00:13:48.079 memory I'd like to talk a little bit 00:13:48.079 --> 00:13:50.079 about sort of the newer 00:13:50.079 --> 00:13:51.600 libraries that are available now for 00:13:51.600 --> 00:13:54.240 doing object-oriented code 00:13:54.240 --> 00:13:56.959 uh as I mentioned I think earlier nno 00:13:56.959 --> 00:13:59.279 the copyright headers for 1996 so that's 00:13:59.279 --> 00:14:00.320 pretty venerable 00:14:00.320 --> 00:14:02.639 coincidentally around the same time eric 00:14:02.639 --> 00:14:05.519 ludlum started developing e-I-e-I-o 00:14:05.519 --> 00:14:08.320 which is a which is sort of inspired by 00:14:08.320 --> 00:14:09.360 a common lisp's 00:14:09.360 --> 00:14:12.720 common lisp object system um I got a 00:14:12.720 --> 00:14:14.240 very good introduction to that from this 00:14:14.240 --> 00:14:14.959 book 00:14:14.959 --> 00:14:16.399 practical common lisp which I would 00:14:16.399 --> 00:14:18.000 encourage you to look at if you haven't 00:14:18.000 --> 00:14:20.079 which you probably have anyway 00:14:20.079 --> 00:14:22.320 e-I-e-I-o was incorporated into Emacs in 00:14:22.320 --> 00:14:23.920 2010 00:14:23.920 --> 00:14:27.839 so that yeah e-I-e-I-o provides um 00:14:27.839 --> 00:14:30.240 the deaf class statements it provides 00:14:30.240 --> 00:14:32.079 deaf generics deaf methods all that sort 00:14:32.079 --> 00:14:32.639 of stuff 00:14:32.639 --> 00:14:34.800 sort of a common lisp object-oriented 00:14:34.800 --> 00:14:36.320 code 00:14:36.320 --> 00:14:38.399 at some point stephan monier's money 00:14:38.399 --> 00:14:39.760 money another name I haven't pronounced 00:14:39.760 --> 00:14:41.199 it all out 00:14:41.199 --> 00:14:43.839 started either cleaning up that code or 00:14:43.839 --> 00:14:45.120 for one reason or another writing a 00:14:45.120 --> 00:14:46.959 re-implementation of generic functions 00:14:46.959 --> 00:14:48.000 which was added 00:14:48.000 --> 00:14:51.440 uh in 2015 and then throughout this time 00:14:51.440 --> 00:14:51.920 another 00:14:51.920 --> 00:14:54.639 sort of object-oriented style 00:14:54.639 --> 00:14:55.760 declaration is 00:14:55.760 --> 00:14:58.160 defstruct which started off in the cl 00:14:58.160 --> 00:15:00.000 libraries 00:15:00.000 --> 00:15:01.600 implemented with vectors later was 00:15:01.600 --> 00:15:02.959 implemented with records so they're 00:15:02.959 --> 00:15:04.639 easier to target 00:15:04.639 --> 00:15:06.720 anyway that's another option so how 00:15:06.720 --> 00:15:08.399 would we this is I'm probably out of 00:15:08.399 --> 00:15:09.279 time already but 00:15:09.279 --> 00:15:13.839 we're only getting to the part 00:15:13.839 --> 00:15:15.760 the whole point of this is how would we 00:15:15.760 --> 00:15:17.920 rewrite someone news's code to use these 00:15:17.920 --> 00:15:19.920 newer libraries 00:15:19.920 --> 00:15:21.760 if we didn't have to support third party 00:15:21.760 --> 00:15:23.839 libraries this wouldn't be that hard 00:15:23.839 --> 00:15:26.639 but out there noose is really up on uh 00:15:26.639 --> 00:15:28.160 you know backwards compatibility and not 00:15:28.160 --> 00:15:30.240 breaking people's stuff and you know 00:15:30.240 --> 00:15:33.040 multi-decade support for things so there 00:15:33.040 --> 00:15:34.240 are people out there who have written 00:15:34.240 --> 00:15:35.759 third-party libraries 00:15:35.759 --> 00:15:38.480 um defining new backends for you can use 00:15:38.480 --> 00:15:40.000 like hacker news or whatever as 00:15:40.000 --> 00:15:41.759 a as a server so we want to be able to 00:15:41.759 --> 00:15:43.199 support those if you didn't have to 00:15:43.199 --> 00:15:44.240 support those it'd be fine you'd 00:15:44.240 --> 00:15:46.079 re-implement you'd use generic functions 00:15:46.079 --> 00:15:47.440 you'd use either structure classes 00:15:47.440 --> 00:15:48.560 whatever but we got a 00:15:48.560 --> 00:15:51.040 it's a little bit tricky to support 00:15:51.040 --> 00:15:52.000 these other people's 00:15:52.000 --> 00:15:54.320 libraries so one of the things we can do 00:15:54.320 --> 00:15:56.079 is rewrite the defu 00:15:56.079 --> 00:15:59.279 so if you remember defu is the thing 00:15:59.279 --> 00:16:00.079 that uh 00:16:00.079 --> 00:16:03.120 or sorry uh defu 00:16:03.120 --> 00:16:04.800 is the thing that defines methods that 00:16:04.800 --> 00:16:07.040 operate on object answers 00:16:07.040 --> 00:16:10.160 instances and we can uh rewrite that to 00:16:10.160 --> 00:16:10.639 use 00:16:10.639 --> 00:16:13.440 cldef generic and that's this is fairly 00:16:13.440 --> 00:16:14.240 fairly simple 00:16:14.240 --> 00:16:15.440 it looks like a lot of code it's not a 00:16:15.440 --> 00:16:17.759 lot of good for instance we have the 00:16:17.759 --> 00:16:20.320 new closed server code that we looked at 00:16:20.320 --> 00:16:21.199 earlier 00:16:21.199 --> 00:16:22.720 and we have this phone call and the new 00:16:22.720 --> 00:16:24.560 skip function so this would look 00:16:24.560 --> 00:16:28.720 like using generic functions and methods 00:16:28.720 --> 00:16:30.240 it would look like this we'd have 00:16:30.240 --> 00:16:32.959 a generic def generic which is just a 00:16:32.959 --> 00:16:34.560 sort of a declaration 00:16:34.560 --> 00:16:36.320 and a doc string and then we have those 00:16:36.320 --> 00:16:37.680 implementations 00:16:37.680 --> 00:16:40.320 so we can see what the original code 00:16:40.320 --> 00:16:42.399 does here is it first says okay what 00:16:42.399 --> 00:16:44.720 type is our our is our argument here and 00:16:44.720 --> 00:16:45.839 if it's a string 00:16:45.839 --> 00:16:48.560 then go and get the proper s the proper 00:16:48.560 --> 00:16:50.160 method definition 00:16:50.160 --> 00:16:52.480 from that string so the way we do that 00:16:52.480 --> 00:16:53.920 with methods is we 00:16:53.920 --> 00:16:56.000 we say if the server is a string so if 00:16:56.000 --> 00:16:57.440 it matches this type 00:16:57.440 --> 00:16:58.720 then what we're going to do is just 00:16:58.720 --> 00:17:00.320 recall we're going to call this function 00:17:00.320 --> 00:17:02.160 all over again 00:17:02.160 --> 00:17:05.199 using uh basically the same code here 00:17:05.199 --> 00:17:06.400 the same code that takes a string and 00:17:06.400 --> 00:17:07.600 gets the object so 00:17:07.600 --> 00:17:10.640 this does this can add extra function 00:17:10.640 --> 00:17:11.600 calls 00:17:11.600 --> 00:17:12.880 depending on how you've written the rest 00:17:12.880 --> 00:17:14.880 of your code um but this is sort of the 00:17:14.880 --> 00:17:16.640 canonical way of doing this 00:17:16.640 --> 00:17:19.679 uh using methods then our next part here 00:17:19.679 --> 00:17:20.559 is 00:17:20.559 --> 00:17:22.000 nishkit function we're going to get a 00:17:22.000 --> 00:17:24.559 function called closed server 00:17:24.559 --> 00:17:26.079 the difference here is that all these 00:17:26.079 --> 00:17:27.360 functions are all going to be called 00:17:27.360 --> 00:17:28.000 close 00:17:28.000 --> 00:17:29.360 news close server they're not going to 00:17:29.360 --> 00:17:31.120 be called news like nni my 00:17:31.120 --> 00:17:32.799 closed server and ntp close server 00:17:32.799 --> 00:17:34.400 they're all going to have the same name 00:17:34.400 --> 00:17:36.160 and what we do is uh we have an around 00:17:36.160 --> 00:17:37.440 method 00:17:37.440 --> 00:17:40.640 for any server that is a const which is 00:17:40.640 --> 00:17:43.679 which is as close as we care to get uh 00:17:43.679 --> 00:17:45.520 for you know zeroing in on the type that 00:17:45.520 --> 00:17:46.799 we're looking for 00:17:46.799 --> 00:17:48.559 we put in a round method on that so that 00:17:48.559 --> 00:17:50.480 we can call the next method which we'll 00:17:50.480 --> 00:17:51.679 call the more specific 00:17:51.679 --> 00:17:53.440 method and then we have our other 00:17:53.440 --> 00:17:55.600 bookkeeping code to clean up you know 00:17:55.600 --> 00:17:57.280 set up tear down code we'll go around 00:17:57.280 --> 00:17:58.640 that 00:17:58.640 --> 00:18:00.080 and then in one of the back-end 00:18:00.080 --> 00:18:02.080 definitions for instance in an imap 00:18:02.080 --> 00:18:04.320 we have another news closed server thing 00:18:04.320 --> 00:18:05.760 this looks at the server 00:18:05.760 --> 00:18:08.880 and it says is this server a list that 00:18:08.880 --> 00:18:10.799 starts with a symbol and an imap and if 00:18:10.799 --> 00:18:12.480 it is then we're almost guaranteed that 00:18:12.480 --> 00:18:13.679 this is what we wanted 00:18:13.679 --> 00:18:15.840 and then this is where we would insert 00:18:15.840 --> 00:18:17.600 all the rest of the code from anonymous 00:18:17.600 --> 00:18:18.960 closed server 00:18:18.960 --> 00:18:20.799 where we'd re-redefine that to look like 00:18:20.799 --> 00:18:22.880 this so it's not that hard 00:18:22.880 --> 00:18:26.080 theoretically so what we would do 00:18:26.080 --> 00:18:28.720 is take the defu macro macro and then 00:18:28.720 --> 00:18:29.679 rewrite that 00:18:29.679 --> 00:18:32.240 so that it actually defines a cl def 00:18:32.240 --> 00:18:33.039 method like 00:18:33.039 --> 00:18:35.520 one of these now there's a couple of 00:18:35.520 --> 00:18:36.320 these things 00:18:36.320 --> 00:18:38.960 unfortunately it's not that easy get rid 00:18:38.960 --> 00:18:41.200 of you 00:18:41.200 --> 00:18:43.490 a couple of these things 00:18:43.490 --> 00:18:46.400 [Music] 00:18:46.400 --> 00:18:49.039 that don't use their server as the first 00:18:49.039 --> 00:18:49.919 argument 00:18:49.919 --> 00:18:52.400 or any of the arguments or it's an 00:18:52.400 --> 00:18:53.280 optional argument 00:18:53.280 --> 00:18:54.720 and we need the server to be in there to 00:18:54.720 --> 00:18:56.640 dispatch on its type 00:18:56.640 --> 00:18:58.799 if the server doesn't show up as a as a 00:18:58.799 --> 00:19:00.080 required 00:19:00.080 --> 00:19:01.760 argument we're not going to be able to 00:19:01.760 --> 00:19:03.600 locate the the proper 00:19:03.600 --> 00:19:07.440 function call so in the case of 00:19:07.440 --> 00:19:10.640 noose request group here we start with 00:19:10.640 --> 00:19:12.080 the group it's the group that matters 00:19:12.080 --> 00:19:12.720 and we get 00:19:12.720 --> 00:19:14.960 the newscommand method as an optional 00:19:14.960 --> 00:19:16.240 argument 00:19:16.240 --> 00:19:18.559 so that's not cool we don't want that so 00:19:18.559 --> 00:19:20.480 what we need instead is something that 00:19:20.480 --> 00:19:21.360 looks like this 00:19:21.360 --> 00:19:23.840 what we're going to do with uh this is 00:19:23.840 --> 00:19:25.360 gonna be just terrible terrible code but 00:19:25.360 --> 00:19:26.640 hopefully it won't get used very often 00:19:26.640 --> 00:19:28.160 it's gonna be really embarrassing 00:19:28.160 --> 00:19:30.559 um defu what's what definitely was gonna 00:19:30.559 --> 00:19:31.520 have to do is 00:19:31.520 --> 00:19:33.200 say okay is this a function that doesn't 00:19:33.200 --> 00:19:34.559 have the server as the first argument 00:19:34.559 --> 00:19:35.360 and if it does 00:19:35.360 --> 00:19:36.960 it's gonna say oh it's news request 00:19:36.960 --> 00:19:38.400 group what happens has to happen with 00:19:38.400 --> 00:19:39.280 news request group 00:19:39.280 --> 00:19:40.799 is we take the news command method and 00:19:40.799 --> 00:19:43.200 we're going to move it up to the front 00:19:43.200 --> 00:19:46.240 to the first argument here and it's 00:19:46.240 --> 00:19:47.520 either going to be 00:19:47.520 --> 00:19:48.720 it's either going to be given or it's 00:19:48.720 --> 00:19:50.840 going to be nil because it's it is 00:19:50.840 --> 00:19:52.080 optional 00:19:52.080 --> 00:19:54.320 okay I briefly edited the space time 00:19:54.320 --> 00:19:55.760 continuum there to conceal the fact that 00:19:55.760 --> 00:19:56.400 I had 00:19:56.400 --> 00:19:57.679 actually not finished writing the code 00:19:57.679 --> 00:19:59.440 that I was supposed to write anyway 00:19:59.440 --> 00:20:02.159 um so now we have once we've reordered 00:20:02.159 --> 00:20:02.960 the 00:20:02.960 --> 00:20:04.320 the arguments to the function then we 00:20:04.320 --> 00:20:05.760 have to check our various possible 00:20:05.760 --> 00:20:06.880 values one is 00:20:06.880 --> 00:20:08.640 uh that the server was not passed in in 00:20:08.640 --> 00:20:10.080 which case we recall 00:20:10.080 --> 00:20:12.400 request group with the server um the 00:20:12.400 --> 00:20:13.840 other is that it's just a string in 00:20:13.840 --> 00:20:15.360 which case we do that and then this is 00:20:15.360 --> 00:20:16.559 sort of the the normal 00:20:16.559 --> 00:20:18.559 the normal case that we would expect to 00:20:18.559 --> 00:20:20.720 cons so that's not that bad it's not you 00:20:20.720 --> 00:20:21.039 know 00:20:21.039 --> 00:20:23.760 it's not beautiful um I would be sort of 00:20:23.760 --> 00:20:24.480 ashamed to 00:20:24.480 --> 00:20:26.159 let anybody see that particular macro 00:20:26.159 --> 00:20:28.000 but I think that it would work okay 00:20:28.000 --> 00:20:30.640 now the more difficult thing is going to 00:20:30.640 --> 00:20:31.440 be 00:20:31.440 --> 00:20:34.640 the data variables so 00:20:34.640 --> 00:20:37.600 the equivalent of def vu because our two 00:20:37.600 --> 00:20:39.360 options for defining classes here are 00:20:39.360 --> 00:20:41.039 def struct and def class both of which 00:20:41.039 --> 00:20:41.919 required you 00:20:41.919 --> 00:20:45.280 to define the slots inside this macro 00:20:45.280 --> 00:20:46.960 itself 00:20:46.960 --> 00:20:49.039 so defu is top level um how do we get 00:20:49.039 --> 00:20:51.280 the top level this top level macro 00:20:51.280 --> 00:20:55.039 uh to insert slot names into these 00:20:55.039 --> 00:20:56.240 definitions it's 00:20:56.240 --> 00:20:58.960 it's possible that it'll be um that I 00:20:58.960 --> 00:21:00.240 could monkey patch 00:21:00.240 --> 00:21:03.039 uh an existing struct or an existing 00:21:03.039 --> 00:21:04.799 class to add a new slot into it that 00:21:04.799 --> 00:21:05.280 sounds 00:21:05.280 --> 00:21:07.760 ugly the other option would be to give 00:21:07.760 --> 00:21:09.600 it a server variable slot which is just 00:21:09.600 --> 00:21:11.520 a generalized bucket 00:21:11.520 --> 00:21:13.760 that holds anything that gets defined 00:21:13.760 --> 00:21:15.520 via def loop 00:21:15.520 --> 00:21:16.720 I don't like either of those solutions 00:21:16.720 --> 00:21:18.799 but I'm I don't see any other 00:21:18.799 --> 00:21:22.480 any other way of doing that so we re 00:21:22.480 --> 00:21:25.520 rewrite the nno declare macro to either 00:21:25.520 --> 00:21:27.440 be a destructor or a def class 00:21:27.440 --> 00:21:29.840 and we rewrite the def boom macro to 00:21:29.840 --> 00:21:31.039 somehow 00:21:31.039 --> 00:21:33.039 associate that variable name the symbol 00:21:33.039 --> 00:21:34.480 with the with the resulting class 00:21:34.480 --> 00:21:36.159 definition 00:21:36.159 --> 00:21:37.760 then the last question is do we use 00:21:37.760 --> 00:21:39.600 structure classes 00:21:39.600 --> 00:21:41.600 they both got their their strengths and 00:21:41.600 --> 00:21:43.200 their weaknesses 00:21:43.200 --> 00:21:46.480 the nice thing is that I mean I've got 00:21:46.480 --> 00:21:47.520 how many servers you're going to have 00:21:47.520 --> 00:21:49.600 really I've got I think less than 10 00:21:49.600 --> 00:21:51.919 uh truly deranged mine might have as as 00:21:51.919 --> 00:21:52.960 many as 00:21:52.960 --> 00:21:55.440 50 let's double that to 100 100 of 00:21:55.440 --> 00:21:56.480 anything is not going to matter it 00:21:56.480 --> 00:21:58.400 doesn't matter what we use 00:21:58.400 --> 00:22:00.159 death structures are simpler they're 00:22:00.159 --> 00:22:02.720 lighter weight they're defined on top of 00:22:02.720 --> 00:22:05.600 the direct the c records so you know 00:22:05.600 --> 00:22:06.960 that's nice 00:22:06.960 --> 00:22:08.559 the slots don't carry very much 00:22:08.559 --> 00:22:10.320 information with them there's no type 00:22:10.320 --> 00:22:11.760 information there's no doc string for 00:22:11.760 --> 00:22:14.480 the slots themselves 00:22:14.480 --> 00:22:16.559 they can also only do single inheritance 00:22:16.559 --> 00:22:17.919 which some might say 00:22:17.919 --> 00:22:21.120 was an advantage def class each slot 00:22:21.120 --> 00:22:22.640 gets a lot more information associated 00:22:22.640 --> 00:22:24.000 with it with it which I think can be 00:22:24.000 --> 00:22:24.480 nice 00:22:24.480 --> 00:22:27.120 it can do multiple inheritance if you're 00:22:27.120 --> 00:22:28.799 going to go there 00:22:28.799 --> 00:22:30.720 they are heavier weight in particular 00:22:30.720 --> 00:22:32.640 their printed representation is gross 00:22:32.640 --> 00:22:34.080 it's enormous 00:22:34.080 --> 00:22:35.840 so if you see one show up in a back 00:22:35.840 --> 00:22:37.520 trace or in your messages buffer can 00:22:37.520 --> 00:22:38.240 really 00:22:38.240 --> 00:22:39.520 it can really blow that up and make it 00:22:39.520 --> 00:22:41.360 hard to read this of course won't be an 00:22:41.360 --> 00:22:43.200 issue because our code won't have any 00:22:43.200 --> 00:22:46.240 errors in it um my argument for multiple 00:22:46.240 --> 00:22:48.320 inheritance here is that I can imagine 00:22:48.320 --> 00:22:51.280 new servers falling into sort of like a 00:22:51.280 --> 00:22:52.720 little two by two matrix of 00:22:52.720 --> 00:22:56.240 of parent classes one being news versus 00:22:56.240 --> 00:22:56.799 mail 00:22:56.799 --> 00:23:00.320 so news the messages belong to somebody 00:23:00.320 --> 00:23:00.720 else 00:23:00.720 --> 00:23:02.080 you can't touch them you can't delete 00:23:02.080 --> 00:23:03.840 them mail meaning 00:23:03.840 --> 00:23:06.000 the messages are under your command 00:23:06.000 --> 00:23:08.960 either a local mail dealer a remote imap 00:23:08.960 --> 00:23:11.039 you're allowed to spool them copy them 00:23:11.039 --> 00:23:12.640 delete them at will 00:23:12.640 --> 00:23:13.919 and then the other sort of line of the 00:23:13.919 --> 00:23:16.400 matrix would be a local file system 00:23:16.400 --> 00:23:19.760 versus some kind of a you know server 00:23:19.760 --> 00:23:20.559 port 00:23:20.559 --> 00:23:23.280 remote access and that second the server 00:23:23.280 --> 00:23:24.960 port remote access thing might require 00:23:24.960 --> 00:23:26.880 authentication it might require a keep 00:23:26.880 --> 00:23:28.559 alive for a connection 00:23:28.559 --> 00:23:30.159 um it's there's going to be a process 00:23:30.159 --> 00:23:31.600 there rather than just file system 00:23:31.600 --> 00:23:32.400 commands 00:23:32.400 --> 00:23:33.840 so I could see if I was going to do 00:23:33.840 --> 00:23:35.360 multiple inheritance that's what I would 00:23:35.360 --> 00:23:36.240 do those two 00:23:36.240 --> 00:23:39.039 those two possible parent classes anyway 00:23:39.039 --> 00:23:40.400 that's as far as I've gotten 00:23:40.400 --> 00:23:41.520 I thought that I would be able to write 00:23:41.520 --> 00:23:43.279 more of this code before I did this talk 00:23:43.279 --> 00:23:44.720 but instead I spent the whole time 00:23:44.720 --> 00:23:46.720 messing with video codecs but that's 00:23:46.720 --> 00:23:48.320 where we're at and I'm going to cut 00:23:48.320 --> 00:23:49.440 myself off now 00:23:49.440 --> 00:23:50.960 I hope there are questions I hope I'm 00:23:50.960 --> 00:23:53.440 there to to answer your questions 00:23:53.440 --> 00:23:55.919 and thanks very much again to everyone 00:23:55.919 --> 00:23:57.120 involved 00:23:57.120 --> 00:23:59.279 bye