[erlang-questions] Package Support/Use
Robert Virding
robert.virding@REDACTED
Tue Nov 7 09:03:20 CET 2006
All I can say is that I completely agree with Richard here.
And that I have NEVER EVER written a file handling sequence in a serious
application as simply as your test case, it's always more complex.
Robert
Richard A. O'Keefe wrote:
> Mats Cronqvist <mats.cronqvist@REDACTED> wrote:
> as a really dumb example, consider three functions open(Filename),
> read(FileDescriptor), and process_data(Data) that can either fail or return
> useful data. in C you'd do something like this;
>
> if ( ( fd = open(name)) == NULL ) return -1;
> if ( read(fd,&data) == -1 ) return -2;
> if ( process_data(&data,&pd) == -1 ) return -3;
> return 0;
>
> That's pretty unforgivable C: nowhere does it close the file,
> and file descriptors are a resource in fairly short supply.
> (And of course open has either 2 or 3 arguments, and read has 3.)
> (And of course there are four possible outcomes for
> read(fd, sizeof data, &data)
> : result == sizeof data => success
> : result < sizeof data && result > 0 => partial read;
> if you are reading a known structure from a disc file
> it's probably a bad case, if you are reading from a terminal
> or a tape drive this can be expected on practically every read
> : result == 0 => normal end of file
> : result < 0 => some exceptional problem
>
> in Traditional Erlang something like this;
>
> {ok,FD} = open(Name),
> {ok,Data} = read(FD),
> {ok,PD} = process_data(Data),
>
> Again, that is pretty unforgivable Erlang: if open/1 creates a resource
> which will not be automatically freed. As has been pointed out on this
> list before, just define
>
> ok({ok,X}) -> X;
> ok(Error) -> signal some kind of error.
>
> and your Traditional Erlang can become
>
> ok(process_data(ok(read(ok(open(Name))))))
>
> in BettErl (tm);
>
> process_data(read(open(Name))),
>
> TradErl is more verbose and binds worthless intermediate variables.
>
> Verbose, yes, a little bit. But it certainly doesn't REQUIRE
> you to "bind worthless intermediate variables", that's a straw man.
> Traditional Erlang, with the ok/1 function, gives you the CHOICE
> of looking at the error result or not, and if you choose not to,
> there are NO intermediate variables unless you want them.
>
> TradErl has poor error reporting.
>
> it will either succeed or fail with "badmatch". not very helpful.
>
> Again, this is only because the example is a straw man. With the
> ok/1 function, you DON'T 'fail with "badmatch"', you get the full
> information that the function returned. So no, The "TradErl" approach
> is IN NO WAY INFERIOR with regard to error reporting.
>
> the BettErl function will either succeed or throw useful stuff
> like {couldnt_open,Name} or {read_failure,enoent}, because that's how
> functions are written in BettErl;
>
> And the Traditional Erlang version with the ok/1 function does exactly the
> same thing.
>
> so, to answer your question, tagged tuples encourages verbose
> code with poor error reporting. in short, bad style. IMO.
>
> Nope. All you have demonstrated is that bad code *can* be written in
> the traditional style, not that it *must* be.
>
> mats
>
> p.s. i'm aware there are some oopses in the meta-code (e.g.
> memory leaks). but i don't think that has any bearing on my
> conclusion.
>
> It has a major bearing on your conclusion, which was an argument about
> "bad style". A style that encourages leaks can hardly be called a good
> style, now can it? The score sheet now looks like this:
>
> Traditional Throw-happy
>
> More verbose A little no
> Worse error reporting no no
> Encourages leaks no yes
>
> The real issue is how exceptional the exceptional condition is and
> whether it is likely that the caller can do anything in an error
> case other than pass it on.
>
> A regular expression not matching is not exceptional.
> A regular expression having bad syntax IS exceptional.
> Reaching the end of a file *between* characters is not exceptional.
> Reaching the end of a file *within* the UTF-8 byte sequence for a
> character IS exceptional.
>
> For me in the open/read/process example, the really important thing is
>
> - if the file cannot be opened,
> is there likely to be anything the immediate caller can do about it?
> (Probably not: good case for an exception.)
>
> - if the read fails, is there anything the caller can do about it?
> A negative result from read(2) counts as exceptional; there is
> probably nothing the program can do about it (except when errno
> is EAGAIN, of course).
> There is something the caller MUST do, and that is close the file.
>
> EAGAIN is a strange special case here; in a language which supports
> lightweight processes we wouldn't need anything like that, so I
> don't want to use it in an argument either wey.
>
> EINTR is nasty. I do not believe I have ever seen a C program that
> handles it correctly, and I'm not only not sure what "correctly"
> would mean, to the extent that I think I know, I don't really
> believe it's POSSIBLE to handle correctly. Again, if it were
> Erlang all the way down, I don't believe cases like that would exist.
>
> - if process_data fails, is there anything the caller can do about it?
> Probably not, but does the process_data/1 function know where the
> problem should be logged?
>
> What does the code *really* look like in these two cases?
>
> % tagged results
>
> Channel = ok(open(Name)),
> Outcome = read(Channel),
> close(Channel),
> case Outcome
> of {ok,Data} -> ok(process_data(Data))
> ; _ -> ok(Outcome)
> end
>
> % exceptions
>
> Channel = open(Name),
> try
> Data = read(Channel),
> after
> close(Channel)
> end,
> process_data(Data)
>
> Funny how the difference becomes less clear-cut when you make the
> example more realistic, isn't it?
>
> Any rate, as the person who designed and implemented exception handling
> in Quintus Prolog and single-handedly installed exception reporting
> throughout the entire QP system and library, I am not opposed to exceptions
> as such. What I am opposed to is designing in the use of exceptions
> without *thinking* about them, and specifically without thinking about
> whether a particular outcome really is exceptional or should be handled
> as part of normal control flow. One way to think about it is this:
>
> if this outcome occurs, would I be happy for the entire calling
> process to drop dead (with a suitable error report)?
>
> If the answer is "yes", then an exception is probably the right thing.
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://www.erlang.org/mailman/listinfo/erlang-questions
>
More information about the erlang-questions
mailing list