Erlang Oddities

0 0

okay so welcome this is a talk about weird strange funny stuff I found in Ireland in my 10 years of experience working at it I've been collecting tiny bits receiving contribution for many people I'm Brujo I'm from Argentina that's why I sound not so English I will try my best and this talk was originally based on this one have you seen that one the what yeah excellent if you don't check it out this five minutes super worthy it's not unusual you have to check in in the in Gary's website but Gary is a it's a parameter but it's also he's also a stand-up comedian so it's much more funny than me I will I will do my best I am NOT a comedian I am a father and an earth so these kind of things will happen along the presentation and sorry you have to bear with me yeah that one was that one as well okay let me show you a couple of things to put them all in context I will I will work along these couple of minutes on a simple exercise that I'm pretty sure everybody's familiar with it's a fit but you have seen it in interviews and stuff it's a very simple thing to do I will add I did a bit of complication to it just to show you stuff and they work them best warning I can give you is don't copy and paste nothing that I were they will show here should be on production code ever okay okay so this is the exercise we will write a script a script that receives a parameter which is a number and it actually counts until that number for every it bonus when I say count it prints the numbers pretty numbers and Bildad that one's starting from one if the number is divisible by three it brings this if it's divisible by five prints but and it's reversible by both prints feedback the only tricky part that it's not usual usually found in interview questions is the last one it is it should work for floating-point numbers that the trick here is that since it will count up to if you put a floating point number once we are past that point we don't print any more numbers simple enough right okay let's see how he'll screw up we can create a scrip for that first of all let's define a module and if you don't see it correctly there I can make it bigger for you look at this is it it is wrong what do you think villi chef just watched my first line not really it actually works you don't need parentheses in inner language of use I can show you you compile an easier module so since the introduction of type and spec there are attributes with parentheses every single attribute you can write it down without parentheses module export it's good it's fine it's something I found later in my mailing history but it's actually work I will come back to that in a bit but for now let's let's start with a very simple case let's just print out number okay easy very easy we write down two functions the first one is the one that's exported you provide a number it calls the other one and it does the other one is a recursive function that traverses the list of numbers and print them out so remember we cannot do a strict pattern matching here because we are working with floating-point numbers right so we have to travel until we exceeded the maximum value the input provided by the user anybody see that right okay in in the last one when top is below the number that we are going to print we don't print the number we print a new line and that's all let's see if it works we try to compile fair enough so we count up to ten this is super test driven development and then then you got it one to ten X now before moving on we need to validate we need to start adding special gauges here so the first one I want to add is to check for input that's wrong that's not a number okay if it's not a number I have to bring the message I will do it in a super super wrong way not the way you have to do it but just has to show you what happens so I have two functions of course instead of choosing the one with one a close I will choose the one with two o'clock and I will do this I will add a guard to check that the provided input is actually a number it looks like this so if it's a number then everything as before both closes but if it's not a number it will fall in the last one right simple clear nothing to worry about let's go to the counseling compile the module perfect now we try with something that should break the code now the number should bring the message that it's not a number what do you think nope it's correct no the number the problem here is this one that one we already proven it works but the 3m development we have to do regression test here so we try again uh-huh uh-huh okay what just happened the problem is that one I will show you the problem is that and and/or for what it's worth they have some president's logic that is quite complicated and so the regard was understood as if it's a number top and if it's numb if it's numbers of and so if all that is bigger than one then do things yeah and this popped up in airline questions mailing list and if you if you know Costas because it is a guy that when when he answers emails he writes a long paragraph he explains everything in detail for you in this case he said done you son who use and also just done don't question so we learned also everything works ok ok I move it it up I turn that thing into the proper thing so that I don't have to deal with those squeaky wheels closes down there so I'm validating the input on the proper function this is the only thing I'm doing right in this whole presentation I promise no more number good thing so let's compile with know the number of course and if you count it's fine everything everybody happy ok let's add fees and bar here remember I'm on an interview so I have to look super smart I won't implemented that the useful function because the interviewer will say well that's shuttin al-rahman I'm not just another programmer so I will do a super smart way to print this bus and all that stuff and basically we go like this so if the number is divisible by 3 I print please if it's divisible by 5 I print bus if it's divisible by both of them I already print their fees but see but but of course yeah if it's not divisible by any of those I will bring the number fair enough it's a little bit infinity oh of course I'm bringing the space at the end otherwise the numbers will be all chunked up right it's a little it's imperative or not but it's a smart way it's using press the interviewer let's see if it works we compile of course and we try to count up to 10 and yeah I know that didn't work why who knows I missed the else part of these theyíve in Erlanger expressions assess everything else they always need a value if you don't arrive a way to understand what happens when the guard is not true it crashes you're missing a clock there in this case true because if the else is a way of writing else in our lungs so this is what I have to have right if it's divisible by 3 please if not I don't care if it's a visual side same thing and the other one same thing and I'm super bored and I have to use two columns in there in the slide I really don't want that but let's first thing check if it works and of course pretty nice it works perfect yeah of course I was testing up to 10 right there is no feedback there what do you think will that work yeah you were expecting to fail I see you not this time but then again to column I don't want that column on the right so and I'm not the only one I found many people in the Yellen community that really deeply wanted and else less if they super heavily wanted that and they came up with not one not two but three different ways to implement s less if none of them Atul but there are three and so I have three closest classes pure pure scale in lakhs right now not intentional I have three wait three places there I will show you three ways of getting else less if in a line let's start with the ugliest one okay remember and also and also is a short-circuit operator so each what's on the left of the and also cloth okay I shouldn't leave into the so if whatever is on the left side of and also is false everything is false on the right side is not evaluated and if that's true then it needs to keep evaluating but it doesn't validate that what you were the result in the end is is a boolean because there are no body of emailing right it's Adam so whatever you put there it works so that even if provides the same behavior as if you were having an affair in Elstad if if it's true evaluates that thing if it's false yeah that'sthat's not evaluate the thing dialyzer one will not be happy with you but the goal is there so let's see if that works we start running tests with 25 we forget that 10 and you go it does everything funny now let's check another one and this one this one is really weird there is a way to write there are many ways to write lists in our line right my favorite one is this comprehension and somebody's at some time came up with this in comprehension let me show you that like that okay what's going on there this comprehension this is one of those things in our life that you always read in the sort of convoluted direction but basically to the right of the two pipes you have to tell airline where to build a list from and on the left side you tell you tell Allah what to do with each one of the elements in the list right it's you're supposed to provide a nourishing there F what's the name of a generator on the right side and filters or many generators are many filters but you can provide no generator so they just give me something if it's if I is divisible by five something where are you taking from I don't know mystical beings and on the other side for each one of those things compute these things this expression as you can see there is no reference to anything on the left side here right because if I put a variable there and good that's that's kind of the point of it so what we are doing here is writing a list comprehensions with just one filter or many filters and a unique expression with not with no variable tie it to any filter on the left side this has the effect of producing a list with one item that's the result of evaluating the expression if the filters are true and an empty list if the filters are false an empty list where you didn't even compute the expression of course so in a weird way it's an else--if again it actually works there you go and if you think that ah if you think that that's weird you know nothing yet look at this okay example I show you that I show you that before right if it's the filter is false it produces a list with one element evaluating the expression level is an empty list sorry alright if it's true at least with one element and now what do you expect here to happen I would take an exception every day because it that's not even a filter not a generator it's nothing right yeah no it's not an exception it's an embolus okay but let me show you a function that is amazing that's a identity function as the first function that teach you when you when they teaching you Haskell for instance so it basically takes irrelevant and the return of the thing one analysis okay okay now we have a function and so identity of false is false in sodium the result is an empty list as above identity of true is true so the result is at least with X as line 23 and so identity of something is something and the result is of course an exception yeah and I leave you to say homework to try with different kinds of functions you can say we need with beefs with other things in each one of those you have to try it you never guess what's going on there okay okay now the last one the last one is the obvious one I'll leave it for the final part because suits the goal but remember when you have a nice without the nest cloth that generates an error right if you if you when it's evaluated there is no true close it produces an error okay there is a way to catch the error show you yeah turn this into this right yeah yeah yeah I know I know if if our format fails for some reason you're cutting the error as well that's environment you have an LCC that's only closed let's do like here about late lines of code that's all and so okay so you can find it works and we got rid of the second column oh yeah yeah yeah but yeah here's this friend of mine constantly bugging me because he he saw an Internet curse about the airline and it was airline LTP and I'm not writing any OTP here okay John let's do it let's go with OTP okay column on the right is what we had before yeah the same function as we had before do you trust me I don't want to I don't want to touch a single character of that colony anymore in my entire life I'm okay with that oh so peaceful I feel so good okay now Jen server well I went to the Internet and I copy paste the region server here it was super straightforward and I also did a little bit more I check the documentation and I check that start link actually returns okay PID if it's the server status and error or error whatever you provide if you return from in it will stop any value right so super dump I I don't want to write any function so I wrote the Jen server that basically computes in prints the numbers and stay there yeah leaking memory other stuff I don't care I just want to write less code so init function if it's a number call the other function same thing as before but if it's not the number returns stop another number that ends up in error not a number and bridge zero all right let's good right since we correct it's according to documentation and we call this copy pasted from the internet so it's fine so I I compile the module I combined the module and suddenly what just happened where is my macro are you telling me the Internet is run okay who knows what am I missing here why why module is not defined not exactly no no you don't need a behavior you do need parenthesis oh yeah these funders out there I was doing yeah you can take out the parentheses and the macros which is good but not but not use one or the other side so will parentheses it works and when we try these it works and now let's try the other case where we have something that's not a number and of course it brings a beautiful message that's not what I wrote before hmm what should happen is this is a computer it's super smart and understanding what I want to print it's printing something else right now there is something odd here right I let's have an exception and I have a case case is not with exception so let's you say let's do something that actually deals with exceptions try catch fair enough any exception any type anything so I catch whatever and print the message okay let's go to the console generate the exemption ah catch the exception try catch the exception uh-huh what am I missing what am I missing ah that's the thing exit signals are faster than return values so if you are if you are doing a chi a case with a return value of a process that your that's link it to you your dev the console looks like it's a constant flow but every single line of those it's a different shell process so we are subbing exits now and there you go now the number C okay we can also we can also do a different thing instead of startling which is a problem we replace that with start like this all right so if you start the thing instead of linking it when it dies you won't be affected that's the thing let's try that of course we have to go back to the previous state otherwise you won't believe what I'm doing and then we try with the exception not an exceptional everybody is happy I this thing actually hit me three times in ten years two of those times I wrote a blog post about it but the second one I already forgotten the first one and somebody reminded me that hey is this thing again I really hope I given this talk I don't forget anymore okay now that's not how gentle words are right everybody knows that fortune server you have to you have to have a handle call like I'm the lien for all that stuff not a need not leaking memory all that stuff so let's do it in the proper way and basically what I'm doing now is I split up this code this behavior so I start the server on one function and account on another one you see nation server call okay but let let's look at that particular atom there you see in it nothing before we have a number there because we had the code for computing the not for printing the numbers on the init function let me digress a little bit about this this is not a whatever I'll to show you it's not particularly bad or tricky or funny about Airlines is more about ourselves like people reading airline documentation I am a I am also an airline trainer so every once in a while I go to some office to talk about the Google to talk to a group of people and tell them how to write in servers or watching servers are in general cigarettes is one of the things that happens every single time I gave a class about this is that they are with this documentation this is straight from the OTP dogs all right and so you see there is no documentation here this is just an example right and then you have this general star link the first part ABC local name that's the name of the process no problems with that the second one is a module that implements the coal box in particular these very same module the last one I don't care nobody cares it's an EM police sometimes you put the bug in it but forget about it for now but the third one is the list an empty list there and it's in the way that you express it is a list of argument right those arguments are going to the init function okay and the init function has one argument called args I will go back to that so whatever you put there comes here all right that's very easy to see but this happens all the time you want to send in one argument to the init function but that's over there is the list of arguments so you put the argument in the list and of course it doesn't work right because it's trying to add at least with with an element to to that crash it so alex is not actually a list of arguments ours is an argument is one thing an argument so if you do occasionally you get at least that's I believe don't do that don't do that let's say you wanna the purpose of it is to if you want to send multiple arguments right so you send the list of arguments and you get the list of elements on the other side all right yeah but actually lists are in general in general or semantically not bounded inside so so you have when you when you will receive a list your let's say you expecting the function with dialyzer if you specify the list you're going to receive you never you're not allowed to say how many at least hot ways it can be one two three whatever so if you're doing this you're yeah misusing lists if only we have an element and type of data that allows you us to stablish things that have a fixed number of arguments what should we use there right lists are not tuples that will be much more convenient so if you have two arguments you want to put it in an object you put a double with it but but since there's not so long ago we have an even cooler way of doing that you can put names to your argument using maps and you see look at that how cool it is of course if you want to send nothing because you don't need an argument yeah it's a nothing like that and it's super clear that's that lesson it's always one of the first I gave to two people on the training constant always comes up with somebody trying to save the lives of their so eventually I think I will I will send a pull request to the documentation to the OTP relation to put a pole or a map there to give you a better example going back to going back to our piece bus thingy this is kind of calls this is what happens when you want to print the numbers with the feedback I am I basically copied from the other side and if it's not a number I'm throwing an exception there look how how smart I am i learned from before I'm not writing if here I'm using and also super goal and then I get the response everything fine right so it's a server when I go to the console and then compile I have to start this first and I put the name on it so I can call it and then I count up to 25 and it actually works and the only thing that's missing here is to try to see what happens if I provide something that's not a number and yeah that happens because I didn't at the behavior option there so when it compiled that if you don't tell me what method of missing so I need terminate that sub terminates here okay and let's try again and ended up okay said we're terminating with a recent battle return value error not number that was not what I was expecting to happen I wanted to report the error but the server I wanted that I wanted that server to keep running and this error actually gives me a clue of what I have to do it says but return value that means what I'm throw-in there is is understood as a return if we fight with return like in the last statement there so I create a return value there and let's see what how it goes I start the server try with not the number that's the message and if I try with something the server is still up there you go see that you can you can return from the middle of your handle call handle cut a function as long as you provide a valid return value that's super cool and and you know that took me this was a service lesson I ever learned in a in Erlang yep it took me it with many conversations some of some of them with Robert and I misguided a couple of students over the course of three years sorry but but I will get it straight this time this is the thing I come from an object-oriented paradigm I used to be a small to process a programmer so I found out that I the way I would use exceptions in an object-oriented paradigm is not the same way to use those things in here I kind of expected that but I didn't expect it with so so radically reasonable let's see so inner luck this is a basic one is this is a easy one what what in Erlang is an error in opie is an error that's fine runtime errors are handled that way you can try got nothing to say about now now the weird part so in our security in the other languages you have a method and there is some problem with the parameters but it's an expected problem it's something that can happen so let's say you're you're writing a method to look up a user in the database and they provided an ID for something that's not the user so you have to say there is no user right you can return null or if you have a proper of sugar in that person and you can't know that you should you return you throw an exception informing that the user was not found so the color can be a with the exception in Cydia that's because not not every function returns a value in Nov and those devices the ones that do return a value they are expected to return it in a proper class or type or option cetera but in Ireland we have a pattern matching and tuples and we can return complex objects so we basically use target status instead of throw if your if you are implementing that lookup function for a user you may return okay and the user or error and what happens are not found or what not that's fine that's tricky but fine that's no big deal but then you have unexpected but with a bad result when some something should be interpreted as an error but it's not it's not a runtime error it's something that went wrong there you try to write a file and the file was not there or uses Reynolds out of space in the in the hard hard drive or whatever and so you want to throw an exception this is the things in Erlang you don't throw an exception you exit the function will exit exit one not to be confused with exit two that deals with exit signals unless it's brutal kill that kills the process but never mind so exit one is what you will use for throw in exceptions with really bad result again it can be caught in a try card but it's not a is not an expected error it's something bad but then you have throw in what is throw then and for for 10 years I listen to people say that throw is non-local return I think rubber burning told me that at least 10 times throw is for non-local return I was a was how fancy name for throwing exceptions what were the good name right no legal return with it's not it's not like that this is the deal this is the real let's say you have a function that doubles every element in a list yeah these two versions of the same thing on the left side we are doing local return this is an anonymous function in between that returns not the number to whoever is calling it in this particular case is the implementation of list map so within list snap the coal is calling the anonymous function for each one of the elements and this function returns not a number there in that part of the code on the other hand on the right side we are doing kind of the same thing but instead of returning not a number we are throwing it and that doesn't mean that we are producing an exception or what not what we are doing here is returning not the number not to map to list map we are returning not the number to the outermost color the one with try and catch it looks like an exception it looks like in any other language that's how you handle exceptions but not in Erlang here you are returning stuff and I said before I was a small dog programmer and in a small dog we have the same thing you can use the that cut the little Hut in the with two arrows like this and you jumped from a closure to the outer most part I didn't recognize that thing here but this is the thing that's why if you're writing your open source libraries or libraries that we other people will use use exits don't use throw throw is to be used within a try you need to know that you're there when you're throwing an exception that's exit whoa okay okay final part let's back to our current business with this one we wanted an S clip not an airline program so we write the next nf script here basically I put a little usage message if the parameter is not provider if the parameter is provider I just call the function that we have before there you go I compile nope this is a new clip don't compile this is interpreter so I just use it this is a usage message I try with 25 oh yeah 25 is not the number of course every parameter is a string here so we have to parse it all right let's parse it we have these two integer there and we parse the parameter turn it off go to the console again try with 25 it worked but now if we try with something that's not a number it generated an awful exception because these two integer produces a runtime error when it's when it's not where the string cannot be false of an integer and we don't want that luckily we have a function that returns that expect things to make that may not be integer and returns the integer or a total informing the error that function is string to integer so drink to integer if it's if the input is a proper integer we return the in there if not it will return an error I'm leaving the input there so that the internal function prints the message not the number you see that fine all right so 25 not a number what am I missing here what nope floating-point numbers so if I try with a floating-point number and there you go it's not an integer of course so we have the past floating-point numbers not in vessel dam Brujo we have the part floating-point numbers on okay let's parse a floating point number and not the number and an integer okay cascading code for you so it is not a float it might be an integer if it's not an integer all right going to the right and then integer words floating point number it works not the number works but then again you know if by this time you know that I like things with less code smaller things and so I turn that into this and I leave you to check why that works but trust me it does that's what I have [Applause] [Laughter] what was what intentionally yes you mean this one all right I leave you there thank you guys