Thread View: comp.lang.functional
2 messages
2 total messages
Started by Mike Goodrich
Wed, 23 Dec 1992 21:07
Completely functional program in C
Author: Mike Goodrich
Date: Wed, 23 Dec 1992 21:07
Date: Wed, 23 Dec 1992 21:07
110 lines
2727 bytes
2727 bytes
Greetings,
The following is an example of a functional program in C I wrote after
reading MaClannan's book on FP. I would like to invite comments from the FP
community. I was pleased to find that the Sun C optimizer knows about tail recursion optimization so that this program runs as fast as the conventional
C version that it is based on.
/*
* Hexdmp.c
*
* Author: Mike Goodrich (804) 864-1790 goodrich@128.155.25.38 (goodrich@lynx.larc.nasa.gov)
*
* Purpose to dump a given file to STDOUT in hex and ascii
*
* NOTE: This version was rewritten to adhere to the 'functional program' paradigm
*
* Usage: hexdmp <filename>
*
* Note: If compiling under Microsoft C must use -J to overide signed char
* default.
*/
#include <stdio.h>
#define REC_SIZE 16
static unsigned char HexTab[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f'};
void PutHexLine(), PutTextLine(), DoLine(), DumpFile();
main(argc, argv)
int argc;
char **argv;
{
unsigned char buff[REC_SIZE];
if (argc < 2) {
printf("\nUsage: hexdmp <filename>\n");
exit(0);
}
DumpFile(fopen(argv[1], "rb"), buff);
}
void
PutTextLine(NumRead, buff)
short NumRead;
unsigned char *buff;
{
switch (NumRead) {
case 0:
return;
default:
if (*buff < ' ' || *buff > '~') { /* printable ? */
printf(".");
} else {
printf("%c", *buff);
}
PutTextLine(NumRead - 1, buff + 1);
}
}
void
PutHexLine(NumRead, buff)
short NumRead;
unsigned char *buff;
{
switch (NumRead) {
case 0:
printf("\t");
return;
default:
printf("%02x ", *buff);
PutHexLine(NumRead - 1, buff + 1);
}
}
void
DoLine(NumRead, buff, count, fp)
short NumRead, count;
unsigned char *buff;
FILE *fp;
{
switch (NumRead) {
case 0:
return;
default:
printf("\n<%d>\t", count * REC_SIZE);
PutHexLine(NumRead, buff);
PutTextLine(NumRead, buff);
DoLine(fread(buff, 1, REC_SIZE, fp), buff, count + 1, fp);
}
}
void
DumpFile(fp, buff)
FILE *fp;
unsigned char *buff;
{
if (fp == NULL) {
printf("Error: cannot open input file\n");
exit(-1);
}
DoLine(fread(buff, 1, REC_SIZE, fp), buff, 0, fp);
}
Re: Completely functional program in C
Author: Fergus James HENDERSON
Date: Fri, 25 Dec 1992 18:02
Date: Fri, 25 Dec 1992 18:02
110 lines
3280 bytes
3280 bytes
goodrich@lynx.larc.nasa.gov (Mike Goodrich) writes:
>Greetings,
> The following is an example of a functional program in C I wrote after
>reading MaClannan's book on FP. I would like to invite comments from the FP
>community.
I would not describe this program as particularly "functional".
It does have a lot of tail recursion, but there is not much else that
could be called functional.
[...]
>main(argc, argv)
> int argc;
> char **argv;
>{
> unsigned char buff[REC_SIZE];
>
> if (argc < 2) {
> printf("\nUsage: hexdmp <filename>\n");
> exit(0);
> }
> DumpFile(fopen(argv[1], "rb"), buff);
>}
- exit(0) is not very functional
- failing to return a value from main() is not very functional
(not to mention that it's not very good C either ;-)
- passing uninitialized parameters (buff) is not very functional
>void
>PutTextLine(NumRead, buff)
> short NumRead;
> unsigned char *buff;
>{
> switch (NumRead) {
> case 0:
> return;
> default:
> if (*buff < ' ' || *buff > '~') { /* printable ? */
> printf(".");
> } else {
> printf("%c", *buff);
> }
> PutTextLine(NumRead - 1, buff + 1);
> }
>}
Why the switch statements? What's wrong with using if statements?
Also, purely functional programs should have declarative I/O.
Since this is impossible, the next best thing is to confine all your
I/O to the very top-level of your program, or alternately to pass
pretend state-of-the-world arguments to and from a library of declarative
I/O functions (OK, admittedly that's a bit silly in this context, but
then it's a pretty silly context ;-)
>
>void
>PutHexLine(NumRead, buff)
> short NumRead;
> unsigned char *buff;
>{
> switch (NumRead) {
> case 0:
> printf("\t");
> return;
> default:
> printf("%02x ", *buff);
> PutHexLine(NumRead - 1, buff + 1);
> }
>}
>
>void
>DoLine(NumRead, buff, count, fp)
> short NumRead, count;
> unsigned char *buff;
> FILE *fp;
>{
> switch (NumRead) {
> case 0:
> return;
> default:
> printf("\n<%d>\t", count * REC_SIZE);
> PutHexLine(NumRead, buff);
> PutTextLine(NumRead, buff);
> DoLine(fread(buff, 1, REC_SIZE, fp), buff, count + 1, fp);
> }
>}
>
>void
>DumpFile(fp, buff)
> FILE *fp;
> unsigned char *buff;
>{
> if (fp == NULL) {
> printf("Error: cannot open input file\n");
> exit(-1);
> }
> DoLine(fread(buff, 1, REC_SIZE, fp), buff, 0, fp);
>}
fread() is not a very functional function, since the buff array is
effectively passed by reference rather than by value.
--
Fergus Henderson fjh@munta.cs.mu.OZ.AU
This .signature virus is a self-referential statement that is true - but
you will only be able to consistently believe it if you copy it to your own
.signature file!
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads