Posts Tagged ‘Programming’
September 1st, 2010
I’ve seen lots of examples of rake (the ruby make replacement) being used as a build tool in non-ruby projects. Many of these are still modern platforms, like .Net. For example, StructureMap builds with rake. But I’ve found that even on older platforms, the power of having a full programming language in your build tool is useful.
Recently, I was working through examples in Thinking in C++
, and there is the need to build many small one file examples. I started writing a Makefile to simplify this, and decided to try rake instead.
The power of a programming language brings a lot to table when doing repetitive tasks. Check out the following Rakefile which generates a build, run, and clean method for each file listed in an array. And there are aggregate methods which will run or clean all.
exe_name = ["hello","c_in_cpp","file","vector"]
exe_name.each do |f|
desc "clean #{f}"
task "clean_#{f}".to_sym do
sh "rm -rf #{f} #{f}.o"
end
desc "build #{f}"
task "build_#{f}".to_sym => "clean_#{f}" do
sh "g++ #{f}.cpp -o #{f}"
end
desc "run #{f}"
task "run_#{f}".to_sym => "build_#{f}" do
sh "./#{f} 2> error.log"
end
end
desc "run all"
task :default => exe_name.collect{|f| "run_#{f}"}
desc "clean all"
task :clean => exe_name.collect{|f| "clean_#{f}"}
If any of the above is unclear, and you want to see the output, do the following: copy and paste that code into a file named “Rakefile”. Run “rake -T” to lists all available tasks. You won’t be able to actually run the tasks, unless you have the appropriate cpp files in the directory (ie “rake run_hello” requires hello.cpp).
If you want to learn a build tool, and know ruby, or want to learn ruby rather than some specialized build language with no other uses, give rake a shot.
February 26th, 2010
I’ve been working with StructureMap lately, and struggled when I need to pass this in. The following code is an example of resolving that issue…
namespace StateMachine
{
public class StateRegistry : StructureMap.Configuration.DSL.Registry
{
public StateRegistry ()
{
For<IState>.Use<StateA>.Named("FirstState");
For<IState>.Use<StateB>.Named("SecondState");
}
}
public interface IStateMachine
{
void ChangeState(IState state);
}
public interface IState
{
void DoWork();
}
public class StateA : IState
{
IStateMachine _machine;
public StateA(IStateMachine machine)
{
_machine = machine;
}
public void DoWork() { // do stuff }
}
public class Machine : IStateMachine
{
public IState FirstState {get;set;}
public IState SecondState {get;set;}
public IState CurrentState {get; private set;}
public Machine()
{
FirstState = ObjectFactory.With<IStateMachine>(this).GetInstance<IState>("FirstState");
SecondState = ObjectFactory.With<IStateMachine>(this).GetInstance<IState>("SecondState");
ChangeState(FirstState);
}
public void ChangeState(IState state) { CurrentState = state; }
}
}
February 24th, 2010
I’ve had several discussion recently some of the more advanced features of JavaScript, such as functions as return values, namespaces, encapsulation, etc. In order to demonstrate some of these things, I contrived a simple example of a dependency injection tool.
Never mind that dependency injection is not really a relevant pattern in JavaScript or other dynamic languages. It just fit all the pieces I wanted to demo. The Rhino JavaScript engine was used to run and test the example.
For more on how this stuff works, check out Douglas Crockford’s JavaScript: The Good Parts
//ObjectMap namespace
var ObjectMap = function (){
var that = this;
that.container = function () {
var registry = {};
var fact = {};
fact.register = function (name, constructor) {
registry[name] = constructor;
};
fact.getObject = function (theType) {
return registry[theType]();
};
return fact;
}();
return that;
}();
//Dog constructor, with encapsulated private name
var Dog = function () {
var d = {};
var name = "spot";
d.getName = function () {return name;};
d.setName = function (val) {name=val; return d;};
d.speak = function () {return d.getName() + " barks";};
return d;
};
//register Dog with the DI tool
ObjectMap.container.register("Dog", Dog);
//get and use an object function the DI tool
var munson = ObjectMap.container.getObject("Dog");
munson.setName("Munson");
print(munson.speak());
February 8th, 2010
I did not realize that functions can fill in for predicates directly without lambda notation. To illustrate, consider the following:
void Main()
{
var words = new List<string>()
{
"therapists",
"s words",
"slang",
"mustache",
"sean connery"
};
var s_words = words.Where(w => w.StartsWith("s" ,StringComparison.CurrentCultureIgnoreCase));
foreach(var word in s_words)
{
Console.WriteLine(word);
}
}
It works, but it’s a rather long lambda, which is why I broke it out of the for loop. Let’s put that logic into a function, getting this:
void Main()
{
var words = new List<string>()
{
"therapists",
"s words",
"slang",
"mustache",
"sean connery"
};
foreach(var word in words.Where(w => SWords(w)))
{
Console.WriteLine(word);
}
}
public bool SWords(string word)
{
return word.StartsWith("s" ,StringComparison.CurrentCultureIgnoreCase);
}
That’s better. And you might find yourself using your test in other places in the code, so it’s useful to have the function. What I found out recently, is that you can go one step further:
void Main()
{
var words = new List<string>()
{
"therapists",
"s words",
"slang",
"mustache",
"sean connery"
};
foreach(var word in words.Where(SWords))
{
Console.WriteLine(word);
}
}
public bool SWords(string word)
{
return word.StartsWith("s" ,StringComparison.CurrentCultureIgnoreCase);
}
In this example, the savings may not look drastic. But for several chained methods you can gain a lot of brevity and clarity.
November 12th, 2009
With a little help from StackOverflow, I got emacs over ssh working on windows. This is trivial on mac/linux, but can be a challenge on windows. dired mode works too!
To summarize:
1. Download putty installer with all the tools.
2. Put putty install in the path
3. Generate a key with PuttyGen
4. Copy public key to your server
5. Append public key to your .ssh/authorized_keys file (be sure to remove extraneous puttygen text, just get the key)
6. Load up pageant and add your private key (this can be automated on windows boot)
7. Add the following to your .emacs config
(require ‘tramp)
(setq default-tramp-method “plink”)
As long as pageant is running with your key, you can edit your remote files using the format ssh://user@server:path/to/file