Without arguing the case whether pike should get official pointers (as opposed to reference types that kind-of become like pointers), why use pointer(string)? What's wrong with
void method(string &var) {}
? It'd be using the C++ reference syntax rather. Even traditional C-syntax would work:
void method(string *var) {}
The use of type* as an alias for array(type) has been deprecated long enough to be repurposed (with the possible problem that backwards compatibility might become tricky).
Overall, do we need "pointer" syntax or is it enough to be able to pass all variables by reference? By reference I mean the C++ "reference" idea, such as:
void getXY(int pos, int &x, int& y) { x = (pos>>8)&0xff; y = pos&0xff; }
... int my_x, my_y; getXY(my_pos, my_x, my_y);
The benefit is that you don't need to mix in pointer syntax and all the issues related to that. The drawback is that it's less clear from the calling method point of view. Other drawbacks in terms of the implementaiton I won't comment on since I'm not qualified to do so.
/ David Hedbor
Previous text:
2003-04-16 00:55: Subject: Pointers/lvalues
Grubba and I started talking a bit about adding lvalues as an explicit data type in Pike. I'll jot down what we arrived at for the record (well, some of it are later thoughts by me):
An lvalue is a pointer to a variable that allows the variable to be changed (as opposed to a pointer to a function). Generic variable pointers could be implemented by adding two new svalue types: Pointer to variable in object and pointer to variable in frame (if programs get "proper" static variables in some future they would get this too).
The frame case is used for pointers to local variables in functions. Refcounting in frames is already implemented for the sake of nested functions, so returning a pointer to a local variable shouldn't be a problem.
The solution with special pointer svalue types is better than the double svalue (the thing to index followed by the index) approach currently used internally for lvalues for two reasons: Firstly the index operation is performed when the pointer is created instead of when it's dereferenced, which trigs errors closer to the source. Secondly it would avoid odd effects in various functions that doesn't expect variable pointers.
Pointers to values in arrays, mappings and multisets don't need new svalue types since their iterator objects can be used then (more on that later).
Variable pointers would be used like in C. Silly example:
int append_to_buf (Stdio.File f, pointer(string) buf) { string in = f->read(); *buf += in; return sizeof (in); }
Some new operator lfuns would be needed:
&foo => Get the pointer to foo; calls `& in foo. &foo->bar => Get the pointer to foo->bar; calls `&->("bar") in foo. &foo[bar] => Ditto for []; calls `&[](bar) in foo.
`& and ``& already exist, so the first operator above would actually become ```& with the current naming system. We're however contemplating a new system with more verbose lfun names; `&this for the new operator, `this&_ for `&, and `_&this for ``&.
The similarity between pointers and iterators is obvious, so iterators should be able to act as pointers. To accomplish that an lfun corresponding to the dereferencing * operator is necessary:
*foo => Gets the value the pointer points to; calls `*this in foo.
It's also interesting to have an lfun that returns a pointer svalue so that it can be used in an lvalue context. An example:
for (pointer ptr = &my_obj[0]; *ptr; ptr++) *ptr = reverse (*ptr); ^^^^ Here `&*this would be called to produce a pointer value which is used as lvalue.
If `&*this returns an object instead of a basic pointer svalue, `&*this would presumably be tried again, which would make it possible to produce a infinite loop if `&*this should be silly enough to return the iterator itself. A simple check for that might be a good idea.
To be symmetric with `[]= and `->=, one would add a `*this=_ instead of `&*this. I do however like `&*this better since it's then possible to do e.g.
*ptr += ({17});
with an efficient `+= operation without the need for a special `*this+=_.
A `&*this lfun makes it possible to try it in any expression where no better suited lfun is available:
foo + bar => Try: foo->`+(bar) Then: bar->``+(foo) Then: *(foo->`&*this) + bar Then: foo + *(bar->`&*this)
That could be handy when implementing e.g. "smart" strings like Locale.DeferredLocale. I don't know yet if it overall is a good idea or not, though. It's clearly not a good idea in simple assignments and arbitrary function calls.
/ Martin Stjernholm, Roxen IS