Sunday, November 30, 2014

Find occurrences of a file in directories where another specific file is present.

There are situations where as a Linux user, you want to find if a file, say .gitignore is present in the current directory and its children. Here is how you do it:
$ find . -name .gitignore
Now let us extend this command to get the list of directories in which these instances of .gitignore are present:
$ find . -name .gitignore | xargs -n1 dirname
The command xargs creates command line inputs from standard input to the command. As is the norm with Linux, this can be the output of other commands. In this case, it takes the total output of find and gives them one by one (because of the -n1) to dirname. As you might know, dirname strips the last part of a input file path.

One more step to check if another specified file exists in the same directory:
$ find . -name .gitignore | xargs -n1 dirname | xargs -n1 -I {} ls {}/README.md 2>/dev/null
Here, we use the same xargs command. The option -I is used to provide a string that can be replaced by the output of the command after this. In this case, the command is ls. In other words, the name of the directory is replaced with the directory name followed by the name of the second file (README.md). The error redirection is to ensure that :No such file or directory error is not thrown by the shell.

Mediator Design Pattern

Simply put, the mediator pattern is used when complex calling relationship between classes exists and we want to avoid placing the code to invoke various classes based on various considerations in all the classes involved.

Purpose

According to the GoF, the mediator pattern
Allows loose coupling by encapsulating the way disparate sets of objects interact and communicate with each other. Allows for the actions of each object set to vary independently of one another.

When to use this pattern?

  1. The pattern is useful in any scenario where we want to centralize the complex relationships between multiple classes.
  2. This pattern is extensively used for GUI programming.

Terminology

Before we go further, it makes sense to understand the terminology.

Mediator

This refers to the class that acts as the intermediate to redirect calls from one class to another.

Colleague

These are the classes that want to communicate with each other or are the actual actors in the flow.

Example

It is easier to understand this with an example. Consider a scenario where the code needs to be go through a flow. The flow contains various colleagues called in different order based on the user's input:

User Input Sequence of call for Colleagues
1 C1 ⇒ C2 ⇒ C3
2 C2 ⇒ C4 ⇒ C3 ⇒ C6
3 C1 ⇒ C5 ⇒ C2
4 C1 ⇒ (if value < 0) { C8 ⇒ C2 } else { C6 ⇒ C3 ⇒ C7 } ⇒ C4

Pictorially

This can be represented pictorially as follows:

This would mean that the code in each of the colleagues would need to have the intelligence to call the others. This leads to a lot of duplication of code.

When a mediator is used, the code organization looks like this:

Code Snippet

The complete code is present at my github repo. The following sections show a relevant part of the code.

Class Diagram

IColleague

package com.karthicksmail.designpatterns.mediator;

/**
 * @author karthicksmail
 */
public interface IColleague {
 void execute();
}

ConcreteColleague1

package com.karthicksmail.designpatterns.mediator;

/**
 * @author karthicksmail
 *
 */
public class ConcreteColleague1 implements IColleague {
 /* (non-Javadoc)
  * @see com.karthicksmail.designpatterns.mediator.IColleague#execute()
  */
 public void execute() {
  System.out.println("Executing " + this.getClass().getSimpleName());
 }

}
You can create as many ConcreteColleague classes as required.

Mediator

package com.karthicksmail.designpatterns.mediator;

import java.util.ArrayList;

/**
 * @author karthicksmail
 *
 */
public class Mediator {
 private ArrayList colleagueList = new ArrayList();
 private boolean value = false;

 public boolean register(IColleague colleague) {
  System.out.println("Registering " + colleague.getClass().getSimpleName());
  return colleagueList.add(colleague);
 }

 public void setValue(boolean  value) {
  this.value = value;
 }

 public void invokeFlow(int flow) {
  switch (flow) {
  case 1: 
   colleagueList.get(0).execute();
   colleagueList.get(1).execute();
   colleagueList.get(2).execute();
   break;
  case 2:
   colleagueList.get(1).execute();
   colleagueList.get(3).execute();
   colleagueList.get(2).execute();
   colleagueList.get(5).execute();
   break;
  case 3:
   colleagueList.get(0).execute();
   colleagueList.get(4).execute();
   colleagueList.get(1).execute();
   break;
  case 4:
   colleagueList.get(0).execute();
   if (value) {
    colleagueList.get(7).execute();
    colleagueList.get(1).execute();
   } else {
    colleagueList.get(5).execute();
    colleagueList.get(2).execute();
    colleagueList.get(6).execute();
   }
   colleagueList.get(3).execute();
   break;
  default:
   System.out.println("ALERT!!! Wrong flow ID");
  }
 }
}

MediatorMain

package com.karthicksmail.designpatterns.mediator;

public class MediatorMain {
 public static void main(String[] args) {
  Mediator mediator = new Mediator();
  ConcreteColleague1 concreteColleague1 = new ConcreteColleague1();
  ConcreteColleague2 concreteColleague2 = new ConcreteColleague2();
  ConcreteColleague3 concreteColleague3 = new ConcreteColleague3();
  ConcreteColleague4 concreteColleague4 = new ConcreteColleague4();
  ConcreteColleague5 concreteColleague5 = new ConcreteColleague5();
  ConcreteColleague6 concreteColleague6 = new ConcreteColleague6();
  ConcreteColleague7 concreteColleague7 = new ConcreteColleague7();
  ConcreteColleague8 concreteColleague8 = new ConcreteColleague8();

  mediator.register(concreteColleague1);
  mediator.register(concreteColleague2);
  mediator.register(concreteColleague3);
  mediator.register(concreteColleague4);
  mediator.register(concreteColleague5);
  mediator.register(concreteColleague6);
  mediator.register(concreteColleague7);
  mediator.register(concreteColleague8);

  for (int flowId = 0; flowId < 6; flowId++) {
   System.out.println("Flow Number " + flowId);
   mediator.invokeFlow(flowId);
  }
  System.out.println("Flow Number 4");
  mediator.setValue(true);
  mediator.invokeFlow(4);
  
 }
}

Output

Registering ConcreteColleague1
Registering ConcreteColleague2
Registering ConcreteColleague3
Registering ConcreteColleague4
Registering ConcreteColleague5
Registering ConcreteColleague6
Registering ConcreteColleague7
Registering ConcreteColleague8
Flow Number 0
ALERT!!! Wrong flow ID
Flow Number 1
Executing ConcreteColleague1
Executing ConcreteColleague2
Executing ConcreteColleague3
Flow Number 2
Executing ConcreteColleague2
Executing ConcreteColleague4
Executing ConcreteColleague3
Executing ConcreteColleague6
Flow Number 3
Executing ConcreteColleague1
Executing ConcreteColleague5
Executing ConcreteColleague2
Flow Number 4
Executing ConcreteColleague1
Executing ConcreteColleague6
Executing ConcreteColleague3
Executing ConcreteColleague7
Executing ConcreteColleague4
Flow Number 5
ALERT!!! Wrong flow ID
Flow Number 4
Executing ConcreteColleague1
Executing ConcreteColleague8
Executing ConcreteColleague2
Executing ConcreteColleague4

Advantages

  1. Increases reusability by ensuring that each of the colleague classes adhere to some simple requirements only.
  2. Since all complicated code is maintained at a single class, the surface area of risk is reduced.

Disadvantages

  1. The Mediator class can become very complex. This means that any change between any unrelated use case would require all use cases to be tested. It can lead to spaghetti code in the Mediator class. But this can be handled by following clean coding practices.

Wednesday, September 04, 2013

Bash & Sed - Display Unix Directory Structure as a Tree

Recently, I wanted to display a directory structure as a tree. However, I did not want to do programming in a high level language like Java or Ruby and parse the file structure etc. I wanted to use something like Bash.

So, here it goes:
find . -name '*' | sed -e 's/^/|-/' -e 's/[^-][^\/]*\//|   /g' -e 's/|   \([A-Za-z0-9_.]\)/|   +--\1/'

The output of this command will be like this:
|-.
|   +--a.out
|   +--arraydecl.c
|   +--coverage
|   |   +--a.out
|   |   +--cov.c
|   +--interposn
|   |   +--cmain.c
|   |   +--cparts.c
|   |   +--cparts.o
|   |   +--libwithso.so
|   |   +--main
|   |   +--main.c
|   |   +--main.o
|   |   +--withso.c
|   +--IPC
|   |   +--pipe.c
|   |   +--pipe_impl.c
|   +--KandR
|   |   +--detab.c
|   |   +--entab.c
|   |   +--Plan.txt
|   |   +--Plan.txt1
|   +--notbitand.c
|   +--ptrjoin.c
|   +--telewords.c

Now to explain this:
First use the find command:
find . -name '*'
This displays the name of all the files and directories under the current directory. Remember that using find would display the relative path from the current directory and does not follow symbolic links, by default.

Next, we need to split the sed command to understand it better.
-e 's/^/|-/'
This replaces the beginning of every line with the characters |-.

Next we have a more complex looking sed expression.
-e 's/[^-][^\/]*\//|   /g'
This replaces any element in the path to the file except the basename with three spaces.

Finally, the expression
-e 's/|   \([A-Za-z0-9_.]\)/|   +--\1/
This replaces the two spaces followed by an alphabet/number/underscore/dot with a "+--" followed by the same alphabet/number/underscore/dot. This gives the "+--" in the structure.

Sunday, August 04, 2013

Sha-bang

Scripts are text files which need to be executed as if they are executables. One way to do this is to execute the script by giving the name of the interpreter and the name of the script like this:
$ inter path/to/file
Here, inter should be replaced by the name of the interpreter. These would be the corresponding executables for the languages like ruby, perl, bash etc. But what if you don't want to expose which language the script is in?
The first thing that you need to do is provide executable permissions on the script. Once this is done, the script becomes eligible to be executed. In other words, it can be executed as follows:

$ path/to/file

A simplistic explanation of what happens is as follows1:
  1. The current process is forked and a copy of itself is created.
  2. The corresponding interpreter is exec'ed to execute the script with the right interpreter.

But how will the OS1 know the correct interpreter to use?

Enter Sha-bang!

Sha-bang is the term for the symbol #!. This has to be given as the first two characters in the script and should be followed by the path to the interpreter in the same line. Some examples are as follows:

#!/bin/bash

#!/usr/bin/ruby

The OS1 takes whatever is given after #! till the end of the line and does the exec using that.

It is important to remember that the rest of the line is totally taken and used. This means that you can have spaces before pass arguments to the interpreter. For example, -d can be passed to perl like this:

#!/usr/bin/perl -d

This would interpret the script as a Perl script and execute it in debug mode.

There is one catch in this method. What if the interpreter is installed in a different location from what is specified in the sha-bang?

The env command is used for this purpose. Here is the usage:

#!/usr/bin/env perl -d

This command finds the interpreter found in the environment variable $PATH and executes the command with the interpreter found.

1Please note that I am not trying to be technically correct. I am trying to explain things simply. For a proper understanding of this, I would suggest a book like Richard Stevens' Unix Network Programming.

Saturday, August 03, 2013

Ruby - Find Phone Numbers corresponding to Words

Remember the 1800 numbers a part of which match up with a name like "1-800 walmart".

I wanted to write a program to convert a name into the corresponding number. I decided to try this first with Ruby. So, here is version 1:

#!/usr/bin/env ruby

print "Enter the name: "
name = gets.chomp
downname=name.downcase

number = downname.gsub(/[abc]/,"2").gsub(/[def]/,"3")
                 .gsub(/[ghi]/,"4").gsub(/[jkl]/,"5")
                 .gsub(/[mno]/,"6").gsub(/[pqrs]/,"7")
                 .gsub(/[tuv]/,"8").gsub(/[wxyz]/,"9")
                 .gsub(/ /,"0") 

puts "The Number corresponding #{name} is #{number}"

The output for this is as follows:
$ ./name_2_number.rb 
Enter the name: Karthick
The Number corresponding Karthick is 52784425
$ ./name_2_number.rb 
Enter the name: 1800-walmart
The Number corresponding 1800-walmart is 1800-9256278

To explain the program:
  1. Line number 1 is the sha-bang. I will put in a separate post to explain that one.
  2. Line number 3 prints the message "Enter the name: ".
  3. Line number 4 accepts the input using gets and removes the \n at the end of the accepted by using chomp. Though not essential in this case, it is generally a good practice to do a chomp of the inputs obtained from the user.
  4. Line number 5 converts the name into lower case character. For this purpose, I am using the downcase method of the String in ruby. Changing the text into lower case helps in simplifying the regular expression (regex, for short) in the next line.
  5. Line number 7 is the one that contains the core logic. In this line, I use the gsub method in String class to replace occurrences of each of the letters with the corresponding numbers. Note that the first argument of gsub is a regex, while the second argument is a string. The sequence of gsub calls replace all occurrences of alphabets and spaces with the corresponding numbers.
  6. Line number 13 prints the message containing the original name given and the corresponding number. I have used puts over here because I want a newline to be appended to the end of the message. This is the difference between a print and puts in ruby. Also, I had created the variable downname so that I can use name in this display.
As you can see, this program works fine but there are some basic issues with this script:

  1. Line number 7 is not efficient. Multiple calls to gsub is the culprit. 
  2. Line number 7 is long and unwieldy.
  3. The maintainer of this code must understand the regex. Based on what I have seen, a surprising number of software engineers are not good with regex.

So, here is version 2:
#!/usr/bin/env ruby

print "Enter the name: "
name = gets.chomp
downname=name.downcase

repl = {'a' => '2', 'b' => '2', 'c' => '2',
        'd' => '3', 'e' => '3', 'f' => '3',
        'g' => '4', 'h' => '4', 'i' => '4',
        'j' => '5', 'k' => '5', 'l' => '5',
        'm' => '6', 'n' => '6', 'o' => '6',
        'p' => '7', 'q' => '7', 'r' => '7', 's' => '7',
        't' => '8', 'u' => '8', 'v' => '8',
        'w' => '9', 'x' => '9', 'y' => '9', 'z' => '9',
        ' ' => '0'}

number = downname.gsub(/[a-z ]/) { |m| repl[m] }

puts "The Number corresponding #{name} is #{number}"

Two lines have changed from the original script. Let me explain these two lines alone:
  1. Line number 7 declares a hash of the mapping between the each letter and its corresponding number. Note that this includes a blank space as one of the characters and it is mapped to 0.
  2. Line number 9 calls one gsub and does the replacement of the values by using the hash declared in the line number 7.
This version works fine in ruby 1.8 and 1.9. However, ruby 1.9 has a shortcut for line number 9 in version 2. Here is the modified script (version 3):
#!/usr/bin/env ruby

# Works with ruby version greater than 1.9

print "Enter the name: "
name = gets.chomp
downname=name.downcase

repl = {'a' => '2', 'b' => '2', 'c' => '2',
        'd' => '3', 'e' => '3', 'f' => '3',
        'g' => '4', 'h' => '4', 'i' => '4',
        'j' => '5', 'k' => '5', 'l' => '5',
        'm' => '6', 'n' => '6', 'o' => '6',
        'p' => '7', 'q' => '7', 'r' => '7', 's' => '7',
        't' => '8', 'u' => '8', 'v' => '8',
        'w' => '9', 'x' => '9', 'y' => '9', 'z' => '9',
        ' ' => '0'}

number = downname.gsub(/[a-z]/, repl)

puts "The Number corresponding #{name} is #{number}"
The new version of gsub does the replacement. It does this by taking the regular expression as the first argument and the second argument as the hash.

Cheers!
Karthick S.

Sunday, September 30, 2012

Two ways to find the max of 5 numbers


It started as an experiment to find out which of the two ways (I could think of) how to find the max of 5 numbers. I wanted to make this language agnostic, in other words, no library functions or language specific features.

I used Java for this. Here is the program:

//LargestIn5.java
//Accept 5 numbers and find the largest of the 5 numbers

import java.util.Scanner;

public class LargestIn5
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);

int a, b, c, d, e; // The five numbers
int nCount = 0;

System.out.print("Enter the first number: ");
a = input.nextInt();

System.out.print("Enter the second number: ");
b = input.nextInt();

System.out.print("Enter the third number: ");
c = input.nextInt();

System.out.print("Enter the fourth number: ");
d = input.nextInt();

System.out.print("Enter the fifth number: ");
e = input.nextInt();

if ((a > b) && (a > c) && (a > d) && (a > e))
{
System.out.println(a + " is the largest");
System.out.println("nCount = 4");
}
else if ((b > a) && (b > c) && (b > d) && (b > e))
{
System.out.println(b + " is the largest");
System.out.println("nCount = 4");
}
else if ((c > a) && (c > b) && (c > d) && (c > e))
{
System.out.println(c + " is the largest");
System.out.println("nCount = 4");
}
else if ((d > a) && (d > b) && (d > c) && (d > e))
{
System.out.println(d + " is the largest");
System.out.println("nCount = 4");
}
else if ((e > a) && (e > b) && (e > c) && (e > d))
{
System.out.println(e + " is the largest");
System.out.println("nCount = 4");
}
else
{
System.out.println("There is something wrong...");
System.out.println("nCount = 0");
}

if (a > b)
{
nCount++;
if (a > c)
{ //a > b & c
nCount++;
if (a > d)
{ // a > b & c & d
nCount++;
if (a > e)
{ // a > b & c & d & e
nCount++;
System.out.println(a + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{ // e > a > b & c & d
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
else
{ // d > a > b & c
nCount++;
if (d > e)
{ // d > e & a > b & c
nCount++;
System.out.println(d + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{ // e > d > a > b & c
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
}
else
{ // c > a > b
nCount++;
if (c > d)
{ // c > d & a > b
nCount++;
if (c > e)
{ // c > d & e & a > b
nCount++;
System.out.println(c + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{ // e > c > d & a > b
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
else
{ // d > c > a > b
nCount++;
if (d > e)
{ // d > e & c > a > b
nCount++;
System.out.println(d + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{ // e > d > c > a > b
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
}
}
else
{ // b > a
nCount++;
if (b > c)
{ // b > a & c
nCount++;
if (b > d)
{ // b > a & c & d
nCount++;
if (b > e)
{ // b > a & c & d & e
nCount++;
System.out.println(b + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{ // e > b > a & c & d
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
else
{ // d > b > c
nCount++;
if (d > a)
{ // d > a & b > c
nCount++;
if (d > e)
{ // d > e & a & b > c
nCount++;
System.out.println(d + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{ // e > d > a & b > c
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
else
{ // a > d > b > c
nCount++;
if (a > e)
{ // a > e & d > b > c
nCount++;
System.out.println(a + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{ // e > a > d > b > c
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
}
}
else
{ // c > b > a
nCount++;
if (c > d)
{ // c > d & b > a
nCount++;
if (c > e)
{
nCount++;
System.out.println(c + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
else
{ // d > c > b > a
nCount++;
if (d > e)
{ // d > e & c > b > a
nCount++;
System.out.println(d + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{ // e > d > c > b > a
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
}
}
}
}


The variable nCount was to find out how many conditions are being executed. Method 2 seems more complex. But is it better in terms of number of conditions executed to find the answer.

Output from few runs:

$ java LargestIn5
Enter the first number: 1
Enter the second number: 2
Enter the third number: 3
Enter the fourth number: 4
Enter the fifth number: 5
5 is the largest
nCount = 4 
5 is the largest
nCount = 4 
$ java LargestIn5
Enter the first number: 2
Enter the second number: 3
Enter the third number: 4
Enter the fourth number: 5
Enter the fifth number: 1
5 is the largest
nCount = 4 
5 is the largest
nCount = 4 
$ java LargestIn5
Enter the first number: 3
Enter the second number: 4
Enter the third number: 5
Enter the fourth number: 1
Enter the fifth number: 2
5 is the largest
nCount = 4 
5 is the largest
nCount = 4 
$ java LargestIn5
Enter the first number: 4
Enter the second number: 5
Enter the third number: 1
Enter the fourth number: 2
Enter the fifth number: 3
5 is the largest
nCount = 4 
5 is the largest
nCount = 4 
$ java LargestIn5
Enter the first number: 5
Enter the second number: 1
Enter the third number: 2
Enter the fourth number: 3
Enter the fifth number: 4
5 is the largest
nCount = 4 
5 is the largest
nCount = 4 


Sometimes, the more complex looking code is not necessarily the more optimal one.

Saturday, March 31, 2012

Handling Return Values

Recently, I was discussing Defensive Programming with a relative newcomer to the industry. I mentioned that the concept was not dependent on languages and more logical in nature. In other words, though a language does not have specific language facilities for Defensive Programming.

To give an example, I used the following:

Consider a function is_data_found() which returns one of the following values:

#define SUCCESS 0
#define FAILURE 1
#define NO_DATA_FOUND 2

int fun1()
{
    //search for data in DB
    //If data not found return NO_DATA_FOUND
    //else if operation failed, then return FAILURE
    //Return SUCCESS
}

Now, one of the common (wrong) ways for a caller fun2() to handle the return values from the call to fun1() is:

void fun2()
{
    //Call fun1
    //if return value is not SUCCESS, continue process
    //else, throw exception
}

Based on code review feedback or testing, they might realize that NO_DATA_FOUND might be a valid scenario. In other words, fun2() might need to do create_if_not_found operation.

To accommodate this, they might change the caller to:

void fun3()
{
    //Call fun1
    //if return value is NO_DATA_FOUND, then create row
    //else if return value is SUCCESS, then continue process
    //else, throw exception
}

This would be fine in the current scenario. But what if a new return value is added to fun1(), say WARNING_POTENTIAL_STALE_DATA:

#define SUCCESS 0
#define FAILURE 1
#define NO_DATA_FOUND 2
#define WARNING_POTENTIAL_STALE_DATA 3

int fun1()
{
    //search for data in DB
    //If data not found return NO_DATA_FOUND
    //else if operation failed but previously fetched data available, then return WARNING_POTENTIAL_STALE_DATA
    //else if operation failed and no previously fetched data available, then return FAILURE
    //Return SUCCESS
}

Now, fun2() would not provide the complete functionality since it does not know about the new functionality. However, no one would notice this, since fun2() does not have the right code for handling such scenarios.

A better way to write the caller is:

void fun4()
{
    //Call fun1
    //if return value is NO_DATA_FOUND, then create row
    //else if return value is SUCCESS, then continue process
    //else if return value is FAILURE, then throw DATA_FETCH_FAILED_EXCEPTION
    //else, return UNKNOWN_RETURN_VALUE_EXCEPTION
}

Now, fun4() will throw an exception when WARNING_POTENTIAL_STALE_DATA is thrown.

Cheers!
Karthick S.

Sunday, December 25, 2011

Installing rvm in mac os x lion using bash

They are giving MacBook Pro as our laptop in our office. I wanted to install ruby. For this purpose, I wanted to install rvm. Based on instructions I found in the rvm site, I gave the command to download the installer and do the installation:

$ bash < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)
-sh: syntax error near unexpected token `<'

Since this can be split into two commands, I did the same:

$ curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer > rvm-installer
$ bash rvm-installer

When I did this, it threw out a lot of output. Hidden in this output was a line:

Installation of RVM to /Users/[user_name]/.rvm/ is complete.

Once I saw this, I did not bother looking further to see if things have failed or if there are any warnings. Turns out it did not work fine. There was an error in the output:

is_a_function: command not found

When I went ahead and added this path in .bash_profile, the error surfaced again. Google did not help either. Finally, with the help of an answer for my question at StackOverflow, I cracked it:
$ curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer | bash -s stable
Now to figure out how to install ruby. :)

Cheers!
Karthick S.

Saturday, October 22, 2011

Special options while printing in Python 3.x

One more post about printing values in Python 3.x and how it differs with Python 2.x.

To print the end of line using Python 2.x, all you need to do is add a comma to the end of the print list.

print "Hello ",
print "World"

The statements above print "Hello World" on the screen.

But with Python 3.x, it is different

print ("Hello ", end='')
print ("World")

This prints "Hello World" on the screen.

Another way to print the same would be:

print ("Hello", end=" ")
print ("World")

In other words, whatever is sent as a value for end is appended to the end of whatever is printed. You can even specify multi-character strings as the value for end.

In addition to this, there is another argument sep, which specifies the separator between the items to be printed.

print ("Hello", "World", sep = " ")

This would help in creating output as a CSV or a TSV files for example:

print ("FirstName", "LastName", sep=",")

Cheers!
Karthick S.

Tuesday, October 18, 2011

Differences in print between Python 2.x and Python 3.x

Recently, I started learning Python and installed the latest version available online - Python 3.2. I did this in spite of the fact that the book I was using Practical Programming: An Introduction to Computer Science using Python.

After completing a few exercises using the Python command line, I decided to save my script and execute them from command line. That is when things started to fail. Python would not allow me to print the output. It kept showing the variable to be printed and said SyntaxError: invalid syntax. To illustrate in command line, it was something like:

>>> i=5
>>> print i
File "", line 1
print i
^
SyntaxError: invalid syntax

Google could not help me with this. Finally, I went with intuition and solved it. I needed to enclose the arguments to print using parenthesis. But the book did not mention it.

This is because the enclosing parenthesis was not a requirement in Python 2.x, but is required in Python 3.x.

It kind of pissed me off (and I am sure I am not the first Python newbie to feel this way), that the language designers did not give a reasonably clear error message for this one.

Cheers!
Karthick S.