In this article I'm going to go through the process of improving some code. I'm mentoring a new developer who is applying for their first job. They were asked to complete some tasks on Codility as the first step of the interview process. To get used to the platform they did the first example task, and I advised them on some changes. I'm writing up here the progression from their code to (what I think is) better code. (Since this is the example task, not a task used to assess applicants, I think this is ok to publically post.)
Building an understanding of code is one of the main tasks in software development. Whenever we want to answer a question about code—what is this doing? why doesn't it work? how can we make it faster?—this is what we're doing. I have found it valuable to consciously surface the strategy I use to answer these questions, and have categorized my approaches into three groups:
In this post I will discuss these different ways of understanding code and their benefits and drawbacks.
I recently led a training session where we implemented the rules for scoring ten-pin bowling in Scala. It makes for a good case study. It’s small enough that you can pick up the rules in a few minutes, but the dependencies between frames makes calculating the score non-trivial. I decided to implement my own solution which turned into an interesting exercise in algebraic data and finite state machines. In this post I'll describe my implementation and my process for developing it.
For my implementation I solely focused on scoring the game. I didn't implement any parsing code, as that part of the problem didn't interest me.
In preparation for a talk at NEScala I wrote this quick survey on the research on curriculum and pedagogy for teaching programming (curriculum means what we teach, and pedagogy is how we teach it). My goals are:
My survey is based on the published literature, but it's not a comprehensive document. I'm not an academic and I don't have the time (sadly) to read all the relevant literature. However I've linked to papers I found interesting or important so you can explore further if something grabs your interest. There is a lot of interesting research out there and the tiny bit I've read has made my teaching much better.
In a previous post I discussed the steps needed to compile a http4s web service to an executable with GraalVM Native Image.. It's natural to ask what tradeoffs are made by going this route instead of using the JVM. In this post I present several benchmark results I obtained comparing the Native Image executable to the running on the JVM. Read on to find out which comes out on top!
A recent project has involved serverless web services in Scala, which led me to investigate using GraalVM's Native Image tool to create native executables. In this blog post I describe the steps necessary to build a native executable from a simple http4s web service. There is also complete code accompanying this example.
A few weeks ago we wrapped up season two of ScalaBridge London. (For us, a "season" is an intensive series of meetings over a short period of time. Season two was six meetings in six weeks, but we might change this in future.) Here I want to reflect on what---in my opinion---were the good and bad parts of this season, and discuss what happens next.
I would like to measure the effectiveness of ScalaBridge London, but this raises some tricky questions. For example, what does it even mean for ScalaBridge to be effective? I'm not sure. I'm writing this largely as a way to organise my thoughts, and share with others who may be able to help.
In an earlier post I described our first run of ScalaBridge London. Now I want to turn to the future and talk about lessons learned and what we're planning for the next run. Some of these plans are more concrete than others. One of the great things about ScalaBridge is we're learning as we do it, and almost everything is subject to change.
ScalaBridge aims to increase diversity within the Scala community by providing training in Scala to traditionally under-represented groups. ScalaBridge London is, as the name suggests, the London chapter of ScalaBridge. A month or so ago we finished the first "season" of ScalaBridge London. Now is a good time to reflect on what we did and how it worked out.
Type classes and records of functions are two very similar tools that are available in languages like Haskell, Scala, and Rust. Given the similarity the question arises of which we should use. In this blog post I discuss when I think one language mechanism should be preferred over the other.
I recently gave a talk on teaching Scala. I first gave the talk at the Scala in the City meetup, which was a dry run for the version I gave at Scala Days. Take a look at my slides if this is of interest to you. My talk centered around five tips for teaching. Here I give a quick rundown of the tips and some references for further reading.
How do you write an abstract for a (industry) conference talk proposal? I like to use a three paragraph structure. The first paragraph gives a quick overview of what attendees can expect to learn if they attend the talk. The second paragraph gives motivation and background---why should attendees care about what I have to say? The third and final paragraph goes into more detail on the points I intend to cover.
Last update: 15 February 2020
I recently switched to Doom Emacs from Spacemacs. The Doom documentation is currently quite sparse, so I've posted here my personal notes on using Doom along with a description of my workflow (something I find vital but missing from most documentation). Doom might be for you if
I'm not going into detail on how Emacs works or basic Vim keybindings here---the focus is on the things I found different and useful.
This is a post about church and state, and how we can unite the two for a better world, while avoiding unfortunate side effects.
Political metaphors aside, this really is a post about Church—Alonzo Church—and how we can use his idea of Church encoding to unite pure FP and imperative OO to achieve, if not a better world, at least better code.
The interpreter is the über pattern of functional programming. Most large programs written in a functional style can be viewed as using this pattern. Amongst many reasons, interpreters allow us to handle effects and still keep desirable properties such as substitution.
Given the importance of interpreters it is not surprising there are many implementation strategies. In this blog post I want to discuss one of the main axes along which implementation strategies vary, which is how far we take reification of actions within the interpreter.
At the Typelevel Summit in Philadelphia I gave a talk about probabilistic programming, which I have recently been exploring. Probabilistic programming combines two great research areas that go great together---functional programming and machine learning (specifically, Bayesian inference). In this blog post I'll attempt to explain the basic ideas behind probabilistic programming. I'm assuming you, dear reader, skew more towards programming than statistics, but are not afraid of numbers. Hence I'll concentrate more on the programming than the machine learning side of things here.
I recently saw this image, taken from a maths test.
The student has been asked to represent 5×3 in terms of repeated addition. They have written 5+5+5. The teacher has marked this as incorrect and given 3+3+3+3+3 as the correct answer. Like many people, when I first saw this I thought the teacher was clearly wrong. After a bit of thought I realised they were correct, and after still more thought I realised this question raises a whole lot of interesting points.
So why isn't 3×5 the same as 5×3?
In a recent training course I was asked if Scala supports static or dynamic polymorphism. These are not terms I had heard before, so I had some homework to do. A bit of research showed this terminology refers to the same thing as early and late binding, which I'm more familiar with. So, here we have a quick discussion of early binding (or static polymorphism) and late binding (or dynamic polymorphism), and how it relates to Scala's polymorphic methods and overloading.
A major theme of this blog is design principles for Scala code. In the past we've talked about Scala mechanics like [sealed traits][sealed-traits] and general principles like [simplicity in Scala][keep-scala-simple]. In this post I want to discuss a very general principle called reification and show its application in two different domains: monad composition and stream libraries like Akka Stream.
I recently wrote about [keeping Scala simple][scala-simple]. That's something you have to work at. Let me explain.
While packing up to move house I came across my undergrad vector calculus notes. Although I, sadly, don't remember the definitions of div, grad, and curl I do remember that course as marking a turning point in my academic career.
In this post I want to explore the design of a type class solving a problem that came up repeatedly in my current project. It's fairly general, so rather than diving into the details of the project, I'll start with a few simple examples:
?.operator in Kotlin and Coffeescript is annihilated by
null, in that once a
nullis introduced the result is always
You don't have to venture far to find people arguing that Scala is a complex language, or that Scala needs to be more opinionated. Luckily I have plenty of opinions, specifically about how to make Scala simpler, and this is something I've been espousing in my recent talks at Scala Days SF and Amsterdam (slides here).
The problem with talking about simplicity is that it becomes one of those things like "good art" that's defined as "I know it when I see it." This provides no guidance. We need more precision. In this blog post I want to discuss complexity from three different angles and give concrete recommendations for creating simple Scala code.
You wouldn't think the Internet would need a an introduction to cats, but then this Cats is a Scala library, not a small furry bed-hogging mammal. Cats is the spiritual successor to Scalaz: a library of absolutely essential utilities you really want to be using in your Scala code. Compared to Scalaz, Cats is more modular and it is using some newer tools to make its code base easier to work with.
Cats is still a closer to being a kitten than the king of the alley, but it has definitely reached the stage where it is usable. In this article I'll provide a basic introduction to getting started with Cats.
My [recent post][sealed-post] on sealed traits had some great feedback but it was clear that I glossed over some points too quickly. In this post I want to go over a new trick I've learned for sealed traits and clear up some of the points I made in the last post.
Sealed traits are essential for idiomatic Scala code, but many developers are hazy on the details of their working. In this post we describe why you want to use them, and how to use them correctly to increase the quality of your code.
Understanding monads is a puzzle with many parts. Understanding the monad interface was easy enough for me, as I'd been programming in functional languages for a while when I first started exploring them, but for a long time I didn't understand how they made IO operations pure. The answer is to add an extra wrinkle, usually glossed over in Haskell oriented sources, by making all IO actions lazy. It this article we're going to explore how this works and undercover some surprising relationships to the free monad, which we have been covering in [recent][free-monad-interpreter] [posts][free-monad-deriving].
The free monad is defined by this structure1:
sealed trait Free[F[_], A] final case class Return[F[_], A](a: A) extends Free[F, A] final case class Suspend[F[_], A](s: F[Free[F, A]]) extends Free[F, A]
We can use the free monad without understanding its implementation, but to really understand it we need to know why it is defined this way.
It certainly wasn't obvious to me why this is the correct definition, and reading the literature quickly devolved into "doughnoids in the category of pretzelmorphisms" land. Here I want to present an explanation aimed at programmers that doesn't involve abstract alphabet-soup.