Robert Virding: Lisp Flavoured Erlang

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

This is awesome

👍︎︎ 2 👤︎︎ u/costml 📅︎︎ Feb 09 2021 🗫︎ replies
Captions
so yeah i'm sorry can we uh stop for a second i actually screwed up i didn't hit the uh uh go live so let me just go through the introduction again yeah quickly okay so uh okay sorry folks i uh a little uh mess up here so uh oh should i stop sharing yeah okay i had to turn that sound off okay uh a little uh technical difficulty okay uh so uh we're opening the parentheses for 2021. welcome to list nyc i'm your host arthur smiles well i have your attention take a moment to hit the subscribe and notification button so you don't miss any of the videos that are coming this year okay i'd like to give uh now i'd like to uh like to introduce our speaker our speaker robert birding with joe armstrong and mike williams developed the language erlang at the erickson computer science lab it was designed for distributed computing and fault tolerance alan kaye noted that quote erlang is much closer to the original ideas i had about objects and how to use them which is the highest praise i've heard coming from the inventor of object oriented programming he also happened to be the star in the movie early erlang the movie historical gem you can find on youtube he is currently the principal language expert at earling solutions limited tonight he'll be talking about his language list flavored erlang and with that i welcome robert birding hello robert hello hello uh yeah the mic should be working great i don't i just want to say yeah um look at the movie the sequel instead it's basically saying the same thing but in a much funnier way and we didn't do that that was really funny so yes this is about lfe and now i'll click up here and we'll see what happens okay am i sharing no um yeah you're not sharing but you're uh we see you on on the screen so yeah so i will share my screen and then we will do that and now we click things on now i can see it so this is a little bit about it it's a real lisp it's in the allen ecosystem and i'll explain what what this means what i mean for here so one thing um i know this is not an outlying talk but to to very briefly try and explain why our lfe looks like it does right i i'm just going to go through some of the basic principles of ailing and i promise you we'll go very quickly if you've seen this start screaming and i'll just keep even faster so the the goal with doing lfe lfe is probably about 12 15 years old now since i've started playing around with it a long time a long time ago so the goal i had was i was it was going to be a proper lisp a real lisp right not just a quick hack um it was going to be running on the beam which is a virtual machine for airline and i wanted to be efficient implementation of this right it's something that's actually fast enough to be usable for it and it had to interact with all of all the libraries that you have in our otp and other languages running on top as well too so these were sort of the base requirements to make which i wanted when doing lfe so look a little bit about the background a little bit about the airling ecosystem i promise it's only a little bit and then we'll get in more into lfe and the reason for talking about the the back of the allen background of things is just to try and explain why lfe looks like it does okay that's that's the main goal here and as arthur was mentioning this was from the computer science lab and uh one of the problems we're looking at there is how to make uh programming of these type type switches much more efficient and easier but keeping the same characteristics and the basic characteristics you have are these type of systems um this comes from a thesis from jana dekker who was our boss in the lab these are some of the points here there was a lot of concurrency going on you might you might lose back in those days you might have a switch with a few hundred thousand connections tens of thousands of calls going on at the same time plus everything that everything that the um the switch is doing you have time inconstraints things have to happen at a certain time and not take too much time or things like this for it this for example uh forces the system to be non-blocking it is just not you just can't stop the whole system for 10-15 seconds do a garbage clip that's just not available is that just acceptable you need distribution to get real fault tolerance you need continuous operation which allows you to upgrade the system you must also be fault tolerant because you accept the fact things are going to go wrong um you need to be able to detect these handle these manage these and make the system keep going so you never crash and what we found later was this wasn't just telecoms so um some reflections here we were not out to implement a functional language alan is a simple functional language but that wasn't the goal to make it functional uh yes we implemented the actor model more or less but that wasn't our goal i didn't actually even know about the actor model until later when i read a report the papers saying that alan implemented and i went out to look for it we more or less did we were trying to solve the problem we had this problem we had our ideas for solving it we had a user group who gave us feedback on our ideas and said are these good ways is this a good solution for the problem or not we do it other ways etc etc so we've got a lot of feedback for it's very problem oriented it was very iterative process as well there's more reflections here this made the development very focused what do we want to do solve the problem what what should look like i don't care as long as it helps solve the problem and this this means we had a very clear set of criteria for what we're going to do was it useful or did it not did it or did not help to build the system a number of times we came up with um we thought were fantastic solutions to the problem but then we found out we just totally misunderstood the problem so just remove it and just get on with it and that's again getting back to that's what we're doing so where did we end up for it so yeah it's all around this and provides direct support for this stuff right so this gets us into the what we're talking about the ecosystem here which i was mentioning and that's this ecosystem diagram is an old one i think this is quite not i like prefer this one there's a set of languages running on top of the beam alan otp so for example you have allen of course alex here now is a very popular one the lfes there i have a prologue implementation as well and the lure implementation running on top if you want to use that and other things as well other languages don't work and by making these things follow the rules you can get very nice efficient things there they can work together very well which is what we want so where do we end up so the otp it's open telecoms platform this is just a set of design patterns for so the language the base language is pretty simple at a low level it's actually very soon making it simple was actually difficult and here we have a set of patterns that help you build things on top of this we have things we call generic behaviors that help you implement design patterns as well and again there's absolutely nothing about telecom in otp the name is purely politically correct inside a telecom company so this i know we've sometimes lost customers because they say we're not a telecom company so why should i use our line because it's a telephone telephone it isn't sorry any where's the question uh no i was just uh agreeing with you uh actually erlang the movie uh the sequel has a really great uh great name for uh otp oh yeah actually that actually i can just say now the quick comment people jumped on the meaning of p and didn't like that thought that was very derogatory and nasty and things like this for but it's a it's a scream that was done by a guy gareth smith um a number of other very funny films as well too i think people need to have a little sense of humor with it and not so go on what's the beam what is the beam it's a virtual machine to run alan so um what this means is that the beam the aolang language and the beam are very closely interact integrated the beam runs allen that's what it does right everything is in there for running our lane for it and this means all the things we find in the aolang language they're all there so the the lightweight the massive concurrency that's done in the beam for you the asynchronous communication which is the base the process isolation the error handling continuous evolution the soft real-timeness the fact that that the system does not block when it's garbage collecting all this is inside the inside the beam for example i don't i never have to worry about a process writing it say a process which looked as a tight loop blocking the system because the beam was not allowed to block the system will schedule out every once in a while non-blocking the preemptive scheduler it's transparent multi-core it will quite happily grab and record and get hold of and will load balance across them by just by default so thinking about writing applications for four or six cores or 20 cores it's just most of the time just something you never have to worry about it just does it there are a lot of powerful introspection tools uh we can look at maybe look at a tool called observer later if we have time and interest and lots of interfaces the outside world this is just more type system type things right and again i don't have to worry about this it's just there so having to think about about making sure my no process blocks the system that is just a concept i've had to worry about for 25 years right running for it and then we've got the language things um we have immutable we don't do mutable we don't do share and we don't do global that's it in the data i cannot mutate data i cannot share data it's not global and this again is built into the low-level machine this is just not an outlying feature this is just built into the machine i cannot get around that there's a predefined set of data types there are no user defined data types in the system that's it you can we fake it but there aren't any there there's support for patent matching to support the functional language and stuff like this there's also a handling of code modules and code which which are very different and yeah so the all these things are baked into into the system so you you if you want to make an efficient implement language efficiently on it that's it right that you have to follow these things yeah i i have a question about the predefined uh data types was that a um was that two to time constraints or is there uh a logic to that okay it was mainly a logic because one of the things one things the system allows you to do is to to dynamically reload code while the system is running which means that um if you had user-defined data types that that would mean maybe a user-defined data type disappears or changes while the system is running and what about all the other modules that are using this data type it just doesn't work right we could not we could not find a way to make that work yeah that makes sense so i also have like a kind of a question relating to that like are the is the code like shared across all nodes do all nodes have access to all the codes all the different um you know pieces of code that are running or uh distributed kind of um in an ad hoc manner it's it's an ad hoc manner in that sense right so even if you had predefined data types not every node is going to know about every data type so if it happens to run across some data it may not even know what type what that type is yeah yeah so now now you do because you have this fixed set of data types and everything uses that a weak fake user to find data types on top of them but at the low level it does that's that means all the systems can talk to each other you can actually you can actually talk to systems that are running quite old versions as well three or four three or four generation older versions they'll still interact with each other there's a lot put into this and that also means that if i'm running multiple nodes there's no requirements they're running the same system or the same software or if i've got a module foo on all of them they don't have to be the same food they can be different foods it's all local to each one it makes the dynamic it makes the distribution think it's pretty close to if i'm running lots of different machines together i mean some of them might be running windows somewhere might be running mac some but might be running ubuntu or whatever with different version everything they can still talk to each other it's the same thing here but yeah and um xkcd this is this is it of course right that's that's i know he's he he says something so very well yes okay so that's a bit about what and these are the properties of the underlying system which i cannot do anything about if you want to run it efficiently so you can run other things on top i've i've written um an implementation of lua in our language implements which implements lua 5.3 on top and lua has all the things that beam does not do it has shared global mutable data which we don't do but that means i put a layer on top which implements that so that becomes less efficient that by the way is online if anyone's interested that is interesting so yeah the wrong place the wrong place what but yeah so what else what it isn't right it's not an implementation scheme it's not an implementation of common lisp and it's not an implementation of closure or any other lisp for that matter i know of because the properties have been made this language is different difficult to implement the efficiency but what is it then right it's a proper lisp well with all the most of the typical lisp features you want in there you're used to but based on within these limitations it runs on the standalone vm so there's no need you don't have to have a special version of vm with hacks in it or anything like this for it and it exists with everything else running there they can interact with other languages running on top of it okay so now i want to start describing lfe that's just the background to try to describe why it looks like it does so look a bit about data types modules functions this one versus list two i don't know if does that war still exist um um i don't know really i i you know yeah like i guess kind of i i started with uh list two and uh common list but then i i kind of got annoyed with list two and i moved i think that we no longer fight wars in the list community there are too few of us we disagree that we don't well i'm i'm used to i'm used to lisp twos so we'll as well show you lfe is a lisp too there's actually i might give you a good reason for it well whether you think and also uh could you press the uh the video icon because i like to also see you while you're talking okay uh what do i press um yeah there you go okay great okay now we're back and now we'll go back on to look at this thing sorry i didn't see things right okay so that's that's we'll look at so data types these are the basic data types that exist inside um inside the allen inside the allen system at all we have numbers of course integers and floats we've got atoms uh they're similar to lisp symbols we have lists we have tuples which are vectors we have maps basically hash maps we have binary data which are really cool which i i'm a bit shamed i'm a bit um depressing that other languages haven't implemented it uh we're a lot of opaque types as well for that reference things we have well if you create a process and process has something called the peer-to-process identifier which is a data type a few other things like this and that's it right so if i want to make it if i want to make a structure i will use tuples i'll use maps tuples and lists to build structures and i can like we for example ailing has something called records which are built on top of tuples so they're implemented with tuples but they're not within it with a syntax for it there's a syntax for this another fee as well um lx here they have something they call structs which are built on top of max would do similar things but if you just don't there's no other way around this right um so atoms and symbols so an atom here only has it it only has it only has a name that's all it has it's not like uh lisp symbols which can have function definitions or values or things like that and our atom doesn't do that it has a name and that's it you can ask it its name and you create out whether you can ask and you get this name back and there's only one name space for all atoms there are there's no there are no name spaces hierarchical namespaces or anything like this which means we can we don't have the equivalence of common list packages or name spaces we just can't do that if i create an atom if i create the atom foo that's the same atom fuel and all on the whole node and it's just one food you can munch names if you wanted to you could you could do something like say if i want foo in the package bar i could i could make the atom food cola on bar to do that but that you don't really want to do that because it just it just ruins things in the long run it looks like a nice hack but it doesn't do that so we just don't do that we don't have a boolean data type we just use the atoms true or false for booleans that's the work structure um binaries are nice i just i i think i i didn't do binaries brother but they're they're a very nice feature so binaries are just a packet binary data either either either bytes or bits as well too so i can make bits i can make a binary which is 13 bits long or things like this for now i can put put together by doing so this binary well the binary one two three that's just three bytes containing one two three the second one down here has got a field t which is 16 bit it's a 16 bit integer and then and the bytes are stored in little engine then i've got two fields of four bits here was 32-bit float and i've got b which just happens to be b string whatever that happens to be i can use these to put together anything right which means like um interfacing protocol sending binary data becomes very simple yeah it's just so fantastic binary records yeah it is really good this bind this is a binary for an ip version four packet header this completely describes it so it's got the version four bits it's got the length and four bit the header length it's got the service type total length id size three flat three bit flags which i've never really understood but they are they always seem to be zero fragment offsets time to lives everything here we've got the source side p and the destination rp they're just 32 bit numbers and all the rest is just as just big pack of bytes and this binary i can use to either to make it um to make a packet or if i get if i get a packet in i can use this as a pattern to just pull it apart in one go so the system does all the shifting and ending and ordering and such an insight when i just don't have to worry about that why this doesn't exist if it does exist i've missed it but what it doesn't exist in other languages i don't know it's just so nice so uh basically what you're telling us is that if er if we had erlang in the entire network stack of the internet we can go from ipv4 to ipv6 in like a minute yeah it's just not a package yeah it's just i mean writing protocols you just go in and look at wikipedia for the protocol and write the binary binding description of it you're done right well not all not quite that simple but that basic idea so so of course we have support for binaries in in our language this is the other fee this is the lfe syntax for it this is the lfe syntax from ip version 4 modules and functions okay they are very basic so don't think uh packages or things like this don't think classes a module is a collection of functions that's basically it right so all i can put in a module is a function the set of functions and it's a flat module name space as well there's no hierarchical module namespace which means you have to have to be work a bit when you're working giving modules names and they're they're the complete unit of code handling so if i'm working with code i'm working with modules so i cannot take a module for example and add a function to it or remove a function to it it means i have to rebuild the whole module and i'm doing that that's just a limitation of the system and this was done for for making it even easier to do dynamic code handling while the system is running so i can i can load modules while the system is running i can delete modules i can reload modules everything like this and this also means that functions only exist in modules real functions only exist in modules and the code in modules is compiled there's no implementation there's no sort of implementation of having things uh being interpreted or not or something like this so all you've got in modules are compiled code um in the repo i i implement functions locally to the repo by implementing an interpreter and another interesting feature here is um there are no interdependencies between modules modules are completely self-contained i can remove one i can put one in blue um why i mentioned the last one here in the basic outliner system you haven't had one modular per file and the module name has to be the same as the file name i've extended that trailer for easy i can have multiple modules in one file i don't know if that's a good idea or not but yeah that's there i can show you some uses of it later for the examples later um so here's a module this is a module we define the module to arith and we're exporting three functions out of two arguments out of three arguments and subject to arguments so we have to just say and here i'm defining add of two arguments which is just a plus a b and added three arguments with abc's just plus a b c and sub a means that minus a big one so it resembles common lisp we can do more things with patent matching but that's that's it um actually def module defund and define all macros anyway so they expand to things what do you mean by no interdependency i mean clearly a module may need things from another module that's a dependency yeah but but there's no dependency it's in the module itself if i need something from another module i will call a function in the other module so if i'm in the module foo then i and i need to run a function in module bar i will call that function the module bar yeah sure so there's no import like give export there but there's no import there's no import well there is an import but it doesn't it's just a name hack there's no export is just saying these are the functions that you can see from the outside that's all export does there's no importance so if i if i happen to have a function here where i don't have one if i didn't export add three for example then you couldn't see it from the outside and then you couldn't call it from the outside here right so are you stuck with the inside names when you call from the outside yep so that means well i don't know yeah that you're stuck with that and you typically when you're calling a function from the outside you have to give the module name and the function okay i mean you probably need qualified names sorry about fully qualified names yeah yeah you need that you can you can do syntactic hacks where i don't have to write that so in a module i can say okay if i call them if i call the module baz i'm actually with that i'm actually meaning to call the module basin from the we'll call the function batters from the module foo instead that's just a syntactic hack um yeah one thing we cannot do again this is a low level limitation i cannot have functions without variable number of arguments each function has a fixed number of arguments so we see here add has two this ad here has two arguments this ad here has three arguments and they're different functions and yet plus plus plus is because plus is a hacking that plus is actually a macro and seminar i see that expands to and these are different functions so if i call add with two arguments i'll get this one if i collide with three arguments i'll get that one if i collect the four arguments i'll be in error because there is no out of four oculus this is again you can't get you can you can hack your way around this but then as things start getting ugly and the interface gets difficult and in the experts for ad too does that does that basically do currying to create a function that where the first arguments are ready to oh this says we're exporting the function add with two arguments oh okay it tells the number of arguments yeah that's the number of arguments for i see i should put up another function here in terms of it yes um and modules are attributes that's just a bit of a module a bit of module metadata we've got function definitions we have macro definitions as well and i can actually do compile time function definitions but um i can't really export macros in that sense right you can't there isn't you can export macros but it's a bit of a hack but well it does it looks looks good and it works but um the only thing i can export from a module is a function that's it this is this is just what we have that's it and again if i want to do something different like implementing packages or something like this i'd have to put a layer on top of it and that would definitely bring down the efficiency there's just no way around it um yeah this one versus list two um that's well basically how you evaluate symbols in the function position in the argument position in this in list one you take both you take both from the function foo here and then from the argument by you take the value in list two from the function you take the function function definition function binding and in the argument you take the value behind it says two okay this is scheme this is common list mac lisp and well list machines as well so why why do one here well i think i thought it made it more consistent so if if we're running in a list one world here i could define i can define through define full of two arguments and fill three arguments but inside bar if i wanted to make a local local variable function called baz it could only be one of them because i could not define base with two arguments of base because then you run into the problem just to say just the value of the symbol without i would have thought that was inconsistent so what you do now is you have an f let again a lot of the syntax is taken from common list so here i can define two functions based local functions bad as one with one argument one with two arguments and i can call them down here i just felt this match better what i can do with global functions so that that's why this you can do this as well too you can use this and bind this to a value so i get the variable local variable bars has the value which is a function i can call that but i can also use these functions like this so right it's actually list two plus or say because you can have the same name with lots of different arguments um but again this is this is not any property of the atom itself this is a property i put of the atom as a function name okay okay so we have pattern matching and we use pattern matching everywhere and we've got direct support i don't know is is is everyone programmed language with patterns matching it i think a lot i think a lot of uh the uh modern programming languages yeah i do haskell has it uh rust has it now um yeah yeah but certainly there's no problem with having common list and scheme libraries that do it yeah i don't think if there is escape the ability to write your own syntax yeah yeah well i give you a summer build here with macros but still but again this but this is built into the machine so we use everywhere for function clauses we'll see what that is i can use let case and receive in macros like i can um i can use mac i can use pattern matching in macros as well when they're selecting things for macros such as it makes it easy to write a macro with different number of arguments just use patterns for it and this is how you bind variables so if i bind local variables i have a pattern here which might be a variable and an expression so you evaluate the expression then when you match against the pattern and by check it's the same thing in bind variables and what have you run then use them i've got a case for doing that that just evaluates that expression then it then selects steps down and selects the first of these we call clauses here which has a matching pattern i'll receive that's for receiving messages again we're using patterns to select which matches you want to receive we use patterns everywhere so i can define a function with multiple patterns so multiple clauses and i can which clause i select depends on on the patterns um the reason i'm using the square brackets here in the argument list is just because it's easier to read so square brackets and parentheses uh are equivalent i just find that easier to read so i can use patent matching to select i have a cons here as well too which does test but it also has a pattern matching test but which one did that as well it's just too good not to have it everywhere yeah i like it yeah once you once you're there you sort of wonder how could i not have it yeah great yeah i kind of created my own little pattern matching uh macro for myself so yeah if you don't have it you just want to invent that so here is just some interest just examples of defining functions using pattern matching so the function atom acoman here is a function of two arguments right that's why we've got two arguments in the list here and if the first argument is 0 we'll choose that clause and then we'll the second the second argument will bound to the variable n or just return n plus 1. now if this first argument is not 0 but the second argument is 0 we'll choose that clause and then we'll call that n will be bound to value first argument which should we call that our command minus m1 and otherwise you have the general case like this again i mean that's just it so we have multiple clauses here and here's another example we could define a member like this more traditional using cond so if if x is a member of ease if ease is empty then of course it's false if x equals the car of it then of course it's true otherwise we call member recursively and step down but we can also do this using patterns down here so here we say okay if if if the second argument is a cons and x equals e we return true if it's if it's not we call ourselves recursively on there on the rest of the list if we hit the end the empty list then is false does this mean that the beam vm is properly tail recursive yes i'm good if your function is written like that yeah this is just something we had i mean that how did we write well i've got some code examples later but um how do we write state machines well you have a function first state you call the other state when you when you when you're changing call the other function when you're changing states you just have to have it it's just better that's that's schemer's favorite example for why tail calling is not an optimization it's a thing you need to be able to rely on yeah that's one thing that really surprised me when i saw closure um they didn't have yeah well they're on the jvm yeah exactly so they i their goal with uh closure in particular was to make it efficient for the jvm which means since the jvm didn't have it they didn't uh support it but but but yes but no there's an implementation of airline for the jvm caller jang okay and that implements tel tell calls not just recursion but telco optimizations because the language needs it so it can do it it does it quite efficiently as well too but how does it do that while retaining the correct security context yeah it retains everything it's it's it you can take your allen system and move it across that and run it there it'll just work right right you can move erlang there but can you call back into java and retain your security contacts correctly that i don't know you i know you can call into java yes there's a lot of things yeah so the reason why they didn't do that is because they couldn't figure out how to do like one of my professors dan wallock figured out how to do that in the jvm um job but son never never used his um okay proposal but there it's it's it can't implement security um and tail calls the way that they have it right now yeah that that i'd i don't know i know the guy who did it uh he was dane when he's a dane he he worked this out because his goal was to implement alan on the jbm right so yeah um so uh before we continue i want to just uh read some comments uh concerning this in particular first of all uh we got a couple of comments about other languages that have uh pattern matching scala and on the chat uh it was javascript also have it also uh duncan mcgregor has a comment saying uh pattern matching and function heads is phenomenal and he also mentioned that you can you can use khan's literals in pattern matching too you just have to quote the things yeah yeah yeah because yes so yes i know um i have a very good link to a a a short little movie duncan's made i'll give it later on the chat um he's giving a presentation that he's used lfe to implement a music generation system so yes which is quite funny and um it's only a short little movie but the music is wonderful so yeah of course we have macros we could not have a lisp without macros right uh you know what you can but what you couldn't do that um they're unhygienic but when you create variables that they're you're creating them with alexa they're scoped so it's not as bad as you would think um there is no gen sim and that is also that's the thing you run into with the underlying virtual machine that when you when you create an atom it goes in it's interned in the atom table and there it stays it never goes away so if you put build too many atoms you'll fill the atom table that crashes the system takes about half a second to do it i can show you some codes later that does it but yeah so that's why it's only it's unsafe on long lead systems so i just don't do it um their compile time at the moment but except when you're running the repel there you can define local macros in there as well um i never allow you to write macros that shadows the core forms so i cannot write a macro called cons well i can write one but it'll just never be used right this again is just to protect yourself um getting into infinite loops and things like this for you it means the core forms there's a big there's a big predefined set of chord forms there they just always do what they expect them to um i can call i can define macros in modules and i can export macros from modules so i can define a macro inside a model and i can support that and then i can call macros and other other modules priority module colon macro this is the same syntax for calling functions and other modules as well but if that's a macro and then then the macro expander when i'm expanding macros we'll check if this is a macro and then we'll just do the expansion while i'm doing that now the macros are pretty straightforward as a macro interface i can define a macro here we have the back quote we have the back quote macro of course so i can define something like this which just expands to something with a plus a plus with values of a and b in there i can do an average like this this expands so we get we plus that we take all these and make an expansion of all these says all the arguments and just divide it with the value of the length and think about this i can do this stuff and stuff like this so we got all the macros given that you have these um fixed and immutable modules unless you recompile them what do you do about the problem of um a mac a non-back quote macro that actually constructs stuff using using um using functions that come from somewhere else that may not even have been seen yet tough okay yeah no that that's one that's one thing um the basic system i mean you you load in you load in modules and um okay there is a bit of there's quite a lot well one very very nice support for you that it will automatically load modules for you so if i call if i call a module if i call the module zip and there is no module sip then the code server in the system will go out and try and find the modules and load it for you and then then right but does this happen at compile time no this happens it runs on is this happening the compiler is written in owling itself so it's just running out on code so that means you you can have back quote macros like this but you can't have macros that execute arbitrary list code yeah yeah they can you can do that but because at compile time the compiler is just it's just an app it's just align right it's written in align it's just just an allen function like any other set of outline modules like any other modules and if you have a macro that calls some function in another module then then say well i'm evaluating this does the module exist no then i'll try and load it for you the code server does that at a low level for you right okay so inside the only thing you cannot guarantee is that i have the same module compiling as when i'm running it later yeah okay yeah but it does this the code loading works just by by default just automatically and this is just a little bit of a code example here this is from the old telecoms um this code if we go back 25 years actually worked 30 years actually worked because we had a we had a little implementation and we had done our initial telephone operating system we could talk to another exchange for it but so here we're using here we have two processors basically running with what we're making a call and the phone's ringing so we've got the a side which made the call on the b side we've got we've got separate processors for these and they're talking with each other so this is the address the a side knows the the appeared and the b address so what happens here is that if someone re lifts the receiver it's going to get an on hook message here the atom on hook and then it sends a sorry if someone puts the person calling the receiver puts the receiver down is getting getting an on hook message then it sends cleared across the other side it stops the tone and then goes the idle state by calling the idle function and here we see an example of the tail call optimization so that and on the b side here it's going to get it cleared which is going to stop in the ring and it will go driving if the b side lifts it gets off hook here it stops the ringing it sends answered across the a side then goes to the speech state here by calling the speech function and here we get an answer we stop the tone we tell it to tell the connected the operator to tell us just wish to connect the a and b side together we go to speeches now here we have a problem to show why we why we can't block so that all the all the communications is asynchronous while we can't block here because while we're sitting here someone might try and call us which means we'll get a seized message coming in this is a topple series here with appeared and if we have to handle that immediately and send back rejected and then we then we just loop and stay in the ringing site back to that on both sides and what we do in this very simple case if we get any other any other message we just ignore it that's what the underscored matches didn't just ignore it just keep going so this is a bit of example for me and yeah i don't have the rest of the system but this this is sort of real code in the sense it actually worked and this is just some examples of again we're using pattern matching for the messages and things like this for doing it i guess we're saying by the way sends a message sends a message to this processor sends the message out and rejected yeah sorry i guess receive blocks until some message comes in yeah i can give a timeout as well but um yeah so here's another bit of real code this is a virus this is a virus code that actually works right um so it's in the module virus it only exports two functions start there's no zero arguments it starts with one argument and i started by calling star now what that is going to what that does what this does is it goes out and finds that well this module here is a macro which expands the module name in this case just there's a predefined you get that macro for free inside when you do the diff module so this goes and finds the code for the beam for the beam for the beam module and then it calls start which spawns a process which calls the spawn process here and checks if if we already have the beam running then we don't do anything with that if if we can't find it we spawn a process running this this little fund here let's create a new process to do this running the virus here with the beam that regis is not itself in the name here so we can check if we only get one virus per node we ask the net kernel which handles it amongst other things connections between the nodes but if another node connects up to it send me a message telling me that this is just telling tell them tell me when modes come and go and now i write out i'm infested and i go to the loop and the loop is very simple when it gets a node up which i'm getting from the from the um net kernel i infest that and i just say that's joined and i sit in the loop here i'm just sitting in a loop every time i get a note up i invest that note and the infest function that's called uh with the node here and this uh what i can say here this is equal to um uh the node here is equal like i can use this a quick with the beam here to set pull the pull right what what i get in here from the whoops from the beam to a tuple with the mod the bin and the file so this is the module name this is the actual binary this is file where it was found now i do an rpc call to the other node and i load that code in so now i've loaded the virus code into the other node through the rpc which is just a standard mechanism that's implemented in the libraries and then i started so now i've invested the other node then this this yeah this is how simple this is to write a virus which running which runs through um a distributed alloy and yeah and and so it continually makes processes until uh or does it just create one virus per machine or is it this yeah it just creates one part okay let's start talking to each other i'll show you i'll show it later i've got it somewhere excellent and uh by the way duncan mcgregor uh made a comment i'm giggling never seen this before this is one thing we say if you're running distributed ally i can say this now i'm saying both as a joke and extremely seriously you must trust all the code that everything that is sent to you because here i'm saying i i've got contacting this other node and i'm telling it to load the virus code to it right so if someone can talk to me they can tell me to load code and then they can start that code and if if they can contact me i cannot stop that i can try and make it difficult for them to do it but if they're slightly smart they can get past all that bob calco mentioned don't play this part of the video to your security team yeah so make sure make sure your uh your code's behind the uh wall yeah i mean you should be uh yeah checking it anyways if you're getting anything outside like a sql injection yeah yeah so our goal was to make a language we could define fault tolerance systems not not safe systems and things like that so that's it so yeah that's what firewalls are for dmz that's not our problem again letting someone run code on your allen system or lfe system for that matter it's the same thing in this case it's like giving someone root privileges on your note on your machine right yeah you do that very trusted people so what i'm doing now is well i'm working with type notations um because the outline system has has type notations and some type checking tools working with that um i have a bit of a closure interface it's just a module that implements something closures like things work i didn't actually write it i've got flavors working on it this machine flavors i don't know how many people have seen flavors they're before close and um they're much they're much more fun if anyone's interested after us i've got a section on flavors as well too i definitely would be interested i don't think i've ever really uh seen it before yeah flavors um close is a limitation you're doing that flavors is much more versatile you can use it for doing for implementing class hierarchies and stuff like this but you can just mix things in it's like cooking right if i want a bit of this i'll put this in off i want some of that i'll put that in i'll add a bit more salt because i want more salt in it and stuff like that i'll just mix things together well plus allows multiple inheritance you can just mix in whatever you want yeah but i can do it that's just cool silas is extremely general but it's but flavors is is designed um from a single perspective it says okay we have one trick and we're going to make it do everything has every known trick yeah you just you just depending what components you put in you can make them behave like class hierarchies or not or put things together oh it's wonderful uh this machine structs um i'm this is something i've been looking at for a while but i'll i'll get back to doing that again where i have to implement it on top of something else right yeah so why well that's easy i like lisp um i like airline i like to implement languages on top of that so that's why implementing lfc natural solid thumbs up i said solid reasons thumbs up yeah yeah yeah yes of course of course so what i want to try and show you here is some examples um you're seeing the screen i'm sharing yes that's good i'll put that down for a time so yeah so so here we're running i've started off an lfe shell um so we're running up a little banner here and i can do things so well i can do plus one two for example this here um i can i can define a function i can define a local function in the shell a b which would be slightly different so we just do times that would be like this and this is this function is purely defined inside the shell it's just interpreted so now i can do um through 42 and find 43 and i'll get back and i can do recursive functions as well if i want to um so yeah i can i can set variables i have a few special the normal thing for setting variables is a let which which is purely um scopes and i don't want that here so there's a special form set here so i can set x to be um 42 now i can now i can do of uh 31 and x and this is just what you expect but it's it's a rapper inside i can do things and i can define recursive functions as well if i want to let's see let's see if i can try and define factorial if i get this right do factorial and we'll say okay we if we get if it gets the argument zero um we get it's going to return one and we're writing multiple clauses here if he gets the argument n uh we have a guard here when n is greater than zero okay and then we'll do that then we're going to call fact of um minus n1 like that now i've got prime factorial and that should work if i do factorial of zero i'll get back one if i do a factorial of um five i'll get back one well i got wrong now multiplications oh something's gone wrong somewhere let's see what you need to do uh yeah what it is is that you need to say uh that when n is greater than zero then it's n times fact n minus one ah yeah sorry thank you yes otherwise it's one as i guess it's i guess uh at the end it's one's all the way down right yeah if we'll just do that again we'll get this right and now it's um fact of uh time then like that that's right it would be actually n times factorial of and yes one right so it would be in other words if it's like two it'll be two times fact of one or just three years three times two yeah there you go now got factorial and now we'll just check it still works we do factoring 520 and factorial 5000. that's because the allen i i have one question when you're running the repo uh is that just a single process on the uh beam yeah so we can have multiple reports and have them communicate with each other there's three processes okay one there's a there's a repeal manager process and there's a repo evaluator which does evaluations and there's one for doing the read which means i can read things while i'm while the rep was working and stuff like this as well too okay interesting and i can see this because there's a built-in function called self which returns the pit of me right that's me here there's a built-in function i was the shell function i here which just lists everything with all the processes we're running at the moment so these are all the processes we're running at the moment and here the ones we saw this is um so i can i can process lots of things so i can do i can define macros in here as well too is there is there a meme myself and i joke hidden in there somewhere not really yeah so the show the show keeps track of everything it's got a state a there's an evaluator which evaluates all these things and keeps track of it so all these are kept in an internal environment variable which i can look at actually it's accessible and if we look at this here we see an awful lot of stuff here for some reason i cannot scroll this screen anymore and i don't know why um let's see won't scroll i don't know exactly why that's not scrolling i'll just stop this and try to start again we'll see if that's the reason yeah there's something there and then this uh this ripple is not exposed to the is not exposed to compiled code as eval or anything like this um you can you can call it the the the the the evaluator is done in a module what did i create one now let's see you know i get that yeah while you're doing that i just want to mention on duncan mcgregor's comment he's talking about this he says yeah it's really nice if the eval process crashes it doesn't bring down the repo the server process just restarts it yeah that's pretty cool what is happening here now let's see right now i'm going to try and start another repel here um we're here yeah now we've got one let's see if this works this works better now oh well doing fun but we can look at the environment here this is the environment here now i can step through it and here i can see all the local variables again this is just taken from the the local variables you can keep saves the last values the last ones the last variables this i just took from from commonlist but here all the functions of here all the functions and macros defined in in the um in the shell so we see here here the i was a function of no arguments which just returns just calls out if you show i here for uh to do one here which looks at information lots of processes and i can actually cross create repeat as well too or the um what's the the hash m that that's that's the syntax for a map oh okay okay right so if we go up here and see we look at this map here there's there's one key i'm changing the syntax in version two will be they'll be they'll have parentheses around the pairs to make it easier to understand what's going on there because that becomes pretty comes very quickly quite unintelligible yeah i mean right now basically it's a p-list instead of an a-list yeah so now that there'll be at least so you said this this be a list around say the dock bit here and it's that end like that more right parentheses but i at least pair them together a bit better right but yeah so these are the functions for it and if i if i if i just do if i'll just go back and do the final foo here and we'll do um times a b here and now i look at dollar end here and we'll see up here here there's a food function i've added so everything's in here which means i can redefine this stuff if i want to but then and then if you look at some sort of module it'll show up in there as well no these aren't kept in a module because then i'd have to be recompiling the module every time i added a function to it and then you run into problems with the code handling okay so there's like there's stuff that's in modules and stuff that's outside modules it's like two yeah and the things outside the modules they're completely local to the repo yeah the evaluator function the evaluator module there's a module call we can look at that it's called um lfeval and here we've got these exported functions here and we can evaluate expressions we can evaluate forms and things like this for as much and then here we just pass in an environment so i can call um what if the uh eval hold on expression and we and i can evaluate the expression times 43 44. like that and i get back that so i'm just passing in the literal it's evaluated if i was to pass in an environment i'd have functions defined in the environment and yeah so again well this is just what it's compared with we see all these flags here saying because there's a lot seeing this the system is quite old things have evolved so we have flags saying well wait if it has these things or it doesn't have these things like that that's what all this stuff is for but yeah and then we can look at other things i mean um let's see which ones i've got here we've weakened ls there's another built in ls shell command here i can look at things what have i got here um yeah we can run something we can run we can run something in the background here so we look at the picker module clicker lfe and we make this big i'm an imax user okay so we have the module clicker and it exports one function start and exports the function tick group and when i call start so if we call ticker we see here that thicker is already compiled um the system does not automatically compile things for you so if the ticket module wasn't compiled you wouldn't find it but we'll start off with so every five every five seconds that's what mean seconds we'll start that and it's going to write something up counting here it's just running in the background and every time we'll just write out to write out the pit of the ticker start one thing so i can start another one and now they've got two pick up processors and we'll see one is not one is 96 and one is 98 and they're both running here they're just running in the background writing things out and um yeah so uh let's see if i do now set of p1 to dollar dollar that's that's 96 and i said t2 to dollar dollar and that's 98 so now i've got variables referencing these ones and if i what we look here if i send it any message it'll just terminate the process and now i can send a message to um p1 i'll just send hello and we'll see that stops and now we'll know what i need to do i can stop that one as well you stopping why aren't they stopping it should stop us there's a simple way of doing that i can stop them very simply simply yes i'll just load in detector again i'll load in ticker again and now now it's gone now they do uh this is just a problem with the code loading um that's also one thing i want to show that's why you have to be very careful if you if you're if you're recompiling mod and reloading modules because the system allows you to have only two versions of a module the old version if you try and load in the third version it will kill off the old delete the oldest version and kill any process running it which is what i was doing here loading it twice and killing all the tickets right this and write packages that more say common lispy i'd have to i'd have to put a layer on top managing that i think it's pretty reasonable for it to to kill to only keep like two versions right like it's like sort of the blue green deployment model model if you need more than that you're probably doing something pretty crazy and you should probably define your semantics clearly rather than rely on what somebody else guesses your semantics might be yeah yeah having having two versions allows you to control upgrades because i can have a process running i wrote in a new version approach which runs the old version then i tell the process to migrate to the new one and it can upgrade and do things adjust data structures and things like that that need to be done i've got another one here for something slightly more complex so i will implement a separate process which is a counter because i don't have shared data so if i want to share data i have to put an account i have to put in a process right so here we can run counter colon start and that just starts up a process which is a counter process whoops actually done um set c to c is equal to the count i can run multiple counters if i want to so now i can i can for example i can call counter column add and add and i'll send it to um also need to see and i'll i add 15 so for example and that just returns just returns a message he just sends a message when i get back if i want to look at the counter i can now do counter colon get and uh this enough to see here and i get back 15. now add again 150 and do a get by now um 365. so what i've started up here is i've started a process that sits in a loop like this and when it gets an ad topic so when i send out i send an ad tuple to it when i get the and the number and that just cause self recursively bumps accounting and sub decrements the counter and get just sends a reply back and so it's a synchronous call here synchronous in the sense we send a message in a simple way for a reply message and let's return it so another little process here running and this this process um i can start multiple counters okay is that is that triple add number and this uh hash friend sub number there's just two different ways to say the same thing those are two different symbols yeah so here here i'm writing it out as a two ball sub and here i'm using the back quote um here i'm using the back quote with the hand i guess the tuple one is basically you're giving it the type right you're you're doing it based on type dispatch whereas the other one is like more pattern that actually expands if we do this when it works so if we go back here i can do macro expand so i do have the macro expand call here and then i can expand this uh which was sub we can do sub here common number that expands a couple sub number okay so the back quote the macro is implemented as a macro macros that's all it's doing now i can start separate one if i want to of course we'll go here we'll do counter we'll set um c1 to that so but now the two counts and if i do if i do um get c1 it's zero because there's nothing in there and again if i do get at c it's still 165 so then i'm just running two separate counter processing i can start up as many as i want to as many as i wish for now i can stop them as well and do things like this and what i did what the final thing i just want to show here well i can show as much as you want but um if we go here and look at this one if we go to another module here so here i'm running raw basically raw lfe on top of airline here but i just want to show i can actually use the otp system in here so now i'm going to run this as what's called a gen server and a gen server um that's an otp that's an otp behavior for doing client servers it implements basically the top group that gives you a lot of functionality for that to do so i do a gen service start here we'll run one of these right we'll run one of these so if i'll compile it i'll just check i've compiled it i work so now i can do counter gs here and i'll start and i'll start this so now i'm running i'm running one here now this is running agency and from one point of view it's done doing exactly the same so now i can do counter counter gs and i can do add uh i can get that playing wrong you can see i've encountered it didn't do it why why wasn't it doing it think c1 is the previous very simple there's a bug in the code yeah do we get it just when you get that should do it why isn't doing it i don't know there's a bug in the code somewhere but um i could do the ad but i couldn't do that oh reply counter counter yeah that should work we'll try this again sorry we'll just try once again and see what's going on here ah yeah okay so we wanted c1 to be counted gs start so i was running the wrong one that's why i was right that's why i wasn't working um yeah so now i can do it and now i can do counter get c1 and it returns exception function called 2-4 blah blah blah what's going wrong there ah add yes 500. i think yeah i think you have to get um the second element of that tuple because the paid is second now that that's yeah um dr mcgregor um mentioned that uh okay i guess in this example you don't have to uh also when you're using gen server you can register a process with a name and just call the module itself for the single it's it's uh you see how it's uh okay and pid i think you're you have to extract the pit from that that tuple the second element of the people yes i exported it yes are you where your mouse is right now that something's quite strange here the add function we just recompile it to make sure it's the last last attempt cg will do cg countercommand start we're up and running here and now we should be able to do a counter gs add cg to 500 and no function clause matching general cost uh yeah it's it's because it's because the pit is the second element of the result from counter gesture ah right sorry that was my fault okay now now i know what's happening here um the the account that you had started returning an okay tuple and i was used i was sending that couple as the address which means it didn't work now it works and now if i look at cg it works and now will work now i can um add things to it and i can add some more i can add another 500 and now i can do a get for example and get back to value so why would i want to bother doing this what i mean this is more my full code than my simple one is because i get a lot of my system features for example i can i can turn on tracing here of cg i can turn that on to true okay this is just built-in functionality i get automatically by the behavior and now when i do it yet well it's writing out it's working out it's getting information back it's getting a request from it sending value back to it i can add and do things like i can do sub for example here and i'm just getting all this information from built into the system which allows them to do these type of things so you have state this is features i get from the very fact that i'm using behaviors as well too for um i can also get error i can get error efficient error reporting and all these type of things and then that works together you've resurrected global variables any more questions anything i'd like you'd like me to show you is that usually what this kind of thing is used for like you can sort of have like a global variable somewhere that keeps the state and then that that's that's why you don't need uh global environment in the language and you'll see the account is yes yeah um so what would this take a short five minute break you know what would this target you know come back and talk about flavors but you have to tell me if you want to see it or not otherwise we'll just go on if you want i think there's a there's a real communication problem between us i don't know if you hear us but um uh yeah some people have some questions so um whoever wants to uh talk i think uh john you had a question yes yeah we'll go on i don't think he hears us at all okay um i think uh new yeah we're here um we're here but uh for some reason uh we're losing the uh then we'll go on okay yeah so if you if yes you had your i don't hear you okay can you hear can you see me i can't hear you i'm afraid okay uh oh great because you can't see us uh just restart the browser he doesn't know what you're telling him yeah i know i i yeah maybe in the message yeah or either that or just shut down the channel and start it again well i i think the channel is fine he just has to restart his browser he'll reconnect and then we'll be fine we don't have there's no way to tell him to do that well um out of bandwagon like email we need pigeons anybody anybody have any messenger pigeons he's talking in the comments okay now you can see i'm sending you privately i'm wait oh wait a minute we'll try that what do you call that when you say you not restart the browser but uh my brain's uh hurting um refresh you might actually sometimes need to actually uh restart the whole pro um browser sometimes our prime has helped us out device okay now now i can hear you guys again i don't know what happened but i just lost we got cut off i wasn't sure there was a delay or what was going on but anyways let's uh let's continue uh john cowan you had a question yeah um what would this talk look like if you were making it to an erlang audience how would you sell them on list um [Music] that would be very difficult okay because uh list doesn't always have a very good reputation outside of this community well let's say they're let's say they're open-minded i mean what would you what would you tell them the advantages are of this familiar syntax besides the macros well the list the syntax is very simple i mean you can describe the list syntax in under five minutes right because everything looks exactly the same right it's a list it's a list where the first thing says what then you got the arguments to it that could be defined or it could be a function called so the syntax is very simple um i i i would i would definitely talk about the macros i mean if you if you're comparing this to alex here one of the things alex here uh that they're selling that with is the mac it has a macro package for it it's all these parentheses everywhere right they wouldn't like that so i don't know i i honestly quite don't exactly know why how i would sell this for it for me it was easy this is this this was my first high-level language above seeing pascal right so one once you know that you compare everything to it right like show them some sort of thing you can do with lisp that you wouldn't be able to easily do in our life yeah yeah i think yeah i quite agree with zaikal here alan macros suck um look i i they suck they suck on purpose okay because i i'm the one who implemented them i didn't i didn't think we should have them and they told me we should have macros so i basically took c macros and made them even simpler it's like i don't want you to use them so i'm going to make people as possible yeah you're like if you want macros you got to use more parentheses no yeah i will give you i will give you the thing you deserve i think i think i think the problem is with selling this e-macros that is that um you have to show it can do something better than in another language i think that's the problem and something which other people will will uh see as being better okay i think that i think that's the problem for it it's it's all very well showing a very good application in it but then you have to tell them well like you can't they can't do anything like that in their own language in another language to which they reply and we have experience of this the list community why would you want to do that anyway that's another one right that's another one yes yeah that's another problem but um macros what macros thinking macros right type just type out everything you know in longhand well if we get back to original airline one of the reasons one reason we had we didn't put much of a macro package in is we explicitly wanted to be exp we explicitly wanted to be explicit so you should write exactly what you want exactly what you get right right one one problem with macros well i said they're a path to heaven but they're also a path to hell right because you can write applied technical yeah you can yeah yeah and it's just too easy to do it and yeah can you mix and match languages like elixir and lfe and lua so once again you have modules that are written in different languages on the beam platform yeah yeah yeah you could do that i mean you can i mean what else so what i mean what i was showing here i mean you can quite easily if we just go back to uh sharing my screen again um i also have one more comment myself i just talking about this subject uh i don't think lfp's uh feature is about bringing lists to erlang i think it's about bringing erlang to lisp yeah yeah i think that's the really big thing is that the erlang platform has a huge pedigree and uh you know um as a medium distributed environment that's all built in and then you can have your list programs utilize that so you don't have to rebuild it from scratch yeah traditionally has always been like in a big monolith right like the applications are running in a huge monolith um and you just load all your code in that one image um yeah and everything just sort of has access to everything and then when you when that dies then uh you know you have all the state that you've accumulated and need to recreate um but erlang has this sort of distributed nature which is completely antithetical to the default um approach but that's that's what gives it something valuable right that it is antithetical and therefore allows you to do completely different things yeah well we saw just by a very simple example here um if we look now i'll just call i can here i should be so if i just call alain call on system info it's allow this is a this is the alloying module contains a lot of built-in function contains all the built-in functions actually there's one called system info which allows me to look inside the system and i can do things i can do things like uh process count i think it was called yeah this tells me i'm running 54 hour processors at the moment because i've started up a number of them and um i can run well the basic uh the basic outlying system can run 262 000 processors at the same time so this that that is what that's one of the things you're selling this this way of looking at concurrency using concurrency to build your system is baked in it down to the lowest level and you're just showing some simple examples uh with my counter right right i mean yeah beyond concurrency but distribution yeah right like distribution i mean if you if you want i can show the virus we can do that we can do that yeah we'll stop that so i'd have to start up an lfv with a minus s name a here now i'm just running this one's running distributed and now i'll start up another node here which is also running distributed let's call this another name this is running b here by the by default they don't know about each other right so let's see i don't i don't think i have the lf the virus here oh so um if we now do if we now stop ah here we this is this one can run the virus here so we'll start up the virus here here now virus colon start yeah and this one's invested now right and um i can start up a third one here well we can now so now i can i can connect up with that one by doing that adding colon ping to it and i want to ping to um now we can start another one here we can start one called c right we'll start an erlang one we'll look at the same thing because we'll just start nailing minus l lfe minus s named c here and now i'm running and now for example um c can ping ping a you're right whoops that's not going to work this is one major problem um we can weaken we can ping a here yes and uh oh now i'm infested and i found that please join and they're all infested right yeah yeah how easy just because they're talking with each other yeah yeah we can do all the cds everywhere they can do a lot of other things as well too so for example this is again what the underlying system gives me so if i go down to control g here and now i do um let's see if i get this right i can ask the questions here so now we started on the on the node uh we'll start on b here i can start a shell b here by running um lfe server should work so now i'm running here and now if i look here i'm running two things if i connect to the second one here i can see no it didn't it didn't like that um ah sorry no no was wrong no that was wrong um we do g here i do i do remote be at absolute that's ben bin by the way now i do um let's see shelf now i should go to connect to it and now i'm seeing i've just started up a shell on there on the v node over here right so now b nodes running two shells one the one i had here and the one i had here now and that one i started here now so again this is just a feature of the distribution so i can run these things across it and if i do things here i can do i can get my node which just happens to be b node and i can do um i can do i here look a little processes running on the b here and now we see um i'm process 113 here up here we've got the other shell as well too so all these things just work the distribution mechanisms just work because of the built-in mechanism and this fact that i'm running a shell on another node almost free so yeah there's just a lot of things you get to get in the system just getting back to the distribution mechanism and of course you can run the virus yeah um uh before i i i take it over to tony to ask a question i just want to uh bring some uh there's some good messages from uh youtube um so uh bob calco said that message messaging systems are built in erlang uh amq rab and mq et cetera jabber was originally written in earlier also um what else do we have here um and also um uh jackson bennett asks uh is erling a widely used language so i guess um those are things oh yeah also someone mentioned whatsapp i think this is like their secret ingredient yeah so this is why we bring this stuff up because this is the secret sauce that makes you look like a genius at work yeah yeah the whatsapp servers are written in alan and also uh so so tony uh you raised your hand what would you like to ask hi uh can everyone hear me yeah yeah uh yeah uh so uh i had uh uh two questions but i i will uh ask the um that's only one of them unless no one else has any other questions but uh my question was regarding um tooling and workflow so for example racketeers have dr racket uh commonless berserk um being on you know um emax and slime i use vim and vittle brittle venus scripts to send snippets to a um a terminal like an animal um what um how does your development process look like with lfe and what options are available okay so um the standard build tool for running airline is called rebar three and that rebar the rebar that rebar has now an lfe interface to it that was written by written by duncan mcgregor by the way he wrote an lfe so you can run rebar and use that to both work on our language and uh and and lfp things as well at the same time for it and that that's that's that's that's the standard outlying build tool for building things these days um i use emacs there are a number of other editors that can talk with it i don't know how many of their of them have lfe modes though however i'm afraid yeah got it thank you um so uh tom small uh well there's there's two things uh maybe i should get our premises first uh what are this machine structs uh it's just a way of implementing structs on this machines with an interface for doing that okay and also i want you to go more into the uh flavors stuff you said you mentioned that if people were interested that you show an example so time small oh show flavor it's much it's much shorter it's much shorter but we'll just do that i'll just get this down now and off get the flavors up here and we will start them up yeah and now we will do that and pop me back up here and oh am i sharing at the moment no yes i am sharing yeah i do see i do see your uh screen we'll start this up the flavors here whoops down i'll go back to the beginning perhaps it's not this is not as long as all as long as the other one don't worry about it okay so again this is implementing flavors um oh yeah and click the uh video icon so we can also see you talking while you're doing it okay thank you so do i have to start the video um the uh so on the bread browser the little background will put your camera inside the screen that you're sharing there you go great okay so we're sharing the screen there and we got there can you still see me yep we can see you yeah so um this machine flavors it's for implementing objects on top of allied howling does not fit very well with traditional objects right in the sense that you see you know say like java or so you sharp or something like that objects it just doesn't fit very well with that the thing that you mentioned the beginning was because uh alan k he said that for him the most important thing about object orientation was was isolation and message passing which we do so in that sense we're very object oriented but this whole idea of classes and things like that and instances just doesn't fit very well you know we'll see some examples when we're looking through here this was just me having a bit of fun so we'll look a bit of this machine flavors and a bit about implementing them and implementing flavor instances as well too yeah that's that's the list machine logger for the lmi machine so what is it it's no it's an object it's an object oriented system running on mit list machines it didn't have a final version just kept developing and after a while it became migrated to close when they were there was expended built the whole the whole life of the list machine but i think they're much more fun so i define a flavor like this this is this is this is how i do lfe so i define a flavor with a name it has a set of instance variables i have components and other options and i can add method definitions i can define local definitions now i have to end it with an end flavor here which you don't need in the lmi and the local instance variables they're local to each instance and um i can give default values like they're calculated when when the instance when the instance is created so far is pretty straightforward i can have options here so i can say which instance variables i want to be automatically gettable settleable initial so by default they're all private but i can say some some of these are going to be gettable these are going to be editable so i can set them when i start and things like this but i can always write methods to access them anyway but this is just being default this is when i'm making components so i can i can say okay i'm making a flavor and i i don't really know what components you're going to put in there but i'm expecting why am i saying they have to have they have to have these instance variables somewhere because i'm going to be accessing it the same thing with methods and flavors and i can just say that something's an abstract flavor which means i can only use it as a component it can't be used as a base this is a pretty straight basic straight stuffing this is taken directly from the um from the lmi the flavors right it's not something like that we can define methods we have different types of methods this is how we define primary methods uh in in in the um for that flavor we'll see some examples i've got some examples later for it and i can define local functions for the flavor as well too so here we have here this is where we're mixing flavors right so we have components we can like and when i create a flavor i can say that it has a list of components that will be part of this flavor and it defines the instance variables the methods which can be used and things like this for it so so then in the end i'll get all the instruments i'll get the union of all the instance variables declared and all the components and myself same thing with the union of all the methods and also i can also see which methods are going to be used so if if a method is defined in multiple components i'm going to get the one in the first component list and that will that will shadow the ones coming later in it but we can get around this by having demons i mean they were thinking right they were thinking here so here's a very simple example of composition so i'm defining two flavors so here on the left side i have a shape flavor with two instance variables x and y and they're both settable and i can define methods move to and relative move to and draw i can also i'll also have methods x accessing x and y as well so i can set them so move two just gets a new x y and sets its own local instance variables to to our new and new uh relative will move to that just relative moving and i have a draw method here which does this so just drawing that as a shape now i can define on the right hand side a circle which has its own local instance variable the flavor but it has a component of a shape so i can set makes radius settable and now when i when i do my circle it also defines a draw method so when i when i do a draw on this i'm going to see this draw method because that shadows the one in in shape okay okay i can show you this afterwards so you had a question comment no um actually i should mute myself because i'm just uh yeah yeah so yeah this is great so here so but that means that means i can't hit this draw right what happens if i want to do something serious i i don't i want to do it even though it might be shadow then i can create demons i can create before and after demons so i have my whole long list of components and i might well i might be running one of the of the methods here but if i create the four demons then the before demons created in each of these each of these components will be run first before i run the method and then i can run after demons going the other way so i'll step down going forward so i'll call i'll call the method it might be the first one but i'll run all the demons and i'll run all the demons coming back up again so even though i my method is not being used i can use demons to make sure that i get things done which i need to get done and a simple example of this one is i have a moving object flavor which has x and y and an x velocity and a y velocity instance variables and all set the initial values are all zero and they're all they're all countable and x and y are settable and immutable as well too and i have my move to which does new x and you y sets there and sets velocity just sets the new velocity that's my moving object but then i want a snail right the snail of course it's a moving object yeah but it's a very slow moving object okay so i don't want to i don't want to set the snail running at 500 kilometers now or something like this that'd be totally ridiculous but um it's a moving object so we'll be using this this set velocity here i want this set velocity but i create an after demon here so this is an after demon which says that when i call set velocity they'll do the moving object one but after i've done that i will check and if if the velocity is is too big i'll use them i'll use my maximum velocity value i'll set here and down that afterwards so this is set after after i've done the method so here i'm going in here you can call this you can call it set velocity you can set it to whatever you want but i'll make sure it doesn't get too big by using these methods we're using the um the demons for it this is this is very nice and cool for never losing control if you always need control for it and that's what the combined method is it's the first primary method and all the before and after degrees that there are for that method to find that method so first you do you evaluate all the before demons in component order then you add then you do the primary method which was the first one the listener had it so i can't i cannot which we saw here i can i can have an after demon without average actually having the method itself and then i all the afternoons afterwards this is a very nice little feature for getting hold of it uh they're just having a lot of fun here for doing this as i said the system kept evolving so every version of the of the of the list machine that they'll be doing more things in the flavors working so the implementation right um now it's starting to get a little bit tricky we're making this work on top of lfe on top of ala so um one of the things when i define a flavor i can define all my flavors in any order i want until i have it's not to actually create the first instance that all these things are put together so i can i can i can define flavors abcd which can which can have each other as components but they're all completely independent until they start putting them together and then then they're all put through as well so it's difficult to build can we build each flavor all the time as the combined methods depend on the ordering that means we have to be cunning and what we do here is for each flavor i create two separate modules one i call the static module which contains all the flavor information that's in the def that's in the deaf flavor so it contains all the instance variables what's gettable and shareable and all this type of stuff this whole thing that there's just a mapping of the depth flavor into into a structure which i can access into into a module with a set of functions and then when i create an instance then i created the dynamic module which puts all these things together and um then i can park i build that i build that combined module and then i compile that when i make the first instance so the static flavor combines only flavor specific stuff and dynamic their flavors specifically their combined can contain all the combined methods they're created run time they're not saved they don't exist in code anywhere but i can pre-compile up all the static ones and release those and make it really useful so yeah so here's just a very simple example the moving object well the static one is called moving object flavor core and this exports this bunch of functions which define this flavor which was in the definition it's got the name it has the components didn't have any the primary methods set velocity move two and here here the here the actual definition of the primary methods these are these functions define the primary methods etc etc it's one function called primary method which uses pattern matching to choose which one i did and here we've got the snail flavor core and here we again we have components we have all the things in it it's a moving object it's got after demons here and here is the after demon definition etc etc so this is all statically taken from the def flavor definition and it knows about the other ones but it doesn't put anything together so this one the snail knows that that the moving object is a component but it doesn't access anything in there at the time here this means if that if i made it you find me if i had another thing working with a snail we do work and other things i can compile each of these separately until i need to put them together then when i create the first snail then i create the snail flavor module which implements the snail the runtime and then we we export this now here we've got we have all the instance variables uh here we have the component sequence so it's called first we call the snail component then we've got the moving object component then there's a vanilla component built in as well too so here's and here's the component and here is the component module name and here we have all the combined methods okay so here we say which which methods are combined and whether where they're combined through and everything like this as well and here is an instance of a combined method so the set velocity combined method well it calls the moving object primary method set velocity with self and args and then it calls a snail after demon set velocity about this and it's worked this out when it's built where's many americans from the list of components but this is how it's implemented currently today right that works quite well yep actually uh uh tony foschetti has a has a question so uh tony if you'd like to uh speak and you can uh just you know interrupt or whatever we usually allow people to just it's more informal type of discussion so go right ahead get into it oh okay uh everyone could hear me i assume okay great um uh yeah so i i would hate to ask a question that i could uh get from google but i thought this would be um you would as a creator would know far more than what a google search would yield in the beginning before the uh meeting began i think uh you mentioned that one of the things that lfe might not be best suited for is numerical computation um and i was wondering if lfe has uh any bindings to you know like um glass or lapak these are linear algebra libraries um but more generally what the um if there's any uh scaffolding in place for like um foreign function binding and that kind of stuff um yeah so we use what's what exists in the allen the alango beam system for it so the beam has the beam has uh built-in ways of for example linking in c code and then calling it from the alarm site in this case from the lfe site so that there's a method for doing that that's built into the system um there come a few packages there's a but there's a java interface uh which which uses this talk to java for example mainly just packing java but java classes that that understand outline data so this myth is built into doing this there's also a way of talking without external other operating system processes and communicating between these functionalities built into it that's that's typically how you do it right that's super cool thank you and we've seen it based on what we can just access this directly there's no problem and again this is what i was getting around to what was saying earlier of course thailand's not good everything it's getting better at more and more things but it's not good at everything but it's it's not too difficult to interface put plug other things in if you want the basic interface is c but i think you're working on doing a rust interfaces at the low level and you can you can load this into the system while the system is running so i don't i don't have to rebuild the whole beam you can dynamic loading the object fasteners and so that's the next one how are we going to implement instances so how much they weigh how accessible are they shareable are they persistent should they be garbage collected how do you handle errors etc etc etc these are all the things you have to look at so we sort of looked at code before but how we're going to handle instance what how we're going to represent an instance and now we're getting into the problem of how do we handle objects classical type objects in an airline system that's exactly exactly the problem we're looking at and the common one is using processors so they're there our process is very very lightweight i mean i can start doesn't take many microseconds as creative process um so that's one way of doing it's very straightforward they're shareable they're more classic like because they don't infect each other they're handled by reference right and they can simulate local behavior however they're not automatically reclaimed in that sense if i create a process it sits there until either it dies or i kill it it doesn't go away just because no one references it um they are heavier than classic object origins so that's something you have to think about and seeing using message passing to communicate between them it's very difficult to um to handle recursive accents so so if instance a references references instance b i still send a request to it which is this which is an asynchronous message and sits and waits for the reply but if but if b sends a request back to a and they won't answer that because it's doing something else at the same time at the same time right so that that's just that's just a problem you get with having multiple processes doing it um yeah so here well this is just saying we're keeping all the instance variables in a map and we're using that that map to access things and do that that that as well too and yeah um it well i do a bit of a bit of an extra handling so if you send a message to yourself then then that's that's translated at compile times we'll copy the world runtime actually to a call so you can call yourself that will work but if a i mean if a equals b which then calls a in the middle of processing that message then then they both both happily block that's just a problem with it um we can use data just to put everything in a data structure that's simple it's very lightweight this is how airline records and lxd structs do it um well we'll give you records trucks on super steroids for doing this but it's not shareable because these objects are immutable they only exist in one process and if and um if i update if i if i have this in a data structure update log the new one the old one will still be unchanged so all the reference the old one we're going to have the changes have to pass these runs because i just have immutable data there's just no way around that and i can't share between i can't charge can't share between processes these ones here i can share these between a process because they are a process itself and the reference contains the pid so any process can send messages to me but yeah this is one way of doing it and here i'm just you again i'm using a map well sorry here i'm just putting them uh i've got i've got the structure here this is the self here i'm just using that as a map and updating things for it but i suppose you've got to handle reference so if i do a send if i do a send to that reference that reference has that send request has to insert a value for them and the updated reference because otherwise any updates are lost that's a that's a serious problem with this it's perfectly okay but it's not what you'd expect from something like using objects and the final one here is here we're being slightly sneaky i think we've been overly cunning there is something called ets tables in the system i'm not going to go into them but um their way of storing data is not shared but it's globally globally accessible and it's quite lightweight and then i can handle them by reference as well too so that means i can have multiple ones accessing this thing and i could do something like this i can i can have the flavors instance table here and i can i can get by accessing and reading apple i'm not going to explain this but i can do that and i can put things in here as well too and i store instance variables in the global table um with references to each instance also containing a containing reference the instance which owns that is that that valuable variable for it so it's an instance it's a variable it's a value for it as well too that works fine right but then you're getting slightly sneaky and you have the trouble with with um uh reclaiming things they're not garbage collected unless you garbage collect them and if some people find garbage technicians i have to go through and find all of them etc so that's not very much what i'm doing and the way i went for what we do now is just to keep it inside a process that's basically all going to say about it for i think i think they're a lot of fun and i can show you some more code here if we go out of this one and we now go here by the way i just want to mention something it's nothing to do with the talk but uh i kind of like the way you uh you have phrases like overly cunning and utterly terrifying sticks in my mind that you have a natural knack for this type of uh language i don't know maybe it's is it laconic i don't know what it is but uh maybe it's a birding is it might think we should create a new uh new way of speaking you know anyways sorry dude yeah yeah no it it it's i think you you get it when you start thinking about things like languages and defining the basic systems you have to you have to you start thinking about things like this since i also interrupted you already i might as well bring up a duncan mcgregor actually wanted to chime in with um tony's um question saying that you can use something like called ports which basically lets you talk to a program using erlang messages so you can run fast rust go etc code with the results passed back to erlang so because everything in erlang is data and it's just a fixed set of data you can basically just communicate it like with any kind of process that's how you uh that's that's how you do things or like in tony's case also with our maybe yeah so yeah um so what i need to do now is here's an example of a flavor i've got i've got three flavors in one module so i've defined the shape flavor that's just well if you go down here we define the shape flavor it's got an x and y with the move tool the r move too i can define a rectangle flavor on top of this which has its own draw method and i can define a circle flavor and i can just just try and load this in and see if it's going to work and i have to restart this again slightly here because i need i need another lsd that just sets up so i can find the flavors now if everything works well if everything works right i should be able to compile that cross your fingers can't find the flavors include that work i thought i could how can't i find that ah sorry yeah there's a mistake there's a bug here don't ask now we should go do it don't run it nice yes and now we should be able to see um these chords in here right so um let's see enough to make sure i get everything correct um we do m of flavors and we've got the instance ng flavor yeah let's see sorry i just have to check this i keep forgetting all this stuff it's include file so we would define the flavor i can make an instance okay so we'll set we'll make an instance here um we'll make a circle we'll make a circle so we'll make it so we'll go up here and we'll make an instance of the circle so we'll set c1 to make an instance of a circle okay we'll find out pretty quickly and then i can set options here and the circle we can set the radius we can set the radius to 25. let's see if this works and define make instance so then we have to do flavors we need to quote this okay so yeah now i've got that so now i've now created this as a flavor instance now i can send messages to it by doing flavors call on send um flavors colon send and because this one was acceptable the thoughts are gettable so i can call i can send that and i can send the value i can send getting the value of radius and i get back 25. okay and we also saw that this this was uh a a shape and the shape has an x and y so i can now do get i can get x for it and now i can see where it's undefined because i haven't set a value to it but now i can do this i can do um set x i can set the x to 100 now if i do get the x i find it's hundred so now i'm working on this flavor for it and i can do i can do a draw for it i can send i can send the draw because the vanilla flavor um includes a draw well here we're also doing a draw so we now do a flavors colon that's where it's flavors colon send to c1 i can do a draw and we'll write back here and we get this draw here so we get the drawing the circle now i can just i could create just a just a shape if i wanted to so i can do um we'll just do one more then we'll put here so we can do uh s1 here and it's we're going to make an instance of just the shape here okay and we will set we can't set the radius because it doesn't have it but we'll set x and y so we'll set x to x to twenty x to two thousand two hundred fifty and we'll set y to twenty so no matter that should not be uh yes one so now i've made a shape right now now if i send the drawer to this s1 i'll get back something else with another one so now i've got these two shapes working here for and um let's see the vanilla creates something if i can remember correctly we will do uh m of vanilla ah so just want to check one thing just bring it down we're done [Music] we've got the definition of vanilla flavor and it doesn't do very much it's got a print it's got a prints off method so if i now send to um ps1 i can send print prints off and it gets me just getting back information about it what let's see if it can do anything else as well too yeah it just prints itself this is just the thing it is itself as well for i can i can i can set variables in it i can get information out as well if i now try and go here and um try and do a which we're looking at for the c1 up here we're doing an x here well i can do the x because it has an x there but i cannot do i cannot do an x i cannot for example get a radius because it doesn't have a radius that gives me an error so yeah this is just a simple example of it and you can put together and make a lot of things here for what you want to do and i think they're fun i think i think it's i i think i think it's great to be able to use some of these uh features if you want to program in this style with flavors you just you have it yeah yeah it's really good yeah and it's it's about as efficient as using the um for the counter gs for example i was using the if i was using the gen server so i'm using that gen server back behind as well too um if we want to do this i can see if this works shall we uh sis poll on the trace all right don't think yeah we will do good of us zero one one three don't ask i will turn on tracing for it and now i should be able now if i send to 113 which is a self i send radius i see it gets this message for it you've got to send radius request and it returns our undefined method back as well too and if i now do for example uh print itself we're getting this method and it's returning this page before so uh so i've got all the features here i have for the for the behaviors because i'm using behaviors to implement it as well too i can log things i'll get a lot of information out of it i can for example do um things i can do we can do get status get status of this one and here we have the internal state of that of that server gen server which implements the shape i get all this information yeah so this is this is one benefit and i can quite happily put these in an otp supervision trees because they are atp comply with all these types of so let me uh ask that everyone uh over do we have any uh final questions yeah you must turn me off otherwise i'll just keep going well you can continue after the livestream's over we're about to stick around forever um but uh if uh no one has any questions i do want to have some final comments um dick ash on youtube says thank you for the great talk uh ogie just mentioned thank you for the great talk i'd like to thank you for the great talk um and uh uh okay robert you just sent the youtube video i'm going to check that out later check that out that's that's duncan stuff right yeah it's used that that's his uh working with we're working with music generation through lsp well i sent my email address so i'm hoping that he'll uh uh give us a talk so um maybe you could help us with that too that would be great but um so i i think if we don't have any more questions i think we'll uh we'll conclude the live stream um i want to thank everybody here and i want to thank everyone on youtube i think the comments and the questions were amazing um i want to remind you if you're on youtube to like the video so um youtube can know to send this to everybody um on youtube to share the video so we can get this video out to everyone on the internet on whatever socials that they happen to be on um and of course to subscribe to the channel so you can keep getting more of these videos and um you can also check us out uh for at lisp.nyc that's our that's our um website address and uh with that i'd like to close the parentheses and uh we'll see you again in the future bye okay
Info
Channel: LispNYC
Views: 1,016
Rating: 4.9245281 out of 5
Keywords: Lisp Flavoured Erlang, Lisp Flavored Erlang, Robert Viriding, Erlang, Beam, OTP, Lisp
Id: CAOrdVJTUow
Channel Id: undefined
Length: 125min 35sec (7535 seconds)
Published: Wed Jan 13 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.