Types, Conditionals, and Loops - Learning Emacs Lisp #2

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Hey folks, happy Friday!

In this stream, we'll continue learning the fundamentals of Emacs Lisp:

  • Primitive types and how to use them
  • Sequence types and how to use them
  • Conditional expressions and logic operators
  • Loops

This will give you a solid foundation for configuring and extending Emacs!

Hope to see you there!

👍︎︎ 7 👤︎︎ u/daviwil 📅︎︎ Jan 15 2021 🗫︎ replies

Awesome work you already done and doing still!! Thank you, I understand emacs much better than ever before!!

👍︎︎ 1 👤︎︎ u/ladjanszki 📅︎︎ Jan 15 2021 🗫︎ replies
Captions
[Music] [Music] what's up everybody welcome to system crafters i'm david wilson and today we are going to go into the the next episode in our learning emacs lisp series and we're going to dive a little bit deeper into some things that we covered briefly in the previous episode uh specifically the basic types that are included with emacs lisp and all the operations and predicates and general things you would want to do with those including like numbers and strings and lists and then we're also going to go into conditional expressions like the if expression and the case expression and then we're going to do a little bit of uh introduction to loops so basically the idea is to continue this discussion on e-max list fundamentals so that we can have a good foundation for the future episodes where we actually start to start writing real emax list code and try to build uh some customizations and some packages etc as we go along so we are recording this video live so i just want to say hello to everybody in the in the chat here hi to uh valdia and glenn and reminator and victor uh thanks a lot for joining today so uh i'm gonna try to get the questions when i can but i might just like make a beeline through this whole discussion because there's quite a lot to cover it's probably going to take about an hour so buckle in for that um we are going to cover a lot so i'm going to have the show notes in the description after the stream is done and so if you miss something while we're doing the stream definitely go back and check the recording and look at the show notes because i've got examples for everything and you can go through and evaluate all of it yourself as we go all right so um let's uh let's just go over once more like what we're going to cover we're going to get a sense for like the basic data types of the language and how we can use them so we're going to talk about true and false in the language which is kind of important we're also going to talk about numbers and characters and then we go into the discussion of the different sequence types which are like the string list and array and then we're going to go into the conditional expressions and then loops so let's jump right into the first thing which is uh for me to tell you that you should try to use the i elm command in emacs this is actually a reply a read eval print loop that's built into emacs for the purpose of evaluating emacs lisp expressions so it might be very useful if you're watching here to open up emacs and uh run i elm using meta x so that's alt x and then type in i elm to to run the uh the interactive mode uh i'm gonna be using that myself during this presentation um let me see if i can pull that up so i'm gonna have this little buffer at the bottom that has the rebel and you can type in arbitrary emax list expressions there and have them evaluated so it's very helpful for experimenting you can get completions for certain things in the buffer and um yeah it's just a really good environment for experimenting it's a lot better than just going through all the lines in this file and just hitting control x control e at the end of them because then you have to go look down in the echo area and this is harder to follow so i figured that this was probably a better way to do it okay so um if that wasn't clear you basically just type in an expression and press enter inside of the prompt here what i'm going to be doing is using a key binding that i set up to evaluate things as we go so line by line basically okay so let's talk about true and false so normally in a programming language one of the most core types that you come in contact with is a boolean type and basically a boolean is a yes or no value a true or false value and the reason why we have this type of value is because you need to to answer a question usually like is one value larger than the other or um is something equal to another thing so we have this boolean value type in many languages to express this however in emacs list there's not an actual boolean type or at least as far as i know what we actually have is the the t and nil symbols so if you go and evaluate the type of function on t and nil which are the values for true and false in emacs lisp then if you look down in the i elm down here i'm running type of t and it tells me that this is a simple symbol it's not a boolean it's just a symbol if you do the same thing for nil it also tells you that it's a symbol that's not really important to your day-to-day use of emacs list but it's interesting to know what all of the types actually are that you're dealing with so that you know how to use them and maybe how to abuse them as time goes on so like i mentioned these symbols are used to provide like a yes or no answer for expressions in the language so there will be many types of functions called predicates which is basically a function that takes in some value and then tells you yes or no so is this a list or is this a string that kind of thing these functions are going to return t or nil to say whether it is true or false or yes or no so that's just something to keep in mind as we go um also a very important thing at the core level is the concept of equality so are two things equal to each other all our two values are two objects equal to each other so oh my goodness thank you so much valdea for telling me that you can't see my screen that's another big mistake so let me just back right up for one second i have been explaining things the whole time without showing them so i'm just going to go back and show you the slides i was looking at so that you have those in mind i apologize for that and now for whatever reason i can't go back in slides let me just uh go back and start the presentation over okay so i elm um just run mxi elm to get the the ex-list for rebel true and false i was just showing that if you run a type of t on sorry type of on the symbol t it shows you that a symbol type of on nil shows you that it's a symbol also uh so hopefully now that makes sense what i was talking about before thank you for the people in the chat for letting me know um and then uh equality okay so we're back on the discussion of equality so uh we need equality to be able to tell whether two values or two objects are of the same um or equal basically that like so basically if you say is one equal to one it should say true i shouldn't say false because 1 equal to 1 is true however there are different ways of comparing equality in emacs lisp that probably are surprising to you so it's good to know what the different functions are for comparing whether two values are equal so that you know when to use them when when they're appropriate to be used so first of all there is the eq function a paul no i did not do it on purposely you don't copy my code copying my code is kind of the whole point so eq is a function that compares two objects to say are they the same object so this is one of the things that's kind of surprising uh in that uh things that you think might be the same object are actually not the same object so whenever we evaluate these two ones basically we do eq on one if i evaluate this if we look down in the reply here we see that these two think two things are equal in terms of their objects which sort of you know makes sense one and one should be the same thing however if we do floating point numbers or decimal numbers and evaluate this it tells us nil that those are not the same thing so certain types of object in emacs lisp may be the same object for the same representation others may not be it really just depends on the type of object same thing for strings so for two strings that look to be the same both the strings are thin they are not equal so this is a thing to keep in mind whenever you are using equality functions in emacs lisp often you will use this when you know that you're trying to find the exact same object like you've got a variable stored sorry a value stored in a variable and you want to compare some other variable to it and make sure it's referencing the same object in that case eq can be very helpful because it's not going to do a value equivalence it's going to be doing an equivalence on the actual object is this the same literal object in memory so that is uh the eq function now the eql function is sort of an in between where we do comparisons on objects uh to see if they're the same object but the special case is for handling numbers in this case we will say that two objects are the same if they are the same object but two numbers can also be compared to the same so now this equal of one and one with eql will give us true as we evaluate it and see it in the rebel same thing for 3.1 to 3.1 but still strings as we see down here strings do not show as being equal with eql so maybe if you want to use something that says if it's two if two objects are the same or they're the same number you can use eql but still it's not perfect for the case where we want to check if two values are the same value basically to do that we need to use the equal function that has the full word equal spelled out what that does is does a value comparison uh between the two values and tells you whether they are equivalent like if it doesn't matter if they're the same object what matters is the value itself is equivalent so we can see that you know i've left comments on the right side of many of these expressions to show you what the value is so i don't have to go and evaluate all of them but basically for all of these they are now returning true because we're comparing the values so now thing and thing if we run this line thing and thing evaluate to true for the equal function so in many cases what you are probably looking for is the equal function with equal all spelled out uh to use for your comparisons because otherwise you will get surprising results that don't actually make sense so um just keep in mind that if you're if you're comparing to make sure that two variables contain the same object that has been created by you or someone else then you can use eql otherwise you probably want to use equal the full word equal to compare two values like two strings etc just to make sure that you are getting the right result from that i've got a link here to the manual about equality predicates to get more information on that if you are interested all right so let's talk about numbers so there are two types of numbers or two main types of numbers in emacs lisp one is the integer which is like a whole number it's just a number like one two three four that doesn't have any decimal place or any kind of complexity to it so it's just a whole number then there's also floating point numbers which do have a decimal place and can be quite large or have many decimal places basically and you often use this for doing more granular calculations or you know scientific calculations etc however floating point numbers are not necessarily the best number for that purpose there are other types of that but we might cover that in a in a different video but for now we're going to focus our attention on just integers and floating point numbers so if we evaluate these two uh numbers here you'll see that they they're self-evaluating they like we mentioned in the last episode there's a concept of self-evaluating objects so 1 evaluates to 1 and this number 3.14 which some of you might recognize as the first part of the number pi that also evaluates to 3.14 blah blah so they can also be negative both for the integers and the uh floating point numbers uh also you can have a period at the end of a number without a number after it uh which also sort of indicates that it is a whole number i don't know if this is just a way to make syntax look more consistent whenever you've got a column of values that maybe some of them are integers and some of them are floating point numbers and you just want to leave the last part off some of them but that's something to keep in mind there if i were to put 1.0 here you'll see that it actually does get evaluated to 1.0 so there is a difference between one point and one point zero as you can see here um uh peter we'll talk about that in just a moment so uh negative zero evaluates to zero because zero itself can't be negative in the language however there are languages where zero can be negative which is kind of confusing so now let's talk about operations on numbers so often what you want to do with numbers is do some kind of mathematical operations so we can do things like addition so 5 plus five if we evaluate that we see that it goes to ten five minus five goes to zero five times five is twenty-five five divided by five is one um and as we mentioned in the previous episode uh the operator comes first in these expressions because uh emacs lisp uses the uh the prefix notation or the pascal or if i'm right about that notation basically where the operator comes first because the way that expressions are evaluated is that the first item in a list to be evaluated as a function has to be the function symbol or a function value so one nice thing about this is it does give you the ability to do nested arithmetic so if you wanted to add three and two uh and then um subtract ten and five and then multiply the results of both of those together we can do this nested function so i'm gonna evaluate this and the result is 25. so three plus two is five ten minus five is five so five times five is 25. so it does allow you to line things up nicely so that you can actually see the the groupings of your calculations with these nested structures also we can do things like you know we already talked about dividing numbers but if you're dividing two numbers that don't divide cleanly together uh like you know 10 and 5 divides to 2 but if you have 11 and 5 then there's a remainder left over so if you're dividing integer numbers you can use the percent sign which is the the integer remainder operator or modulus operator if you evaluate that that returns one so where this can be useful is if you want to do a calculation where let's say you have five a range of five values that you're concerned with but you want to condense a number that could be any number down into those five values you can use this modulus operator to say okay so i care about five values so if i use any number modulus five i'm going to get a number in the range of 0 1 2 3 4. so if you're trying to like put values into buckets or if you're trying to do some computations where you're sort of you know shrinking the number down somewhat this can be kind of useful for that probably won't come up into in day-to-day e-max configuration though unless you're doing something really interesting uh same thing for floating point numbers you can get the floating point remainder um so uh yeah the floating point remainder using the mod function so it's basically the same operation it's just that which will deal with floating point numbers correctly so if i do the calculation here it's 1.09999 so that's useful for if you want a remainder for a floating point division and then we also have just the simple incrementation functions uh one plus and one minus so it just takes a single value and returns that value either incremented by one or decremented by one so uh one plus five gives you six and then one minus five gives you four so this can be useful if you're like running a loop and you just need to increment some integer value you can do that very easily using the plus or minus functions um you can also convert between integers and floats using the truncation functions um i won't really you know spend too much time on this but basically they all have different rules about how they truncate a floating point number to an integer so truncate rounds it uh by moving the value towards zero so if it's a positive number it moves it towards zero uh which is through subtraction but uh if you have a negative number then it rounds it towards zero the other direction where it adds a number to it so truncate of 1.2 will give you one but truncate of negative 1.2 will give you negative 1 instead of going down to negative 2. floor on the other hand will round it to the the integer by subtracting every time so floor of 1.2 will give you 1 because we're subtracting the floor of negative 1.2 will give you negative 2 because we are subtracting from negative 2 which ends up in continuing to be a negative number ceiling rounds up to the next integer no matter what the value is so if it's anything over point zero it's going to round up so 1.1 1.2 all of that is going to round up to 2 and then 1.0 is going to remain to be 1 because it's 1.0 it doesn't need to be rounded up because it already is a what you might consider a whole number in that case um and then a round uh rounds to the nearest integer uh depending on where that integer is so this sort of splits the integer in half to where anything from point zero sorry yeah point zero to point four will round down anything from uh 0.5 to the next number will round up so rounding 1.5 will go to 2 and rounding 1.4 will go to 1. uh so there are some more operations you can do on numbers there's a lot more stuff you can do if you want more complicated things like square roots or powers and stuff like that sign cos if you know those kind of operations check out the links here to find out about those kind of operations including uh bitwise operations uh and more floating point rounding operations so i'm not gonna go into those because they're probably not very common for day-to-day use but if you are interested you can follow these links and learn more about that so um let's talk about uh predicates so like we said before a predicate is a function that answers a question yes or no about some value so a lot of times what you'll see is the predicate is to tell you whether a value is of a particular type so in this case we're going to call the integer p function to say whether the value we give it is an integer or not so in this case running it on 1 is going to return true because one is an integer but if we run it on 1.1 it's going to return nil because 1.1 is a floating point number also if you give it any other type like a string that says 1 is going to tell you nil because a string is not a number um so for floating point numbers same thing applies if it's an integer it will tell you no if it's a floating point number it will tell you yes uh and then for any other value it will tell you no or nil because you know it has to be a floating point number to return true now number p will tell you if it's a number of any kind whether it's a a an integer or a floating point number which can be useful if you only care whether it's a number it can be treated like a number so evaluating these two expressions will give you true however any other type will give you nil still and then there's a way to check for zero um because uh yeah you may just need to check if something is zero and it doesn't really matter what type it is whether it's a integer or floating point number you just want to know if it's zero then you can use zero p to do that so uh giving it one returns nil because it's not zero and then any of the other two forms of uh zero will return true in this case so finally the comparisons of numbers uh there's a general things of you know whether a number is equal to another number or if it's greater than or less than there's also the greater than or equal to and less than or equal to in case you wanted to see if uh 5 is less than or equal to uh five and then it will tell you yes because it's it's equal to also so all these examples are here i'm not going to run through all those because they're pretty uh pretty obvious and self-explanatory one thing that is interesting with equal though is that you can give any number of values that you want and this is the equal sign operator basically so um you could say you have a whole list of numbers and say are these numbers equal they can be variables that you have so you're just checking all of them and then um if you evaluate this expression it's going to return true because they're all ones uh and also we're using this thing where we can break the line and have the rest of the numbers on the next line which is one of the nice features of emacs list syntax where you can kind of reorganize things as long as they're still within the same set of parentheses so let's go on to the next little bit here oh min and max this is also pretty useful if you want to see what the minimum or maximum value is for a list of numbers so basically you can just put in any set any amount of numbers here it could be 2 it could be 10 it could be whatever and it will give you the maximum number in the list so in this case it's 7 if we evaluate it and then the min function will give you the minimum value which in this case is negative one so those can be useful if you are trying to do some um some maximum minimum comparisons or calculations based on those okay let's talk about characters characters actually are just integers integers but they have special syntax for typing them into the language so um you usually use the question mark in front of a letter to encode a character in emacs lisp syntax so if we were to evaluate this question mark a it's going to tell us 65 because 65 is the integer that represents the letter a in ascii now someone asked about the rest of this stuff that we're seeing after the value whenever a number is evaluated so since a number can be represented in a few different ways the result of the evaluation is just giving this hint that um there is a there are two different representations here i think this is octal representation and then this is hex representation and then there's the the character representation for that number so anytime you get a number as a result in um an ielm or in just doing regular evaluation numbers um interactively it will tell you this little bit of information at the end so that you know okay this is an integer of 65 but there's also these three other representations that are pretty common that you might want to know about so you'll see that a lot when evaluating these characters so the lowercase a has a different value because it's a different character it's lowercase it's not the same it's not the same actual letter in terms of ascii so that has a different letter there's also special characters in ascii like the new line character the slash n there's also slash t for tab and there's a bunch of other characters that fall in this category you can evaluate those as well but you have to keep the slash in front of them like this so that they get evaluated correctly so here is slash n it tells us that it is uh number 10. the funny thing is that it tells us also this resolves to the control j character because emacs uses ctrl j as like next line or new line basically so sometimes you may see something that doesn't line up with what you originally put it in but that's because emacs is interpreting it in terms of what it knows that a character to stand for um you can deal with unicode characters as well uh using these various syntax uh all four of these lines resolve to the same unicode character they're just different syntax to get to that character so you may need to use different syntax based on how you um like where the character is in the unicode table um so i'm not going to evaluate those the values are here but basically it's just a matter of how wide the unicode character is because there are different widths basically like in there four but four bytes or eight bytes i might be saying that wrong um but uh it's good to know that there are there's there's a normal set of unicode characters and there's like an extended range of unicode characters and then you would use one of these based on whether you needed that extended range to be able to refer to that character you can also refer to these characters by their their name so a lot of these unicode characters have some kind of name to describe them in this case this character is called latin small letter a with grave and you can put that inside of these curly braces to describe it so if you know the name of the unicode character you can also look at look it up that way there's also uh control and meta character syntax and this shows up a lot when you're doing key bindings um some you you often won't see it because you usually usually excuse me usually using a function like kbd which turns a string representation of a key into the underlying representation but if you need to use the actual uh character coding for the key binding or for the control c or the meta something you know control whatever meta whatever this is the kind of syntax you would use for that so control c returns three and then uh kbd of control c returns control c but that's really just the same value in the end it's three meta x returns a number that is pretty large i don't really know where that comes from and then the kbd of meta x returns an array containing that number because kbd is actually dealing with key sequences so it returns an array that says what the sequence of numbers are for those characters uh i've got a link to the manual here for more information if you need that as well so there there are some very basic comparisons that can be done for characters just equality are they the same characters so in this case we're checking a against a and they are true for sure uh we can also do the comparison of the letter against the integer that it represents so a and 65 which returns true because the question mark a resolves 265 one interesting interesting thing here is that care equal will return true for characters of different capitalizations so a and a here is also going to return true however this is controlled by the variable called case fold search so case fold search is true by default i think i mean on both computers i've tried this on it's been true by default if we look at the documentation for that using ctrl h v or describe variable it tells us that if it's non-nil searches and matches should ignore case so basically this dictates whether comparing a character a string is going to take case into account so if we were to turn that off by evaluating set q case fold search nil and then we ran this comparison of a and lowercase a again it will tell us nil for false because they don't they're not equal anymore so uh i will turn that back on to t now just so we don't have any trouble later all right so now we're going to talk about sequences and this is where things start to get interesting because now we're not dealing with single values anymore we're dealing with um multiple values that could be used as a list or an array etc is everybody seeing everything fine on the stream i just noticed not much activity in the chat i just want to make sure that everything is good so um there are multiple sequence types in emacs lisp and the ones that we're going to be concerned with today are strings lists and arrays they're all considered to be sequences so um first of all what we kind of want to know is whether something is a sequence so since we've said that strings lists and arrays or sequences we should be able to evaluate with a predicate to check all of those so we're going to check sequence p first so sequence p on a string returns true sequence p on an empty string also returns true because technically speaking it's uh it's a string thanks everybody for letting me know um now sequence p on a list will return true because it's also a sequence uh sequence p will return uh true on an empty list because it's still a list same thing for arrays um now if you put anything else into sequence p that's not a a sequence type of some sort like an integer or a character is going to return nil because they're not lists so anything that you can you can treat as a sequence will return true from the predicate sequence p uh so let's let's talk about one little interesting aspect of this though what do you expect to happen whenever i say sequence p of nil well you would think it's uh it's false but actually it's true if you evaluate that it returns true and that's because nil can be treated as an empty list in some cases so in this case sequence p is returning true because nil could be considered an empty list we'll talk about that a little bit more in a bit so you can get the length of any sequence with the length function so this works on strings it works on lists arrays and anything else that's considered to be a sequence so if i run length on the string hello with an exclamation point it returns six characters long linked on a list of three items returns three linked on an array or vector of four items returns four and then length of the nil value returns zero because it is considered to be an empty list so um that is pretty useful because you do need to find out what the length of a list is in a lot of cases especially to be doing calculations on those lists so you can also get the element of any sequence type at a zero based index with the elt function which stands for element now for people who don't know about zero-based and one-based indexing of uh of lists or arrays the idea is that normally whenever you are counting if you have five items uh you as a human being are going to count them saying one two three four five however in many programming languages uh you don't actually use one to refer to the first item you use zero instead so if you have five items to to index those you use zero one two three four instead so that is an important thing to know whenever you're using the elt function because if you want the first item of a sequence you need to give 0 as the index you ask for so we will show that in examples right now i think so we're going to ask for element one of the string hello when i evaluate that it returns uh the character e it's returning 101 but if you look at it has the the string representation or sorry the um the representation of the character e with uh question mark e um now if you ask for the negative one element of the string hello it's going to give you an error saying that it's out of range did that just no okay i evaluated the wrong line yeah so eval error args out of range so the string doesn't have a position negative one because there's nothing before zero because there's nothing there you know it's just the string hello and zero is h in this case so uh there will be range checking in some cases now for lists if you ask for uh element number two it's going to give you one so let's say we're at and element number two is actually the third element since we're doing a zero base so zero one two and one is the third element in this list so basically which whichever element that you want just subtract one from that in your mind and that's the one you're asking for so i want the third element so if i subtract one i'm asking for number two um also if we ask for something that's out of range so in this case we're asking for three which is actually the fourth element since there's no fourth element it's going to return nil for the list just because um actually let's try five because there's a reason why the last one would work okay so it's still nil so basically if you ask for anything out of range with a list it is going to give you nil now we can ask for negative number indexes on lists but actually what it does is only gives you the first item no matter what so it doesn't go backwards in the list and get you something from the end it only gives you the first item anytime so with negative one i get three with negative two i get three with negative six i get three because they're all just returning the first item in that list which is 3. so for arrays or vectors which is basically an array the same thing works basically where you ask for item 2 which is 3 in this case and then also if you ask for things out of range you will get an error because an array is a fixed number of items and then there's there's nothing outside of that range of items all right so uh now that we've talked about the basics of sequences we're going to talk about strings which are a string is a sequence or an array of characters so we've seen this already you know a lot of times where we just deal with strings so i am going to evaluate the string hello and it's going to return hello and as we mentioned in the previous episode whenever you evaluate the string hello you're going to get hello back with quotation marks around it because the string representation of a string in emacs lisp has quotation marks around it so that's just the way that it that it works you're not going to get a string with no quotation marks same thing for um multiple line strings you can use a single slash i i think this is forward slash someone correct me if i'm wrong um it's the one above the enter key on the us keyboard uh if you use that slash then you can put a new line in the string and then have like a multi-line string so if i were to evaluate both of these lines together it's going to give me hello system crafters and it's not going to have a new line in it unless i actually put a new line character in the string i believe yeah so now i have a new line in the string okay so so tay says backwards slash so um similarly if you want to have an actual literal slash in the string you need to use two slashes so that you're doing something called escaping so when you escape a character in a string usually what you're trying to do is saying i i want this character to be literally in the string and not being used as a special character that indicates something like a new line or whatever so if you wanted slash n to be in your string you would want to put slash slash and then slash n which looks a little bit nutty but that's the way it works if i uh actually maybe i need to do multiple slashes here yeah that that's getting a little bit wild anyway basically you have to escape a slash before it will show up in the strings if i go back to that that initial simple example then you'll see that now you've got uh two slashes oh anyway uh if i put the regular slash in here does it show up yeah it doesn't show up okay anyway something about the way this is printing out is is acting a little bit different than what i expect uh so victor says slash slash n let's see what that does okay yeah it still says slash literally which is interesting but uh but thank you victor all right so um let's go back to that all right so now we can also make strings so if you want to make a string that's five letters long that's some character you can do that with the make string function if i evaluate this basically what we're going to try to do is make a string five characters long with that are exclamation points because we're extremely excited about this episode then i can do that basically it just makes a five character long string with exclamation points you can also make a string out of individual characters using the string functions so here i'm calling string and i'm giving an arbitrary number of characters using the character syntax we talked about before and that creates a function sorry a string called hello with an exclamation point at the end um all right so for strings there are a number of uh predicates that you can use that will tell you some things about it first of all um there is just the string p predicate which is pretty obvious usually whenever you're doing predicates for a type it's just going to be the type name followed by p so in this case it's string p so string p on test tells us true because test the string test is a string if you say string p on one it says nil because one is not a string same thing for nil itself it will return nil because nil is not a string there's also a function called string or null p which will return true if the value is a string or a nil care nil symbol i'm not sure what case that's useful in but apparently it's useful somewhere and then there they have provided it for you also there's character or string p which will tell you if it's a string or a character representation and since we mentioned before that characters can be represented by integers also evaluating 65 with this function returns t because 65 is equivalent to that question mark a for the letter a and ascii also um since we said that a string is a sequence and also an array we can use the array p and sequence p predicates to see that a string actually is an array and a sequence so if we evaluate both of these they return true because an array is both a sequence and an array however a string is not a a list because it doesn't follow the same semantics as lists so for comparisons on strings excuse me um so we have a string equal string less than and string greater than there's other comparisons you can do with strings i haven't really covered them here because we were short on time but the idea is that if you want to see if two strings are equal you can use the string equal function if you want to see if a string is less than the other use less string less p or string less than character and then string greater than character or string greater p i think these symbol functions are aliases of the other functions that existed well before in emacs so string equal will tell you true for if for two strings of hello however comparing hello with all caps and hello with one capital letter does not return true because uh we're thinking of equality of strings in terms of how they would be sorted if if they're two if they're equal strings in terms of where they would be sorted then it would return true in this case so uh sorting of strings goes based on the numeric values of the letters involved and possibly also some lexicographical sort rules based on the language that you're using um in your editor i guess or the the string itself the characters in the string so in the case of hello and hello uh hello and hello are equal so one is not less than the other so if we use string less than it's going to return nil because they're basically equal but we have mellow and yellow here and the letter m comes before the letter y in the alphabet so if we evaluate string less than on this it will return true because mellow would be sorted before yellow in a list then we also have two strings that start with the same characters but one is shorter than the other so uh hell and hello so if i evaluate this it returns true because hell is shorter than hello which means that it would be it would come before hello in a list of sorted strings also string greater than uh same thing for the two same strings it would be nil because they are equivalent however if we use the same values we used before in string less than for string greater than we're going to receive nil for all of those because we know already that this the left one is less than the right one in these in these specific examples there's more information about text comparison in the emacs list manual in this link that i've provided here so operations on strings this is something that might happen pretty commonly for you whenever you are writing code in emacs list especially for customization etc you want to like find the substring of a string or maybe split a string into its constituent components or maybe concatenate a few strings together there are functions for that so uh substring will give you the a piece of a string based on the indices of where you're asking for and like we were talking about before with the elt function this is zero based so in this case i'm saying i want uh the subsection of the string hello starting at index zero and ending at index four if we evaluate this it returns hell because uh 2020 was hell no because uh zero through four is the first four letters of the the string so um substring of hello starting at one will give you everything after that or at that index and then after so we're basically skipping index zero and just taking everything from um from one four so that returns hello now um concatenating multiple strings uh you can provide as many strings as you want to this function and it will basically just jam them all together and return a single string out of it so if i evaluate this function it's just going to return hello system crafters all as one string and then concat by itself with no parameters we'll give you a an empty string basically so that's one way to get an empty string if you uh are lazy i guess it's more lazy to just type quotation marks that are empty so anyway uh split string will split based on a predefined splitting pattern so basically split string takes an input string and then takes these a pattern to split by it's actually a regular expression uh we won't talk about regular expressions in any depth in this episode but in a future one we will definitely cover it so by default it's going to be splitting based on white space so if we evaluate that line it's going to give us hello system crafters all as individual items individual strings in a list now if we say hello system crafters and use the lowercase s to split them it's going to give us the parts of this string that don't have s anymore because we've split based on s but as you notice we use lowercase s but it also split on the uppercase s in system so if we run with eight in an uppercase s it does the same thing this goes back to this case fold search variable again when you're matching against a string if case fold search is set to true then it's going to split using case insensitive search meaning that the case will not will not be considered it will take lowercase or uppercase just the same if we set case full search to nil and then go back and do that lowercase s split again it will leave the capital s in but only split on the lowercase s so that's the thing to keep in mind whenever you are using split string also you can do character classes so this is a very basic regular expression where we're saying we want to split the string based on a white space character a space and the exclamation point so if i were to run this it will give us hello system crafters and then an empty string at the end of the list if we want no empty strings to show up uh we can use a parameter of t at the very end of this call to split string and then it will take out any any empty entries that are created by splitting that string so let's see um so the default splitting pattern is basically any kind of white space character or tabs or new lines etc so it will catch most things that you would care about when splitting but definitely make sure to constrain those split characters a split pattern whenever you need a more specific splitting operation okay formatting i'm not going to spend very much time on this format is very useful for taking values that you have that aren't strings and then plugging them into a string using a template syntax in this case we're calling the format function with the string hello and then there's this percent d and percent s these are called format specifications and these are standing for uh like number or or integer basically and string so uh percent d is integer percent s is string and we're passing in these values to be formatted into this text so if i were to evaluate this it will give us hello 100 system crafters and then there's also you can you can pass in arbitrary things like lists as well if i evaluate this line it'll say here's a list and then one two three in the list syntax if you want to learn more about what you can do with formatting there's a lot more format specifiers you can use for like floating floating point numbers etc check out the manual page on that similarly you can use the message function to write out uh strings that have been formatted in the same way to the echo area and the message buffer so it's kind of useful for debugging things sometimes or maybe showing a message to the user in this case i'm going to evaluate this and it's going to write to the echo area this is five and we'll also see this is five here because it returns a string as well and if we go look at the messages buffer then we'll see this is five right here at the end of the messages buffer so that's a way to write out some messages if you just want to have some diagnostic output or just output to the user and like i mentioned it uses the same formatting specifications as the format functions so those two things are pretty similar okay now let's talk about one of the most useful data types in emacs lisp which is the list lists are interesting because they are sort of arbitrarily expandable because they they're basically a chain of values so you're basically having a chain of uh like there's a value that's connected to a next value connected to a next value so there's this this chain of things if you ever ever used a programming language before or learned anything about data structures you'll know that this is called a linked list so in emacs list we build up linked lists using something called cons cells a const is basically a pair of two values and you may know of this as a tuple or a tuple in other languages but basically you create a const to have a left value and a right value so it could be one and two and it's just a pair so whenever you store this value you can get the left value or the right value out of it so if we evaluate this code here we'll see that const of one and two will return a this pair with this very special syntax it looks like a list but actually has a period in in the middle of it so 1.2 so that's not a list that's a cons and you can also type in this representation directly with the quote syntax so the single quote and then the open parenthesis 1.2 so that gives you the same thing so the idea here is that you can extract those values using the car and cutter functions now i'm not going to go into the background of why they're called this but this is a traditional lisp naming convention for a const cell so just get used to this idea and you'll it won't be a big deal to you so car gives you the left value excuse me card gives you the left value if we evaluate this it will give us 1 because 1 is in the left position and cutter gives you the right value so if we evaluate this it gives us two which is in the right position now this const and car encoder is the the basis for lists in a lisp language and it's pretty interesting um because we start dealing with recursive functions you can build up these lists recursively and do all kinds of processing on them however we're not really going to talk about that very much because that is out of scope for emax lisp we have a lot of helpful functions that can help help us with these things we don't have to really rely on recursion as much so we can store a const in a variable and we can also set the values that are in that const so i've stored that one and two pair in some const a variable called some cons now i'm going to use the set car function to change the car the left value to 3. if i evaluate this it's going to return 3 so we have to go and look at that variable again to see that now it's 3.2 or 3.2 3 and 2. same thing for the cutter we can use setcoder to set the right value for that we set it to four now and if i evaluate some const again is 3.4 so now you've got this variable that holds two values that you can set at any point and this gives you the ability to do things like manipulating uh list and whatnot as we start to build those up so now let's talk about building lists from cons pairs so um like we said a const pair is a left value and a right value well a list is actually just a chain of constants so in a list you have a constant has the first value which is the first item in the list and then the right value is another const pair that has a single value and a const pair so you're chaining these const pairs together where the first value the first value is always some value and the second value is always another const pair or nil to denote the end of the list so we can do this more literally by showing this example here where we have a const of one uh and then the the right hand value is another const which has two which has another const which has three which has another const which has four and nil once you do this this you have built a list of one two three four if we evaluate this you're gonna see uh oh i think i have an extra parenthesis yes you're gonna see one two three four so uh emacs lisp knows because all the internal representation of lists are const or const pairs that if you evaluate this kind of nested const pair is a list so it just treats it as a list and we'll print it back out as a list similarly you can build up a list by constanting a single value with an existing list because that existing list is a chain of const pairs so if we were to evaluate const one and the list of two three four we also get one two three four because this is an a valid list made of const pairs now if we were to try to const together a list with another list then it's not the same because uh the value on the left is not a single value it's another list so this can actually be valid in some cases if you want to do that but if you evaluate this you'll see that the first value in the list is a list of one two three and the second value is four uh similarly if we were to put let's say five six here and evaluate that we'll see that there the values of this list are a list of one two three and then four five and six so it is a valid list but it's not what you would think if you want to append two lists together you would instead use the append function which can take either a single value um which will const together the the first part of the list with the single value or it will if you take if you give it two lists it will append them together so that they make a single contiguous list so that's the way you can build up lists from const pairs so yeah we are going to be super long on the stream today i apologize for the link to this i really wanted to get through all the basics so we can move on to the interesting stuff in future streams so uh let's just quickly talk about the predicates list p will tell you if something is a list uh so and a list will be true a non something that's not a list will be false also there is a const p predicate for const pairs so if you give it a list or a icons it will return true anything else will be false so um let's move on to a list because those are interesting uh a lists or association lists are lists containing const pairs for the purpose of storing named values it's like key value pairs so um what if we set up this sum a list variable so if i evaluate this what we have here is a list of const pairs now this doesn't make this into a a single list because we have uh each item of the list is a const pair so you're basically making a chain of const pairs where the value in the left-hand side is const so when you do that you have this sort of association list where each value is a pairing of some name to some value or some some key to some value let's say in this case we are keying we have a key of one with a value of the integer one we have a key of two symbol two with the value of two and we have a key of the symbol three with the value three the integer value three now now that we've evaluated that we can use the a list dash get function to retrieve the value based on those keys the symbols in this case so if i were to evaluate this for the symbol one it would return the number one because uh the association between the symbol one is the value one same thing for two and three uh the symbol two and the symbol three they return two and three three respectively also if we ask for the symbol four which is not in that association list it gives you nil because it's not there um you can also get the pairing that corresponds to that key by using the assq or the uh association q function i guess what they call it if you evaluate that it will give you the pair four one and one basically the symbol one and the number one also you can use the rassq function to look up based on the value instead of the key so if i want if we want to know what pair is associated with what value we can evaluate this and it will give us one um so you may be asking yourself so maybe is there like an a-list set function to set a value a key value pair and an a-list well no there's not but there is a way to use the setf function to set a value in an a-list we're going to talk about set up a little bit more in detail in another episode maybe in one or two episodes next but um i'm just going to show you this example now so that you know set f takes a place and then a value and then sets the value in that place and in this case the place is the location of a list get one out of some a list i think what it's doing basically is it's retrieving um the the const pair for this and then setting the value in it so if we evaluate this it's going to change the pair of one and one to one and five and if i use a list get now to ask for the value for the symbol one it's going to give me five so i've successfully updated that value in the a list p lists are another thing that you can use as a type of key value pair list where instead of having these const pairs in the list you can just have a flat list where there's key value key value key value you will see this sometimes in emacs list but association lists are typically more common but if you want to get things from a p list we can just create one in line here with one and one and two and two if i evaluate this it's going to return one because we are we have a p list where the symbol one is associated with one and we're asking for what the value is for symbol one same thing for symbol two it will return two now for plus there is a simpler way to set the value here there is a p list put function that will allow you to add a value or change a value so if we were to say the value 3 and the number 3 and evaluate that now we will see that the list has been updated to contain the symbol 3 and the value 3 as a new pairing so we may go into more detail on plus as we we running come in contact with them later but right now we're just going to kind of skip past the rest of that excuse me all right so arrays arrays are sequences of values that are stored next to each other in memory so they're quicker to access so with lists before they're very convenient but they can also be slow to iterate on because they're sort of different pieces of memory that are all sort of chained together but with an array everything is next to each other in memory so that it's quicker to access however you can treat them pretty similarly in that you can create an array using very simple syntax and then you can excuse me you can use the elt function to get one of the values out of the array at a particular index you can also use the a set function which is stands for array set to set a value so we want to set the value at index one which is zero base so this is the second value second index change it to number five and if i run that it's gonna return five because the value that we set however if i if i evaluate some array you'll see now that it's one five three four because i change the second element to five um strings can also be treated as arrays you can set some string to the string hello and then we can change the first index 0 to m and then evaluate some string and now that's mellow so you can you can mutate the string the same way as you would an array because they're the same kind of type you can also fill all the values in an array using the fill array function so if you have an existing array like some array here that i'm going to evaluate now you can use filler rate to say i want to fill all the existing slots that array with the value 6. so if we evaluate that now we get 666 the number of the boost and if you look at summary then you will see that one more time okay so let's talk about logic expressions because um if you want to do anything interesting or useful in emacs lisp you need to know how to excuse me combine different logic to uh obtain some goal so all these predicates we've been learning about before are these comparison operators we need a way to combine those so we can do more uh elaborate logic checks whenever we're setting up our configuration or making our own packages so you can think of these uh of these as operations on the truthiness or falsiness of expression so basically they they are expressions that give you the ability to um look at the the nature of a value and then give you back something based on that so first of all let's talk about what is true in emacs list we're not going to talk about some philosophical idea of what what things are true or false but we're going to say what values emacs list considers true or false so when evaluating expressions everything except the value nil and the empty list is considered to be true even the number zero so that might be kind of confusing to you if you've been using other languages where zero is considered to be false in lisps typically the nil value and the empty list are considered to be false but everything else any other valid value is considered to be true so if we evaluate any of these things here um then they will all return true except for the last two so um the so if we check the the value t it's going to return true if we if we check the value five it'll return true if we check these two strings they will return true but if we check nil or we check the empty list they're going to return false now we're using the if statement here which i'll explain explain in a little bit but the idea is that knowing what values resolved to true or false is helpful in understanding how logic operators are going to work whenever you use them so logic operators these are basically ways to combine checks against the truth or falsiness of a particular set of values so the not function inverts the truth value of the argument so if the value is true and you evaluate that it's going to return nil and since 3 is also considered true if i say not 3 it's going to return nil however if i say not nil it will return t for true now we have also the and operator which returns the last value in the list if all of the expressions resolve to true so they all have to be true if any of them result in nil it's going to return nil immediately so in this case actually i probably should have done this instead let's try this in this case um we're going to have an and of four true values and then foo so if i evaluate this it's going to return food because food is the last value there let's actually try putting food here and then delete these two and evaluate this that returns true so like i was saying it's gonna return the last value that that was true in the list of values that were being checked so um similarly for one two three four five they're all true so it's going to return five at the end now it's going to break here when we try to do end of nil and something if we evaluate this it returns nil because the first thing it ran into was nil so as soon as it sees that no it's going to bail out and say okay we're done it's nil i'm going to return no because i know that it's nil we also have the or operator which will return the first value that resolves to true so in this case um we are checking the or of nil and the symbol something so whenever it sees that first nil it's going to say okay no problem let's see what else we have available to us so now it's gonna return something when we evaluate that because it is uh the uh the the truthy value that's in this list now if i were to put um t at the end here and evaluate this it's going to give us something again because it's only going to return the first thing that resolved as true in this list it doesn't care about the rest because as soon as it knows there's something that's true it's just going to return that directly so this can be useful when you are trying to check the a list of different function evaluations the values of those because it will not evaluate anything in that list until it reaches it so you could have a function here that that's like a mathematical equation or something that changes the value of a value a variable and it won't be evaluated until it needs to be evaluated so the short short circuiting can be helpful to you to save you some time whenever you're writing your code also let's see what was i trying to do here i don't even know what this example is supposed to be showing i think um yeah so i did two mathematical expressions sort of nested here this one is going to return zero this one is going to return true since 0 is truthy it only resolves the first one first and returns 0 because that one result as true all right so conditional expressions now we're starting into the point where we can change the behavior of our code based on whether something evaluates to true or false and we're getting close to the end here people so so thank you for bearing with me this long so the if expression basically evaluates a an expression and then chooses from one of two paths if the if the expression evaluates true it picks the first path if it evaluates to false it picks the second path so if we look at this expression here of if true what we're doing here is we're returning 5 if the expression is true because if t then 5 otherwise return run whatever comes afterward so if i were to select all this code and evaluate it it's going to return 5 because t is true so it will return the the truth branch for this if statement or if expression and that's another interesting thing excuse me thing to notice about emacs lisp is that if expressions are expressions it's not like an if statement in some languages where you have to like set a variable or return something the if if expression itself will return the value of the branch that got executed in the end so either the true branch or the false branch is going to return the value of the last statement or the last expression that was evaluated so in this case you can see that there are two expressions in the else case of this if expression there's a we're writing a message and then we're also doing two plus two if you were to go down here and look at this next example that i have uh oh i actually don't have one for that let's run this one so if uh excuse me if nil then five otherwise do message and then two plus two if we evaluate this what it's going to do is return 4 because it's going to return the value of 2.2 because that's the last expression in the else branch for that if statement so that is useful to know because then you can nest this if statement into some other expression so that you can more concisely express logic when you're assigning things or doing some complicated calculation you can do if statements like right in line inside of your computations which is pretty pretty cool so the the true branch in an if statement can only have one expression however we can use the prog in function to then make that capable of doing multiple expressions which is basically what progn does is uh progn basically says okay give me any number of expressions and i'm going to evaluate all of them then i'm going to return the value from the last expression that was evaluated so here we have a an if expression where we say if true then we do a prog n and we say message hey it's true and then return five otherwise we can have arbitrary number of expressions in the else branch so if i were to select all this and then evaluate it uh whoops wrong wrong keybinding uh it's gonna write the message hey it's true because we did that inside of the true branch and it's also going to return five so uh progn is the way to go if you want to have multiple expressions in your true statement otherwise you you can just call a function or just return a single value whatever whatever you want to do um all right so like i was mentioning before you can use if expressions in line when setting variables so if you really want to make your life difficult on mondays even more difficult than it probably already is then you can have something in your configuration that sets your tab width to a different value based on whether the day of week is monday so in this case we're checking to see if uh the string is equal the format time string for the day of the week with monday and if basically if this function tells us that today is monday then we're going gonna set our tab width to three so we can piss off all of our co-workers otherwise uh we're gonna set it to two so uh i'm not gonna mess with mine right now because i don't wanna have any trouble but if you really want to uh have some fun with yourself then here's a nice little thing you can add to your configuration okay so the when and unless expressions are kind of useful because they simplify the um checking for a particular condition and just doing a single thing like you don't care about the else case you only care about whether that expression resolves to true or false so um for for when when says that whenever the expression resolves to true evaluate whatever comes next and whatever comes next can be a series of expressions and as usual it will return the value of the last expression in that list of expressions so uh this win is only one line but it could be multiple lines after the the expression to be evaluated so we use when and then we have some expression like in this case is when two is greater than one then we want to return foo so if we were to evaluate this it will return foo now the unless function is the opposite of that so unless basically says unless the thing that um you see here is true run something so this can be useful whenever you're looking to say unless something has been initialized then run the initialize initialization code for it or something like that so in this case whenever this two greater than one gets resolved to true it's going to not run what's inside of it because it is looking for the value of nil so if i were to evaluate this it will return nil because when the when the when function or the unless function does not succeed in evaluating or getting the value it expects from the expression to evaluate it will return nil instead so we can see the contrast here when we say when one is greater than two return foo but since one can't be greater than two if we evaluate that it returns nil however for unless when we say when one or went unless one is greater than two return foo and in this case we evaluate that and it returns foo so these two functions are very useful for conditional code in your configurations and in your packages so definitely keep those in mind whenever you're trying to do this stuff and as i mentioned before you can have multiple forms inside of them uh and the last value is what gets returned so if i were to evaluate this whole thing here uh whoops if i evaluate this whole thing here it will return four because the last expression is two plus two which is four same thing for unless here um uh it also returns four okay so um let's talk about the con expression which is a more um capable type of comparison which lets you do multiple cases and then have different result values based on those cases so let's say that we assigned a variable a to the value 1 and we have this con expression where there is a a set of forms inside of this for each of the different cases so you have the the function called cond then you have the first list which the first item in the list is an expression to evaluate and then anything after that is a series of expressions that get executed whenever this evaluates to true so the first thing in this list of expressions that evaluates to true is going to dictate what uh sort of resulting expression or for set of forms gets evaluated so in this case since we set a to one this first case is going to get hit because it's equal to one so if we were to evaluate this it's going to return equal to one however if we change a to two it's going to hit the second case which is a is great greater than one so if i evaluate that it will say greater than one now if we make a negative one it won't be greater than one and it won't be equal to one so it's going to be something else so in the case that you want to do like an else case basically the catch-all or what what happens whenever nothing else is true then you can just put the value t because that basically is always true and if you evaluate this then it will return something else so that could be very useful for having a series of expressions that you're checking and then returning certain values for and as the same with the if statement or the if expression the con expression as you see here also returns the value of the last thing inside of the branch that succeeded so this can also be used in line in your other expressions to make more concise logic for things you're trying to do so uh the p case expression is very powerful it's kind of like a match expression for emacs list we're not going to go into detail now because we've already killed a bunch of time this this stream has already been going for about an hour and 10 minutes so let's skip on past that the last thing we're going to cover today is loops there are four ways to do loops in emax lisp the first one is the while loop so if you've ever used any other programming language before you've probably seen the uh the while loop before which basically is like as long as some expression evaluates to true just keep running if it ever evaluates to nil or false then stop so we're gonna set up a variable called my loop counter and we're gonna set it to zero and now we're gonna set a while loop and we're gonna check as the expression that keeps this loop going whether loop counter is less than five so since we since we start at zero we're going to keep looping until loop counter and is five now inside of our while loop we're writing a message to say what that loop is where we are in the loop and then we are going to set that loop counter variable to increment by one so that the next time the value is greater than it was the previous time so if i were to evaluate this loop now we don't see any value here because we're not returning anything at the end however if we go look at our messages buffer we'll see that it says i'm looping and it goes zero one two three four and we know that that's supposed to happen because um we're we stop anytime that loop counter becomes five so that is the while loop it's very simple and very useful if you have some loop you just want to keep going until some value becomes true now the same thing we just did is much easier with the do times loop whenever you have a certain number of times you want to run something instead of having to have an external variable that you set up with the value of the count you can actually use due times to set up a variable locally inside of this loop so here we're setting up the variable count and we're saying we want to run this loop five times so the value of count will be zero to four because it starts at zero as usual so in this case if we run this due times uh it will also return nil but if we go and look at our messages buffer it says i'm looping more easily because that's what we were writing with the message command that we were using before so if you are going to be doing a loop based on some number this is a much easier way to do that and finally if you uh excuse me my throat gets really dry during these presentations so i apologize for all the coughing and breathing um so if you want to do a loop on a list if you have a list already and you just want to do a loop on every single item of that list what you can do is use the do list function this function takes a list where the first item of the list is the variable name to use for the current item in the list and then the second is either a list or a variable containing a list so in this case this list is going to execute the body of this loop uh sorry this this function is going to execute the body of this loop for every item that's in the list that you pass into it so in this case we're going to write out item one item two item three item four item five so if i were to evaluate this and we go look at our message buffer we're gonna see that it says item one item two item three item four item five here because we're writing out those messages now um it tells me in the documentation that there's supposed to be a way to return a value from this do list but i think that if you were to so the idea is that the third item in the list of the specification of the loop is supposed to be a value to be returned or a variable to be returned but it seems that it doesn't work with the variable that is defined for that loop so if somebody knows about that definitely let me know and apparently i'm even setting this up wrong right now but uh the the idea being that you should be able to do this but it doesn't seem to work so let's just take this out and not cover that and finally the last way to loop in emacs list is to use something called recursion which is basically where a function will call itself any number of times to basically run that behavior in a loop so here we are defining a function called efs recursion test and we'll talk about function definitions more and probably the next episode or the one after for now let's just assume you you understand what i'm doing so we define a function that could takes a variable called a parameter called counter and a parameter called limit so counter is the um the current state of the loop and then limit is the amount of times that we want to do the loop so in this function we're checking to see if counter is less than limit so if counter is zero and limit is five we're going to check if counter is less than limit and then run the code inside of this using the win expression uh if that's the case so that's gonna write out this message message and then we're gonna call efs excuse me recurs and test again and we're going to increment counter by one when we pat when we call that function so that we're doing the incrementation of the loop so excuse me so now i'm going to run this function definition and i'm also going to run efs recursion test and uh we're going to go check our message buffer one more time to see if those are written and now we see i'm looping via recursion here so um this is um an interesting way to do looping in uh scheme i'm very familiar with doing this in scheme because this is sort of the primary way of doing looping and scheme however i wouldn't really recommend doing this very much in emacs lisp if you're going to be doing loops over very long lists because emacs list does not have the necessary optimizations to prevent doing recursion on long lists from actually causing an error in your program there's something called tail recursion we're not going to go into detail on that because it's kind of a funny concept but um you can use recursion if you're not going to do very much looping with your recursive function and it can be kind of fun to write these but more often you'll probably be using do list for a lot of what you do or due times so um that's all for what i was planning to cover today excuse me and thank you piotr for the uh the recommendation i i have some water here but i just i don't like drinking on camera so um so what's next i i think that there's there's two ways we could go one is we could either talk about um the p case and regular expressions to talk about matching of values and strings but i kind of want to jump into actually writing some code and and talking about like functions defining functions so i might do a side video um on the series excuse me geez for dealing with uh the p case and regular expressions just to sort of do a one-off thing but for the stream on friday next friday i'm totally losing my voice now i i think i want to do function so we're going to talk about that then so we're going to start getting into a real practical project at that point where we start writing a package from scratch so it's going to be a lot of fun i think all right so before my voice goes completely uh let's just thank my sponsors thank you so much sponsors i can't speak to you right now uh but if you want to learn how to become a sponsor check out the links below in the description and thanks a lot for joining today people i know this is a very long stream but check out the show notes at the end uh to to see all the details what we talked about today and uh let me know in the comments if you have any questions or if you have any ideas for what we can cover next time i promise the future videos will not be this long because we had to cover a whole lot today but we did that so we can move on to more fun stuff uh next week basically all right thank you so much everyone for being here today um and until next time happy hacking see ya you
Info
Channel: System Crafters
Views: 8,546
Rating: 4.9657145 out of 5
Keywords: emacs, configuration, emacs lisp, lisp, fundamentals, programming
Id: XXpgzyeYh_4
Channel Id: undefined
Length: 76min 12sec (4572 seconds)
Published: Fri Jan 15 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.