Exactly. A wordprocessor document *should* be data, in any well-designed system. But some vendors (mentioning no names) have mixed code and data together and given no way to distinguish the two.
I think there are two main classes of mail worms: those which rely on sending an attachment, and those which work by executing scripting commands directly in the mail client. The former could be avoided by making separate operations for 'open a document' and 'run a program'. (Opening an executable as a document would mean loading it into the disassembler, I guess. Or perhaps a message 'this is an executable not a document'.) The latter class of worm could be avoided by mail clients that treat messages as documents and never as executable code. Of course almost all Unix mail clients do this, so if someone sends you some Javascript in a message it will just be viewed as text.
The best hope is a user interface that clearly distinguishes between *running a program* and *opening a document*. Windows over the years has deliberately blurred this - even in Win3.x Program Manager the command to run an application was called 'Open'. Cute, but it doesn't help people learn the difference between documents, which are just data that can be viewed, and programs, which are instructions for your machine to perform.
You may object that things like Word macros (and their associated viruses) blur the line between files and executables. But that is another instance of the same problem: 'opening' such a document should be split into the two questions it implies: do you want to *view* the file contents? do you want to *execute* the instructions in the file?
If user interfaces and especially mail clients bothered to present this distinction to the user then a lot of the worm problems would go away. Some people would still have virus checkers, mostly companies who don't trust their employees not to execute dancing_elephants.exe. But even in those cases, it would be simple to lock down mail clients to not allow execution, as long as they bother to make a clear distinction between viewing and executing to start with. (And as long as the applications they launch, such as Word, do the same.)
One way of explaining this in non-technical language is: 'If I sent you a letter and it said "please jump off the nearest cliff" and you read it, would it do any harm to you? Why should the equivalent message sent to a computer be any different?'
I don't think most compilers would be smart enough to optimize away the checks at run time. For example, if f is declared to return a number between 10 and 20:
range_int x(11, 12); x = f();
(Here I have passed the min and max to the constructor at run time, following your example.) I really doubt that any compiler will be smart enough to see that f()'s returned value does not need further checking, even if f() uses range_int internally. Maybe if f() is inlined then some would. But certainly not across translation units.
The essential problem is that your idea leaves no way to declare things like 'f is a function which returns a value between 5 and 10'. All you can say is 'f returns a range_int' but the compiler has no idea what the range is (short of doing very cunning static analysis).
OTOH, if you did manage to implement it with templates then you could be certain of no overhead in the cases where the number is guaranteed not to overflow, because you could arrange for no code to be generated. Only in the cases where there could be overflow would there be overhead, and these cases would require an explicit range_cast() from the programmer.
Some people have defined 'typeints', a mapping between integers and types, to be able to do fun stuff with numbers in templates. And of course you can parameterize a class by an int or two. So perhaps the range_int<n, m> idea is not out of the question.
[sorry, forgot about Slashdot's brain-damaged HTML quoting system the last time I posted]
Your range_int class does the checking at run time, which is often better than nothing but does make it a lot slower than a normal int.
Better would be using templates and compile-time assertions to do the check at compile time, for example:
range_int<10, 20> a; range_int<20, 40> b; a = 15; b = 2 * a;// guaranteed to be in range, okay b = 3 * a;// error - not necessarily in range
For cases like that third assignment, an explicit conversion could be used so the programmer knows that the conversion might fail:
b = range_cast<20, 40>(3 * a);// run-time check
For these explicit casts there will be a slowdown and a possible exception thrown. But for calculations certain to be within the allowed range the code compiles down to normal integer operations.
I don't know if such a library is possible with C++, or just a template-addled fantasy.
Your range_int class does the checking at run time, which is often better than nothing but does make it a lot slower than a normal int.
Better would be using templates and compile-time assertions to do the check at compile time, for example:
range_int a; range_int b; a = 15; b = 2 * a;// guaranteed to be in range, okay b = 3 * a;// error - not necessarily in range
For cases like that third assignment, an explicit conversion could be used so the programmer knows that the conversion might fail:
b = range_cast(3 * a);// run-time check
For these explicit casts there will be a slowdown and a possible exception thrown. But for calculations certain to be within the allowed range the code compiles down to normal integer operations.
I don't know if such a library is possible with C++, or just a template-addled fantasy.
I don't get it. Why not offer web and email access via Minitel (lynx and pine, or equivalent)? It seems that FT have resisted doing this for a long time.
Numbers with a specified range is something I've always wanted in C and C++ - and about the only good thing I remember about Pascal. I imagine that although assigning a larger-range number to a smaller-range variable is illegal without an explicit cast, it ought to be okay to do the opposite, for example (excuse the lack of Ada syntax):
a : integer 100..200 b : integer 150..160 b:= 155 a:= b # okay, it will be in the range
Your example seems to suggest that the two ranges are considered completely different, as if they were different units (as 'weight' and 'height' must be). I hope there is a way to make two integer types which are of the same 'units', so they can be added and stuff, but of different ranges. Or conversely to make two types which have the same numeric range but mean different things (maybe 'age' is 0..100 and so is 'popularity_rating').
I do wonder if range-limited integers would not be possible with C++ templates and compile-time assertions, as in:
range_int<100, 200> a;
But I can't see anything in the STL or at boost.org for this.
Can you give an example of something that Ada's strong typing helps with, but C++ (or C) does not? I agree that C++'s type system could do a lot more but I'm not familiar with Ada.
Strangely, it seems to me that languages differ in the amount of bashing-other-languages they do. Perl books and articles seem particularly bad in comparing Perl to 'Java, C++ and other static-braindead languages' (a quote from one book), while I haven't so far read any C++ writings that make a point of bashing on other programming languages (with the obvious exception of interviews that specifically ask 'Dr Stroustrup, what think you of Java?').
At university I was once given an assignment to write two functions; what the functions should do was clearly specified in the assignment, and even how they should do it. (I think it was two different ways to calculate Fibonacci numbers, or something like that.)
Obviously I didn't put a comment at the top of the two functions, because what they did was exactly stated in the spec I had been given, and the names of the functions (and a comment at the top of the file) made it clear that they implemented the spec. So an extra comment was not needed. But I still got marked down for not having one.
Moral: programming assignments often aren't marked on what is the most sensible thing to do in this case, but on what would be the most sensible thing if this code were part of some imaginary 'larger project' that you know nothing about. Similar remarks apply to global variables, which can be the simplest and clearest way to do things in small programs but get awkward in other ones.
Compiling stuff will go roughly twice as fast with two processors (at least for difficult translation units, eg C++ with templates and stuff). Although in that case you could just buy two machines and use distcc / Mosix / doozer / etc etc, so I guess the question still stands. An SMP motherboard with two pricier processors and a bigger PSU is a _bit_ cheaper than two separate boxes I expect.
Minix tries to be like UNIX Seventh Edition, from the _user's_ point of view it counts as Unix - unless you're willing to say that V7 UNIX is not Unix. Of course, the kernel is very different and all the userland programs have been rewritten (though maybe not that different).
I think the difference is that in this case it is _faster_ to run IKVM inside Mono than to run a free JVM directly. I don't know whether this means that Mono and IKVM are well-written, or that free JVMs are incredibly slow, or both.
I wonder if you can invoke IKVM/Mono directly with a wrapper that looks just like 'java' or 'jre' or 'kaffe', but runs faster?
(Also: has anyone tried compiling Eclipse using gcj? Surely that would be faster than running it under Mono.)
What you suggest is done by programs like GNU Stow, I think. Although I would prefer to build an RPM package from the source code and then install that, that way you can use the standard RPM tools to manage and update packages.
But either of these solutions don't address the problem nearly as well as appdirs. We have a mechanism for grouping related files, it is called directories. Let's use it.
(Random thought: how about 'soft symlinks' which when the pointed-to file is removed are also removed themselves. Then grep could live in/programs/grep/ or whatever but be soft-symlinked to/bin/grep for compatibility.)
Hmm but if you remove/Libraries/Zlib or whatever how does it know to also remove all applications that depend on zlib - or to warn you about them and ask if you really want to go ahead?
Checking INT_MAX (or its C++ equivalent) is the better strategy because you are checking what you really need - a large enough range of values - rather than doing platform-dependent fiddling on the basis of internal representation (number of bits). Also it doesn't turn the code into boilerplate, and doesn't force you to use a typedef like INT32 when what you really want to say is 'let the compiler decide'.
Although a third option open to a 'competent coder' is to simply say this program requires a platform with large enough ints. Just as it may require a platform with at least 100Kbyte of memory available but you don't check that at compile time.
I'm not sure whether you are agreeing or disagreeing. My point is that most of the time you shouldn't know or care how many bits are in an int, only that it is enough. On platforms of days gone by this wasn't the case, but now there is no good reason.
I wouldn't advocate using long instead of int because it may not give such good performance. On some platforms long is 64 bits wide while the compiler may feel that the best general-purpose integer type is only 32 bits. On the other hand, it may be that 64 bit integers are best suited to the platform and so int may be 64 bits wide. You let the compiler decide for you, unless you have a very good reason to insist on a particular representation.
It seems to me that all they've done is replace one set of hardcoded directory names with another. Whether you have/usr/X11R6 or/Packages/XFree86 makes very little difference.
The trouble with the Unix filesystem is that it makes it hard to install and uninstall software, because the files for an application are scattered all over the place. Package managers like RPM work around this problem a bit - and indeed if you are stuck with the conventional filesystem layout then using RPM or dpkg is the best option - but there is no easy or intuitive view of the packages installed.
This leads to user interfaces and desktop environments which try to hide the filesystem from users. Windows mas 'My Documents' and all that, not giving any clue where My Documents really is on the disk; Unix desktop environments aren't usually that bad but still they don't dare to just show the root of the filesystem to the user, or even to show by default a complete view of the user's home directory (because there are 'hidden' files scattered around it like confetti).
The Mac OS X or ROX-desktop approach is better; an application is contained in its own directory, installing an application is just copying it and uninstalling is just deleting. On RISC OS (which ROX spritually inherits from) I used to arrange my applications by task, so drawing apps would be in one directory and music apps in another. Often the apps and the files they operated on would be in the same directory, but this is of course up to the user. Then there is no 'start menu' or similar layered brokeness trying to disentangle the different applications into a meaningful hierarchy - you just move apps around to where you want them. So the root directory of the hard disk would have Drawing and Music subdirectories.
I think this is the key point, BTW - if you ever find yourself building some tree-structured abstraction on top of the filesystem in an attempt to make life easier for users, you should stop and ask whether the filesytem itself couldn't handle the job better. This applies to Start Menu, My Computer, and their imitators in Unix world. It also kinda applies to the Windows registry, another case where Microsoft reinvented a new tree structure instead of using the filesytem.
Now I should say I'm not a big fan of the ROX approach *at present*. I think it is too confusing to have a mixture of conventional RPM-installed apps and application directories on the same system, and it would be better to have some smoother transition, such as being able to treat uninstalled RPM packages as application directories and double-click to run them. But if a whole distribution took the appdirs approach, it would rock.
There are questions about how to make _everything_ installable, deletable and movable just by dragging things around the filesystem. How do you handle shared libraries? What about multi-user systems where two users will want different arrangements of applications? (For that I'd say user symlinks, and yes, they should be exposed to the user as part of the GUI.)
Fair enough, I wasn't really thinking of low-level programming or raw binary message encodings. Although I think that in these cases you would have a header file defining the structures used, and then any low-level 'I require this number of bits' integer types would be confined to that header file.
I agree with documenting the int size requirements in the code, where there really are requirements. But that is not the same as 'use INT32 for everything instead of int', which is documenting that you require _exactly_ 32 bits when really what you need is something 'big enough'. Instead it would make more sense to use an int, and on a platform where 64-bit ints are the native integer type the compiler will use that. You could have a check in some global header file that 'int' is at least 32 bits wide, I think this is usually adequate and you don't need to stick INT32 in every single place you use an integer.
I will have a look at the C99 minimum-sized types you mention, they sound like a good answer to the problem.
But the point is, the size of int _should_ vary from compiler to compiler. It's bad practice to write code that requires or assumes a particular int size. Maybe back in the day of 16-bit or 18-bit systems, where there was a real chance of int overflow in many applications, you had to worry about using a type big enough. But when the choice is between 32 bits and 64 bits, best practice is usually to just say 'int' and use the native integer type of the machine.
Yes I agree you do have to worry about overflow in C and C++. But for many applications it is reasonable to assume a 32 bit int is big enough and you can just stick your fingers in your ears and go 'la, la, la'.
If people were porting to 16-bit platforms it might make sense to have an INT32 type, although I think I would prefer a compile-time assertion that the maximum integer value is at least a million or whatever high number you feel comfortable with. But it's a bit braindead to insist on INT32 and similar typedefs when you are making a loop counter and the code will run only on modern systems. You should just let the compiler pick the optimum sized int for the current platform.
Of course every language feature 'just makes it easier' in some sense, and there's nothing you can do in a high-level language that can't be done in assembler. But it will confuse people if you describe these things as 'syntactic sugar'. That's the point.
Actually I would dispute that assember is wholly a syntactic sugar for machine code - consider labels for example, there is no way to put labels in the middle of your raw machine code and have them automatically be updated to a new address when you inser some code before them.
Absolutely. C++ seems to bring out some prudish, put-clothing-on-the-table-legs attitudes in people who are somehow embarassed to use the naked language.
Sometimes you see arguments for avoiding the standard int type and defining INT32 (or more likely _MyInt32 or some other monstrosity) on the grounds of portability. Then you can have a header file which defines INT32 appropriately on various platforms. But in fact this will usually have the effect of limiting portability, because you're making your code too dependent on a particular int size. Most code should neither know nor care how long an int is, it should just use the native integer type provided by the compiler.
C suffers from the same problems to some extent but C++ is worse, probably because there are more language features to 'wrap' and some people feel that simple code is to be disallowed because it is 'not object-oriented enough'. The exact meaning of 'object-oriented' is not specified, but you get the feeling that the more ugly BiCapitalized method names it involves, the more likely it is to be OO. So for example using the built-in boolean type is not OO enough, but a new class with isFalse() and isTrue() methods will be okay. A simple enum { a, b, c } is not allowed: a class with isA(), isB() and isC() methods must be used instead (but a single method to get the value would not be OO enough).
Stroustrup's book introduces object-oriented programming techniques fairly late on, after templates. Using C++ does not mean you have to treat the language as though it were Java circa JDK1.0.
Exactly. A wordprocessor document *should* be data, in any well-designed system. But some vendors (mentioning no names) have mixed code and data together and given no way to distinguish the two.
I think there are two main classes of mail worms: those which rely on sending an attachment, and those which work by executing scripting commands directly in the mail client. The former could be avoided by making separate operations for 'open a document' and 'run a program'. (Opening an executable as a document would mean loading it into the disassembler, I guess. Or perhaps a message 'this is an executable not a document'.) The latter class of worm could be avoided by mail clients that treat messages as documents and never as executable code. Of course almost all Unix mail clients do this, so if someone sends you some Javascript in a message it will just be viewed as text.
The best hope is a user interface that clearly distinguishes between *running a program* and *opening a document*. Windows over the years has deliberately blurred this - even in Win3.x Program Manager the command to run an application was called 'Open'. Cute, but it doesn't help people learn the difference between documents, which are just data that can be viewed, and programs, which are instructions for your machine to perform.
You may object that things like Word macros (and their associated viruses) blur the line between files and executables. But that is another instance of the same problem: 'opening' such a document should be split into the two questions it implies: do you want to *view* the file contents? do you want to *execute* the instructions in the file?
If user interfaces and especially mail clients bothered to present this distinction to the user then a lot of the worm problems would go away. Some people would still have virus checkers, mostly companies who don't trust their employees not to execute dancing_elephants.exe. But even in those cases, it would be simple to lock down mail clients to not allow execution, as long as they bother to make a clear distinction between viewing and executing to start with. (And as long as the applications they launch, such as Word, do the same.)
One way of explaining this in non-technical language is: 'If I sent you a letter and it said "please jump off the nearest cliff" and you read it, would it do any harm to you? Why should the equivalent message sent to a computer be any different?'
I don't think most compilers would be smart enough to optimize away the checks at run time. For example, if f is declared to return a number between 10 and 20:
range_int x(11, 12);
x = f();
(Here I have passed the min and max to the constructor at run time, following your example.)
I really doubt that any compiler will be smart enough to see that f()'s returned value does not need further checking, even if f() uses range_int internally. Maybe if f() is inlined then some would. But certainly not across translation units.
The essential problem is that your idea leaves no way to declare things like 'f is a function which returns a value between 5 and 10'. All you can say is 'f returns a range_int' but the compiler has no idea what the range is (short of doing very cunning static analysis).
OTOH, if you did manage to implement it with templates then you could be certain of no overhead in the cases where the number is guaranteed not to overflow, because you could arrange for no code to be generated. Only in the cases where there could be overflow would there be overhead, and these cases would require an explicit range_cast() from the programmer.
Some people have defined 'typeints', a mapping between integers and types, to be able to do fun stuff with numbers in templates. And of course you can parameterize a class by an int or two. So perhaps the range_int<n, m> idea is not out of the question.
[sorry, forgot about Slashdot's brain-damaged HTML quoting system the last time I posted]
// guaranteed to be in range, okay // error - not necessarily in range
// run-time check
Your range_int class does the checking at run time, which is often better than nothing but does make it a lot slower than a normal int.
Better would be using templates and compile-time assertions to do the check at compile time, for example:
range_int<10, 20> a;
range_int<20, 40> b;
a = 15;
b = 2 * a;
b = 3 * a;
For cases like that third assignment, an explicit conversion could be used so the programmer knows that the conversion might fail:
b = range_cast<20, 40>(3 * a);
For these explicit casts there will be a slowdown and a possible exception thrown. But for calculations certain to be within the allowed range the code compiles down to normal integer operations.
I don't know if such a library is possible with C++, or just a template-addled fantasy.
Your range_int class does the checking at run time, which is often better than nothing but does make it a lot slower than a normal int.
// guaranteed to be in range, okay // error - not necessarily in range
// run-time check
Better would be using templates and compile-time assertions to do the check at compile time, for example:
range_int a;
range_int b;
a = 15;
b = 2 * a;
b = 3 * a;
For cases like that third assignment, an explicit conversion could be used so the programmer knows that the conversion might fail:
b = range_cast(3 * a);
For these explicit casts there will be a slowdown and a possible exception thrown. But for calculations certain to be within the allowed range the code compiles down to normal integer operations.
I don't know if such a library is possible with C++, or just a template-addled fantasy.
I don't get it. Why not offer web and email access via Minitel (lynx and pine, or equivalent)? It seems that FT have resisted doing this for a long time.
Numbers with a specified range is something I've always wanted in C and C++ - and about the only good thing I remember about Pascal. I imagine that although assigning a larger-range number to a smaller-range variable is illegal without an explicit cast, it ought to be okay to do the opposite, for example (excuse the lack of Ada syntax):
:= 155 := b # okay, it will be in the range
a : integer 100..200
b : integer 150..160
b
a
Your example seems to suggest that the two ranges are considered completely different, as if they were different units (as 'weight' and 'height' must be). I hope there is a way to make two integer types which are of the same 'units', so they can be added and stuff, but of different ranges. Or conversely to make two types which have the same numeric range but mean different things (maybe 'age' is 0..100 and so is 'popularity_rating').
I do wonder if range-limited integers would not be possible with C++ templates and compile-time assertions, as in:
range_int<100, 200> a;
But I can't see anything in the STL or at boost.org for this.
Can you give an example of something that Ada's strong typing helps with, but C++ (or C) does not? I agree that C++'s type system could do a lot more but I'm not familiar with Ada.
Strangely, it seems to me that languages differ in the amount of bashing-other-languages they do. Perl books and articles seem particularly bad in comparing Perl to 'Java, C++ and other static-braindead languages' (a quote from one book), while I haven't so far read any C++ writings that make a point of bashing on other programming languages (with the obvious exception of interviews that specifically ask 'Dr Stroustrup, what think you of Java?').
At university I was once given an assignment to write two functions; what the functions should do was clearly specified in the assignment, and even how they should do it. (I think it was two different ways to calculate Fibonacci numbers, or something like that.)
Obviously I didn't put a comment at the top of the two functions, because what they did was exactly stated in the spec I had been given, and the names of the functions (and a comment at the top of the file) made it clear that they implemented the spec. So an extra comment was not needed. But I still got marked down for not having one.
Moral: programming assignments often aren't marked on what is the most sensible thing to do in this case, but on what would be the most sensible thing if this code were part of some imaginary 'larger project' that you know nothing about. Similar remarks apply to global variables, which can be the simplest and clearest way to do things in small programs but get awkward in other ones.
Some British newspapers have a superstition about using the % sign, they always write 'per cent' or 'pc'. No idea why.
Compiling stuff will go roughly twice as fast with two processors (at least for difficult translation units, eg C++ with templates and stuff). Although in that case you could just buy two machines and use distcc / Mosix / doozer / etc etc, so I guess the question still stands. An SMP motherboard with two pricier processors and a bigger PSU is a _bit_ cheaper than two separate boxes I expect.
Minix tries to be like UNIX Seventh Edition, from the _user's_ point of view it counts as Unix - unless you're willing to say that V7 UNIX is not Unix. Of course, the kernel is very different and all the userland programs have been rewritten (though maybe not that different).
I think the difference is that in this case it is _faster_ to run IKVM inside Mono than to run a free JVM directly. I don't know whether this means that Mono and IKVM are well-written, or that free JVMs are incredibly slow, or both.
I wonder if you can invoke IKVM/Mono directly with a wrapper that looks just like 'java' or 'jre' or 'kaffe', but runs faster?
(Also: has anyone tried compiling Eclipse using gcj? Surely that would be faster than running it under Mono.)
What you suggest is done by programs like GNU Stow, I think. Although I would prefer to build an RPM package from the source code and then install that, that way you can use the standard RPM tools to manage and update packages.
/programs/grep/ or whatever but be soft-symlinked to /bin/grep for compatibility.)
But either of these solutions don't address the problem nearly as well as appdirs. We have a mechanism for grouping related files, it is called directories. Let's use it.
(Random thought: how about 'soft symlinks' which when the pointed-to file is removed are also removed themselves. Then grep could live in
Hmm but if you remove /Libraries/Zlib or whatever how does it know to also remove all applications that depend on zlib - or to warn you about them and ask if you really want to go ahead?
Checking INT_MAX (or its C++ equivalent) is the better strategy because you are checking what you really need - a large enough range of values - rather than doing platform-dependent fiddling on the basis of internal representation (number of bits). Also it doesn't turn the code into boilerplate, and doesn't force you to use a typedef like INT32 when what you really want to say is 'let the compiler decide'.
Although a third option open to a 'competent coder' is to simply say this program requires a platform with large enough ints. Just as it may require a platform with at least 100Kbyte of memory available but you don't check that at compile time.
I'm not sure whether you are agreeing or disagreeing. My point is that most of the time you shouldn't know or care how many bits are in an int, only that it is enough. On platforms of days gone by this wasn't the case, but now there is no good reason.
I wouldn't advocate using long instead of int because it may not give such good performance. On some platforms long is 64 bits wide while the compiler may feel that the best general-purpose integer type is only 32 bits. On the other hand, it may be that 64 bit integers are best suited to the platform and so int may be 64 bits wide. You let the compiler decide for you, unless you have a very good reason to insist on a particular representation.
If example.com has a public key which is widely known, they might as well just use that to sign all outgoing mail to start with.
It seems to me that all they've done is replace one set of hardcoded directory names with another. Whether you have /usr/X11R6 or /Packages/XFree86 makes very little difference.
The trouble with the Unix filesystem is that it makes it hard to install and uninstall software, because the files for an application are scattered all over the place. Package managers like RPM work around this problem a bit - and indeed if you are stuck with the conventional filesystem layout then using RPM or dpkg is the best option - but there is no easy or intuitive view of the packages installed.
This leads to user interfaces and desktop environments which try to hide the filesystem from users. Windows mas 'My Documents' and all that, not giving any clue where My Documents really is on the disk; Unix desktop environments aren't usually that bad but still they don't dare to just show the root of the filesystem to the user, or even to show by default a complete view of the user's home directory (because there are 'hidden' files scattered around it like confetti).
The Mac OS X or ROX-desktop approach is better; an application is contained in its own directory, installing an application is just copying it and uninstalling is just deleting. On RISC OS (which ROX spritually inherits from) I used to arrange my applications by task, so drawing apps would be in one directory and music apps in another. Often the apps and the files they operated on would be in the same directory, but this is of course up to the user. Then there is no 'start menu' or similar layered brokeness trying to disentangle the different applications into a meaningful hierarchy - you just move apps around to where you want them. So the root directory of the hard disk would have Drawing and Music subdirectories.
I think this is the key point, BTW - if you ever find yourself building some tree-structured abstraction on top of the filesystem in an attempt to make life easier for users, you should stop and ask whether the filesytem itself couldn't handle the job better. This applies to Start Menu, My Computer, and their imitators in Unix world. It also kinda applies to the Windows registry, another case where Microsoft reinvented a new tree structure instead of using the filesytem.
Now I should say I'm not a big fan of the ROX approach *at present*. I think it is too confusing to have a mixture of conventional RPM-installed apps and application directories on the same system, and it would be better to have some smoother transition, such as being able to treat uninstalled RPM packages as application directories and double-click to run them. But if a whole distribution took the appdirs approach, it would rock.
There are questions about how to make _everything_ installable, deletable and movable just by dragging things around the filesystem. How do you handle shared libraries? What about multi-user systems where two users will want different arrangements of applications? (For that I'd say user symlinks, and yes, they should be exposed to the user as part of the GUI.)
Fair enough, I wasn't really thinking of low-level programming or raw binary message encodings. Although I think that in these cases you would have a header file defining the structures used, and then any low-level 'I require this number of bits' integer types would be confined to that header file.
I agree with documenting the int size requirements in the code, where there really are requirements. But that is not the same as 'use INT32 for everything instead of int', which is documenting that you require _exactly_ 32 bits when really what you need is something 'big enough'. Instead it would make more sense to use an int, and on a platform where 64-bit ints are the native integer type the compiler will use that. You could have a check in some global header file that 'int' is at least 32 bits wide, I think this is usually adequate and you don't need to stick INT32 in every single place you use an integer.
I will have a look at the C99 minimum-sized types you mention, they sound like a good answer to the problem.
But the point is, the size of int _should_ vary from compiler to compiler. It's bad practice to write code that requires or assumes a particular int size. Maybe back in the day of 16-bit or 18-bit systems, where there was a real chance of int overflow in many applications, you had to worry about using a type big enough. But when the choice is between 32 bits and 64 bits, best practice is usually to just say 'int' and use the native integer type of the machine.
Yes I agree you do have to worry about overflow in C and C++. But for many applications it is reasonable to assume a 32 bit int is big enough and you can just stick your fingers in your ears and go 'la, la, la'.
If people were porting to 16-bit platforms it might make sense to have an INT32 type, although I think I would prefer a compile-time assertion that the maximum integer value is at least a million or whatever high number you feel comfortable with. But it's a bit braindead to insist on INT32 and similar typedefs when you are making a loop counter and the code will run only on modern systems. You should just let the compiler pick the optimum sized int for the current platform.
Of course every language feature 'just makes it easier' in some sense, and there's nothing you can do in a high-level language that can't be done in assembler. But it will confuse people if you describe these things as 'syntactic sugar'. That's the point.
Actually I would dispute that assember is wholly a syntactic sugar for machine code - consider labels for example, there is no way to put labels in the middle of your raw machine code and have them automatically be updated to a new address when you inser some code before them.
Absolutely. C++ seems to bring out some prudish, put-clothing-on-the-table-legs attitudes in people who are somehow embarassed to use the naked language.
Sometimes you see arguments for avoiding the standard int type and defining INT32 (or more likely _MyInt32 or some other monstrosity) on the grounds of portability. Then you can have a header file which defines INT32 appropriately on various platforms. But in fact this will usually have the effect of limiting portability, because you're making your code too dependent on a particular int size. Most code should neither know nor care how long an int is, it should just use the native integer type provided by the compiler.
C suffers from the same problems to some extent but C++ is worse, probably because there are more language features to 'wrap' and some people feel that simple code is to be disallowed because it is 'not object-oriented enough'. The exact meaning of 'object-oriented' is not specified, but you get the feeling that the more ugly BiCapitalized method names it involves, the more likely it is to be OO. So for example using the built-in boolean type is not OO enough, but a new class with isFalse() and isTrue() methods will be okay. A simple enum { a, b, c } is not allowed: a class with isA(), isB() and isC() methods must be used instead (but a single method to get the value would not be OO enough).
Stroustrup's book introduces object-oriented programming techniques fairly late on, after templates. Using C++ does not mean you have to treat the language as though it were Java circa JDK1.0.