Projects
-
Advent of Code Day 14: That Won't Work
I guess finding the answer to part 2 manually is not going to work.
Imagine this GIF goes up to iteration 4999….
-
Composing Functions in Python
Beethoven did not compose any functions, that I know of.
I have not done a lot of functional programming, although someone I used to volunteer with was very into it. This weekend, while attempting to solve Advent of Code, I came back across some functional techniques.
I probably should have solved the day’s puzzle (a variation on the missing operators puzzle) with these tools. (Did I? Reader, I did not - I concatenated a giant string and then
eval()
ed it. I am a massive hack.) But let’s talk about composing functions, because I think it’ll be useful someday.What does it mean to compose a function?
Composing functions does not have anything to do with writing music. It simply means to create a function that returns another function as its result. (I have also heard this described as a higher-order function.)
So if you have:
def square(x): return x*x def add_one(x): return x+1
The normal way of invoking both of these functions might be:
x=2 x=square(x) #x is now 4 x=add_one(x) #x is now 5
But using composability, we could:
def compose(*fns): return functools.reduce(lambda func1, func2: lambda x: (func2(func1(x))), fns) square_and_add_one=compose(square,add_one) square_and_add_one(2) #result is 5
If this looks like witchcraft to you, it also did to me at first. Let’s break down what’s going on in
compose
.compose
takes one parameter,fns
, which is prefixed by the splat operator, which means we unpack each item passed to it into a list. (Similar-ish to...spread
syntax in Javascript). Then we use thereduce
function on the list.I’m much more familiar with a reducer from math operations. For example, if you have
[1,2,3,4,5]
and want to know the product of 1*2*3*4*5, you can write:nums=[1,2,3,4,5] result = functools.reduce(lambda acc, num: num*acc, nums)
Or in other words, for every item in
nums
, multiply it by the accumulated (reduced) result.1*2=2 2*3=6 6*4=24 24*5=120
Our
compose
reducer does the same thing, but instead of performing a multiply operation, it returns a new function whose function is to call the previous function.So if we do
square_and_add_one=compose(square,add_one)
the result is a function that first squares its input, then adds one to it. It would be the equivalent of:add_one(square(x))
Cool. Why do we care?
I initially thought I could solve the Advent of Code puzzle by composing functions. As I said, the puzzle was essentially the following:
Given the numbers (for example) 81, 40, and 27, what combination of multiplication and addition will create the desired total, in this case 3267?
With three numbers and only two possible operators, this is easy enough to brute force by hand, but of course the real challenge has 10+ digits in each line. I was hoping that I could get every combination of length n of the two operators (e.g.
"+,+,+,+,+,+,+,+,+,+"
,"+,*,+,+,+,+,+,+,+,+"
, and so on) and toss those into a compose, and see what popped out.This did not work for a number of reasons. One, because if you want your composed functions to take more than one parameter, you have to do some fancy work.
Two, and this is more important, I don’t actually want to do
add(multiply(81,40,27))
. What I want isadd(multiply(add(81,40),27))
and that subtle distinction is actually quite a big difference. I won’t say there isn’t a way to get that result with composing functions, because there is almost certainly a way to do everything, every way, in code. But by that point I’d been hacking away at the problem for a bit and I decided to just make a silly naive solution.I also think that unless you’re very careful, composing functions can lead to abstractions that are hard to read and debug, as cool as they look.
I am not sure I will be making heavy use of this technique in my own work but I’m glad to have messed around with it, if only to recognize this pattern when I see it in the wild.
-
Why I'm Not Doing Advent of Code (in Go)
I want to learn Go.
- another statically typed language would be good to have under my belt
- everyone seems to LOVE go
- I want to see what all the fuss is about and stretch my brain
Ergo1, I should do a bunch of coding puzzles this month in go, right?
That’s what I thought, until I actually started working with go. Perhaps embarrassingly, I didn’t know much about go before that other than the facts listed above: it’s strongly typed, and developers who use it love it, like Crossfit cult levels of love. Obviously I want to know what all that is about.
After I went through a few tutorials, I decided that I like:
- My god it’s fast. Go says “you won’t feel like you’re running a compiled language” and that is absolutely true.
- Go’s error handling feels a lot like the
Either
control structure in Java that we use a lot at work, so while I don’t have strong opinions on whether that’s the “best” way to do error handling, at least it’s familiar - Pointers (jk, I do not like these, but I should probably learn how to use them eventually)
However, besides those strengths, Go is not the best language for me for Advent of Code, which (in my experience) requires being fast, flexible, and a little bit hacky. This is the canonical way to reverse a string in go:
func reverse(s string) string { chars := []rune(s) for i, j := 0, len(chars)-1; i < j; i, j = i+1, j-1 { chars[i], chars[j] = chars[j], chars[i] } return string(chars) }
In hindsight, Go’s strengths are not those that serve one person doing silly coding puzzles for a month2. As I have now read, Go is fabulous for concurrency, memory management, for working on big codebases with multiple people, and for deploying across multiple computers, none of which I will be doing in December.
The other factor that worried me is that Advent of Code prioritizes speed. Not that I’m going to be hitting any leaderboards, but I still want to keep up with the daily exercises. I got to worrying that learning a new language while trying to be that fast might start me off learning bad patterns, and I want to learn Go correctly.
So for Advent of Code this year, it’s back to Python for me, which is great because I can always improve there too. The first day wasn’t so bad so far. And I’ve picked out a Coursera course on Go that I’ll be working through instead.
-
About The F*ck
Dunno how y’all are feeling lately, but I just have a lot of curse words on my mind. And by complete coincidence (actually no really), continuing with my theme of terminal tricks I have discovered the most perfectly named, magnificent app: The Fuck. It corrects your previous console command. All you have to do is install it and type:
fuck
.Here’s an example that I have already used (twice):
➜ git push fatal: The current branch master has no upstream branch. To push the current branch and set the remote as upstream, use git push --set-upstream origin master ➜ fuck git push --set-upstream origin master [enter/↑/↓/ctrl+c] Counting objects: 9, done.
(And yes I’ve done
git config --global push.autoSetupRemote true
but I just got a new work computer argh)It also works on typos:
➜ git stats git: 'stats' is not a git command. See 'git --help'. The most similar command is status ➜ fuck git status [enter/↑/↓/ctrl+c] On branch main Your branch is up to date with 'origin/main'.
I suppose I could make aliases for all my common typos but this is way easier. Also, it’s fun to type swears in the terminal.
It auto-configures itself after you install it and type
fuck
the first time, and even can configure itself withfish
(which I’m trying out on my work computer). Also, have I mentioned it’s fun to type swear words? -
Webpack, Explained by Someone Who Just Learned What It Is
Image by digital designer from Pixabay
What is webpack?
At a recent casual meeting of Women & Gender eXpansive Coders DC (a local group I’ve become involved with over the past year) a Python user asked me this question, and boy did I stutter out a non-answer. I think I said something like, “Webpack is a build tool that magically bundles all your Javascript for the web.”
Does that sentence actually mean anything? I mean, I think I got the basics down, but I did use the word “magically,” so negative points for that. Also, pretty sure I inserted about a million “um”s as well.
I work with Javascript pretty much daily at work, but I’ve never really put much thought into Webpack or other Javascript build tools. That’s probably a good thing – after all, it shouldn’t be something I need to think about – but I decided I should have a slightly deeper level of understanding of these tools that are ubiquitous in modern front-end development.
For this post I’ll be talking about Webpack exclusively, but know that it’s not the only tool out there.
Okay, but what is Webpack, actually?
(Most) modern websites need Javascript to run. (This site uses no JS, thank you Jekyll.) Javascript used to be just added to the top of each page where you wanted to use it:
<!--index.html--> <html> <head> <script src="notavirus.js"></script> </head> <body> ... </body> </html>
//notavirus.js window.alert("Your computer has been compromised! Click here to download our malware remover!")
And that worked fine for years. It was all we had and we were okay with that.