February 23, 2012
On Thursday, 23 February 2012 at 01:57:49 UTC, Jonathan M Davis wrote:
> The D equivalent would really be Array, not Appender.

Array!T in D is ref counted and more geared towards T being a
struct. And I had big trouble sorting it with sort!()() in D2.056,
so I made my own sort just to be able to use Array!(T).

I know that that situation will not remain forever (and I didn't
check if it was already fixed in D2.058).

> I'm not sure that it's a great idea to use Appender as a
> container - particularly when there are types
> specifically intended to be used as containers. Appender is geared specifically  towards array building (like StringBuilder in Java, except generalized for all
> arrays). If it's a container that you're looking for, then I really think that
> you should use a container.
>
> - Jonathan M Davis

If Appender supports the range interface, then it is a
container. Someone will use it that way, because in the real
world people take the things for what they are, not for
what they are named.

Appender can work with T classes well. Contains items.
It would be GC managed (as opposed to Array!T).
So it is a container. If it is not O(1) to access, it
should be said big in the ddoc though.

It is a recurrent trend in your posts, that you post just
because you have some ideallistic concern or opinion.

If we are going to get ideallistic, this is an extract
of a poem by Jorge Luis Borges (argentinian writer) that
illustrates my point:

      If (as the Greek states in the Cratilo)
      the name is the archetype of the thing,
      in the letters of rose it is the rose
      and all the Nile is in the word Nile

      Si como escribió el griego en el Crátilo,
      el nombre es arquetipo de la cosa,
      en el nombre de rosa está la rosa
      y todo el Nilo en la palabra Nilo.
      --Jorge Luis Borges

--jm











February 23, 2012
On Wednesday, February 22, 2012 20:07:37 Robert Jacques wrote:
> StringBuilder in .Net is implemented using lists and doesn't expose iteration nor indexing; why are we worrying about the indexing and container performance of D's appender?l

Because we're losing something that we currently have and which is potentially useful. Now, improving the performance of appending may outweigh that, but if we don't need to lose it, then we shouldn't.

>From the sounds of it though, we don't have much choice if we want to really
improve Appender's appending performance.

- Jonathan M Davis
February 23, 2012
On Thursday, 23 February 2012 at 02:12:20 UTC, Juan Manuel Cabo wrote:

> If we are going to get ideallistic [..]

I'm sorry. I went over the top. I apollogize.

..I won't post for a while.
This thread is almost poping a vein in my neck..

Passion can do that!
I love D. Love all your good work guys!!!

--jm



February 23, 2012
On Wednesday, 22 February 2012 at 07:30:54 UTC, H. S. Teoh wrote:
> I have an idea. What if handlers took *two* arguments, a Condition, and
> a (possibly derived) Exception object? The raise system would then match
> conditions to handlers by both the Condition type and derived Exception
> type.
> *snip*
>

The Condition approach you propose is fairly similar to what I was thinking of, as an approach to fixing Problems that occur (not necessarily exceptions). One of the fundamental problems I have with exceptions is that, despite intended to be recoverable as opposed to Errors, they are not recoverable. The operation still fails when an exception is thrown, and you have to restart all over again (even if it's something easily recoverable from). The other issue, is that exceptions are just poorly designed for multithreaded and event based applications. If you queue some work to be done, you likely won't even know if an exception is thrown. If you have a callback / event based approach, you have to do the equivalent of returning error codes (something exceptions were designed to avoid), except with passing in error codes instead. An example is .NET forcing all asynchronous operations to have a Begin____ and an End____ with the End____ rethrowing whatever problems occurred during the operation (even if they were easily solveable if the caller simply had immediate access to handle them).

The first one, is solveable with something similar to Conditions. A Problem would generally be a state issue. For example, you're writing a simple file transfer tool. The client authenticates with the server and gets a session ID. The server then starts transferring to the client, when suddenly the client loses connection for a moment (maybe they lost Wi-Fi signal, maybe someone unplugged their router momentarily, maybe they just had a bad route). With the exception based approach, the only way to notify this is to stop the entire operation, reconnect, reauthenticate, create a new session, negotiate what was being transfered, negotiate how far in the transfer completed, and other annoying things. Instead, we could register a handler to solve network problems. At the lowest level, the socket could have a handler that attempts to reconnect if any socket operations fail due to a connection error. Then, the transfer protocol could have a handler that, if the dependent socket reconnect handler is successful, notifies the server of the session key (and maybe the last packet it received) and carries on seamlessly without having to do a bunch of work. If the socket reconnect fails, the network problem handler reports a failure, and the transfer protocol handler does not get executed. If there is no transfer protocol handler, or there is one that basically says a solution is not possible, the same happens. Instead, that Problem is executed into an Exception, as the operation could not continue. (Unfortunately, unless you have a global problem handler for the entire transfer operation, this still suffers from the second issue about how those exceptions do not get carried up to the caller that starte the operation.)

The transfer approach might not be the greatest example, but it demonstrates something that (IMO) Exceptions are misused for, which affects the design of Exceptions themselves as it attempts to hammer a solution they're not great for in with them.
February 23, 2012
On 2/21/2012 2:29 PM, Ali Çehreli wrote:
> On 02/18/2012 09:09 PM, Jim Hewes wrote:
>
>  > I think of exception handling as tied to contract programming.
>
> I think your use of the word 'contract' is colliding with the contract
> programming feature. What you describe later does not match with the
> contract programming and I guess is the reason why Andrei is pointing
> out two chapters from TDPL.
>
> I will reread those chapters later today but I think Andrei is referring
> to the distinction between assert() and std.exception.enforce().
>

Thanks. I assume the objection is about the bad parameters. In design by contract, a function should not be checking the input, correct? It assumes it's correct. But I was mostly thinking of the case when the functions are more of a public API and you can't trust the input. I did mention using assert for internal functions. But I guess if you are strict, you should never check input. I just shouldn't mention design by contract at all then. :)
February 23, 2012
On Thu, Feb 23, 2012 at 04:00:04AM +0100, Juan Manuel Cabo wrote: [...]
> I'm sorry. I went over the top. I apollogize.

I apologize too, for some of the inflammatory things I said in the heat of the moment in some of my replies to this thread.


> ..I won't post for a while.
> This thread is almost poping a vein in my neck..

Heh, several times I had to stop myself from hitting Send, take a deep breath, clear my head, and go back to edit out my inflammatory remarks before posting it.


> Passion can do that!
> I love D. Love all your good work guys!!!
[...]

Me too. D is the closest to what I've always wanted in an ideal programming language. It's not perfect, and its implementation still has a ways to go, but it already far surpasses all other languages that I've looked at in terms of what I consider important in an ideal language. I'm loving it so much I just can't convince myself to go back to C++ anymore in my personal projects, except for maintenance. (At work I just grit my teeth and comfort myself that they're paying me for it, so I'll tolerate C/C++. :P)


T

-- 
Без труда не выловишь и рыбку из пруда.
February 23, 2012
On Wednesday, February 22, 2012 22:33:47 Jim Hewes wrote:
> On 2/21/2012 2:29 PM, Ali Çehreli wrote:
> > On 02/18/2012 09:09 PM, Jim Hewes wrote:
> >  > I think of exception handling as tied to contract programming.
> > 
> > I think your use of the word 'contract' is colliding with the contract programming feature. What you describe later does not match with the contract programming and I guess is the reason why Andrei is pointing out two chapters from TDPL.
> > 
> > I will reread those chapters later today but I think Andrei is referring
> > to the distinction between assert() and std.exception.enforce().
> 
> Thanks. I assume the objection is about the bad parameters. In design by contract, a function should not be checking the input, correct? It assumes it's correct. But I was mostly thinking of the case when the functions are more of a public API and you can't trust the input. I did mention using assert for internal functions. But I guess if you are strict, you should never check input. I just shouldn't mention design by contract at all then. :)

In DbC, you use assertions to verify arguments, because it's up to the caller to ensure that the arguments are valid - otherwise it's breaking the contract. So, in release mode, there are no checks, and in non-release mode, your program gets killed if the contract is violated. It's considered a bug in the code if bad arguments are passed to the function.

In defensive programming, however, you use exceptions, which is much safer, because the function will never actually execute with bad arguments, but it's slower, because it's always checking, whereas assertions are compiled out in release mode. Also, it's not necessarily a bug when you pass an invalid argument to a function using defensive programming, because throwing an failure is part of its normal behavior (and won't be compiled out in release mode) and is recoverable, unlike an AssertError. Rather, the function is merely informing the caller that it was given bad arguments and lets the caller sort it out.

DbC tends to work better with internal stuff where you control both the caller and the callee, whereas defensive programming works better with public APIs. But regardless, which is best to use depends on the situtation and what you're goals are.

- Jonathan M Davis
February 23, 2012
On Thu, Feb 23, 2012 at 02:57:43AM -0800, Jonathan M Davis wrote: [...]
> DbC tends to work better with internal stuff where you control both the caller and the callee, whereas defensive programming works better with public APIs.  But regardless, which is best to use depends on the situtation and what you're goals are.
[...]

The way I understand it, DbC is used for ensuring *program* correctness (ensure that program logic does not get itself into a bad state); defensive programming is for sanitizing *user input* (ensure that no matter what the user does, the program doesn't get into a bad state).

That's why DbC is compiled out in release mode -- the assumption is that you have thoroughly tested your program logic and verified there are no logic problems. Input sanitizing is never compiled out, because you never know what users will do, so you always have to check.

The two do somewhat overlap, of course. For example, failing to sanitize user input may eventually lead to passing invalid arguments to an internal function.


T

-- 
Only boring people get bored. -- JM
February 23, 2012
On 23 February 2012 05:09, Regan Heath <regan@netmail.co.nz> wrote:
> On Tue, 21 Feb 2012 14:19:17 -0000, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>
>> On 2/21/12 5:55 AM, Regan Heath wrote:
>>>
>>> On Sun, 19 Feb 2012 23:04:59 -0000, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>>>
>>>> On 2/19/12 4:00 PM, Nick Sabalausky wrote:
>>>
>>>
>>>>> Seriously, how is this not *already* crystal-clear? I feel as if
>>>>> every few
>>>>> weeks you're just coming up with deliberately random shit to argue so
>>>>> the
>>>>> rest of us have to waste our time spelling out the obvious in insanely
>>>>> pedantic detail.
>>>>
>>>>
>>>> It sometimes happened to me to be reach the hypothesis that my interlocutor must be some idiot. Most often I was missing something.
>>>
>>>
>>> I get the impression that you find "Devil's advocate" a useful tool for generating debate and out of the box thinking.. there is something to be said for that, but it's probably less annoying to some if you're clear about that from the beginning. :p
>>
>>
>> Where did it seem I was playing devil's advocate? Thanks.
>
>
> "Devil's Advocate" is perhaps not the right term, as you don't seem to ever argue the opposite to what you believe.  But, it occasionally seems to me that you imply ignorance on your part, in order to draw more information from other posters on exactly what they think or are proposing.  So, some get frustrated as they feel they have to explain "everything" to you (and not just you, there have been times where - for whatever reason - it seems that anything less than a description of every single minute detail results in a miss understanding - no doubt partly due to the medium in which we are communicating).
>
>
> Regan
>
> --
> Using Opera's revolutionary email client: http://www.opera.com/mail/

I think that is technically called being facetious.

--
James Miller
February 23, 2012
On Thursday, February 23, 2012 07:47:55 H. S. Teoh wrote:
> On Thu, Feb 23, 2012 at 02:57:43AM -0800, Jonathan M Davis wrote: [...]
> 
> > DbC tends to work better with internal stuff where you control both the caller and the callee, whereas defensive programming works better with public APIs.  But regardless, which is best to use depends on the situtation and what you're goals are.
> 
> [...]
> 
> The way I understand it, DbC is used for ensuring *program* correctness (ensure that program logic does not get itself into a bad state); defensive programming is for sanitizing *user input* (ensure that no matter what the user does, the program doesn't get into a bad state).
> 
> That's why DbC is compiled out in release mode -- the assumption is that you have thoroughly tested your program logic and verified there are no logic problems. Input sanitizing is never compiled out, because you never know what users will do, so you always have to check.
> 
> The two do somewhat overlap, of course. For example, failing to sanitize user input may eventually lead to passing invalid arguments to an internal function.

Exactly. But where things tend to blur is the concept of "user input." For instance, if you're using a 3rd party library, should it be asserting on the arguments that you pass it? Unless you compile it in non-release mode, it obviously won't, which could be an argument for using exceptions, but regardless of that, from the library's perspective, you're a user. If it used DbC, it would be putting assertions it in its own code to test _your_ code. And since you're a user, it arguably should use exceptions to make sure that the arguments that it gets are correct. So, it all tends to get blurry, and the best decision varies from situation to situation. It's also part of what makes the concept of assertion vs exception harder for some folks (and as nice as enforce may be it, it blurs the line even further for many people IMHO, since it then makes exceptions the same as assertions syntactically).

Arguably, the best thing would be if there was a way for the caller to indicate whether it wanted the callee to have DbC enable and possibly even indicate whether it wanted the callee to use DbC or defensive programming. But there's no way to do that in D, and I'm not sure that it could even be done with the C linking model - at least, there's no way to it without templatizing everything and giving an argument to the template indicating what you want, which obviously isn't a good solution (and won't work at all in the case of virtual functions, since they can't be templatized).

- Jonathan M Davis