Re: Arrays of functions, function signatures and template instantiation

2013-04-30 Thread anonymous

On Tuesday, 30 April 2013 at 10:02:07 UTC, JR wrote:
[...]
For instance, is it possible to have MatrixWalker's F type to 
have a default value of a NOP void function(), have the 
innermost foreach loop check if the element is a function, and 
if so call it directly without needing FuncRunner at all?


Let's start by turning MatrixWalker into a function template 
(fixing the matrix template parameter on the way):

---
void walkMatrix(F,M: E[I][T],E,I,T)(F func, M matrix) {
/* those foreaches */
}
---

This way it can be called without explicitly instantiating the 
template:

---
walkMatrix(&runner, funcyMatrix);
---

Now add an overload for callable elements:
---
void walkMatrix(M: E[I][T],E,I,T)(M matrix) 
if(is(typeof(&FuncRunner!M.run))) {

walkMatrix(&FuncRunner!M.run, matrix);
}
---

A call:
---
walkMatrix(funcyMatrix);
---

Of course, FuncRunner is now only needed by that overload, so you 
could move its implementation in there.


Also, is there a clever approach to have MatrixWalker call its 
passed function variadically with only the arguments that its 
signature allows? As in;


-

import std.stdio;
import std.concurrency;

struct Event { /* ... type, sender, target, content and 
friends ... */ };


template MatrixWalker(F,E: E[I][T],I,T) {
   // note addition of Event below
   void applyFunc(ref Event evt, F func, E[I][T] matrix) {
   /* ... Inception foreach ... */
   func(evt, /* only the arguments of E, I and/or T that 
type F accepts */);

   }
}

const alias Blaawp MAJOR;
const alias Oorgle MINOR;
static void function(ref Event, MINOR)[MINOR][MAJOR] 
funcyMatrix;

// note no MAJOR in func sig

void populate() {
   /* ... */
}

void traverse() {
   sendMessageAdapter = void function(ref Event evt, Tid) {
   std.concurrency.send(tid, evt);
   };

   alias 
MatrixWalker!(typeof(&sendMessageAdapter),typeof(funkyMatrix)).applyFunc 
apply;


   writeln("Traversing funcy matrix");
   apply(&sendMessageAdapter, funkyMatrix);
}

void main(string[] args) {
   populate();
   traverse();
}

-

That sounds too good to be true, but it would make me warm and 
fuzzy inside if I didn't have to resort to keeping a dozen 
adapter/shim functions around.


I don't have a clever solution for that.


Re: Arrays of functions, function signatures and template instantiation

2013-04-30 Thread JR

On Tuesday, 30 April 2013 at 09:18:56 UTC, anonymous wrote:

On Tuesday, 30 April 2013 at 08:42:57 UTC, JR wrote:

On Tuesday, 30 April 2013 at 02:38:27 UTC, anonymous wrote:



Don't know what's going wrong there. It works for me:
http://dpaste.dzfl.pl/5c71f80e


My bad, I switched the wrong runner/&runner and in the wrong 
direction. Thanks!


Any other protips?

For instance, is it possible to have MatrixWalker's F type to 
have a default value of a NOP void function(), have the innermost 
foreach loop check if the element is a function, and if so call 
it directly without needing FuncRunner at all?


Also, is there a clever approach to have MatrixWalker call its 
passed function variadically with only the arguments that its 
signature allows? As in;


-

import std.stdio;
import std.concurrency;

struct Event { /* ... type, sender, target, content and friends 
... */ };


template MatrixWalker(F,E: E[I][T],I,T) {
// note addition of Event below
void applyFunc(ref Event evt, F func, E[I][T] matrix) {
/* ... Inception foreach ... */
func(evt, /* only the arguments of E, I and/or T that 
type F accepts */);

}
}

const alias Blaawp MAJOR;
const alias Oorgle MINOR;
static void function(ref Event, MINOR)[MINOR][MAJOR] 
funcyMatrix;

// note no MAJOR in func sig

void populate() {
/* ... */
}

void traverse() {
sendMessageAdapter = void function(ref Event evt, Tid) {
std.concurrency.send(tid, evt);
};

alias 
MatrixWalker!(typeof(&sendMessageAdapter),typeof(funkyMatrix)).applyFunc 
apply;


writeln("Traversing funcy matrix");
apply(&sendMessageAdapter, funkyMatrix);
}

void main(string[] args) {
populate();
traverse();
}

-

That sounds too good to be true, but it would make me warm and 
fuzzy inside if I didn't have to resort to keeping a dozen 
adapter/shim functions around.


Re: Arrays of functions, function signatures and template instantiation

2013-04-30 Thread anonymous

On Tuesday, 30 April 2013 at 08:42:57 UTC, JR wrote:

On Tuesday, 30 April 2013 at 02:38:27 UTC, anonymous wrote:

To get rid of the cast:

[...]

Instantiating the template with a function parameter causes a 
compilation error when actually calling the function;


--
  asdf.d:13: Error: variable asdf.MatrixWalker!(@system 
void(string major, uint minor, void function(string, uint) 
func), void function(string, 
uint)[uint][string]).applyFunc.func cannot be declared to be a 
function
  asdf.d:16: Error: function expected before (), not func of 
type _error_

--

I have a vague feeling I had it working like that at one point 
but I cannot recall with any degree of certainty.


Don't know what's going wrong there. It works for me:
http://dpaste.dzfl.pl/5c71f80e


Re: Arrays of functions, function signatures and template instantiation

2013-04-30 Thread JR

On Tuesday, 30 April 2013 at 02:38:27 UTC, anonymous wrote:

To get rid of the cast:

[...]

Instantiating the template with a function parameter causes a 
compilation error when actually calling the function;


--
  asdf.d:13: Error: variable asdf.MatrixWalker!(@system 
void(string major, uint minor, void function(string, uint) func), 
void function(string, uint)[uint][string]).applyFunc.func cannot 
be declared to be a function
  asdf.d:16: Error: function expected before (), not func of type 
_error_

--

I have a vague feeling I had it working like that at one point 
but I cannot recall with any degree of certainty.


Re: Arrays of functions, function signatures and template instantiation

2013-04-29 Thread anonymous

On Monday, 29 April 2013 at 23:49:18 UTC, JR wrote:
[...]

http://dpaste.dzfl.pl/9273fb92

Can't it be done neater than this? It *does* work now, but it's 
incredibly hacky and I'm not satisfied with it. The whole 
'passing a function pointer to a function that casts the 
signature and invokes it' deal makes me cringe. :>


To get rid of the cast:

13c13
<   void applyFunc(F* func, E[I][T] matrix) {
---

  void applyFunc(F func, E[I][T] matrix) {

16c16
<   func(major, minor, &element);
---

  func(major, minor, element);

29,30c29,30
<   void run(T major, I minor, F* func) {
<   (cast(void function(T,I))*func)(major, minor);
---

  void run(T major, I minor, F func) {
  func(major, minor);

52c52
<   alias
MatrixWalker!(typeof(runner),typeof(funcyMatrix)).applyFunc apply;
---
  alias 
MatrixWalker!(typeof(&runner),typeof(funcyMatrix)).applyFunc 
apply;


Arrays of functions, function signatures and template instantiation

2013-04-29 Thread JR
I'm piecing together a small IRC bot as my second pet project, 
and next up is splitting the socket-listening/event handling into 
a separate thread.


TL;DR: skip to the link at the bottom -- can't it be done neater?


Raw IRC commands are strings whose format differs depending on 
the *type* of the IRC event (for lack of a better word). These 
event types are arbitrary short strings like "NICK", "PRIVMSG", 
"NOTICE", "PING", "001", etc. I'd sleep better if it were an 
enum, but as it is I'm parsing the type from the raw string by 
regex, so obviously I'm getting another string out of it. 
(Granted, you could cast them to that enum in a huge switch, but 
I'm not sure you'd gain any academic efficiency points 
considering the extra time spent in that switch.)


After some more regex I have an Event struct with string members 
like .sender, .target, .type, .content and some others. 
Naturally, depending on what actually happened I may want to 
react to it. Most on-event reactions are functions to pass the 
Event to, like onPrivateMessage(Event evt) -- but sometimes I 
want to know the impending server response of a command I just 
sent.


As an example, when you connect to a server, the first things you 
send are user details (full name etc) and a nickname request. If 
what the server sends next is the welcome event "001", then all 
is well -- wait for the end-of-motd event "376" and then slowly 
start joining your channels and doing your stuff. But if it is 
the nickname-in-use event "433", then everything stops until you 
have requested an available nick.


So I had in mind an event handler and a message dispatcher. The 
event handler would be in its own thread listening to the socket 
stream, and once it reads a string it would parse it into an 
Event, then pass it along to the message dispatcher. The 
dispatcher would keep a record of which threads have registered 
interest in receiving what events, and would send messages 
accordingly. The solution that springs to mind is an associative 
matrix/array-of-array where one of the index keys is the event 
type string, and the other is the thread ID (Tid).


But I still want to keep onPrivateMessage(Event evt) and friends 
around, so in a stroke of hubris I thought it would be neat if I 
could find a generic solution that could work with both arrays of 
thread IDs *and* arrays of function pointers. I'm not sure where 
the 'event handler' struct would end and where the 'message 
dispatcher' would start though -- perhaps I'll just combine them, 
call it Overlord and be done with it. Or maybe 
ResponsibilityCreep.


Much shotgun programming later and I now have two templates; 
MatrixWalker and FuncRunner, subject to serious renaming. (They 
were called Herp and Derp a few hours back.)


Given a function pointer and a matrix of type Foo[Tid][string], 
MatrixWalker will foreach all and invoke the function on both 
keys (Tid, string) and the final element Foo. The function 
signature must match the types used, hence the FuncRunner 
template as an adapter. Tid needn't be Tid unless it's in the 
context of messaging, naturally, and in the context of messaging 
Foo is irrelevant and could be bool. (Keeping a single array like 
Tid[string] would only allow for one event registered per Tid, so 
Tid has to be a key unless you could somehow store multiple 
values per key. Even if possible [?], deregistering the right Tid 
from an event string key wouldn't be straightforward anymore.)


Error: function expected before (), not func of type void 
function(string, uint)*

Yay! Woe.


http://dpaste.dzfl.pl/9273fb92

Can't it be done neater than this? It *does* work now, but it's 
incredibly hacky and I'm not satisfied with it. The whole 
'passing a function pointer to a function that casts the 
signature and invokes it' deal makes me cringe. :>



Many thanks in advance, would love any and every piece of advice 
you could spare. With some luck there are some easy shortcuts and 
I'm just too green to see them.