October 27, 2017
On Wednesday, 25 October 2017 at 22:19:23 UTC, Walter Bright wrote:
> for core D devs.
>
> "How Non-Member Functions Improve Encapsulation" by Scott Meyers
>
> http://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197
>
> Note that I'm as guilty as anyone for not understanding or following these guidelines. I expect we can do much better.

The irony is that D’s private is “public to anyone in this module”. With that in mind free function or not you don’t get anything.

Splitting it off to another module is clunky and I’d use it only for functions that may work for different types (template).




October 27, 2017
On 2017-10-26 12:42, Kagamin wrote:

> You mean non-member functions are preferred? I encountered this more from performance point: especially in case of small structures like Point it would be more beneficial to pass them by value than by reference, which can be achieved by extension methods, but then you need to import the respective module to have those extension methods available.
Adding methods to a struct will not increase its size.

-- 
/Jacob Carlborg
October 27, 2017
On Thursday, 26 October 2017 at 12:19:33 UTC, Steven Schveighoffer wrote:
> D's lookup rules fail miserably when it comes to templates:
>
> mod1.d:
>
> auto callFoo(T)(T t)
> {
>   return t.foo;
> }
>
> mod2.d:
>
> struct S
> {
>    int x;
> }
>
> int foo(S s) { return s.x * 5; }
>
> void main()
> {
>    auto s = S(1);
>    assert(s.foo == 5);
>    assert(s.callFoo == 5); // can't compile
> }
>
> Would be nice to have a way around this. Not sure what it would look like.

Assuming you don't want to change the original struct, this can be worked around by making a wrapper type using alias this. I think that's logical because you have to be explicit about which foreign functions you want the imported algorithm to see. There would be a function hijacking problem otherwise.

What is the catch here, is that alias this won't solve cases where the free function takes a reference to the wrapped type or returns it.
October 27, 2017
On Thursday, 26 October 2017 at 23:29:24 UTC, Walter Bright wrote:
> The point is that functions that do not need access to private fields should NOT be part of the class. Most of the discussion here is based on the idea that those functions should still be semantically part of the class, even if not physically. That idea should be revisited. Why should they be semantically part of the class?

Because it's functionality of the class. If it's not available, it will be reimplemented and duplicated. C++ doesn't have such problem, because in a way all imports are public there so you have no chance to separate a function from type.
October 27, 2017
On Friday, 27 October 2017 at 07:36:45 UTC, Jacob Carlborg wrote:
> On 2017-10-26 12:42, Kagamin wrote:
>
>> You mean non-member functions are preferred? I encountered this more from performance point: especially in case of small structures like Point it would be more beneficial to pass them by value than by reference, which can be achieved by extension methods, but then you need to import the respective module to have those extension methods available.
> Adding methods to a struct will not increase its size.

Instance methods require this be passed by reference, which requires storage fiddling on the caller side. It's likely to disappear after inlining, but still.
October 27, 2017
On 2017-10-27 11:06, Kagamin wrote:

> Instance methods require this be passed by reference, which requires storage fiddling on the caller side. It's likely to disappear after inlining, but still.

Ah, right.

-- 
/Jacob Carlborg
October 29, 2017
I've noticed the benefits of writing non member functions in Python codebases. Say if you have a User model in a Django ORM, and you have a Thing model, and some operation on User and Thing. I've noticed that your code is almost always better if you write a non member function on User and Thing, instead of a member of User or Thing.

Often a function belongs to neither type. Instead the logic cuts across those two types. The key disadvantage I notice is ending up with very large and unreadable classes which poorly categorise business logic, when you could have been categorising functions in modules based on different business needs.
October 29, 2017
On Sunday, October 29, 2017 08:45:15 w0rp via Digitalmars-d wrote:
> I've noticed the benefits of writing non member functions in Python codebases. Say if you have a User model in a Django ORM, and you have a Thing model, and some operation on User and Thing. I've noticed that your code is almost always better if you write a non member function on User and Thing, instead of a member of User or Thing.

Yeah, making functions generic can be a big win. The bigger question is what to do when it doesn't really make sense to make the function generic, and it doesn't need access to the private members of the type that it would always be used with. In that case, it doesn't need to be a member function, but it could be.

- Jonathan M Davis

October 30, 2017
On Wed, Oct 25, 2017 at 03:19:23PM -0700, Walter Bright via Digitalmars-d wrote:
> for core D devs.
> 
> "How Non-Member Functions Improve Encapsulation" by Scott Meyers
> 
> http://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197
> 
> Note that I'm as guilty as anyone for not understanding or following these guidelines. I expect we can do much better.

Page 2 of this article is essentially another reason why UFCS in D totally rawkz.  In D, we can take Scott's advice *without* suffering from syntactic inconsistency between member and non-member functions:

	// C++:
	class C {
		public:
			int method();
		private: ...
	};

	int anotherMethod(C &c, ...);

	C c;
	c.method();
	anotherMethod(c);	// <-- syntactic inconsistency


	// D:
	class C {
		public int method();
		private: ...
	}
	int anotherMethod(C c, ...);

	C c;
	c.method();
	c.anotherMethod();	// <-- Uniform syntax FTW!

Arguably, this means in D encapsulation is even better than in C++: the user doesn't even have to care whether a function is a member or not. The same syntax does the Right Thing(tm).

Furthermore, if the class implementation changes in a drastic way that makes it possible to make a current member function a non-member, we can do it in D without needing to touch any client code at all!


T

-- 
Кто везде - тот нигде.
October 30, 2017
On 10/30/17 1:40 PM, H. S. Teoh wrote:

> Page 2 of this article is essentially another reason why UFCS in D
> totally rawkz.  In D, we can take Scott's advice *without* suffering
> from syntactic inconsistency between member and non-member functions:

You're missing a key piece here, in that anotherMethod does not ensure the encapsulation of C. It can call 'method' just fine.

Yes, it's great that UFCS can help with encapsulation via external methods, but it's going to be difficult to prevent access to private data, you have to use 2 modules. Not a very clean solution IMO.

-Steve