<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5953796462512646386</id><updated>2012-02-16T11:08:53.839-08:00</updated><category term='Intro'/><title type='text'>On Beyond Lambda</title><subtitle type='html'>A travel log of a .NET developer as he explores Clojure and F#, and looks for ways to apply C# to a multi-core world.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://onbeyondlambda.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5953796462512646386/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://onbeyondlambda.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Rick</name><uri>http://www.blogger.com/profile/15734518728736260336</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5953796462512646386.post-1102121379824851696</id><published>2012-02-15T07:34:00.002-08:00</published><updated>2012-02-15T07:34:10.557-08:00</updated><title type='text'>Project Euler and Refactoring</title><content type='html'>&lt;p&gt;I started doing the problems on &lt;a href="projecteuler.net"&gt;Project Euler&lt;/a&gt; the other day.  For anyone that doesn't know, Project Euler is a website that has a collection of math problems for you to solve.  You can solve the problem any way you want.  The site keeps track of which problems you have submitted correct answers to.&lt;/p&gt;&lt;p&gt;Just finding the right answer is a good programming challenge, but refactoring makes for much deeper learning.  &lt;/p&gt;&lt;p&gt;Another benefit from doing the problems is that you are building samples of your work that you can show to prospective employers.  If you are going to show the world your code, you want it to be clean.&lt;/p&gt;&lt;p&gt;Here is an example of my process solving one of the problems in Clojure.  I can't show what I have learned without displaying my ignorance, but I am less ignorant now because of this process.  &lt;/p&gt;&lt;p&gt;Every line of code you see here represents at least 5 lines of experimentation preceding it.&lt;/p&gt;&lt;p&gt;Problem 3 asks, "What is the largest prime factor of the number 600851475143 ?"&lt;/p&gt;&lt;p&gt;&lt;h3&gt;Solution 1&lt;/h3&gt;  Find all of the divisors of n, filter the ones that are prime and then take the largest.  To find all of the divisors, iterate through all of the numbers from 1 to n, and test remainder of n divided by i. &lt;/p&gt;&lt;p&gt;Works just fine with 42.  Doesn't show any signs of returning with 600851475143 .  Restart the REPL.  &lt;/p&gt;&lt;p&gt;&lt;ul&gt;&lt;li&gt;Learned a bit more about 'for' like the difference between :while and :when.&lt;/li&gt;&lt;/ul&gt;  &lt;/p&gt;&lt;p&gt;&lt;h3&gt;Solution 2&lt;/h3&gt;  Create a function that finds a single factor, called afactor.  In Clojure you don't use loops with breaks, you use sequences and take the items you want.  Lazy sequences don't calculate numbers until you ask for them, so you can create an expression which calculates all of the divisors, but only actually calculate one or two.&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;(defn afactor [base]&lt;br /&gt;  (nth (for [x (range 1 (+ 1 base))&lt;br /&gt;             :when (= 0 (rem base x))] x ) 1))&lt;br /&gt;&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;&lt;ul&gt;&lt;li&gt;Learned how to use 'for' in a lazy way.&lt;/li&gt;&lt;/ul&gt;  &lt;/p&gt;&lt;p&gt;Now to create a function that returns a pair of factors.&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;(defn factor [base]&lt;br /&gt;  (let [first (afactor base) ]&lt;br /&gt;    (list first (/ base first))))&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;&lt;ul&gt;&lt;li&gt;Got more confidence with 'let' binding.&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;The next step is a test whether a number is prime.  A prime number has 2 divisors, but counting the number of divisors of our number is going to leave us restarting the REPL again, which of course is just a menu item in Clooj, but it is painful to admit that I was dumb enough to think that would work, so we will skip that step.  Since a prime number is only divisible by 1 and itself, its 2nd largest factor will be itself.&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;(defn prime? [base]&lt;br /&gt;  (= base (afactor base) ))&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;&lt;ul&gt;&lt;li&gt;I assumed (= base (afactor base)) would allow me to return a boolean, glad to see that it actually does.&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;The first call to factor with our number yields a result large enough that I don't care to retype it.  Let's set up a manual recursion of 1 level.  &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;(defn prob3 [base]&lt;br /&gt;  (map factor &lt;br /&gt;       (filter #(complement prime?&lt;br /&gt;                (factor base)))))&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;&lt;ul&gt;&lt;li&gt;Playing around with this function and others like it really got me confident with the #(%) syntax of anonymous functions.  Not long ago they were a mystery, but with repetition they are comfortable.&lt;/li&gt; &lt;li&gt;Playing with the ugly (map factor (filter ...   construction was good practice with maps and lists even if the resulting code is terrible.&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;It is not hard to see a way to the right answer from this.  Either you take the output of prob3 and call prob3 again, typing in the first result, or you could nest the map factor filter inside of another map factor filter.  This isn't anything you are going to show off to your friends.&lt;/p&gt;&lt;p&gt;&lt;h3&gt;Solution 3&lt;/h3&gt;Solving a problem earlier on &lt;a href="http://www.4clojure.com/"&gt;4clojure&lt;/a&gt; I found out that Clojure has a function called tree-seq.  We always drew trees when we were factoring numbers in school, so that will probably yield a more satisfying result.  Tree-seq takes 3 parameters, branch? children and root.  branch? is a function that tests whether a node has children, children is a function that returns the children for a node and root is the initial value.  &lt;/p&gt; &lt;pre&gt;&lt;br /&gt;(defn factor-tree [base]&lt;br /&gt;  (tree-seq (complement prime?) factor base))&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;&lt;ul&gt;&lt;li&gt;I got to learn how to use tree-seq.  Also, prime? was returning true when a node didn't have children, exactly opposite the desired result.  After (not prime?) failed, I understand when to use not and when to use complement.&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;factor-tree is returning a list of all of the factors.  That is easy enough to handle.  Getting all of the prime factors we may want to do on another problem, so lets give it its own function.&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;(defn prime-factors [base] &lt;br /&gt;    (filter #(prime? %)  (factor-tree base)  ))&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;For this problem, we just want the largest prime factor.&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;(defn problem3 []&lt;br /&gt;  (apply max (prime-factors 600851475143)))       &lt;br /&gt;&lt;/pre&gt;&lt;p&gt;&lt;ul&gt;&lt;li&gt;I was surprised that I had to type (apply max(...)) instead of just (max (..)).  In the imperative world so often you are calling methods on parameters, so it is not hard to think of LISP syntax differently.  Every language I have ever used though has had a function called max that operates on a list of data, which is why it is hard for my brain to see that max(list) isn't correct.&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;&lt;h3&gt;Solution 4&lt;/h3&gt;Using the tree-seq makes for a much nicer solution, and I was tempted to stop there.  One thing still bothered me though.  In one video I saw, Stuart Halloway said that with lazy evaluation, there seldom was a reason to return just one of anything.  It is much more flexible to return a sequence and let the caller decide which elements they need.&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;(defn afactor [base]&lt;br /&gt;  (nth (for [x (range 1 (+ 1 base))&lt;br /&gt;             :when (= 0 (rem base x))] x ) 1))&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Needs to be rewritten.  &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;(defn lazy-factor [base]&lt;br /&gt;  (for [x (range 1 (+ base 1))&lt;br /&gt;     :when (= 0 (rem base x))]&lt;br /&gt;     x ))&lt;br /&gt; &lt;/pre&gt; &lt;p&gt;&lt;ul&gt;&lt;li&gt;The idea of returning a lazy sequence instead of a single value is a different philosophy that I have used in the past.&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;p&gt; As you can see, the change was very minor.  In fact, it is easier to do it the right way than the wrong way.  If I hadn't rewritten it, I never would have found that out!&lt;/p&gt;&lt;p&gt;Because I am now returning a lazy sequence instead of a single element, I do have to modify the callers to choose the element they want.&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;(defn prime? [base]&lt;br /&gt;  (= base (nth (lazy-factor base) 1)))&lt;br /&gt;&lt;br /&gt;(defn factor [base]&lt;br /&gt;  (let [first (nth (lazy-factor base) 1) ]&lt;br /&gt;    (list first (/ base first))))&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;&lt;h3&gt;Solution 5&lt;/h3&gt;I thought I was done, but moving when I moved on to other problems, I kept finding myself typing things like (range 1 (+ 1 base)), as I did in the lazy-factor function.   Range is built to give you a c style loop, so (range 5) gives you (0 1 2 3 4).  Usually this is fine, but for the Project Euler problems, I constantly find myself wanting a basic style loop, (1 2 3 4 5) instead.  This was enough motivation for me to attempt my first macro.&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;(defmacro rangeb [last]&lt;br /&gt;  (list 'range 1 (list '+ 1 last)))&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;With this change, lazy-factor becomes:&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;(defn lazy-factor [base]&lt;br /&gt;  (for [x (rangeb base)&lt;br /&gt;     :when (= 0 (rem base x))] &lt;br /&gt;     x ))&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;I expect that in the not too distant future I will be able to look back at this post and cringe.  I am sure that I will find other situations where I find a simpler way to do things and will be tempted to refactor again.  &lt;/p&gt;&lt;p&gt;I find myself using 'for' quite a bit, though only in the factor function (afactor and then its replacement lazy-factor) here.  for feels imperative, and I wonder if I am overusing it.  &lt;/p&gt;&lt;p&gt;My rangeb macro is overly specific.  Right now you can only pass an ending number; it always starts at one and increments by one.  When the spirit moves me, or when a situation demands it, I will update it.  In the meantime I will pretend that YAGNI applies here.  &lt;/p&gt;&lt;p&gt;One other thing I think my subconscious is learning is how easy it is to write and test things in Clojure.  Next time I use C# I am sure I am going to miss the REPL.  Even now, I can ponder having to write methods to call and output my code, compiling every change.  /shudder&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5953796462512646386-1102121379824851696?l=onbeyondlambda.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onbeyondlambda.blogspot.com/feeds/1102121379824851696/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://onbeyondlambda.blogspot.com/2012/02/project-euler-and-refactoring.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5953796462512646386/posts/default/1102121379824851696'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5953796462512646386/posts/default/1102121379824851696'/><link rel='alternate' type='text/html' href='http://onbeyondlambda.blogspot.com/2012/02/project-euler-and-refactoring.html' title='Project Euler and Refactoring'/><author><name>Rick</name><uri>http://www.blogger.com/profile/15734518728736260336</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5953796462512646386.post-3464229716928079348</id><published>2012-02-11T11:18:00.000-08:00</published><updated>2012-02-11T11:18:40.626-08:00</updated><title type='text'>What is functional programming?</title><content type='html'>&lt;p&gt;One assertion made a lot is that functional programming is an important concept for handling concurrency.  So what is functional programming, and how is it applicable to concurrent programming?&lt;/p&gt;&lt;p&gt;While there are a lot of topics can be included in a discussion of functional programming, there are two key ideas:  Higher order functions and pure functions.&lt;/p&gt;&lt;p&gt;&lt;h3&gt;Higher Order Functions&lt;/h3&gt;Higher order functions are functions that are meant to be applied to other functions.  They can also be thought of as functions as data.  The idea is that functions can be passed as parameters to a function or a function can return a function.  &lt;/p&gt;&lt;p&gt;A common example of passing a function as a parameter is passing a function to filter data.  Using Linq in C# you may write something like: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;    var GeorgiaCustomers = Customers.Where (c =&gt; c.StateCode == "GA");&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The section in parenthesis is called a lambda expression.  Read aloud it is "C goes to c dot statecode equals GA".  The lambda expression is a function that we are passing as a parameter to the Where method of the Customers collection.  The function StateCode == "GA" is applied to each item in the Customers collection; if the function returns true, that gets added to the new GeorgiaCustomers collection.&lt;/p&gt;&lt;p&gt;The Where method takes a single parameter, which is a function that takes a customer and returns a boolean (whether the StateCode matches).  &lt;/p&gt;&lt;p&gt;&lt;h3&gt;Pure Functions&lt;/h3&gt;Pure functions are functions that return a value without having any side effects.  Side effects are changes in things outside of a function, such as printing text to the screen, or setting a property or updating a database.  &lt;/p&gt;&lt;p&gt;Here is an example in C#.&lt;/p&gt;&lt;h4&gt;imperative:&lt;/h4&gt;&lt;pre&gt;&lt;br /&gt;     public static void doubler(int input) &lt;br /&gt;     { &lt;br /&gt;          Console.WriteLine(" {0} doubled = {1}.", input, input * 2) &lt;br /&gt;     } &lt;br /&gt;&lt;br /&gt;     public static void main(string[] args)&lt;br /&gt;     {&lt;br /&gt;          doubler(2);&lt;br /&gt;     }&lt;br /&gt;&lt;/pre&gt;&lt;h4&gt;functional:&lt;/h4&gt;&lt;pre&gt;&lt;br /&gt;     public static int doubler(int input) &lt;br /&gt;     { &lt;br /&gt;           return input * 2 ; &lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     public static void main(string[] args)&lt;br /&gt;     {&lt;br /&gt;           int result = doubler(2);&lt;br /&gt;           Console.WriteLine(" {0} doubled = {1}.", 2, doubler(2))   &lt;br /&gt;     }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;While this is a silly example, the difference is clear.  In the imperative example we are calling a double and print method, and in the functional example we are calling a double method and printing the result.  Which is more reusable?  Which is easier to test?&lt;/p&gt;&lt;p&gt;&lt;h3&gt;Why is this important&lt;/h3&gt;If you want to start executing programs on multiple processors you need to break the work into pieces that can be run independently.  Consider a function that will return the sum of the squares of a range of numbers.  In C#, you might write something like:&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;int SumSquares(int maxInput)&lt;br /&gt;{&lt;br /&gt;     int accumulator = 0;&lt;br /&gt;     for (int x = 1; x &lt;= maxInput; x++)&lt;br /&gt;     {&lt;br /&gt;          accumulator += x * x;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     return accumulator;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This code is written to be executed sequentially.  You have single thread of execution which accumulates a value and increments a counter each time through a loop.  &lt;/p&gt;&lt;p&gt;In F# it would be more natural to write the program like this:&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;let SumSquares maxInput =&lt;br /&gt;    {1 .. maxInput}&lt;br /&gt;    |&gt; Seq.map(fun x -&gt; x * x)&lt;br /&gt;    |&gt; Seq.sum&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The Seq.map function is working exactly like the Where method did in our first example.  It is being passed a lambda function and applying it to a list of items.  It is returning a list of the results.  &lt;/p&gt;&lt;p&gt;The |&gt; operator takes the output of a function and sends it as an input of the next function.  &lt;/p&gt;&lt;p&gt;First we create a list of numbers and then we pass that as an input to a function which returns a list contains the squares of an original list of numbers.  &lt;/p&gt;&lt;p&gt;This list is then being applied to the Seq.Sum method, which is a function that returns the sum of all of the elements in a list. &lt;/p&gt;&lt;p&gt;The same function in Clojure could be written:&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;(defn SumSquares  [maxInput]&lt;br /&gt;  (reduce +&lt;br /&gt;       (map (fn [x] (* x x))&lt;br /&gt;              (range 1 (+ maxInput 1)))))&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The syntax is different, but this works the same as the F# version.  Working from the inside out (and bottom to top) we create a range from 1 to the maxInput, which we input to the map function which applies the square function to each element.  &lt;/p&gt;&lt;p&gt;The important feature of both the F# and Clojure implementations is that by passing an anonymous function and a list to a map function and then only doing the accumulation after the fact, each number in the list can be processed independently.&lt;/p&gt;&lt;p&gt;Neither of these implementations is actually running in parallel right now, they are just written in a way that will easily support parallelism.&lt;/p&gt;&lt;p&gt;Continuing on with the Clojure version, to make it parallel all we have to do is change the map function to pmap.  I am also going to modify my anonymous function so that it produces a side effect to show that it does work in parallel and why side effects in parallel programs cause problems.  &lt;/p&gt;&lt;p&gt;The new version is:&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;(defn SumSquares  [maxInput]&lt;br /&gt;  (reduce +&lt;br /&gt;  (pmap (fn [x] &lt;br /&gt;         (do&lt;br /&gt;           (println x) &lt;br /&gt;           (* x x)))&lt;br /&gt;    (range 1 (+ maxInput 1)))))&lt;br /&gt;&lt;/pre&gt;In this version, the anonymous function now prints out its input and then returns the square of the input.  Running it twice, I got the following 2 results:&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-SNM6okLc3zE/Tzaul9dZF5I/AAAAAAAAACU/5e3hS_lmH4o/s1600/pmapResult.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="320" width="257" src="http://1.bp.blogspot.com/-SNM6okLc3zE/Tzaul9dZF5I/AAAAAAAAACU/5e3hS_lmH4o/s320/pmapResult.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;We are no longer guaranteed that our map will execute in a particular order.  Adding the side effect of writing to the console just looks strange.  I especially like the second execution where the program switched from the 1 thread to the 4 thread before the 1 thread wrote its own newline character, which is how we ended up with 14 on the first line and then a blank line a couple lines later.&lt;/p&gt;&lt;p&gt;&lt;h3&gt;Summary &lt;/h3&gt;Writing in a functional style supports breaking work up into pieces that can be run in parallel.  Being able to pass functions as parameters to higher order functions allows for the creation of things like pmap which handle the dispatching of work to different threads.  Writing pure functions, without side effects, leads to solutions that can be broken into the smaller independent pieces that can be passed to a map or pmap function.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5953796462512646386-3464229716928079348?l=onbeyondlambda.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onbeyondlambda.blogspot.com/feeds/3464229716928079348/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://onbeyondlambda.blogspot.com/2012/02/what-is-functional-programming.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5953796462512646386/posts/default/3464229716928079348'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5953796462512646386/posts/default/3464229716928079348'/><link rel='alternate' type='text/html' href='http://onbeyondlambda.blogspot.com/2012/02/what-is-functional-programming.html' title='What is functional programming?'/><author><name>Rick</name><uri>http://www.blogger.com/profile/15734518728736260336</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-SNM6okLc3zE/Tzaul9dZF5I/AAAAAAAAACU/5e3hS_lmH4o/s72-c/pmapResult.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5953796462512646386.post-5315810572596170617</id><published>2012-01-31T07:44:00.000-08:00</published><updated>2012-01-31T07:44:21.885-08:00</updated><title type='text'>Why C++ and where to look</title><content type='html'>&lt;p&gt;The theme of this blog is finding out how programming will have to change to deal with computers containing dozens or hundreds of processors.  So far most of the posts have been related to Clojure.  In addition to Clojure, F# and C# also have good answers to parallelism.  &lt;/p&gt;&lt;p&gt;The approach in all three of these languages is to write applications that can be run in parallel safely, so that you can benefit from having multiple processors without breaking anything.  In all three cases, the actual hardware is abstracted away.&lt;/p&gt;&lt;p&gt;In addition to the number of processors in a machine though, we are also seeing a diversity of processors being used within a single machine.  Graphical Processing Units are very powerful, but their vector processing gives a bigger boost to some operations than others.  GPUs and other chips have reduced instruction sets, which means that some code that is perfectly legal on a CPU won't work on a GPU.&lt;/p&gt;&lt;p&gt;Reducing the number of clock-cycles and choosing lower power processors are important whether you are trying to increase the battery life of a mobile device or having to power (and cool) a server farm.  Cloud computing, which provide CPUs as a metered service, also encourages using cycles sparingly.&lt;/p&gt;&lt;p&gt;If you want to be optimizing cycles and choosing chips you need to be running "on the metal" and that means C or C++.&lt;/p&gt;&lt;p&gt;There have been a lot of changes to C++ in the C++ 11 specification.  There are also new libraries that deal specifically with the problems of developing on different types of chips.  When even Microsoft, with their traditional focus on drag and drop development and managed code, starts talking about a C++ renaissance you know it is a big deal.  &lt;/p&gt;&lt;p&gt;Microsoft is hosting a 2 day "Going Native" event on February 2nd and 3rd.  The event is being streamed live (for free) at http://channel9.msdn.com/Events/GoingNative/GoingNative-2012.  I am sure they will also have videos of the keynotes and sessions available later on the channel 9 site.&lt;/p&gt;&lt;p&gt;I will not watch it live (I am still trying to learn Clojure), but it is timely information, so I thought I would pass it along.&lt;/p&gt;&lt;p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5953796462512646386-5315810572596170617?l=onbeyondlambda.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onbeyondlambda.blogspot.com/feeds/5315810572596170617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://onbeyondlambda.blogspot.com/2012/01/why-c-and-where-to-look.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5953796462512646386/posts/default/5315810572596170617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5953796462512646386/posts/default/5315810572596170617'/><link rel='alternate' type='text/html' href='http://onbeyondlambda.blogspot.com/2012/01/why-c-and-where-to-look.html' title='Why C++ and where to look'/><author><name>Rick</name><uri>http://www.blogger.com/profile/15734518728736260336</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5953796462512646386.post-7938835194702815491</id><published>2012-01-25T11:42:00.000-08:00</published><updated>2012-01-25T11:42:20.134-08:00</updated><title type='text'>Setting up clojure emacs on windows</title><content type='html'>&lt;p&gt;Setting up a Clojure development environment proved to be quite a challenge, especially given my handicap of using Windows.  &lt;/p&gt;&lt;p&gt;The most widely used editor for Clojure is Emacs.  I don't have any idea how to use it, but I have seen video of people who know what they are doing, and I really want that!  &lt;/p&gt;&lt;p&gt;There are lots of options for setting up Clojure.  If you are just starting out, there are too many.  There are at least half a dozen editors that have Clojure plug-ins.  Emacs itself has two.  The instructions available also tend to present different ways of accomplishing the same thing.  &lt;/p&gt;&lt;p&gt;I am not going to give you lots of options.  I am going to give you the steps to go from a clean Windows 7 install to having the most popular plug-in for the most popular editor using the most popular build tool for Clojure.  I am sure there is a lot of value to all of the flexibility that other people support, but it is lost on me and if you are reading this, it is probably lost on you too.&lt;/p&gt;&lt;p&gt;Also, I intend to cover each step in excruciating detail.  I know from experience that any instructions on this subject, no matter how detailed, would include at least  one or two steps that assumed I actually knew how to use Emacs.  If you follow these instructions and there is a step that is not completely clear to you, please put it in the comments so that I can fix it.  If the detail is too much for you, just read the bold print!&lt;/p&gt;&lt;p&gt;Our goal is to have a working installation of the Leiningen build tool, and the SLIME plug-in for the Emacs editor.&lt;/p&gt;&lt;p&gt;Before I start, let me say this works best if you do not already have clojure installed on your computer, or more specifically that you do not have the clojure.jar file in your class path.  The Leiningen install will fail if you do.&lt;/p&gt;&lt;p&gt;&lt;h3&gt;Install the Java Development Kit (JDK )&lt;/h3&gt; &lt;br /&gt;Version 1.6 or better is required, I am running 1.7 Standard Edition. &lt;a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html"&gt;Download this from Oracle&lt;/a&gt;. There is also a link to installation instructions on that page.  &lt;/p&gt;&lt;p&gt;After jdk is installed you need to make sure that the environment variables are set up correctly.  (Control Panel &gt;&gt; System and Security &gt;&gt; System &gt;&gt; Advanced system settings &gt;&gt; Environment Variables...)&lt;/p&gt;&lt;p&gt;Under user variables I have JAVA_HOME with a path to the folder where the jdk is installed.  On my system this is C:\Program Files\Java\jdk1.7.0_01&lt;/p&gt;&lt;p&gt;Under System Variables, the java bin directory needs to be in your path.  click edit on the path, so you can scroll through and look to see if these settings are already there, and if not add them (path items are separated with ; on windows) %Java_Home%\bin\   and   the physical path to the bin directory that holds the jdk executable.  In my case this is C:\Program Files\Java\jdk1.7.0_01\bin\ &lt;/p&gt;&lt;p&gt;Test the java installation by going to a command prompt (click the windows button in your taskbar and type cmd in the search box)  at the command prompt type: &lt;br /&gt; javac -version &lt;br /&gt;  if the computer responds with a version number the jdk is set up properly, if it says that javac is not found, you have a problem you need to fix before you move on.&lt;/p&gt;&lt;p&gt;&lt;h3&gt;Install Leiningen&lt;/h3&gt; (build tool) &lt;br /&gt;Create a folder that will hold the leiningen batch file and also a helper utility it needs.  Mine is in c:\lein.  to create it I went to the command prompt, typed  &lt;br /&gt; cd \   &lt;br /&gt; md lein   &lt;br /&gt;After that type exit to close that command prompt window.  Add the path to your new folder to your path setting.  &lt;/p&gt;&lt;p&gt;Download curl from  &lt;br /&gt; http://www.paehl.com/open_source/?download=curl_723_1_ssl.zip &lt;br /&gt;and place curl.exe and into your new folder.&lt;/p&gt;&lt;p&gt;download libssl from &lt;br /&gt; http://www.paehl.com/open_source/?download=libssl.zip &lt;br /&gt; and place libeay32.dll and ssleay32.dll into your new folder.&lt;/p&gt;&lt;p&gt;Download the lein.bat file from  &lt;br /&gt;https://raw.github.com/technomancy/leiningen/stable/bin/lein.bat  &lt;br /&gt; and put it in to your new folder.  (My browser displayed the text, so to save it I did file &gt;&gt; save page as     and then navigated to my c:\lein folder.&lt;/p&gt;&lt;p&gt;Open a new command prompt and type &lt;br /&gt; lein self-install  &lt;/p&gt;&lt;p&gt;After the installation completes you can test your leiningen install by typing &lt;br /&gt; lein repl  &lt;br /&gt;at the command prompt.  It should launch the clojure repl which you can test by typing  &lt;br /&gt;(+ 1 2)  &lt;br /&gt;at the user prompt.  &lt;/p&gt;&lt;p&gt;click the x in the upper right to close the command prompt.&lt;/p&gt;&lt;p&gt;&lt;h3&gt;Install Emacs&lt;/h3&gt; (Editor) &lt;br /&gt;Download emacs from  &lt;br /&gt; http://ftp.gnu.org/pub/gnu/emacs/windows/emacs-23.1-bin-i386.zip  &lt;br /&gt;extract the emacs-23.1 folder, and put it somewhere.  I just put mine in c:\&lt;/p&gt;&lt;p&gt;Create a folder to hold plugins for emacs named .emacs.d  I put mine in my emacs-23.1 folder.&lt;/p&gt;&lt;p&gt;Create a new user environment variable called HOME in the value put the path to the .emacs.d folder.  in my case this is C:\emacs-23.1&lt;/p&gt;&lt;p&gt;Add the path to the emacs.exe folder to your path.  mine was C:\emacs-23.1\bin&lt;/p&gt;&lt;p&gt;&lt;h3&gt;Install Clojure mode&lt;/h3&gt;Create a file called init.el in your .emacs.d folder and enter this text &lt;br /&gt;(add-to-list 'load-path "~/.emacs.d/")&lt;br /&gt;(require 'clojure-mode)&lt;br /&gt;Add the file clojure-mode.el from &lt;br /&gt;https://github.com/technomancy/clojure-mode/blob/master/clojure-mode.el &lt;br /&gt; to your .emacs.d directory.  I found the easiest way to do this was to copy the text in the code window at that url and paste it into a new text file that I called clojure-mode.el.  If you just download the webpage, you will get lots of html commands that will cause errors in emacs.&lt;/p&gt;&lt;p&gt;&lt;h3&gt;Install Swank plugin&lt;/h3&gt; open a new command prompt and type &lt;br /&gt;lein plugin install swank-clojure 1.3.4 &lt;br /&gt;-- note initially this install got hung for me, when I disabled avg link scanner it worked right away.&lt;/p&gt;&lt;p&gt;Create a new Clojure projectfrom the command prompt, navigate to a folder where you would like to create clojure files.from c:\Users\Rick I typed &lt;br /&gt;md projects&lt;br /&gt;   then  &lt;br /&gt;cd projectscreate the new project by typing &lt;br /&gt;lein new testproj&lt;br /&gt;then type&lt;br /&gt;cd testproj&lt;br /&gt;emacs&lt;/p&gt;&lt;p&gt;after emacs loads type&lt;br /&gt; alt-x clojure-jack-in &lt;br /&gt;emacs will spend a couple of moments processing the plugin.After this, you should have a running REPL that you can test the same way that you tested the repl from leiningen.  type&lt;br /&gt; (+ 1 2). &lt;br /&gt; If you get 3, it works.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5953796462512646386-7938835194702815491?l=onbeyondlambda.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onbeyondlambda.blogspot.com/feeds/7938835194702815491/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://onbeyondlambda.blogspot.com/2012/01/setting-up-clojure-emacs-on-windows.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5953796462512646386/posts/default/7938835194702815491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5953796462512646386/posts/default/7938835194702815491'/><link rel='alternate' type='text/html' href='http://onbeyondlambda.blogspot.com/2012/01/setting-up-clojure-emacs-on-windows.html' title='Setting up clojure emacs on windows'/><author><name>Rick</name><uri>http://www.blogger.com/profile/15734518728736260336</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5953796462512646386.post-2670184289323777543</id><published>2012-01-23T09:37:00.000-08:00</published><updated>2012-01-29T18:34:13.784-08:00</updated><title type='text'>Clojure is one answer</title><content type='html'>My &lt;a href="http://onbeyondlambda.blogspot.com/2012/01/laying-out-problem.html" &gt;last post &lt;/a&gt; was a link to a video talking about the challenges of many-core computing.  Today I am linking to another video from Channel 9.  This one is a discussion with Rich Hickey about Clojure.  The topics build on one another: introducing Clojure, why Clojure is a lisp, functional programming, lists and vectors, persistent data structures, identities and concurrent programming.  I recommend the whole video, but if you just want to jump to the section on concurrency that starts at 37:15.&lt;br /&gt;&lt;iframe style="height:288px;width:512px" src="http://channel9.msdn.com/Shows/Going+Deep/Expert-to-Expert-Rich-Hickey-and-Brian-Beckman-Inside-Clojure/player?w=512&amp;h=288" frameBorder="0" scrolling="no" &gt;&lt;/iframe&gt;&lt;br /&gt;edit:  For people who didn't like the embedded player, here is the &lt;a href="http://channel9.msdn.com/shows/Going+Deep/Expert-to-Expert-Rich-Hickey-and-Brian-Beckman-Inside-Clojure/"&gt;link to the video on msdn.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5953796462512646386-2670184289323777543?l=onbeyondlambda.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onbeyondlambda.blogspot.com/feeds/2670184289323777543/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://onbeyondlambda.blogspot.com/2012/01/my-last-post-was-link-to-video-talking.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5953796462512646386/posts/default/2670184289323777543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5953796462512646386/posts/default/2670184289323777543'/><link rel='alternate' type='text/html' href='http://onbeyondlambda.blogspot.com/2012/01/my-last-post-was-link-to-video-talking.html' title='Clojure is one answer'/><author><name>Rick</name><uri>http://www.blogger.com/profile/15734518728736260336</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5953796462512646386.post-6302502085303865605</id><published>2012-01-12T12:35:00.000-08:00</published><updated>2012-01-12T12:35:45.468-08:00</updated><title type='text'>Laying out the problem</title><content type='html'>&lt;p&gt;I recently saw a video on Channel 9 that provides a great background on parallel programming.  &lt;/p&gt;&lt;p&gt;The amount of information available to developers from Channel 9 is incredible.  Naturally there is good coverage of Microsoft technologies, but there is also a lot of material that has nothing to do with Microsoft.&lt;/p&gt;&lt;p&gt;The video is an interview with Burton Smith.  I recommend it to anyone.&lt;/p&gt;&lt;p&gt;  &lt;iframe style="height:288px;width:512px" src="http://channel9.msdn.com/Shows/Going+Deep/Burton-Smith-On-General-Purpose-Super-Computing-and-the-History-and-Future-of-Parallelism/player?w=512&amp;h=288" frameBorder="0" scrolling="no" &gt;&lt;/iframe&gt;&lt;/p&gt;&lt;p&gt;If you don't want to watch the interview, or the whole interview, here is how I would break down the talk:&lt;/p&gt;&lt;p&gt;(0:30)Hardware for mainstream computing is changing in a way that makes ideas that were once only relevant to supercomputers important to the mainstream.&lt;/p&gt;&lt;p&gt;(1:52)Multi-core refers to 8 or fewer processors, multi-core refers to either more than 8 processors, or utilizing different types of processors such as CPUs and Graphics Processing Units.&lt;/p&gt;&lt;p&gt;(3:08) In the early days super computers were powerful machines used for general purpose, transactional processing tasks.  &lt;/p&gt;&lt;p&gt;(4:05) The introduction of vector processing caused supercomputing to become much more specialized.  Programs that had a lot of branching could not benefit from vector processing.  Tasks that involved performing the same operation across a set of data could be written to use Instruction Level Parallelism were able to get big gains from vector processing.&lt;/p&gt;&lt;p&gt;(5:37) After vector processing, the next big change was distributing computations among many smaller computers.  This is the state of super computing today.  Distributed parallel computing works by different machines sending messages to each other, though within each machine itself there may not be any parallel processing going on.  In practice this makes supercomputing even more specialized than vector processing did.&lt;/p&gt;&lt;p&gt;(7:17) Now that mainstream computers are being built with multiple cores, the goal is to make parallel processing very general.&lt;/p&gt;&lt;p&gt;(8:56) In the 80s people realized that the physical limits of a single core would be reached.  Their research didn't lead to success in the marketplace, but we can learn today from the knowledge they gained.&lt;/p&gt;&lt;p&gt;(10:00) It is not only computer architecture that you worry about.  One of the major problems is programming languages.&lt;/p&gt;&lt;p&gt;(10:45) A decision made at the foundation of computing that is inhibiting attempts at parallelization is the idea of a variable.&lt;/p&gt;&lt;p&gt;(11:32) In a computer that executes one instruction at a time, you know the order in which the instructions will be done.  &lt;/p&gt;&lt;p&gt;(14:28) Smith gives an analogy of parallel computing by describing a development team and talking about the implication of an office full of programmers working together to write a piece of software.  He describes the risks of mutability and the strengths of messaging and immutability.&lt;/p&gt;&lt;p&gt;(16:25)  Tweaking C++ a little bit isn't sufficient for solving parallel problems.  The transformation needed is much more radical and will change programming styles for ever.&lt;/p&gt;&lt;p&gt;(20:33)  The dominant programming languages today require the reading and writing of shared data.  The programs are challenging and difficult to maintain as a result.&lt;/p&gt;&lt;p&gt;(21:00)  Software Transactional Memory is one of the alternatives being pursued today.  &lt;/p&gt;&lt;p&gt;(21:46)  SQL is a functional programming language that a lot of people are able to use and understand.  When people wish to modify data they use transactions.  &lt;/p&gt;&lt;p&gt;(22:46)  Excel is a functional programming environment.  Every cell contains either a value or an expression that is a function of other values.  &lt;/p&gt;&lt;p&gt;(26:28)  Even in a parallel functional program, when state is modified it is still done sequentially.  The difference is the imperative state changes become isolated pieces of a program.  &lt;/p&gt;&lt;p&gt;(30:54)  Databases are an example of a persistent store that has to be accessible in parallel, with changes done in isolation.&lt;/p&gt;&lt;p&gt;(32:43) Databases combine transactions with functional programming.  That is the most successful parallel programming in the world.&lt;/p&gt;&lt;p&gt;(33:03)  "There are only 3 ways to do parallel computing:  1.  Get an expert.  2.  Use functional Language.  3.  Use transactions." &lt;/p&gt;&lt;p&gt;(33:40)  Changes have to be done in isolation, but there are many ways to get the isolation in either space or time.&lt;/p&gt;&lt;p&gt;(33:20)  Based on our experience with databases, transactional memory should be able to scale very well, but just adding to C++ probably won't be enough.&lt;/p&gt;&lt;p&gt;-- After that is a long discussion about different levels of programming and making parallelism more accessible.  It is a fascinating discussion, but tougher to tease out parts for this blog.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5953796462512646386-6302502085303865605?l=onbeyondlambda.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onbeyondlambda.blogspot.com/feeds/6302502085303865605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://onbeyondlambda.blogspot.com/2012/01/laying-out-problem.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5953796462512646386/posts/default/6302502085303865605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5953796462512646386/posts/default/6302502085303865605'/><link rel='alternate' type='text/html' href='http://onbeyondlambda.blogspot.com/2012/01/laying-out-problem.html' title='Laying out the problem'/><author><name>Rick</name><uri>http://www.blogger.com/profile/15734518728736260336</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5953796462512646386.post-8900811882226765181</id><published>2012-01-10T12:30:00.000-08:00</published><updated>2012-01-10T12:35:04.318-08:00</updated><title type='text'>Something to look forward to</title><content type='html'>One of the problems that developers have to learn to address is concurrency.  I expect this to be a recurring theme on this blog.  From what I have seen Clojure is the language best suited to dealing with concurrency. &lt;br /&gt;&lt;br /&gt;Rather than talking about the different problems of multi-threaded programming and how they are addressed with Clojure, as if it is some necessary evil, here is a great presentation about Clojure's strengths before even considering the issue of concurrency. &lt;br /&gt;&lt;br /&gt;This is from Stuart Halloway, author of &lt;a href="http://pragprog.com/book/shcloj2/programming-clojure"&gt;&lt;i&gt;Programming Clojure&lt;/i&gt;.&lt;/a&gt;  This was filmed at Øredev 2009.&lt;br /&gt;&lt;br /&gt;It appears Vimeo doesn't want me to embed it, so here is the link:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://vimeo.com/10896148"&gt;Clojure - Stuart Halloway&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5953796462512646386-8900811882226765181?l=onbeyondlambda.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onbeyondlambda.blogspot.com/feeds/8900811882226765181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://onbeyondlambda.blogspot.com/2012/01/something-to-look-forward-to.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5953796462512646386/posts/default/8900811882226765181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5953796462512646386/posts/default/8900811882226765181'/><link rel='alternate' type='text/html' href='http://onbeyondlambda.blogspot.com/2012/01/something-to-look-forward-to.html' title='Something to look forward to'/><author><name>Rick</name><uri>http://www.blogger.com/profile/15734518728736260336</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5953796462512646386.post-2713304839549323141</id><published>2012-01-07T07:31:00.000-08:00</published><updated>2012-01-07T08:09:18.899-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Intro'/><title type='text'>Why?</title><content type='html'>Every blog must have a first post.  The usual model is to lay out some grand ambitions and ideals to inspire embarrassment or regret in the author later.  In lieu of that, I will admit that this is my third attempt at blogging. &lt;br /&gt;&lt;br /&gt;The first blog was about .NET programming that I started when I was playing with WinFX and Indigo, which became Windows Communication Foundation in .NET 3.0.  I think I wrote 4 posts.  I don't even remember the name of that blog now.&lt;br /&gt;&lt;br /&gt;The second was an attempt at non-fiction prose.  I wrote a bit more there, but no where near as much as I had hoped.  That was a grand vision that didn't pan out.&lt;br /&gt;&lt;br /&gt;So why a new blog?  Because I am more excited about programming than I have been since at least the WinFX beta, possibly even more than when I first switched to .NET in 2002, and maybe since ever.&lt;br /&gt;&lt;br /&gt;Computer platforms are mobile, multi-core and distributed.  But sometimes developers are so focused on the problems they face day to day that they don't have a chance to see how the world has changed around them. &lt;br /&gt;&lt;br /&gt;Think of this blog as the diary of Rip Van Programmer.  I have recently woken up and now I have to learn to live in this strange modern world. &lt;br /&gt;&lt;br /&gt;This blog is about the process of my learning.  I hope that it will contain useful things for others, but I expect to make mistakes along the way.  If a year from now I can't look back and find mistakes in this blog it will have been a failure.&lt;br /&gt;&lt;br /&gt;If you see mistakes or better ways to do things, please tell me!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5953796462512646386-2713304839549323141?l=onbeyondlambda.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onbeyondlambda.blogspot.com/feeds/2713304839549323141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://onbeyondlambda.blogspot.com/2012/01/why.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5953796462512646386/posts/default/2713304839549323141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5953796462512646386/posts/default/2713304839549323141'/><link rel='alternate' type='text/html' href='http://onbeyondlambda.blogspot.com/2012/01/why.html' title='Why?'/><author><name>Rick</name><uri>http://www.blogger.com/profile/15734518728736260336</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
