 Talking anything Emacs related, we're talking about, I mean, there's going to be programming involved. Now, my session tends to be much more programming involved than even your typical Emacs talk. So the question is, programming experience, list specific programming experience, everybody has basic understanding. So I will not talk that much about Emacs list. There is some Emacs list by the end that I will demonstrate. But primarily it will be common list and its integration into Emacs and how a normal application development workflow can. And in this specific case, I will be talking about an application that I've worked on for a little while. It's essentially, it started out as a, we needed an alternative to Slack because Slack was online. We couldn't use an online service. So we had to use something that can run on our own servers. And turns out at the time there wasn't anything. So we decided, we figured it can't be that difficult to put something together. So we did. And in a few months we had something fairly decent. It's been running in production for quite a long time in our office. And so I developed the server site and the service written in common list. And the client is written in code descripts, which is, but I wrote perhaps only about 15% of that code, maybe 20%. But anyway, so just a little bit background what's going on. There is, the entire system is stores all the state they encounter. There is a, all the components communication between the different modules is done using Rabbit NQ. And I would like to thank Pivotal for actually supporting that product. It's pretty awesome. And then there's some Emcache and some Solr for free text search and things like that. So anyway, when, how many of you have developed a real application in Lisp or maybe or small talk perhaps that also has a similar view? All right. So Lisp development is quite different or somewhat different from typical development. That's a C++ or Java or even Ruby in that you don't normally write your code, compile it, run it, test it, and then restart. That loop does not exist. So anyone who has tested maybe you guys have tried out, you know, a Lisp tutorial or something like that where you start a session, probably something like this. And then the tutorial tells you, oh, you can type plus one, two, and give you three. Great. And you can print something on the screen. Great. But then what? And when I've talked to people that wanted to use Lisp to develop an application, they really didn't get much further than this. Because they didn't really figure out, okay, where's what's the next step? How do I actually develop an application? How do I take advantage of this pretty awesome tool, which is Emacs, Slime, and CommonLisp to actually do a real application? So I'm going to skip now project definitions and things like that and just suffice it to say that once you have a project definition and set up all the paths and everything, all you do is to load the application like this. This will, if any files were changed, they would be compiled. And then the compiled files goes into the cache. So when you reload the application, it's very fast. But if I were to flush the cache now, my slow machine would take quite a long time to compile. Probably a minute. So let's just do this because I'm going to demonstrate some things like that. So right now, I've loaded the application. It consists of some number of functions, quite a lot. And we can open the source, let's just start the application first. So right now, I just ran a function that starts the server. This starts the web server. So we can just do a quick look to see that it runs. And it does. It remembered my session, so I didn't need to log in. Let's try to log in. See if it works. Test, test. So what is actually going on here? I have now an application running in a web server is running. We can, from within Emacs, we can look at the threads. So these are the threads that we have, 33 threads right now. And one of those threads being the interaction thread where I typed my commands. I can, of course, do this still. And I'm now interacting with the runtime that is actually doing all the web stuff here. That means that I can interact with the running system. So let's say, for example, that I want to load a user. So I have an email and this test user. Now, this, now, this is quite obvious. I simply loaded an object. And this loads from the database with some caching or magic, but never mind. And this represents, this shows me that it has now loaded this object that represents this user here. Now, but, and this is a really, in my opinion, a quite neat feature in Slime that because of this is red, it means that this is not just the text that represents the object that I loaded. It's actually contains inside of it a reference to the underlying object in the list machine that is running. Which means that I can go to this line and press ctrl-c, ctrl-e, tab. And this shows me the actual, so the user is actually an instance of an object. And it shows me here that the class is a class user. And here are the fields. And, you know, we can manipulate these fields. For example, we can change the description here. So, we set the description here. Now, it actually changed the object that is inside the list runtime. So, what does that mean? Well, it means that I can go in and manipulate actual live objects in the system. So, and this even survives copy and paste. So, I can, for example, copy this and do a, I don't know, type of, I call type of, which returns the classes like in Java dot class or dot get class. And tells me that this is type of type user. Now, had I written something like this, whatever something, I would get an error because hash less than is not a valid character. But what this shows is that the thing I pasted in here isn't actually the string. It's actually the object that is represented by that string inside the list. So, I can even take this and then I say, for example, So, I built a, before we do that, let's just take a look again. So, I can obviously do quick jumps. So, when I press make a dot, I can jump to whatever I'm pointing at. In this case, I'm pointing at an instance of an object. So, it jumps to the source code that defines this object. So, this defines the class. Description can pass with blah, blah, blah, blah. So, this is a special magic here, a special meta class that allows me to using only this definition here to transparently map objects in instances to a persisted object in CouchDB. So, we can take a look at that just for now. The primary key in CouchDB is this. Oops, sorry. It's actually this. So, I can copy this here. Let's go to CouchDB here and let's take a look at this object. So, you can see it created a CouchDB object. So, I didn't have to write any CouchDB code to persist the object. It's all handled automatically by the system. And it's propagated all the way to the web application as well. So, if I decide to save this object, if you keep your eye on this, once I save this object instead of changing the name, it should automatically change in the session here. So, let's try this. It should work because it's quite extensive here. So, I just saved that instance and it updates all the way to the project. Now, the way this works is... Well, if it doesn't really matter how it works, there are callbacks being called and the persistence and representations of the object on the browser side. But now my... What I want to illustrate here is how you work with objects inside the running instance. The entire application runs now and I can make modifications to the application without actually restarting anything at all, even in an active session in Okta. So, for example, let's take a look at... I mean, I'm sure a lot of you have played around with something like Rubin Rails where you define handlers for a web method. So, let's see how such a thing can be done here. So, let's take a look at this, for example, and let's pick something... I'll tell you what, let's create a new file. No, let's just create something. Let's add something here. So, I can do this foo screen, for example, and the URL to access this one is slash foo... slash bar because I think I have a slash foo already. And let's make it a bit more clever. Let's make it like that. a2z plus this is not any regex that matches that. And let's find that to a variable v. Now, as soon as someone... if I were to now go to this page, the resource is not there. Because I haven't actually... I just typed this entry now. I would get the same one for bar because I'm there, right? So, let's simply return a string. Hello. And what I can do in slime is if I want to compile just a single function or a single form, I just go to the form and I press counter c, counter c. And that gave me an error. Oh, okay. Format, nil, hello. So, what this does is essentially it's... some name, so it's more clear, some name. What this does is whenever someone goes to slash bar slash and the sequence of letters, the variable sum name will be bound to this string. And now I can press counter c, counter c. And it's compiled that function. It just compiled that function. It didn't compile anything else. Just that function. And now that URL is a real working URL. Now, what is interesting here is that since I didn't have to restart anything, that means that even if I have an existing web socket connection like here, it's not impacted whatsoever. So, this way of developing, I find to be quite, shall we say, liberating. Because, as you can see, there is no... there is no edit, compile, test cycle. It's edit and it's all blurs together into one thing, which makes development of these things incredibly simple. Because if I want to change something, hello again, and like this, I just reload the page and change it. Without anything else being impacted, in fact. And this is something I did not prepare for, so let's see if it works. Because I haven't actually tested this in a while. Because Slime allows you to communicate with the remote instance of a Lisp instance. I can even connect to a live running production system. So, I have a test environment running on the internet, which is here, which is the same. I just have a different set of channels and some stuff here. But what I can do now is I can connect to that instance, and I have to do a port forward for the port that is used to communicate with the running instance. So, okay, there. Now, one thing I would like to mention before I show something else is that what is running is actually this binary here. This is a pure Linux binary that is generated from the... I will compile the application into a separate binary that I want. But I can still, let's see if it works. So, let's say I want to this one, and pivot, and Slime connect, and localhost for 98.98, and let's say it works. And, of course, it didn't because crap. It's because the version of Slime I'm running here is not matching the version of Slime I'm running remotely. Sadly, that means that I can't demonstrate that part, but suffice it to say, I'll just tell you. Essentially, it works exactly the same. There's no difference whatsoever. It looks the same, it works the same. Whenever I choose to go to the source code, it will use Tramp, which, as you know, is a way to transparently access files remotely. So, it uses Tramp over SSH to access the actual source file on the remote side, which means... Oh, yeah, it doesn't work here. It creates the thing about it, then I get all of these errors and sort of frustrating. So, let's start my local connection to time, but then it's frustrating and annoying. So, let's just do this again, and put it ahead, 98, and Slime, and there, and build the application again. Here, as you can see, I modified some file, and the problem is that file I modified was dependent. All of these were actually dependent on that one, so they decided to recompile all of that stuff as well. But as you can see, it's not that slow, and if you have a fast machine, it's never really a problem to recompile anything. Let's take a look at another interesting aspect of... This is more of a benefit of Communist rather than Emacs itself. Emacs just made it easier to show you what's actually going on. So, if we go to the main page here, and we look at the source code, we see, well, HTML, and this is all generated by a template. And what template language am I using? Well, I'm in this program, so of course I wrote my own. So, let's take a look. It looks like it's somewhat... It's quite decent, ish. So, this one has... This stuff should be pretty clear, so let's look at the main logged in, and here we have... So, we have some... We have includes, we have some if statements. We can put in some... Yeah, inject some information that was passed to the code that calls the template. So, let's take a look at this, and we go in here, and let's take a look at that. Now, what's called show time. So, what happens here is that I call in my handler. So, this is a variation of the handler that ensures that you're logged in. Otherwise, it's the same. So, it says show the stream represented by this template find with these parameters here. Now, one thing this is really good at is manipulating data structures, which is actually code. So, all I really have to do in order to create a template language is to parse the template and then generate the corresponding list code that would execute that template. That means that if I have a template that just contains raw text, the resulting list code will be a single write... write array that just writes the binary data represented by that page to the screen. It's one instruction, compiled to native code. So, because of that, there is perhaps a case for me arguing that this is possibly the world's fastest template language under certain circumstances. Those circumstances being there's no logic inside it. But even when there's logic, the each statement inside the template is just translated into a corresponding statement in list code. So, I wrote a small function that I used when I developed the template language so that I can test to see the resulting code. So, that one is called debug something, debug parser, and I just put my template code in a string. So, if I have a template that just contains this, well, there's a lot of stuff around it, but the key here is that... the key here is that the entirety of the code compiled into this. So, this is UTF-8 representation of that string. However, if I want to say, do something like this, so I'm using this kind of if, foo, then xx, otherwise else, yy, and... And as we can see here, first we write some text, then an if statement followed by two different write sequences depending on which one. So, we can see here how this compiles into native code. Then I just pass this through the compiler because in this you have the compiler all the time available. So, obviously when I do a lookup of the template, the template will... it checks the local cache if it's already there. If it is, then it checks if the file has changed. If it hasn't, then recompile it. So, we can take a look at that. So, this one, those are stored in the global variable called cached template. So, this one is... we can see that it's a hash table that contains zero elements because I have to reload the page, sort of. There. So, we've got a debug message saying that it parsed the files. Now, this hash table contains two elements. As you can see, the same way, we can just inspect the object live. And we can see that this is a hash table containing two elements. And this is the, again, the inspector, which is really nice. So, you can see that this is a hash table where these two files are mapped to the corresponding instance of an object to parse files. So, we can dig down into that and take a look at, okay, so, this one is actually an instance we've talked about that has the modifier of the time and the name containing a list of the files that were used to construct this file so that it knows which files to check, modification for it. And a function. And this is the function that was compiled when the file was parsed. It generated the lambda expression that you saw. It ran it through the compiler. The compiler returns the function object that is the compiled code. Well, this is given a random internal name because you don't call it normally. You always call it through this reference. It has this data type. And it has this code. So, you can even go in here and take a look at the actual generated source code. So, the inspector also allows me to look at the disassembly for any function. Now, obviously, the disassembly is also available through the list command of the disassembly, the princet, but it's easier to traverse and edit using... using the inspector. Now, this is all cool and stuff, but we need more emails. So, not being happy with this, then I realize that this is a very nice... this application, which is cool and all, but it's also a very nice thing to use to experiment with other things. Like, for example, learning how to write a fully-fledged Emacs application. So, I did. So, I decided... So, I needed something to test the API because the... Oh, now I know why this thing doesn't load. It doesn't load because... Oh, crap. Oh, no. It doesn't load. I haven't started the Clojure script part yet because I've resorted my Emacs course. And I guess I should do that. I'm terribly sorry. I should have remembered that. So, let's just... I was hoping that my colleague would come today so that he could talk more about how the Clojure script is used here. I only use it a bit to develop some parts of the application. My problem is that I am a terrible web designer. I am the absolute worst. And if you claim that you are worse than me, I challenge you to a competition because you will lose. But... But I do know. I do know my JavaScript and HTML and Clojure script and those things. I just don't know the zone. Absolutely not. Which makes it even... So, while waiting for this... Oh, okay. There it is. So, let's... Let's go ahead and do this and go into the source code because I have put the mnemonic in there as to what command to type to actually connect it. Because this is all pretty cool. I can just demonstrate a little bit about it because Cider is sort of like slime but for Clojure. And it also works with Clojure script. Meaning that when I do this... So, let's go to the web picture and... Let's see if I can remember the stuff. So, what I can do here... Let's inspect. So, console is here. So... I can use... Plus 1, 2. So, when I run commands like this, you see it takes a little while for this thing to return. It's because my computer is slow. So, this is actually being executed in this browser plugin that allows me to integrate this here. Which means that, for example, if I could... Let's see. Yeah, if I want to put up... Gosh, what is it? GS standard. GS standard. Yeah, like that, right? And this should pop up that one here. Which means that I can manipulate and look at the state of the actual application on the client through Emacs and using Clojure instead of having to work with JavaScript. So, all the... And I get, of course, all the extensions so we can do slash... Let's see if we have something interesting. Like I said, most of this code is not mine, so that's why... And I haven't worked on this for a little while, so that's why... But anyway, you can look at the variable here. Yeah! What was your goal last time, Chase? Yeah. So, here I just displayed the content of the variable... Now, since we're using... Since we're using React, that means that if I were to actually change these objects, the underlined Clojure script objects, the... the GUI changes automatically. And so, that's how the... These fields here, like anything I changed on the server side, it propagates all the way down because it updates the state on the browser side, and then the React.js comes into play and updates the GUI to represent the internal state. Anyway, so... But I also decided to implement... Sorry! So, let's go here to this one, and let's load a little bit of Emacs here. And implement... So, to test the... the API, the newest client, of course. Because, well... So, let's just give a buffer and... And it should hopefully connect... Now, I'm using the external server there. So, let's use... I don't know, tests... Tests... When I type something here, this is a new message. That's here. Hello! I get the proper notifications. Basically, if I... If I send a message directly to a user, then if that user is not logged in, he will get an email after a while or there will be a notification popping up. Now, I'm logging in as the same user on both sides. So, even when I do send a direct message, I will not get messages from myself. But, this taught me that you can actually work with pictures as well. So, obviously, since I uploaded a photo here, let's do it again, just to show you what that works. Pictures... Let's start our pictures. That's all I have, because that's all you need. And it's uploaded. And hopefully, unless I mis-configure anything up there, and there is any of this in all its glory. Now, as I said, I didn't really... In my mind, before today, I went through and had a number of things in the head that I wanted to mention. I wanted to talk about how cool it is to be able to write a chat in an Emacs. Now, one interesting thing here is that this file is... Okay, it's just Chai 1000 lines of code. And I wanted to mention that Cider allows you to integrate with a browser just the same way as Stein allows you to talk to a a common list. I wanted to show you the fact that the inspector allows you to not only look at objects, you can modify them, and that you can look at everything, including functions, and its disassembly. And I also wanted to show how you can compile functions on the slide, and how those functions necessarily just have to be an normal function. It can be stuff that do something more, like register a web handler, like I showed. And so, that was essentially the list of things I wanted to mention and show off. And so, that sort of covers the things I wanted. Now, I really, really hope that someone has questions, because that means that there's at least a little bit of interest. So, are there any questions? Yeah. So, back towards the earlier part of the slide, we have the dynamic reference that's not just text. So, the computation that's lying around. Yeah. Now, if you put the cursor on it and do control u, control x equals, it's much easier to get. Ah, you mean how it's implemented? Yeah. You are right. I'm going to see why. Ah, that is very, very. So, actually, I do the same thing in the chat client. Let me use the chat client instead, because it's simpler to understand. So, let's go to Hello. Okay, it's really hard to reconnect. So, again, let us see how I implemented this. So, user references. So, let's put, for example, someone's name, one of my test users. Ah, okay. Test. So, the thing is, here what you're seeing on the screen right now is just our test, a name and test. Okay, fine. There are some color changes, whatever. But when you press return, what I need to send to the server is not just this string. I need to send the user ID of the user that I typed in. So, how do I handle this here? Because what I manipulate here is just text. And this is exactly the same the same problem that the designers of Slime were faced with when they had to connect some extra information to some piece of information in they had to attach some extra information to some text in an Emacs buffer. So, let's do it again just to see one trick here, for example, if I remove this, it's no longer a reference to the user. So, then, of course, the highlight disappears. So, how is this actually done? So, what's the recommendation was to use Ctrl U, Ctrl X equals, which will show information about the character here, the D in this case what is actually there. And this is a super useful feature especially it would show you what font that's cool. And it shows me the actual character and it shows me the Unicode name it should show me somewhere the code point here 64 that's a Unicode code point all of this is useful, but it also shows me that there's something called an overlay and in this particular case, the overlay specifies an alternate face and the face is a set of attributes governing how a character is displayed. In this particular case it's the one-call-potato message in produce name which is just gray background black text. It also has a modification hook in case I change it then I need to remove the reference and then the special potato user rush. This, so the overlay is simply just a set of, it's a key value map essentially but that's good nothing so in this case the key potato user ref contains a string which is the which is the ID of the object in the database so I go here I can of course go here and I should be able to put that in the database and because that's on the remote server if I were connected to that one I would get this corresponding information for that. Now overlays when you copy and paste overlays don't the overlays don't come with the they don't follow the text when you copy and paste it just sits there but if you you know I mean if you edit before and after it follows the text but as soon as I remove it or try to copy it or anything it disappears. Now in Slime's case you can copy and paste it but that's because Slime is a bit clever that they do stuff that I didn't really want to but I mean I could what they do here and we can take a look at it as you can see here they have a multiplication hook they are inserted behind the these are functions that are called oh wait these are the properties these are functions that are called when certain things happen to a given part of the text and in Slime's case what they do is they know they check if you try to copy it then you take the information then you trade the new reference to the new copy so element but in essence the underlying functionality is the same now as you can see they use text properties text properties are kind of like overlays but they are touched directly to characters they do follow the characters when you copy and paste it but overlays are objects in their own rights text properties is only for one character has a certain property so what I do I also take advantage of that in the in my sorry in this test here so as you can see now it says ABC there so if I decide to say delete that it should disappear from the in the emacs here or if I decide to edit it let's just change this text and it changes I use text properties in order to be able to so when a message comes to the browser to the emacs application that says oh a message has been changed or it has been deleted it contains the information it contains the message ID so in order for me to be able to find the message ID I actually assign the message ID as a property to this text here which means all I have to do is I just have to search the buffer for some characters that has this message ID associated with it and I can then manipulate the text just like in the other emacs code and of course I also need to be able to store the timestamp because when a message comes in it may actually be an older message because sometimes messages don't come in the right order so I just need to be able to put it in the right place so I also track the timestamp in a proper ISO 8601 format so I don't have to try to parse this stuff because this depending on language this may be different but the actual under buying data is stored in a standardized format here so that's how you can put a lot of extra information together with text so as you can see the buffer in emacs is not just text it's the text but with a lot of extra additional information associated with the actual characters so I think that was an absolutely astonishingly excellent question I would pet you on the back if it wasn't for the fact that I was sitting so far away I think the analogy of text qualities or of kind of like extra attributes I think it was born into something and maybe that again sure, yes, when emacs is a buffer sub-stream which is just a buffer sub-stream it's certainly got to be with text so you actually have to say that the function was actually no properties if you just want to say I want to hear a bunch of stuff there's another function that can strip the text property we can show that actually if I put let's see what the value of point is now so point is 3148 so let's just do this so I do buffer sub-stream properties point and point so I take three characters from point that should give me food let's see what it looks like when I take buffer sub-stream and as you can see this is actually also but it contains a bunch of properties all the functions in emacs that works with strings they work with these objects too so if you play them they look a bit weird but it's actually because it's the string the only part you're interested in is in this part here the rest is just saying technically this says between character number 0 and 3 you have these properties set so you can have a lot more complicated sets parts of the string may have some properties other parts may have others and if you use the don android programming it stands in android yes are you sure yeah yeah you're right now I'm using hk one of these days I'm going to make ctrl x equals to swap them because I don't think I've ever needed ctrl x equals but you ctrl x equals I have all the time in emacs things emacs what I've made dozens of emacs things does ctrl u ctrl x equals show you the properties it's like a extra complicated display of place for the current character I don't know it just gives me this no no we ctrl u exactly ctrl u that's what I'm saying ctrl x equals I never ever use it's complete so what are one of these days I'm going to make ctrl x equals b ctrl u ctrl x equals so yeah that's some of the things that you can do if you like this so I managed to create an entire workflow with this application where there is everywhere literally everywhere if you if you want to call ctrl j which some people do so that's cool I think any other questions from someone else Cider actually uses Cider uses Cider uses I'm sure it does yeah that's slightly good if I even read s expressions in my software itself there will be over the years I did that that would be one of the variations of Cider are you sure overlay I mean overlays is just a very very low level fundamental concept where you attach create an object that belongs to a range of characters that's all that overlay is it has no visual representation at all unless you choose to give it a special visual representation for example in both overlays and the properties you can add some extra text that is displayed but it's not actually part of the buffer so you can do the opposite or you can mark a section as being not shown which is what the hiding features in ormo for example that's when you press add pretty simple so if you have that js pretty simple zone you can have function terms about this one or like a play show or something like that which is quite a lot of text it means a thing there it's not the other text right you create an overlay that changes the appearance of the characters but the characters in the buffer are still the same so at the end if we're just going to be open I guess we'll better end up with cogs for example let's do the core one and this I'll go to any function and press control and add this one and what do you want me to press what control and add control make the x it actually creates an overlay that tells you that you're very clean I really like that because I don't actually have to go and look at the record and see what looks like oh okay that thing that's interesting because have you tried that for clodra script the thing is here it's called siderecton I'm using siderecton with clodra script there's a new function in siderecton it's called siderecton in clodra script so it makes you direct to your clodra script rather than to run it that's why I actually wanted my colleague to talk a little bit more about the clodra script part because like I said I wrote I'm probably a pretty bad clodra script developer yeah I get by but frankly I can't say I like it much but it's better than clodra script but it's not hard to be better than clodra script so yeah so basically 90% of my time was spent on writing the server code so there that's where I put my focus and my I mean if I needed to do more clodra script development sure I'll probably look into more what you can do but that kind of executing a function like this like you said I don't really never had really the need to do it I just start the raffle and just type the command from there and because you can do that stuff in slime and I rarely do it there either so usually what I do and I want to experiment that I want to develop a new function I very often start from the innermost part for example let's say I want to create a function that calls a rest API returns from data they can return some representation of that data so what I typically do is I simply start by typing drachma ht so drachma is the htd library htd request google.com for example okay there is the data and then I start to maybe okay we assign that to a variable I want to do something with that variable et cetera et cetera and then I continue like this and I start to build up something that that's what I want when I have that I paste it into a file put the define around it and finish it up that way so in this case for example I would have this and let's say this is pretty much what I wanted okay I take this I copy that and let's go into this and then so I would probably end up doing something like this something URL paste it there and then I realize okay this one should be the URL I compile that there and then in here and I do something I want to attack there so that's sort of the way I would be developing a new function that does something so I test it out through the repo and then I just into the file compile it to the .c. it's in there now it's available to be used by everything the next question is let's say you are developing a variable something goes wrong so how do you go about doing that that sounds about you like even in unix for your unix for example you'll be writing something normally if there's one weakness in it depends on what you're using if you're using sbcl for example sbcl's tracing functionality is somewhat limited I don't really use it much so let's just construct an error so first by default the web server does not stop when there's an error it just lobs the error because you don't want to just break into the debugger so we have to set the variable catcher as p to nil and this will disable the catching and logging functionality so I get a proper error then let's go to the sorry let's go to the so this is the file that contains the definition of the handler for the channel so when it shows the channel let us go instead before showing the stream let's print 1 over 0 this should give me a divide by 0 on sequence c we compile that I reload this page and here's what we get at the division by 0 so this breaks me into the debugger and this is c and as you can see we get divide by 0 it's very easy question then is where did it happen well I can I can go to the line and I press v that will bring me to the source line now in this case it only brought me to the first line of the function why is that? well it's because the function is optimized so there's no debug information so we can the web browser keeps trying to reload the page it's a chrome thing I hate it so much so you can press ctrl c or I could have changed my default compile declaration to something because I have this global variable that sets what optimization level to use and I could all set that one and we compile all the files but with ctrl c I can compile a file but with full debug for a given function only and in this particular case that's enough normally when you develop you would just simply compile everything with maximum debugging so you never have to worry about that so let's just go back to the page and wait for the error and ok and now it jumps jumps so as you can see it highlights a specific part just the part of the expression where the error occurred in this particular case I got a compile error as well because the urban compilation is good for that but what the debugger also gives me is the entire stack trace here and if they are green that means that they are I have the source code available for it and the source code and the source code is reasonably it's not optimized or not fully optimized essentially it means I can go to it so I can jump this line I can also press return and I can see for example these are the local variables I can also see the parameters that were passed so the call with login handler this function takes an argument called bodyfm and we can see we can see that bodyfm is passed because it's called with a function and of course I can further inspect that function I can see because it's closure I can even see what values is closed over and in fact you can actually change that if I remember no wait can you you might but I think you can and you can of course go in and look at the actual function and go this deep if you want to which is kind of neat coming from just the stack trace from a running environment remember when you are remotely connected even to a production environment you can do this so I've done that when the application was running and I had to fix a small bug I fixed it in the repository and then I realized we don't want to do a redeploy of the application because that's annoying and that causes people to lose their session and then it reconnects half a minute later and that's annoying so I just went in connected created the function and it took seconds and yeah so I like that yeah so let's see and now the browser is ready to keep the loading again in the future now and next week you and right any other questions? that's the thing I've been doing open source development for a very very long time but one thing I realized was that working with third-party libraries in Lisp is so much nicer than any other language and one of the reasons for that is let's take a look for example just as we were I just called here drachma htp request htp request is the drachma library is the main library everybody uses for htp it's really good it takes a million parameters because htp is complete but it doesn't matter because all the time I can always and this is any library I can always try to make a dot and I will jump to the big function where is it where does it start this is function so I can always jump into the function so I can see okay what does this do well it does stuff let's see if you find something interesting I don't know what does so flexestreams is a third-party library that does it allows you to create streams that wrap some other streams with different encodings things like that same thing here flexestream element type I just press that function and I realize that okay it has a generic function with one implement with model method so let's jump to the method and this one is as we can see part of the flexestreams library so now I jump into a different one if I want to make a change to this third-party library I modify the code I press ctrl c it's right there it's modified and ready to go and I have contributed to so many external libraries where I might have contributed to a handful of Java ones maybe two or three in my entire life not because I can't but because it's such a hassle if you are working in a Java project and let's say for example that you want to make a small change to I don't know the RabbitMQ Java library you might have the source code but the source code is in the jar file that was downloaded just for reference if you want to change that you have to clone the project you have to build it you have to then integrate your version into your build process and just doing that might take half an hour just for you to be able to make a small modification to make a small change to this third-party library and then you want to push that change upstream it's asked in let's say you don't ever do that you just jump into the file because you have all the files make the modification press ctrl ctrl c if you want to push the change to find you have to clone but you already have the change so you take it this and you just submit to this so that's why if you go to my GitHub you will see a very long list of projects a lot of them are mine but a lot of them are third-party projects that I've just contributed stuff to because it's so easy and that I think is the absolute beauty of doing open source development lists because the community is so welcoming and it's so easy to become part of and the final thing is personally I find looking at third-party list codes much easier and you are looking trying to find out what the Java library is doing you have to navigate so many classes you have to understand the way the objects fit together how conceptually the infrastructure works this code tends to be much more straightforward you can fit so much code in a single function or sorry not so much code but you can fit so much logic in a single function without having to have slight exaggeration Java can be in many ways it just turns out a particular set of names I'm writing Java at work and I find myself writing the kind of code I don't want to write I find myself writing code that when I think about it and I say if I were a third-party looking at this code what would I think and I wouldn't be happy and I realize it's very hard to not get that feeling when you write Java and the thing is I actually like Java for what it is it's not bad it just I don't know it doesn't make it happen no it doesn't at least it's hard to screw up in it which is a good thing when you work on a large project with hundreds of developers which I am but still it's not it's not exciting yeah yeah and of course all of these benefits when it comes to the language itself and the benefits of language itself is of course so the fact that and that translates also to the when you work with third-party Emacs list libraries and that code is obviously much more fun to to work with them if Emacs had used Java as an extension language yeah I was calling this though compared to Emacs list well Emacs list takes a lot of ideas from Congolese a lot of knowledge and a lot of things you know about one will transfer over to the other I think the key difference is one of the key differences is that Emacs list does not have a package system you don't have modules or namespaces which can be incredibly frustrating for someone like me that is used to Congolese but in terms of the way the language behaves for example Emacs list used to be completely used dynamic binding all the time that has changed in the 23 24 34 they introduced lexical binding which is the recommended way to do it now and that is what Congolese has always been using and Emacs list's object system is very old Emacs something object that is more probably so that is more or less a direct translation of the Congolese publicist which I could do an entire session across this and what it can do and how awesome it is compared to other object systems so yeah it is very similar to the point where some people on the Emacs mailing list has proposed that perhaps the underlying list engine in Emacs should be Congolese instead making that change wouldn't be that hard Congolese has some interesting features that allows you to create your own you can manipulate the reader for example so that you can add new syntax so it is possible to within the Congolese standard you can let the language alter its own syntax to the point where it could actually read the Emacs list code without change you have to create a new evaluator but you can still read it so yeah so they're quite similar enough that an Emacs list programmer should not have any problems getting used to Congolese this is the problem with this you mentioned that you compile everything to the binary most common implementations do with a few exceptions so you collect the repo from the binary and you edit a file that's the binary change there is no binary file the binary file the executable is only generated when you choose to it changes it in memory it compiles it in memory each compiled file gets what is called the fastload file and that one contains the compiled content of the corresponding file it's only used when you load it in a runtime, it's not used when you create the binary file but what I can show you in terms of I think the question is if you're doing library in a running binary you can't write it to your back or can you? yeah if you just define a function like this the function X 1 plus X okay this creates a function that adds one to the argument this function only exists in the running image so this is something you have to keep in mind so if I were to create an editor file in my source code that calls the function foo that would work until I restart then the function would not be there anymore by the way when talking about native code I can show one thing that is kind of cool that perhaps some people have not seen if we take a look at the function foo here as we know it's a function that adds one to X so let's look at what kind of assembly that one generates and you will see that it's not very optimised this is the entire function but as you can see it makes a call to another function called generic plus why is that? well it's because the compiler does not know what kind of argument you pass in because you don't declare variables normally in this one so you could pass in a string and then you have to throw an exception you could for example pass in a very large number so it's a big number or you could perhaps pass in a complex or a floating number so generic plus is a function that can handle all of this it basically has a big case statement where it checks the type and then it's implemented internally as efficient as it can but if you know if you know that the type of X is a fixed number then let's just add optimise speed through safety and you know that it will never ever be called with anything but a fixed number it's a number that fits in a register then the function can be much more optimised so let's take a look at the top sorry let's take a look at the code now it's not fully optimised yet here what happens is that it does the addition somewhere here here it does the increment but what if the value is the maximum value of a fixed number f f f f f f f then the result has to be a big number which is why there is an if statement and it checks if it fits then it returns otherwise it calls the function alox.bignum but perhaps you know that the type is not just a fixed number it's actually an integer between 0 and 1000 then we know then the function should be able to optimise it really well and it should be as you can see it just becomes an added the reason it adds to is because the way values in common list are handled is that you can have a value in a register so it's 64 bit value but this value could be a pointer it could be an integer it could be a floating pointer it could be a pointer to some object or it could be one half of a complex number or it could be one quarter of a complex number built up from rationals now what they do is they let the lowest bits the least significant bits indicate the type or the lowest significant bits but if that bit is 0 that means it's a fixed number so it doesn't have to check for it because it knows it's a fixed number which means this bit in which case adding 2 means you add 1 but with the last bits being always 0 and then it just just moves it into rbp which is the return value and just returns so as you can see you can optimise code very very heavily just by adding the right type specifications I ported over a JavaScript implementation of a basically I was writing a game and I needed to do create a map so I took an existing implementation of a fractal generator what's it called the standard algorithm so anyway I ported it over from the JavaScript it took 10 seconds to generate the map but after I added some type declarations here and there it was down to one second or less than a second so you can have a huge difference it was an extreme case because it was an inner loop that was super badly optimised once I added the right type declaration the loop was just one instruction so typically you could have heavy computation heavy routines you can probably see between 10 and 20 times improvement just by adding the right type declarations but of course this function is now very dangerous if I do this I've corrupted the image now at some point later I will get a quarter of it for this guy this will never happen if you set safety to zero that can happen but as long as you keep safety at one or above you can do the correct type checking so this stuff will never happen but now I have to restart the entire thing because just to come back to the rest of the theorem question 24 when you did that puth fix in production you said it didn't work with the port so if that server process had been killed for whatever reason that would have revert this it would have rebelled the binary it would have revert to its own state so you still had to do such a good deployment I did re-compile the binary but I didn't do a full redeploy because the full redeploy packages up all the CSS files and that stuff and prepares it for compiles all the code into the production because the production generation is highly compressed into a single file but when you do development it's many files so a full redeploy does that but I knew that I didn't change any of that so I modified the file, compiled the new binary and then I did the hotfix in the running instance and then you just found a deployment later in the program? I knew that it was good now so next time we did the re-app the program department everything would be there but yeah, when you do that you have to be careful you have to know what you're doing so I don't recommend anyone going in and doing primary development of the application on Pro unless it's something where you're really okay or something so how does php back up? that sounds worse to me what? php back up? I read the article a fractal of that design that I'm sure everybody's read that's all my knowledge about php stems from that document have you read it? yes the good thing is you can deploy php, if you have an asterisk you can deploy it into your deployment that's the part of it it's great, fantastic what can it be simple? I try to kind of stay away from things I don't like as much as possible