SBTB 2015: Jason Arhart and Marconi Lanna, Powerful and Elegant Scala one*-liners
Recording: SBTB 2015: Jason Arhart and Marconi Lanna, Powerful and Elegant Scala one*-liners
this talk is actually by my coworker Marconi Lana he unfortunately couldn't due to a scheduling conflict couldn't be here to present it so I asked me to present it for him and we both work at originated and there's a lot of material here if the talk goes if the top goes well it's all in the presentation if it doesn't go so well to all the material so but there's a lot of material so I'm going to jump right in and hopefully I have time that's not formatting correctly it's already going badly ok so um I think we all can probably agree Jabba can be painfully verbose meagre hello world takes parently 129 keystrokes 425 if you use tabs pinned down with tabs done again with tabs it is the butt of all jokes Scala has a very powerful and flexible syntax that lets you write lets you write concise but not terse code very much very expressive code a single line of Scala code can leverage quite a bit of JVM power I actually think a line of Scala code is on average worth three or four lines of Java code slightly slightly paraphrased quote from a really old dilbert comic strip I wrote an entire database program using only one liners so let's see some of these powerful and elegant Scala one-liners using only language features and the standard library if we pulled in a library like Scala Z we could open up a whole new world of one liners but these are just from the standard library and all examples have been tested with Scala to 11 7 and Java 8 update 51 and apparently they also work on whatever i'm running so this is not code golf not that there's anything inherently wrong with code golf it's fun but don't use reproduction code this is not about writing the shortest code possible cryptic one-liners don't impress anyone code responsibility right for readability I think I think it was Martin Fowler said any idiot can write program can write code the computer can understand good programmers write code that humans can understand so keep that in mind apparently it was a lot of fun for Marconi to put this talk together I hope you have fun too and maybe even learn a trick or two I learned I learned a few things going through this talk which surprised me I thought I knew everything about one liners in Scala I hope you learn a trick or two for very large values of two all right the ultimate Scala one-liner the case class case class seriously case classes who doesn't know about case glasses but actually raise your hand if you don't know about case classes in Scotland so everyone now raise your hand if you know for sure everything that a case class gives you every single thing I actually thought I did I was wrong there's no there's actually no Scala dock for for what case classes give you apparently the default Scala doc page doesn't tell you much it doesn't give you any of the compiler generated methods or even the companion object even a simple case class with only a few parameters could take dozens of lines of scholar even hundred lines of Java undreds of lines of Java to write by hand so let's look at everything a case class gives you you get getters obviously we know that you get setters if you really really want them you can use var but seriously don't do that you get st. implementations of the methods from java.lang.object to string basically just prints out a string that could recreate the case class equals compares the values like you'd expect and hash code is consistent with equals it also gives you can equal which is what Scala adds to the protocol for equality to make object equality actually work right it gives you the copy method which lets you create a copy of the the case class instance and change only the values that you want so you should use that instead of making it mutable and it gives you serialization and deserialization it extends serializable and implements read resolve and it extends product this is one of the things I didn't know about about them extent the case class extends products you get product arity product element and product iterator I didn't even know those things existed and in the companion object you get the apply factory method obviously that's how most of us create in the case class instances and then arguably the reason for case classes existing the UH apply they are called case classes because you use them in pattern matching and another thing that I didn't know case class the actual companion object go away the actual companion object implements implements function so you get curried into pulled methods a downside of course case classes can't be subclassed by other case classes that wasn't always the case up until Scala 2.8 you could and it caused all sorts of problems and I think they just decided it was the wrong thing to do and just don't allow it anymore so let's see some examples and I'm going to run this so we define a case class person with a name and an age and flag for whether the person is deceased but which should seems a little bit morbid to me but maybe it's a Brazilian thing Marconi's Brazilian or from Brazil he's actually international but lives in Canada so we can create a we can create a person called Jim who is 27 and still living and then on his birthday we can replace him with a copy of himself that is one year older and we have product elements so we can get the peat we get the values out of out of this case class by index but of course it's untyped because there's no way to make that tight and product iterator will iterate over those things again untyped and then because because the companion object is a function you get tuple so you can take all of the parameters to create the case class wrap them up into a tuple and create it that way and you can also you can also curry it because it's a function and build the person up piece by piece and of course apply them all at once so let's look at some extension methods on Java types one of the cool things about Scala is you can add methods to existing classes so that's used in the standard library to add useful methods to the existing Java types so for let's look at some of them on numeric types you can get the absolute value of a number you can get the men in the max of two numbers actually more than two also you can get the sign num which is basically it's negative 14 negative numbers positive 14 positive numbers and 0 40 which I'm sure that's useful somewhere you can you've got methods to create ranges you can create use to to create an inclusive range until to create an exclusive range and you can even use by after that to change the step of the range let's look at floating oops so good float and double so you have you have ceiling which moves up to the next highest whole number floor which moves down to the next lowest whole number round which moves through the closest whole number and turns it into an integral value to n which turns it into an int x just throwing away the fractional part you can also convert between degrees and radians interestingly for some reason if you convert an integer to radians you get a float and not a double not sure why that is you've got some predicates you can check if it's valid in which means it could be converted into an int without losing any information so only whole numbers that will fit into an int our valid ends and you also have is hole which just tells you whether it has any fraction whether it doesn't have any fractional part and characters char we've got some we've got some extension methods on part we've got predicates to determine what sort of character is a digit is the letter letter or digit we can check if it's white space we can check if it's upper or lowercase then we've got methods to convert to lower or upper case and finally you can actually create ranges of characters as well as enters integers all right string see what it adds to string you can multiply string by an integer to basically get that string repeated and concatenated as such you can capitalize a string you can compare ignoring case if you have a multi-line string you can get the lines out it returns lines returns an iterator so or will convert it to a list here to see it in the repple and in scala string is a collection of char and in most ways behaves that way so you can map over it you can use exists and for all so next looks look at array in Scala and array is just a Java array if you create an array it's just a Java array but of course scala gives you a bunch of extension methods for erase that make a mac like most other collections so you can map over them you can get the sum so let's look at collections cool thing most Java collections can be basically basically turned into the Scala equivalence just import Java converters to report everything from Java converters and then that gives you as Scala for the Java collections and it also by the way gives you as Java version for the Scala collections that can be converted into equivalent Java collections useful when when you're forced to work with Java libraries all right let's get some idioms common to most collection types and we'll use as an example collection here sequence that is the sixth row of Pascal's triangle so you can of course map over map a function over a sequence there's a cut a number of different ways to do that here we're showing a couple different ways to do with point freestyle or point less style if you don't like it you can you can reduce here we can reduce with plus to get the sum but you could just use the sum method better way to do it similarly we can reduce with multiplying to get the product or just use product if we define a predicate than we've got some got some methods we can work with predicate so we can check if check for the existence of something that satisfies our predicate here we can check whether everything in the sequence satisfies the predicate this case doesn't so we can find out exactly how many items in the collection satisfy the predicate count and we can even find the first element that satisfies the predicate so get filtering and grouping you can you can filter use filter to get only the elements that satisfy predicate or filter not to get only the elements that don't satisfy the predicate if you need both at the same time you can use partition you can use group by to turn a sequence into a map it groups by the result of the applying the function to the sequence and then just gives you lists of everything that fits into that group you can use take while to get you all of the elements at the beginning of the sequence that matched the predicate and then drop while to do the opposite give you go through until it doesn't match the predicate and then gives you everything else and if you need to do both at the same time you can use span and you can even find out if you were to take use take while how many elements you would get with prefix length you can check for the existence of an element within a collection with contains you can find the index of an element from both will be either the beginning with index of or from the end with last index of 15 appears twice in the sixth row Pascal's triangle you can you can do you can use a predicate instead of looking for a specific element with index where and last index where you can check whether a sequence starts with a subsequence or ends with the subsequence which starts with and ends with and you can use contain slice to see if it has that sequence as a sub sequence and use index of slice to find where it is you can get the maximum value from a sequence or the minimum values from a sequence with max and min and you can even use you can use max by with a function to in this case we want to find the max by the person's age you can use sorted to sort the sequence you can use sort with to use a different comparison function sort in this case where we reverse the comparison to get the reverse sort order and you can sort by you sort by to use a particular function to say what's sort by and you can of course just reverse the sequence and if you want to reverse the sequence and then map over you can use reverse map instead of reverse map presumably it's more efficient you can use grouped to these are these next two are a little bit tricky to explain groups just so groups in this case with three it takes the first three and then the next three and the next three and slightly different is sliding which takes which it's like groups but it only moves by one each time so you get in this case one through three then two three four then three through five and so on did i do sliding yeah okay so we can use that for example to find the first three consecutive elements whose sum is greater than 40 I'm considering what that's doing that's a nice and concise a little bit of code there make string you can actually use make string with with no arguments and just converts all everything in the sequence to a string with two string and then gannets it all together if you give it a single argument it uses that as a separator in the string and you can give it three arguments which are prefix separator and suffix as such you can check for intersection of sequences or collections of any sort of I suppose you can check for the difference between two sequences you have actual sets in Scala so the proper set so you can do dooset Union you can check whether set is a subset of another set you can get all of the subsets of a set including the empty set and the set itself or if you only want the subsets of a certain size you can give it an argument in this case we only want the subsets of size two you can find all the combinations of the sequence all the permutations and you can get only the distinct values you can remove all the duplicates with distinct you've got this interesting thing called corresponds which takes a binary function and then checks whether corresponding elements between the two sequences all satisfy that predicate in this case they do and you can transpose a sequence of sequences this is it's exactly the same as matrix transposition okay lift deserves a little bit of explanation so a sequence is actually a partial function of its index to its values which makes sense a you know a function is a mapping from its domain to its codomain a sequence is a mapping from index to value so it makes sense that there it's a partial function lift takes lift as a method on partial function that lifts it into a total function that returns an option for so returns some some value for all the values for which the partial function is defined and then none where it isn't so if we can we can use lifts to try to get something from an index and if it's not there we just get none parallel collections we've got parallel collections in Scala they behave for the most part exactly like sequential collections except that operations are performed in parallel using all cpu cores or as many cpu cores as make sense so we do that by Justin we'd have the dot par method which turns a collection into a parallel collection and now it's kind of hard to can't really tell but some and map actually work in parallel now to compute this so presumably that window actually probably didn't go any faster but if you had a computationally expensive function you were mapping with those they would we can use for each here to sort of demonstrate that it's actually doing this in parallel because every time we run it we get a little bit different order alright let's talk about maps so with maps you can you have a function called get ur l or a method called get or else which if the value is not in the map you'll values in the map you'll get some you'll get that value in a sum otherwise you'll get I'm sorry that's what get does get or else we'll give you the value or if it's not in there it'll give you the default value that that you give as the actually the default expression you give as the second argument and you can in addition to all the other the normal collection methods you with maps you can do things with just the keys or values like filter just the keys or you can map over just the values and you can use a mutable map as a very simple in-memory cache using the method get or else update which is like it or else but if it's the or else it sticks it it actually puts it into the maps of the next time you'll just get it out which we can see here we've put we didn't have let's see I forgot what the demonstration here was the way I get her else update be with bug because the bee was already in there we got be okay you get the idea all right let's look at streams no one liner talk would be complete without a Fibonacci implementation or three so here's one gives you the Fibonacci sequence here's another this one's actually my favorite that is this is you see the cursor this here is actually the complete ooh complete Fibonacci well I guess I guess since it's recurse if you need the whole line but that's a pretty short Fibonacci sequence implementation which obviously works and then this one using stream iterate it's a little more complicated I don't like that one as much but those are three different Fibonacci implementation they're all different than the one I knew so all right how am i doing for time cool I've been blowing through this every time I practiced it I ran out of time when I got to this point okay putting it all together we got supposedly a pangram the quick brown fox jumps over the lazy dog that supposedly has every letter in it does it really lets check let's use for all and for all says it does but Marconi's very skeptical he won't believe until he sees it so let's use distinct and sorted to actually look at all the letters and look there they are a through z plus capital T in a space so how many times does each letter appear so we can group by the we can to lower the letter we can group by to see that this one it's kind of hard to see well I mean we can see the EU peers three times because we see three e's let's actually compute the frequency of each there now we actually see it as a frequency space peers eight times now let's remove the white space and save it in a value so we have it for the next slide we can sort it by frequency here nice now we see that the most frequent one is at the end o is the most frequent with four but we want the most frequent first so let's sort it with the the opposite comparison and there we see at the beginning Oh followed by e followed by T and let's only look at the letters that appear more than once and then format them nicely cool let's find all the words with the letter O so we'll use split to split on white space and or split on space get all the words and then filter those for just the ones that contain a brown fox / and dog and let's look at all strings that contain at least one of a set of keywords so here we've got some may be hypothetical headlines let's look for the ones that contain either scala or Swift we're both and Java 9 delay does not all right let's plot a horizontal chart but of our Pascal triangle sixth row so that's pretty cool we can we actually graphically see the numbers in the row let's add some value labels cool 16 15 20 now let's make it vertical pretty cool but I'd like to actually see all of the stars you spot the difference between these two anybody here let's make it so that everybody can see it yeah just equal versus greater than equal so now we get a proper charter like that so let's use some negative numbers here we're going to plot a sine wave that's pretty cool for that little bit of code huh and we can do the same with cosine all right extension methods but we can this is how we actually add our own methods to some we doing on time so we add our own methods to some existing classes so here we have stars we can add to int to get to just get a set of stars or a list oops the list of stars we can add is blank two strings if there any rails programmers out there this active support does this for Ruby strings so it is blank if it contains nothing but white space cool we can read the contents of a file very easily here's a we've got a file here with a bunch of characters from The Simpsons we can process a file line by line using get lines on the source let's put them out with line numbers cool we can select a little line at random with random dot next int cool we can run this several times and get different characters now we can fetch a line from the web so hopefully my internet connection is working great and we can read the news we're going to read some XML apparently that's a theme at this conference and we need some XML in every presentation but we don't want to actually read write xml XML is not as human readable as it was and it was advertised so I want to see just the headlines cool and importing instance members so we can actually we actually just we have our person Jim here we can actually import the instance method members of that and just refer to them as name and age there is a method in Marconi's random is plenty actually we actually don't remember what this is it what this is about oh just a bunch of next inside s next doubles get a bunch of doubles we can get we can get gout normally or Gaussian distributed values we can get bullion's get random bullion's we can get random printable characters pretty cool we can get random next string of a certain number of characters this is interesting we get we get characters like that pretty much every time but if we only want alphanumeric characters we can just say random alphanumeric I'm actually not sure what random dot alphanumeric by itself returns is that is that an iterator of some kind it's a stream okay cool even learn something just now all right you can shuffle shuffle sequences and another thing that I learned from this presentation you actually have console colors from this console thing so now we can actually make colorful stuff preconditions you have a pre you have a thing called require which which you can use for preconditions it's very similar to assert except it throws a different kind of exception you use require when require to use a web analogy exception storm by require kind of like 400 errors whereas assert would be like 500 years sir search things that should never happen so now we try to create a person with a with a basically only white space as a name I get an exception or with a negative age get an exception all right regular expressions regular expressions are very easy to create in Scala you just add dot R to a string but you want to use triple quotes so you don't have to escape all your backslashes and want to kill yourself like we did in Java you can extract this this is a really cool thing regular expressions have a nun apply method so you can use them as extractors take that pearl now let's do it let's parse some numbers part some string representations of numbers cool and we can even run system processes more stuff that I didn't know before this presentation you can import the Scala sis process that underscore and then you get things like bang to to run a string as a shell command Michelle you can use bang bang to capture the output very cool and you even got think you can even do piping and and ordering just I mean just like you can in a shell script I completely didn't know anything like I couldn't even imagine this existed very cool all right and I got through it excellent so this talk is actually on github at that URL and if you liked this talk you may also like other talks from the same author idiomatic Scala your options do not match kind of a rant about among other things using pattern match musing options and pattern matching that's he gave that as both a talk and a blog post on our originated blog and there are lots of other Greg blogs on blog originated calm and the somebody already asked even before the presentation about this this thing I'm using to do the presentation from a rebel and that's Marconi that's a thing Marconi wrote called represent which is on github it's very simple at this point I'm sure he would love pull requests and thank you very much any questions comments pretty straightforward all right great thanks guys enjoy