Consider the following example:
The user wants a program to calculate a few fibonacci numbers. Sounds easy enough. pseudocode:
stdout.write("How many fibonacci numbers do you want to calculate? ") int count = int(stdin.readline()) while count>0: stdout.writeline(calculate_next_fibonacci_number()) count--
Even a very simple program like this is already flawed:
- The program writes to stdout. That is not actually what the programmer intended, is it? The intention is to display a bunch of number to the user, not to write some text to stdout - there's no guarantee the user will ever see the text that's written to stdout.
- Similarly, the user input is read from stdin, which is a text (or file, if you prefer) interface, when in reality, the program requires a number, not text. This seems fundamentally wrong.
Let's think about what we're trying to do more abstractly. We want to:
- Calculate a bunch of numbers. How many is up to the user.
- display the results to the user.
Why, then, don't we write code exactly like that? (Most) programming languages provide this thing called a "function", which accepts parameters and uses them to do something. Does that not sound exactly like what we're trying to do?
void display_fibonacci_numbers( int number "how many fibonacci numbers to calculate"): Sequence<int> numbers while number>0: numbers.append(calculate_next_fibonacci_number()) number-- notify(numbers) display_fibonacci_numbers()
This code is, of course, incomplete - the
notify function isn't implemented anywhere, and the user needs some way of inputting a number. I would imagine the user's operating system or desktop manager or whatever to take care of that - it could display a terminal, it could generate a GUI, it could tell the user do write the number into the air with his nose; either way it does not (should not) concern me, the programmer.
It is my belief that software should be more abstract.
A few more examples.
- inter-process communication. How do you do it? Sockets? Signals? DBus? Files? The goal isn't to use sockets, signals or dbus, it's to communicate with another process. Why not something like
- Downloading files.
local_file.write(remote_file.read())? Why not
download(url), which could, depending on the system configuration, start the download right away, but with a low priority so as not to slow down other downloads, or add it to the download queue to be downloaded later, or whatever?
- File paths. Why on earth are file paths still strings (in most languages, at least)? Why do we have to deal with whether the path separator is
\, whether it's
.., or whatever? Why is there no
FilePathclass that takes care of this?
Going a step further, why not apply the duck-typing concept to modules? For example, in python, HTML is often parsed using the
from bs4 import BeautifulSoup page= BeautifulSoup(urlopen('http://test.at'))
Again, the programmer's goal wasn't to use BeautifulSoup, but to parse HTML. Why, then, would he explicitly tell his code to use the BeautifulSoup module? What he really wants is to
import HTMLParser page= HTMLParser.parse(urlopen('http://test.at'))
Duck-typing for modules: Who cares what module it is as long as it does what I want?
Why is programming not like this? Am I overlooking something, something that makes all this impossible (or impractical)?