October 07, 2008
Benji Smith wrote:
> Hmmmmmm... I still hate opCall, though :)

One context in which I found opCall very valuable is parameterized functions: functions that take, say, 1 argument but are parameterized by another. An example is a Gaussian kernel of parameterized bandwidth:

double gaussianKernel(double d)
{
    return exp(-d * d / alpha * alpha);
}

We'd like to be able to configure alpha properly (not via a global, because there could be several Gaussian kernels around). A solution would be to use delegates, but that's inefficient and a kernel is evaluated so often it's not even funny. So a good solution is to make the function a struct with state:

struct GaussianKernel
{
    private double alpha2InvNeg = -1;

    double opCall(double d) const
    {
        return exp(d * d * alpha2InvNeg);
    }

    void alpha(double a)
    {
        enforce(a > 0);
        alpha2InvNeg = -1 / (a * a);
    }

    double alpha() const
    {
        return sqrt(-1 / alpha2InvNeg);
    }
}


Andrei
October 07, 2008
Andrei Alexandrescu wrote:
> Benji Smith wrote:
>> Andrei Alexandrescu wrote:
>>> b) Template@Arg and Template@(Args)
>>>
>>> This approach not only accepts the need for a contraption, it actually leverages it by allowing you to drop the parens if you only have one argument. That way "@" becomes a true operator, the template instantiation operator. Note that this can be done with the current "!" as well, except that Template!Arg does not look to me like anything enticing.
>>
>> Interesting.
>>
>>    // If this is possible.......
>>    auto myTemplate = Template @ (1, 2, 3, uint);
>>
>>    // ......shouldn't this be possible too?
>>    auto args = (1, 2, 3, uint);
>>    auto myTemplate = Template @ args;
>>
>> All other binary operators can operate on either a literal or on an expression, and I'd expect a template instantiation operator to do the same.
>>
>> What do you think?
> 
> I think you will have a hard time (re)using parentheses and commas to define literals.
> 
> Andrei

The actual syntax I used isn't important. That's not what I was talking about.

It was the idea that template instantiation is the result of a binary operator. Which, to me, implies that the operands could be either literals or other types of expressions. I suppose the real syntax would be more like this:

   auto args = Tuple @ (1, 2, 3, real);
   auto myTemplate = Template @ args;

So, if "@" is a binary operator, it has two operands: a template name and an argument list. But, currently, there's no way to express either of those constructs symbolically. Only literally.

It seems to me that, in your proposal, "@" is not really an operator. It might act a little bit like an operator, but since its operands can't exist by themselves, then they're not really operands. And "@" is not an operator.

It'd be cool if template instantiation really was the result of an operator, with all of the necessary implications regarding the operands.

Of course, I'm not actually *proposing* that implementation. I'm just drawing a fine line in the sand delineating what it actually means to be an "operator" rather than "template syntax".

--benji
October 07, 2008
On Tue, 07 Oct 2008 20:05:28 +0400, Benji Smith <dlanguage@benjismith.net> wrote:

> Andrei Alexandrescu wrote:
>> Benji Smith wrote:
>>> Andrei Alexandrescu wrote:
>>>> b) Template@Arg and Template@(Args)
>>>>
>>>> This approach not only accepts the need for a contraption, it actually leverages it by allowing you to drop the parens if you only have one argument. That way "@" becomes a true operator, the template instantiation operator. Note that this can be done with the current "!" as well, except that Template!Arg does not look to me like anything enticing.
>>>
>>> Interesting.
>>>
>>>    // If this is possible.......
>>>    auto myTemplate = Template @ (1, 2, 3, uint);
>>>
>>>    // ......shouldn't this be possible too?
>>>    auto args = (1, 2, 3, uint);
>>>    auto myTemplate = Template @ args;
>>>
>>> All other binary operators can operate on either a literal or on an expression, and I'd expect a template instantiation operator to do the same.
>>>
>>> What do you think?
>>  I think you will have a hard time (re)using parentheses and commas to define literals.
>>  Andrei
>
> The actual syntax I used isn't important. That's not what I was talking about.
>
> It was the idea that template instantiation is the result of a binary operator. Which, to me, implies that the operands could be either literals or other types of expressions. I suppose the real syntax would be more like this:
>
>     auto args = Tuple @ (1, 2, 3, real);
>     auto myTemplate = Template @ args;
>
> So, if "@" is a binary operator, it has two operands: a template name and an argument list. But, currently, there's no way to express either of those constructs symbolically. Only literally.
>
> It seems to me that, in your proposal, "@" is not really an operator. It might act a little bit like an operator, but since its operands can't exist by themselves, then they're not really operands. And "@" is not an operator.
>
> It'd be cool if template instantiation really was the result of an operator, with all of the necessary implications regarding the operands.
>
> Of course, I'm not actually *proposing* that implementation. I'm just drawing a fine line in the sand delineating what it actually means to be an "operator" rather than "template syntax".
>
> --benji

You could do it this way:

alias Tuple@(1,2,3,real) Args;
alias Template@Args MyTemplate;
October 07, 2008
Andrei Alexandrescu wrote:
> Benji Smith wrote:
>> Hmmmmmm... I still hate opCall, though :)
> 
> One context in which I found opCall very valuable is parameterized functions: functions that take, say, 1 argument but are parameterized by another. An example is a Gaussian kernel of parameterized bandwidth:
> 
> double gaussianKernel(double d)
> {
>     return exp(-d * d / alpha * alpha);
> }
> 
> We'd like to be able to configure alpha properly (not via a global, because there could be several Gaussian kernels around). A solution would be to use delegates, but that's inefficient and a kernel is evaluated so often it's not even funny. So a good solution is to make the function a struct with state:
> 
> struct GaussianKernel
> {
>     private double alpha2InvNeg = -1;
> 
>     double opCall(double d) const
>     {
>         return exp(d * d * alpha2InvNeg);
>     }
> 
>     void alpha(double a)
>     {
>         enforce(a > 0);
>         alpha2InvNeg = -1 / (a * a);
>     }
> 
>     double alpha() const
>     {
>         return sqrt(-1 / alpha2InvNeg);
>     }
> }
> 
> 
> Andrei

Great example!

I've actually implemented the same thing (in Java). I have a KernelDensityEstimator class, for estimating the shape of a distribution, based on sample values from that distribution.

The KDE constructor takes a Function object to define the kernel. (Rather than defining a "Kernel" as an interface or an abstract class, I define a more general "Function" interface, and let the caller make his own choice about whether his function makes an appropriate kernel.)

So the code looks like this:

interface Function {
   public double project(double value);
}

class GaussianFunction implements Function {

   private double height;
   private double mean;
   private double stdev;
   private double denominator;

   public GaussianFunction(double height, double mean, double stdev) {

      enforce(height > 0);
      enforce(!Double.isInfinite(height));
      enforce(!Double.isNaN(height));
      enforce(!Double.isInfinite(mean));
      enforce(!Double.isNaN(mean));
      enforce(stdev > 0);
      enforce(!Double.isInfinite(stdev));
      enforce(!Double.isNaN(stdev));

      this.height = height;
      this.mean = mean;
      this.stdev = stdev;

      // Pre-calculate the denominator of the exponent
      // (since it won't vary from call to call).
      this.denominator = 2 * stdev * stdev;
   }

   public double project(double value) {
      double difference = x - mean;
      double numerator = difference * difference;
      return height * Math.exp(- (numerator / denominator));
   }
}

class KernelDensityEstimator {
   private Function kernel;
   private List<Double> samples;
   public KernelDensityEstimator(Function kernel) {
      this.kernel = kernel;
      this.samples = new ArrayList<Double>();
   }
   public double addSample(double sample) {
      samples.add(sample);
   }
   public estimatedProbabilityOf(double value) {
      double sum = 0;
      for (double sample : samples) {
         sum += kernel.project(sample);
      }
      return sum / samples.size();
   }
}

Anyhoo... maybe that's a little too much code to dump, but I wanted to show the definition of the concept of a "Function", separated from the definition of a particular function class, separated from the instantiation of that class, and separated from the invocation of the function.

In my mind, opCall would encourage code like this:

   foreach (double x; values) {
      GaussianKernel(alpha)(x);
   }

In this code, the alpha gets set... over and over and over again. If the construction of the parametric function is distinct from the calling of it, the user is encouraged to write code more like this:

   auto kernel = new GuassianKernel(alpha);
   foreach (double x; values) {
      auto result = kernel.valueOf(x);
   }

It can be convincingly argued that a Function object shouldn't have a *named* method. Or at least, if it does have a named method, the name should be the same at the name of the function. But then that makes it hard to use functions polymorphically.

What you and I are doing is pretty much the same, except that I call my function "project" (since a function is a projection from an x value to a corresponding y value), whereas you use opCall.

The nice thing about using a named function, though, is that it allows me to pass functions around polymorphically, and since Java doesn't have function pointers, this is the best solution to the problem.

I totally agree with you, though, that this is the best possible use for opCall.

--benji
October 07, 2008
Andrei Alexandrescu wrote:

> Aarti_pl wrote:
>> I would be much more happy with implementation of my proposal: http://d.puremagic.com/issues/show_bug.cgi?id=1827
>> 
>> I mean here especially syntax for "is expression" for templates.
>> 
>> http://digitalmars.com/d/1.0/expression.html#IsExpression
>> 
>> As it occurred on Tango conference in talk of Rafał Bocian (who lead the D course for students) syntax for "is expression" and specification (among few other things) is especially difficult for newbies in D.
>> 
>> Unfortunately answer from Walter, why he didn't decide to change current
>>  syntax was.... guess what? --- It doesn't look nice in code...
>> 
>> Bad luck, said sad pirate .(
>> 
>> BR
>> Marcin Kuszczak
>> (aarti_pl)
> 
> Your proposal should be reevaluated in wake of the conditional templates, which Walter has implemented a couple of releases ago.
> 
> Andrei

Yes, I am aware of that. They are just small part of the whole proposal, but currently implemented in such a way that it is not possible to use it in e.g. static asserts and aliases like it was proposed.

I still think that proposal is good (no one pointed out problems with it).
It could be implemented as kind of compile time expression once, and then
used in other places. It allows also more expressiveness and predictable
syntax e.g.
void call(T : class)(T instance) {}
I hope that above mentioned issues with current design of IsExpression will
be eventually fixed somehow, sometime...

The strange think here is how minor issues (as most of community doesn't
have problem with it) suddenly emerges from deeps and good ideas (which
solve real problems) are sunken in the water... Well, I can give more
examples if you want :-)

-- 
Regards
Marcin Kuszczak (Aarti_pl)
-------------------------------------
Ask me why I believe in Jesus - http://www.zapytajmnie.com (en/pl)
Doost (port of few Boost libraries) - http://www.dsource.org/projects/doost/
-------------------------------------

October 07, 2008
Marcin Kuszczak wrote:
> Andrei Alexandrescu wrote:
> 
>> Aarti_pl wrote:
>>> I would be much more happy with implementation of my proposal:
>>> http://d.puremagic.com/issues/show_bug.cgi?id=1827
>>>
>>> I mean here especially syntax for "is expression" for templates.
>>>
>>> http://digitalmars.com/d/1.0/expression.html#IsExpression
>>>
>>> As it occurred on Tango conference in talk of Rafał Bocian (who lead the
>>> D course for students) syntax for "is expression" and specification
>>> (among few other things) is especially difficult for newbies in D.
>>>
>>> Unfortunately answer from Walter, why he didn't decide to change current
>>>  syntax was.... guess what? --- It doesn't look nice in code...
>>>
>>> Bad luck, said sad pirate .(
>>>
>>> BR
>>> Marcin Kuszczak
>>> (aarti_pl)
>> Your proposal should be reevaluated in wake of the conditional
>> templates, which Walter has implemented a couple of releases ago.
>>
>> Andrei
> 
> Yes, I am aware of that. They are just small part of the whole proposal, but
> currently implemented in such a way that it is not possible to use it in
> e.g. static asserts and aliases like it was proposed.
> 
> I still think that proposal is good (no one pointed out problems with it).
> It could be implemented as kind of compile time expression once, and then
> used in other places. It allows also more expressiveness and predictable
> syntax e.g. void call(T : class)(T instance) {} I hope that above mentioned issues with current design of IsExpression will
> be eventually fixed somehow, sometime...

I agree that pattern matching on type trees will have to make it into the language in one form or another. In fact, syntactically it is already there, but compiler bugs/limitations prevent it from happening. One thing with the notation you suggest is that it doesn't quite look like the rest of the language, and perhaps a few simple steps could be taken to make it more integrated.

> The strange think here is how minor issues (as most of community doesn't
> have problem with it) suddenly emerges from deeps and good ideas (which
> solve real problems) are sunken in the water... Well, I can give more
> examples if you want :-)

This is pointing at some being born into royalty while others' good work is under-compensated. Well in a way I'm glad you bring this up. One thing that has caused and is causing an amount of stir and occasional irritation is the perception that I came out of nowhere and captured Walter's attention effortlessly. The reality is that being neighbors with Walter was part of the mix, but the prosaic bulk of it is that Walter cared only because of my previous and ongoing 99% transpiration. For better or worse, this state of affairs makes it that whatever I say is perceived as much more intense, imposing, controversial, quirky, or arrogant, than it is, and therefore much more scrutinized and criticized. This reaction is entirely understandable, and I'm still thinking of ways to assuage it. In the meantime it's costing me time because I feel obligated to answer the many replies to my posts.

That being said, it is always great if you can bring to the fore more outstanding problems that you think have good solutions thought of by you or others. Just please consider the above when you compare and contrast them against the petty issue of "!()".


Andrei
October 08, 2008
Andrei Alexandrescu pisze:
> Marcin Kuszczak wrote:
>> Andrei Alexandrescu wrote:
>>
>>> Aarti_pl wrote:
>>>> I would be much more happy with implementation of my proposal:
>>>> http://d.puremagic.com/issues/show_bug.cgi?id=1827
>>>>
>>>> I mean here especially syntax for "is expression" for templates.
>>>>
>>>> http://digitalmars.com/d/1.0/expression.html#IsExpression
>>>>
>>>> As it occurred on Tango conference in talk of Rafał Bocian (who lead the
>>>> D course for students) syntax for "is expression" and specification
>>>> (among few other things) is especially difficult for newbies in D.
>>>>
>>>> Unfortunately answer from Walter, why he didn't decide to change current
>>>>  syntax was.... guess what? --- It doesn't look nice in code...
>>>>
>>>> Bad luck, said sad pirate .(
>>>>
>>>> BR
>>>> Marcin Kuszczak
>>>> (aarti_pl)
>>> Your proposal should be reevaluated in wake of the conditional
>>> templates, which Walter has implemented a couple of releases ago.
>>>
>>> Andrei
>>
>> Yes, I am aware of that. They are just small part of the whole proposal, but
>> currently implemented in such a way that it is not possible to use it in
>> e.g. static asserts and aliases like it was proposed.
>>
>> I still think that proposal is good (no one pointed out problems with it).
>> It could be implemented as kind of compile time expression once, and then
>> used in other places. It allows also more expressiveness and predictable
>> syntax e.g. void call(T : class)(T instance) {} I hope that above mentioned issues with current design of IsExpression will
>> be eventually fixed somehow, sometime...
> 
> I agree that pattern matching on type trees will have to make it into the language in one form or another. In fact, syntactically it is already there, but compiler bugs/limitations prevent it from happening. One thing with the notation you suggest is that it doesn't quite look like the rest of the language, 

Really? I got in my code a lot of similarly looking code. My proposal is in fact generalization and "uniformization" of existing syntaxes of template parameters and is expression. In most common cases you get same syntax as now.

> and perhaps a few simple steps could be taken to make it more integrated.
> 

I have nothing against improving this syntax. But I would be happy to get one uniform syntax for: template parameters, IsExpression, static assert, static if. And to dismiss this ugly:
T : T[]
creature ;-)

With my proposal you got only one universal syntax and few design mistakes fixed. With current implementation state we probably lost opportunity for uniform syntax.

>> The strange think here is how minor issues (as most of community doesn't
>> have problem with it) suddenly emerges from deeps and good ideas (which
>> solve real problems) are sunken in the water... Well, I can give more
>> examples if you want :-)
> 
> This is pointing at some being born into royalty while others' good work is under-compensated. Well in a way I'm glad you bring this up. One thing that has caused and is causing an amount of stir and occasional irritation is the perception that I came out of nowhere and captured Walter's attention effortlessly. The reality is that being neighbors with Walter was part of the mix, but the prosaic bulk of it is that Walter cared only because of my previous and ongoing 99% transpiration. For better or worse, this state of affairs makes it that whatever I say is perceived as much more intense, imposing, controversial, quirky, or arrogant, than it is, and therefore much more scrutinized and criticized. This reaction is entirely understandable, and I'm still thinking of ways to assuage it. In the meantime it's costing me time because I feel obligated to answer the many replies to my posts.

Great that you see this issue. And even greater that you think rationally how to solve it.

Currently I think that it would be good to ask community about top 5 problematic issues with D (not features, nor bugs because it would be better to get more general knowledge). And after sorting out final top 5 list, commit to improve situation or solve problem in these areas in reasonable, defined time. I think that people could post here proposed features, most annoying bugs, D design mistakes, problems with processes, problems with web pages etc. Just one restriction: only 5, single, well defined issues in decreasing priority.

Well, I think that it might help to know what community really needs.


> That being said, it is always great if you can bring to the fore more outstanding problems that you think have good solutions thought of by you or others. Just please consider the above when you compare and contrast them against the petty issue of "!()".
> 
> 
> Andrei

I think that asking people about "top 5 issues" (see above) will bring a lot of such a things. I will certainly contribute with my 5 groszy (Polish "cents").

Best Regards
Marcin Kuszczak
(aarti_pl)
October 08, 2008
On Mon, 06 Oct 2008 12:39:29 +0200, Benji Smith <dlanguage@benjismith.net> wrote:

> Andrei Alexandrescu wrote:
>> One morning I woke up with the sudden realization of what the problem was: the shouting.
>
> Here's my (nutty) opinion:
>
> Neither the "!" nor the "." really want to be there. I think the language really *wants* to be using a bare set of parens for templates. Because the language actually wants templates and functions to converge.
>
> Instead of a special-case syntax for templates, and a set of special rules for CTFE, and a whole set of parallel "static" statements (if, else, foreach) and a special compile-type-only type construct (tuples), just let D be D, either at runtime or compile type.
>
> If a function could return a Type, and if that type could be used in a Type Constructor, then you'd have all the magic template sauce you'd need, and templates could happily converge themselves with regular functions.
>
> Hey! I told you it was going to be nutty!!!
>
> <g>
>
> --benji

That would only work for templated functions, though. What about templated types?

-- 
Simen
October 08, 2008
Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> Leandro Lucarella wrote:
>> "enum" as the way to declare manifest constants were much more ugly than
>> "!(", and most of the people were against it. I don't see why ".(" should
>> be introduced.
>
> Ugly or not, enumerated symbols were manifest constants to begin with. That's kinda hard to argue against because it's a sheer fact.

All bears are animals, so lets call all animals bears. See where this is wrong?

-- 
Simen
October 08, 2008
Aarti_pl wrote:
> Andrei Alexandrescu pisze:
>> I agree that pattern matching on type trees will have to make it into the language in one form or another. In fact, syntactically it is already there, but compiler bugs/limitations prevent it from happening. One thing with the notation you suggest is that it doesn't quite look like the rest of the language, 
> 
> Really? I got in my code a lot of similarly looking code. My proposal is in fact generalization and "uniformization" of existing syntaxes of template parameters and is expression. In most common cases you get same syntax as now.

Probably I misread the samples you posted with that bug report. Could you please point me to a more thorough description?

>> and perhaps a few simple steps could be taken to make it more integrated.
>>
> 
> I have nothing against improving this syntax. But I would be happy to get one uniform syntax for: template parameters, IsExpression, static assert, static if. And to dismiss this ugly:
> T : T[]
> creature ;-)

Oh how I wish Walter let that go.

> With my proposal you got only one universal syntax and few design mistakes fixed. With current implementation state we probably lost opportunity for uniform syntax.

Then I guess it's of interest. Again, need to build some more understanding.

>>> The strange think here is how minor issues (as most of community doesn't
>>> have problem with it) suddenly emerges from deeps and good ideas (which
>>> solve real problems) are sunken in the water... Well, I can give more
>>> examples if you want :-)
>>
>> This is pointing at some being born into royalty while others' good work is under-compensated. Well in a way I'm glad you bring this up. One thing that has caused and is causing an amount of stir and occasional irritation is the perception that I came out of nowhere and captured Walter's attention effortlessly. The reality is that being neighbors with Walter was part of the mix, but the prosaic bulk of it is that Walter cared only because of my previous and ongoing 99% transpiration. For better or worse, this state of affairs makes it that whatever I say is perceived as much more intense, imposing, controversial, quirky, or arrogant, than it is, and therefore much more scrutinized and criticized. This reaction is entirely understandable, and I'm still thinking of ways to assuage it. In the meantime it's costing me time because I feel obligated to answer the many replies to my posts.
> 
> Great that you see this issue. And even greater that you think rationally how to solve it.
> 
> Currently I think that it would be good to ask community about top 5 problematic issues with D (not features, nor bugs because it would be better to get more general knowledge). And after sorting out final top 5 list, commit to improve situation or solve problem in these areas in reasonable, defined time. I think that people could post here proposed features, most annoying bugs, D design mistakes, problems with processes, problems with web pages etc. Just one restriction: only 5, single, well defined issues in decreasing priority.
> 
> Well, I think that it might help to know what community really needs.

I think that's a good idea. For now, I'm waiting on the results of the Tango conference to percolate. I understand there was some discussion about mistakes in D's design.

>> That being said, it is always great if you can bring to the fore more outstanding problems that you think have good solutions thought of by you or others. Just please consider the above when you compare and contrast them against the petty issue of "!()".
>>
>>
>> Andrei
> 
> I think that asking people about "top 5 issues" (see above) will bring a lot of such a things. I will certainly contribute with my 5 groszy (Polish "cents").

Ok.


Andrei