March 08, 2005
On Tue, 08 Mar 2005 02:07:28 +0100, xs0 <xs0@xs0.com> wrote:
>> Nope. IMO adding aspects to a class defines a new class.
>
> Well, I looked at several AOP languages, and you seem to be the only one that thinks aspects define a new class. If I'm wrong, please provide a reference (preferably on web this time).

Sorry, no can do. The article is in DDJ, and you have to be a subscriber to read it, IIRC.
I'm not saying "you're wrong". I'm saying I prefer my concept to yours (the one you're describing).

>>> Well, then you can implement the aspect in a way that supports this. The  point is that the aspect code still gets executed all the time, even  though it can obviously do nothing if it is written that way. That does  not require two different classes.
>>  This is less efficient.
>
> How? I'd say it's faster to check a var than to execute completely different code

It's not "execute completely different code", it's "execute no code at all" as in, the class without the aspect applied. So, it's faster.

> , because modern CPUs rely on cache so heavily, its far more efficient to stay within cache than to avoid two CPU instructions. That is even more true in the case you're arguing (tracking a single instance), because the branch predictor will be right most of the time, avoiding even the potential cost of conditional jump (i.e. pipeline flush).

I'm saying additional code will make it slower.

>>> I don't see how you can do this by producing a new class (how will you  switch implementation in runtime?
>>  You wont. You simply need a locked version of class Foo at one point, and  not at another.
>
> Why do you need an aspect for this? There is no cross-cutting concern and whatnot, if that is what you want to do..

How else can I apply a set of generic code to specific methods of any number of existing classes?

>>> Now, if the aspect produces a new class (even if it is named A_B (or  whatever) automatically), you need to change the last line to
>>>
>>> A obj=new A_B();
>>  no, A_B obj = new A_B();
>
> How is that less of a change?

It's not, I was correcting a mistake.

>>> I don't see how that could be useful
>>  It's useful because you can _also_ say:
>>  A obj = new A();
>>  at the same time, and use both the normal class and the class with aspects  applied.
>
> But there is no point in using aspects if all you want is different versions of the same class.

Yes there is, because there is no other generic way to do it.

> Or, as a question, why would you use an aspect in this case?

Why not? It appears to be the best way to achieve what I want.

>> I agree with this example, it's a good description of where you'd use AOP.
>> I still prefer my concept/method of implementing it.
>
> Well, it's a contradiction that you agree with what I said and also think that aspects should produce new classes.

No, it's not. I agreed with your description of a problem. A problem solved by AOP. There are other problems, also solved by AOP. I believe my concept solves them better than the one you're describing.

> If an aspect produces a new class, you still have to manually change all references from OriginalClassName to AOPClassName (and back when you no longer want it),

No. I've already explained how that would be done. Using alias.

> which is again far more work than just changing the original class, so rather pointless. Why would you do more work with same benefits (i.e. new functionality) and how is that better?

It's not more work. My way has more benefits i.e. is more flexible. That is why I prefer it.

Regan
March 08, 2005
>> How? I'd say it's faster to check a var than to execute completely  different code
> 
> It's not "execute completely different code", it's "execute no code at  all" as in, the class without the aspect applied. So, it's faster.

It's not no code at all.. if you apply an aspect to a method/function (and all code is in a method or a function), there are then two functions, the original, and the original+aspect (and in the case the original does nothing, why is it there?)


> I'm saying additional code will make it slower.

Good for you.. I was wondering, however, what your arguments are? And, like explained above, there is actually more code in your case..


> How else can I apply a set of generic code to specific methods of any  number of existing classes?

Well, OK, that might be true, but let's compare:

- in "my" version, you can easily define a new class that extends the original and have the aspect target just the new one. All you need to do is to define the new class, which takes a line of code. So, you have both versions, which you seem to want, while you can still use aspects to change existing classes in cases where you don't want new classes..

- in "your" version, new classes are always produced, which might be useful in some cases, but is completely useless when you don't want new classes, as there is no single-line-of-code "workaround" (unless you go and change all the rest of the code as well; again, this defeats the purpose)


xs0
March 08, 2005
On Tue, 08 Mar 2005 03:13:23 +0100, xs0 <xs0@xs0.com> wrote:
>>> How? I'd say it's faster to check a var than to execute completely  different code
>>  It's not "execute completely different code", it's "execute no code at  all" as in, the class without the aspect applied. So, it's faster.
>
> It's not no code at all..

Sorry, I meant to say "no additional code".

> if you apply an aspect to a method/function (and all code is in a method or a function), there are then two functions, the original, and the original+aspect

Correct. If I don't need the "original+aspect" then being forced to use it, but skip it with a variable will be slower than "the original" without aspect applied.

>> How else can I apply a set of generic code to specific methods of any  number of existing classes?
>
> Well, OK, that might be true, but let's compare:
>
> - in "my" version, you can easily define a new class that extends the original and have the aspect target just the new one. All you need to do is to define the new class, which takes a line of code. So, you have both versions, which you seem to want, while you can still use aspects to change existing classes in cases where you don't want new classes..

True.

> - in "your" version, new classes are always produced, which might be useful in some cases, but is completely useless when you don't want new classes

True.

> , as there is no single-line-of-code "workaround"

There is a workaround, alias, it's a couple of lines, its comparable to what is done in C/C++ for the same reason.

I still prefer to create a new class. If, simply because when a class behaviour ismodified I think the name should change to relfect that. It appears there is little or no function difference between our ideas, I simply prefer mine. Go figure.

Regan
March 08, 2005
On Tue, 08 Mar 2005 15:36:36 +1300, Regan Heath <regan@netwin.co.nz> wrote:
> On Tue, 08 Mar 2005 03:13:23 +0100, xs0 <xs0@xs0.com> wrote:
>>>> How? I'd say it's faster to check a var than to execute completely  different code
>>>  It's not "execute completely different code", it's "execute no code at  all" as in, the class without the aspect applied. So, it's faster.
>>
>> It's not no code at all..
>
> Sorry, I meant to say "no additional code".
>
>> if you apply an aspect to a method/function (and all code is in a method or a function), there are then two functions, the original, and the original+aspect
>
> Correct. If I don't need the "original+aspect" then being forced to use it, but skip it with a variable will be slower than "the original" without aspect applied.
>
>>> How else can I apply a set of generic code to specific methods of any  number of existing classes?
>>
>> Well, OK, that might be true, but let's compare:
>>
>> - in "my" version, you can easily define a new class that extends the original and have the aspect target just the new one. All you need to do is to define the new class, which takes a line of code. So, you have both versions, which you seem to want, while you can still use aspects to change existing classes in cases where you don't want new classes..
>
> True.
>
>> - in "your" version, new classes are always produced, which might be useful in some cases, but is completely useless when you don't want new classes
>
> True.
>
>> , as there is no single-line-of-code "workaround"
>
> There is a workaround, alias, it's a couple of lines, its comparable to what is done in C/C++ for the same reason.
>
> I still prefer to create a new class. If, simply because when a class behaviour ismodified I think the name should change to relfect that. It appears there is little or no function difference between our ideas, I simply prefer mine. Go figure.

I can't seem to 'edit' with my client "Opera".. allow me to re-phrase the para above:

I still prefer to create a new class. If, simply because when a class
behaviour is modified I think the name should change to relfect that. It
appears there is little or no functional difference between our ideas, I
simply prefer mine. Go figure.

Regan
March 08, 2005
I see no point in arguing this further. You're just making arbitrary unsubstantiated claims and/or say that your preference is somehow a good argument in itself. Even when I said the whole world disagrees with you, the only thing you managed to respond with was that I'm not a DDJ subscriber..


xs0


> I still prefer to create a new class. If, simply because when a class
> behaviour is modified I think the name should change to relfect that. It
> appears there is little or no functional difference between our ideas, I
> simply prefer mine. Go figure.
> 
> Regan
March 08, 2005
On Tue, 08 Mar 2005 08:50:54 +0100, xs0 <xs0@xs0.com> wrote:
> I see no point in arguing this further.

I agree.

> You're just making arbitrary unsubstantiated claims and/or say that your preference is somehow a good argument in itself. Even when I said the whole world disagrees with you, the only thing you managed to respond with was that I'm not a DDJ subscriber..

*sigh* I just don't understand what I'm doing that makes you so hostile. Obviously it must be something *I'm doing* because "the whole world disagrees with [me]"

Regan
March 08, 2005
Disclaimer: this post is long and meant for Regan, so it is probably not worth your time reading it.

>> You're just making arbitrary unsubstantiated claims and/or say that your  preference is somehow a good argument in itself. Even when I said the  whole world disagrees with you, the only thing you managed to respond  with was that I'm not a DDJ subscriber..
> 
> *sigh* I just don't understand what I'm doing that makes you so hostile.  Obviously it must be something *I'm doing* because "the whole world  disagrees with [me]"

I'm not trying to be hostile, perhaps that is the result of my limited knowledge of english or something. But since you asked why you [annoy] me (in random order):

- you ignore half of what other people write (e.g. I said something about CPU cache and how checking a flag could actually be faster, you just said "no, it's slower" without even considering _why_ I said checking a flag _could_ be faster)

- when you misread something, you'll tag the other person as basically stupid without considering that you may be the one that made the mistake (e.g. in the thread on stable functions you misunderstood the comment on caching and suggested that the poster is proposing some bizarre global caching scheme)

- you cling to your ideas like it was a matter of life and death (e.g. in the opCast thread, even after several people, including me, said that using cast to select a method is ridiculous, you still went on and on how it is something natural; if it was the natural thing to do, there would obviously be no disagreement)

- you use a type of argument, but don't allow others to use that same type of argument (e.g., again in the opCast thread, the whole Brad is with me/Greg is with you thing)

- you never admit you're wrong (e.g. I said "if you want to log all calls, you can't also want to not log some calls", and you said you can; that's simply a logical fallacy, but you failed to admit even something that simple)

- even though you're quick to point out that other people use their preference as arguments, _your_ own preference is often the only argument you have (e.g. "I'm saying I prefer my concept to yours" without any argumentation; if you do manage to say something like "I prefer it because it is more flexible", you totally fail to argument that it is indeed more flexible, at least in my opinion)

- you fail to provide counterarguments in most cases, and just say something arbitrary. Our typical conversation goes like
me: A
you: B
me: ~B, because C, D, E
you: B
me: ~B, because D, F, G
you: B, isn't it obvious?
this thread was also going this exact same way, so I decided to drop it, because I don't feel any of us is gaining something from it.

- you take things out of context way too often (e.g. "the whole world disagrees with you"; the point of that sentence was that you fail to counterargue and I exagerated a bit to make that point clearer; you sliced it and took it out of context (which naturally completely changes its meaning) and again failed to counterargue (which you could do by showing that you do indeed counterargue))


There you have it, it got much longer than I planned, but I tried to argument that you do indeed do those things that bother me :)


xs0
March 08, 2005
Walter wrote:
> "Unknown W. Brackets" <unknown@simplemachines.org> wrote in message
> news:cu25p2$1jbc$1@digitaldaemon.com...
> 
>>Walter says: if it's compile time, programmers will patch it without
>>thinking.  That's bad.  So let's use runtime.
> 
> 
> That's essentially right.
> 
> I'll add one more example to the ones you presented:
> 
> int foo(Collection c, int y)
> {
>     foreach (Value v; c)
>     {
>         if (v.x == y)
>             return v.z;
>     }
> }
> 
> By the nature of the program I'm writing, "y" is guaranteed to be within c.
> Therefore, there is only one return from the function, and that is the one
> shown. But the compiler cannot verify this. You recommend that the compiler
> complain about it. I, the programmer, knows this can never happen, and I'm
> in a hurry with my mind on other things and I want to get it to compile and
> move on, so I write:
> 
> int foo(CollectionClass c, int y)
> {
>     foreach (Value v; c)
>     {
>         if (v.x == y)
>             return v.z;
>     }
>     return 0;
> }

Hey, hey, one really sould put an assert(0) there!

And then I remebered, that a year ago I would've put the return(0) there myself, if all it was for was to shut up the compiler.

> I'm not saying you would advocate "fixing" the code this way. I don't
> either. Nobody would. I am saying that this is often how real programmers
> will fix it. I know this because I see it done, time and again, in response
> to compilers that emit such error messages. This kind of code is a disaster
> waiting to happen. No compiler will detect it. It's hard to pick up on a
> code review. Testing isn't going to pick it up. It's an insidious, nasty
> kind of bug. It's root cause is not bad programmers, but a compiler error
> message that encourages writing bad code.
> 
> Instead, having the compiler insert essentially an assert(0); where the
> missing return is means that if it isn't a bug, nothing happens, and
> everyone is happy. If it is a bug, the assert gets tripped, and the
> programmer *knows* it's a real bug that needs a real fix, and he won't be
> tempted to insert a return of an arbitrary value "because it'll never be
> executed anyway".
> 
> This is the point I have consistently failed to make clear.

You got me.

Now I see it your way!
March 10, 2005
On Tue, 08 Mar 2005 12:05:09 +0100, xs0 <xs0@xs0.com> wrote:
> I'm not trying to be hostile, perhaps that is the result of my limited knowledge of english or something. But since you asked why you [annoy] me (in random order):
>
> - you ignore half of what other people write (e.g. I said something about CPU cache and how checking a flag could actually be faster, you just said "no, it's slower" without even considering _why_ I said checking a flag _could_ be faster)

The reason I didn't address the cache comment is because you missunderstood what I was trying to say, here is the thread:

<quote>
>>>>>> Well, then you can implement the aspect in a way that supports this.The  point is that the aspect code still gets executed all the time,even  though it can obviously do nothing if it is written that way.That does  not require two different classes.
>>>>>
>>>>> This is less efficient.
>>>>
>>>> How? I'd say it's faster to check a var than to execute completelydifferent code, because modern CPUs rely on cache so heavily, its farmore efficient to stay within cache than to avoid two CPU instructions.That is even more true in the case you're arguing (tracking a singleinstance), because the branch predictor will be right most of the time,avoiding even the potential cost of conditional jump (i.e. pipeline flush).
>>>
>>> It's not "execute completely different code", it's "execute no code at all"as in, the class without the aspect applied. So, it's faster.
>>
>> It's not no code at all.. if you apply an aspect to a method/function (andall code is in a method or a function), there are then two functions, theoriginal, and the original+aspect (and in the case the original does nothing,
>> why is it there?)
>
> Correct. If I don't need the "original+aspect" then being forced to use it, butskip it with a variable will be slower than "the original" without aspect applied.
</quote>

caching didn't apply to what I was saying.


> - when you misread something, you'll tag the other person as basically stupid without considering that you may be the one that made the mistake (e.g. in the thread on stable functions you misunderstood the comment on caching and suggested that the poster is proposing some bizarre global caching scheme)

FYI: I don't "tag" people as anything.

In that particular example the OP suggested a compile time optimisation, I ammended their definition of "stable functions" to include "known at compile time", they agreed.

<quote "martin">
>> Instead I suggest the concept of "stable functions". A class of functions
>> (and methods), that have no side effects and are guaranteed to generatethe same result given the same input
> known at compile time.

Exactly.
</quote>

Ilya disagreed "No need to limit it to compile-time known arguments.  ... " we discussed it, Sebastian joined in, I am still unclear exactly what he was suggesting. I would still like to know.


> - you cling to your ideas like it was a matter of life and death (e.g. in the opCast thread, even after several people, including me, said that using cast to select a method is ridiculous, you still went on and on how it is something natural; if it was the natural thing to do, there would obviously be no disagreement)

I will argue my own point of view up and until I convice you, you convince me, or we agree to go our seperate ways. It appears (to me) you do the same thing.

Yes, some people disagreed, you, and brad. Some people also agreed.

<quote "georg">
If we had overloading on return type, then in some
situations we'd want some way to choose which return
type to use. Using cast for this would seem natural.
</quote>

<quote "derek">
To counter this, one could make the rule that every call to a function must
either assign the result or indicate to the compiler which return type is
being ignored/required. This would help make programs more robust and help
readers know the coder's intentions better.

For example...
   cast(int)foo('x');  // Call the 'int' version and ignore the result.
   bar( cast(real)foo('y') ); // Call the 'real' version of foo and bar.
</quote>


> - you use a type of argument, but don't allow others to use that same type of argument (e.g., again in the opCast thread, the whole Brad is with me/Greg is with you thing)

That was a bad comment on my part, "taking sides" should not happen in a NG.
Sorry.


> - you never admit you're wrong (e.g. I said "if you want to log all calls, you can't also want to not log some calls", and you said you can; that's simply a logical fallacy, but you failed to admit even something that simple)

You missrepresented my argument (and you're doing it again), that is logical fallacy.

<quote "regan">
The very reason I don't like it. What if I want to use the old class and  the new class in the same application?
</quote>

To which you replied with a very long paragraph, which I won't quote in entirety, the part in question read:
<quote>
Like, if you want to log all calls to some method (or whatever), you can't also want to not log some of them
</quote>

You brought up logging all calls, not I. You missunderstood my comment.


> - even though you're quick to point out that other people use their preference as arguments, _your_ own preference is often the only argument you have (e.g. "I'm saying I prefer my concept to yours" without any argumentation; if you do manage to say something like "I prefer it because it is more flexible", you totally fail to argument that it is indeed more flexible, at least in my opinion)

The entire thread was my argument as to why I preferred my idea.

As it turned out, our ideas were almost functionally identical. But, they were different and I preferred the tradeoffs of my idea to the tradeoffs of yours. Those statements were reflections of that fact.


> - you fail to provide counterarguments in most cases, and just say something arbitrary. Our typical conversation goes like
> me: A
> you: B
> me: ~B, because C, D, E
> you: B
> me: ~B, because D, F, G
> you: B, isn't it obvious?
> this thread was also going this exact same way, so I decided to drop it, because I don't feel any of us is gaining something from it.

Please post an example of this. I don't believe it has ever occurred as I intentionally make a point to address every argument someone makes (the exception being when I got "fed up" halfway thru a reply to you).


> - you take things out of context way too often (e.g. "the whole world disagrees with you"; the point of that sentence was that you fail to counterargue and I exagerated a bit to make that point clearer;

You should have said "you fail to counterargue". Instead your statement could not be prooven and was simply inflamatory.

> you sliced it and took it out of context (which naturally completely changes its meaning) and again failed to counterargue (which you could do by showing that you do indeed counterargue))

What is the point in arguing with a statement which cannot be proven?


> There you have it, it got much longer than I planned, but I tried to argument that you do indeed do those things that bother me :)

I honestly believe that a lot of the 'problems' we seem to have with each other stem from missunderstanding.

You've stated that you have a "limited knowledge of english", so I will take extra care to be as clear as possible in future discussions.

For the record I can only speak english, I have respect for anyone who is multi-lingual.

Regan
March 10, 2005
I'll reply to OT stuff via e-mail later, as it probably is of no interest to anybody but us..


> The reason I didn't address the cache comment is because you  missunderstood what I was trying to say, here is the thread:
> 
> [snip quotes]
> 
> caching didn't apply to what I was saying.

Yes it did. You're suggesting that there exist two methods (actually, two entire classes), one without the aspect code, the other one with aspect code. Code also occupies cache. If the compiled original method is 1000 bytes long, and the new method is 1200 bytes, they take 2200 bytes of cache. If you just have one version that checks a flag, it's like 1210 bytes (including the flag). Considering that L1 cache is usually really small (like 16K for code and 16K for data), that can be a significant difference. I'm not saying it's always the case that it's better to check flags than to have two methods, I'm just saying it can be faster in some cases. Not to even mention how much more flexible a flag is than conditionally doing something with two separate classes..

If you test this with really simple/short functions (I did test), flag checking is indeed slower, because you'll have everything in cache anyway (although even such a simple thing as "if (flag) a++; else a+=2" is only like 2% slower compared to having two methods that "a++" or "a+=2"), but in "real" code, flag checking may be faster.

Efficiency (as in speed) in modern systems is really not that simple anymore. I read an article the other day on real-time ray tracing, and the two things that provided the biggest speed gains were using SSE instructions (because they can work on more than one data at a time) and a cache-friendly layout of data structures.

It was faster to unconditionally do 4 calculations than to conditionally do one. It was faster to convert everything to triangles so that only one case exists, than to handle other primitives (even though a single sphere became like 50 triangles). It was faster to just compute some stuff than to have a check if it is even needed and only then compute it (even though the check was far simpler and the total executed instructions count would be lower, the time that took was longer). These cases all go against the conventional wisdom that the fastest code is the one that doesn't get executed (that is still true, of course, just not 100% of time).


xs0