Comparison Shopping for Toilet Paper, in multiple computer languages.

It's hard to concentrate when you're tired and cranky, so I wasted some time writing a simple calculator in several different languages. This is a simple calculation of the cost-per-sheet for toilet paper. You can do this on a calculator, but this is just for fun. It's a toy program.

Maybe this can be like a "Rosetta Stone" useful for learning a bit about each language. There's a similar, much bigger list of Hello, World in many programming languages.

The shortest versions tend to be with the scripting languages:
PHP:

if ($argc != 4) {
	print "usage: php $argv[0] price rolls sheets-per-roll\n";
	exit;
}
print $argv[1] / ( $argv[2] * $argv[3] );
print "\n";

Perl, Python and Javascript are also short. Haskell, despite being compiled (or compilable), and using static, compile-time type checking, is short. It was the hardest one to code, because everything seems to be different in Haskell. Going from PHP to Python to C and even Java was kind of straightforward. Haskell required a lot of reading and searching (and this is a language I was trying to learn a couple months ago!):

import System.Environment

tpc :: (Fractional a) => a -> a -> a -> a
tpc p s r = ( p / ( s * r ) )

main = do
  args <- getArgs
  let (p:s:r:dummy) = args
  putStrLn (show (tpc (read p) (read s) (read r) ) )

C was pretty long, but it compiled into the smallest binary. I probably could have use a tighter, functional-style coding, but having written a whole lot of Visual Basic for Applications lately, and having modified my PHP and Java style to be more "spaced out", I'm doing the same here.

#include <stdio.h>
#include <stdlib.h>

void main(int argc, char *argv[]) {
	double p;
	double t;
	double r;
	double s;
	if (argc!=4) {
		printf("usage: %s price rolls sheets-per-roll\n", argv[0]);
		exit(0);
	}
	p = atof(argv[1]);
	r = atof(argv[2]);
	s = atof(argv[3]);

	t = p / ( r * s );
	printf("%f\n", t);
}

C++ was even worse, sorta. I riffed on what the Java version looked like, and made it fat on purpose, adding a totally gratuitous class where one wasn't needed. I'm a C bigot :) that and C++ isn't really a language for tiny toy programs:

/* Uses a gratuitous class.  I'm not a C++ programmer. */

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

class TPCalc {
	public:
		float tpc(float,float,float);
};

float TPCalc::tpc(float p, float r, float s) {
	return p / ( r * s );
}

int main(int argc, char *argv[]) {
	float p;
	float r;
	float s;
	float t;
	TPCalc calculator;

	if (argc!=4) {
		cout << "usage: " << argv[0] << " price rolls sheets-per-roll\n";
		return 0;
	}
	istringstream pbuffer(argv[1]);
	istringstream rbuffer(argv[2]);
	istringstream sbuffer(argv[3]);

	pbuffer >> p;
	rbuffer >> r;
	sbuffer >> s;

	t = calculator.tpc(p,r,s);

	cout << t << "\n";
	return 0;
}

I won't show the Java and Visual Basic.NET ones, but they're thick with structure, because those languages aren't really for little toy programs like this. The code just ends up looking absurd. I also cheated by using the MonoDevelop IDE to get my VB.NET template.

Here's a language I've never, ever coded in: vala

class TPCalc : GLib.Object {
	public static int main(string[] args) {
		double p;
		double r;
		double s;
		if (args.length != 4) {
			stdout.printf("usage: %s price rolls sheets-per-roll\n", args[0]);
			return 0;
		}
		p = double.parse(args[1]);
		r = double.parse(args[2]);
		s = double.parse(args[3]);
		stdout.printf("%f\n", (p/(r*s)) );
		return 0;
	}
}

Vala's a lot like Java, except it's designed to feel more like C. It's based around the GLib object system, and compiles to C code, which then compiles to executables, so it runs really fast on Linux and *nix systems. The printf part is like C, and the double.parse() is like Java. The class { ... } is like Java and all its copycats.

Just for comparison, binary sizes were 6216 for C, 10360 for Vala, 10560 for C++, and 14936 for Haskell. All these are dynamically linked Linux executables.

You can't really compare the VB.NET and Java class files, because the .exe file produced by vbnc includes code to fire up the Mono CIL and run the bytecode. Java class files don't have that. The TPCalc.class file was 715 bytes.

Part 2

There are more odd languages. Before I venture off into making GUI versions of TPCalc, I'll do some more odd languages. First up is Guile, the embedded Scheme language used in The GIMP, but which also runs as a standalone language. You'd think a Lisp language would be terse, and not sequential, but this script is a little longer than expected, sequential, and uses temporary variables. I even omitted checking for correct argument length because this verbosity bugged me.

#!/usr/bin/guile -s
!#
(define (tpc p r s) (/ (* 1.0 p) (* r s)))
(define c (command-line))
(define p (string->number (cadr c)))
(define r (string->number (caddr c)))
(define s (string->number (cadddr c)))
(write (tpc p r s))
(newline)

Lua is another language I don't know. Despite this, I was able to code this faster than most of the other examples, except maybe PHP and Perl, which I do know. That's something right there. It's a minimalist language intended for embedding in other programs; it's popular for video games and is part of the OpenWRT embedded Linux. The language is kind of like Python or Basic, but the # operator, which tells you the last index of an array, is like Perl. This code includes a gratuitous function definition, just like the Guile version.

#!/usr/bin/lua
if #arg < 3 then
  print ("usage: " .. arg[0] .. " price rolls sheets-per-roll")
  return
end
function tpc (p, r, s)
  return (p / (r * s))
end
p = arg[1]
r = arg[2]
s = arg[3]
print (tpc(p,r,s))

A Bash shell script rivals Haskell and Perl in its laconic clarity :) The sh language is so minimal that it lacks comparison operators and floating point math functions; they are carried out by commands. That is some kind of restraint in language design:

#!/bin/bash
P=$1
R=$2
S=$3
if ( test "" = "${S}" ) then
	echo "usage: $0 price rolls sheets-per-roll"
	exit 1
else
	echo "scale=8; ($P / ($R * $S))" | bc
fi
AttachmentSize
tpcalc.c316 bytes
tpcalc.cpp677 bytes
tpcalc.js_.txt197 bytes
tpcalc.php_.txt178 bytes
tpcalc.pl_.txt158 bytes
tpcalc.py_.txt252 bytes
tpcalc.vb429 bytes
TPCalc.java382 bytes
tpcalc.hs208 bytes
tpcalc.vala361 bytes
tpcalc.guile236 bytes
tpcalc.lua212 bytes
tpcalc.sh157 bytes