comp.lang.ada
 help / color / mirror / Atom feed
* Top 10 Worst C# Features
@ 2015-09-02 10:59 Stefan.Lucks
  2015-09-02 17:37 ` Álex R. Mosteo
                   ` (3 more replies)
  0 siblings, 4 replies; 31+ messages in thread
From: Stefan.Lucks @ 2015-09-02 10:59 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 2274 bytes --]

Eric Lippert from the C# design team has an interesting article on the ten 
worst features of C#. At least eight of these have been solved in Ada. Did 
Jean I. time-travel into the future and learned from the C# mistakes, when 
designing Ada?

Lean back and enjoy!

http://www.informit.com/articles/article.aspx?p=2425867


BTW, the two issues that are, to some degree, applicable to Ada are

#9 Comparison operators for your own arithmetic (e.g., for your own 
rational numbers).

In Ada, the "/="-operator is automatically the negation of "=". Which is 
great. But given "=", "<", and ">", why does one have to implement "<=" 
and ">=", as well. (Five Operators, where three would suffice.) (*)

The situation with C# is even worse. You need to define/override at least 
nine methods.

#2 Finaliz(ers) are fragile

In Ada, the finalize procedure for an object can be called more than once, 
Finalize should rather not raise an exception, ... apparently, C# 
finalzisers suffer from similar problems: "any time a finalizer runs, you 
could argue that the program either has a bug or is in a dangerous state, 
such as being shut down unexpectedly via a thread abort".

The remaining eight C# issues have been solved in Ada.



-------

(*) One might argue that two operators, e.g., "=" and "<" would suffice, 
rather than three. If neither A=B nor A<B, then A>B is obvious, isn't it?

But not all sorts of "arithmetic", where you want to take comparisons, 
have the property that either of A=B, A>B, A<B is true:

    -- Arithmetic with "special values", such as "Not a Number" for
       floating point operations. If A is NaN, then neither A=B nor A>B
       nor A<B would hold, even if B is also NaN.

    -- Another example would be sets: A<B would indicate "A is a proper
       subset of B. If, e.g., A={1} and B={2,3}, then neither A=B nor
       A<B nor A>B.

On the other hand, A <= B should never mean anything different from

   (A < B) or (A = B)!

Similarly for A >= B.

--------  I  love  the  taste  of  Cryptanalysis  in  the morning!  --------
www.uni-weimar.de/de/medien/professuren/mediensicherheit/people/stefan-lucks
----Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany----

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-02 10:59 Top 10 Worst C# Features Stefan.Lucks
@ 2015-09-02 17:37 ` Álex R. Mosteo
  2015-09-02 19:39 ` Randy Brukardt
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 31+ messages in thread
From: Álex R. Mosteo @ 2015-09-02 17:37 UTC (permalink / raw)


Stefan.Lucks@uni-weimar.de wrote:

> Eric Lippert from the C# design team has an interesting article on the ten
> worst features of C#. At least eight of these have been solved in Ada. Did
> Jean I. time-travel into the future and learned from the C# mistakes, when
> designing Ada?
> 
> Lean back and enjoy!
> 
> http://www.informit.com/articles/article.aspx?p=2425867

I chuckled at the point:

"As Benjamin Franklin (never) said, language designers who give up a little 
type safety for a little performance will discover they have neither."

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-02 10:59 Top 10 Worst C# Features Stefan.Lucks
  2015-09-02 17:37 ` Álex R. Mosteo
@ 2015-09-02 19:39 ` Randy Brukardt
  2015-09-03  8:14   ` Georg Bauhaus
  2015-09-03  8:51 ` gautier_niouzes
  2015-10-01 14:03 ` Paul Colin de Gloucester
  3 siblings, 1 reply; 31+ messages in thread
From: Randy Brukardt @ 2015-09-02 19:39 UTC (permalink / raw)



<Stefan.Lucks@uni-weimar.de> wrote in message 
news:alpine.DEB.2.20.1509021228510.5314@debian...
...
>#2 Finaliz(ers) are fragile
>
>In Ada, the finalize procedure for an object can be called more than once,
>Finalize should rather not raise an exception, ... apparently, C#
>finalzisers suffer from similar problems: "any time a finalizer runs, you
>could argue that the program either has a bug or is in a dangerous state,
>such as being shut down unexpectedly via a thread abort".

Based on the article, the situation in Ada is far less bad than the C# one. 
His description of C++ finalizers apply to Ada's as well: "[they] run 
deterministically, run on the current thread, and never run on partially 
constructed objects."
Moreover, they always run when objects are destroyed, while apparently in C# 
they don't run for explicit calls to Dispose.

Ada's issues come from two things: extremely rare cases involving exceptions 
where a finalizer might start twice, and the fact that someone can 
explicitly call it on an object. If one has control over the entire system, 
neither of these cases need happen; a program like AdaControl can enforce 
appropriate style rules to avoid problems.

If not, it's relatively easy to make Finalize callable multiple times (you 
just need a "Valid" bit in the object, which is turned off by Finalize; if 
it's off, Finalize does nothing).

Of course, Ada gets this by not supporting garbage collection on objects 
that have non-trival finalization (such an object cannot be garbage 
collected until the finalization has run, meaning they have to exist until 
they go out of scope, meaning no useful garbage collection can happen. 
Fixing that would probably introduce more problems (although if the points 
at which garbage collection could happen were appropriately limited it would 
not be a huge issue; if this issue is ever addressed in Ada, that would have 
to be the case).

In any case, Ada's situation is nothing like the asynchronous mess he 
describes for C#. It may not be perfect, but it's a heck of a lot better 
than C#.

                                                 Randy.



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-02 19:39 ` Randy Brukardt
@ 2015-09-03  8:14   ` Georg Bauhaus
  2015-09-03  9:26     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 31+ messages in thread
From: Georg Bauhaus @ 2015-09-03  8:14 UTC (permalink / raw)


On 02.09.15 21:39, Randy Brukardt wrote:
> "[they] run
> deterministically, run on the current thread, and never run on partially
> constructed objects."
> Moreover, they always run when objects are destroyed, while apparently in C#
> they don't run for explicit calls to Dispose.

Still, finalizers are an accidental bit of design. It uses just scopes
and it involves garbage. And while that's something, this very bit is
being carried to the limit, perhaps too far: if finalizers are popular,
problems pop up with corresponding frequency.

What finalization can presumably solve I'd love to see addressed
systematically, using language that attaches life cycle events to
types. Events addressable in the type's very definition, not attached
by implication, testament style, about things to happen while objects
are dying. Events becoming part of the type definition, the program
then makes the objects react to events while they are still alive and
well. Actions will no longer be some "last words" that require
additional efforts to get right.

Is it possible to produce a scheme that makes attaching "event
subprograms", say, well defined? Maybe permissions would be based
on visibility of entities referred to?

For a start, using subprograms,

    type T is ...
    for T'Some_Event use ...

or

    type T is ...
    with T'Some_Event => ...

When new attachments would be desired in deeper scope, maybe one could
use some type derived there.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-02 10:59 Top 10 Worst C# Features Stefan.Lucks
  2015-09-02 17:37 ` Álex R. Mosteo
  2015-09-02 19:39 ` Randy Brukardt
@ 2015-09-03  8:51 ` gautier_niouzes
  2015-10-01 14:03 ` Paul Colin de Gloucester
  3 siblings, 0 replies; 31+ messages in thread
From: gautier_niouzes @ 2015-09-03  8:51 UTC (permalink / raw)


Le mercredi 2 septembre 2015 13:09:47 UTC+2, Stefan...@uni-weimar.de a écrit :

> The remaining eight C# issues have been solved in Ada.

For those not fluent in both languages, it would be useful to develop these points, IMHO.
_________________________ 
Gautier's Ada programming 
http://gautiersblog.blogspot.com/search/label/Ada 
NB: follow the above link for a valid e-mail address


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-03  8:14   ` Georg Bauhaus
@ 2015-09-03  9:26     ` Dmitry A. Kazakov
  2015-09-03 11:39       ` G.B.
  0 siblings, 1 reply; 31+ messages in thread
From: Dmitry A. Kazakov @ 2015-09-03  9:26 UTC (permalink / raw)


On Thu, 3 Sep 2015 10:14:35 +0200, Georg Bauhaus wrote:

> What finalization can presumably solve I'd love to see addressed
> systematically, using language that attaches life cycle events to
> types.

What a horrific idea...

> Is it possible to produce a scheme that makes attaching "event
> subprograms", say, well defined? Maybe permissions would be based
> on visibility of entities referred to?

No.

1. Regarding types there is no any events. It must be clearly understood.
Either a type exists or it does not. Furthermore a type is immutable
throughout all its life, which is extremely important for substitutability.
An object of a type is *same* in all contexts, because the type is same.
What you propose is not typed.

2. Regarding finalization, another crucial point. Finalization is *not* an
operation. The object ceases to exist after its finalization. Therefore
exist certain composition rules of how finalization is defined upon type
operations such as aggregation, inheritance etc.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-03  9:26     ` Dmitry A. Kazakov
@ 2015-09-03 11:39       ` G.B.
  2015-09-03 12:00         ` G.B.
  2015-09-03 13:47         ` Dmitry A. Kazakov
  0 siblings, 2 replies; 31+ messages in thread
From: G.B. @ 2015-09-03 11:39 UTC (permalink / raw)


On 03.09.15 11:26, Dmitry A. Kazakov wrote:
> On Thu, 3 Sep 2015 10:14:35 +0200, Georg Bauhaus wrote:
>
>> What finalization can presumably solve I'd love to see addressed
>> systematically, using language that attaches life cycle events to
>> types.
>
> What a horrific idea...
>
>> Is it possible to produce a scheme that makes attaching "event
>> subprograms", say, well defined? Maybe permissions would be based
>> on visibility of entities referred to?
>
> No.
>
> 1. Regarding types there is no any events.

Yes. Perhaps I should first say what "event" is to name.
(The word being used in different contexts, AFAICT.)
Extensionally, an event is something that happens at some
point in the lifetime of an object, such as being passed,
or one of its operations being called (maybe for the 'Nth
time).

> Either a type exists or it does not.

Yes.

> Furthermore a type is immutable
> throughout all its life,

Yes.

> An object of a type is *same* in all contexts, because the type is same.

While an object doesn't change either identity or type,
it does changes state. This is an event, too.

> What you propose is not typed.

I think that what you might have misunderstood is not typed. :-)

> 2. Regarding finalization, another crucial point. Finalization is *not* an
> operation.

I'm not asking for finalization as an operation.
I'm asking for clearly defined hooks made for operations
(or something else) for what programmers will now put into
Finalize, since there is nothing else where to put it.


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-03 11:39       ` G.B.
@ 2015-09-03 12:00         ` G.B.
  2015-09-03 13:59           ` Dmitry A. Kazakov
  2015-09-03 19:12           ` Randy Brukardt
  2015-09-03 13:47         ` Dmitry A. Kazakov
  1 sibling, 2 replies; 31+ messages in thread
From: G.B. @ 2015-09-03 12:00 UTC (permalink / raw)


On 03.09.15 13:39, G.B. wrote:
>> An object of a type is *same* in all contexts, because the type is same.
>
> While an object doesn't change either identity or type,
> it does changes state. This is an event, too.

Seen from a different angle:
What could a type system have to offer to GUI programming?
Some kinds of "event" are as ubiquitous in GUI programming
as they are essential. Can this be made static?

AFAICT, today we have string literals identifying things
that can be called (Gtk), or we have selectors (Objective-C)
for a similar thing, etc.  A mouse click or gesture is thus
another kind of event to which programmers might want to attach
something that reacts. How would static type systems help,
knowing that trying to make them help has allegedly failed
in the past?


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-03 11:39       ` G.B.
  2015-09-03 12:00         ` G.B.
@ 2015-09-03 13:47         ` Dmitry A. Kazakov
  1 sibling, 0 replies; 31+ messages in thread
From: Dmitry A. Kazakov @ 2015-09-03 13:47 UTC (permalink / raw)


On Thu, 3 Sep 2015 13:39:22 +0200, G.B. wrote:

> On 03.09.15 11:26, Dmitry A. Kazakov wrote:
>> On Thu, 3 Sep 2015 10:14:35 +0200, Georg Bauhaus wrote:
>>
>> An object of a type is *same* in all contexts, because the type is same.
> 
> While an object doesn't change either identity or type,
> it does changes state. This is an event, too.

Yes, but according to that definition finalization is not an event. After
finalization the object is in no state.

>> 2. Regarding finalization, another crucial point. Finalization is *not* an
>> operation.
> 
> I'm not asking for finalization as an operation.
> I'm asking for clearly defined hooks made for operations
> (or something else) for what programmers will now put into
> Finalize, since there is nothing else where to put it.

Hook is OK except that if spelled as an operation there is a danger of
being called explicitly. Which is why a syntax sugar of a body without
interface would be much preferable.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-03 12:00         ` G.B.
@ 2015-09-03 13:59           ` Dmitry A. Kazakov
  2015-09-03 19:12           ` Randy Brukardt
  1 sibling, 0 replies; 31+ messages in thread
From: Dmitry A. Kazakov @ 2015-09-03 13:59 UTC (permalink / raw)


On Thu, 3 Sep 2015 14:00:52 +0200, G.B. wrote:

> On 03.09.15 13:39, G.B. wrote:
>>> An object of a type is *same* in all contexts, because the type is same.
>>
>> While an object doesn't change either identity or type,
>> it does changes state. This is an event, too.
> 
> Seen from a different angle:
> What could a type system have to offer to GUI programming?
> Some kinds of "event" are as ubiquitous in GUI programming
> as they are essential. Can this be made static?

Yes it can. See below.

> AFAICT, today we have string literals identifying things
> that can be called (Gtk), or we have selectors (Objective-C)
> for a similar thing, etc.

GtkAda has typed events on top of untyped Gtk events. The problem with it
is that it is reversed. The interface is of the button, e.g. it is the
primitive operations of the button (e.g. On_Button_Clicked), which is
useless in most cases. It should have been of the widget handling button
events:

   Button ---------event----------> Handler widget
    |
   On_Button_Clicked

The operation, and types hierarchy, must be on the right. The controlling
parameter is not Button but the handler widget.

> A mouse click or gesture is thus
> another kind of event to which programmers might want to attach
> something that reacts. How would static type systems help,
> knowing that trying to make them help has allegedly failed
> in the past?

The design is that you have a handler interface, e.g. of a button events
handler with the primitive operations of event notifications. The widget
catching button events implements this interface. Note that differently to
Ada or C++ interfaces this one is additive. I.e. if you handle more than
one button, the inherited interfaces of do not coalesce. Other examples of
this type of inheritance is doubly-linked list header, queue element etc.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-03 12:00         ` G.B.
  2015-09-03 13:59           ` Dmitry A. Kazakov
@ 2015-09-03 19:12           ` Randy Brukardt
  2015-09-04  7:33             ` Georg Bauhaus
  1 sibling, 1 reply; 31+ messages in thread
From: Randy Brukardt @ 2015-09-03 19:12 UTC (permalink / raw)


"G.B." <bauhaus@futureapps.invalid> wrote in message 
news:ms9cm8$leh$1@dont-email.me...
...
> AFAICT, today we have string literals identifying things
> that can be called (Gtk), or we have selectors (Objective-C)
> for a similar thing, etc.  A mouse click or gesture is thus
> another kind of event to which programmers might want to attach
> something that reacts. How would static type systems help,
> knowing that trying to make them help has allegedly failed
> in the past?

I have no idea why you think this is a problem. Claw uses statically defined 
action routines that one overrides. This is type-safe, it's impossible to 
handle an action that cannot happen (such as a click on a drawing canvas), 
and one can easily see that all required actions are handled (they're 
abstract in that case).

GWindows uses (optionally) call-back access-to-subprograns, which definitely 
have the first two properties (but not the third).

The implementation of this (the actual GUI binding) is groddy, but that's 
because we're trying to build something clean on top of a C implementation 
that resists that at every step. :-)

So I fail to see any problem that isn't being addressed here. Finalization 
is a very special kettle of fish, because the objects don't exist 
afterwards. It's needed to provide last wishes to objects, for clean-up of 
various sorts. (For instance, Claw uses finalization to unhook windows from 
the active window list, else we'd be calling actions on non-existent 
windows. There is no other bullet-proof way to do that, if one wants there 
library to work in the face of exceptions and abort, as well as programmer 
mistakes [failing to call Close appropriately].)

                                    Randy.


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-03 19:12           ` Randy Brukardt
@ 2015-09-04  7:33             ` Georg Bauhaus
  2015-09-04 21:34               ` Randy Brukardt
  0 siblings, 1 reply; 31+ messages in thread
From: Georg Bauhaus @ 2015-09-04  7:33 UTC (permalink / raw)


On 03.09.15 21:12, Randy Brukardt wrote:
> "G.B." <bauhaus@futureapps.invalid> wrote in message
> news:ms9cm8$leh$1@dont-email.me...
> ...
>> AFAICT, today we have string literals identifying things
>> that can be called (Gtk), or we have selectors (Objective-C)
>> for a similar thing, etc.  A mouse click or gesture is thus
>> another kind of event to which programmers might want to attach
>> something that reacts. How would static type systems help,
>> knowing that trying to make them help has allegedly failed
>> in the past?
>
> I have no idea why you think this is a problem.

Much like Objective-C is making use of C for implementing a rather
flexible O-O PL, one could use Ada the same way, or one can use Ada's
existing O-O features for implementing GUI style event handling
programs. But this addresses the problem (GUI event driven programming,
say) at the level of implementation, i.e. not directly. The language
is not generally providing wishes to objects, for handling events of various
sorts. Simply because Ada, like most languages I guess, doesn't address
events in the language, except for a very few. These "events" can be mapped
to problem domain events. Like objects dying, or signals handled
in a PO, or file streams ending in an I/O exception.

GUI programming is therefore just using general programming features for
implementing callback style subprograms that involve objects.
Programmers know the recommended ways, work is based on conventions.
The model is implying the existence of some conventional run loop
that operates using conventional means of  the language.
Events are implicit, not language. So, while there is no problem with
either a very flexible O-O system emulated in C, or with having the Ada
compiler help with earlier binding, both approaches do not handle events
in the language.

That's not a problem, but it is an opportunity, I think.

> So I fail to see any problem that isn't being addressed here. Finalization
> is a very special kettle of fish, because the objects don't exist
> afterwards. It's needed to provide last wishes to objects, for clean-up of
> various sorts. (For instance, Claw uses finalization to unhook windows from
> the active window list, else we'd be calling actions on non-existent
> windows. There is no other bullet-proof way to do that, if one wants there
> library to work in the face of exceptions and abort, as well as programmer
> mistakes [failing to call Close appropriately].)

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-04  7:33             ` Georg Bauhaus
@ 2015-09-04 21:34               ` Randy Brukardt
  2015-09-05  6:31                 ` Dmitry A. Kazakov
                                   ` (3 more replies)
  0 siblings, 4 replies; 31+ messages in thread
From: Randy Brukardt @ 2015-09-04 21:34 UTC (permalink / raw)


"Georg Bauhaus" <bauhaus@futureapps.invalid> wrote in message 
news:msbhc8$6qq$1@dont-email.me...
...
> So, while there is no problem with
> either a very flexible O-O system emulated in C, or with having the Ada
> compiler help with earlier binding, both approaches do not handle events
> in the language.

I have not the slightest clue as to what "handling events in the language" 
would look like, assuming Ada doesn't have it. "Events" to me are just calls 
(dynamic control flow), and I don't see anything sensible that would make 
calls "better". Perhaps a lack of imagination on my part.

> That's not a problem, but it is an opportunity, I think.

Opportunity for what, madness? Event-driven GUI programming is just one step 
short of madness as it is, I'd hate to expand that. Such code is necessarily 
unstructured spaggetti, because every routine has to be able to handle 
anything in essentially any order.

Much like OOP itself, I don't see it having much application away from the 
GUI (and I'm dubious that it is that good of an organization even for a 
GUI). As such, it doesn't make much sense in a general purpose programming 
language.

                             Randy. 



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-04 21:34               ` Randy Brukardt
@ 2015-09-05  6:31                 ` Dmitry A. Kazakov
  2015-09-05  6:44                 ` Georg Bauhaus
                                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 31+ messages in thread
From: Dmitry A. Kazakov @ 2015-09-05  6:31 UTC (permalink / raw)


On Fri, 4 Sep 2015 16:34:40 -0500, Randy Brukardt wrote:

> Opportunity for what, madness? Event-driven GUI programming is just one step 
> short of madness as it is, I'd hate to expand that. Such code is necessarily 
> unstructured spaggetti, because every routine has to be able to handle 
> anything in essentially any order.

There are competing relationships which do not map each other. An
issuer-handler relationship is a mess because other relationship, the
hierarchy of widget types, is considered more important. Another messy
relationship is container-child. We cannot have all three structured, thus
two of them are necessarily mess.
 
> Much like OOP itself, I don't see it having much application away from the 
> GUI (and I'm dubious that it is that good of an organization even for a 
> GUI).

GUI is a poor example for OO actually, because of above.

> As such, it doesn't make much sense in a general purpose programming 
> language.

Only OOP makes sense. There is *no* application where procedural
decomposition is superior to OO decomposition.

Procedural decomposition is untyped per design, because procedures can work
with existing types only. Therefore you must have all types *before* you
start thinking in terms of procedures. So the only types which can be
involved are primitive scalar types or messy ad-hoc low-level records and
arrays.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-04 21:34               ` Randy Brukardt
  2015-09-05  6:31                 ` Dmitry A. Kazakov
@ 2015-09-05  6:44                 ` Georg Bauhaus
  2015-09-05  7:07                   ` Dmitry A. Kazakov
  2015-09-05  6:45                 ` Niklas Holsti
  2015-09-05  7:16                 ` Shark8
  3 siblings, 1 reply; 31+ messages in thread
From: Georg Bauhaus @ 2015-09-05  6:44 UTC (permalink / raw)


On 04.09.15 23:34, Randy Brukardt wrote:
> Event-driven GUI programming is just one step
> short of madness as it is, I'd hate to expand that. Such code is necessarily
> unstructured spaggetti, because every routine has to be able to handle
> anything in essentially any order.

Unstructured spaghetti in O-O programs is the very thing that rings
a bell. ;-) But I'd expect to see the same in unstructured procedural
programs (of structured programming) and also in massively coupled
equational definitions (of functionists' programs). It's common.

There is an overabundance of attempts at addressing systematically
one kind of event handling, viz. JavaScript based DOM events in client-
server systems. Lots of frameworks to choose from, more or less mature;
some nice ideas; some good old ideas. No universally accepted solution.
(And nothing in the language, really, other than the names in
   addEventListener(event_name, function, ...).)

Some questions that might frequently arise, I think:

- How are the program's objects related when such-and-such happens?
   Can we express that in source text, specifically?

- Are there any ways for correctly reacting to Pig_flies_By?
   E.g. topsorted orders of calls. Can we declare that set of orders
    in the source text, specifically?

If, to find an answer, we are now looking at simulators, or at graphs drawn
by some tool, or just study the sources and write memos. then these ways
of explaining reactions to events  seems to work only after the fact, not
by declaration.

Temporal logic is, I guess, one way of formalizing these relationships.
Not that I'm fluent in it!


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-04 21:34               ` Randy Brukardt
  2015-09-05  6:31                 ` Dmitry A. Kazakov
  2015-09-05  6:44                 ` Georg Bauhaus
@ 2015-09-05  6:45                 ` Niklas Holsti
  2015-09-05  7:21                   ` Dmitry A. Kazakov
                                     ` (3 more replies)
  2015-09-05  7:16                 ` Shark8
  3 siblings, 4 replies; 31+ messages in thread
From: Niklas Holsti @ 2015-09-05  6:45 UTC (permalink / raw)


On 15-09-05 00:34 , Randy Brukardt wrote:
> "Georg Bauhaus" <bauhaus@futureapps.invalid> wrote in message
> news:msbhc8$6qq$1@dont-email.me...
> ...
>> So, while there is no problem with
>> either a very flexible O-O system emulated in C, or with having the Ada
>> compiler help with earlier binding, both approaches do not handle events
>> in the language.
>
> I have not the slightest clue as to what "handling events in the language"
> would look like, assuming Ada doesn't have it.

It seems to me that Georg's "events" are rather like the "pointcuts" or 
"join points" in aspect-oriented programming 
(https://en.wikipedia.org/wiki/Aspect-oriented_programming) where some 
computation is added to certain points in a program without modifying 
the original source code, and instead coding the new computation 
separately and somehow declaratively defining how the original and new 
computations are interleaved at run-time at the join points.

Ada has three  features that are similar to this: controlled types, 
run-time constraint checks, and predicate checks. By making a type 
controlled, implicit calls of Initialize, Adjust, and Finalize are added 
at specific points (Georg's "events") in the program. By adding 
constraints to a type, or predicates to a type or operation, implicit 
checks ("calls") of those constraints and predicates are added at 
specific points in the program.

However, in aspect-oriented programming the implicitly invoked, new 
computation is not meant to affect the original computation, but to 
implement some other linked computation, another aspect of the application.

Aspect-oriented programming aims to let programmers define more such 
pointcuts/events and added computation, for application-specific 
purposes, and thereby isolate the different "aspects" of the program -- 
a new sort of modularity and separation of concerns.

> "Events" to me are just calls
> (dynamic control flow), and I don't see anything sensible that would make
> calls "better". Perhaps a lack of imagination on my part.

I have long wished for an easier way to return multiple results from a 
call, especially when the set of results that is really available 
depends on the run-time outcome of the call, for example on whether the 
called operation succeeded or failed in some way.

At present, to return multiple results from a call, the callee either 
has to have multiple "out" parameters, or an "out" parameter that is a 
record type with multiple components. The caller then has to declare her 
own variables to stand as actual parameters, even if these variables are 
used only to receive the outputs of this call.

If the set of available outputs depends on the outcome of the call, some 
of the "out" parameters, or some of the components of the "out" record, 
are often irrelevant and meaningless in some outcomes. For example, if a 
procedure that searches for an item based on a key fails to find the 
item, it must return both a "not found" status and an irrelevant, dummy 
item value. A variant-record "out" parameter can be used to hide the 
irrelevant item component in such cases, but this adds complexity to the 
declaration of the record type, and again it will often be the case that 
this record type is used only for this one procedure and its calls.

I have vague ideas that it should be possible to declare, in a 
procedure's parameter profile, the various outcomes that are possible 
(found, not found, ...) and which outputs are available in which outcomes.

Then it should be possible to call a procedure in a way that opens a 
block that implicitly starts with a case statement and separates into 
different branches for different outcomes, with the available "out" 
parameters directly accessible (as constant objects) in each branch 
without the caller having to declare her own local variables just for 
use as actual "outs". Alternatively, the outputs of the call could be 
implicitly organised like a variant record, with a designated output 
playing the role of discriminant and case selector.

In addition to the variant-record (or class-wide) "out" parameter, Ada 
has two ways to implement such things:

- Different outcomes of a procedure can be signalled by propagating an 
exception from the call, but this is an extreme all-or-nothing method: 
if an exception is propagated, the only output from the call is the 
identity of the exception (and possible side effects).

- Outputs of a computation can be made available to a caller, without 
the caller having to declare "out" variables, by implementing the 
computation in the elaboration block in the body of a generic package, 
which has generic formal objects corresponding to the formal "in" and 
"in out" parameters of the computation, and declares public variables 
corresponding to the "out" parameters of the computation. To "call" this 
computation, the "caller" instantiates the generic, and can then access 
the public variables of the instance, with the values computed at 
elaboration of the instance, without explicitly declaring her own 
variables for use as "outs". But I'm sure that most programmers would 
consider this to be a weird misuse of the generic facility. Further, the 
instantiation must be done as a declaration, not as a statement, and the 
"out" variables can seldom be declared constant, because the computation 
is often too complex to be done in the declaration of the generic package.

In a more functional-programming approach, a procedure could be made to 
"return" its outputs by calling different "continuation" procedures 
(given as "in" parameters) for the different outcomes; each such 
continuation procedure could have its own set of "in" parameters 
corresponding to the "outs" available from the original procedure in 
this outcome. This would be rather far from the procedural Ada style, 
but perhaps it could be used as the internal implementation of what I 
proposed above, even if the source syntax does not look like continuations.

> Opportunity for what, madness? Event-driven GUI programming is just one step
> short of madness as it is,

Ooh, strong agreement here... but I don't think Georg means such events.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-05  6:44                 ` Georg Bauhaus
@ 2015-09-05  7:07                   ` Dmitry A. Kazakov
  0 siblings, 0 replies; 31+ messages in thread
From: Dmitry A. Kazakov @ 2015-09-05  7:07 UTC (permalink / raw)


On Sat, 5 Sep 2015 08:44:14 +0200, Georg Bauhaus wrote:

> - How are the program's objects related when such-and-such happens?

Individual relationships of objects is a recipe for mess. BTW, this is what
is so wrong in OOA/D, which many wrongly equate to OO.

> Can we express that in source text, specifically?

Make a list of language mechanisms and go through it...

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-04 21:34               ` Randy Brukardt
                                   ` (2 preceding siblings ...)
  2015-09-05  6:45                 ` Niklas Holsti
@ 2015-09-05  7:16                 ` Shark8
  3 siblings, 0 replies; 31+ messages in thread
From: Shark8 @ 2015-09-05  7:16 UTC (permalink / raw)


On Friday, September 4, 2015 at 3:34:43 PM UTC-6, Randy Brukardt wrote:
> "Georg Bauhaus" wrote in message 
> > That's not a problem, but it is an opportunity, I think.
> 
> Opportunity for what, madness? Event-driven GUI programming is just one step 
> short of madness as it is, I'd hate to expand that.

But what about Ada's Task (and protected objects) -- aren't the rendezvous-mechanisms EXACTLY event-driven?

> Much like OOP itself, I don't see it having much application away from the 
> GUI (and I'm dubious that it is that good of an organization even for a 
> GUI). As such, it doesn't make much sense in a general purpose programming 
> language.

Well, if you consider that MVC is a design-pattern for GUIs, you could do the same sort of separation "on the other side" letting the model essentially be the interface between the buisness-logic-layer and either of the GUI/DB layer... and on the DB side of the interface you could directly map "save model X" to the appropriate DB call.


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-05  6:45                 ` Niklas Holsti
@ 2015-09-05  7:21                   ` Dmitry A. Kazakov
  2015-09-05 12:07                   ` Peter Chapin
                                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 31+ messages in thread
From: Dmitry A. Kazakov @ 2015-09-05  7:21 UTC (permalink / raw)


On Sat, 5 Sep 2015 09:45:43 +0300, Niklas Holsti wrote:

> - Outputs of a computation can be made available to a caller, without 
> the caller having to declare "out" variables, by implementing the 
> computation in the elaboration block in the body of a generic package, 
> which has generic formal objects corresponding to the formal "in" and 
> "in out" parameters of the computation, and declares public variables 
> corresponding to the "out" parameters of the computation. To "call" this 
> computation, the "caller" instantiates the generic, and can then access 
> the public variables of the instance, with the values computed at 
> elaboration of the instance, without explicitly declaring her own 
> variables for use as "outs". But I'm sure that most programmers would 
> consider this to be a weird misuse of the generic facility. Further, the 
> instantiation must be done as a declaration, not as a statement, and the 
> "out" variables can seldom be declared constant, because the computation 
> is often too complex to be done in the declaration of the generic package.

It is worth to have a language construct for this. There are cases beyond
multiple out parameters when this is necessary, e.g.

   if X in T'Class then
      declare
          Y : T'Class renames T'Class (X);

or

   if Ptr /= null then
      declare
          X : T := Ptr.all;

> In a more functional-programming approach, a procedure could be made to 
> "return" its outputs by calling different "continuation" procedures 
> (given as "in" parameters) for the different outcomes; each such 
> continuation procedure could have its own set of "in" parameters 
> corresponding to the "outs" available from the original procedure in 
> this outcome. This would be rather far from the procedural Ada style, 
> but perhaps it could be used as the internal implementation of what I 
> proposed above, even if the source syntax does not look like continuations.

This is an independent case to me. It falls into the basket "co-routines".
If we had co-routines we could use them to handle multiple outputs.

BTW, this is rather data-driven approach than functional. DDA is a mess on
a much bigger scale than one could imagine...

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-05  6:45                 ` Niklas Holsti
  2015-09-05  7:21                   ` Dmitry A. Kazakov
@ 2015-09-05 12:07                   ` Peter Chapin
  2015-09-06 10:45                   ` Georg Bauhaus
  2015-10-13 19:57                   ` Eryndlia Mavourneen
  3 siblings, 0 replies; 31+ messages in thread
From: Peter Chapin @ 2015-09-05 12:07 UTC (permalink / raw)


In article <d4vhcnF9eulU1@mid.individual.net>, 
niklas.holsti@tidorum.invalid says...

> I have long wished for an easier way to return multiple results from a 
> call, especially when the set of results that is really available 
> depends on the run-time outcome of the call, for example on whether the 
> called operation succeeded or failed in some way.

Functional languages have thought about this. Most provide a way of 
defining a kind of variant record with very lightweight syntax so 
defining a new record for each use isn't onerous.

As an example Scala (for instance) has an Option type in its library 
specifically for use by functions that may not have a valid value to 
return. A function that might or might not return an integer can be 
declared to run an Option[Int] (like a generic instance) that either 
holds the integer in question or has the special value None. This can be 
simulated in Ada without too much pain but what makes functional 
languages different is that it is easy to define and use variations of 
this idea without a lot of ceremony.

> Then it should be possible to call a procedure in a way that opens a 
> block that implicitly starts with a case statement and separates into 
> different branches for different outcomes...

This is done using pattern matching in functional languages which, as 
you observe, complements the features above very nicely. Actually Scala 
provides higher order methods on the Option type that allows you, in 
that case, to operate on data that might or might not be there without 
worrying about checking for its existence until the last minute. This 
pushes error handling out of the main logic of your program without 
using exceptions for that purpose.

I'm not sure how possible it would be to retrofit these ideas into Ada. 
I'm going to guess it would be hard. Ada is not a functional language 
and as soon as you start walking down the path I'm talking about here 
you end up dragging in a lot of the usual functional machinery.

Peter


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-05  6:45                 ` Niklas Holsti
  2015-09-05  7:21                   ` Dmitry A. Kazakov
  2015-09-05 12:07                   ` Peter Chapin
@ 2015-09-06 10:45                   ` Georg Bauhaus
  2015-10-13 19:57                   ` Eryndlia Mavourneen
  3 siblings, 0 replies; 31+ messages in thread
From: Georg Bauhaus @ 2015-09-06 10:45 UTC (permalink / raw)


On 05.09.15 08:45, Niklas Holsti wrote:
> On 15-09-05 00:34 , Randy Brukardt wrote:
>> "Georg Bauhaus" <bauhaus@futureapps.invalid> wrote in message
>> news:msbhc8$6qq$1@dont-email.me...
>> ...
>>> So, while there is no problem with
>>> either a very flexible O-O system emulated in C, or with having the Ada
>>> compiler help with earlier binding, both approaches do not handle events
>>> in the language.
>>
>> I have not the slightest clue as to what "handling events in the language"
>> would look like, assuming Ada doesn't have it.
>
> It seems to me that Georg's "events" are rather like the "pointcuts" or "join points" in aspect-oriented programming (https://en.wikipedia.org/wiki/Aspect-oriented_programming) where some computation is added to certain points in a program without modifying the original source code, and instead coding the new computation separately and somehow declaratively defining how the original and new computations are interleaved at run-time at the join points.

These "aspects" (of AOP) would come to mind, but rather than focus on them,
I wanted to start from a more inclusive definition of "event", perhaps
a little broader than those "aspects", but applicable to a number of
programming situations. A definition that can lead the way to language
for writing a program's reaction to specific "events".

Summarily: Some words of source text would then express "event handling",
but neither by way of having "_Handler" as the suffix of some primitive
operation's name, nor by the event being an exception, say, and event
handling being the statements of an exception handler.


Exploring a bit:
First and foremost, programmers need to be oriented when being asked
about events and how their programs handle them, so that's an aspect
to keep in mind when defining "event".

If you think about both programming situations (involving humans) and
also about programs that run (involving technology like clocks, mice,
touch screens, networks, thermometers), then "event" becomes the name
of quite many different ideas. However, they all share certain qualities:

1) that of being tied to one single point in space-time
2) that of having economic impact
3) that of being recurring problems in need of a solution

ad 1) while (1) happens to agree with what dictionaries say,
there is limited support for the property of being single in the Ada
language. More so if there would be other sorts of things single,
besides event handlers. The support that Ada offers is not addressing
events in particular. (Ada is not unique here.)
If there is a chance that some event requires a 1:1 mapping in the source
text, or in the mind of a programmer being asked about it, then just a bit
of general Ada language paired with conventions is all there is.

ad 2), imagine a programmer needing to answer questions of the kind
"What happens if A?". Can they just point at some place in the source text?
What will they find, and how? I guess it is some table-like thing, or
some more or less implicit connection of types.

These two "traces" of event handling both would contain hints at the parts
of the program involved in handling the event "A".  Managing this "cross
referencing structure" is tedious and costly. (No surprise that GUI
programming is considered tricky; it is full of patterns.) If a program
does not provide any of this (Gordian spaghetti), then long hours might
pass until programmers can answer after studying their program once again.
(I am assuming that a majority of GUI programs is not modeled after
some real specification. Unfortunately.)

Also, when developing a program that handles events, there is no specific
guidance by the language; there are libraries that make use of some of
the language's features. Of necessity, this creates idiosyncrasies.
This state of the art might be good when selling proprietary class libraries,
but engineers and project leaders may want something more standard for
this very standard programming problem, lest they become "part of the
business". (At whose cost?)

ad 3) a "problematic" event is an easily named entity; like whenever input
channel X14 is delivering data, the program's behavior should be
such-and-such, possibly depending further on such-and-such. Or behavior is
unexpected.

Now, in general,Without these events, many programs would be pointless.
Still, language-wise, solutions aren't directly available: programmers
rely on class libraries or similar. But solutions need to be found
again and again, so as to have programs that handle anything at all.

In case of unexpected behavior, solving the problem means modifying
the program. But how, if someone else has written the program and used
this or that convention?


Tasks to the rescue? What can you learn from a task's interface that you
couldn't learn from a type's interface? There is one additional bit, viz.
independent execution. Does it help event handling? Not according to
Aaron Hillegass, who explains that many activities seen to be concurrent
can actually be handled conveniently by programming to the run-loop.
(I believe some OS design guys also suggest non-communicating processes,
but don't remember the name of their project.)

A last idea: GUI design programs are a visualization of some event handling,
Or rather, they show the stage for event handling. But either way, somehow
events are present there. So, GUI design programs use somewhat formal
definitions of how objects should be tied together for handling events.
They produce some manifestations of "event handling". Is this kind of
formalization inaccessible to programming languages?



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-02 10:59 Top 10 Worst C# Features Stefan.Lucks
                   ` (2 preceding siblings ...)
  2015-09-03  8:51 ` gautier_niouzes
@ 2015-10-01 14:03 ` Paul Colin de Gloucester
  2015-10-14  8:00   ` Maciej Sobczak
  3 siblings, 1 reply; 31+ messages in thread
From: Paul Colin de Gloucester @ 2015-10-01 14:03 UTC (permalink / raw)


On September 2nd, 2015, Steven Lucks sent:
|------------------------------------------------------------------------|
|"[. . .]                                                                |
|                                                                        |
|In Ada, the "/="-operator is automatically the negation of "=". Which is|
|great. [. . .]                                                          |
|[. . .]                                                                 |
|                                                                        |
|[. . .]"                                                                |
|------------------------------------------------------------------------|

One of the bugs which I detected in Crap-Poo-Poo code which I referred
to in the paper referred to below involved two functions like these,
but they accidentally did not return values compatible with each
other. I explained this to Crap-Poo-Poo advocates involved, but they
lacked sufficient intelligence to comprehend a reason as to code
cloning producing a bug. I also advised that Ada does not do
this. They persisted with Crap Poo Poo.

@article{
  author = {{de Gloucester}, Paul Colin},
  title = {{Referees Often Miss Obvious Errors in Computer and
  Electronic Publications}},
  journal = {Accountability in Research: Policies and Quality
  Assurance},
  volume = {20},
  year = {2013},
  pages = {143--166},
  number = {3}
  }


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-09-05  6:45                 ` Niklas Holsti
                                     ` (2 preceding siblings ...)
  2015-09-06 10:45                   ` Georg Bauhaus
@ 2015-10-13 19:57                   ` Eryndlia Mavourneen
  3 siblings, 0 replies; 31+ messages in thread
From: Eryndlia Mavourneen @ 2015-10-13 19:57 UTC (permalink / raw)


On Saturday, September 5, 2015 at 1:45:45 AM UTC-5, Niklas Holsti wrote:
> I have long wished for an easier way to return multiple results from a 
> call, especially when the set of results that is really available 
> depends on the run-time outcome of the call, for example on whether the 
> called operation succeeded or failed in some way.

Sounds just like the Icon programming language, a derivative and elaboration of SNOBOL/SPITBOL.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-10-01 14:03 ` Paul Colin de Gloucester
@ 2015-10-14  8:00   ` Maciej Sobczak
  2015-10-14 14:26     ` Ben Bacarisse
  2015-11-06 14:50     ` Nicholas Collin Paul de Gloucester
  0 siblings, 2 replies; 31+ messages in thread
From: Maciej Sobczak @ 2015-10-14  8:00 UTC (permalink / raw)



> One of the bugs which I detected in Crap-Poo-Poo code which I referred
> to in the paper referred to below involved two functions like these,
> but they accidentally did not return values compatible with each
> other. I explained this to Crap-Poo-Poo advocates involved, but they
> lacked sufficient intelligence to comprehend a reason as to code
> cloning producing a bug.

Apparently you have talked to wrong advocates.
For the sake of discussion I will play that role in this post.

Yes, we understand that it is possible to have incompatible implementations of operator== and operator!= in C++ (assuming that this is the language you are referring to), but we are willing to take this risk (and address it by other means) as it allows us to implement these operators more efficiently.
One possible example where this could be possible is when the encapsulated data has a digital signature or some other short digest available with the property that when two digests are different then the objects are surely different (and this can be determined very quickly), whereas when the digests are equal then more work is needed to determine whether the objects are equal, too. In this case, our operator!= can be much faster than operator== and we are willing to benefit from the optimization opportunity here. This could not be possible if one is automatically derived from the other.

> I also advised that Ada does not do
> this.

Yes, we know that Ada prevents some optimization strategies. This is not the only one.

> They persisted with Crap Poo Poo.

Yes, we prefer to get better performance at the expense of higher verification effort.


If you are willing to address the above, please use the actual name of the programming language that you are referring to.

-- 
Maciej Sobczak * http://www.inspirel.com


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-10-14  8:00   ` Maciej Sobczak
@ 2015-10-14 14:26     ` Ben Bacarisse
  2015-10-14 16:50       ` Paul Rubin
  2015-10-15 12:24       ` Maciej Sobczak
  2015-11-06 14:50     ` Nicholas Collin Paul de Gloucester
  1 sibling, 2 replies; 31+ messages in thread
From: Ben Bacarisse @ 2015-10-14 14:26 UTC (permalink / raw)


Maciej Sobczak <see.my.homepage@gmail.com> writes:
<snip>
> Yes, we understand that it is possible to have incompatible
> implementations of operator== and operator!= in C++ (assuming that
> this is the language you are referring to), but we are willing to take
> this risk (and address it by other means) as it allows us to implement
> these operators more efficiently.

Do you mean that there are reasons to permit !(a == b) and a != b to
have different values in some cases?  I don't think you mean this
(because your example does not obviously address that possibility), but
I am not 100% sure.

> One possible example where this could be possible is when the
> encapsulated data has a digital signature or some other short digest
> available with the property that when two digests are different then
> the objects are surely different (and this can be determined very
> quickly), whereas when the digests are equal then more work is needed
> to determine whether the objects are equal, too. In this case, our
> operator!= can be much faster than operator== and we are willing to
> benefit from the optimization opportunity here. This could not be
> possible if one is automatically derived from the other.

I don't see why

  bool operator!=(const T &other) const noexcept
  {
    if (this.hash != other.hash)
      return true;
    return !this.long_slow_equality_test(other);
  }

is any more or less efficient than

  bool operator==(const T &other) const noexcept
  {
    if (this.hash != other.hash)
      return false;
    return this.long_slow_equality_test(other);
  }

but I may have missed the point you are trying to make.

<snip>
-- 
Ben.


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-10-14 14:26     ` Ben Bacarisse
@ 2015-10-14 16:50       ` Paul Rubin
  2015-10-14 18:17         ` Stefan.Lucks
  2015-10-15 12:24       ` Maciej Sobczak
  1 sibling, 1 reply; 31+ messages in thread
From: Paul Rubin @ 2015-10-14 16:50 UTC (permalink / raw)


Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> Do you mean that there are reasons to permit !(a == b) and a != b to
> have different values in some cases? 

I think he meant they should both return the same value, but it is ok if
they don't use the same algorithm.  Of course it may be possible for the
compiler to optimize the first into the second.  The idea is just that
if (a != b) { ... }   can be much faster than  if (a == b) { ... } .

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-10-14 16:50       ` Paul Rubin
@ 2015-10-14 18:17         ` Stefan.Lucks
  2015-10-14 19:54           ` Ben Bacarisse
  0 siblings, 1 reply; 31+ messages in thread
From: Stefan.Lucks @ 2015-10-14 18:17 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 2394 bytes --]

On Wed, 14 Oct 2015, Paul Rubin wrote:

> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>> Do you mean that there are reasons to permit !(a == b) and a != b to
>> have different values in some cases?
>
> I think he meant they should both return the same value, but it is ok if
> they don't use the same algorithm.  Of course it may be possible for the
> compiler to optimize the first into the second.  The idea is just that
> if (a != b) { ... }   can be much faster than  if (a == b) { ... } .

As I seem to understand, Ben questioned that either the test on equality 
or on non-equality could be much faster than the other one.

In Ada syntax:

   function "="(A, B: T) return Boolean is
   begin
      if Hash(A) /= Hash(B) then
         return False
      else return Slow_Equality_Test(A, B)
   end "=";

   function "/="(A, B: T) return Boolean is
   begin
      if Hash(A) /= Hash(B) then
         return True
      else return Not Slow_Equality_Test(A, B)
   end "/="; -- if this where allowed in Ada

It seems quite clear that for any inputs X and Y, the expressions X = Y 
and X /= Y should evaluate at the same speed. Or what am I missing?

Actually, "/=" could be faster than "=" if either where defined as 
follows:

   function "="(A, B: T) return Boolean
      renames Slow_Equality_Test;

   function "/="(A, B: T) return Boolean is
     (Hash(A) /= Hash(B)); -- second case

Redefining "=" this way is just missing an optimization.

Redefining "/=" is that way is a bug.

So how could "/=" really be faster than "="?

My guess is that the devil's advocate, Maciej Sobczak, assumed that "=" is 
already in use as identifier, instead of another identifier for the 
Slow_Equality_Test, as I call it. Which means, we cannot employ the 
optimization for equality. An independent "/=" would then allow us to 
optimize non-equality.

But this would be a design flaw, and it might be easy to fix:

   function "="(A, B: T) return Boolean is
     -- optimized equality
   begin
      if Hash(A) /= Hash(B) then
         return False
      else return Outer_Package."="(A, B)
   end "=";


--------  I  love  the  taste  of  Cryptanalysis  in  the morning!  --------
www.uni-weimar.de/de/medien/professuren/mediensicherheit/people/stefan-lucks
----Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany----

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-10-14 18:17         ` Stefan.Lucks
@ 2015-10-14 19:54           ` Ben Bacarisse
  0 siblings, 0 replies; 31+ messages in thread
From: Ben Bacarisse @ 2015-10-14 19:54 UTC (permalink / raw)


Stefan.Lucks@uni-weimar.de writes:

> On Wed, 14 Oct 2015, Paul Rubin wrote:
>
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>> Do you mean that there are reasons to permit !(a == b) and a != b to
>>> have different values in some cases?
>>
>> I think he meant they should both return the same value, but it is ok if
>> they don't use the same algorithm.  Of course it may be possible for the
>> compiler to optimize the first into the second.  The idea is just that
>> if (a != b) { ... }   can be much faster than  if (a == b) { ... } .
>
> As I seem to understand, Ben questioned that either the test on
> equality or on non-equality could be much faster than the other one.

Yes, exactly.  If !(a == b) and a != b don't have to be the same for
this imagined type then of course one can be faster than the other, but
if the usual laws are to hold, implementing one can't be anything but
trivially easier then the other.

<snip>
-- 
Ben.


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-10-14 14:26     ` Ben Bacarisse
  2015-10-14 16:50       ` Paul Rubin
@ 2015-10-15 12:24       ` Maciej Sobczak
  2015-10-15 13:59         ` Ben Bacarisse
  1 sibling, 1 reply; 31+ messages in thread
From: Maciej Sobczak @ 2015-10-15 12:24 UTC (permalink / raw)



> Do you mean that there are reasons to permit !(a == b) and a != b to
> have different values in some cases?

Why not? We are already talking about the language where a+b is not necessarily equal to b+a (hint: strings). ;-)

There is also an interesting area for objects that might be neither "equal" nor "different" (that is, where both operators might return false at the same time).
As an illustration, Apples and Oranges are neither equal nor different, even though they are all Fruits and might be modeled in a flat type system.

Of course, diverting from the usual laws is asking for trouble, but as I have already said - some programmers might be willing to get some added flexibility at the expense of higher verification effort. Definitely, one should not automatically assume that all C++ programmers are morons.

> I don't see why
> 
>   bool operator!=(const T &other) const noexcept
>   {
>     if (this.hash != other.hash)
>       return true;
>     return !this.long_slow_equality_test(other);
>   }
> 
> is any more or less efficient than
> 
>   bool operator==(const T &other) const noexcept
>   {
>     if (this.hash != other.hash)
>       return false;
>     return this.long_slow_equality_test(other);
>   }
> 
> but I may have missed the point you are trying to make.

No, but you have missed the point that I tried to address. Your example is OK with regard to performance, but for some reason you have still used *distinct* implementations of these operators, instead of calling one from another. And interestingly, your WCET is even worse than in my example, as it might need to execute two comparisons (fast and slow) instead of just the one which is asked for.

Of course, I don't claim that these are typical usage scenarios. Typically, these operators indeed should be based on common logic.

-- 
Maciej Sobczak * http://www.inspirel.com


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-10-15 12:24       ` Maciej Sobczak
@ 2015-10-15 13:59         ` Ben Bacarisse
  0 siblings, 0 replies; 31+ messages in thread
From: Ben Bacarisse @ 2015-10-15 13:59 UTC (permalink / raw)


Maciej Sobczak <see.my.homepage@gmail.com> writes:

>> Do you mean that there are reasons to permit !(a == b) and a != b to
>> have different values in some cases?
>
> Why not? We are already talking about the language where a+b is not
> necessarily equal to b+a (hint: strings). ;-)

I asked because I wanted to know the context for the remark that
prompted my reply.  That remark was

  In this case [when there is a hash or signature], our operator!= can
  be much faster than operator== and we are willing to benefit from the
  optimization opportunity here.

<snip>
>> I don't see why
>> 
>>   bool operator!=(const T &other) const noexcept
>>   {
>>     if (this.hash != other.hash)
>>       return true;
>>     return !this.long_slow_equality_test(other);
>>   }
>> 
>> is any more or less efficient than
>> 
>>   bool operator==(const T &other) const noexcept
>>   {
>>     if (this.hash != other.hash)
>>       return false;
>>     return this.long_slow_equality_test(other);
>>   }
>> 
>> but I may have missed the point you are trying to make.
>
> No, but you have missed the point that I tried to address. Your
> example is OK with regard to performance, but for some reason you have
> still used *distinct* implementations of these operators, instead of
> calling one from another.

No, I've just given an example of both because I disputed this remark:

  In this case [when there is a hash or signature], our operator!= can
  be much faster than operator== and we are willing to benefit from the
  optimization opportunity here.

There is no reason at all to use both, but the easiest way to explain
why I find the claim hard to accept is to show both.  In practice,
either one will do with the other implemented as the negation of the one
chosen.

You claimed that the case you gave (where the objects have a hash or
signature that allows for rapid non-equality testing) was an example
where separate implementations of != and == would be advantageous, but
what you described is not enough for the conclusion to hold.  That's
why I asked about !(a != b) == (a == b).

<snip>
-- 
Ben.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Top 10 Worst C# Features
  2015-10-14  8:00   ` Maciej Sobczak
  2015-10-14 14:26     ` Ben Bacarisse
@ 2015-11-06 14:50     ` Nicholas Collin Paul de Gloucester
  1 sibling, 0 replies; 31+ messages in thread
From: Nicholas Collin Paul de Gloucester @ 2015-11-06 14:50 UTC (permalink / raw)


On October 14th, 2015, Maciej Sobczak sent:
|-------------------------------------------------------------------------|
|"> One of the bugs which I detected in Crap-Poo-Poo code which I referred|
|> to in the paper referred to below involved two functions like these,   |
|> but they accidentally did not return values compatible with each       |
|> other. I explained this to Crap-Poo-Poo advocates involved, but they   |
|> lacked sufficient intelligence to comprehend a reason as to code       |
|> cloning producing a bug.                                               |
|                                                                         |
|Apparently you have talked to wrong advocates.                           |
|For the sake of discussion I will play that role in this post.           |
|                                                                         |
|Yes, we understand that it is possible to have incompatible              |
|implementations of operator== and operator!= in C++ (assuming that       |
|this is the language you are referring to), but we are willing to        |
|take this risk (and address it by other means) as it allows us to        |
|implement these operators more efficiently.                              |
|[. . .]"                                                                 |
|-------------------------------------------------------------------------|

This Crap-Poo-Poo code was inefficient. The idea of an operator which
is a complement of another operator being implemented in terms of a
complementary operator had not occurred to these idiots.

|-------------------------------------------------------------------------|
|"> I also advised that Ada does not do                                   |
|> this.                                                                  |
|                                                                         |
|Yes, we know that Ada prevents some [. . .]. This is not the only one."  |
|-------------------------------------------------------------------------|

Ada prevents bugs.

|-------------------------------------------------------------------------|
|"> They persisted with Crap Poo Poo.                                     |
|                                                                         |
|Yes, we prefer to get better performance at the expense of higher        |
|verification effort."                                                    |
|-------------------------------------------------------------------------|

Actually, they untruthfully boasted about both being faster and being
verified.

|-------------------------------------------------------------------------|
|"If you are willing to address the above, please use the actual name     |
|of the programming language that you are referring to.                   |
|                                                                         |
|--                                                                       |
|Maciej Sobczak * http://www.inspirel.com "                               |
|-------------------------------------------------------------------------|

Why? It was supposedly in C++ (which one of the aforementioned idiots
frequently used to accidentally call C then) and supposedly SystemC(R)
code. Note that persons who impose a requirement on how to use the
SystemC(R) name do not even adhere to this requirement themselves.

Regards,
Nicholas Collin Paul de Gloucester


^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2015-11-06 14:50 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-02 10:59 Top 10 Worst C# Features Stefan.Lucks
2015-09-02 17:37 ` Álex R. Mosteo
2015-09-02 19:39 ` Randy Brukardt
2015-09-03  8:14   ` Georg Bauhaus
2015-09-03  9:26     ` Dmitry A. Kazakov
2015-09-03 11:39       ` G.B.
2015-09-03 12:00         ` G.B.
2015-09-03 13:59           ` Dmitry A. Kazakov
2015-09-03 19:12           ` Randy Brukardt
2015-09-04  7:33             ` Georg Bauhaus
2015-09-04 21:34               ` Randy Brukardt
2015-09-05  6:31                 ` Dmitry A. Kazakov
2015-09-05  6:44                 ` Georg Bauhaus
2015-09-05  7:07                   ` Dmitry A. Kazakov
2015-09-05  6:45                 ` Niklas Holsti
2015-09-05  7:21                   ` Dmitry A. Kazakov
2015-09-05 12:07                   ` Peter Chapin
2015-09-06 10:45                   ` Georg Bauhaus
2015-10-13 19:57                   ` Eryndlia Mavourneen
2015-09-05  7:16                 ` Shark8
2015-09-03 13:47         ` Dmitry A. Kazakov
2015-09-03  8:51 ` gautier_niouzes
2015-10-01 14:03 ` Paul Colin de Gloucester
2015-10-14  8:00   ` Maciej Sobczak
2015-10-14 14:26     ` Ben Bacarisse
2015-10-14 16:50       ` Paul Rubin
2015-10-14 18:17         ` Stefan.Lucks
2015-10-14 19:54           ` Ben Bacarisse
2015-10-15 12:24       ` Maciej Sobczak
2015-10-15 13:59         ` Ben Bacarisse
2015-11-06 14:50     ` Nicholas Collin Paul de Gloucester

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox