digitalmars.D.learn - Function template declaration mystery...
- =?iso-8859-1?Q?Robert_M._M=FCnch?= (22/22) Feb 28 2018 Hi, I'm lost reading some code:
- TheFlyingFiddle (12/31) Feb 28 2018 Testing this with:
- =?iso-8859-1?Q?Robert_M._M=FCnch?= (8/25) Feb 28 2018 Well, I stripped things trying to the core of where I'm struggeling.
- H. S. Teoh (21/45) Feb 28 2018 Basically, the `alias f` is a catch-all template parameter that can
- =?iso-8859-1?Q?Robert_M._M=FCnch?= (29/63) Feb 28 2018 Aha... ok that makes it a bit more clear. So, if I have:
- Steven Schveighoffer (11/38) Feb 28 2018 unaryFun is a template that returns a callable item. It could be a
- =?iso-8859-1?Q?Robert_M._M=FCnch?= (18/29) Feb 28 2018 As long as it's a function, makes sense.
- H. S. Teoh (18/21) Feb 28 2018 [...]
- Steven Schveighoffer (19/36) Mar 01 2018 It means that it simply becomes the alias you passed in. It means,
- =?iso-8859-1?Q?Robert_M._M=FCnch?= (17/31) Mar 01 2018 Yes, AFAIU this can be kept around for reference. Seems to be intended
Hi, I'm lost reading some code: A a; auto do(alias f, A)(auto ref A _a){ alias fun = unaryFun!f; return ... ... } How is this alias stuff working? I mean what's the type of f? Is it an anonymous function which then gets checked to be unary? How is it recognized in the code using the function template? This function can be called with code like this: a.do((myType) {...myCode...}); do(a, (myType) {...myCode...}); What's wondering me here is that the template function only has one paraemter (_a) but I somehow can get my myCode into it. But the code looks like a parameter to me. So why isn't it like: auto do(alias f, A)(auto ref A _a, ??? myCode){... I'm a bit confused. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Feb 28 2018
On Wednesday, 28 February 2018 at 17:47:22 UTC, Robert M. Münch wrote:Hi, I'm lost reading some code: A a; auto do(alias f, A)(auto ref A _a){ alias fun = unaryFun!f; return ... ... } How is this alias stuff working? I mean what's the type of f? Is it an anonymous function which then gets checked to be unary? How is it recognized in the code using the function template? This function can be called with code like this: a.do((myType) {...myCode...}); do(a, (myType) {...myCode...}); What's wondering me here is that the template function only has one paraemter (_a) but I somehow can get my myCode into it. But the code looks like a parameter to me. So why isn't it like: auto do(alias f, A)(auto ref A _a, ??? myCode){... I'm a bit confused.Testing this with: auto foo(alias f, A)(auto ref A a) { return f(a); } I can call foo either like this: foo!(x => x + x)(1); or 1.foo!(x => x + x); but these will give errors foo(1, x => x + x); //Error 1.foo(x => x + x); // Error I don't see how you can get that kind of behavior...
Feb 28 2018
On 2018-02-28 18:01:50 +0000, TheFlyingFiddle said:Testing this with: auto foo(alias f, A)(auto ref A a) { return f(a); } I can call foo either like this: foo!(x => x + x)(1); or 1.foo!(x => x + x); but these will give errors foo(1, x => x + x); //Error 1.foo(x => x + x); // Error I don't see how you can get that kind of behavior...Well, I stripped things trying to the core of where I'm struggeling. The 'a' in my code is a static and of course there is much more around going on. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Feb 28 2018
On Wed, Feb 28, 2018 at 06:47:22PM +0100, Robert M. Münch via Digitalmars-d-learn wrote:Hi, I'm lost reading some code: A a; auto do(alias f, A)(auto ref A _a){ alias fun = unaryFun!f; return ... ... } How is this alias stuff working? I mean what's the type of f? Is it an anonymous function which then gets checked to be unary? How is it recognized in the code using the function template?Basically, the `alias f` is a catch-all template parameter that can bind to basically anything that has a symbol. It's typically used to bind to functions, delegates, and lambdas. Technically, the function is missing a sig constraint that verifies that f is in fact a unary function. So it will fail to compile if you pass something other than a unary function in.This function can be called with code like this: a.do((myType) {...myCode...});Are you sure the function name is 'do'? Because that's a keyword, and I don't think it's a valid identifier.do(a, (myType) {...myCode...});Are you sure this actually works? Is there another overload that takes a different parameter? The overload with `alias f`, AFAIK, can only be called with a compile-time parameter, like this: foo!((myType) { ... })(a); // or: a.foo!((myType) { ... });What's wondering me here is that the template function only has one paraemter (_a) but I somehow can get my myCode into it. But the code looks like a parameter to me. So why isn't it like: auto do(alias f, A)(auto ref A _a, ??? myCode){... I'm a bit confused.[...] Are you sure there isn't an overload that takes a second parameter? Doesn't look like this will compile, given the above declaration. T -- Food and laptops don't mix.
Feb 28 2018
On 2018-02-28 18:09:41 +0000, H. S. Teoh said:Basically, the `alias f` is a catch-all template parameter that can bind to basically anything that has a symbol. It's typically used to bind to functions, delegates, and lambdas.Aha... ok that makes it a bit more clear. So, if I have: auto myFunc(alias f1, alias f2, alias f3, A)(auto ref A _a){... I can use it like: a.myFunc( (myType) {...myCode...}, (myType) {...myCode...}, (myType) {...myCode...} ); and the aliases just continue to collect whatever comes inside the parameter specification. Does this idea hold? And it will give an error if there are to few/many aliases/parameters?Technically, the function is missing a sig constraintHow would that look like?that verifies thatf is in fact a unary function. So it will fail to compile if you pass something other than a unary function in.Ok, that's clearn.Well, it's just a bad picked word for my pseudo-code example... sorry.This function can be called with code like this: a.do((myType) {...myCode...});Are you sure the function name is 'do'? Because that's a keyword, and I don't think it's a valid identifier.I'm trying to better understand the D reactive framework rx: https://github.com/lempiji/rx This is the real code: osStream().filter!(wm => wm.message == WM_CREATE).doSubscribe((winMsg wm) {appInit();}); doSubscribe(osStream().filter!(wm => wm.message == WM_CREATE), (winMsg wm) {appInit();});do(a, (myType) {...myCode...});Are you sure this actually works? Is there another overload that takes a different parameter? The overload with `alias f`, AFAIK, can only be called with a compile-time parameter, like this: foo!((myType) { ... })(a); // or: a.foo!((myType) { ... });To be honste I'm not sure, I try to understand the code. It's the rx.oberservable file. Thanks a lot so far. -- Robert M. Münch http://www.saphirion.com smarter | better | fasterWhat's wondering me here is that the template function only has one paraemter (_a) but I somehow can get my myCode into it. But the code looks like a parameter to me. So why isn't it like: auto do(alias f, A)(auto ref A _a, ??? myCode){... I'm a bit confused.[...] Are you sure there isn't an overload that takes a second parameter? Doesn't look like this will compile, given the above declaration.
Feb 28 2018
On 2/28/18 12:47 PM, Robert M. Münch wrote:Hi, I'm lost reading some code: A a; auto do(alias f, A)(auto ref A _a){     alias fun = unaryFun!f;     return ...     ... } How is this alias stuff working? I mean what's the type of f? Is it an anonymous function which then gets checked to be unary? How is it recognized in the code using the function template?unaryFun is a template that returns a callable item. It could be a struct with an opCall, it could be a function template, it could be an alias to a real function, it could be a function pointer, delegate, etc. It also supports string lambdas, which existed before our current lambda syntax. i.e. alias f = unaryFun!"a - 5"; assert(f(10) == 5);This function can be called with code like this: a.do((myType) {...myCode...}); do(a, (myType) {...myCode...}); What's wondering me here is that the template function only has one paraemter (_a) but I somehow can get my myCode into it. But the code looks like a parameter to me. So why isn't it like: auto do(alias f, A)(auto ref A _a, ??? myCode){... I'm a bit confused.This question is a little harder to understand. Perhaps you have real code that shows what you are confused about? -Steve
Feb 28 2018
On 2018-02-28 18:25:37 +0000, Steven Schveighoffer said:unaryFun is a template that returns a callable item.That far I made it too :-)It could be a struct with an opCall, it could be a function template, it could be an alias to a real function, it could be a function pointer, delegate, etc.As long as it's a function, makes sense.It also supports string lambdas, which existed before our current lambda syntax. i.e. alias f = unaryFun!"a - 5"; assert(f(10) == 5);Yes, that's what the docs state. And I can imagin this. Bit this sentence is a bit hard to understand: "If fun is not a string, unaryFun aliases itself away to fun." Whatever this means.This question is a little harder to understand. Perhaps you have real code that shows what you are confused about?Ok, here it is: https://pastebin.com/tKACi488 See lines 81-84 for how I call it. And the problem I have is that doSubscribe returns "something" I'm not sure what I can do with. But if the scope ends, my subscription seems to be deleted and hence is not called when a message is coming in (see line: 118) And the question is now, what do I have to do that subscriptions that are done anywhere in the code survive the scope where they have been created? -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Feb 28 2018
On Wed, Feb 28, 2018 at 09:36:33PM +0100, Robert M. Münch via Digitalmars-d-learn wrote: [...]Yes, that's what the docs state. And I can imagin this. Bit this sentence is a bit hard to understand: "If fun is not a string, unaryFun aliases itself away to fun." Whatever this means.[...] That means no overhead is introduced if `fun` is not a string. When `fun` is a string, unaryFun needs to create a lambda that implements the operation described in the string, and this may involve a GC allocation. If `fun` is already a function, delegate, or lambda, though, it can be used directly, so there's no need to incur the overhead of creating yet another delegate to wrap around `fun`. The way this is done is by unaryFun defining itself to be an alias to `fun` in this case, so that all references to unaryFun with that argument essentially becomes references to `fun` instead. It's really an implementation detail of Phobos that users don't really need to know, but I suppose the intent was to reassure the user that no unnecessary overhead will be incurred where it's avoidable. T -- If Java had true garbage collection, most programs would delete themselves upon execution. -- Robert Sewell
Feb 28 2018
On 2/28/18 3:36 PM, Robert M. Münch wrote:Yes, that's what the docs state. And I can imagin this. Bit this sentence is a bit hard to understand: "If fun is not a string, unaryFun aliases itself away to fun." Whatever this means.It means that it simply becomes the alias you passed in. It means, there's no extra overhead in calling that unaryFun. But if you pass it something that needs some wrapping, it will do the wrapping.Looking through the rx package, it seems that it returns a class instance. That class implements the Disposable interface.This question is a little harder to understand. Perhaps you have real code that shows what you are confused about?Ok, here it is: https://pastebin.com/tKACi488 See lines 81-84 for how I call it. And the problem I have is that doSubscribe returns "something" I'm not sure what I can do with. But if the scope ends, my subscription seems to be deleted and hence is not called when a message is coming in (see line: 118)And the question is now, what do I have to do that subscriptions that are done anywhere in the code survive the scope where they have been created?I'm guessing from this observation that the class instance will unregister the subscription if it's destroyed, and because you aren't keeping a reference to that instance, the GC comes along and destroys it at some point. What I would recommend is you have to keep a reference to that class somewhere. Start out by just assigning it to a global. If that fixes your problem, I suggest you reach out to the author of rx, or read through the docs to see how you should properly use it, and where you need to keep that subscription (and for what purpose). If that *doesn't* fix your problem, then I'm not understanding what is happening, and you should definitely contact the rx author. File an issue in the github project. -Steve
Mar 01 2018
On 2018-03-01 12:01:19 +0000, Steven Schveighoffer said:Yes, AFAIU this can be kept around for reference. Seems to be intended for later access to the observers.Ok, here it is: https://pastebin.com/tKACi488 See lines 81-84 for how I call it. And the problem I have is that doSubscribe returns "something" I'm not sure what I can do with. But if the scope ends, my subscription seems to be deleted and hence is not called when a message is coming in (see line: 118)Looking through the rx package, it seems that it returns a class instance. That class implements the Disposable interface.I'm guessing from this observation that the class instance will unregister the subscription if it's destroyed, and because you aren't keeping a reference to that instance, the GC comes along and destroys it at some point.That was my guess too. But it's not the case. The unary is kept, hence I can just ignore the return value. What bite me here was a Windows effect. I subscribed my observer after the call to RegisterClass/CreateWindow. But Windows sometimes calls the window-procedure directly, without going through the message loop. And the messages I want to trigger on, are exactly ones that go directly. So, my code was never triggered because it just wasn't there. And after it was there, no more messages flow in. :-/ After rearranging things a bit it's working. But anyway, learned a lot while digging through the code and your feedback helped too. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Mar 01 2018