January 30, 2013
On Wednesday, 30 January 2013 at 17:35:25 UTC, Dmitry Olshansky wrote:
>> 2) How much code
>> breakage?
>
> A lot + subtly wasting memory.

I still have to read your other comments, but the issue of wasting memory has already been addressed by suggesting that the compiler detect that absence of any actual data in the struct and prohibit taking its address or referring to "this" except perhaps in the case of "alias someFunction this" to allow it to call that function transparently. It would not give the function a pointer or anything, the goal being to truly harness the power of struct's semantics without paying a price in performance of any kind.
January 30, 2013
On Wednesday, 30 January 2013 at 17:42:48 UTC, TommiT wrote:
> On Wednesday, 30 January 2013 at 17:02:44 UTC, Zach the Mystic wrote:
>> [..] 1) How hard to implement structs nested in structs to mimic ones nested in functions?
>
> Given:
>
> struct Outer {
>     struct Inner {
>         int n1;
>     }
>     int n2;
> }
>
> Outer.sizeof should be equal to 2 * int.sizeof, because there's no point in introducing any overhead here. Whereas structs inside functions do their magic by having an implicit pointer, which increases their size. I don't think we want to introduce any memory overhead with something as insignificant as properties.

See my first answer to Dmitri's post. Most properties will hold no data of their own, and the compiler could detect this, thus eliminating the need for the pointer at runtime.
January 30, 2013
On Wednesday, 30 January 2013 at 17:35:25 UTC, Dmitry Olshansky wrote:
>> Okay, cool. Two questions remain: 1) How hard to implement structs
>> nested in structs to mimic ones nested in functions?
>
>
> IMO if property is to be implemented in the library it has to include the field itself. (And I suspect properties should enjoy compiler support).
>
> Then something like:
>
> struct A{
> 	Property!(int, filter, getter) prop;
> private:
> 	void func()
> 	{
> 		...
> 		prop.raw = xxx; //direct write
> 		prop = yyy; //goes through setter
> 	}
> }
>
> where .raw is the field itself and there must be a way to let only struct itself have access to it. I have one method to get this but I don't like it - put this in each module:
>
> mixin PropertyForModule!(my_module);
>
> introducing a Property template in this module, with private .raw accessible thusly only in this module.
>
> Getter is then just any function that maps T => T, with x => x  by default so can be omitted.
>
> Filter is something new but in essence it works like the following setter:
>
> void setter(T)(ref T val, T newVal)
> {
> 	val =  filter(newVal); //filter may through
> }
>
> It's a bit more restrictive though so feel free to destroy.

Does my suggestion about the compiler detecting a struct with no data warm you up a bit to properties as structs? If so, there is really very little need for ANY library support. Strangely, implementing struct-nested structs with actual data could be a significantly harder task than implementing them with no data. No extra pointer need be created.

I'll try to summarize the changes required. The first two are necessary. The third is for aesthetic reasons, but as in the case of lambda functions that could make a huge difference.

1. Have non-static struct-nested structs be able to refer to their parent's data. With no-data structs, I suspect this will be easy, and it's actually the primary intended usage, which makes only the corner case tricky, where new pointers must be added, etc.

2. Add opGet to the compiler's list of overloads. It is simply opCall but with parens banned instead of mandated.

3. Enable Highlander structs so that defining a property is as easy as define a new-style lamba:
struct __fooHidden {}
__fooHidden foo;

simply becomes:

foo struct {}
January 30, 2013
On 01/30/2013 05:39 PM, TommiT wrote:
> ...
>
> "Empty parentheses may be omitted when calling functions with a
> user-defined name."
> ...

This is subject to 4 exceptions:

auto foo() { ... }

1. &foo           // get function pointer or delegate
2. alias x = foo; // alias to function (same for alias params)
3. typeof(foo)    // type of function
4. foo()          // function called
January 30, 2013
30-Jan-2013 22:05, Zach the Mystic пишет:
> On Wednesday, 30 January 2013 at 17:35:25 UTC, Dmitry Olshansky wrote:
>>> Okay, cool. Two questions remain: 1) How hard to implement structs
>>> nested in structs to mimic ones nested in functions?
>>
>>
>> IMO if property is to be implemented in the library it has to include
>> the field itself. (And I suspect properties should enjoy compiler
>> support).
>>
>> Then something like:
>>
>> struct A{
>>     Property!(int, filter, getter) prop;
>> private:
>>     void func()
>>     {
>>         ...
>>         prop.raw = xxx; //direct write
>>         prop = yyy; //goes through setter
>>     }
>> }
>>
>> where .raw is the field itself and there must be a way to let only
>> struct itself have access to it. I have one method to get this but I
>> don't like it - put this in each module:
>>
>> mixin PropertyForModule!(my_module);
>>
>> introducing a Property template in this module, with private .raw
>> accessible thusly only in this module.
>>
>> Getter is then just any function that maps T => T, with x => x by
>> default so can be omitted.
>>
>> Filter is something new but in essence it works like the following
>> setter:
>>
>> void setter(T)(ref T val, T newVal)
>> {
>>     val =  filter(newVal); //filter may through
>> }
>>
>> It's a bit more restrictive though so feel free to destroy.
>
> Does my suggestion about the compiler detecting a struct with no data
> warm you up a bit to properties as structs? If so, there is really very
> little need for ANY library support. Strangely, implementing
> struct-nested structs with actual data could be a significantly harder
> task than implementing them with no data. No extra pointer need be created.
>
I have one key problem - the hidden pointer detail.
In other words how should it find the instance of the outer struct to to access it?

struct A{
	int a;
	struct B{
		void foo(){ a = 42; }
	}	
	B b;
}

A a;
a.b.foo(); //how that b is supposed to know it's outer struct without the hidden pointer?

auto x = a.b;
x.foo();// and now what?


> I'll try to summarize the changes required. The first two are necessary.
> The third is for aesthetic reasons, but as in the case of lambda
> functions that could make a huge difference.
>
> 1. Have non-static struct-nested structs be able to refer to their
> parent's data. With no-data structs, I suspect this will be easy, and
> it's actually the primary intended usage, which makes only the corner
> case tricky, where new pointers must be added, etc.
>
> 2. Add opGet to the compiler's list of overloads. It is simply opCall
> but with parens banned instead of mandated.
>
> 3. Enable Highlander structs so that defining a property is as easy as
> define a new-style lamba:
> struct __fooHidden {}
> __fooHidden foo;
>
> simply becomes:
>
> foo struct {}


-- 
Dmitry Olshansky
January 30, 2013
On Wednesday, 30 January 2013 at 18:06:47 UTC, Timon Gehr wrote:
> This is subject to 4 exceptions:
>
> auto foo() { ... }
>
> 1. &foo           // get function pointer or delegate
> 2. alias x = foo; // alias to function (same for alias params)
> 3. typeof(foo)    // type of function
> 4. foo()          // function called

I'd count only 1. and 3. as exceptions to the rule. I don't see how is 4. is an exception - it's just a regular function call without omitting the parens. I'm not sure if it's possible to create an alias to an expression like:

alias x = foo;

...but if it's possible, then I think it's fine to allow it. It will work as if x were the expression it aliases, and would work like:

int value = x; // this is same as writing int value = foo;

...given that foo() returns something that's convertible to int.
January 30, 2013
On Wednesday, 30 January 2013 at 18:06:47 UTC, Timon Gehr wrote:
> 2. alias x = foo; // alias to function (same for alias params)

Oh, yeah, now I see what you mean. It would be impossible to alias the function name if foo is considered a function call in that case.

Would it be possible that an alias would have multiple interpretations, depending on the context where it's used? E.g.

int foo() {...}

alias x = foo;

int value = x;

auto func = &x; // function pointer

Or is that too weird.
January 30, 2013
I kind of like this strange love child of a namespace and a variable that you're talking about. But I wouldn't call it a struct. I wouldn't make empty structs be these weird special cases which behave completely differently. Instead, I'd introduce a new keyword for this... thing.
January 30, 2013
On 01/30/2013 07:49 PM, TommiT wrote:
> On Wednesday, 30 January 2013 at 18:06:47 UTC, Timon Gehr wrote:
>> This is subject to 4 exceptions:
>>
>> auto foo() { ... }
>>
>> 1. &foo           // get function pointer or delegate
>> 2. alias x = foo; // alias to function (same for alias params)
>> 3. typeof(foo)    // type of function
>> 4. foo()          // function called
>
> I'd count only 1. and 3. as exceptions to the rule.

They are all exceptions that an implementation does need to consider.

> I don't see how is
> 4. is an exception - it's just a regular function call without omitting
> the parens.

It is an exception because foo means call foo, and foo() means call foo, and not call foo and then the result of foo.

> I'm not sure if it's possible to create an alias to an
> expression like:
>
> alias x = foo;
>
> ...but if it's possible,

That is mostly a compiler implementation detail. (Create a hidden enum symbol vs store the value in the alias directly.) Expressions may bind to template alias params.

I think rule 2. should probably be replaced/extended by:

2. Foo!foo // direct template argument

template Bar(int x) { ... }
int foo(){ ... }

mixin Bar!foo; // error

(Alternatively DMD may be declared to be in error here.)


> then I think it's fine to allow it. It will
> work as if x were the expression it aliases,
> ...

That is how it works for identifiers.
January 30, 2013
On 01/30/2013 07:55 PM, TommiT wrote:
> On Wednesday, 30 January 2013 at 18:06:47 UTC, Timon Gehr wrote:
>> 2. alias x = foo; // alias to function (same for alias params)
>
> Oh, yeah, now I see what you mean. It would be impossible to alias the
> function name if foo is considered a function call in that case.
>
> Would it be possible that an alias would have multiple interpretations,
> depending on the context where it's used? E.g.
>
> int foo() {...}
>
> alias x = foo;
>
> int value = x;
>
> auto func = &x; // function pointer
>
> Or is that too weird.

The above code is equivalent to

int value = foo;
auto func = &foo;

So I do not see what could be considered weird.