My First Taste of Pattern Matching in Scala

I just got a taste of some pattern matching in Scala. It was not really like what I had scene in Elixir or Haskell, but seems straight forw...

January 29, 2014

Another diversion

I was working through the Koans and got distracted.  I'm still learning Ruby, I promise!

Somewhere, I stumbled across Ruby Warrior, and it looked fun.  Plus it looked like something I could do without need to concentrate quite so hard, which helps if you're stuck on the couch watching "kid shows", for instance.

This is a turn based game where you can only do one action on your turn.  It is a two dimensional board, where you, as the warrior, have only a small set of abilities:

  • walk
  • feel
  • attack
  • health
  • rest
  • rescue
Before you decide what to do, you can also "feel" a square.  This tells you what is there.  The result can be one of five states:
  • empty
  • stairs
  • enemy
  • captive
  • wall
Currently, I am stuck on level 6, but I'll still give you a taste for the code:


class Player
  @last_known_health = nil
  RUNAWAY = 20 * 0.40
  BANZAI  = 20 * 0.75
  @found_wall = false
  
  def play_turn(warrior)
    @last_known_health = warrior.health unless @last_known_health
    took_damage = @last_known_health > warrior.health
    
    if !@found_wall
      if warrior.feel(:backward).captive?
        warrior.rescue! :backward
      elsif warrior.feel(:backward).wall?
        @found_wall = true
        warrior.walk!
      else
        warrior.walk! :backward
      end
    else
      if warrior.feel.empty?
        if took_damage
          if warrior.health <= RUNAWAY
            warrior.walk! :backward
          else
            warrior.walk! :forward
          end
        else
          if warrior.health < BANZAI
            warrior.rest!
          else
            warrior.walk! :forward
          end
        end
      else
        if warrior.feel.captive?
          warrior.rescue!
        else
          warrior.attack!
        end
      end
    end

    @last_known_health = warrior.health
  end
end

It doesn't really feel like I'm taking advantage of any of the Ruby idioms.  Or maybe I am?

Time to go for a think about this...



January 18, 2014

Your company might be making mistakes if...

I recently found this article about mistakes that companies make with development.  In it, they list out these mistakes:

  1. Paying poorly
  2. Providing inadequate equipment
  3. Going into technical debt
  4. Rolling your own when good alternatives exist
  5. Not providing dedicated project management
  6. Using developers for non-developer tasks
  7. No learning for learning's sake
  8. Offshoring Development
I have worked at firms that have committed all of these, except #1.

So, should you leave to get improvements in any of these?  That, of course, is up to you.  I only really see two options:

  1. Be an agent of change
  2. Leave
Being an agent of change is very difficult in my experience.  I wish I had some success stories to share with you, but I don't.

Here's one example:  I have thus far unsuccessfully, argued for a group of developers to write unit tests.

You'd think that this would be easy, because isn't unit testing at this stage a given best practice?  You'd think so, yet, I see many of the excuses used.  In fact, the "Word has been given" that we shall not write them at all on one project, and we may not commit them to the repository with the rest of the source on any other project.

So, I can write unit tests, somebody else will break them and be completely clueless about it.

I have tried to educate, but so far, it has meant nothing.  If people don't want to change, it is unlikely they will.

As for the other points in that list.

#2 and #3 affect you every day when you start working.  Does your PC work?  Does the code stink?  Both of those suck to deal with every single day you work.  Incurring technical debt is natural, but if you can never go back and fix it, then that load of debt keeps growing and bogs down everything you do.  Projects stall, or take longer than expected.  Bugs are very difficult to fix, as well.

The worst thing is that without doing #7, people may not even know they are incurring more technical debt.  Unaware of unit testing?  Writing huge monolithic procedures?

That's debt that you may never get out from under and you may not even know it.

January 16, 2014

Ruby's Data::Dumper

I was poking around a bit trying to find the Ruby equivalent of Perls Data::Dumper or Data::Printer.  At first, I didn't think anything like those existed.

Upon further research, it seems that the "normal" way of doing this is to use Marshal or YAML.

These are ok, and I'll probably play with them, but I got more excited when I subsequently discovered Awesome Print.

After installing...

gem install awesome_print

First run:

ctreptow@vm-0:~$ cat 1.rb                                                                                                                                                 
#!/usr/bin/env ruby
require "awesome_print"
data = [ false, 42, %w(forty two), { :now => Time.now,
 :class => Time.now.class, :distance => 42e42 } ]
ap data


ctreptow@vm-0:~$ ./1.rb                                                                                                                                                   
[
    [0] false,
    [1] 42,
    [2] [
        [0] "forty",
        [1] "two"
    ],
    [3] {
             :now => 2014-01-15 22:49:02 +0000,
           :class => Time < Object,
        :distance => 4.2e+43
    }
]
ctreptow@vm-0:~$  

I like that.  I think it will come in handy when I get around to actually making something.


Ruby Koans: current status

Just finished strings:

your path thus far [............X_____________________________________] 70/280

January 15, 2014

Knowing When

I was a Computer Science major in college.  This, of course, meant lots of programming.  In my case, the majority was in Pascal, plus I dabbled in others: Modula-2 and C primarily.

So, when it was time to graduate, I needed a job.  I interviewed at a couple of local places (one insurance, one PC software).  Well, neither one worked out, plus I felt I needed to farther away from home.  I eventually took one in Des Moines.

Was I programming?  Nope.  The choice was either program COBOL, or do something in their "Research & Development" department.  So, I became a "Research Analyst".  It was fun, but we didn't do much more than review software and hardware, write up the report and tell people in the company what to buy.

One of those projects was to compare UNIX systems.  That was actually pretty cool, I got to meet employee #33 at Sun (whatever his name was) and got me going on UNIX.

So that led me around to a path of doing DBA work and sysadmin work.  Eventually, I was sick of sysadmin work and wanted to program.  Of course, since I hadn't been doing programming, I didn't think I'd ever get a programming job.

That's when an old friend called and said "we need good people, will you come back?".  "Is there programming?", I said.  "No, not really".  I took it anyway.

The position was to manage our networking devices, thousands of routers, switches, and hubs.  I also managed DHCP, and DNS.  I did manage to find some programming, though.  I modified the DHCP server using C, and wrote bunches of scripts in bash and Perl.

That position turned into a dead end, but I didn't know when to call it a day and leave.  I stayed probably 10 years too long.

I finally did get another internal position supporting some software.  I also found a way to get a little programming in using Java.  I should have left after that first year, but once again, I didn't know when to leave.

I and my team got transferred out to another area where I stuck it out for another two years.  Here again, I didn't know when to leave and should have after the first year, because this new area was horrible.

I finally did get out of there and into my current position.  I think I've finally learned something, because in this case, I do think I know when to leave.  More on the in the future perhaps.

The lesson for you is: figure out when it is time to leave and leave.  Sticking it out in something you hate is horrible, don't do it.

January 14, 2014

Ruby Koans: Fun With Hashes

So, I was working through getting Enlightened about hashes, when I came across this:

 79   def test_default_value
 80     hash1 = Hash.new
 81     hash1[:one] = 1
 82 
 83     assert_equal 1, hash1[:one]
 84     assert_equal nil, hash1[:two]
 85 
 86     hash2 = Hash.new("dos")
 87     hash2[:one] = 1
 88 
 89     assert_equal 1, hash2[:one]
 90     assert_equal "dos", hash2[:two]
 91   end
 92 
 93   def test_default_value_is_the_same_object
 94     hash = Hash.new([])
 95 
 96     hash[:one] << "uno"
 97     hash[:two] << "dos"
 98 
 99     assert_equal ["uno","dos"], hash[:one]
100     assert_equal ["uno","dos"], hash[:two]
101     assert_equal ["uno","dos"], hash[:three]
102 
103     assert_equal true, hash[:one].object_id == hash[:two].object_id
104   end
105 
106   def test_default_value_with_block
107     hash = Hash.new {|hashkey| hash[key] = [] }
108 
109     hash[:one] << "uno"
110     hash[:two] << "dos"
111 
112     assert_equal ["uno"], hash[:one]
113     assert_equal ["dos"], hash[:two]
114     assert_equal [], hash[:three]
115   end

It's easy to cheat and get these to pass, but I want to know what is going on, specifically in lines: 86, 90, 94, 96/97, 109/110, and 114.

Time for some research!

So, doing this, hash = Hash.new("dos"), means that "dos" will be used for all default values in that hash.

That explains line 90 and why the correct value is "dos", rather than nil, like I originally thought.  Turns out if we don't provide a default value, nil is what you'll get.  Makes sense, I guess.

So then on line 94, we are setting the default value to an empty array.  What I forgot before was that << is pushing a value onto an array.  In this case, the empty arrays that are the values associated with the keys: :one and :two.  Cool, it makes sense!

This brings us to line 114.  It is related to how this hash was created on line 107.  In this case, it was created with a block.  This is defaulting the value to an empty array each time, but would pay attention to the value of the key if you pass one in.

The docs are good and illustrate the difference:

h = Hash.new("Go Fish")
h["a"] = 100
h["b"] = 200
h["a"]           #=> 100
h["c"]           #=> "Go Fish"
# The following alters the single default object
h["c"].upcase!   #=> "GO FISH"
h["d"]           #=> "GO FISH"
h.keys           #=> ["a", "b"]

# While this creates a new default object each time
h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
h["c"]           #=> "Go Fish: c"
h["c"].upcase!   #=> "GO FISH: C"
h["d"]           #=> "Go Fish: d"
h.keys           #=> ["c", "d"]

Wow, I think I just learned some things here, but the trick will be to remember them.

January 13, 2014

Ruby Koans

I was sitting with my wife last night and she wanted to watch the rest of the Golden Globes.  I had stopped with my new game for the day and I don't particularly care for awards shows.

What to do?

I know!  Ruby Koans!

So, I've taken a slight diversion before eventually getting back on the path to Ruby on Rails.  I've only completed 12 steps on my path to Enlightenment, and already, I can see that the Codecademy Ruby track leaves just a bit out. :)

January 12, 2014

Setting up the Ruby environment

So, I want to take a stab at building an app with Ruby on Rails.  Before I start, I want to make sure I can reproduce it on a different machine.  The first step to doing that is to control the version of Ruby I'm using.

I found this guide to get started.  Luckily, I was already familiar with Perl's plenv setup, so this all looked very similar.

Although plenv wants you to run your shell as a login shell and modify .profile, rbenv doesn't seem to work that way.  I needed to follow the instructions exactly, and only modify the .bashrc, and then change my shell to NOT be a login shell.

Install rbenv

I used this guide: rbenv

Install ruby-build

This is used to provide rbenv the ability to install new versions of Ruby.  I used this guide: ruby-build

Install Ruby

I chose to install the latest: rbenv install 2.1.0

However, this produce an error:

The Ruby openssl extension was not compiled. Missing the OpenSSL lib?

So, first you need to install libssl-dev

sudo apt-get install libssl-dev


Set the default version to Ruby 2.1.0

ruby env global 2.1.0

Ok, so now that this is all complete, I can now be confident about what Ruby version I'm working with.

Next up is bundler to manage the versions of gems I want to use.


January 11, 2014

Healthy Eating

A long time ago, I read Gary Taube's book Bad Calories, Good Calories.  I found it a bit difficult to get through and totally understand, but there were a couple of very basic takeaways for me:

  • The "healthy eating" ideas most people grew up with is wrong and based on bad or no science.
  • Carbohydrates (refined) and other are bad, as proven by what our bodies actually do with them.
Well, since then, I've also watched a few documentaries, such as Food Matters, Fat Head, Forks Over Knives, Hungry for Change.  I found them to be either inspiring, informative, or both.

So, this got me going to make some changes.  Luckily, my wife is also on board.  She must have mentioned something on Facebook about it, because she suddenly had an old friend start telling us about the 21 Day Sugar Detox.

I'm not sure about the "detox" portion, but I am convinced that most of the food I've been eating is actually bad for me.  I'm also not eating enough vegetables, that's for sure.

So, armed with some information and support, we are making some changes.

I bought a juicer and the two 21 Day Sugar Detox books, and off we go.

My plan is to have a glass of juice everyday when I get home, rather than eating whatever may be within reach.  I've started with variations of the Dr. Oz green drink.  It's actually pretty tasty.

The easiest thing so far has been to replace cereal in the morning with an omelet.  They are easy and quick to make, plus I can add things (veggies and meats) depending on what is in the fridge.

It is suddenly, very hard to eat out AND avoid the bad carbs, because they are everywhere, embedded  in all sorts of meals.  I did find a bacon and shrimp spinach salad at Applebee's that is very tasty.

So, less sugar and more veggies.  Let's see how this goes.

January 8, 2014

Becoming a Rubyist

So, I've decided to finally "officially" learn Ruby.  A couple of times, I remember having a terminal up and spitting out something like:

puts "Hello, world!

..and then I walked away.  Well this time it will be different...I promise!

So far, I have completed the Ruby track on Codecademy and now Smarterer says I'm proficient.  Time to spit out a couple of answers in Ruby on Code Eval as well.

What next, though?  I think that answer is Ruby on Rails.  Everybody around this area seems to use it, so I may as well put some effort into one of my ideas and see if I can get a site built with it.