Ruby, etc

Learn all the things

He who enjoys doing and enjoys what he has done is happy. - Fortune Cookie

Cool Things in Clojure 1.9

I was glad to see Clojure 1.9 out because of Spec and some more things. But, was sad, because I can no longer say “Hey! I have a commit in the latest version of clojure!”. Course, that just gives me some motivation to find ways to help out in .. Clojure 2.0 ?? OMG. I don’t like to brag, but it was fun when this guy in my community (mostly he didn’t do Clojure) when he heard I had a patch in 1.8, come up to me and say “BADASS!!! WAY TO GO!!!”. I did have the help of Alex Miller and others and it was partly done when I took it over. It was really fun to be a small part of 1.8

Here are the things I think are cool (besides Spec) in Clojure 1.9:

Reader Syntax for Namespaced Maps

1
2
3
4
5
user=> (def data #:person{:name "Nola", :color "purple", :state "TX"})
#'user/data

user=> (keys data)
(:person/name :person/color :person/state)

Using #:ns-name{ key value key value } gives you an easy way to write out your map without prefixing each key. COOL.

Predicate Functions

This were put in mainly (I think) to support Spec, but in short, predicate functions (ending in ?) return true or false.

Some of them added in this patch are:

  • boolean?
  • int? pos-int? nat-int?
  • double?
  • ident?
  • qualified-keyword?

For example, Using remove with a collection will remove all values for which the predicate is true. So to remove all the postive integers from a vector:

1
2
user=> (remove pos-int? [-4 -2 4 1 0 -2 5])
(-4 -2 0 -2)

Then of course, in a spec:

1
2
3
4
5
6
7
8
user=> (s/def ::age pos-int?)
:user/age

user=> (s/conform ::age -16)
:clojure.spec.alpha/invalid

user=> (s/conform ::age 13)
13

Then lets remove everything not a qualified keyword, using in an anonymous function::

1
2
user=> (remove #(not (qualified-keyword? %))  [:name/nola :color/purple 1 5 0])
(:name/nola :color/purple)

Previous you could do the samething of course, but you’d have to write more code. I don’t know if you would use them much outside of spec, but if you do there they are there. Nice.

Atoms get new functions!

Ever wanted to give an atom a new value but also get back what the value was too?

1
2
3
4
user=> (def name (atom "Nola"))

user=> (reset-vals! name "Nick")
["Nola" "Nick"]

Instead of just reset! you now have reset-vals! returning the old value followed by the new (current) value. And this funtion’s cousin swap-vals!:

1
2
3
4
5
user=> (def size (atom 10))
#'user/size

user=> (swap-vals! size inc)
[10 11]

This function, swap-vals! takes an atom and a function and returns the new and the old value.

And before you bikeshed on the names of these functions, don’t bother, it has been done. I think they are good names :)

Brew Install

Not exactly a part of the Clojure 1.9 Release Notes but I think it bears mention along with this release is that for you Mac Users (like me!), you can now brew install clojure. I wrote about it early because I was so excited. Read the post for more details which also links to more documentation on it.

And also if you are an new Clojure dev, with Atom you can setup a decent Clojure environment with Atom. I recommend looking over the docs for parinfer to learn its magics, but once you get it you are good for life.

I hope you are excited about Clojure 1.9 and are using it in your projets :) It was a long time coming, but the best things are worth waiting for, right? :)

One-Liners in Clojure and Ruby

A quick post to start off the new year.

You and your co-workers can’t decide where to go for lunch?

1
2
 ruby -e "puts [:tacos, :chicken, :bbq].sample"
chicken
1
2
 clj -e "(rand-nth [:tacos :chicken :bbq])"
:tacos

Observations:

Ruby I had to tell it what to do with the output, to puts it. It didn’t automatically display like if I had done that line in the irb repl. Oh and don’t do what I did at first and forget the , (comma) :)

Clojure, since everything returns a value, I just had to call the function.

Have fun using code to make important decisions, like .. Lunch :)

Getting Started With Clojure Is Now Easier Than Ever - on a Mac

As of Dec 8, 2017 a brew recipe has been added to install Clojure with brew install clojure and it gives you commands clj and clojure.

To try it out, I created a file, test.clj with the following:

1
2
3
4
5
6
7
#!/usr/bin/env clojure

(println "Hello World")

(println (+ 1 2 3 4 5))

(println (clojure.string/upper-case "hello world"))

After you make it executable with:

1
chmod u+x test.clj

You can execute it:

1
2
3
4
▶ ./test.clj
Hello World
15
HELLO WORLD

A popular way to play with Clojure is to use a repl. You can start a repl, by using either clj or clojure without a file name

1
2
3
4
5
6
7
8
 clojure
Clojure 1.9.0
user=> (+ 1 2 3 4)
10
user=> (apply str [1 2 3 4])
"1234"
user=> (map #(* 2 %) [1 2 3 4])
(2 4 6 8)

I was curious about commands clojure and clj and found an explaination of how it works.

You can have a deps.edn file to include dependencies. At first I was confused on :mvn/ prefix, and thought how to include a library from clojars? So I looked farther and found that :mvn includes this group of locations (which includes clojars), as shown here.

1
2
3
{:mvn/repos
 {"central" {:url "https://repo1.maven.org/maven2/"}
  "clojars" {:url "https://repo.clojars.org/"}}}

to test this out, I created a directory and put a file deps.edn file with the following:

1
2
{:deps
 {anagrams {:mvn/version "4" }}}

Anagrams is a fun little library I found browsing clojars. It takes a list of words separated with \n and finds words that are anagrams of a word you give it. My example is a little contrived, but see it working:

Start the repl in that same directory, if needed it will download and install dependencies:

1
2
3
4
5
6
7
8
9
10
11
12
13
 clj
Clojure 1.9.0
user=> (require '[anagrams.core :as a])
nil

user=> (a/set-word-list! "cat\ntac\natc\ndog\ngod\ntaco")
"done"

user=> (a/anagrams-of "cat")
#{"tac" "atc" "cat"}

user=> (a/anagrams-of "dog")
#{"dog" "god"}

Cool, that’s fun :)

A new way to try out Clojure.. (on a mac at least). Pretty easy!

Data Structures in Clojure and Elixir: Structs and Records

Both Elixir and Clojure have a way to make a more “organized” entity, like a map but more structure. Elixir can easily have default values whereas with Clojure, it is not built in but you can create a helper functions to set some default values and create a record.

Elixir

A defstruct takes on the name of the defmodule it is in:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
iex(1)> defmodule User do
...(1)>   defstruct name: "", state: "", color: "green", size: "M"
...(1)> end
{:module, User,
 <<70, 79, 82, 49, 0, 0, 8, 60, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 232,
   0, 0, 0, 22, 11, 69, 108, 105, 120, 105, 114, 46, 85, 115, 101, 114, 8, 95,
   95, 105, 110, 102, 111, 95, 95, 9, 102, ...>>,
 %User{color: "green", name: "", size: "M", state: ""}}

iex(2)> %User{name: "nola", state: "TX"}
%User{color: "green", name: "nola", size: "M", state: "TX"}

iex(30)> user.name
"nola"

iex(30)> user.color
"red"

Using an attribute that doesn’t exist:

1
2
3
4
iex(32)> user["country"]
** (UndefinedFunctionError) function User.fetch/2 is undefined (User does not implement the Access behaviour)
    User.fetch(%User{color: "", name: "nola", state: "TX"}, "country")
    (elixir) lib/access.ex:304: Access.get/3

Yeah don’t do that :) Accessing a key not defined is not good.

Clojure

First define a record with defrecord and a vector for the names of the attributes:

1
2
user=> (defrecord DataRecord [name state])
user.DataRecord

Then create a record

1
2
user=> (def data (->DataRecord "Nola" "TX"))
#'user/data

Access the values just like a map:

1
2
3
4
5
user=> (:name data)
"Nola"

user=> (:state data)
"TX"

Or create using a map:

1
2
user=> (map->DataRecord {:name "bob" :state "IL"})
#user.DataRecord{:name "bob", :state "IL"}

To create a Record that may have default values, create a helper function to build it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
user=> (defrecord Person [name state color size])
user.Person

user=> (defn create-person [{:keys [name state color size] :or {color "green" size "M" }}] (->Person name state color size))
#'user/create-person

user=> (def data (create-person {:name "bob" :state "TX"}))
#user.Person{:name "bob", :state "TX", :color "green", :size "M"}

user=> (:name data)
"bob"

user=> (:state data)
"TX"

user=>

I wrote about Clojure records awhile back, See more on records.

See my previous posts on Maps, Lists, Tuples, Vectors and Sets.

Data Structures in Clojure and Elixir: Maps

Elixir

Tuples used { } .. but maps use %{ }. You can use anything for a key.. here are string keys:

1
2
3
4
5
iex(1)> data = %{"name" => "nola", "color" => "red"}
%{"color" => "red", "name" => "nola"}

iex(4)> data["name"]
"nola"

If you use a string to set the value, obviously you need to use that to get the value.

Using atoms for keys is alot nicer for maps, the syntax is shorter and you can use .name to access the value

1
2
3
4
5
iex(2)> more_data = %{city: "Austin", state: "TX"}
%{city: "Austin", state: "TX"}

iex(5)> more_data.city
"Austin"

I don’t know why you would, but you can use integers as keys too:

1
2
3
4
5
iex(3)> yet_more = %{1 => "user 1", 2 => "user 2"}
%{1 => "user 1", 2 => "user 2"}

iex(12)> yet_more[1]
"user 1"

And, even a list as a key:

1
2
3
4
5
iex(8)> weird_keys = %{ [1, 2] => "one two", [3, 4] => "three four"}
%{[1, 2] => "one two", [3, 4] => "three four"}

iex(9)> weird_keys[[1,2]]
"one two"

I can’t think of a use case for that, but if you need it, then you can do it.

Some methods for maps:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
iex(6)> Map.keys(more_data)
[:city, :state]

iex(7)> Map.keys(data)
["color", "name"]

iex(13)> Map.keys(weird_keys)
[[1, 2], [3, 4]]

iex(14)> Map.values(weird_keys)
["one two", "three four"]

iex(25)> Enum.count(weird_keys)
2

Updating a value in a map

1
2
3
4
iex(15)> data = %{color: "red", name: "nola"}

(16)> updated = %{data | color: "pink" }
%{color: "pink", name: "nola"}

Using the | operator with either syntax for strings or atom keys (whichever you are using) ie `”color” => “pink”’.

But if the key does not exist, you will get an exception!

To add a new key to a map, you use Map.put_new:

1
2
3
4
iex(1)> data = %{color: "red", name: "nola"}

iex(2)> Map.put_new(data, :state, "TX")
%{color: "red", name: "nola", state: "TX"}

If the key was already there, the change is ignored.

To add a new key to a map reguardless if it was there before or not use:

1
2
3
4
5
6
7
8
iex(10)> data = %{color: "red", name: "nola"}
%{color: "red", name: "nola"}

iex(11)> more = Map.put(data, :color, "green")
%{color: "green", name: "nola"}

iex(12)> Map.put(more, :state, "TX")
%{color: "green", name: "nola", state: "TX"}

Still, the data is not actually changed but a copy is returned. The original is unchanged.

Clojure

1
2
3
4
5
user=> (hash-map :name "nola" :state "TX" :color "red")
{:color "red", :name "nola", :state "TX"}

user=> (array-map :name "nola" :state "TX" :color "red")
{:name "nola", :state "TX", :color "red"}

I was trying to figure out what the difference was and found this on stackoverflow

Array maps and hash maps have the same interface, but array maps have O(N) lookup complexity (i.e. it is implemented as an simple array of entries), while hash maps have O(1) lookup complexity.

If you notice in my code above, the hash-map has the keys in a different order than I created them in.

So, thats the difference.

Using the literal { } it produces an array-map.

1
2
user=> (class {:name "Nola" :state "tx"})
clojure.lang.PersistentArrayMap

Some functions for maps:

1
2
3
4
5
6
7
8
9
10
11
user=> (def data {:color "red", :name "nola", :state "TX"})
#'user/data

user=> (keys data)
(:color :name :state)

user=> (vals data)
("red" "nola" "TX")

user=> (count data)
3

Editing or adding new keys to a map:

1
2
3
4
5
user=> (assoc data :state "IL")
{:color "red", :name "nola", :state "IL"}

user=> (assoc data :food "tacos")
{:color "red", :name "nola", :state "TX", :food "tacos"}

Unlike Elixir, Clojure doesn’t care if this value is new or not when updating a map. It also doesn’t change the original data structure like Elixir.

Let me know if I am understanding these languages right. Next post will talk about Elixir Structs and Clojure Records.

See my post on Lists, Tuples, Vectors and Sets.

Data Structures in Clojure and Elixir: Sets

My last post talked about Lists, Tuples and Vectors comparing Elixir and Clojure … now lets cover a related topic.. sets.

When you think of set, think of Math Sets.

Elixir

There are two ways to create a Set in Elixir

Using the Pipe Operator and put:

1
2
set = MapSet.new |> MapSet.put("apple") |> MapSet.put("apple") |> MapSet.put("banana")
#MapSet<["apple", "banana"]>

Or use a List and pass that to MapSet.new

1
2
iex(1)> set = MapSet.new(["apple","orange","grape", "grape"])
#MapSet<["apple", "grape", "orange"]>

I purposely put duplicates when I created it to see what would happen. It quietly dismissed the duplicate value and made a collection of unique values.

Passing a list to new would be a good way to filter out duplicates in a collection as well as build a set more easily.

1
2
iex(3)> unique_values = MapSet.new(["apple","orange","grape", "grape"]) |> MapSet.to_list()
["apple", "grape", "orange"]

Some more functions for sets

1
2
3
4
5
iex(4)> fruit = MapSet.new(["apple","orange","grape"])
#MapSet<["apple", "grape", "orange"]>

iex(5)> MapSet.member?(fruit, "apple")
true

and subset

1
2
3
4
5
6
7
8
iex(4)> fruit = MapSet.new(["apple","orange","grape"])
#MapSet<["apple", "grape", "orange"]>

iex(6)> other_fruit = MapSet.new(["apple", "grape"])
#MapSet<["apple", "grape"]>

iex(8)> MapSet.subset?(other_fruit, fruit)
true

Read more on MapSet

Clojure

You have two ways to make a set in Clojure, using the set function and the #{} literal.

1
2
3
4
5
user=> (set [:apple :grape :orange :orange])
#{:orange :apple :grape}

user=> (set '(:apple :grape :orange :orange)
#{:orange :apple :grape}

We are converting a vector or a list to a set.

Also testing putting duplicates and as expected, the result is all unique values.

1
2
3
4
user=> (def taco-restaurants #{"torchys" "maudies" "torchys" "taco bell"})

IllegalArgumentException Duplicate key: torchys  clojure.lang.PersistentHashSet.createWithCheck (PersistentHashSet.java:68)
RuntimeException Unmatched delimiter: )  clojure.lang.Util.runtimeException (Util.java:221)

No, the error is not calling taco bell a restaurant, it is putting torchys twice. YIKES… the literal syntax does not like duplicates. If you think your values might have duplicates, put in vector first and pass to set.

Edit: Alex Miller pointed out, the reason we have an error it because it is an invalid set. Now I think it should error and since Elixir doesn’t have a literal syntax it is not exactly the same thing to compare. Thanks for pointing that out why it errors Alex :)

Some useful functions for sets:

1
2
3
4
5
6
7
8
user=> (def valid-actions #{:get :post})
#'user/valid-actions

user=> (contains? valid-actions :post)
true

user=> (contains? valid-actions :head)
false

Use a set when you need to see if a certain value is one of X. It is surprisingly not easy to do the same with checking membership in a list or vector :) Use a set, you don’t need duplicates anyways so it makes sense.

There is a Set namespace with functions for sets:

1
2
3
4
5
6
7
8
user=> (require '[clojure.set :as set])
nil

user=> (set/subset? #{:post} valid-actions)
true

user=> (set/subset? #{:head} valid-actions)
false

Next, we’ll cover Maps!

Data Structures in Clojure and Elixir: Lists, Tuples, Vectors

In my free time I’ve been learning more Elixir, and I’ve already been doing Clojure for awhile now. I am going to write this blog post to compare/contrast the data structures available in both languages as well as a few functions you can use. Just for fun and so I can keep it in my head.

List / Vector

This is aslso known as an array in some languages. This is a collection of items, in which case order is generally depended on to access items. When I am explaining this to new developers I describe it as a bookshelf, each book on the shelf is an element.

Elixir

We have two kinds of these in Elixir, a Tuple and a List. A Tuple is fast and intended to be for short (<= 4 items) and a List is stored as Linked List. It is much slower than a Tuple because it is stored as a Linked List (if you are not familiar, under the hood, each item in the list has a pointer to the next item).

Lists are defined using [] Here’s what it looks like:

1
2
iex(1)> favorites = ["bbq", "tacos", "pizza"]
["bbq", "tacos", "pizza"]

Then some methods to access items in a list:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
iex(2)> Enum.at(favorites, 0)
"bbq"

iex(4)> Enum.at(favorites, 2)
"pizza"

iex(5)> List.first(favorites)
"bbq"

iex(6)> List.last(favorites)
"pizza"

iex(7)> length(favorites)
3

Notice that length is not part of any namespace, it’s part of Kernel which doesn’t need prefix of module name (as you might expect) … it is the same place that def, defmodule, if and hd are defined.

A tuple is define with { }:

1
2
iex(7)> not_favorites = {"shrimp", "squid", "octopus"}
{"shrimp", "squid", "octopus"}

Then accessing elements is like this:

1
2
3
4
5
6
7
8
9
10
11
iex(7)> not_favorites = {"shrimp", "squid", "octopus"}
{"shrimp", "squid", "octopus"}

iex(8)> elem(not_favorites, 0)  # index of first item is 0
"shrimp"

iex(9)> elem(not_favorites, 2)  # index of third item is 2
"octopus"

iex(10)> tuple_size(not_favorites)
3

Tuples are often used as return values from functions and for pattern matching in case statements. I dont often see the elements of a tuple accessed with elem, most of the time I’ve seen it decontructed with pattern matching. But if you need it, you that is how you do it.

Clojure

Clojure has two kinds of sequential containers … Vectors and Lists. A vector is more efficient adding to the end, where as a list (think single linked lists) is more efficient adding to the front.

1
2
3
4
5
6
7
8
9
10
11
user=> (def favorites ["pizza" "tacos" "cake"])
#'user/favorites

user=> (def not-favorites '("squid" "shrimp" "octopus"))
#'user/not-favorites

user=> (first favorites)
"pizza"

user=> (rest not-favorites)
("shrimp" "octopus")

The ’ in front of a list tells clojure don’t evaluate this right now.. which you’ll see why next.

Take this code:

1
(def name "nola")

It defines a value of “nola” which you can refer to as “name”. It’s not exactly like a variable that you might thing of from other languages, but for now lets say it is close.

However notice something about a list and code:

1
2
3
4
5
6
7
8
9
10
11
user=> (count '(1 2 3))
3

user=> (count '(def name "nola"))
3

user=> (first '(def name "nola"))
def

user=> (rest '(def name "nola"))
(name "nola")

This code is defining a value called name to be nola … is itself a list. So you may hear Clojure people chant “code is data. data is code.” and this is what they are talking about. It took me awhile to get it then it seemed so simple.

Next post I will talk about Sets in Elixir and Clojure.

Managing My Tasks

Some one asked me how I manage my tasks and I showed him but I thought it would make for a good blog post. I’m not saying I am the perfect solution but this is what works for me.

For long term storage of projects, tasks and ideas I use Omnifocus. I have used it for 7 years. I initially got a free copy of the Mac app because I know someone who works there but since then I’ve paid for updates and bought it for iPhone and iPad. It is really handy for whatever device I have in my hand at the moment. They provide a sync service so all my apps are in sync. I can put ideas into the Omnifocus “inbox” via my phone then later put them in the right place when I am on my mac. Omnifocus is only available on apple platforms.

The key feature for me with Omnifocus is the Review Tab, which I often use the iPad. It steps through each project allowing you to change due dates for tasks, flag, or delete.

No system will work unless you have a way to review! You can use a spreadsheet, stack of index cards (See hipster pda) or trello. But unless you review regularly it is junk. The fact this is one of the side tabs in Omnifocus is Review is the #1 reason I have used it this long.

If you are disciplined enough to review without that, then good for you. Maybe you don’t need Omnifocus :).

For very short term (ie todo this week) I’ve used a variety of things. Trello. Google Spreadsheets. Index cards … right now I have been using org mode in emacs partly for fun to learn it. I commit the files to github in a private repo. I use org-pomadoro to set a 25 minute timer (especially when I really need to focus) and it makes a log section under the task.

This time last year, I was using index cards. One per project, with tasks written out. When I was working on a project I would put that card on top to remind me to stay focused. When I was done, I recorded the project done in OmniFocus and threw the card away.

And even longer ago, I used Google Spreadsheets. I had one tab per project with the tasks listed out. It was easy to get to on multiple devices (hard to edit on a phone but not impossible).

I get bored easy, so maybe thats why I switch my short term tasks planning, but that keeps it fun.

Anyways, hope I’ve given you some ideas on manging your own tasks, both long term and short term :)

What I Wished I Knew

A few things I wish I knew when I started my career as a software developer.

Go to User Groups! I was working for 2-3 years before I got the courage to go to my first user group. Now I currently run one, and have in the past run more than one. Get out there and meet people, if it is a long commute to the meeting or you have little kids at home (often an excuse/reason I hear) then maybe only go every 2-3 months. It is a sacrifice you must make for your career.

This one has occasionally blocked me: The language you did when you started doesn’t have to be the one you are doing now. People change and the language they used at one time (PHP) may not appeal to them anymore and IT IS OK TO CHANGE. And when you do, you don’t need to make a big deal about it. I’ve seen some recent “I’m done with ruby! and here’s why it sucks” posts. If you are done with Ruby, then fine.. just go :) You probably don’t even need to write a blog post on why.

I see friends/associates of mine that are relentless on making their favorite language do things that maybe is not best, when other languages are better. It is such a waste of time, energy and resources. So don’t get too tied to the langauge because it may not be best for all things. Learn the principles and concepts of a language so learning another is just a matter of syntax and idioms.

I hoped I made you think about a few things and maybe save you some disappointment. What did you learn that you wished you knew when you started?

Interview Prep

I recently went through this process so I thought it would be good to share what I think are good things to do to prepare for an interview.

Logistics

Arrive early, sit in your car or outside and walk in 15 mins before (I’m kind of paranoid, so I get there 30 mins before usually). Ask me about a job I didn’t get (years ago) because I was late. Hey, I had a good reason, they changed the time on me and mentioned it an attachment (not the body of the email) that I didn’t notice was there. To help with miscommunications, email your contact the day before and confirm time, date, place. Ask about parking or landmarks around the office so you can be sure you are in the right place.

Bring a bottle of water. It’s crazy, but sometimes you are not offered a drink! Always good to bring some just in case.

Bring some printouts of your resume just in case. One of the last interviews I had, they had printouts of what was on linkedin which was a more abbreviated version of my resume. Don’t know why they didn’t have my actualy resume, but I immediately regretting not having print copies. In the past I’ve had a nice folder for my resumes and pen too like this leather portfolio.

Dress up, at least with nice pants and a shirt. I think the only time I wore jeans to an interview is on a second interview when I saw around me everyone was in shorts the first time. While you are there, glance around to see how everyone else is dressed so you know what to wear on your first day. Bring a sweatshirt/jacket in case it’s cold in the office.

Expectations

Make sure you tell the recruiter or initial interviewer what you want to do. You wouldn’t believe it this, but one job I said I wanted to do Ruby and after 4 hours and 9 people, they told me they didn’t have that much ruby. I was pretty mad to have my time wasted.

Or another time, someone comes recruiting at a cojure conference, I do a code challenge (in clojure) and interview for 4 hours (including 30mins talking about my clojure code challenge) … only to have them say I was too specialized and they want someone to do python and Go. Also a frustrating experience! If they would have only asked me, “hey you are great on clojure, but how do you feel about go and python?”.

One more… one place they wanted ruby and I talked about my 11 years of Ruby and also 4 years ago I also started learning clojure for new challenges. He didn’t continue the interview process, afraid he’d hire me and I’d leave for clojure. Well, sorry for being a polyglot! I’m hoping this was just a rare case and not everyone is so narrow minded. Also, there are no clojure jobs in Austin (everyone who does it in Austin is remote!).

Yep, next interviews I clarified what I wanted to do and what they needed and tried to gauge how they felt about being a polyglot..

Coding

I know you might not use Big O Notation and analysis In Real Life very often, so even I forget it form time to time. But when you are set to start interviewing, learn it or review it.

Do some exercism or codewars exercises to review for the language you think you will be tested on. Find a friend and do some pair programming so you can get the hang of talking about your code as you write. Practice setting up a project. I remember doing a couple new Clojure apps and setting up a library and the tests for the library and getting all the paths and names correct. With ruby, setup a new project and install minitest and make sure you can make a module and a test and it just works.

Google ‘list of questions to ask at an interview’ and get some ideas. One question that I found in that manner is asking your interviewer “What challenges do you think I will face in this position?” which revealed a little more about the position than I knew before.

Don’t complain about your last job(s) .. it doesn’t matter at this point and you don’t want to look like you are a whiner. If they ask why you left your last job, go ahead and say why but keep it to facts not emotion.

Hopefully these will help you land your next job .. Do you have any tips?