A reminder of why I don’t miss Ruby

About two minutes if thumbing around the official documentation for Ruby’s standard library, I quickly realised it would be faster to Google how to use the module for MD5/SHA* stuff than read the official stuff:



    def encrypt_password
      # This is just a place holder implementation for now
      require ‘digest’
      self.password = Digest::SHA512.hexdigest(password)
    end
Compare the documentation for Ruby’s Digest to Pythons’ hashlib. Even an uncommented C++ header file would be more useful than the docs for Ruby’s Digest module :-S.

The STAMAN Project: Phase IV,

Having thought of tasks and storage formats, it’s now time to figure out an implementation language, i.e. what programming langauge am I going to write the task manager in.

O.K. based on what we’ve got so far, it is easy to infer the following is worth having:

  • Portable between systems—a must for me 😉
  • Easy access to SQLite—usually trivial.
  • Better tools than gmtime().
That means this page is rather useful, for what languages can be ruled out. In my répertoire this means Go (aww), Scheme, AWK, and shell languages can be skipped. Reason being the portability of Scheme bindings in general, and the others lacking sufficient portability (for my taste) at this time. That still leaves about 13 languages, lol. PHP, Java, Lua, JavaScript, and X86 assembly are easy for me to rule out. Reasons for that can all be easily guessed; at least if you remember how much I enjoy Suns Java tools. JS/Lua are great choices but I don’t want to screw with the bindings and stuff.

I’m not very interested in compiling SQLite in C/C++ on Windows, or the CLI binding everywhere. So this effectively makes the choice Perl, Python, or Ruby. Out of those three, none is perfect either: perl doesn’t come with the required database code, it just has the definitive interface for databases everybody mimics. Python and Ruby on the other hand, come with SQLite bindings—which many distributions separate out into separate packages. It’s just a lose, lose situation when you think about dependencies, but it does beat writing your own everything for every program. Sometimes. Setup with these three dynamic languages would be easy though, in so far as we’ve gotten with the above.

Time handling is another issue. Perl has fairly minimalist handling of time built in, but on the upside, if you need it, it’s probably three abreast on CPAN. Time::Format and the core Time::Piece module each come to mind. What isn’t built into Perl, often comes with it or can be added to it. Ruby provides a simple but effective Time class, that makes for more natural code than you may expect. More complex operations will require Googling for a Ruby gem, or hand coding it on demand. Python on the other hand provides a comprehensive datetime module, and supporting time and calendar modules, all out of the box! I would say Python takes the lead here.

Rule one of getting work done: know how to leverage libraries.

In terms of programming languages, Perl, Ruby, and Python are generally equal enough for most tasks, so long as you don’t shoot yourself in the foot. Some subtle differences that personally irk me:

  • Perls autovivification can be almost as much a miss-feature as it can be a convenience. You’ve just got to learn the damn language :-P.
  • Ruby functions are not first class objects! Some things can also be weird if you’re not used to Ruby.
  • Python doesn’t always stand up well to typos, especially if they involve indentation o/.

Because of how many lines of code I’ve done in Python over the years, I am more familiar with it’s set of “Irks” than Ruby’s, like wise I know Sh, C, and Perl more intimately than other languages, so I really know their irks. For perl, it’s mostly thin things that get in inconvenient when combing the warnings pragmata with the nature of perl syntax. They spiritually conflict at times. Under Ruby, I mostly find gripes that have a bigger place in programmer culture. My issues with Python generally have to do with trade-offs that I disagree with as a matter of my convenience, even if it usually results in a Good Thing overall. It comes from a C-oriented background meshed with a love for the Perl programming language.

This is a fact: you will always be irked by your programming language, if you use it enough. What can I say, nothing is perfect. Shoot!

For this particular application, there’s some things worth noting also: language portability. If the machine doesn’t run perl, it’s not a real computer. Most systems you’re likely to care about will run Ruby and Python, and there’s probably a crusty old version of Python for those you don’t (nor directly should). In contrast however, Perl is often a lower level of “Cross platform” behaviour than Ruby/Python. You’ll find this highlighted well in the Camel book. One reason I use Python frequently, it always behaves as expected without so many subtle hiccups.

How much this pertains to the current matter, i.e. implementing STAMAN. Perl is the most universally available language, and I’m more prone to need such a feature than most people. A plus over Ruby is no crappy 1.8.x/1.9.x porting issues…! Of course however, I have a camel to ask about minor details, hehe. In my experience the Python 2k/3k thing is less issue than Ruby’s for writing code yourself, more of an issue in leveraging existing code.

So I reckon, that means Perl or Ruby is best called for here. I exclude Python, because I just use the frick’n thing to often.

Quick & Painless C/C++ header installations using rake

In wrapping up and refactoring my new rake driven build system, I’ve written numerous utility functions. Most stuff specific to compiling crap is in a custom “Builder” module that provides a templated interface to the current OS/Compiler kit, via environment variables and methods like make_object, make_shared_library. My top level rakefile also has a neato inference rule rigged together for handling my triple-tree and quad tree build patterns.

The real fun of the day however, is this baby:


#
# A magic function that generates file tasks that copy all headers from
# directory ind # to directory outd.  Any missing directories are created as
# needed.
#
# The return value is a list suitable for the right hand side of a task, e.g.
#
#   task :headers => header_magic(src, dest)
#
def header_magic(ind, outd)
  dirs = []
  hdrs = []

  find_files(ind, /.*.h[hxp]*$/) do |p|
    outdir = File.dirname p.sub(ind, outd)
    outfile = File.join(outd, File.basename(p))

    directory outdir
    file outfile => p do
      cp_r p, outdir
    end
    dirs.push outdir
    hdrs.push outfile
    CLEAN.include outfile, outdir
  end

  dirs+hdrs
end
find_files is another custom function, it simply takes a block and yields and file names matching the specified pattern. (In this case, more liberal than the usual header extensions but sufficient for my needs)
I call it header_magic, because it after all the other stuff I played with, it’s the closest to Clarke’s third law. Which is exactly what I want!
footnote: I just have my top level clean task nuke the entire build tree; so the CLEAN part hasn’t been tested.

Todo: Toolkit and Library madness

Examine for portability the following toolkits under these OSes: Windows NT, Mac OSX*, Unix-like.

*I sadly don’t have a Mac, although I would really love one. So a OSX binary of some form will have to pass.

GTK+ — C, C++, Perl, Python, Ruby, PHP, C#.NET (Java bindings also avail but seem to be gnome-centric)

Qt4 — C++, Perl, Python, Ruby, Java (C#.NET and PHP bindings seem to be questionable and only C++/Python and possibly Java bindings can be depended on).

WxWidgets — C++, Perl, Python, Ruby, Java, C#.NET

Swing and SWT would be considered if they were available under more languages !!!

Evaluate portable standard/add-on libraries to each language for the following capabilities:

String handling (they all do well in the language standard)
Regular Expressions (Only Perl and Ruby get this great imho)
XML Processing
Network programming — both sockets based API and protocol support (IMAP, POP, HTTP/S, FTP)
Database handling — must support MySQL, SQLite, and some form of flat file.
Basic compression and archive format support (e.g. tar; zip; gz; bz2; lzma)
Inter-Process Communication (IPC) methods and related process control (e.g. fork(), exec(), signal(), kill() type routine-families).
Ease of use and deployment

Goals:

Build up a standard frame work of toolkits/libraries/etc that are portable across both my general operating environment and the various languages I use

Attempt to standardize myself on few languages rather then rubber banding between various programming languages + sh/awk/sed/friends

Ensure full development environments are available to me under FreeBSD 7 and Windows NT 5.1 (e.g. I can code from either machine and not change tools)

At least one language for scripting/prototyping and one for more efficient execution when implemented in that language (e.g. 1 interpreted + 1 compiled)

and try to stay sane along the way without writing a few libraries in the process >_>

Something that has been on my mind of late

DRAFT POST

I very much need to start standardizing myself on a smaller set of tools. Maybe tools is not the best choice of ord, o much as it is a question of languages and libraries. It’s actually kind of ironic, I really would like to learn several more languages (Ada, Fortran, C#, Erlang, and I never did wrap my head around Scheme).

C++

Pro’s:

can do low level stuff

can interface well with C code and libraries

Qt is natively C++ and supports everything I need it to run on (in Qt4 OSE hehe)

Fairly portable and standardized (at least much of the 1998 standard…) with several compilers available.

Mainly toolkits and frame works available, both native and from C.

Widely used and my first language

Con’s:

having to dig into lower level interfaces is very error prone when doing it with a headache the size of California.

Often not my first choice for building a prototype *quickly* but good for final implementation.

Java

Pro’s:

Inheritable portable between JVMs of the same implementation (e.g. Sun JVM for Win and Sun VM for Mac can run same code).

Simpler OOP syntax then C++, imho

The Swing GUI toolkit is fairly portable and SWT sufficiently supports the platforms I want to avoid skipping.

I like the way it handles exceptions, and usually like checked exceptions — when a class is designed appropriately.

It’s well defined if not perfectly standardized and compliant implementations are fairly common enough (Sun’s)

Wildly used and my third language.

Well documented (if a bit boring)

Con’s:

Everything is OOP….

I prefer native code to waiting on java to load

Requires a suitable runtime

Conventions expected by some tools can occasionally be irksome (to me)

C# (C Sharp)

Pro’s:

It’s not Java

It’s similar to Java/C++

Core elements are standardized

Less resistance to shooting oneself in the foot / doing stupid things then Java but not as much as C++.

Gtk#, the binding of GTK+ to C# is available on the platforms I care about.

Con’s:

Most C# applications are probably tied to Microsoft Windows implementation via .NET or through Gnome related interfaces

Requires a runtime (e.g. .NET, Mono, or Dot GNU)

Requires just enough learning of it’s differences from Java, for me to use it.

PHP5

Pro’s:

Portable and interpreted

Widely used across the WWW for server side scripting.

GTK+ bindings to PHP available and portable’ish

Simple language and member of the CBF.

The OOP increasingly resembles Java syntax and is just “enough” syntax to be useful without cramming.

Well documented

Con’s:

Local php.ini files can cause problems (how much can you assume?)

Needs a run time (php) of the right version (5)

php4/php5 is less common off web servers or developers systems

Python

Pro’s:

Great for writing prototypes

Several toolkits available that are fairly portable

Easy to work with and quit portable (and issues of portability well noted in the docs)

Large standard library

Implementations for the Java Virtual Machine and Microsoft .NET framework are available (if not as current as CPython) as well as the standard (C)Python implementation.

Con’s:

Requires a run time

I *hate* it’s handling of regular expressions after being so used to Perl…

It’s slower then native code

Interfacing with C /or C++ code can, uhh… Get interesting, from a portability perspective.

The program is the source

Ruby

Pro’s:

Handy pure OOP language

Great handling of regular expressions within the language itself, as opposed through importing an object oriented interface (i.e. as in Python/Java/C++)

Usually very “comfortable” to write.

Large standard library

Con’s:

It requires a run time and alternative compilers (e.g. xruby, ironpython) may be lacking in reliability or cause some features to be unavailable

The program is the source

Wishing Ruby 2 would come sooner….

Documentation can be irksome at times

It’s slower then native code and even slower then Python (Ruby 1.8.x)

Some how, I think if I was the type for it, I would be stone cold drunk tonight… but as it is, I am sober as a codfish =/ Getting lit never helped any thing and my Families history is enough that it is not a fond concept. Although I must admit, a nice mixture of wodka, rum, and a little lemon juice does sound like an interesting idea.. Oh well, a spider can think lol.

trying to see if I can get QT (and possibly KDE) bindings for Ruby installed, I’ve had no luck with qtruby yet but so far korundum-3.5.5 is doing good, hope I don’t jinx it =/.

That’s not why I feel like getting drunk though, but even if I was that kind of person I’ve got to much crap to get done then to worry about it.

It is strange, how being busy is a two edged sword, in that it does have it’s advantages but it can be so damn exhausting some days !

damn, the build just blew, would be bloody nice if it would tell me *which* library is missing. Oh well, it’s not important. Hmm, what else to work on…

Wasting time with the Euclidean Algorithm

The other night, I was very bored so… When I remembered reading about the Euclidean Algorithm on Wikipedia, which is a method of finding the greatest common denominator (gcd). I fed several implementations through ye ol’time(1) to get a rough idea of what differences they made.

At first I did it in Ruby and C for comparison, then I recompiled the *.c files with maximum optimization. Tonight I added a set of Java and Python files to the setup, I’ll probably include Bourne Shell and Perl later for fun.

For any one interested,

C // no optimization
./iteration 0.00s user 0.00s system 50% cpu 0.003 total
./recursion 0.00s user 0.00s system 66% cpu 0.002 total
./original 0.00s user 0.00s system 57% cpu 0.003 total
Ruby
./iteration.rb 0.01s user 0.00s system 59% cpu 0.014 total
./recursion.rb 0.00s user 0.00s system 79% cpu 0.010 total
./original.rb 0.00s user 0.01s system 75% cpu 0.010 total
C // optimized, -O3
./iteration-o 0.00s user 0.00s system 48% cpu 0.003 total
./recursion-o 0.00s user 0.00s system 32% cpu 0.005 total
./original-o 0.00s user 0.00s system 37% cpu 0.004 total
Java
java EuclideanIteration 0.39s user 0.38s system 66% cpu 1.165 total
java EuclideanRecursion 0.48s user 0.30s system 72% cpu 1.066 total
java EuclideanOriginal 0.36s user 0.42s system 67% cpu 1.155 total
Python
./iteration.py 0.01s user 0.01s system 59% cpu 0.034 total
./recursion.py 0.01s user 0.01s system 65% cpu 0.032 total
./original.py 0.01s user 0.01s system 65% cpu 0.031 total

done with:

ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-freebsd6]
gcc version 3.4.6 [FreeBSD] 20060305
javac 1.5.0
Python 2.5.1

The C versions were the same sources but compiled with -O3 for the optimized
version.

I’ve assigned each outcome a score, 3 for what I feel is fastest, 2 for the intermediate (often close) and 1 for the worst and totalled it:

method  C RB C(-O3) Java Python Total
iteration 2 1 3 2 2 10
recursion 3 2 2 1 1 9
original 1 3 1 3 3 11

And the code, which I tried to keep similar. Also the gcd()/mygcd() routines were always implemented as a function because of the recursive version in the tests.

#include <stdio.h>

#define A 1071
#define B 1029

int
mygcd( int a, int b ) {
int t = 0;
while ( b != 0 ) {
t = b;
b = a % b;
a = t;
}
return a;
}

int
main(void) {
mygcd(A, B);
return 0;
}


#include <stdio.h>

#define A 1071
#define B 1029

int
mygcd( int a, int b ) {
if ( b == 0 ) {
return a;
} else {
return mygcd( b, a%b );
}
}

int
main(void) {
mygcd(A, B);
return 0;
}


#include <stdio.h>
#define A 1071
#define B 1029


int
mygcd( int a, int b ) {
while ( b != 0 ) {
if ( a > b ) {
a = a-b;
} else {
b = b-a;
}
}
return a;
}

int
main(void) {
mygcd(A, B);
return 0;
}

#!/usr/local/bin/ruby -w

def gcd(a, b)
while b != 0
t = b
b = a % b
a = t
end
return a

gcd( 1071, 1029 )
#!/usr/local/bin/ruby -w

def gcd(a,b)
if b == 0
return a
else
return gcd(b, a % b )
end
end

gcd( 1071, 1029 )
#!/usr/local/bin/ruby -w

def gcd( a, b )
while b != 0
if a > b
a = a - b
else
b = b - a
end
end
return a
end

gcd( 1071, 1029 )

class EuclideanIteration {
static final int A = 1071;
static final int B = 1029;

public static int
mygcd( int a, int b ) {
int t = 0;
while ( b != 0 ) {
t = b;
b = a % b;
a = t;
}
return a;
}

public static void
main( String[] args ) {
mygcd(A, B);
}
}



class EuclideanRecursion {
static final int A = 1071;
static final int B = 1029;

public static int
mygcd( int a, int b ) {
if ( b == 0 ) {
return a;
} else {
return mygcd( b, a%b );
}
}


public static void
main( String[] args ) {
mygcd(A, B);
}
}


class EuclideanOriginal {
static final int A = 1071;
static final int B = 1029;

public static int
mygcd( int a, int b ) {
while ( b != 0 ) {
if ( a > b ) {
a = a-b;
} else {
b = b-a;
}
}
return a;
}


public static void
main( String[] args ) {
mygcd(A, B);
}
}

#!/usr/local/bin/python

def mygcd(a, b):
while b != 0:
t = b
b = a % b
a = t
return a


mygcd( 1071, 1029 )
#!/usr/local/bin/python

def mygcd( a, b ):
if b == 0:
return a
else:
return mygcd( b, a %b )


mygcd( 1071, 1029 )
#!/usr/local/bin/python

def mygcd( a, b ):
while b != 0:
if a > b:
a = a-b
else:
b = b-a
return a


mygcd( 1071, 1029 )

New toy..

Managed to get some nice time off today, read some of the library books, watched Tron, Ghost Busters I, and Spaced Invaders, but most of all got to relax. I’ve also placed my VIMRC file into a cvs repository on my OpenBSD box, that should make syncing changes with my Desktop/Laptop easier, plus allow me to see what I’ve changed hehe.

Had an interesting idea and started playing with some Ruby today also.

Normally when I start a new program I make a new directory in ~/code/Lang/src/ and copy a template makefile over from ../../makefiles/ and edit it to my needs. In one of the library books, I found a GNU Makefile that essentially automates building a C/C++ program where by all C/C++ source files (subject to make handling the dependencies) are compiled into corresponding files and get linked together into the binary, nice little thing when you look at it. With a little tinkering it could probably be made semi-language independent but I don’t really have time to dig into GNU Make’s syntax and features to do that.

I’ve basically written makefiles in the past that should work with just about any ol’make program. For much the same reason I write shell scripts that should run on most any /bin/sh, because I don’t want to edit the freaking thing if I ever meet a Unix like OS it won’t run on lool.

The idea I had was a enlazynating program that by knowing a fair bit about a given languages normal build process (such as C, C++, and Java), it could then automate the process of building it without having to generate a makefile, kind of like a ‘smart-makefile’ of sorts. I’ve got a alias set in my shell so that gcc is called on the command line with my usual settings. I also tend to include a few more once the things done.

It’s probably a stupid idea to do this, a decent BSD or GNU Makefile would likely serve much better (and be worth the learning of each ones extensions to make). But I rather like to be able to just ‘have fun’ playing with and testing stuff.

Right now, it seems to be able to handle a simple compile/link of files in one directory but needs some work to properly link files in subdir’s, lots of other stuff to do. But working on it has been a good way to pass the time.

Currently I classify this as a toy rather then a program for serious usage. But if I ever finish it, I might use it just for the sake of keeping a fairly fast build/test cycle.

If I could, I would’ve made a machine to manage VHS-Tape/DVD-Disk changing but hey, I’m not an inventor when it comes to to building some thing out of thin air…

Here is what I’ve done over the past couple hours, it’s not very good but it’s a starting point for later play.

#!/usr/local/bin/ruby -w
# usage: make [opt] project [dir]
# TODO:
# rdoc...
# handle header files and linking properly in C
# support more then C
# implement a way to set lang opts/debug/profiler stuff correctly
# reduce usage of $globals
# clean up code... looks like sludge

require 'getoptlong'
require 'rdoc/usage'

$lang=nil
$project=''
$startdir=Dir.pwd
$debug=false
$profiler=false
$verbose=false

def main()

opts = GetoptLong.new(
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
[ '--lang', '-l', GetoptLong::REQUIRED_ARGUMENT ],
[ '--lang-opts', '-o', GetoptLong::REQUIRED_ARGUMENT ],
[ '--debug', '-d', GetoptLong::OPTIONAL_ARGUMENT ],
[ '--prof', '-p', GetoptLong::OPTIONAL_ARGUMENT ],
[ '--clean', '-c', GetoptLong::NO_ARGUMENT ],
[ '--verbose', '-v', GetoptLong::NO_ARGUMENT ]
)

begin
opts.each do |opt, arg|
case opt
when '--help'
RDoc::usage()
when '--lang'
proc_lang( arg )
when '--lang-opts'
puts "#{arg} -> --lang-opts not implemented!"
when '--debug'
$debug = true
when '--prof'
$profiler = arg
when '--verbose'
$verbose=true
end
end

if ARGV[0]
$project = ARGV[0]
end
if ARGV[1]
$startdir = ARGV[1]
end
puts ARGV #debug
puts "nn"
n=LangC.new()
n.make()

unless $lang
$stderr.puts( 'WARNING: --lang not set!, defaulting to ISO C99' )
end

# call usage() on *any* error and print the problem
rescue StandardError
puts( $! )
RDoc::usage()

end

end

def proc_lang( str )

case str
when 'c','C'
# set up for C
$lang=str
when 'c++','cpp','C++','C++','cc','CC','cxx','CXX'
# set up for C++
when 'java','Java'
# set up for Java
when 'Perl','pl', 'plx'
# Setup for Perl
when 'Python','py'
# Setup for Python
when 'Ruby','rb'
# set up for Ruby ;-)
end
end

class Lang

def make()
end

def each( startdir, &block )
dp = Dir.open(startdir) do |dir|
dir.each do |node|
if node == '.' or node == '..'
next
end
p = File.expand_path( node, startdir )
yield( p )
if File.directory?( p )
self.each( p, &block )
end
end
end
end

end # !class Lang


class LangC < Lang

@@compiler = 'gcc'
@@cflags = "-Wall -Wpointer-arith -Wcast-qual -Wcast-align " +
"-Wconversion -Waggregate-return -Wstrict-prototypes " +
"-Wmissing-prototypes -Wmissing-declarations " +
"-Wredundant-decls -Winline -Wnested-externs " +
"-std=c99 -march=i686 -pipe "
@@ldfags = nil
@@debug = '-g'
@@prof = nil
@filelist = Array.new()

# The very bloody boring constructor which serves only to override the
# defaults for our static class variables.
#
def initialize( compiler=false, cflags=false, ldflags=false,
debug=false, prof=false )

if compiler then @@compiler = compiler end
if cflags then @@cflags = cflags end
if ldflags then @@ldfags = ldflags end
if debug then @@debug = debug end
if prof then @@prof = prof end
@@ldflags=nil;@@prof=nil#debug

end

# Assemble project
def make()

@filelist = Array.new()
self.compile()
self.link()

end

# Walk the directory tree and compile all .c files into .o
#
def compile()

$stdout.puts '------- COMPILING -------' if $verbose

self.each( $startdir ) do |file|
if file =~ /.*.c$/
p = file.to_s.gsub( File.extname(file),".o" )
@filelist.push( p )
# Don't compile unless the source is newer then the object files
if File.exists?( p )
next unless timecheck(file,p)
end

system( "#{@@compiler} #{@@cflags} #{@@debug} #{@@prof} " +
"#{file} -c -o #{p}" )
end
end
end

# Walk the directory tree and link all object files
def link()

$stdout.puts '------- LINKING -------' if $verbose

@filelist.each do |obj|
system( "#{@@compiler} #{@@cflags} #{@@ldflags} #{@@debug} " +
"#{@@prof} #{obj} -o #{$startdir}/#{$project}" )
end
end

# Return true if first filename has a newer time stamp then the second
#
def timecheck( f1, f2 )
File.mtime( f1 ) > File.mtime( f2 ) ? true : false
end

end

if __FILE__ == $0
main()
end

Code and Gems

On a whim, I started work on anew toy.

A ruby script to process in an M3U play list and output a track list in HTML (with some nice options and stuff too).

While I could probably find a script for amarok or google some thing to do it. I’ve been itching for some thing to sink my teeth in, thats not going to take years to do. To be honest, I’ve been going crazy…. Can’t stand not to have some program to work on, ether writing, debugging, configuring, or testing.

I’ve never really been the sort of guy, that could just sit down and say “Ok, we need to get result foo… So we’ve got to do bar to get it”. When I have most of what I’m doing formed in my minds eye, I can write it out. And kick it about till I make it work (usually). But if I just knock my head on the wall, I usually fail to figure out how to do the things in the middle. Unless my brain kicks into gear and figures out a nice overview $_$

Needless to say, I doubt I’d ever be happy playing with searching and sorting algorithms.. lol. To night, I’ve had a lot of fun. The program might not be one I’ll use much but the important thing is

  1. I’ve had fun working on it and
  2. It lets me learn more about the Language
  3. Enjoying working on a little some thing every now and then is my favorite way to learn the features, standard library/e.t.c, and memorize the syntax of the language

It’s been one of the rare times where I got a simple idea, a ruby script to take M3U files and spit out HTML track listings (simple and fancy/detailed). Sat down and started munching on the problem… step by step, without any real overview of how to do it.

When I worked on rf.c, a little program I made… Because using cat(1) to print an entire file to stdout instead of concatenating files annoys me 0.o

I had a lot of fun learning, it helped me get used to using GDB and writing C instead of reading for a change. but when I did rf.c, I had a pretty complete mental picture of the program before I ever started, I knew I’d want it to do x.y.z. And I knew how I would have to implement it more or less, before I started line one. With this toy, I had no idea what the heck I would be doing in Ruby other then I’d be dealing with strings and file paths.

So, it’s been a wonderful time just sitting and working as I go along… Hell when I do some thing. I test sections of it before I use it, make a prototype, fix the errors I can find, adopt it into a semi-finalized version. And work on it till it’s the best quality program I can make of it. So, whats the harm in playing with a toy? xD

Instead of having to sit down and create the blue print before hand !

0442 local, nearly 1000 Hours Zulu time… So I’m glad that I’ve only got a short run to work tomorrow and little need of waking up EARLY besides walking the dogs.. Ok, bed time !

http://en.wikibooks.org/wiki/Ruby_Programming/Syntax

What a nice find hehehe.

I know the most about C syntactically, I even tend to think in terms of C when my brain tries to figure out how to deal with some thing. But I’d like to have the same grasp on Ruby as I do on C’s syntax. Get ride of those oh joy I need to fetch a language reference moments when I’m trying to do some thing.