Bonnie EisenmanJekyll2021-03-30T19:29:08+00:00http://blog.bonnieeisenman.com/Bonnie Eisenmanhttp://blog.bonnieeisenman.com/bonnie.eisenman@gmail.comhttp://blog.bonnieeisenman.com/blog/dont-tolerate-isms-in-your-interviews2020-09-17T00:00:00+00:002020-09-17T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>My organization typically interviews in pairs: two interviewers, one candidate. This is beneficial for several reasons: it helps interviewers calibrate against each other, it frees up one person to take notes while the other asks a question, it helps the candidate meet more potential coworkers during the process. Sometimes it also creates an opportunity for odd observations.</p>
<p>I’ve had several interviews play out where I ask the technical question….and the candidate directs all of their answers exclusively to my male colleague.</p>
<p>Oh, dear.</p>
<p>The first – and most notable – time this happened, my co-interviewer started by verbally nudging the candidate to direct his answers to me. When that didn’t work, my coworker literally picked up his chair, placed it behind mine, and sat back down. The candidate continued to solely address answers to my coworker, craning his neck to avoid looking at me, even as I continued to ask him questions directly.</p>
<p>Even after that bizarre experience, I was surprised and relieved when my co-interviewer backed me up in the post-interview huddle. The whole time, I’d been questioning myself. This seemed absolutely absurd. Maybe I was making a big deal about something as mundane as eye contact. Maybe I was imagining it! Or, rather, I wished I was imagining it; that would be a nicer world to live in.</p>
<p>I’ve had several interviews since then where the candidate refuses to address me directly – avoiding eye contact, turning their back to me, sometimes failing to acknowledge that I’ve said anything at all. Invariably, they focus their attention on my (male, white) co-interviewer. It’s infuriating, every time. I’ve also heard enough similar stories, especially from women and Black engineers, that I suspect this is far more common than some people realize.</p>
<p>This happens notably less often now that I can introduce myself as a staff software engineer. I don’t think our candidate pool has become less sexist. I think that my title means that <a href="https://leaddev.com/harassers-are-nice-me-and-probably-you">assholes are more likely to be nice to me</a>. I’m missing out on an important signal now that I’ve become more senior.</p>
<p>If your more-junior or less-privileged coworker leads the interview, you might see some interesting behavior from candidates. Have them ask more (or most, or all) of the technical questions. See how the candidate reacts.</p>
<p>Don’t tolerate discrimination in your interviews. Sexist or racist behavior should be included in your written interview feedback. Condescending or arrogant behavior should be documented. It’s also grounds to end an interview early! I know this feels awkward. I know it’s tempting to come up with reasons to give the candidate the benefit of the doubt. But sexism, racism, and other kinds of discrimination <em>must</em> be a deal-breaker. Don’t force yourself or your coworkers to endure an hour of flagrant rudeness. And, perhaps most importantly – believe your junior colleagues if and when they report questionable interviewee behavior. They’re the ones most likely to see it, and it’s an important signal.</p>
<p><a href="http://blog.bonnieeisenman.com/blog/dont-tolerate-isms-in-your-interviews/">Don't tolerate -isms in your interviews</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on September 17, 2020.</p>http://blog.bonnieeisenman.com/blog/what-is-processing2020-08-21T00:00:00+00:002020-08-21T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>If you’ve delved into programming-for-art before, chances are that you’ve encountered Processing. It’s a phenomenally successful tool for coding for visual art.</p>
<p>Processing describes itself as “<a href="https://processing.org/">a flexible software sketchbook and a language for learning how to code within the context of the visual arts</a>”. It’s based loosely on Java, but it ships with its own development environment and code editor (the Processing “sketchbook”) and its syntax is not-quite-Java. These changes are primarily aimed at making Processing simpler and more accessible; the target audience has little to no prior programming experience. There’s no need to puzzle over the arcane incantation of <code class="language-plaintext highlighter-rouge">public static void main(String[] args)</code> in Processing. Instead, there’s a <code class="language-plaintext highlighter-rouge">draw()</code> function that somehow gets magically invoked when you run your “sketch.”</p>
<p><img src="/images/processing-gameoflife.png" /></p>
<p>Another simplification: if you use the Processing IDE, you don’t have to deal with imports. All of the files in a given “sketch” directory are somehow available to use. This makes it easy to introduce newcomers to Processing. However, as a programmer, I want to know what’s happening under the hood.</p>
<p>There’s some light documentation around this (see: <a href="https://github.com/processing/processing/wiki/FAQ#i-know-java-is-this-java-how-do-i-use-it-that-way">Is this Java?</a> from the FAQ) but not a ton of technical detail. For a while, I was still confused – is Processing a separate programming language in its own right, or is it just Java? Can I use a normal Java IDE to write Processing, or do I need to use the Processing IDE?</p>
<p>As far as I can tell, Processing actually consists of three pieces:</p>
<ul>
<li>a Java library</li>
<li>a Java pre-processor, which compiles the Processing language into normal Java</li>
<li>a coding environment (the “sketchbook” / Processing IDE)</li>
</ul>
<p>The pre-processor does some interesting things. Most dramatically, imo, it takes all of the code in a single sketch and shoves it into a single class. Any classes you declare in your .pde files are now <em>inner classes</em>. Also, your files will be concatenated in alphabetical order – so you can end up with e.g. conflicting definitions of variables. All of that content then gets wrapped in more boilerplate, which takes care of things like creating that nice PApplet popup window, running the drawing loop, and importing some classes like PConstants by default. This is neat on some levels (no worrying about imports! You always have access to a PApplet instance!) but can be a real headache if you need to debug something related to the pre-processor’s invisible magic.</p>
<p>In order to invoke the pre-processor, it seems like you need to either use the Processing IDE, or use one of the existing command-line tools like <a href="https://github.com/processing/processing/wiki/Command-Line">processing-java</a>. There is also a support <a href="https://py.processing.org/">Python “mode”</a> but honestly I don’t know much about how it’s implemented.</p>
<p>Another option is to use the standalone Java library from any other JVM environment, which means that you could use something like Kotlin, Clojure, or Scala. The tricky bit is that you’ll be missing any magic from the pre-processor or the IDE. Some considerations if you want to use Processing as a standalone library:</p>
<ul>
<li>You’ll need to subclass the <a href="https://processing.github.io/processing-javadocs/core/processing/core/PApplet.html">PApplet</a> class.</li>
<li>Some of the syntax is slightly different.</li>
<li>You’ll need to handle imports on your own. There are magical constants like <code class="language-plaintext highlighter-rouge">PI</code> that are available in Processing without needing to specify any imports; these are located in the <a href="https://processing.github.io/processing-javadocs/core/processing/core/PConstants.html">PConstants</a> class.</li>
<li>The Processing IDE handles a lot of Java classpath issues for you. Processing uses its own version of Java, not whatever Java you have installed on your system. Also, if you want to use the Processing library you’ll need to <a href="http://pages.cs.wisc.edu/~cs302/labs/EclipseTutorial_Processing/Step_02.html">add the core.jar file to your classpath</a>.
<a href="https://github.com/processing/processing/wiki/Supported-Platforms#java-versions">Processing 3.x doesn’t support Java 9 or later.</a> It doesn’t support all Java 8 features, either.</li>
</ul>
<p>None of these are insurmountable issues. The most difficult part is that the Processing docs all assume that you’re using the “full” Processing experience of library, pre-processor, and IDE. Luckily, the source code itself is fairly straightforward and well-commented.</p>
<p>Personally, now that I have a better understanding of the different abstraction layers at play, I’ve really been enjoying using Processing with Scala, using IntelliJ as my IDE and SBT for my build tool. I have a very small and poorly-tested <a href="https://github.com/bonniee/ProcessingSBTTemplate">template project</a> demonstrating this.</p>
<p>Using Processing outside of the standard “sketchbook” environment means that I can use all of my usual tools. I can write tests for my code, I can organize my code into many classes and files, I can use a full-fledged IDE where I’ve already memorized the keyboard shortcuts. I like using Scala because I already use it at work, so it’s a natural language to think in. You could also use Processing from other JVM languages, like Kotlin or Clojure. As an example, <a href="https://tylerxhobbs.com/essays">Tyler Hobbs</a> uses a Clojure library called <a href="http://quil.info/">Quil</a> for interacting with Processing.</p>
<p>So, in summary – Processing isn’t Java. It’s a Java library, and some tools on top of that. If you’d rather treat it like a Java library, then as a programmer, we can do that!</p>
<p><em>Thank you to Michael Noronha and Akiva Leffert for commenting on an early draft of this post.</em></p>
<p><a href="http://blog.bonnieeisenman.com/blog/what-is-processing/">Is Processing Java?</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on August 21, 2020.</p>http://blog.bonnieeisenman.com/blog/senior-work2020-01-31T00:00:00+00:002020-01-31T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>Software engineering is more than just coding. I hear a lot of questions from early-career engineers about what exactly constitues “work”, and how they’re expected to spend their time. They might say things like:</p>
<p><em>“I feel like I didn’t get anything done today. I didn’t write any code, I just did a lot of project planning.”</em></p>
<p><em>“I spent a lot of time today investigating this bug, but I don’t know if I should’ve spent that much time on it.”</em></p>
<p><em>“I’m not sure what my mentor does. They spend a lot of time in meetings, and it doesn’t seem like they commit much code. What are all those meetings about, anyway?”</em></p>
<p><em>“My manager says I’m not really a senior engineer yet, but I don’t know what that means.”</em></p>
<p>This last one might seem unrelated, but I think there’s actually an interesting connection there. Let’s talk about the differences between straightforward, difficult, and exploratory work, and who is expected to do which kinds of work.</p>
<p>Straightforward work is work where it’s obvious to the team <em>what</em> needs to be solved and <em>how</em> it should be done. This is often repetitive; there may be examples of very similar work that can be copied, and the systems involved are probably well documented.</p>
<p>Difficult work requires a deeper understanding of the systems involved. It may involve undocumented, unusual, or subtly complicated systems. Perhaps it’s a frustratingly elusive bug that needs to be understood and fixed. Or, it may involve implementing a change that doesn’t feel natural given the existing structure of the code. The team is probably clear on <em>what</em> needs to be solved, but it won’t be obvious <em>how</em> to solve it.</p>
<p>Both of the first two are types of <em>implementation</em> work. In both cases, the team agrees on what needs to be solved.</p>
<p>Exploratory work is a little different. It’s about framing problems and figuring out what should be done. Initially, both the <em>how</em> and the <em>what</em> are unknown; usually you start with a question, or a problem, and see where it takes you. You might start with something like:</p>
<p><em>“It seems like it takes us a long time to write new features. What’s slowing us down?”</em></p>
<p><em>“This system has a lot of bugs and is pretty fragile; it’s making our oncall rotations a nightmare. What should we do about it?”</em></p>
<p><em>“The product team wants us to build this new feature, but none of the engineers have worked on this kind of thing before. We need to do some research to figure out what kinds of approaches make sense.”</em></p>
<p>Exploratory work can be extremely impactful - a good recommendation here might save your team weeks, months, or years of wasted effort. It’s also easy to bullshit, because it’s difficult to measure or assess. In order to do this effectively, you generally need deep context on the systems involved as well as your team’s priorities. Figuring out <em>how</em> to solve the problem might be out of scope entirely - the goal here is to define <em>what</em> the problem should be.</p>
<p>I expect successful junior engineers to be able to do straightforward work (#1). Midlevel engineers should be able to tackle difficult work (#2). Senior and staff engineers will be able to do exploratory work (#3).</p>
<p>(There are other aspects that separate junior/midlevel/senior engineers - for instance, can you work alone? Collaboratively? Can you teach new engineers? Can you lead teams? Can you propose new projects and get buy-in for them? Do you follow through and clean up after yourself? But I’m going to set those aside for now.)</p>
<p>Depending on your company and your team, the mix of work required will vary wildly between 1/2/3. Some teams will have mostly #1, with some #2, and therefore even the senior engineers will spend most of their time writing code and implementing straightforward projects. My current team is probably a balance of mostly #2 and #3. (The larger/older/more complicated the codebase, the more likely you are to have #2 or #3 work.)</p>
<p>Exploratory work can overlap strongly with <a href="https://noidea.dog/glue">glue work</a>, as described by Tanya Reilly.</p>
<p>Much like with glue work, there’s a risk of doing too much exploratory, “problem-framing” early on in your career. It can take a lot of time and not produce a lot of measurable (i.e. promotable) artifacts. Also, your judgment simply won’t be as good, if you haven’t done enough implementation work in your team’s current domain. Often, it’s the pain points encountered while doing implementation work that lead to obvious questions to explore.</p>
<p>Doing exploratory work rarely helps support a promotion from junior to midlevel engineer, because exploratory work is largely irrelevant to the qualifications of a midlevel engineer. Most companies seem to define midlevel as “can this person accomplish tasks independently, within a reasonable amount of time, with minimal direction?” By contrast, a “senior” engineer is usually roughly defined as “can this person figure out what we should be doing, and make a good argument for it, and implement it?”</p>
<p>The division between senior and staff is even fuzzier, and depends a lot on what company you work for. As a staff engineer at a large-ish tech company, right now my job consists almost entirely of doing two things. First, I advise other engineers on how to approach implementation tasks, though I don’t usually do implementation myself. This includes a bunch of assorted feedback, mentorship, design review, code review, and brainstorming sessions. Secondly, I do exploratory work for issues that affect multiple teams.</p>
<p>This means I spend a lot of time learning more about problem domains; learning about individual team’s needs / priorities / motivations; learning about the history of different aspects of the company; and then, finally, synthesizing that into a sufficiently reasonable plan of action and convincing people that my approach makes sense. Sometimes, I do all of this research, only for my recommendation to be “do nothing, for now, for these reasons”. This is weird work! The hardest parts are often invisible, and difficult to verify. It often takes many months, or even years, to evaluate if I’ve done my job well.</p>
<p>The somewhat surprising takeaway here is that senior engineering work includes a <em>lot</em> of stuff that doesn’t naturally produce concrete artifacts…but that doesn’t mean it’s unimportant. Exploratory work is real work, too. That doesn’t always mean it’s the best use of your time (implementation has to happen eventually, right?), but don’t discount it as a valuable pursuit.</p>
<p><a href="http://blog.bonnieeisenman.com/blog/senior-work/">More than Coding: What is Exploratory Work?</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on January 31, 2020.</p>http://blog.bonnieeisenman.com/blog/non-obvious-accessibility2019-05-01T00:00:00+00:002019-05-01T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>Accessibility and ability are both complex spectrums. Many venues that claim to be “ADA accessible” aren’t actually accessible for all attendees with disabilities - or, perhaps, they’re only partly accessible.</p>
<p>As an example: I have intermittent mobility limitations and chronic pain. When I did a batch at the Recurse Center in its former location, the elevator-accessible door was often deadbolted shut in the morning, long after other participants had arrived. I’d have to balance the tradeoff between taking the stairs (painful, exhausting) versus taking the elevator and then banging on the door until someone let me in (differently painful, exhausting).</p>
<p>I was involved in a conversation a while back about how venues and event organizers can be more transparent about accessibility. Here are some suggestions I have for less-obvious accessibility questions:</p>
<ul>
<li>Is there room to sit? Is seating guaranteed?</li>
<li>Do chairs have backs?</li>
<li>Are attendees permitted to sit? (e.g. many bookstores do not allow customers to sit on the floor)</li>
<li>If this is a large venue, what’s the typical distance between activities? Is there a to-scale map available? Can attendees with mobility issues arrive early / leave early?</li>
<li>Is there a map of which paths through a space are accessible? Where are there heavy doors, or stairs?</li>
<li>What are the acoustics of the space like? Will attendees with sound-processing issues be able to hear? Will there be captioning?</li>
<li>Are there outlets available for charging? (e.g. some assistive devices or prosthetics need to be charged)</li>
<li>Will attendees be permitted to bring medications? (some music venues have attempted to confiscate my prescription medication)</li>
<li>Is there a quiet space available for attendees to relax and recharge?</li>
</ul>
<p>Obviously, this list doesn’t encompass what I consider the “standard” accessibility questions. (See the <a href="https://adata.org/publication/temporary-events-guide">ADA National Network planning guide</a> for detailed suggestions for event planning.)</p>
<p>As an organizer, the more information you can provide up-front, the more informed decisions your attendees can make about whether or not a space will be accessible to them at a particular time.</p>
<p><a href="http://blog.bonnieeisenman.com/blog/non-obvious-accessibility/">Less-obvious accessibility questions</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on May 01, 2019.</p>http://blog.bonnieeisenman.com/blog/a-software-engineers-guide-to-estimation2018-08-01T00:00:00+00:002018-08-01T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>Software estimation is one of those tasks that can feel like a distraction from the “real” work of engineering. In practice, though, I’ve found that making reasonable estimates for engineering tasks is a really useful - if mysterious - skill. So let’s talk about it!</p>
<p>I work on a team of ~8 engineers at a large company. Many other teams depend on our work, and we depend on many others. There is always more work to be done than we have time for, so prioritization and communication are crucial. Software estimates are one of the tools we use to help with project planning.</p>
<p>If I worked at a startup with a single engineering team, like my last job, my estimation process would be really different! But in the kind of environment that I work in today, I find software estimation useful for….</p>
<ul>
<li>Sequencing work: What can be parallelized? What work depends on other projects? Do your timelines make sense?</li>
<li>Staffing: again, what work can be parallelized? If it’s mostly linear, it doesn’t make sense to assign multiple engineers; conversely, parallelizable work benefits from having multiple engineers implementing it.</li>
<li>Forcing prioritization: there’s only so much time in a day (or week, or month), and a limited number of people per team. Having estimates helps you make explicit tradeoffs and identify the highest-impact work.</li>
<li>Outward communication: if another team really wants or needs something that I’m going to build, having a rough timeline is useful for setting expectations.</li>
</ul>
<p>In order to meet the above goals, we don’t need exact estimates. Here’s the granularity that I like to use (also referred to as “t-shirt sizing”):</p>
<ul>
<li>XS: tasks that take less than a day</li>
<li>S: a couple of days, no more than a week</li>
<li>M: several weeks</li>
<li>L: several months</li>
<li>XL: several quarters</li>
</ul>
<p>The above generally assumes 1 engineer working on a project. In practice, as part of this exercise we’ll identify which pieces can be parallelized. Then we can adjust our wall-clock estimate based on project staffing.</p>
<p>Of course, some kinds of work can’t be easily estimated. Exploratory work, where you’re working in a new codebase, or hunting for a bug, or doing some kind of novel project, will usually defy estimation. That’s fine! This is more relevant to work where you are already familiar with the systems involved.</p>
<p>Okay! Now that I’ve gotten the long-winded parts out of the way, let’s break down the formula. Credit to my former coworker <a href="https://twitter.com/alexcebrian">Alex Cebrian</a>, from whom I’m stealing these tips:</p>
<ol>
<li>
<p>List all the tasks related for this feature. Be as specific as you can, as you would break them into branches.</p>
</li>
<li>
<p>Assign how much time you think you would need to spend on each task with 1 day minimum. Nothing should be more than 3-4 days, if it is, it should be broken down even further.</p>
</li>
<li>
<p>Go back to whatever number you assigned on (2) and double it… Really.</p>
</li>
<li>
<p>Build a dependency graph between tasks. This will help you identify what can be parallelized.</p>
</li>
<li>
<p>Have you thought about time for code reviews? Go back to (3) and add 30% more, minimum one day.</p>
</li>
<li>
<p>Have you thought about time for testing? (Both unit tests & manual end-to-end testing.) For features which need end-to-end testing, add at least 1 day each.</p>
</li>
</ol>
<p>…and that’s it! I can’t stress enough how important steps #3 and #5 are, really, even if the estimate you end up with seems excessive. In practice, I’ve found that this approach does a good job of accounting for all of the unexpected problems that crop up in real software development. Did you need to do a minor refactor to add your new feature? Maybe you discovered a pre-existing bug that needed to get fixed? Or did you CI pipeline break just as you were ready to roll out your feature for testing? Those kinds of issues are entirely normal, so having a buffer for your “unknown unknowns” is really useful.</p>
<p>Okay. Now you have an estimate. What do you do with it?</p>
<p>This depends on your organization’s culture around estimation, project planning, and roadmaps, as well as what stakeholders are involved. Maybe you just share this with your manager, or perhaps you need to communicate this with other teams as well. The most nerve-wracking software estimate I’ve been asked to provide ended up being passed along to our CEO.</p>
<p>That probably sounds a lot scarier than it needs to be. I’ve most often seen these estimates being used to evaluate tradeoffs: “If we build Product A, it might take several months. But we can build Product B in a couple of weeks. Or we could build Product C, which will still take my team a few months, but we can unblock the other teams in about two weeks, and then we can develop in parallel with client engineers….” If your product managers or designers or executives are gung-ho about Product A but would still be happy with B or C, this lets them make more realistic choices about which direction to pursue. Crucially, in order to make those decisions effectively, your estimates don’t need to be precise; they just have to be accurate relative to each other.</p>
<p>This “formula” definitely isn’t scientific, but it doesn’t need to be. Hopefully, it gives you a starting point the next time someone asks you, “So how long will that take?”</p>
<p><em>Thanks to Laura Lindzey, Peter Lyons, Venkatesh Srinivas for their feedback on a draft of this post.</em></p>
<p><a href="http://blog.bonnieeisenman.com/blog/a-software-engineers-guide-to-estimation/">An Engineer's Formula for Software Estimation</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on August 01, 2018.</p>http://blog.bonnieeisenman.com/blog/fractal-streets2018-06-17T00:00:00+00:002018-06-17T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>I’ve continued to build on my <a href="https://blog.bonnieeisenman.com/projects/clojure-puzzles/">experiments</a> with two-dimensional generative art using Clojure. Here’s my latest batch of experiments: procedural generation of some squiggly lines. My favorites from this set look sort of like fractal street maps.</p>
<p><img src="/images/hyphae/14-streets.png" width="600px" alt="A blue curve that dips up then down." /></p>
<p>It starts from a handful of seed points, and then grows outward, avoiding collisions and gradually tapering off.</p>
<p><img src="/images/hyphae/stopmotion.gif" width="600px" alt="A blue curve that dips up then down." /></p>
<p>Here are some progress shots. To begin with, I drew “lines” of dots; then I actually joined them to make contiguous lines…</p>
<p><img src="/images/hyphae/03-branching.png" width="300px" alt="A blue curve that dips up then down." />
<img src="/images/hyphae/04-branching.png" width="300px" alt="A blue curve that dips up then down." /></p>
<p>Experimenting with various parameters leads to interesting differences.</p>
<p><img src="/images/hyphae/06-factors.png" width="400px" alt="A blue curve that dips up then down." /></p>
<p>The impact of angle of growth is pretty dramatic.</p>
<p><img src="/images/hyphae/07-angles.png" width="300px" alt="A blue curve that dips up then down." />
<img src="/images/hyphae/08-angles.png" width="300px" alt="A blue curve that dips up then down." /></p>
<p>Originally I was inspired by <a href="https://inconvergent.net/generative/hyphae/">inconvergent’s hyphae</a> post. Here are some of the more organic-looking images I made.</p>
<p><img src="/images/hyphae/09-trees.png" width="300px" alt="A blue curve that dips up then down." />
<img src="/images/hyphae/10-trees.png" width="300px" alt="A blue curve that dips up then down." /></p>
<p>When we smooth things out, we get something pretty interesting.</p>
<p><img src="/images/hyphae/11-streetlike.png" width="600px" alt="A blue curve that dips up then down." /></p>
<p>Let’s explore that more.</p>
<p><img src="/images/hyphae/12-streets.png" width="600px" alt="A blue curve that dips up then down." /></p>
<p><img src="/images/hyphae/13-streets.png" width="600px" alt="A blue curve that dips up then down." /></p>
<p>If we give them room to grow they fill in quite a bit.</p>
<p><img src="/images/hyphae/14-streets.png" width="600px" alt="A blue curve that dips up then down." />
<img src="/images/hyphae/15-streets.png" width="600px" alt="A blue curve that dips up then down." /></p>
<p><img src="/images/hyphae/16-streets.png" width="600px" alt="A blue curve that dips up then down." /></p>
<p>I’m pretty happy with how this turned out. I don’t know where I’m going to go from here with these sketches, but I think that I want to keep exploring this space of 2D visual, generative art.</p>
<p><a href="http://blog.bonnieeisenman.com/blog/fractal-streets/">Experiments with Fractal Streets</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on June 17, 2018.</p>http://blog.bonnieeisenman.com/blog/being-sick-at-work2018-03-15T00:00:00+00:002018-03-15T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>Workplace accommodations can be a fraught topic - what are you legally entitled to? How do you figure out what’s reasonable? How do you manage the emotions around <em>needing</em> help? I’m pretty happy with how I handle my illness / invisible disability / whatever-you-wanna-call-it at work these days, and thought I’d share some notes on what has and hasn’t worked for me.</p>
<p>My angle on this: I’m American, my experiences are coming from being a software engineer at a tech company. My disability / illness is usually invisible. I appear young and able-bodied. This gives me passing privilege, which is useful in many scenarios, but sometimes a hindrance. (Nobody will offer me their seat on the subway.)</p>
<p>Specifically, I have an autoimmune disorder, and I deal with chronic pain, mobility limitations, a suppressed immune system, and migraines. Usually this doesn’t impact my work: sitting at a desk is a pretty cushy job. Sometimes it does: I’ve had days where inflammation flare-ups in my joints made me unable to use a keyboard.</p>
<p>I’ve spent a lot of time working on skills to make it easier for me to exist in a professional environment. This includes figuring out what accommodations I need, how to ask for help, and what to tell my coworkers when they (understandably) have questions.</p>
<h2 id="things-that-have-worked-well-for-me">Things that have worked well for me:</h2>
<p><strong>Stating my limitations / accommodation needs as facts:</strong>
“I won’t be able to do $ACTIVITY because I have $LIMITATION”. “I’m going to sit down now.” “I need $ACCOMMODATION.”</p>
<p>My limitations are real, and it’s my responsibility to figure out how to communicate them clearly and succinctly. I try to leave as little room as possible for argument or interpretation, and to use the same tone I’d use for remarking on the weather. Keep things polite, friendly, and impersonal. I’m not making a request when I’m talking about accommodations; I’m stating a need.</p>
<p>(Unless I’m actually making a request for something that’s not essential to my job, like “Hey, I would love to participate in $EVENT, can you tell me if there will be $TYPE_OF_ACTIVITY? I have $LIMITATION. Thanks!”)</p>
<p><strong>Don’t try to hide my limitations</strong>: because my disability is invisible it’s often tempting to deliberately keep it that way, but this is an antipattern. Example: walking into a very large meeting where all the chairs are taken, and as the room overflows, people have switched to standing in the back of the room. I could also try to stand, but that’s a bad idea. Instead, I will sit on the floor, or - if I think my presence there is actually warranted and relevant to the meeting - I will ask someone to give me their seat. If people look at me funny, that’s fine. I will not pretend to be OK when I am not OK.</p>
<p><strong>Finding compromises:</strong> it helps if I can find ways to participate in the purpose of an event or task without doing it identically to everyone else. Do I have to stand during standup? No.</p>
<p>Another example: my department was planning an offsite to a shooting range during a time when I couldn’t comfortably lift…well, anything, really. Definitely not a shotgun. I still wanted to spend social time with my coworkers, though, since I was in a remote office, so I went along on the trip and just didn’t shoot. I didn’t explain myself beforehand to anyone but my manager (maybe I should have? yeah…) and some people were a bit confused. I explained why I wasn’t shooting if they asked. Everyone was good-natured about it. People take their cues from you, if you act like your accommodations are normal other people will tend to react similarly. :)</p>
<p>Relatedly, this often requires me being okay with making my issues visible.</p>
<p><strong>Being unafraid to ask:</strong> It’s better to ask for an accommodation and be told “Nope, we can’t do that because $REASON” than to suffer in silence. e.g. I noticed that my back pain was much worse whenever I was oncall, because I had to carry a laptop everywhere for two weeks. The damage I was doing to my back was pretty significant - I’d usually need an entire weekend of bedrest to recover. It took me way too long to realize that I could just…ask…for a second laptop to keep at home, so that I didn’t have to shuttle an extra five pounds back and forth. I felt guilty for asking for a second laptop (??) but once I asked, everything was great. I told my manager I thought it would help, she said “That makes sense!”, I talked to IT, and a week later I had a second laptop. Lo and behold, I no longer injure myself by being oncall.</p>
<p><strong>Participating in planning:</strong> If I’m the one planning an activity, or running a meeting, or whatever, I can make it suit me. This means: if I’m facilitating standup, we’re doing it in a room with chairs. (I once worked at a place that insisted we do standup meetings with actual standing once…so I would awkwardly drag a barstool over and scowl at the facilitator…that was frustrating.) My manager can’t read minds, and also isn’t nearly as familiar with my problems as I am, so if I can suggest solutions and help with the planning/logistics, everybody wins.</p>
<p><strong>Talking about my disability:</strong> like I’m doing here! I can pass as able-bodied, which means that if people don’t know that I’m sick, they’ll be pretty confused when I ask for accommodations. It’s better for everyone if it’s not some weird secret that takes them by surprise.</p>
<p><strong>Losing the shame:</strong> this one is harder, but it’s been important. I’ve cried in front of several of my coworkers; some of them have seen me on the verge of passing out after particularly bad incidents. My illness robs me of the privacy around medical stuff that I might otherwise wish I had. Treating this as matter-of-factly as I can makes it easier for me, and, I suspect, for them as well. When my coworkers ask questions about my condition, I answer as concisely and straightforwardly as possible. This is much easier now that I have a formal diagnosis.</p>
<p><strong>Believing other people:</strong> similarly, I try to model the behavior I want. I believe people when they describe their own experiences or symptoms. I remember that it took me a decade to get a diagnosis, and many people have confusing and sometimes contradictory stories about their own conditions. When I’m planning an event, I explicit ask for things like accommodation needs, and I try to take everyone’s preferences and needs into account.</p>
<h2 id="things-that-have-not-worked-well">Things that have not worked well:</h2>
<p><strong>Snark:</strong> I have a really dark sense of humor about my illness that other people don’t share - which makes sense! The line between “totally funny joke about me bleeding out” and “horrifying, triggering story” is really not obvious to people I don’t have a deep personal relationship with. And frankly, it’s probably not professional of me to let that bleed into the workplace. (Heh.)</p>
<p>I do fall back on snark when people start insisting that I can actually do $THING. Memorable conversation: my company was doing a trip to Six Flags. I love theme parks because roller coasters are awesome, but they involve way too much walking for me. One of my coworkers was really insistent on me going, so I finally snapped, “$NAME, I’ll go if you’ll push my wheelchair the whole day!” This was Very Awkward, but IMO I was just surfacing the existing awkwardness: my very well-meaning coworker was <strong>already making it awkward</strong> by not believing me about my own abilities. Sometimes a Bad Joke can snap people into realizing what they’re doing.</p>
<p><strong>Over-justifying myself:</strong> like many people, I get nervous about taking sick days, asking for accommodations, etc. “But I’m not REALLY sick,” I’ll think. “If I was just less LAZY I could SUCK IT UP and keep working.” Or, “If I just TRY HARDER, I can TOTALLY stand long enough to last through this meeting.” Sometimes this results in me over-justifying why I’m taking a sick day and sharing personal health details with way too broad an audience. Chill out. If I treat myself with suspicion, other people will too. Be honest, be direct, but also be concise rather than oversharing.</p>
<p>Speaking of which…<strong>oversharing</strong>! My idea of “normal mundane detail” is, for some people, “horrifyingly traumatic story”. It’s not fair of me to inflict emotional distress on my coworkers just because they asked how my weekend was.</p>
<p><strong>Trying to pretend nothing’s wrong:</strong> this is misguided and always screws me over eventually. It’s true that I can’t take a sick day every time I feel bad, but I also need to be honest about my limitations. Powering through will not make me a more productive worker. (No, self, you shouldn’t keep working when you have a migraine. All that code you write will be SHIT.)</p>
<p>Reframing this problem from “I’m lazy if I stop working” to “I have a responsibility to take care of myself and I will be more productive this way” has been very important to me. This one will vary a lot based on your team culture, your company’s policies around stuff like sick leave, and your particular disability/illness. Being able to say “in order to take care of myself, I need to rest today” is an immense privilege, and one I don’t take for granted. Still, even without super-generous sick-leave, being honest about what’s wrong is helpful. Maybe you can’t take a day off, but can you control something else about your work environment? (Take painkillers when you need them? Take a few minutes to do stretches or physical therapy exercises in your office bathroom? Work in a conference room with the lights off if you’re feeling photosensitive?)</p>
<p><strong>Hoping that other people will remember my limitations, and feeling betrayed/sad/offended when they don’t:</strong> I am the foremost expert on myself and it’s not reasonable to expect other people to 1) remember everything I tell them or 2) to internalize it. Healthy, able-bodied people might not realize that by scheduling a lunch meeting two floors away from the cafeteria, I will now have to plan around how to carry a tray of food through the building, because for me a lunch tray is actually a heavy object. It’s my responsibility to communicate directly when something doesn’t meet my needs, and to not assume fault or malice when someone forgets my needs or - much more common - just hasn’t internalized all of the implications.</p>
<h2 id="tldr-communication-is-important-️">TLDR; communication is important. ❤️</h2>
<p>A lot of this boils down to: be honest, be direct, be kind (to yourself, and to others). My coworkers <em>want to be nice people</em>. Being upfront about my needs and limitations makes it easier for them to be kind to me.</p>
<p>I’ve been really lucky to work with some fantastic people, who have supported me through tough times - and also have done me the huge favor of treating me like a Normal Person. I don’t want to be an Inspirational Cripple, yaknow? Everyone has needs, everyone has preferences, and learning to navigate them with honesty and sensitivity has improved my life a lot.</p>
<p><em>Thank you to Veit Heller, Julia Evans, Andrew Boot, and Vijith Assar for providing feedback on a draft of this post.</em></p>
<p><a href="http://blog.bonnieeisenman.com/blog/being-sick-at-work/">What I Know About: Being Sick at Work</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on March 15, 2018.</p>http://blog.bonnieeisenman.com/blog/unowned-code2018-02-17T00:00:00+00:002018-02-17T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>Recently, I needed to add a new feature to an unowned codebase at work.</p>
<p>What do I mean when I say unowned code? I think of unowned codebases as having a few qualities:</p>
<ul>
<li>There are no planned improvements or changes to the code.</li>
<li>The original author(s) are unavailable for questions. (Perhaps no longer working for the company, or nobody knows who wrote it, etc.)</li>
<li>While there may be people who have familiarity with the codebase, nobody is responsible for it.</li>
</ul>
<p>How does this happen? It’s not such an odd thing. You write some software, it’s useful, it sticks around. But once it’s feature-complete, or close enough—you move on. Not all software needs constant changes. Who owns it? Not your team, because they’re not investing in it anymore. It carries on, stewardless, borne ceaselessly into the future…</p>
<p>I don’t think it’s a bad thing to have unowned code lying around, but sometimes you do need to make changes! What happens then?</p>
<p>In my particular case, I poured myself a cup of coffee and settled in to read the code. My change was small in scope; I wanted an existing tool to handle a new kind of file format. The codebase that I needed to dive into was about 1,500 lines of Ruby.</p>
<p>I was reasonably lucky, because:</p>
<ul>
<li>I knew that this code is currently in a good state, i.e., it’s working (and has even been re-deployed recently! amazing!)</li>
<li>There is a README, explaining how to get it running locally, and it mostly works</li>
<li>There are comments in the code, and the structure is generally reasonable</li>
<li>There’s one other person left at the company (!) who’s read the code and figured out how to run & deploy it.</li>
</ul>
<p>That being said, there are some smelly bits. Not surprising, for a single-author, unowned codebase:</p>
<ul>
<li>There are TODOs scattered around that obviously will never be cleaned up.</li>
<li>You can see the organic growth of this code: there are layers of abstraction that probably built up as the author understood the problem space better. (I think this is a common single-author problem. Peer code review tends to strip this kind of scaffolding away.)</li>
<li>It’s difficult to fully onboard a developer - you need to track down one person at the company to get proper permissions setup (for getting a functioning developer environment with staging, deploying permissions, etc).</li>
<li>There are no tests.</li>
<li>There is a lot of dead code which never gets executed.</li>
</ul>
<p>Tackling an existing system like this isn’t so bad, especially when it’s reasonably-sized. Here’s how I handled it:</p>
<ul>
<li>Developer setup: can I run it in its current state?</li>
<li>Look through the git history to figure out if anyone still at the company has modified the code (there’s one other person, perfect)</li>
<li>Read the source code to figure out how the code is structured, and where I should add my new feature
<ul>
<li>this involves a combination of “start at the beginning” and reading from the entry point inward, as well as judicious use of <code class="language-plaintext highlighter-rouge">grep</code></li>
<li>incidentally, I’m not super familiar with Ruby, so I end up learning a lot about things like blocks</li>
</ul>
</li>
<li>Add my new feature, implementing it in tiniest-possible pieces and testing frequently on my local machine</li>
<li>Discover bugs in the existing code, and fix them</li>
<li>Continue implementing my new feature</li>
<li>Manually test that my new functionality works</li>
<li>Write some tests for the bugs I found, to prove that they haven’t snuck back in</li>
</ul>
<p>At this point, I now had Choices! I could clean up this code. In fact, as the most recent editor, I probably had the most context on this codebase, because I’d already dumped it into my head.</p>
<ul>
<li>I could write tests for all of it.</li>
<li>I could do some cleanup, like deleting the unused code.</li>
<li>I could leave it as-is, once I’ve added my new feature.</li>
</ul>
<p>Option #3 would contribute directly to the poor quality of the codebase, and in fact make it worse (there is now more code in this unowned little codebase, bah). But! It might be the right choice for the business. I had higher-priority things on my plate, and I could fully justify leaving this alone.</p>
<p>Buuuuut…..Option #2 isn’t substantially more effort. So that’s what I did: add a couple of tests around the new feature, delete some of the unused code, and call it a day.</p>
<p>This was a fun detour from my usual job! I enjoyed the process of dumping a bunch of new code into my brain and then poking at it until it did what I wanted, and hopefully I left things in a better state than I found them in. (But really…who knows?)</p>
<p>Every time I have to do this I remember that new codebases don’t have to be particularly scary; they just require patience, and some time to explore and poke around. Just because there isn’t a map doesn’t mean that you’ll get lost!</p>
<p><a href="http://blog.bonnieeisenman.com/blog/unowned-code/">Notes on Modifying Unowned Code</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on February 17, 2018.</p>http://blog.bonnieeisenman.com/projects/clojure-puzzles2018-01-13T00:00:00+00:002018-01-13T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>I spent the last week learning Clojure and generating jigsaw puzzles as part of my one-week programming retreat at the <a href="https://www.recurse.com/">Recurse Center</a>.</p>
<p>Why jigsaw puzzles? I was motivated by two things: first, I wanted a good-sized language-learning project. Secondly, I was heavily inspired by the amazing, beautiful, intricate jigsaw puzzles produced by <a href="https://n-e-r-v-o-u-s.com/shop/line.php?code=12">Nervous Systems</a> and wanted to experiment with similar-ish generative methods. (I’m a sucker for generative things and hadn’t played with generative algorithms too much before.) If you want a crazy cool puzzle, seriously, go buy one from Nervous.</p>
<p>I think they turned out well!</p>
<p><img src="/images/svg-puzzles/11-cat-whimsy.png" width="350px" alt="A black-and-white outline of a jigsaw puzzle. There's a cat shaped piece in the top left." />
<img src="/images/svg-puzzles/puzzle-cat-piece.JPG" width="250px" alt="A hand holding the cat-shaped puzzle piece." /></p>
<p>Because I have access to <a href="https://www.nycresistor.com/laser/">NYC Resistor’s laser cutter</a>, the obvious thing to do was generate SVGs which I could then laser cut. If you haven’t worked with SVG before, it’s an XML-based format for describing vector graphics. It’s pretty easy to generate “by hand”.</p>
<p>Here is what an SVG looks like, if you open it up with a text editor:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><svg</span> <span class="na">width=</span><span class="s">"100"</span> <span class="na">height=</span><span class="s">"100"</span><span class="nt">></span>
<span class="nt"><circle</span>
<span class="na">cx=</span><span class="s">"50"</span>
<span class="na">cy=</span><span class="s">"50"</span>
<span class="na">r=</span><span class="s">"40"</span>
<span class="na">stroke=</span><span class="s">"green"</span>
<span class="na">stroke-width=</span><span class="s">"4"</span>
<span class="na">fill=</span><span class="s">"yellow"</span>
<span class="nt">/></span>
<span class="nt"></svg></span>
</code></pre></div></div>
<p>This produces a yellow circle, centered at (50, 50), with a radius of 40, and a four-pixel green outline. You can view an SVG file in any web browser, or edit it in an editor like Inkscape.</p>
<p><img src="/images/svg-puzzles/00-basic-circle.png" alt="A yellow circle" /></p>
<p>See? Easy-peasy.</p>
<p>I started by generating a “classic” jigsaw puzzle shape, and figuring out how to tile it.</p>
<p><img src="/images/svg-puzzles/01-simple.jpg" alt="A single classic jigsaw puzzle piece." width="100px" />
<img src="/images/svg-puzzles/02-grid.jpg" alt="A grid of mostly-identical jigsaw puzzles" width="500px" /></p>
<p>But I wanted something more interesting than just a grid of similar puzzle pieces! My next step was to use a <a href="https://en.wikipedia.org/wiki/Voronoi_diagram">Voronoi diagram</a> to draw more irregularly-sized polygons around “seed” points. At first this created some amusing failures:</p>
<p><img src="/images/svg-puzzles/03-blooper-voronoi.jpg" alt="A grid of orange dots and some black lines between them. Something looks weird - the lines skew off in random directions!" width="500px" /></p>
<p>Oops. This is what happens when you draw points at (x, x) instead of (x, y). Let’s fix those coordinates.</p>
<p><img src="/images/svg-puzzles/04-voronoi.jpg" alt="A grid of orange dots, surrounded by black lines representing voronoi edges. Now they actually are enclosed cells, like they're supposed to be." width="500px" /></p>
<p>If we replace those straight lines with puzzle-piece edges, we get something that starts to look like a more interesting puzzle. There are still obviously flaws to be ironed out here (e.g. edge overlap).</p>
<p><img src="/images/svg-puzzles/05-simple-voronoi-tiling.jpg" alt="Similar to the previous image, polygons constructed by voronoi tiling then have their edges deformed using puzzle-piece-like squiggles. There is some overlap between lines so this would not make a good puzzle." width="500px" /></p>
<p>I wanted to make more novel puzzle piece shapes, though, so I turned to the SVG <code class="language-plaintext highlighter-rouge">path</code> type. You can draw Bézier curves in SVG pretty easily:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><path</span> <span class="na">d=</span><span class="s">"M 0 0 C 0 -100 50 -100 50 0 S 100 100 100 0"</span>
<span class="na">stroke=</span><span class="s">"blue"</span>
<span class="na">fill=</span><span class="s">"transparent"</span>
<span class="na">transform=</span><span class="s">"translate(0 400)"</span><span class="nt">/></span>
</code></pre></div></div>
<p><img src="/images/svg-puzzles/06-01-bezier-blue.png" width="200px" alt="A blue curve that dips up then down." /></p>
<p>OK, here’s what it looks like when we replace our puzzle piece shape with some random-ish curves:</p>
<p><img src="/images/svg-puzzles/07-simple-bezier-tiling.jpg" width="500px" alt="More puzzle pieces, now with squiggles." /></p>
<p>Add more curves and it gets even better!</p>
<p><img src="/images/svg-puzzles/08-many-squiggles-tiling.jpg" width="500px" alt="Very squiggly pieces." /></p>
<p>I also experimented with variations on how to place the seed points for my puzzle generation. Here’s one that’s based on a circular point distribution.</p>
<p><img src="/images/svg-puzzles/12-circular.png" width="500px" alt="A puzzle arranged by concentric circles of squiggles." /></p>
<p>Now I had some monstrously-irregular puzzle pieces to play with. Cool! I wanted to take it one step further by implementing whimsy pieces. In jigsaw jargon, a <a href="https://www.wentworthpuzzles.com/articles/what_is_a_whimsy_piece.htm">whimsy</a> piece is a themed, recognizably-shaped puzzle piece. They might be butterflies or people or letters or…you name it!</p>
<p>I modified my puzzle-generator to clear space for a whimsy piece, first testing it with circular whimsy pieces.</p>
<p><img src="/images/svg-puzzles/09-01-whimsy-clearing.png" width="500px" alt="A puzzle with two circular pieces placed inside it." /></p>
<p>Then, using a <a href="https://en.wikipedia.org/wiki/K-d_tree">kd-tree</a>, I identified the whimsy piece’s nearest-neighbors and connected it back to the rest of the puzzle. Here’s a cat!</p>
<p><img src="/images/svg-puzzles/11-cat-whimsy.png" width="500px" alt="Same image as earlier - a puzzle with a cat-shaped piece in it." /></p>
<p>And, finally, I took these files over to NYC Resistor and lasered them.</p>
<p><img src="/images/svg-puzzles/lasering.gif" alt="Laser cutting cutting puzzle pieces into white acrylic" />
<img src="/images/svg-puzzles/puzzle-cat.jpg" alt="The completed puzzle, with the cat whimsy removed." /></p>
<p>It took a group of us about ninety minutes to solve the cat puzzle. Not bad for four days’ work!</p>
<p><img src="/images/svg-puzzles/puzzle-cat-playtesting.jpg" alt="Several people gathered around the puzzle, working on solving it." /></p>
<p>All of the code is available on Github at <a href="https://github.com/bonniee/svg-puzzle-gen">bonniee/svg-puzzle-gen</a>. (It’s my first Clojure program, so I’m sure there are plenty of non-idiomatic things happening there.)</p>
<p>Dependencies / thank-yous:</p>
<ul>
<li><a href="https://github.com/trystan/voronoi-diagram">trystan/voronoi-diagram</a></li>
<li><a href="https://github.com/abscondment/clj-kdtree">abscondment/clj-kdtree</a></li>
<li><a href="https://n-e-r-v-o-u-s.com/shop/line.php?code=12">Nervous Systems</a> and their associated <a href="https://n-e-r-v-o-u-s.com/projects/albums/generative-puzzle-system/">blog posts</a></li>
<li><a href="http://shop.oreilly.com/product/0636920034292.do">Living Clojure</a>, the textbook I used to learn Clojure</li>
<li><a href="https://www.recurse.com/">Recurse Center</a>, for providing an inspiring and uplifting space in which to explore/learn/play</li>
<li>The various people who pair-programmed with me on this puzzle! You’re all awesome :)</li>
</ul>
<p>Testimonials from playtesters:</p>
<ul>
<li>“This is awesome!”</li>
<li>“This is horrible!”</li>
<li>“This is amazing! And by amazing I mean terrible!”</li>
<li>“Why are all the puzzle pieces the same ???”</li>
<li>“Is this supposed to be evil?”</li>
<li>“How can I get one?”</li>
</ul>
<p><a href="http://blog.bonnieeisenman.com/projects/clojure-puzzles/">SVG Jigsaw Generation in Clojure</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on January 13, 2018.</p>http://blog.bonnieeisenman.com/blog/2018-01-01-books-20172018-01-01T00:00:00+00:002018-01-01T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>This year I read 44 books by 24 different authors, including one 15-book series. Most importantly, though - this year I really dove back into reading for <em>fun</em>.</p>
<p><img src="/images/books/books-2017-pt1.png" /></p>
<p><img src="/images/books/books-2017-pt2.png" /></p>
<p><img src="/images/books/books-2017-pt3.png" /></p>
<p>Fifteen of those authors were female, and nine were male; 75% of the books I read were by female authors. When I first started tracking my numbers on this I was habitually reading works almost exclusively by male authors, so I’m happy that this happened without any intentional action on my part! I’m doing much worse when it comes to other sorts of diversity; only 11% of the books I read were by authors of color.</p>
<p>While the vast majority of the books I read were science fiction, I also expanded a bit beyond my usual zone: I read comics, graphic novels, poetry, business books, relationship and communication books, and a couple of other nonfiction books.</p>
<p>Eighteen of the books I read were a direct result of my boyfriend’s recommendations. (Predictable side effect of dating an amateur librarian, I guess.) One of the books was literally handed to me by someone on the street near my apartment, when I stumbled into the <a href="http://www.brooklynbookfestival.org/">Brooklyn Book Festival</a>.</p>
<p>There’s another pattern that I noticed.</p>
<p><img src="/images/books/books-2013-2017-books.png" />
<img src="/images/books/books-2013-2017-pages.png" /></p>
<p>2016 was, incidentally, the year that reading became <em>pleasant</em> again, as the neurological impacts of my illness started to recede.</p>
<p><img src="https://media.giphy.com/media/xUySTUZ8A2RJBQitEc/giphy.gif" /></p>
<h2 id="would-recommend">Would recommend</h2>
<p>Of the books I read in 2017, here are some of my favorites / the ones I’d recommend to others:</p>
<p><em>The Body Keeps Score</em> is a painfully fascinating account of the physical impact of trauma on the body, including the many-years-long aftereffects that can persist long after trauma has passed. It’s accessible to a general reader, but it’s not really a pop-sci book; it draws on a mixture of clinical stories and current research. It was a very emotional read for me, and should come with plenty of trigger/content warnings, but I highly recommend it.</p>
<p><em>The Vorkosigan Saga</em>: a crippled, overachieving kid on a backwater planet accidentally becomes a space pirate; shenanigans ensue. The books get progressively better-written as the series progresses, and several of the later ones have won Hugo awards. I recommend beginning with <em>The Warrior’s Apprentice</em>.</p>
<p><em>All Systems Read</em>: a cyborg has feelings. Mostly, it wants to be left alone to watch its soap operas.</p>
<p><em>Never Split the Difference</em>: a bombastic, entertaining book on negotiation.</p>
<p><em>The Lifespan of a Fact</em>: This one gets recommended for sheer novelty of format. It’s a dialogue on fact-checking and “literary” non-ficiton, played out in the commentary on a dubiously-factual essay.</p>
<p><em>Nimona</em>: It’s a funny graphic novel about a monster-girl and the “villain” she teams up with.</p>
<p><em>The Impossible Fairy Tale</em>: a surreal horror story involving elementary school children, neglect, and anger. The imagery reminded me of Nabokov’s early works. It’s a translation from the Korean; I wonder what it’s like in the original.</p>
<h2 id="onward">Onward</h2>
<p>Some things I want to do in 2018:</p>
<ul>
<li>Keep reading. God, it feels good to have spoons to do this again.</li>
<li>Read at least 1 technical book (i.e. finish Land of Lisp? Maybe?)</li>
<li>Read at least 1 foreign-language book. (Kid’s books count.)</li>
<li>Use the library more.</li>
<li>Don’t finish any books out of a sense of obligation. Keep it fun.</li>
</ul>
<p><a href="http://blog.bonnieeisenman.com/blog/2018-01-01-books-2017/">Books 2017</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on January 01, 2018.</p>http://blog.bonnieeisenman.com/blog/lisp-learning2017-12-29T00:00:00+00:002017-12-29T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>I’m going to be participating in the <a href="https://www.recurse.com/">Recurse Center</a> one week mini-batch in January. Recurse Center describes itself as <em>“a self-directed, community-driven educational retreat for programmers in New York City.”</em> For the mini-batch, my proposed project was to 1. learn some lisp and 2. generate SVGs of jigsaw puzzles, for laser cutting.</p>
<p>Why these projects?</p>
<p>I’ve been wanting to learn Lisp for a while, because I thought that it would be a different kind of problem-solving experience - I like making my brain bend and the Lispers I know have different problem-solving instincts than me. I was also curious about it from a historical POV. Apparently it’s been around <a href="https://en.wikipedia.org/wiki/Lisp_(programming_language)">since the 1950s</a>? Though I guess that depends on which dialect we’re talking about; Common Lisp, which is what I’m learning, dates from the <a href="https://en.wikipedia.org/wiki/Common_Lisp">1980s</a>.</p>
<p>Why generate SVGs? Because it’s relatively straightforward (I’ve done SVG generation <a href="http://twitter.com/dailyoblo">before</a>) and learning how to print things is a standard newbie-programmer task. Also, I adore generative art, and I love puzzles. I was heavily inspired by the work of <a href="http://inconvergent.net/">inconvergent</a> and <a href="https://n-e-r-v-o-u-s.com/projects/albums/generative-puzzle-system/">nervous systems</a>.</p>
<p>This post isn’t about jigsaw puzzles, though, it’s about my first experiences learning Lisp. Here are some jumbled thoughts!</p>
<p>I’m following <a href="http://landoflisp.com/"><em>The Land of Lisp</em></a>. The book is…hrm. Interesting. I <a href="https://twitter.com/brindelle/status/944037633117900805">grumbled about it</a> on Twitter. First of all, the illustrations are adorable.</p>
<p><img src="https://www.safaribooksonline.com/library/view/land-of-lisp/9781593272814/httpatomoreillycomsourcenostarchimages780406.png" /></p>
<p>The pedagogical approach of the book also works really well for me - I enjoyed following along with the beginning exercises. Ideologically, though, I’m a bit annoyed. The book spends a lot of time assuring you that Lisp is “beautiful” and “pure” and “elegant”, and also warning you that Lispers can be judgmental assholes, though it doesn’t use those words. Arrrgh.</p>
<p>The clisp REPL also includes this somewhat baffling ASCII art, which I kind of love:</p>
<p><img src="/images/lisping/clisp.jpeg" /></p>
<p>Anyway, here are some unordered musings:</p>
<ul>
<li>
<p>In Lisp, you can get the head of a list with a function named CAR (Contents of the Address Register) and the remainder with CDR (Contents of the Decrement Register). Look, they even have a <a href="https://en.wikipedia.org/wiki/CAR_and_CDR">Wiki page</a>. I’m given to understand that many modern Lisps just call these FIRST and REST or some such English-language thing. I think it’s pretty interesting that 1. they compose well and 2. you can’t just get the nth element of a list.</p>
</li>
<li>
<p>Relatedly, implementing my own <code class="language-plaintext highlighter-rouge">randselect</code> function looked like this:</p>
</li>
</ul>
<div class="language-common-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">randselect</span> <span class="p">(</span><span class="nv">somelist</span><span class="p">)</span>
<span class="p">(</span><span class="k">let</span>
<span class="p">((</span><span class="nv">n</span> <span class="p">(</span><span class="nb">length</span> <span class="nv">somelist</span><span class="p">)))</span>
<span class="p">(</span><span class="nb">car</span> <span class="p">(</span><span class="nb">nthcdr</span> <span class="p">(</span><span class="nb">random</span> <span class="nv">n</span><span class="p">)</span> <span class="nv">somelist</span><span class="p">))</span>
<span class="p">)</span>
<span class="p">)</span>
</code></pre></div></div>
<ul>
<li>
<p>How on earth does performance work in this language? I’m super curious.</p>
</li>
<li>
<p>I want to make tongue twisters out of cadddraddadar. No, seriously, it’s adorable that you would name a function after the <em>actual registers involved</em> but I think this is one of those, uh, historical quirks that shows Lisp’s age. Someone sent me a link to this <a href="https://news.ycombinator.com/item?id=16009280">HackerNews discussion</a> which actually seemed quite reasonable all-around.</p>
</li>
<li>
<p>I’m dying to know how you write maintainable, shareable code in Lisp that lots of people can work on who aren’t all inside each other’s heads. The way that <em>Land of Lisp</em> is encouraging me to write code - where you basically have lots and lots of unnamed heterogeneous lists where each element does Something Special and functions expect things in some weird undocumented order - is EXACTLY how I like to write python scripts for my side projects. As came up in my RC pairing interview, however, that approach is extraordinarily bug prone. It also takes forever for someone new to learn it. So … I’m curious. But so far at least it matches how I think :) (Fast to write, infuriating to debug…)</p>
</li>
<li>
<p>These function names are a little weird. MAPCAR, really ??? I get it but also I’m coming in with pleeeenty of my own biases and this feels weird.</p>
</li>
<li>
<p>Evidently using APPLY is dangerous ?? But it’s so useful! Gah! I can’t wait til we get to tail recursion.</p>
</li>
<li>
<p>Someone suggested I switch to using <a href="http://www.sbcl.org/">sbcl</a> for my REPL; apparently it is More Efficient. However it lacks clisp’s awesome autocomplete in the REPL, at least on Mac.</p>
</li>
<li>
<p>The usage of <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Association-Lists.html">association lists</a> (alists?) confuses me. Is there anything that distinguishes an alist? How do you tell if something can be used as an alist?</p>
</li>
<li>
<p>Figuring out how to print stuff is weird. String interpolation is confusing. I thought that FORMAT was the answer but then it always prints to screen instead of returning a value? Unless you pass “nil” as the first argument, apparently. Should I be using CONCATENATE? I ended up finding a useful resource <a href="http://cl-cookbook.sourceforge.net/strings.html#concat">here</a>.</p>
</li>
</ul>
<blockquote>
" If the string will be constructed out of (the printed representations of) arbitrary objects, (symbols, numbers, characters, strings, ...), you can use FORMAT with an output stream argument of NIL. This directs FORMAT to return the indicated output as a string. "
</blockquote>
<ul>
<li>Random apparently doesn’t have a time-based seed ?? At least not by default. You have to seed it yourself, laŭ <a href="https://stackoverflow.com/questions/4034042/random-in-common-lisp-not-so-random">StackOverflow</a>:</li>
</ul>
<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">setf</span> <span class="vg">*random-state*</span> <span class="p">(</span><span class="nb">make-random-state</span> <span class="no">t</span><span class="p">))</span>
</code></pre></div></div>
<ul>
<li>The syntax for LET is weird. I was confused about how to set up a variable that depends on another variable, e.g. <code class="language-plaintext highlighter-rouge">a = 5, b = a + 1</code>. It turns out that you need to use LET* for this? I got this from <a href="http://www.gigamonkeys.com/book/variables.html"><em>Practical Common Lisp</em></a>.</li>
</ul>
<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">x</span> <span class="mi">10</span><span class="p">)</span>
<span class="p">(</span><span class="nv">y</span> <span class="p">(</span><span class="nb">+</span> <span class="nv">x</span> <span class="mi">10</span><span class="p">)))</span>
<span class="p">(</span><span class="nb">list</span> <span class="nv">x</span> <span class="nv">y</span><span class="p">))</span>
</code></pre></div></div>
<p>At the end of my very early flailings about, I’ve made it through six out of twenty chapters of <em>Land of Lisp</em> and written my very first basic script. It’s adapted from my <a href="https://github.com/bonniee/bot-experiments/tree/master/dailyoblo">SET bot Python code</a>, and right now it generates an SVG with a randomly-colored circle.</p>
<p><img src="/images/lisping/foo.svg" /></p>
<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;;;; sbcl --script setsvg.lisp > foo.svg</span>
<span class="c1">;;;; Creates an SVG with a randomly-colored circle.</span>
<span class="c1">; Initialize the global random state.</span>
<span class="c1">; https://stackoverflow.com/questions/4034042/random-in-common-lisp-not-so-random</span>
<span class="p">(</span><span class="nb">setf</span> <span class="vg">*random-state*</span> <span class="p">(</span><span class="nb">make-random-state</span> <span class="no">t</span><span class="p">))</span>
<span class="p">(</span><span class="nb">defparameter</span> <span class="vg">*begin-svg*</span> <span class="s">"<svg xmlns=\"http://www.w3.org/2000/svg\"
xmlns:xlink=\"http://www.w3.org/1999/xlink\"
width=\"500\" height=\"500\">"</span><span class="p">)</span>
<span class="p">(</span><span class="nb">defparameter</span> <span class="vg">*end-svg*</span> <span class="s">"</svg>"</span><span class="p">)</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">ellipse</span> <span class="p">(</span><span class="nv">color</span><span class="p">)</span>
<span class="p">(</span><span class="nb">concatenate</span> <span class="ss">'string</span> <span class="s">"<ellipse
cx=\"250.0\"
cy=\"250.0\"
rx=\"100.0\"
ry=\"100.0\"
stroke=\"#fc8d62\"
stroke-width=\"5\"
fill=\"#"</span> <span class="nv">color</span> <span class="s">"\"
/>"</span><span class="p">)</span>
<span class="p">)</span>
<span class="p">(</span><span class="nb">defparameter</span> <span class="vg">*colors*</span> <span class="o">'</span><span class="p">(</span><span class="s">"66c2a5"</span> <span class="s">"fc8d62"</span> <span class="s">"8da0cb"</span><span class="p">))</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">randselect</span> <span class="p">(</span><span class="nv">somelist</span><span class="p">)</span>
<span class="p">(</span><span class="k">let</span>
<span class="p">((</span><span class="nv">n</span> <span class="p">(</span><span class="nb">length</span> <span class="nv">somelist</span><span class="p">)))</span>
<span class="p">(</span><span class="nb">car</span> <span class="p">(</span><span class="nb">nthcdr</span> <span class="p">(</span><span class="nb">random</span> <span class="nv">n</span><span class="p">)</span> <span class="nv">somelist</span><span class="p">))</span>
<span class="p">)</span>
<span class="p">)</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">randcolor</span> <span class="p">()</span>
<span class="p">(</span><span class="nv">randselect</span> <span class="vg">*colors*</span><span class="p">)</span>
<span class="p">)</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">svg</span> <span class="p">(</span><span class="nv">body</span><span class="p">)</span>
<span class="p">(</span><span class="nb">format</span> <span class="no">t</span> <span class="s">"~d"</span> <span class="vg">*begin-svg*</span><span class="p">)</span>
<span class="p">(</span><span class="nb">format</span> <span class="no">t</span> <span class="s">"~d"</span> <span class="nv">body</span><span class="p">)</span>
<span class="p">(</span><span class="nb">format</span> <span class="no">t</span> <span class="s">"~d"</span> <span class="vg">*end-svg*</span><span class="p">)</span>
<span class="p">)</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">randcircle</span> <span class="p">()</span>
<span class="p">(</span><span class="nv">svg</span> <span class="p">(</span><span class="nv">ellipse</span> <span class="p">(</span><span class="nv">randcolor</span><span class="p">)))</span>
<span class="p">)</span>
<span class="p">(</span><span class="nv">randcircle</span><span class="p">)</span>
</code></pre></div></div>
<p><a href="http://blog.bonnieeisenman.com/blog/lisp-learning/">Lisp Learning, Part 1: Generating a Circular SVG</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on December 29, 2017.</p>http://blog.bonnieeisenman.com/blog/for-want-of-a-sandwich2017-12-21T00:00:00+00:002017-12-21T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>Today I made myself a sandwich. Two slices of toasted rye, fig jam, turkey, swiss, pickles.</p>
<p>The ingredients arrived from FreshDirect this morning. I had to open the door. Unbox the groceries. Put them in the fridge. Open the bag of sliced bread. Plug in the toaster. Put two slices of bread into the toaster. Open a cabinet door, take down a plate. Open a drawer, pick up a knife…</p>
<p>And so on.</p>
<p>This time last year, each of those steps was notably taxing. I generally couldn’t make myself a sandwich in one go; I’d have to sit down, catch my breath, drink some water. It might take me an hour to make lunch. Doable, but difficult. Maddeningly difficult.</p>
<p>(And that, lest we forget, was a step forward from the year prior, where even “unbox groceries” would have expended all of my spoons for the day, and I would instead retreat to my bed to drink Soylent.)</p>
<p>Recovery feels wonderful. I’m keenly aware of all of these small pleasures.</p>
<p>I made myself a goddamned sandwich.</p>
<p><a href="http://blog.bonnieeisenman.com/blog/for-want-of-a-sandwich/">For want of a sandwich</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on December 21, 2017.</p>http://blog.bonnieeisenman.com/blog/underscores-in-scala2017-12-18T00:00:00+00:002017-12-18T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>This post brought to you by my shiny new drawing tablet! I decided to gift myself a tablet for my birthday. I like making doodles of things - I remember information better that way - and I’m also always envying <a href="https://drawings.jvns.ca/">@b0rk’s drawings</a>. So, this is me, giving it a test run.</p>
<p>When I first started learning Scala, the underscores everywhere were one of the things I found most confusing. Why were there underscores everywhere??? I was coming from a background of JavaScript/Python/Java/Golang/Ruby, so I had enough polyglot experience that <em>most</em> of Scala syntax made sense at a glance. But those underscores. Man.</p>
<p>Of course when I tried Googling my problem I ended up on the relevant-sounding page <a href="http://docs.scala-lang.org/tutorials/FAQ/finding-symbols.html">“How do I find out what some symbol means or does?”</a>. Helpfully, the page informs you that the underscore has “many different meanings”, and neglects to expand further on the topic. *headexplode*</p>
<p>Other, more useful explanations include <a href="http://ananthakumaran.in/2010/03/29/scala-underscore-magic.html">Scala _ [underscore] magic</a> and, for reference (<em>not</em> explanation), this StackOverflow post: <a href="https://stackoverflow.com/questions/8000903/what-are-all-the-uses-of-an-underscore-in-scala">What are all the uses of underscore in Scala?</a></p>
<p>OK, enough linkspam. Here’s my doodle:</p>
<p><img src="/images/zines/underscore.png" /></p>
<p>TLDR; I think of the underscore as the “meh” operator. :)</p>
<p>…also, I really need to get better at drawing.</p>
<p><a href="http://blog.bonnieeisenman.com/blog/underscores-in-scala/">Underscores in Scala</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on December 18, 2017.</p>http://blog.bonnieeisenman.com/blog/reading-papers-as-a-working-programmer2017-12-13T00:00:00+00:002017-12-13T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>When talking about the computer science research papers with other software engineers, I get a lot of comments to the effect of, “Neat! I wish I read papers, <em>but</em> … (I don’t).” Many of these comments were followed by “…and I feel some imposter syndrome over the fact that I don’t.”</p>
<h2 id="do-software-engineers-andor-professional-programmers-read-cs-research-papers">Do software engineers and/or professional programmers read CS research papers?</h2>
<p>After having a couple of these conversations, I was curious, so I <a href="https://twitter.com/brindelle/status/734757812530741248?ref_src=twsrc%5Etfw">polled my Twitter followers</a>. The results were pretty even, at 45% yes / 55% no.</p>
<p><img src="/images/research-paper-poll.png" /></p>
<p>I have a lot of followers who are JavaScript-only developers, or frontend- and mobile-centric, thanks to my work with React Native. I also have a good number of Twitter employees following me. (Hi, coworkers!) Obviously, this is not a representative sample, but I still found it interesting.</p>
<p>tldr; I think that <strong>most programmers don’t read CS research papers.</strong> This makes sense! Research papers are their own genre, and reading papers is a skill that requires time, effort, and practice.</p>
<p>One of my professors assigned us this <a href="http://www.albany.edu/spatial/WebsiteFiles/ResearchAdvices/how-to-read-a-paper.pdf">How to Read a Paper</a> paper. It’s really useful and I’d recommend it to anyone who struggles with the research paper format.</p>
<p>Anyway, this got me thinking about whether or not working programmers read computer science research, and why.</p>
<h2 id="why-is-it-useful-to-read-papers">Why is it useful to read papers?</h2>
<ul>
<li><strong>Get new ideas.</strong></li>
<li><strong>Build up confidence critiquing ideas.</strong> Sometimes you read a paper and think, “why did they do that?” Discussing papers can be great practice for learning how to critique others’ proposals or designs.</li>
<li><strong>Get a sense for the “state of the art”.</strong> Some people will tell you that papers are usually several years behind “today’s” tech. But that doesn’t mean they aren’t useful - reading papers can give you a sense of what currently-understood thinking in a field is.</li>
<li><strong>Build up knowledge in a new area.</strong> If you don’t know much about a given topic area, beginning with a literature survey can be fun.</li>
<li><strong>Learn the history of a field.</strong> There are some papers that are historically significant, and reading them will give you more context.</li>
</ul>
<h2 id="why-isnt-it-useful-to-read-papers">Why <em>isn’t</em> it useful to read papers?</h2>
<ul>
<li>
<p><strong>Industry moves too fast / research papers are usually outdated.</strong> This is probably true a lot of the time! But then it begs the question: where are you positioned, industry-wide? If you’re working on cutting-edge stuff at your day job, cool. But you’re just one person, working at one organization. How are you keeping track of other companies’ cutting-edge work? (Conferences? Meetups? Twitter? Blog posts?)</p>
</li>
<li>
<p><strong>Reading papers is hard / not worth my time.</strong> Legit! I can’t really argue with this one.</p>
</li>
<li>
<p><strong>There isn’t useful research in my field.</strong> Also possible, if your particular kind of work isn’t addressed by academia.</p>
</li>
</ul>
<h2 id="should-you-read-papers">Should you read papers?</h2>
<p>For the general “you”, as usual, I think the answer is “you’re not obligated to do anything”.</p>
<p>In general I like to always be learning things, and studying what other people are doing. Papers are one source of this kind of information, but far from the only source, or even the best one. I try to fill my feed with a diversity of sources for this kind of thing: Twitter, RSS feeds from individual blogs, recommendations from my friends, conversations at meetups, conference talks, etc, etc…</p>
<p>(I’m not recommending that anyone spend all their free time on this, either. IMO trying to learn more things is a legitimate use of work-time!)</p>
<p>By that metric, <em>I</em> should be reading papers because it’s one more source of information, and I personally find it to be interesting/valuable from time to time. Should <em>you</em> read papers? I dunno! I think it’s something that depends a lot on your individual goals, preferences, and interests.</p>
<p>Some links if you’re interested in reading more papers:</p>
<ul>
<li><a href="https://blog.acolyer.org/">the morning paper</a> - a blog that describes + links to one CS paper per weekday</li>
<li><a href="http://paperswelove.org/">Papers We Love</a> - a repo of computer science papers, and a community of people who love reading them</li>
</ul>
<p>And some papers I’ve read lately:</p>
<ul>
<li><a href="https://research.fb.com/wp-content/uploads/2016/11/scuba-diving-into-data-at-facebook.pdf">Scuba: Diving into Data at Facebook</a></li>
<li><a href="https://n-e-r-v-o-u-s.com/education/papers/nervousSystem_2012-jigsaw-puzzle-paper.pdf">Multiphase Numerical Modeling of Dendritic Solidification for Jigsaw Puzzle
Generation</a></li>
<li><a href="https://www.microsoft.com/en-us/research/wp-content/uploads/2016/12/The-Byzantine-Generals-Problem.pdf">The Byzantine Generals Problem</a></li>
</ul>
<p>🎉</p>
<p><a href="http://blog.bonnieeisenman.com/blog/reading-papers-as-a-working-programmer/">Reading Papers as a Working Programmer</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on December 13, 2017.</p>http://blog.bonnieeisenman.com/blog/quitting-facebook2017-12-13T00:00:00+00:002017-12-13T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<blockquote><pre>
this is just to say
I have deleted
my account
from facebook
which you probably
noticed
and worried
about
please,
celebrate with me -
I feel so free
and
so calm.
</pre>
</blockquote>
<p>…I’ve received several concerned messages from folks who noticed that I’m not on Facebook anymore. I deleted my account! It felt really good. If you need to get in touch, you can probably find a way. (Hint: my email address is listed on this site.)</p>
<p><a href="http://blog.bonnieeisenman.com/blog/quitting-facebook/">Quitting Facebook / this is just to say</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on December 13, 2017.</p>http://blog.bonnieeisenman.com/blog/what-i-know-about-debugging-circuits2017-12-09T00:00:00+00:002017-12-09T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>I’m a trained software engineer, but I am decidedly an amateur when it comes to working with physical hardware and building circuits. I’m juuuust teetering on the edge of self-sufficiency when it comes to physical computing projects and circuit-building: I can comfortably program an Arduino; I can stitch together existing tutorials and remix them into my own projects; I can read and replicate simple circuit diagrams. I still tend to rely on microcontrollers for anything complicated because, let’s be honest, version control is the <em>best</em> and I’m much more comfortable writing code.</p>
<p>As I’m working on my current project, I’m noticing that I’m getting better at debugging circuits. Here are some things that help me!</p>
<p><strong>Double-check things with a multimeter.</strong> You can use a multimeter to double-check that things are connected how you think they should be. You can also use a multimeter to read values, like current/resistance, to confirm that e.g. your sensors are working. This feels pretty cool!</p>
<p><strong>It’s worth the time to solder carefully.</strong> Soldering is one of those really basic skills that pay dividends. For a while I felt really nervous about soldering (what if I did it wrong??). Being able to double-check my connections with a multimeter made me a lot less afraid of that.</p>
<p><strong>Just because it worked yesterday doesn’t mean it will work today.</strong> You don’t have version control, so it’s quite possible that you changed something when you put your project away and then took it back out again. Did you plug something in backwards? Did something break when you moved it?</p>
<p><strong>Document, document, document.</strong> See again: not having version control. This is one reason why I write tutorials: they are gifts to my future self.</p>
<p><strong>How’s your power?</strong> Over- or under-powering your circuit is a pretty common reason behind “hey this works but only sorta???”</p>
<p><strong>Are you grounded?</strong> This is really common when powering projects from e.g. your laptop. Make sure your laptop is plugged in with a three-prong plug. I do a lot of capacitative sensing projects and they’re affected by things as simple as someone touching the metal case of my computer.</p>
<p><strong>Read the datasheet.</strong> Ughhhh I wish I was better at reading datasheets! They contain all sorts of useful information, like “how much voltage does this component need to function properly”. See above.</p>
<p><strong>Test every step.</strong> Never assume that you did it right. Whenever you have a chance to verify that a component is working, or that you built part of a circuit correctly, do it. And take notes.</p>
<p>Debugging circuits is a lot like debugging software in terms of the questions you should ask. (<em>What am I seeing? How do I know that? What can I measure? What do I expect to see? How do I confirm that?</em>) But the tools are really different and also it takes way more time to fix your mistakes.</p>
<p><a href="http://blog.bonnieeisenman.com/blog/what-i-know-about-debugging-circuits/">What I know about debugging circuits</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on December 09, 2017.</p>http://blog.bonnieeisenman.com/blog/strange-loop-2017-sketchnotes-edition2017-10-04T00:00:00+00:002017-10-04T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>I went to Strange Loop this year (as well as PWL Conf). And I took some notes…</p>
<p>PS: <a href="https://www.youtube.com/watch?v=kxMKnx__uso">My talk is on YouTube!</a></p>
<p><a href="https://www.youtube.com/playlist?list=PLcGKfGEEONaDzd0Hkn2f1talsTu1HLDYu">All the talks are up on YouTube.</a></p>
<p><img src="/images/strangeloop2017/haxl.jpg" /></p>
<p><img src="/images/strangeloop2017/antics.jpg" /></p>
<p><img src="/images/strangeloop2017/obs.jpg" /></p>
<p><img src="/images/strangeloop2017/twitter-streaming.jpg" /></p>
<p><a href="http://blog.bonnieeisenman.com/blog/strange-loop-2017-sketchnotes-edition/">Strange Loop 2017: Sketchnotes Edition</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on October 04, 2017.</p>http://blog.bonnieeisenman.com/blog/chronic-pain2017-06-02T00:00:00+00:002017-06-02T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>Almost exactly a year ago I published my <a href="http://blog.bonnieeisenman.com/blog/zero-to-ten-a-chronic-pain-scale/">chronic pain scale</a>.</p>
<p>At the time, if I’m honest with myself, I was living pretty consistently in the 4-7 range. As a refresher…</p>
<blockquote>
<p>7: Unmanageable. I am in pain all the time. It keeps me from doing most activities.</p>
<p>4: Moderate. I am constantly aware of my pain, but can continue most daily activities.</p>
</blockquote>
<p>I had been in that range for many years - the lowest I’d been since puberty was maybe a 3. And I had a lot of days stuck at 7 or higher: trapped in bed, unable even to hold my phone and spend time on the Internet. (It is REALLY BORING to be in that much pain. THE CEILING IS NOT THAT INTERESTING OH MY GOD.)</p>
<p>In the time since then I’ve gotten a diagnosis and treatment. (Hey, it turns out that autoimmune diseases really suck!) I <em>think</em> that most days now, I’m sitting at a 3.</p>
<blockquote>
<p>3: Uncomfortable. My pain bothers me, but I can ignore it most of the time.</p>
</blockquote>
<p>Some days, I even make it to 2.</p>
<blockquote>
<p>2: Mild. I have a low level of pain. I am aware of it only when paying attention to it.</p>
</blockquote>
<p>My pain tolerance and awareness have changed a lot. Something that a functional pain scale obscures is the huge variation in perceived pain. Chronic pain is an intensely personal, relative, and emotional experience. Case in point: I had <em>forgotten that I got migraines</em> because they were below my baseline levels. That was a fun thing to rediscover. But hey, I can feel those now!</p>
<p>My ability levels have improved a lot, too. I am still mobility-limited and I would still call myself <em>disabled</em>: I am literally unable to do certain physical tasks. But I’m considerably more able-bodied than I was.</p>
<p>I am so, so, so lucky: to have good healthcare (finally, finally); a good sick leave policy at work; an incredible support network.</p>
<p>It’s been a weird and difficult and wonderful year.</p>
<p><a href="http://blog.bonnieeisenman.com/blog/chronic-pain/">Chronic pain, some time later</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on June 02, 2017.</p>http://blog.bonnieeisenman.com/projects/why-should-you-learn-tmux2017-03-27T00:00:00+00:002017-03-27T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p><a href="http://bit.ly/wrangletmux">Hey, I’ve got a brand-new tmux course out!</a> It’s free on egghead.io for the first few days.</p>
<p><img src="/images/tmuxgif.gif" alt="Screen recording of tmux in use" /></p>
<p>I’ve met a lot of developers who use the command line every day, but confess that they don’t feel totally comfortable. They’ve hit the <a href="http://www.thepolyglotdream.com/why-youre-still-an-intermediate-language-learner/">intermediate plateau</a>: that awkward stage where you can get shit done, but you know that you’re still not fluent.</p>
<p>The intermediate plateau is a difficult place to be. Unlike when you’re a total beginner, it’s not obvious what you need to learn, and the gains are smaller.</p>
<p>tmux is one of those tools that can feel like a leap forward, even if you’ve been working on the command line for a long time. Similar to screen, it allows you to wrangle multiple terminal sessions from one window. Instead of keeping track of many windows yourself, you can use tmux to create, organize, and navigate between them.</p>
<p>Even more importantly, tmux lets you detach from and re-attach sessions, so that you can leave your terminal sessions running in the background and resume them later. This is especially useful if you’re working on a remote server: you can set up a persistent session that will continue running when you close your laptop. You can even share a tmux session to facilitate pair programming.</p>
<p><a href="http://bit.ly/wrangletmux">My tmux course is free on egghead.io for the next few days.</a> If you’re interested in picking up a new skill, go check it out!</p>
<p><em>This is a cross-post from <a href="https://medium.com/@brindelle/why-should-you-learn-tmux-7a55cfb5668f">Why should you learn tmux?</a></em></p>
<p><a href="http://blog.bonnieeisenman.com/projects/why-should-you-learn-tmux/">tmux course on egghead.io</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on March 27, 2017.</p>http://blog.bonnieeisenman.com/blog/scala-jargon2017-03-25T00:00:00+00:002017-03-25T00:00:00+00:00Bonnie Eisenmanhttp://blog.bonnieeisenman.combonnie.eisenman@gmail.com<p>I went to the Typelevel Summit / NE Scala Symposium this week. It was my first time going to a Scala conference, ever. At this point I’ve been working in Scala professionally for about ~1.5 years.</p>
<p>My goal in attending NE Scala was to see what Scala looks like outside of my particular corner of the universe. I write Scala at Twitter, which has a particular style; and I’ve only worked on one team at Twitter, which makes my view even narrower. Scala is notoriously “flexible” as a language, i.e. put three Scala devs in a room and you’ll have at least nine dialects. What does Scala look like when other people write it? What challenges and interesting problems do people have? What are people excited about?</p>
<p>It turns out that I had inadvertently picked a conference that’s known for being a little more functional-programming-theory-heavy and less about “pragmatic” Scala. One of the other attendees said to me, “I feel like I write blue-collar Scala compared to this.”</p>
<p>I have Strong Feelings about jargon. Jargon comes with an inherent cost. It needs to earn its place. (And it often does: jargon is necessary to discuss complex and domain-specific ideas.) But…eh. There was a lot of jargon at this conference.</p>
<p>Here’s some jargon that I heard at the conference that I didn’t understand:</p>
<ul>
<li>monoids</li>
<li>monads</li>
<li>monadic</li>
<li>free monads (sometimes with a capital-F)</li>
<li>cats</li>
<li>kittens</li>
<li>spark</li>
<li>pure</li>
<li>suspend</li>
<li>lift</li>
<li>monad transformers</li>
<li>applicatives</li>
<li>functors</li>
<li>endofunctors</li>
<li>algebra</li>
<li>trampoline</li>
</ul>
<p>There were also some Scala concepts that I’m familiar with but admittedly don’t use often in my own code, like implicits and certain operators like <code class="language-plaintext highlighter-rouge">~></code>, <code class="language-plaintext highlighter-rouge">:+</code>, <code class="language-plaintext highlighter-rouge">+:</code>, and <code class="language-plaintext highlighter-rouge">|@|</code>. (These are really hard to Google for, btw, which is one of my biases against them.)</p>
<p>And again - I want to emphasize this - I manage to be a productive software engineer in Scala <em>without</em> these concepts. These are not mandatory bars to entry, at least in my workplace. But I wanted to learn more about them, so here we go. (Spoiler alert, it turns out that many of them were things I was already using but didn’t know the names for. Neat.)</p>
<p>Shoutouts to the following people for teaching me things, sending me great links, etc:</p>
<ul>
<li><a href="https://twitter.com/b0rk">@b0rk</a></li>
<li><a href="https://twitter.com/viskobatz">@viskobatz</a></li>
<li><a href="https://twitter.com/kelleyrobinson">@kelleyrobinson</a></li>
<li><a href="https://twitter.com/oacgnol">@oacgnol</a></li>
</ul>
<p><em>Note: I probably get some things wrong below. Got more stuff for me to read, or thoughts? I’m <a href="https://twitter.com/">@brindelle</a> on Twitter.</em></p>
<h2 id="monoids">monoids</h2>
<p>Apparently monoids are just things that 1. have an identity function (aka no-op) and 2. have an append function.</p>
<p>This sounds so simple. OK then!</p>
<p>(s/o to <a href="https://www.youtube.com/watch?v=U0lK0hnbc4U&feature=youtu.be">Kelley Robinson’s talk</a> )</p>
<h2 id="monads">monads</h2>
<p>I’ve always been a bit embarrassed to admit that I don’t really grok monads. The good news is that when you admit you don’t understand something, people usually send you great links / answers.</p>
<p>@b0rk replied to me and was like, aren’t monads just things with flatMap? Which was a bit of an ah-ha moment for me. I have plenty of experience working with things with flatMap! And that’s clearly a <em>pattern</em> for which I don’t currently have language. Hmmmm.</p>
<p>Libby Kent sent me a link to her talk, <a href="https://www.youtube.com/watch?v=J3Djb1VyzkM">Monads Made Semi-Understandable</a>. Best quote: “Can you explain what monads are? Are they a burrito?”</p>
<p>This was an even bigger ah-ha moment! Ah, yes, this is a thing I’ve worked with but only have an inferred, non-systematic understanding of.</p>
<p><strong>Monads (in Scala) are things with flatMap and apply defined.</strong> In other words: monads let you compose functions for values in a context. Common monads are: Option, List, Try, Future.</p>
<p>flatMap lets you nest functions.</p>
<p>The Monad Laws, as defined by Libby’s talk: they boil down to “don’t do weird shit inside of flaTMap or apply”.</p>
<p>Identity Law:</p>
<pre>monadA.flatMap(a => apply(a)) == monadA</pre>
<p>Associative Law:</p>
<pre>flatMap(f).flatMap(g) = flatMap(a => f(a).flatMap(g))</pre>
<p>Googling this also led me to <a href="https://devth.com/2015/monad-laws-in-scala">Monad laws in Scala</a> which was useful.</p>
<h2 id="free-monads">Free monads</h2>
<p>The <a href="https://github.com/nescalas/proposals-2017/blob/master/long-spiewak-daniel-free-as-in-monads.md">first talk</a> at NE Scala was by <a href="https://twitter.com/djspiewak">@djspiewak</a>, in which he built up something called the Free monad from scratch. This was confusing because I had never heard of free monads before and didn’t know what they were, or why they were useful or interesting or etc.</p>
<p>So! Today I watched Kelley Robinson’s talk, <a href="https://www.youtube.com/watch?v=U0lK0hnbc4U&feature=youtu.be">Why the free Monad isn’t free</a>. The Free monad is apparently a pattern that lets you <strong>separate out function composition from computation/interpretation.</strong></p>
<p>“Free” here means “unrestricted”, not “zero cost”.</p>
<p>Free monads should not lose any data during the composition (<code class="language-plaintext highlighter-rouge">flatMap</code>) step. So we can’t evaluate any functions as we do this. So we store up the data (e.g. the functions) as we’re building the structure; and then we’ll evaluate it later.</p>
<p>It’s not something that’s “built in” to the language or anything like that; it’s a pattern for structuring how you handle stuff. You’re delaying evaluation (aka side effects). There are implementations available in Scalaz and Cats.</p>
<p>What’s the point? Separating composition from computation seems really great for testing, since you’re separating out side effects from the wiring / composition step.</p>
<p>However, it involves a lot of boilerplate, and a steep learning curve. Means building up big interpreters, too. I hear that there are also some performance issues with this in Scala?</p>
<h2 id="free-monoids">Free monoids</h2>
<p><a href="https://youtu.be/U0lK0hnbc4U?t=12m34s">https://youtu.be/U0lK0hnbc4U?t=12m34s</a></p>
<p>Free from interpretation; don’t lose input data when appending.</p>
<p>Example: list concatenation doesn’t involve interpretation. Integer addition, on the other hand, loses information during the input step.</p>
<h2 id="trampolining">trampolining</h2>
<p>Express it in a loop: use the heap instead of the stack.</p>
<p>I actually really like this phrase, it’s cute.</p>
<h2 id="cats">Cats</h2>
<p><a href="https://github.com/typelevel/cats">https://github.com/typelevel/cats</a></p>
<p>The tagline calls it a “lightweight, modular, and extensible library for functional programming” which tells me …. <em>absolutely nothing</em> about what it is, except that it’s for functional programming. OK? Can’t I do functional programming in a bunch of languages without a library?</p>
<p>Wait, just kidding, the README actually has a great introduction:</p>
<blockquote>
<p>Cats is a library which provides abstractions for functional programming in Scala.</p>
<p>The name is a playful shortening of the word category.</p>
<p>Scala supports both object-oriented and functional programming, and this is reflected in the hybrid approach of the standard library. Cats augments the standard library with tools that further enable functional programming such as Validated, Monad, and Traverse. A broader goal of Cats is to provide a foundation for an ecosystem of pure, typeful libraries.</p>
</blockquote>
<p>Given that Day 1 of the conference was the Typelevel Summit, it makes sense that there was much discussion of Cats.</p>
<h2 id="kittens">Kittens</h2>
<p><a href="https://github.com/milessabin/kittens">https://github.com/milessabin/kittens</a></p>
<p>This one has a better Github tagline: “Automatic type class derivation for Cats”.</p>
<p>OK! Cool. I like these puns but there were fewer cat GIFs during presentations than I would have liked.</p>
<h2 id="spark">Spark</h2>
<p>From <a href="http://spark.apache.org/">http://spark.apache.org/</a>: “Apache Spark™ is a fast and general engine for large-scale data processing.”</p>
<p>The “killer app” for Scala, apparently. Interestingly, a lot of Spark code is apparently not very functional at all. (As usual, programming for data science looks different than other kinds of programming?) There were lots of Spark users in the audience.</p>
<h2 id="pure">pure</h2>
<p>No side effects. That’s it??</p>
<h2 id="suspend">suspend</h2>
<p>This is a free monad thing, it means “don’t do the computation yet”.</p>
<h2 id="lift">lift</h2>
<p>This is what the apply method does in Scala: “lift” a value into a ~monadic context~. I guess it’s sort of like putting something into a different abstraction?</p>
<p>From Libby’s talk: apply lifts a value into a ~monadic context~ (aka the context of whatever you called <code class="language-plaintext highlighter-rouge">.apply()</code> on). <code class="language-plaintext highlighter-rouge">map</code> “lifts” a function into the same.</p>
<h1 id="monad-transformers">monad transformers</h1>
<p>Something that takes a monad and turns it into another monad?</p>
<h2 id="applicatives">applicatives</h2>
<p>“A type which wraps a value”. More at <a href="https://softwaremill.com/applicative-functor/">this blog post explaining applicative functors</a>.</p>
<h1 id="functors">functors</h1>
<p>“A family of types that has implemented the map method”; there’s an identity function, and also grouping doesn’t matter.</p>
<p>Kelley Robinson’s talk, again: <a href="https://youtu.be/U0lK0hnbc4U?t=5m21s">https://youtu.be/U0lK0hnbc4U?t=5m21s</a></p>
<h2 id="endofunctors">endofunctors</h2>
<p>Laŭ Kelley Robinson’s talk, again, “functors are endofunctors” in Scala.</p>
<p>“endo” = mapping from one category to itself; in Scala that means mapping from a Scala type to a SCala type.</p>
<h1 id="algebra">algebra</h1>
<p>There is a very math-y usage of this word. I still haven’t found a good concise definition for it.</p>
<p><a href="http://blog.bonnieeisenman.com/blog/scala-jargon/">Scala jargon</a> was originally published by Bonnie Eisenman at <a href="http://blog.bonnieeisenman.com">Bonnie Eisenman</a> on March 25, 2017.</p>