Category: Programming

haxe-logo.png

Time for a new goal in life. Learning Haxe just for the heck of it. Looks like something interesting and worthwhile to tackle. Like I always say, you are never too old to learn more stuff.

angular-to-csv-table.png

Just for fun, I created an example Angular application which converts a CSV file to a Material Table dynamically. Guess I was a little bored, but nonetheless it was a fun quickie break from an otherwise uneventful day.

https://github.com/kgish/angular-csv-to-material-table

Okay, so you are never too old to follow yet another dream. Time to become a future famous game developer, and this is a great way to start.

construct3.png

My goal is to design a truly amazing golf game which will attract droves of eager followers and in the process make me happier.

Looks like Ruby 2.7.0 has now been officially released.

There are many new improvements in this version, but here's one that I really like.

array-tally-ruby-2.7.png

ng-be-2019.png

So what if I was the oldest guy there. I still learned a lot about Enterprise Angular architectures with Nx Monorepos, Strategic Design and a bunch of other interesting topics.

The younger crowd there was part of a different generation, remaining glued to their mobile phones during breaks and lunch, staring the whole time at their open laptops while the speaker gave his workshop.

As I always say and live by as well, "You're never too old to learn new stuff!"

Decided to go out and splurge again, so I signed up for the following online course: Functional Programming in Haskell.

This is an even more serious training for experienced software developers, and I look forward to starting it in September.

Later on I can impress family and friends with such amazing one-liners like this:

pascal = map ([1,1]^) [0..]

which generates the infinite list of rows of Pascal's triangle (yawn).

Paying the extra €69 to get some so-called paper certificate sounds like a waste of money, but I think that it will encourage me to take things more seriously and do my best to complete the grueling course with flying colors.

Wish me luck.

In view of my upcoming assignment next month, it's time to get serious about the Ruby programming language. Although I already consider myself pretty good and gain great pleasure when coding amazing stuff with this wonderful language, an in-depth refresher from beginning to end would be useful and fun.

That's why I decided to give in and splurge, expanding my computer library collection by ordering the famous book.

the-ruby-way.png

This thick tome of more than seven hundred pages is the perfect medicine for me. It also looks real nice next to all my other Ruby books. I've now read about a third of this book and am sawing through it nicely with speed and agility.

the-haskell-road-ro-logic.png
Order the book yourself

Have I gone too far and lost totally my wits by purchasing this book? Now I am going to have to read it and sludge through the jungle of mathematical proofs in order to get my money's worth. Who knows if I will ever be able to understand it completely.

The other day I was looking around for a more advanced static website generator, and I happened to stumble across a wonderful tool called Middleman. Easy to install, customize, build and deploy, and the documentation is fantastic. There are even a number of template blueprints and ruby gems you can use to enhance things.

middleman.png

Compared to the more popular Jekyll, which is more for creating blogs anyway, Middleman is more complicated and takes a bit more technical insight in order to get to grips with its sometimes hard to understand way of getting things done.

Decided my next goal in life will be to gauge my learning Haskell progress by using it to find solutions to all of the Project Euler problems.

So far so good, I completed the first one with success.

Problem 1: Multiples of 3 and 5

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 1000.

The very compact and elegant Haskell one-liner solution is:

sum [ x | x <- [1..999], x `mod` 3 == 0 || x `mod` 5 == 0]

There's still a long way to go...

I figured that it was high time that I finally sit down, roll up my sleeves and really figure out at a deep philosophical level what this whole functional programming languages paradigm is all about.

What better way to do this than by wrestling with the big bad bear of them all called Haskell?

So I went out and bought a book online that claims to once and for all explain clearly how it works, all the way through functors, monads, etc. I barely survived the first chapter about lambda calculus, and it's starting to get very interesting (though heavy-going at the same time). They claim that learning Haskell doesn't have to be difficult, but I've still got thirty odd chapters to go.

haskell-book-cover.png
Haskell Programming from First Principles

Add this to the collection of all my other books about Haskell, and you could say that I'm on my way to becoming the nerdiest functional programmer around.

Eat your hearts out all you Elixirians and Clojurians.

Today I received an interesting email from someone trying to sell an online tutorial on WebdriverIO which posed the following:

"Quick question: What holds you back from writing automated tests?"

Based on my personal experience doing various projects in the wonderful world of software development, here is a list of reasons with which I replied:

  • The product is already finished and in production so there's no more budget left for automated testing.
  • The platform is legacy software and no one understands how it works.
  • We already have an army of functional testers in India who are manually testing everything, and it's cheap.
  • You need "technical" people to setup the the automated test environment, and the only technical people we have are developers and system admins.
  • Developers hate to write tests and have no time to learn it.
  • Most testers are high-level black-box functional testers and are not concerned with the internal details nor are technical enough to understand the underlying software.
  • Setting up an automated environment is expensive.
  • There are already tons of tests failing and no one gives a damn.
  • The CI runs from Jenkins and the guy that set things up is no longer working for us (don't fix whats not broken).
  • Managers do not fully understand what automated testing is and how it really works and are therefore unwilling to invest money.
  • Automated testing means that the functionality of the complete product is known, however mostly it is undocumented or specific areas of expertise limited to certain privileged individuals.
  • We're too busy and have no time.
  • Good testers are hard to find, especially those that are technically inclined and/or understand how to write software.
  • The product is not stable and is changing too frequently, meaning that time spent invested in writing test scripts that will continuously break is not worth it.

Signed up for the Learn Elixir and Learn Phoenix online video training.

Been procrastinating long enough so it's time to make the move and learn even more new stuff.

One of the most important credos for boosting a development team into the realm of excellence is to ensure that they can feel very proud of what they create as a coherent team. This power of creative energy mixed in with just the right amount of the fun factor is not to be under-estimated.

The speed of feedback is very important in order for the product developers to do the right job.

Developers depend on feedback in order to make the right choices at the right time.

Feedback also allows developers to realize their mistakes and incorrect assumptions early on in order to recover before it is too late.

Proper and timely feedback allows one to operate the product development process effectively, especially in a very noisy and erratic environment.

By analyzing and reacting to feedback early, one adapts efficiently to unpredictability, and one is more flexible and dynamic to ever-changing business needs.

Unfortunately, current orthodox beliefs view feedback as the evil cause of undesirable rework loops, stubbornly insisting that rework is to be avoided by designing things right the first time (as if this is ever possible).

Of course we all know how foolish such an unfounded belief is, history has shown us too many failed projects which have fallen victim to this stubborn way of thinking.

Feedback gives one new and valuable information that can be used to freshen our viewpoints and make better economic choices.

There's an illusion going on out there, and it's best to avoid it with all your might. Just because you are in a hurry and think it's expedient to throw important requests over the wall into the development team as quickly as possible, does NOT mean that you are following the shortage route to getting it done. Done, done. Not done by development, not done by testing and not done as in "delivered" to the customer and curing his headache. That's really the moment of truth when the customer benefits from all that effort (money spent), when profits start rolling in. Repeat, does NOT. Too many people fail to understand this simple concept, because they are blinded by the glitter of money (so-called) and the individual bonus. In truth, injecting random tasks without proper preparation will in the end take much longer to actually get to the happy customer. Think about best practices. Follow the rules of thumb, and you will avoid being consumed later by the nightmare of endless after care and all night bug-fixing marathons (which will eat up any short term profits in no time). Here is what you should do with these request first. Analyse and localize, provide a structured and high-level description, prioritize, and then wait. Waiting is the hardest thing to do, especially in a commercial world where we the greedy ones are pressured to make a quick buck, or else. Or else the competitors will jump in front of you at your slightest hesitation. No, be wise and wait until the last possible moment, wait through that incubation period until the time is ripe. Decide when you are just still in control, just at furthest point within the window of opportunity, right before the moment that the decision will be forced upon you.

RESTful Rails Development by Silvia Puglisi

I couldn't resist the great book offer that the kind folks at O'Reilly emailed me, so I splurged and purchased the e-book called RESTful Rails Development by Silvia Puglisi.

Although I may fool myself into believing that I am some kind of expert and this is already all very familiar material, it's always good to refresh one's mind. Perhaps even discovering new information or coming across eye-opening code snippets. Rails, REST and Ruby, yeah sure I already know all that stuff. Or do I?

Coding years on end without keeping track of new stuff can be compared to driving a car your whole life and thinking that you are perfectly competent when actually you have unknowingly become a bigger danger on the road than you realize.

Be careful before you accidentally kill your fellow developer who is pair-programming next to you. Like I always say (sorry if I keep repeating myself too much), I am never too old to learn new stuff.

The book is still the early release raw and unedited, but I still found that there were way too many errors and typos. Sure the price was right and I should not have high expectations, but when you get into the flow of reading and are regularly disrupted by unclear and misspelled words, it's a bit of a hassle.

Especially when code fragments are wrong, I hate it when there are code typos. You never know if that is how it's really supposed to be or if it is an error, until you fire up irb or vi, type it all in yourself and (if there are no syntax errors) running it.

For example, seeing '{ :product_id =&gt; 2 }' all over the place instead of '{ :product_id => 2 }', now that's pretty aggravating.

Although the English isn't fluent, the contents and descriptions are done quite well and the story-line is very complete. I just hope that in the coming newer releases that the errors will be fixed and the sentences made to flow better.

In Elixir, the pipe operator '|>' takes the output of the expression on the left of it, and feeds it in as the first argument to the function on the right of it.

You can even tag on additional functions together in an endless chain to form a pipeline of functions to be called, very similar to the Unix method of piping command utilities together, e.g. 'ps ax|grep vim|awk '{ print $1 }'.

In other words, the following statement using the pipe operator |> :

f( a ) |> g( b ) |> h( c )

is equivalent to:

h( g( f( a ), b ), c )

This can be extended to include functions with multiple parameters like this:

f( a, b ) |> g( c, d )

being equivalent to:

g( f( a, b ), c, d )

See if you can figure out what the following does:

-5 |> abs |> Integer.to_string |> IO.puts

Here's a small hint to help you along:

IO.puts(Integer.to_string(abs(-5)))

Here are some references in which you might be interested:

No I didn't forget. The answer is 5 of course.

When working with ember-cli and things seem to get messed up and you cannot figure out for the life of you what's wrong you can always resort to nuking it all and refreshing the environment.

This often helps me alot, and although I do not know for sure the exact details behind the reason it fixes things, I don't care as long as it works.

In my ~/.bash_aliases I've added the following aliases, a "regular" fix nom and a "nuke-it-all-and start-over-again" fix nomallas follows:

alias nom='rm -rf node_modules && npm cache clear && npm install'
alias nomall='rm -rf node_modules && npm cache clear && npm install && rm -rf bower_modules && bower cache clean && bower install'
...
alias realias='$EDITOR ~/.bash_aliases; source ~/.bash_aliases'

Just run realias to make the required changes and you're all set.

The Erlang notation [ F(X) || X <- L] means "the list of F(X) where X is taken from the list L."

1> L = [1,2,3,4,5].
[1,2,3,4,5]
2> [2*X || X <- L ].
[2,4,6,8,10]

Thus, [2*X || X <- L ] means "the list of 2*X where X is taken from the list L."

There's tons of other really really cool stuff you can do. Like qsort(L) for quick sorting lists:

qsort([]) -> [];
qsort([Pivot|T]) ->
	qsort([X || X <- T, X < Pivot])
	++ [Pivot] ++
	qsort([X || X <- T, X >= Pivot]).

Or perms(S) for generating all possible permutations of a string:

perms([]) -> [[]];
perms(L)  -> [[H|T] || H <- L, T <- perms(L--[H])].

Or pythag(N) for generating all Pythagorean triplets (sets of integers {A,B,C} where A2 + B2 = C2):

pythag(N) ->
    [ {A,B,C} ||
        A <- lists:seq(1,N),
        B <- lists:seq(1,N),
        C <- lists:seq(1,N),
        A+B+C =< N,
        A*A+B*B =:= C*C 
    ].

Ad infinitum into the wee hours of the morning...

The absence of side effects means that we can parallelize our software programs.

The technical term for memory areas that can be modified is mutable state. Erlang is a functional programming language and has immutable state.

If you use a conventional programming language such as C or Java to program a multicore CPU, then you will have to contend with the problem of shared memory.

In order not to corrupt shared memory, the memory has to be locked while it is accessed. Programs that access shared memory must not crash while they are manipulating the shared memory.

In Erlang, there is no mutable state, there is no shared memory, and there are no locks. This makes it easy to parallelize our programs.

jaerlang2_xlargecover.jpg
Programming Erlang (2nd edition)
by Joe Armstrong

All the code runs inside lightweight threads of execution (called processes) that are isolated and exchange information via messages.

Due to their lightweight nature, it is not uncommon to have hundreds of thousands of processes running concurrently in the same machine. Isolation allows processes to be garbage collected independently, reducing system-wide pauses, and using all machine resources as efficiently as possible (vertical scaling).

Processes are also able to communicate with other processes running on different machines in the same network. This provides the foundation for distribution, allowing developers to coordinate work across multiple nodes (horizontal scaling).

The unavoidable truth about software running in production is that things will go wrong. Even more when we take network, file systems and other third-party resources into account.

To cope with failures, it provides supervisors which describe how to restart parts of your system when things go awry, going back to a known initial state that is guaranteed to work.

elixir-logo.png

The future is uncertain, but I remain adamant and well-prepared for whatever might come my way.

That's why I decided to sharpen my programming skills further by refreshing my knowledge of Ruby, Rails and Ember. Lots of reading and practicing to do, great stuff to look forward to figuring out.

Long live convention over configuration.

I'm never too old to learn new stuff. Perhaps I should just retire early and become a gardener for fun and relaxation (not).

ember-mvc.png

This is the way that ember.js does it.

Completed and solved my first problem of the year. I know that today is only the first day of the year, but why wait when there are so many interesting challenges to pursue in life? Here is what I encountered on the RubyMonk website.

Problem Statement:
Given a 3 or 4 digit number with distinct digits, return a sorted array of all the unique numbers than can be formed with those digits.

Example:
Given: 123
Return: [123, 132, 213, 231, 312, 321]

My solution:

def number_shuffle(number)
  number.to_s.split(//).permutation.to_a.map {|a| a.join.to_i }
end

Tutorial solution:

def number_shuffle(number)
  no_of_combinations = number.to_s.size == 3 ? 6 : 24
  digits = number.to_s.split(//)
  combinations = []
  combinations << digits.shuffle.join.to_i while combinations.uniq.size!=no_of_combinations
  combinations.uniq.sort
end

My solution is not only conciser but in my opinion more elegant as well. Applying Occam's razor principle here, I'll let you decide for yourself

Rails enhances the flexibility of Ruby nicely. It allows built-in classes to seamlessly include extra fancy methods which sound like human language.The elegance and power of Rails is leveraged atop the malleability of the underlying Ruby language. Here's some proof:

kiffin@F5SL:...orial-hartl/sample_app $ rails console
Loading development environment (Rails 4.0.2)
>> 1.year.from_now
=> Sun, 21 Dec 2014 14:20:37 UTC +00:00
>> 10.weeks.ago
=> Sat, 12 Oct 2013 14:20:47 UTC +00:00
>> 1.kilobyte
=> 1024
>> 5.megabytes
=> 5242880

See Learn Web Development with Rails by Michael Hartl for a great introduction to Rails.

The quote below is taken from the MOOC I am following on BerkeleyX which is called CS.169.2x Software as a Service, part 2 (Refactoring and Legacy):

"... or we could do it the more principled way which is cover and modify, which means, let good test coverage be your security blanket. If you've got a good test suit, then when you make changes that breaks something, your test switch had tip you off to that fact, because you'll have regression test and plays. You'll know if you broke something." -- Armando Fox

Of the many software companies who were interviewed, more than eighty percent state that the most important skill lacking in modern day software engineers is the ability to deal successfully with legacy code.

How far can we push things the Ruby way? Here's an elegant Ruby one-liner for the fibonacci function. I was secretly hoping that it would go on and on forever spewing out endless rows of digits until the end of time, but that was not going to happen.

kiffin@F5SL:~ $ irb
irb(main):001:0> fibonacci = Hash.new{ |h,k| h[k] = k < 2 ? k : h[k-1] + h[k-2] }
=> {}

Function defined and working...

irb(main):002:0> fibonacci[10]
=> 55

Let's go deeper ...

irb(main):003:0> fibonacci[100]
=> 354224848179261915075

And deeper ...

irb(main):004:0> fibonacci[1000]
=> 43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875

Even more deeper ...

irb(main):005:0> fibonacci[5000]
=> 3878968454388325633701916308325905312082127714646245106160597214895550139044037097010822916462210669479293452858882973813483102008954982940361430156911478938364216563944106910214505634133706558656238254656700712525929903854933813928836378347518908762970712033337052923107693008518093849801803847813996748881765554653788291644268912980384613778969021502293082475666346224923071883324803280375039130352903304505842701147635242270210934637699104006714174883298422891491273104054328753298044273676822977244987749874555691907703880637046832794811358973739993110106219308149018570815397854379195305617510761053075688783766033667355445258844886241619210553457493675897849027988234351023599844663934853256411952221859563060475364645470760330902420806382584929156452876291575759142343809142302917491088984155209854432486594079793571316841692868039545309545388698114665082066862897420639323438488465240988742395873801976993820317174208932265468879364002630797780058759129671389634214252579116872755600360311370547754724604639987588046985178408674382863125

Deeper still ...

irb(main):006:0> fibonacci[10000]
SystemStackError: stack level too deep
	from /home/kiffin/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/irb/workspace.rb:86
Maybe IRB bug!
irb(main):007:0> 

Oops, we went too deep.

The moral of the story is that although Ruby is an elegant and amazing programming language with endless possibilities, even it's magical powers are not limitless.

Learning the ML programming language is a lot of fun. This is my first in-depth initiation into the exciting world of functional programming. Here's something to whet your appetite, an elegant function for appending two lists of any type:

fun append e =
    case e of
        ([],ys) => ys
      | (x::xs,ys) => x :: append(xs,ys)

Here we are passing the function append an expression e, and if the pattern matches empty string plus string we stop, otherwise we prepend the first element to the tail appended to the list.

I am following the online Coursera training by the University of Washington called Programming Languages given by Dan Grossman.

Great stuff to keep my aging brain cells oiled and running efficiently.

Random entries

Here are some random entries that you might be interested in:

Recent Assets

  • 2023-09-24-jong-tegen-oud-1.jpg
  • 2023-09-24-jong-tegen-oud-2.jpg
  • just-call-me-fred.png
  • foggy-morning.png
  • oma-2023-07-27.jpg
  • i-almost-died.png
  • chipping-from-twenty-meters.png
  • de-koepel.png
  • screenshot-www.udemy.com-2023.05.18-10_02_39.png
  • screenshot-www.golf.nl-2023.05.08-09_57_30.png
  • IMG-20230423-WA0000.jpg
  • me-and-my-radio-paradise-hat.png

Recent Comments

  • Long time no see: I remember them, as well. I remember Donald was my ...
    - Charles
  • Bridge to the moon: Yes it was a drawing and my older brother told me ...
    - jpmcfarlane
  • Bridge to the moon: Wow, that's quite a coincidence that we both sent ...
    - Kiffin
  • Bridge to the moon: Hello I was in my teens when Gemini 4 went up that ...
    - jpmcfarlane
  • Back to work: Congratulations Kiffin, I hope it is something you ...
    - KathleenC

Golf Handicap

Information

This personal weblog was started way back on July 21, 2001 which means that it is 7-21-2001 old.

So far this blog contains no less than 2498 entries and as many as 1877 comments.

Important events

Graduated from Stanford 6-5-1979 ago.

Kiffin Rockwell was shot down and killed 9-23-1916 ago.

Believe it or not but I am 10-11-1957 young.

First met Thea in Balestrand, Norway 6-14-1980 ago.

Began well-balanced and healthy life style 1-8-2013 ago.

My father passed away 10-20-2000 ago.

My mother passed away 3-27-2018 ago.

Started Gishtech 04-25-2016 ago.