Pascal vs C
-
- Member
- Posts: 1146
- Joined: Sat Mar 01, 2014 2:59 pm
Re: Pascal vs C
Funny how everyone missed my new big point of the functions/procedures thing in Pascal. In my opinion it is far more elegant to abstract something than to break it down into subtypes to the point where the relationship between then is lost - that's how functions and procedures are in Pascal, where a subroutine has to be given a different name just because it happens to need to return a value e.g. an error code.
In C, "int open_file(char *filename);" and "void close_file(int file_descriptor);" can be both referred to as "procedures" to handle files or "functions" to handle files - the terms are interchangable. The code is consistent and the documentation can be consistent as well.
In Pascal, one would have to be "Function open_file(filename:Char):Integer" (might have the syntax slightly wrong there, but the important part is the "Function" keyword) and the other would be "Procedure close_file(file_descriptor:Integer)". So while these are both logically in the same category, as subroutines to handle files, the code and the documentation are both forced to be inconsistent not because of the meaning of the functions but simply because one needs to return a file descriptor and the other one doesn't.
Another thing that results from this, too, is that in C the return value of a function can be dumped, whereas in Pascal a "function" is required to have somewhere to return its value, meaning something like some of the C standard library functions (such as "strcpy" which returns the destination pointer as a return value of the function - probably to allow one to write "new_string = strcpy(malloc(strlen(old_string) + 1), old_string);" which is very useful, by the way) would be really painful to use or something which returns an error code which isn't really needed while we're just getting the basics written (we'll add the error handlers later).
To me these are both serious flaws.
In C, "int open_file(char *filename);" and "void close_file(int file_descriptor);" can be both referred to as "procedures" to handle files or "functions" to handle files - the terms are interchangable. The code is consistent and the documentation can be consistent as well.
In Pascal, one would have to be "Function open_file(filename:Char):Integer" (might have the syntax slightly wrong there, but the important part is the "Function" keyword) and the other would be "Procedure close_file(file_descriptor:Integer)". So while these are both logically in the same category, as subroutines to handle files, the code and the documentation are both forced to be inconsistent not because of the meaning of the functions but simply because one needs to return a file descriptor and the other one doesn't.
Another thing that results from this, too, is that in C the return value of a function can be dumped, whereas in Pascal a "function" is required to have somewhere to return its value, meaning something like some of the C standard library functions (such as "strcpy" which returns the destination pointer as a return value of the function - probably to allow one to write "new_string = strcpy(malloc(strlen(old_string) + 1), old_string);" which is very useful, by the way) would be really painful to use or something which returns an error code which isn't really needed while we're just getting the basics written (we'll add the error handlers later).
To me these are both serious flaws.
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
- Kazinsal
- Member
- Posts: 559
- Joined: Wed Jul 13, 2011 7:38 pm
- Libera.chat IRC: Kazinsal
- Location: Vancouver
- Contact:
Re: Pascal vs C
Also, a point re: pascal being "antiquated": If Pascal is antiquated, so is C; both were created around 1968-1970.
-
- Member
- Posts: 1146
- Joined: Sat Mar 01, 2014 2:59 pm
Re: Pascal vs C
Yeah but C has been kept up to date. Pascal has had a few attempts at being updated, none of which really flow on from the original language in the same way that C has been slowly built up and had new features integrated in an elegant way.Kazinsal wrote:Also, a point re: pascal being "antiquated": If Pascal is antiquated, so is C; both were created around 1968-1970.
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
PascalABC.NET :)
For those desperately wanting a bunch of features from other languages and not wanting to leave Pascal there's little-known PascalABC.NET.
Documentation seems to be in Russian only, so, I'll try to summarize some features you don't find in Pascal circa Turbo Pascal (extracted from these slides):
Documentation seems to be in Russian only, so, I'll try to summarize some features you don't find in Pascal circa Turbo Pascal (extracted from these slides):
- Variable definitions anywhere between begin and end as in C99/C++
- Variable initialization at the place of definition as in C/C++
- Variable definition in for as in C99/C++
- Type deduction from initializers similar to auto in C++11, also short syntax for definition+initialization of records from initializers (types deduced, names are automatic, e.g. Item1, Item2, etc akin to C++ make_pair)
- Lambda functions and short function definition syntax as in functional languages and one-liner lambda functions of Python
- BigInteger
- Dynamic arrays
- Sets of any type
- Arbitrary length strings
- Procedure/function variables as function pointers in C/C++
- Operators += and *= as in C/C++
- switch/case on strings, not just on integers
- ranges instead of loops as in Python
- Lists, stacks, dict(ionary)s
- LINK/select/where
- foreach on lines of text file as in Perl
- Write/WriteLn printing aggregate types like arrays, records and sets
- Library extensions
- .NET
- OpenMP
- etc
Re: Pascal vs C
Huh?onlyonemac wrote:Another thing that results from this, too, is that in C the return value of a function can be dumped, whereas in Pascal a "function" is required to have somewhere to return its value
The only difference i see is that in C the return statement is a result+exit combined, while in pascal it's two separate pieces.
Which is actually more useful for return codes, since in C you would have to define additional variable for it, adding a whole extra line.
Code: Select all
function decode_error(w:word):dword;
begin
result:=0;
if (w and $01)<>0 then result:=result or ERR_RUN;
if (w and $02)<>0 then result:=result or ERR_HCRESET;
if (w and $04)<>0 then result:=result or ERR_GRESET;
if (w and $08)<>0 then result:=result or ERR_EGSM;
end;
Code: Select all
uint32 decode_error(uint16 w)
{
uint32 res=0;
if (w & 0x01) res|=ERR_RUN;
if (w & 0x02) res|=ERR_HCRESET;
if (w & 0x04) res|=ERR_GRESET;
if (w & 0x08) res|=ERR_EGSM;
return res;
}
I don't get how is it different from void sub(); and int sub(); - you use different words as well.onlyonemac wrote:In Pascal, one would have to be "Function open_file(filename:Char):Integer" (might have the syntax slightly wrong there, but the important part is the "Function" keyword) and the other would be "Procedure close_file(file_descriptor:Integer)". So while these are both logically in the same category, as subroutines to handle files, the code and the documentation are both forced to be inconsistent not because of the meaning of the functions but simply because one needs to return a file descriptor and the other one doesn't.
In documentation, both functions and procedures are subroutines, for example.
I don't get what the inconsistency is.
Re: Pascal vs C
You're writing a Pascal compiler? Nice.Artlav wrote:Totally agree. I miss them quite often, and my own compiler is not up to speed yet...
To be fair, though, that would probably the kind of syntax extension that the FPC developers would be likely to accept for the native FPC modes if someone provided a patch.+1Kevin wrote:arrays need to be declared with their size instead of deriving it from the initialiser list
Maybe they actually improved it? I haven't updated my cross compiler from 2.4.x yet.Hm? Never had that problem.Kevin wrote:The other one is that the compiler isn't really meant for making changes to or even writing your own system unit. If a compilerproc is missing or has the wrong interface, you usually get a fatal internal error with a number and no useful message. Next thing is grepping the compiler source for the number and checking what was really missing. That's not quite how I'd like the error handling to be.
Won't it just fail to compile with "fpc_so_and_so not found" error?
Because it's actually a minor detail. In C, you replace int with void; in Pascal, you replace function with procedure. There needs to be a way to say that there is no return value and I wouldn't call one or the other inherently better.onlyonemac wrote:Funny how everyone missed my new big point of the functions/procedures thing in Pascal.
C avoids the procedure keyword, but introduces a void type instead, which is a rather strange type and comes with more inconsistencies. First of all, most people don't even think you can declare void variables at all (and in fact some got mad at me and told me it doesn't make any sense when I said that "extern const void" is the correct type for a symboll declared in the linker script). That's not quite correct, but there is no way to define a void variable or to have a void literal. This results in special syntax for void functions: Because you'll have a hard time finding anything void that you could return, "return" changes its syntax to work without a return value. And at the end of the function, it can even be left out. If this isn't inconsistent, what would be? (It's convenient, though, so I don't mind...)
You also have functions that are declared to take a void argument (which is the only way to declare a function without arguments), but then they work without being passed anything. In fact, it's even an error if you're bold enough to take the prototype literal and pass something "extern const void"!
For all I know, this is not true, at least not in modern Pascal dialects.Another thing that results from this, too, is that in C the return value of a function can be dumped, whereas in Pascal a "function" is required to have somewhere to return its value
Actually, to me modern Pascal dialects like ObjFPC fit very nicely into the original language. C appears to have had the larger changes, where even basic parts of the syntax have been deprecated (but are still supported by current compilers): Think of K&R style function declarations, including functions with no specified argument list and/or return type, implicit function declarations...onlyonemac wrote:Yeah but C has been kept up to date. Pascal has had a few attempts at being updated, none of which really flow on from the original language in the same way that C has been slowly built up and had new features integrated in an elegant way.
Actually, FPC gives you the choice. It supports the short exit(0); syntax, which I use most times. But there are still cases, as you mention, where the old Pascal syntax is more convenient and I'm happy to use it in those cases.Artlav wrote:The only difference i see is that in C the return statement is a result+exit combined, while in pascal it's two separate pieces.
-
- Member
- Posts: 1146
- Joined: Sat Mar 01, 2014 2:59 pm
Re: Pascal vs C
In C, the following is valid:Artlav wrote:Huh?onlyonemac wrote:Another thing that results from this, too, is that in C the return value of a function can be dumped, whereas in Pascal a "function" is required to have somewhere to return its value
Code: Select all
int test_function()
{
return 0;
}
int main(int argc, char *argv[])
{
test_function();
exit(0);
}
Code: Select all
function test_function();
begin
test_function := 0;
end
begin
(* lol I have no idea how to do an "int main" in Pascal *)
test_function();
exit(0);
end.
I was under the impression that to specify a return value you have to write "<name_of_function> := value;" not "result := value;" - another inconsistency of the language.Artlav wrote:Code: Select all
function decode_error(w:word):dword; begin result:=0; if (w and $01)<>0 then result:=result or ERR_RUN; if (w and $02)<>0 then result:=result or ERR_HCRESET; if (w and $04)<>0 then result:=result or ERR_GRESET; if (w and $08)<>0 then result:=result or ERR_EGSM; end;
The inconsistency is simply that in C we can call a "procedure" (which conceptually does not return a value) a "function with return value of type void". It is not an error to place a "return" statement in a rpocedure in C, as long as the return value is of type void. "Void" is furthermore an important concept, because it also allows one to declare arbitrary blocks of memory and pointers to those blocks without having to make any untyped blocks of memory arrays of unsighed char.Artlav wrote:I don't get how is it different from void sub(); and int sub(); - you use different words as well.onlyonemac wrote:In Pascal, one would have to be "Function open_file(filename:Char):Integer" (might have the syntax slightly wrong there, but the important part is the "Function" keyword) and the other would be "Procedure close_file(file_descriptor:Integer)". So while these are both logically in the same category, as subroutines to handle files, the code and the documentation are both forced to be inconsistent not because of the meaning of the functions but simply because one needs to return a file descriptor and the other one doesn't.
In documentation, both functions and procedures are subroutines, for example.
I don't get what the inconsistency is.
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
-
- Member
- Posts: 1146
- Joined: Sat Mar 01, 2014 2:59 pm
Re: Pascal vs C
No, you're wrong. In C a subroutine *always* has a return value, but if there is no actual "value" to return then we say that the return value is of type void (which basically means, a variable/value type that cannot hold anything).Kevin wrote:Because it's actually a minor detail. In C, you replace int with void; in Pascal, you replace function with procedure. There needs to be a way to say that there is no return value and I wouldn't call one or the other inherently better.
It doesn't matter what most people think, we're talking about the languages themselves, assuming that a programmer is fluent in his language of choice. People's knowledge of a language has nothing to do with the capabilities of that language itself.Kevin wrote:First of all, most people don't even think you can declare void variables at all (and in fact some got mad at me and told me it doesn't make any sense when I said that "extern const void" is the correct type for a symboll declared in the linker script).
I'm not sure what you're referring to. I assume you're referring to the old prototype syntax of "int get_last_error(void);" to specify that the function does not take any arguments, but that is an old syntax that I haven't seen in anything since the 90s. These days, if a function takes no argumetns then you just write it as such: "int get_last_error();"; if the function takes a void argument then you write it as such "int get_last_error(void useless_argument);". A void argument and no argument are not the same thing, just as a void return value is not the same as having no return value (the latter of which cannot be done in C).Kevin wrote:You also have functions that are declared to take a void argument (which is the only way to declare a function without arguments), but then they work without being passed anything. In fact, it's even an error if you're bold enough to take the prototype literal and pass something "extern const void"!
Case in point, see below:onlyonemac wrote:Yeah but C has been kept up to date. Pascal has had a few attempts at being updated, none of which really flow on from the original language in the same way that C has been slowly built up and had new features integrated in an elegant way.
Whoa, super cool!!! Now we have a whole TWO DIFFERENT WAYS of returning from a function!Kevin wrote:Actually, FPC gives you the choice. It supports the short exit(0); syntax, which I use most times. But there are still cases, as you mention, where the old Pascal syntax is more convenient and I'm happy to use it in those cases.
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
Re: Pascal vs C
It doesn't.onlyonemac wrote:and the line "test_function();" has to read "some_variable := test_function();".
Just calling a function without assigning it's result to anything like your example did is perfectly fine, and was so since the original pascal, AFAIK.
Would have been awful otherwise, i agree.
You did it right, actually.onlyonemac wrote:lol I have no idea how to do an "int main" in Pascal
Both are correct these days. The function_name method is the older way, which got deprecated since it makes it difficult to rename functions.onlyonemac wrote:I was under the impression that to specify a return value you have to write "<name_of_function> := value;" not "result := value;" - another inconsistency of the language.
I don't see how it is less inconsistent.onlyonemac wrote:The inconsistency is simply that in C we can call a "procedure" (which conceptually does not return a value) a "function with return value of type void".
"A function without a return type is called a procedure" on one hand, "a procedure is called a function with a void return type" on the other hand.
Same thing, different approach angle.
Re: Pascal vs C
ANSI C and C99:onlyonemac wrote:It is not an error to place a "return" statement in a rpocedure in C, as long as the return value is of type void.
Some compilers, however, allow code like this:A return statement with an expression shall not appear in a function whose return type is void.
Code: Select all
void a(void) {}
void b(void) { return a(); }
Re: Pascal vs C
I assume that you agree with all I said about C when you didn't quote that part? It would have been good style to be explicit about that.
Interestingly, despite the standard forbidding it, gcc seems to accept an expression of type void for return types (but as I mentioned, passing a void value for an empty argument list (declared with void) doesn't work).
"int get_last_error()" is the old deprecated syntax. It doesn't mean that the function doesn't get any arguments, but that the argument list is unspecified. You can call it with any arguments. Quoting the standard: "The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature." (C11, 6.11.6)
"int get_last_error(void)" is the correct current syntax. It's somewhat inconsistent because passing a void value isn't actually allowed, whereas a function declared "int get_last_error(int)" takes an int argument. This is an exception, but clearly defined. ("The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters." - C11, 6.7.6.3)
If you have a named parameter of type void - like your "int get_last_error(void useless_argument)" - the exception doesn't apply any more (yay for consistency!) and that will actually result in a compiler error. (C11, 6.9.1, paragraph 5 explicitly forbids using an identifier for a single void argument.)
And the K&R syntax I was talking about is something like the following (really old, but it's an example taken from the current standard!):
You may say so, but it's still not like any other return value. You get special syntax instead where return is only allowed without a value: "A return statement with an expression shall not appear in a function whose return type is void. A return statement without an expression shall only appear in a function whose return type is void." (C11, 6.8.6.4). This is an exception, no matter what you say about return values.onlyonemac wrote:In C a subroutine *always* has a return value, but if there is no actual "value" to return then we say that the return value is of type void (which basically means, a variable/value type that cannot hold anything).
Interestingly, despite the standard forbidding it, gcc seems to accept an expression of type void for return types (but as I mentioned, passing a void value for an empty argument list (declared with void) doesn't work).
It's good that we agree on that, because you seem to be fluent neither in C nor in Pascal, see below:It doesn't matter what most people think, we're talking about the languages themselves, assuming that a programmer is fluent in his language of choice. People's knowledge of a language has nothing to do with the capabilities of that language itself.
Please, please, please, before you engage in hair splitting, go do your homework and learn C.I'm not sure what you're referring to. I assume you're referring to the old prototype syntax of "int get_last_error(void);" to specify that the function does not take any arguments, but that is an old syntax that I haven't seen in anything since the 90s. These days, if a function takes no argumetns then you just write it as such: "int get_last_error();"; if the function takes a void argument then you write it as such "int get_last_error(void useless_argument);". A void argument and no argument are not the same thing, just as a void return value is not the same as having no return value (the latter of which cannot be done in C).
"int get_last_error()" is the old deprecated syntax. It doesn't mean that the function doesn't get any arguments, but that the argument list is unspecified. You can call it with any arguments. Quoting the standard: "The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature." (C11, 6.11.6)
"int get_last_error(void)" is the correct current syntax. It's somewhat inconsistent because passing a void value isn't actually allowed, whereas a function declared "int get_last_error(int)" takes an int argument. This is an exception, but clearly defined. ("The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters." - C11, 6.7.6.3)
If you have a named parameter of type void - like your "int get_last_error(void useless_argument)" - the exception doesn't apply any more (yay for consistency!) and that will actually result in a compiler error. (C11, 6.9.1, paragraph 5 explicitly forbids using an identifier for a single void argument.)
And the K&R syntax I was talking about is something like the following (really old, but it's an example taken from the current standard!):
Code: Select all
extern int max(a, b)
int a, b;
{
return a > b ? a : b;
}
-
- Member
- Posts: 1146
- Joined: Sat Mar 01, 2014 2:59 pm
Re: Pascal vs C
Frankly these quotes and accompanying argument threads are getting too complicated for me to keep track of with my screenreader, but nobody has yet to explain why Pascal is *better* than C. And so far the issue of "Pascal is not used anymore" has not been addressed either, and as far as I'm concerned that is still a reason alone not to use it for anything new.
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing