Wednesday, March 15, 2017

Approaching Functional Programming Completely Wrong

 So I got a new book, and I was pretty excited about it: Mazes for Programmers by Jamis Buck (Amazon link).


I figured this would be a good chance for me practice some functional programming -- and then I did it completely wrong.

Making Mazes
After reading the first 2 chapters, I was well on my way to creating mazes. I created some using the Binary Tree algorithm:


And some using the Sidewinder algorithm:


It's not hugely exciting so far, but it's a start. And it's nice to have something visual after just a little bit of work.

Very Object-Oriented Code
These mazes weren't created using functional programming, they were created with OO code (which I'll talk about in a bit). The book samples are written in Ruby. Here's the Binary Tree algorithm:


I'm not much of a Ruby programmer, so I did the same thing in C#:


You can grab my code from GitHub if you're interested: jeremybytes: mazes-for-programmers.

Functionally Challenged
So my goal is to get this running with F# because I need to practice to get comfortable with functional programming. I followed the book code in C# because I figured I'd have a better chance of understanding what was going on after I had a working version.

Yes, the code is very object-oriented: there is a Grid class consisting of a set of cells and also knows how to display itself; and there is a Cell class that knows how to link itself to other cells. I figured it was pretty safe to start with the algorithms, though.

If we look at the "Binary Tree" code above, we have a static method that takes a grid as a parameter and returns a grid. It doesn't rely on anything external to itself. This looked like a really good candidate to be converted over to a functional style using F#.

I didn't get very far. In fact, I created a complete mess (that didn't work). I ended up deleting everything I had.

I tried taking the C# code and breaking out bits and pieces into separate functions: the part that get the collection of neighbors of a cell, the part that creates a link based on a random value. The goal was to use these function in a mapping of the entire cell collection.

I wish I had kept the code just so I could show how wrong a direction I was headed.

Trying Again
I'm going to take another shot at this, but I need to understand more of the big picture first. For example, each Cell object knows about all the cells that it's "linked" to. So for example, Look at this picture:


The circled cell object knows that it is linked to 2 other cells: one on the "east" and one on the "south". But more than that, the cell has references to those other 2 cells.

What this means is that by starting with any individual cell object, we can create a graph of the entire maze by walking the links for each cell. This becomes important in Chapter 3 where we start looking for ways to solve a maze using Dijkstra's Algorithm.

Mazes for Programmers intentionally stays away from graph theory. But I think I'm going to have to learn some graph theory if I want to approach this from a more sane direction in the functional world.

Taking the existing objects which are linked to other objects which are linked to other objects... that's going to create a bit of a mess (at least with my current knowledge of these things).

Continuing
First tries aren't always successful. In fact, they can be a huge learning experience when you discover that you're headed in the wrong direction. When we recognize the wrong direction, we can step back and look at other options.

I'm going to continue coding through the book with C#. This will help me understand the problem space and the solutions. Along the way, I'll start looking into potential functional ways of implementing the code.

Rather than taking the current objects and shoving them into F#, I'm pretty sure there's a better approach. But for that, I'll need to do a bit more learning. Keep an eye out here (and on the GitHub code) to see where I end up.

Happy Coding!

Monday, March 13, 2017

Understanding Introversion (and Other Personality Features)

So, I recently finished reading Quiet: The Power of Introverts in a World That Can't Stop Talking by Susan Cain (Amazon link). I found this book to be very interesting and relevant to me. And it actually gave some names to things that I've noticed in myself.

I really wish that I had read this book sooner. I bought a copy of it last June (the receipt was still inside the book), but I didn't start reading it until last month.

I'm not really here to review the book, just point out some things that I found interesting. And I found a lot of things interesting. Here's a picture of all the markers that I dropped:

There is a bit of "Yay, Introverts!", but it's understandable. One very interesting observation is how the U.S. culture changed as more and more people moved into the cities.

The Extrovert Ideal
When people lived in small towns and rural areas, we knew all of our neighbors and the people that we interacted with. This meant that our judgments of other people were based on experience and reputation (although that's not always a great thing).

As people moved into the cities, now we are interacting with strangers on a regular basis. Who do we choose to do business with? Who do we choose for friends? Rather than relying on experience, we now have to make snap judgments based on first impressions. Now having an outgoing personality and winning smile is considered essential.

Introverts and Extroverts
I won't talk about the differences in being an introvert or extrovert because I've talked about that before: Becoming a Social Developer: A Guide for Introverts. The short version is that introverts get their energy internally while extroverts get their energy externally.

Insight: I'm Pretty Introverted
Cain presents a list of 20 (admittedly unscientific) questions to try to figure out how introverted or extroverted you are. I found that I answered all 20 toward the introversion side. This is not anything new to me. I know that I'm a pretty solitary person who enjoys the company of a few friends. I don't get bored when I'm alone. I love to read, think, and solve problems. Large gatherings and loud activities tend to exhaust me.

High-Reactives and Low-Reactives
Another thing that I was able to identify with is the idea of being a high-reactive. This stems from how people react to unfamiliar stimuli. A high-reactive person will tend to get agitated or nervous; a low-reactive will tend to stay calm.

This is not directly related to introversion and extroversion. There are high-reactive introverts and high-reactive extroverts.

Insight: I'm a High-Reactive
But this describes me pretty spot-on. When I go into a new situation or I'm doing something unfamiliar, I get extremely nervous. And it sometimes has to do with pretty ordinary things, like going to the eye doctor. This is why I can never take a polygraph test; just being tested will cause me to fail.

In addition, there's a tendency to observe things from the edges rather than just jumping in. That describes me pretty perfectly as well -- and I've written about that: High Risk vs. Low Risk. When I'm put into a conversation with people I don't know, I tend to observe and listen. I'm trying to figure out the "rules" before I join in.

Last month, I had someone point out that I was awfully quiet when she introduced me to some people that she worked with. This was because I didn't know the "rules" for interacting with that group of people. That is typical for me.

Public Speaking
Fear of public speaking is common across all people. And you would think that a high-reactive introvert would avoid it at all costs. But there are some people who enjoy it (including me). That enjoyment comes within some parameters.

Insight: I'm Fine When I'm Prepared
First, I have to be prepared. If I have time to figure out what I'm going to say in advance, I do just fine. I've confirmed the opposite. When I've been on panel discussions, I don't do very well. I'm a slow thinker, and I have trouble responding to ideas that I haven't had time to digest.

Second, I treat it like a performance. I have a role to play (more on that in a bit). If I understand that role and I'm prepared for it, I can execute on it just fine -- without falling into a panic.

Third, I have lots of repetition. I give the same technical talks over and over again. Some topics I have presented over 25 times. This means that I've heard most of the questions that people come up with, so I can answer confidently. And when I get a new question, I'm not afraid to say "I don't know. I'll need to look into that further."

All of these things combined have made me a successful public speaker even though my makeup fights against that.

A False Persona?
One thing that I've been concerned about is my stage persona. When I speak about technical topics (and some non-technical topics), I appear very extroverted. When I do this, am I still being true to myself?

Cain mentions a former psychology lecturer, Brian Little, who is an effective public speaker, quite boisterous on stage, and very entertaining. At the same time, he is an introvert who must find a quiet place to recharge between his presentations and interactions. That sounds familiar.

Little proposed the Free Trait Theory. The idea is that even though we're endowed with the trait of introversion or extroversion, we can act out of character in the service of "core personal projects", things that we care deeply about.

Insight: I Can Be Extroverted Regarding Things I'm Passionate About
So what comes out of this? It means that even though I am an introvert, I can act out of character when I'm doing work that I care deeply about. One thing that I care deeply about is helping developers learn about technology.

This is exactly what I'm seeing in my world. I'm not putting on an act. I'm still true to myself. I'm just behaving a bit differently than usual to reach a goal.

Encouraging False Behavior?
This all loops back to my work in encouraging people to be Social Developers. I've seen huge benefits from breaking out of my normal behavior to talk to strangers at developer events. Because I've seen these benefits, I want to encourage other introverted developers to try it and hopefully see some of those same benefits themselves.

It's a fine balance. I want to encourage people to try something new and scary. But I also want to make things as comfortable as possible (which is why I don't force people to talk to their neighbors in my presentations). And most of all, I want people to remain true to themselves.

Insight: A Social Developer Can Still Be True to Himself / Herself
Based on the idea that I can be extroverted about things that I'm passionate about, I don't have a problem with encouraging other people to do the same thing. Talking to strangers is outside the standard introvert behavior. But we can change our behavior for a good reason. In this case, it's expanding our knowledge, our circle of influence, our resources, and our friends.

So I don't feel like I'm encouraging people to change who they are. Instead, I'm encouraging people to change their behavior for something they care deeply about. (And hopefully I can encourage them to care deeply about it by showing the benefits I've found in my world.)

Wrap Up
I really enjoyed reading Quiet by Susan Cain. I don't know that I found out anything "new" about myself. But this definitely brought ideas into focus for me. I'm able to understand myself a bit better. I realize that who I am is normal, and there are plenty of other people out there just like me.

And with this better understanding of myself, I can better understand the people around me. I can recognize how we are the same and how we are different. That will lead to better interactions overall.

Happy Coding!

Sunday, March 12, 2017

1250 Miles, 2 Cats, and a Banjo

Now for something a bit different. During February, I chucked the cats in the car and drove up to northern Washington. The Skagit Valley is really beautiful.

If you're interested in pictures, you can check out the album:
1250 Miles, 2 Cats, and a Banjo
(Okay, so it was actually 1250 miles each way. So 2500 miles with cats in the car. Oof.)

After 2 days in the car, the cats were happy to be anywhere (although I'm sure they would have rather been at home). They settled in after a couple days, and it almost seemed like they enjoyed it.

The weather was a bit different each day. After I arrived, there was snow for a couple days covering everything with about 4 inches of really fluffy snow. Then the sun came out and brightened things up. Then it alternated among overcast, rain, and a little bit of snow, with some sunshine thrown in to make things interesting.

Fortunately, I got accustomed to the cold while I was in London (where the temperature was in the low 40s). In Washington, it varied from the 30s to the 50s, but I had the coat and scarf and hat to keep me nice and warm. Much different from Southern California where I'm in short sleeves most of the year.

Just across the road from where I stayed, there was a great trail that went down to the Skagit River. The river was really beautiful (and the water was incredibly cold). It was nice to see it in the snow and the sunshine and the rain.

We took several side trips, including the Seattle Aquarium, the Freemont Troll, the Woodland Park Zoo, a ferry ride to Port Townsend, Whatcom Falls, Darrington, Anacortes, and Bellingham.

I ended up picking up used books at several places. Somehow, I managed to collect 13 books, including a US Army edition of King Solomon's Mines. Most of the other books were pulp sci-fi (I have a weakness for Larry Niven stories). And I came across a 70s sci-fi book called The Methuselah Enzyme that looks really interesting (in a cult-classic sort of way).

It was really nice to be away from the world for a while. I had time to read and relax and tromp through the woods (and the snow made a wonderful crunching sound). There was also time to watch movies and put together jigsaw puzzles. It was really hard to leave; I even extended my stay a few more days.

Altogether, I was away for 25 days, including the 2 days in the car getting back to So Cal.

(BTW, her name is Kelly, and she was the reason for the journey.)

Thursday, March 9, 2017

Speakers, Let's Change Our Terminology: No More Rejections

[Update: There's a huge, awesome update to this story, so be sure to scroll all the way down.]

I'm probably just getting philosophical in my old age, but how 'bout we, as speakers, change our terminology regarding whether we are selected to speak at an event:
No longer "Rejected"
Now "Not Selected"
This came up when my friend Jonathan Mills (@jonathanfmills) was dealing with the joys and sorrows of selecting sessions for KCDC (link: https://twitter.com/jonathanfmills/status/839957293550673920):


This got me thinking a bit, particularly since I wrote about the topic earlier this week: Rejection Gets Harder (Not Easier). What can we do to change our perceptions to make this process more productive?

Words Have Meaning
It seems like I've run into a number of different examples of how the words we use change the perception of the situation. A big example is the difference between "Sorry" and "Thank You".

When you keep someone waiting...
Don't say, "Sorry I'm late."
Instead say, "Thank you for waiting."
This changes the tone of the statement and injects gratitude into the relationship. The same thing is true when a speaker thinks about being "accepted" or "rejected" for an event. These words have meaning that may not really apply.

Let's look at an example, let's say that I decide to play Xbox. I've got a number of choices:


If I choose to play "Zoo Tycoon", I'm not rejecting "Batman Arkham Knight" or "The Witcher 3". I'm selecting the item that best matches my current needs (whether relaxation or catharsis), and I can only accommodate one selection. The other items just remain unselected. (Of course, I may decide to forego Xbox and watch "Rocky and Bullwinkle" instead.)

"Rejected" implies that someone made a conscious choice to exclude you from the selection process. This translates into "We don't want you." This may be true in some cases, but the vast majority of events get way more submissions than they can possibly accept.

"Not Selected" implies that other choices were made in preference. This may mean, "We really like you, but we don't have space for everyone."

A Speaker Problem, Not an Event Problem
The terminology of "accepted" and "rejected" is not coming from the events themselves. I think that events go out of their way to avoid the term "rejected". Here's an example from a recent event notification that I received (and I've got lots of examples):
"We regret to inform you at this time that your papers were not selected."
This is pretty common, but we as speakers tend to translate this into "rejected".

Change Your Words, Change Your Thoughts
As I mentioned in the previous article, it's really easy to take rejection personally even though it isn't personal. But by changing how we refer to things, we can change how we think about things.

I'll be the first to stop using the word "rejected". I will now say that I wasn't selected. I know that I'm good at what I do. I know that my talks are useful. But I also know that there are other speakers and topics that are better fits for a particular event than I am.

And that's okay.

Huge, Awesome Update
This topic had been on my mind for a while. A couple of events that I have submitted to use PaperCall.io to collect submissions and handle selection. I noticed that the site used the term "rejected", so I tweeted about it.

To my huge surprise, PaperCall.io responded within just a few minutes of the tweet:


Then 2 hours later, they implemented the changes (tweet link):


I immediately went out to my profile, and found that the updates were already in place (I had grabbed a screenshot from before the updates were made):


A big thanks to PaperCall.io on getting on board with this idea and jumping on it so quickly. This is really amazing.

Happy Speaking!

Tuesday, March 7, 2017

Rejection Gets Harder (Not Easier)

When starting out as a speaker, you get a lot of rejections. It takes a while to get used to, particularly because you're never quite sure why your submission was rejected. I don't take it personally (at least that's what I say publicly even though it does feel a bit like a personal rejection).

Different events have different priorities: sometimes they are looking for particular topics, sometimes they are looking for particular speakers, sometimes they put preference on local speakers to build the community, sometimes they are looking for brand new sessions, sometimes they are focused on a particular audience.

You generally don't get feedback for a rejection. (I don't think I've ever received feedback from a rejection.) Many times events get so many submissions that they can't go through and say why a particular session was *not* selected. Often times, it's just that they have too many submissions for each slot, and you're number 105 when there are 100 openings.
Look to the next event on the list, trust that you'll find the right audience, and keep moving forward.
When you're first starting out, this isn't as big of a deal. Yes, it hurts when someone says "no". But it's also pretty much expected, particularly when you don't have much of a track record.

Fewer Rejections
Something I didn't expect is that rejection has gotten harder as I've been accepted at more places.

Here's why: early in my speaking journey, I would submit to a lot of events, and I would get selected for a few of them. It was really easy to double- or triple-submit for a particular time frame because there was no way that I would get selected for more than one of them.

But I hit a turning point, and I started to get more acceptances than rejections. I actually ran into a problem with this last year. I was accepted to two events for the same time period, and I had to decline an acceptance. (I actually had to do this twice.)

No More Double-Submissions
After this happened to me, I stopped double-submitting. This is because I know how difficult it is for a selection committee to get a line up that works well for their event. When someone backs out, it leaves a hole that they need to back fill.

In order to make sure that doesn't happen, I no longer submit for more than one event for the same time period. Often I don't submit for two events that are back-to-back so that I won't be too tired from attending multiple events during a single trip. (I did this one time last year; it was a great experience, but I was exhausted. It's not something I want to do again.) This is especially important since I am committed to being present at events, and I want to be able to talk to as many people as possible.

Picking the "Right" Events
So now comes the hard part. Now I have to select which events I'm going to submit to. This means picking one event over another (and sometimes over two others). And that makes each rejection that much harder.

For example, last year I submitted to a particular event that I was pretty sure I was going to get in to. There was another event that I really wanted to speak at as well, but the dates overlapped. Well, I submitted to the first event (and not the second). There were a couple of reasons for this decision (including travel cost), but I got rejected from the first event. That left a gap in my schedule, and I was left wondering if I had made the wrong decision.

Finding the Right Audience
In my particular case, I have a pretty specific focus: I deal with mid-level language features and patterns. You can look through my presentation topics to get an idea of what that is. These are core skills that are important for developers, but they aren't new or shiny.

No Feedback
It is difficult when you don't get feedback from an event. For example, if I knew that an event was only looking for fresh topics that haven't been presented before, then I would know that I'm not a good fit for that. If I knew that an event was focused on "what's new", then I would know that I'm not a good fit for that. Some events put this in their descriptions, but many do not.

"Wrong" Decisions, New Opportunities
The end result is that I do make "wrong" decisions, but those sometimes work out for the best. For example, remember the event I mentioned above where I got rejected? Well that opened up additional time for another event I was already scheduled to attend. Because of that, I was able to add a workshop for that event, and I got some good experience with a full-day format.

I've also received a rejection from an event I was planning on speaking at this summer, and I chose not to submit to another event in order to leave space for it. It was hard to get the rejection, but I think it will all work out for the best. I have some changes coming up in my life and having some free time during the summer is probably just what I need.

Rejection Gets Harder
When I have to pick among three events for a time period, I never know if I'm making the best decision. For the events that I know, I can make a pretty intelligent choice (Yes, this is the right audience for me. No, I don't quite fit in with what they are looking for.) But for the events that I don't know, I have to take a gamble.

As someone who loves to speak, I hate to miss out on opportunities. At the same time, I'm better off speaking in front of the right audiences.

This is one reason why I asked people to contact me if they want me to come to their events. If someone wants me at their event, then I know that I'll probably have the right audience. This makes it easier for me to prioritize things on my schedule.

The good news is that I have gotten to know a lot of event organizers. And I've also managed to build a good reputation at the events I've spoken at. This has opened up a lot of opportunities for me.

[Update 03/09/2017: On further thought, I'm going to remove the word "rejection" from this scenario. Read more here: Speakers, Let's Change Our Terminology: No More Rejections.]

No Second Guesses
Ultimately, when you're rejected from an event, you have to accept that you won't know why. And it's really easy to second-guess reasons. But don't do that.

Instead, look to the next event on the list, trust that you'll find the right audience, and keep moving forward.

Happy Speaking!

Monday, March 6, 2017

Rediscovering Fire: Effective Learning?

So I've got a bit of a dilemma. I ran across an article today (thanks to Tomas Petricek (@tomaspetricek) for pointing it out), and after drilling into it a bit, I felt like I've been rediscovering fire while I've been learning functional programming.

So here's the question:
"Does the rediscovery make the learning more effective?"
The Article
The article in question is from Eirik Tsarpalis (@eiriktsarpalis): F# and Purity. This is a great read, particularly if you've been trying to reconcile functional and imperative programming (like I have). Go read it now.

But as I read the article (and started following some of the links), I found quite a few things that looked familiar.

Down the Rabbit Hole
When I started learning functional programming, I tried to be "pure", meaning that I wanted to use functional concepts all the way down. Eirik points to an article about Fibonacci Sequences by Adam Esterline: Fibonacci Sequence in Haskell. If you've tried to write Fibonacci sequences in Haskell, go read this now.

Haskell by it's nature is a "pure" functional language in that it doesn't let you do those imperative things that we have access to in things like F#. But there are still different ways to implement the Fibonacci sequence.

Adam points to the "Slow but Easy" method using recursion. This looked very familiar, because I created something very similar, thinking that recursion was the "right" solution to this problem.

Here's my code (more on this here: A Functional Fibonacci Sequence (as learned by an imperative programmer)):


This code works, but it is *SLOW*. It takes over 20 seconds to calculate the 35th place. And it just gets slower from there.

Adam shows a similar slowness and points to a solution in Haskell using "zipWith". This is a solution that I ran across as well:


This solution is *FAST*. I thought I understood how this worked (and tried to explain it a bit in my article), but Adam points to a better explanation on StackOverflow from someone who understands how Haskell works: Understanding a Recursively Design List. (You should definitely read this as well.)

Granted, Adam's article was published after mine, but the StackOverflow answer was published years before mine. So this information has been around for a while.

So I struggled through this problem (speed of the recursive implementation), and I asked questions from functional devs who have much more experience than I do. This questioning led me to look for other solutions, and it made me understand that I wasn't "doing it wrong" because I didn't use a standard recursive function implementation.

Popping the Stack
So back to Eirik's article. The core of the article talks about how "pure" functional programming is all based on mathematical functions, but our CPUs and environments aren't really set up to deal with these things. Instead, our environments (in my case, Windows and .NET) are really set up to deal with imperative programming.

The result is that if we program only with pure functions, we often run into issues of performance, heap usage, and even stack overflows (which I'm pretty good at generating).

The solution is a compromise: we keep our functions externally "pure", meaning discrete input leads to deterministic output, no mutation or shared state, etc. But we can use imperative code inside of those functions. We just need to make sure the imperative bits don't leak out of our functions.

Again, this sounded really familiar. When I was working on my Digit Recognition application, I was using code from Mathias Brandewinder's book on machine learning. I ran into some performance issues. The functions that he created were great for batch processing, but I was running the functions in a different way, which meant I was running them over and over again.

Here's the original function (you can read more about it here: Exploring the Digit Recognizer with F#):


To me, this seemed like the "right" way of coding this. It was using the functions on the Array object, and it was piping results from one function to another. But this was *SLOW*.

I had a chance to talk to Mathias about this. I showed him my F# code (above) and also the C# code that I had (which used "for" loop). The C# code was significantly faster. So he said that we could do the same thing in the F# code:


This made things significantly faster. I'm really glad that Mathias recommended this because he is a serious functional programmer, and it was like it gave me permission to cheat.

But when I looked at it more closely, it really wasn't cheating -- for the same reasons that Eirik gives in his article. In this case, there is mutable state inside the function, but that mutation never leaks out. It is contained in the function itself. From the outside, this function is "pure" it takes 2 arrays and returns a deterministic result.

(If you're interested in the Digit Recognizer project, here's where you can find all the articles: Machine Learning (sort of)).

Rediscovering Fire
I feel like quite a bit of my learning in programming has been about rediscovering fire. These are just two examples from the functional programming world. And that brings us back to the original question:
Does the rediscovery make the learning more effective?
I know that in my case, going through the pain of finding out that my solution had serious performance issues is what spurred me to look for other solutions.

Pretty much every talk that I do is based on some pain or hurdle that I had in my development career. My goal is to help other developers over those hurdles. I get stuck easily, and I also get easily frustrated. I don't want other folks to get stuck and frustrated.

Finding the Balance
If we are constantly rediscovering fire, then we won't make progress beyond those who came before us. We'll just keep walking the same road over and over again.

If we don't go through the pain ourselves, then we don't fully appreciate the solutions that we are using. I know that when I was a young programmer, I didn't think that I needed to follow "best practices" (okay, so I really hate that term, but I'll use it anyway). When I got myself into trouble too many times, I finally learned that "best practices" are a good place to start, particularly if I'm new to an environment.

There's a balance somewhere here. A place where we can learn from our own pain, but we can also learn from the people who came before us.

I need to keep this balance in mind for myself and also for the developers that I teach on a regular basis.

Happy Coding!