[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