September 10, 2004
Matthew wrote:
> But what about when you want to traverse a range from two arbitrary integers, with arbitrary step? i.e. when you don't
> know, a priori, whether you need a ++, --, +=, or -=?

Each is trivially capable of being written in terms of +=.

> There are other advantages, e.g. generics, to anyone caring to delve into the subject
<snip top of upside-down reply>

Not sure what you mean....

Stewart.

-- 
My e-mail is valid but not my primary mailbox.  Please keep replies on the 'group where everyone may benefit.
September 10, 2004
>Joey, Ben was talking about /static/ opCall() - something of limited use.
>Your example is a /non-static/ opCall() - something profoundly useful.
>
>There really should be a FAQ about this distinction, as s-o  m-a-n-y times we see this mistake cropping up.
>
>Arcane Jill
>
>

D in general needs a better home, sometimes I really can't find what I'm looking for. Anyway, what 'is' the difference other than other differences with static? I could figure a use for it, like, counting references from instances of objects so you may use them anonymously (whatever you spell it, i'm not native ;)).

// I so hate this newposting form, they don't do spaces
class Foo {
public:
static Foo[uint] references;
static uint cycle;
uint self;
this() {
self = cycle;
references[cycle] = this;
++cycle;
}
static Foo opCall(int ref)
in {
assert(ref >= references.length);
}
body {
return references[ref];
}
void bar() {
printf("Hello :) %i\n", self);
}
}

void anonFunction() {
Foo(0).bar();
}

void main() {
new Foo; new Foo;
anonFunction();
}

I have something similar in my dragon stl, it counts spawn references in hashes which you can later cast back to their former type. There's also a selecter class so you can use delegates to select certain instances with certain properties set to value X (select LIST where DELEGATE is TRUE). But that's really out of the question now :P.


September 10, 2004
In article <chruhb$1ao8$1@digitaldaemon.com>, Joey Peters says...

>Anyway, what 'is' the difference other than other differences with static?

Well, as I'm sure you know, non-static functions have access to a "this" pointer, and therefore have access to a "state", maintained by a class instance. static functions, on the other hand, cannot maintain a state - except by using global variables (which includes static member variables).

So static opCall() can do nothing that couldn't otherwise have been done by an ordinary function. In fact, there is almost no diffence between:

#    class F
#    {
#        static int opCall() { /*whatever*/ }
#    }

and

#    int f( /*whatever*/ }

apart from the case of the function name. Both can access private variables declared in the same module. That said, many people use static opCall() to mimic a constructor (since currently structs don't have constructors). The reasoning being that the calling syntax is the same (apart from the word "new").



>I could figure a use for it, like, counting references from instances of objects

Yes, that's true. However, an ordinary function could do exactly the same job. All that static opCall() gives you is a function whose name has an uppercase first letter.


>// I so hate this newposting form, they don't do spaces

That's why I write code examples
#    like this



>static Foo opCall(int ref)
>in {
>assert(ref >= references.length);
>}
>body {
>return references[ref];
>}

Sure, but there are many alternatives you could have used to do the same thing, for example:

#    Foo getFoo(int n); // 1
#
#    class Foo
#    {
#        static Foo opIndex[int n];  // 2 (This is an array lookup, after all)
#        static Foo getReference(int n); // 3
#
#        // or simply
#        static Foo[uint] references; // 4 -- access the array directly
#    }

Of course there's nothing "wrong" with your approach. It's just unexpected, which could be a maintainance problem for other coders.



>I have something similar in my dragon stl, it counts spawn references in hashes which you can later cast back to their former type. There's also a selecter class so you can use delegates to select certain instances with certain properties set to value X (select LIST where DELEGATE is TRUE).

Those sound like very good ideas, and I see absolutely nothing wrong with any of them, though I do question whether static opCall() is the most appropriate dispatch mechanism for them.

When Ben said that he tended not to use static opCall() these days, a few posts back, I believe he meant that the only use he had for it previously was as a fake constructor, and that he now believes even that use to be not that useful.

Arcane Jill


September 10, 2004
>>static Foo opCall(int ref)
>>in {
>>assert(ref >= references.length);
>>}
>>body {
>>return references[ref];
>>}
>
>Sure, but there are many alternatives you could have used to do the same thing, for example:
>
>#    Foo getFoo(int n); // 1
>#
>#    class Foo
>#    {
>#        static Foo opIndex[int n];  // 2 (This is an array lookup, after all)
>#        static Foo getReference(int n); // 3
>#
>#        // or simply
>#        static Foo[uint] references; // 4 -- access the array directly
>#    }
>
>Of course there's nothing "wrong" with your approach. It's just unexpected, which could be a maintainance problem for other coders.

I don't overload opCall yet, there is a reason for that. Though, there is also a reason to not put it in the (global) namespace as a normal function, but rather as a static function of a class (more about that later, the problem is when you start grouping instances).

>>I have something similar in my dragon stl, it counts spawn references in hashes which you can later cast back to their former type. There's also a selecter class so you can use delegates to select certain instances with certain properties set to value X (select LIST where DELEGATE is TRUE).
>
>Those sound like very good ideas, and I see absolutely nothing wrong with any of them, though I do question whether static opCall() is the most appropriate dispatch mechanism for them.

Not yet, I want to keep opCall for some form of a special query object, for now it is something that looks sort of hackish but correct:

Foo.select.as!(Foo).by(&delegate).dragon stl arrayfunctions...

select is static here, and it embeds the reference counting mechanism as a simple object, which, as you see, makes sense in an english form ;), 'as' is primarely there for if you use inheritances, that it doesn't lose it's functionality. I tried to mixin as!(Foo) so you could Foo.select.by(&...) but that just looped the compiler (for whatever reason). I'm working on a better interface though, and static opCalls might prove useful not typing out long statements such as:

Fruit.select.as!(Fruit).by(&startWithP).del() // deletes fruit instances
starting with P

I'd imagine you sometimes want to use this 'query' more often than just once, or want them to change dynamically. So eitherway, I could make it so it does:

Fruit.select(queryobject).del()

and that would then again beat the sense out of a static opCall, since a non static version is embedded in select, and select itself is a static member.

However, what if I want to group spawns? Imagine I'd be calling a query from a class Animal, and it would contain all <<put super large integer here>> animals in the whole planet. If I'd apply a query on that, it would iterate a gigantic list of references. So instead, I may want to make an enum, AnimalType, to further specify what I'm looking for, logically:

Animals(Birds).select(queryobject).array function;

And to construct them, you would have to:

new Animal(birdtype, ...)

In a more complex form of hash. Here, mixing in constructors would also prove useful, but I think that when I get to writing this functionality for the stl, I'd probably end up doing something like:

Animal.setType(Bird);
// create birds

Anyway, that's not relevant for now, what is relevant is that static opCalls from a very far perspective would make some sense, and there is no real reason to destroy them from being overloadable except for teaching stupid programmers a stupid lesson (d0nt h4x0r ur c0d3).

>When Ben said that he tended not to use static opCall() these days, a few posts back, I believe he meant that the only use he had for it previously was as a fake constructor, and that he now believes even that use to be not that useful.

as in

Foo a = Foo()?

I'd figure that could be useful, but like Ben said, not 'that' useful.

#// Example where it would be useful
#class Point {
#public:
# int x, int y;
# this(int x_, int y_) {
#  x = x_;
#  y = y_;
# }
# static Point opCall(int x, int y) {
#  return new Point(x, y);
# }
#}
#DrawLine(Point(5, 5), Point(10, 10));


>Arcane Jill
>
>


1 2 3
Next ›   Last »