2023-12-08

On case sensitiveness and path syntax

Just another filler article. And what is this about? The usual stuff, of course!

To be or not to be case sensitive? That’s the question!

In languages like C, C++, and others, symbols are case sensitive. The variable x is different from X, the function get_name() isn’t the same as get_naMe(), and so on.

In few languages the case is semantically relevant1: in Go the first letter case determines the visibility (uppercase for public, lowercase for private); in Erlang atoms begin with a lowercase letter, and variables begin with an uppercase letter2 (similar to Prolog); in Ruby an uppercase first letter says it is a constant (and classes’ and modules’ names need to be constant, hence they must begin with an uppercase letter)3

Once I thought that a language must have case-sensitive symbols, and almost disliked languages which haven’t. Now I changed my mind: case insensitive languages are fine by me, and maybe even better. It doesn’t make sense to distinguish between X and x], and a symbol appearing once or few times with a letter in different case shows just typos — the program will compile and work as expected — but of course if the same symbol appears several times with inconsistent case… it is “just” bad style.4

Languages like Ada, Fortran, PL/SQL, are case insensitive. But the group of non case sensitive languages seem to be smaller than the case sensitive group.5

The same goes for the filesystems: after all, why should I bother to type a directory or a file with the right case?6

Everything should be an expression

Many languages have statements and expressions. Expressions have a value, statements don’t. In C (just to pick a language) the following code is syntactically wrong:

int a = if (c > 5) 14; else 12;

This is when you can use the so called ternary operator, which is nothing else but an if-then-else as an expression — and so, it serves also the purpose of showing what I mean.

int a = c > 5 ? 14 : 12;

Let imagine another case:

int l = for (int x = 0; x < 10; x++) {
  printf("%d\n", x);
};

At the end of the for loop, what should l be? Well, in this case I’d say: the value returned by the last execution of the printf (which in fact returns a value).

This isn’t very much useful, but I am just showing what I mean. Each statement could have a value, as an expression; when looping, the value of the expression would be the value of the last statement.

int sr2 = do {
  int r = INITIAL_VALUE;
  // implementing some computation
  r;
} while(0);

The code above would assign to sr2 the value of r. It looks like an inlined function…

Languages that work like this exist, and I think this is nice.

Paths

The directories (folders) in a path should be separated by /. Microsoft Windows uses \. It is just a choice until you have to deal with strings in some programming language. This because the backslash can be used as the escape character. So that a path like c:\Windows\xxx\yyy could need to be written as:

   const char *where = "c:\\Windows\\xxx\\yyy";

This is very annoying. Microsoft should change that and allow the use of just /. As unix, linux, mac, amiga, do or did.

An URI for files in Windows uses / and looks like:

file:///c:/Windows/xxx/yyy

So, Microsoft could accept c:/Windows/xxx/yyy!

More on paths to files/resources

On Windows you are used to the C: part. That is a “good” idea, but done wrong. The wrong part is that in Windows it is a single letter, as it was in Microsoft DOS, and there cannot be very much the user can do about what that letter is and represent.

Take the Amiga instead. Before the path part, Amiga too had a part with the :, but it was (is?) very much more powerful than the single letter stuff of Windows.

On Amiga (where the : aren’t followed by / and it does not need to be a single letter), it could be the name of a mounted drive (harddisk) partition, a logical device of some kind, an alias, … Some logical names were created automatically, others can be created by the user (at startup or anytime later) using the command assign — and it is even possible to assign more than a directory to a single “assign”!

Examples:

  • c: refers to the location of the folder(s) where you put the commands — something like the bin on *nix. If I remember correctly, by default it is sys:c, where in turn sys: is the location of the operating system (where the system booted from).7
  • custom work: — I had this on the Amiga back then, and it was simply a path to the disk/folder where much of the work was done. I shared the system with my dad, and so I had work:mauro — see? no / after : – which in turn I could write also as dh1:path/I/cannot/remember/now/mauro. Where dh1: was the name of the second drive where all the data were: dh0: was the system partition, that is, it would be also the same as sys: — don’t ask why dh instead of hd (hard-disk): I cannot remember why they were named like that.
  • df0:, df1: referred to the floppy disk device(s). The df0: should be the drive Amigas was equipped with.
  • con: was used to send commands to the console driver8, and allowed you to make the Amiga open a console window to be used as output of a program.
  • nil: like /dev/null on *nix systems — in fact, what Linux has as /dev/…, likely Amiga would have as …:.
  • devs: points to where the *.devices were (that is, what you’d call drivers, I believe, though the l: logical directory is where the Amiga DOS handler were)
  • libs: points to where the dynamic libraries were (something like DLL on Windows, SO on Linux, …)
  • speak: sending a text to this logical name was a way to make your Amiga speak with its speech synthesis system!
  • ram: an in-memory filesystem (ramdisk) was mounted here – a volatile filesystem, consuming RAM, as its name suggests, useful to store files on the fly, and temporaries, usually in ram:t (the t: name is usually assigned to ram:t, consuming RAM — but you could assign it to a drawer on the hard disk)
  • envarc: where the environment variables are stored persistently, while env: is where you can access volatile environment variables.
  • fonts: the logical name of the folder containing the fonts

You get the idea. For some of the functions shown, on Linux you would use /dev/…, /proc, /sys

I am not saying other systems should embrace this path completely: it would make no sense on Linux to have nil:, for example. But I’d like the possibility to have aliases like work:.9


  1. And by that I mean that it is not just a convention: you need to use uppercase/lowercase because it changes the “meaning”.↩︎

  2. An underscore alone is an anonymous variable. Variables starting with an underscore don’t raise a warning if unused. See the documentation.↩︎

  3. All the remaining uppercase/lowercase usage is convention: the conventional style says to name constants like this: THIS_IS_A_CONST. But This_is_a_const would do, too. And it would be a different constant!↩︎

  4. The fact that the language isn’t case sensitive does not mean that conventions on letters’ case shouldn’t exist and be enforced.↩︎

  5. Parsing a case sensitive language can be a little bit easier/faster, I think. Is this really relevant?↩︎

  6. Real story: I can’t remember how, but at a certain point I had a folder Documents and a folder documents, on a case-sensitive FS. An external harddrive I use for backups is formatted as NTFS, which isn’t case sensitive. I use rsync -av, but most of the time I correctly wrote Documents, and so the files in documents didn’t get backed up. When I noticed, I rsync-ed documents into Documents and then rm -rf documents, and everything went back to how it should have been. What is the value of being able to have documents and Documents, or any other names which differ just in the letters case?↩︎

  7. Also, you can assign multiple drawers to a name like c:, so that you can put your commands around: sys:c would always be present, for the system commands; then you could add name:c, for instance.↩︎

  8. If I remember well, it is more correct to say handler. Amiga DOS had these “components” called handlers, a different thing than drivers (which would be in the logical directory devs:)↩︎

  9. On the system I am using right now, I have a data disk mounted at /DATA. This appears “for real” in the root of the filesystem, /, like other mounted things could appear there (/mnt/whatever could be an alternative; and luckly /media is where removable media are mounted into, e.g. /media/user/USB0 — I’d prefer the data: option, though).↩︎

No comments:

Post a Comment