September 13, 2020
On Sunday, 13 September 2020 at 01:25:43 UTC, mw wrote:
> On Saturday, 12 September 2020 at 20:29:40 UTC, Paul Backus
>> If you have a "real-life" application in mind for this, I'd be curious to hear what it is.
>
> I'm wrapping a C library, trying to write a single D function / template that can work with a group of C functions, hence I need that kind of signature I described.
>
> I'll post the code when I'm ready.

Here it is: D wrapper for https://ta-lib.org/

https://github.com/mingwugmail/talibd

I end up using C macro to generate D functions, the single template is this one:

https://github.com/mingwugmail/talibd/blob/master/source/talibd.h#L117
#define DECL_TA_FUNC(TA_FUNC, FUNC_INS, FUNC_OUTS, expected_lookback) __NL__\


and the macro instantiations are on line 144, 158, 168:

DECL_TA_FUNC(TA_MA, MA_INS, MA_OUTS, (MA_optInTimePeriod-1))
DECL_TA_FUNC(TA_RSI, RSI_INS, RSI_OUTS, RSI_optInTimePeriod)
DECL_TA_FUNC(TA_MACD, MACD_INS, MACD_OUTS, (optInSlowPeriod+optInSignalPeriod-2))


the generated D functions are here:

https://github.com/mingwugmail/talibd/blob/master/source/talibd.d#L47

you can take a look of the 3 generated functions to see the similarities, and pay attention to:

-- func decl: TA_xxx( <out array params>, <in options> )
-- assertions on <out arrays>
-- func calls: TA_xxx_Lookback(<in options>)
-- func call: talib.TA_xxx(<in options>, <transformed out arrays>, <also note: &begin, &num>)


There are a number of C macro tricks was used, which I just did some googling to be able to get it done in C -- and with the added benefits that I can directly see the generated source file to debug in the development process.


I think it's a non-trivial task to get this compile-time meta-programming done in D, if it can be done at all (I'm not sure).


Anyone want to give it a try? and submit a PR :-)

September 13, 2020
On Sunday, 13 September 2020 at 07:00:36 UTC, mw wrote:
>
> Here it is: D wrapper for https://ta-lib.org/
>
> https://github.com/mingwugmail/talibd
>
> I end up using C macro to generate D functions, the single template is this one:
>
> https://github.com/mingwugmail/talibd/blob/master/source/talibd.h#L117
> #define DECL_TA_FUNC(TA_FUNC, FUNC_INS, FUNC_OUTS, expected_lookback) __NL__\

The most straightforward way to do this in D is with a mixin template. Something like:

mixin template DECL_TA_FUNC(string TA_FUNC, FUNC_INS, FUNC_OUTS, int expected_lookback)
{
    bool impl(...)
    {
        // ...
    }

    // Could also wrap the whole function in a string mixin,
    // but this is easier.
    mixin("alias ", TA_FUNC, " = impl;");
}

Which you would then use like this:

mixin DECL_TA_FUNC!(
    "TA_MA",
    Tuple!(int, "MA_optInTimePeriod", TA_MAType, "opInMAType"),
    Tuple!(double[], "outMA"),
    MA_optInTimePeriod - 1
);
September 13, 2020
On Sunday, 13 September 2020 at 10:16:46 UTC, Paul Backus wrote:
> On Sunday, 13 September 2020 at 07:00:36 UTC, mw wrote:
>>
>> Here it is: D wrapper for https://ta-lib.org/
>>
>> https://github.com/mingwugmail/talibd
>>
>> I end up using C macro to generate D functions, the single template is this one:
>>
>> https://github.com/mingwugmail/talibd/blob/master/source/talibd.h#L117
>> #define DECL_TA_FUNC(TA_FUNC, FUNC_INS, FUNC_OUTS, expected_lookback) __NL__\
>
> The most straightforward way to do this in D is with a mixin template. Something like:
>
> mixin template DECL_TA_FUNC(string TA_FUNC, FUNC_INS, FUNC_OUTS, int expected_lookback)
> {
>     bool impl(...)
>     {
>         // ...
>     }
>
>     // Could also wrap the whole function in a string mixin,
>     // but this is easier.
>     mixin("alias ", TA_FUNC, " = impl;");
> }
>
> Which you would then use like this:
>
> mixin DECL_TA_FUNC!(
>     "TA_MA",
>     Tuple!(int, "MA_optInTimePeriod", TA_MAType, "opInMAType"),
>     Tuple!(double[], "outMA"),
>     MA_optInTimePeriod - 1
> );


Thanks, I will do the exercise some other day.

But, I'd reflect on my experience so far on compile-time meta-programming in D as a novice user, the big problems are:

-- in D, there are too many choices, with no clear guideline which one is *THE* one to use for a particular purpose: language or library mechanisms? mixin? template? AliasSeq / aliasSeqOf? Tuple? (non-)?-eponymous version of ...?; and even for a particular option, e.g. Tuple!(int, "MA_optInTimePeriod", TA_MAType, "opInMAType"),  there are choices to use either token (int) or string ("MA_optInTimePeriod"). And user does not have a strong guide on which choice is *THE* way to proceed. Each mechanism seems to have / fit a particular purpose, but when you start to use it, you'll probably find there are new problems come-in later, and you want to revisit the choice you made earlier on.

By contrast, in C: there is only *ONE* mechanism, i.e. macro, that's it.

-- in D, there is no easy way to convert between token <==> string. Given a token, does token.stringof always work to paste with other strings to generate a new token? and given a string, does mixin!"string" always work to be a valid token?

By contrast, in C: there is only *ONE* way: xxx ## yyy.

-- in D, there is no easy way to see directly the generated source code by the compiler at compile-time, which makes the debug difficult during development.

By contrast, in C: one can easily see the result via: cpp -P foo.h > foo.c


As I said earlier, I'm not very experienced with C macros either, however with some googling, I was able to work out a C macro version to generate D code; but with all the help so far, I still have no confidence that I can work out a solution in D to implement this:

```
     bool impl(...)
     {
         // ...
     }
```

September 13, 2020
On Sunday, 13 September 2020 at 18:24:01 UTC, mw wrote:
> But, I'd reflect on my experience so far on compile-time meta-programming in D as a novice user, the big problems are:
>
> -- in D, there are too many choices, with no clear guideline which one is *THE* one to use for a particular purpose: language or library mechanisms? mixin? template? AliasSeq / aliasSeqOf? Tuple? (non-)?-eponymous version of ...?; and even for a particular option, e.g. Tuple!(int, "MA_optInTimePeriod", TA_MAType, "opInMAType"),  there are choices to use either token (int) or string ("MA_optInTimePeriod"). And user does not have a strong guide on which choice is *THE* way to proceed. Each mechanism seems to have / fit a particular purpose, but when you start to use it, you'll probably find there are new problems come-in later, and you want to revisit the choice you made earlier on.
>
> By contrast, in C: there is only *ONE* mechanism, i.e. macro, that's it.

I think the biggest issue here is that, like you said, it's hard to find good resources for learning how to use D's various reflection and code-generation facilities. In the community Discord, we've tried to collect some links in the #resources channel, which you might find helpful:

- Philippe Sigaud's "D Template Tutorial"
  http://dpldocs.info/experimental-docs/std.typecons.Tuple.html

- Bradley Chatha's "Intro to D metaprogramming"
  https://bradley.chatha.dev/Blog

- Vladimir Panteleev's "Functional Image Processing in D"
  https://blog.thecybershadow.net/2014/03/21/functional-image-processing-in-d/

Ideally, we'd have some official, easy-to-find place where tutorials like this could be collected (maybe on the Wiki?), but so far no one's taken the initiative to set that up. One of the downsides of having a volunteer community, I suppose.

> -- in D, there is no easy way to convert between token <==> string. Given a token, does token.stringof always work to paste with other strings to generate a new token? and given a string, does mixin!"string" always work to be a valid token?

There's no 100% reliable way to round-trip a token to a string and back again, because the same token can have a different meaning depending on what scope it's used in. Adam Ruppe goes over some alternatives to string mixins you can use to avoid this pitfall in one of his "Tips of the Week":

http://www.arsdnet.net/this-week-in-d/2016-feb-21.html

> -- in D, there is no easy way to see directly the generated source code by the compiler at compile-time, which makes the debug difficult during development.
>
> By contrast, in C: one can easily see the result via: cpp -P foo.h > foo.c

I agree that this is an issue. There are a couple compiler flags that can help (-mixin=filename, -vcg-ast), but mostly you're stuck with printf-style debugging via `pragma(msg)`.
1 2
Next ›   Last »