Re: DIP 1030-- Named Arguments--Formal Assessment

2020-09-18 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Friday, 18 September 2020 at 13:39:14 UTC, Mike Parker wrote:

It's from a phone call they had while they were discussing 
whether to approve or reject the DIP.


LOL no wonder I couldn't find it.


Re: DIP 1030-- Named Arguments--Formal Assessment

2020-09-18 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Thursday, 17 September 2020 at 12:58:06 UTC, Mike Parker wrote:

So they decided that a new `std.traits` template and a 
corresponding `__traits` option are needed which expand into 
the exact function signature of another function.


I have been trying to locate that specific discussion, without 
success so far. Help? This is of great interest to me, and I may 
throw in my $.02.


Re: DIP 1030-- Named Arguments--Formal Assessment

2020-09-17 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Thursday, 17 September 2020 at 13:45:16 UTC, Mike Parker wrote:
On Thursday, 17 September 2020 at 13:42:47 UTC, Jean-Louis 
Leroy wrote:


this point I have some hope that the DIP is not damaging in 
the way Mike thinks.


What Mike thinks appears nowhere in my post :-)


OK, s/thinks/reports/ ;-)



Re: DIP 1030-- Named Arguments--Formal Assessment

2020-09-17 Thread Jean-Louis Leroy via Digitalmars-d-announce
On Thursday, 17 September 2020 at 13:23:38 UTC, Jean-Louis Leroy 
wrote:
Actually, Parameters!origFun will carry storage classes, UDAs, 
etc for all the parameters. And Parameters!origFun[0..1] (note 
the two dots) will carry everything about the first parameter. 
The trouble begins when, for some reason, you need to 
manipulate the parameter at a finer level. For example, in 
openmethods, I need to change the type while preserving 
everything else.


(For the rest of this post, to make things clear, I will call 
Parameter declarations that appear inside the function 
definition, and Arguments the values that are passed to a 
function call).


I like named arguments. However, I would be greatly disappointed 
if:
1/ Parameters!origFun and Parameters!origFun[i..i+1] stopped 
working as well as they do now.
2/ The named arguments did not come with new traits (or at least 
is(__parameter) magic) to allow fully analyzing the parameters.


That being said, does the new feature imply any change in the 
*parameters* themselves? I.e. are there changes in the way the 
function is defined, not only in the way it is called?


I have not followed the discussion and just skimmed over the DIP 
now. I'm going to try to find time for this. However, at this 
point I have some hope that the DIP is not damaging in the way 
Mike thinks.


Re: DIP 1030-- Named Arguments--Formal Assessment

2020-09-17 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Thursday, 17 September 2020 at 12:58:06 UTC, Mike Parker wrote:

DIP 1030, "Named Arguments", has been accepted.

During the assessment, Walter and Atila had a discussion 
regarding this particular criticism:


https://forum.dlang.org/post/mailman.1117.1581368593.31109.digitalmar...@puremagic.com

"Named arguments breaks this very important pattern:

auto wrapper(alias origFun)(Parameters!origFun args)
{
  // special sauce
  return origFun(args);
}"

They say that, though it's true that `Parameters!func` will not 
work in a wrapper, it "doesn't really work now"---default 
arguments and storage classes must be accounted for. This can 
be done with string mixins, or using a technique referred to by 
Jean-Louis Leroy as "refraction", both of which are clumsy.


Actually, Parameters!origFun will carry storage classes, UDAs, 
etc for all the parameters. And Parameters!origFun[0..1] (note 
the two dots) will carry everything about the first parameter. 
The trouble begins when, for some reason, you need to manipulate 
the parameter at a finer level. For example, in openmethods, I 
need to change the type while preserving everything else.


Re: Picking function templates with __traits(getOverloads, ..., true)

2020-07-29 Thread Jean-Louis Leroy via Digitalmars-d-learn

On Thursday, 30 July 2020 at 00:27:49 UTC, user1234 wrote:
On Wednesday, 29 July 2020 at 23:57:21 UTC, Jean-Louis Leroy 
wrote:

This works:

[...]
I may be missing the obvious...or it's a compiler bug???


Yes and it's just been fixed, see 
https://github.com/dlang/dmd/pull/11431.

So uncommenting the second times works on ~master.


Ah thanks! In the meantime I realized that picking the 
overload at index 1 works. That's the difference between 'foo' 
and 'times'. Then I was 80% sure it was a bug.


Picking function templates with __traits(getOverloads, ..., true)

2020-07-29 Thread Jean-Louis Leroy via Digitalmars-d-learn

This works:

module test;

void foo(T)(T a, T b) {}
void foo(T)(char a, T b) {}

template InstantiateTemplateAt(alias Module, string name, int 
index, T...) {
alias Template = __traits(getOverloads, test, name, 
true)[index];

alias InstantiateTemplateAt = Template!(T);
}

pragma(msg, typeof(InstantiateTemplateAt!(test, "foo", 1, int)));
// pure nothrow @nogc @safe void(char a, int b)

class Matrix(T) {}

Matrix!T times(T)(Matrix!T a, T b);
// Matrix!T times(T)(T a, Matrix!T b); // <-- second 'times' 
overload


pragma(msg, typeof(InstantiateTemplateAt!(test, "times", 0, 
int)));

// Matrix!int(Matrix!int a, int b)

But if I uncomment the second 'times' function template, I get an 
error:


templateoverloads.d(8): Error: template `test.times` matches more 
than one template declaration:

templateoverloads.d(16): `times(T)(Matrix!T a, T b)`
and
templateoverloads.d(17): `times(T)(T a, Matrix!T b)`
templateoverloads.d(19): Error: template instance 
`test.InstantiateTemplateAt!(test, "times", 0, int)` error 
instantiating

_error_

I may be missing the obvious...or it's a compiler bug???
(not sure if this belongs to the Learn section either)




Upcoming refraction module in bolts [was: DUB project type support for Emacs Projectile]

2020-06-15 Thread Jean-Louis Leroy via Digitalmars-d-learn

On Monday, 15 June 2020 at 16:03:08 UTC, jmh530 wrote:

On Monday, 15 June 2020 at 13:17:11 UTC, Jean-Louis Leroy wrote:

[snip]

Nah, I saw it. Well. My take on it has been ready for months 
but I had to wait for my employer's permission to publish it. 
They are very open-source friendly, and as a consequence there 
is a glut of requests for open-sourcing personal projects. I 
guess I am going to cancel my request...




Ah. I suppose that depends implementation/performance/feature 
differences...


No, it's just that they are essentially equivalent. I spent some 
time supporting InterfaceValues to immutable and const classes 
and objects. Not sure if he has that, I haven't played with tardy 
yet. OTOH I didn't bother with allocator support.




On the bright side, I just got authorized to contribute my 
work on function refraction (currently part of openmethods) to 
bolts. You can see it here: 
https://github.com/aliak00/bolts/pull/10


I saw when you mentioned it earlier. Though it hasn't been 
something I've needed as yet, it's good to know that it's there.


This allows the function mixins to work when they are in 
different modules, right? I don't see a test for that, but it 
might be useful to include such an example (I'm pretty sure


You mean an example with two modules?

I plan to write a D blog entry that walks through the pitfalls of 
cross-module mixing.


Atila's tardy makes use of a similar functionality when they 
are in different modules).


Actually we were in contact (and with Ali of course). I pointed 
him to the part of openmethods that creates functions. He has a 
'refraction.d' too. I coined the term 'refraction'. ;-)


It's interesting that many of the examples for refract are like 
refract!(F, "F") or refract!(answer, "answer"). Would something 
like
Function refract(alias fun, string localSymbol = 
__traits(identifier, fun))()

work for you?


Not at all :-D That would return a name in the caller module. In 
the mixture you want to use only local names, and navigate from 
there.


Maybe I should change all the examples, including the unit tests, 
to avoid giving the impression that the original function name is 
a good default for the localSymbol. In most cases it's not.





Re: DUB project type support for Emacs Projectile

2020-06-15 Thread Jean-Louis Leroy via Digitalmars-d-learn

On Sunday, 14 June 2020 at 18:49:01 UTC, jmh530 wrote:

On Sunday, 14 June 2020 at 17:19:05 UTC, Jean-Louis Leroy wrote:

[snip]


In case you missed it, I thought you would find this interesting
https://forum.dlang.org/thread/dytpsnkqnmgzniiwk...@forum.dlang.org


Nah, I saw it. Well. My take on it has been ready for months but 
I had to wait for my employer's permission to publish it. They 
are very open-source friendly, and as a consequence there is a 
glut of requests for open-sourcing personal projects. I guess I 
am going to cancel my request...


On the bright side, I just got authorized to contribute my work 
on function refraction (currently part of openmethods) to bolts. 
You can see it here: https://github.com/aliak00/bolts/pull/10


Re: DUB project type support for Emacs Projectile

2020-06-14 Thread Jean-Louis Leroy via Digitalmars-d-learn

On Sunday, 14 June 2020 at 16:04:32 UTC, Jean-Louis Leroy wrote:

On Sunday, 14 June 2020 at 09:11:58 UTC, Andre Pany wrote:
On Saturday, 13 June 2020 at 19:27:53 UTC, Jean-Louis Leroy 
wrote:
On Monday, 18 November 2019 at 23:06:14 UTC, Per Nordlöw 
wrote:
Have anybody written support for DUB project types in Emacs' 
projectile?


See: 
https://www.projectile.mx/en/latest/projects/#adding-custom-project-types


Normally it should be as easy as this:

(projectile-register-project-type
 'dub '("dub.json" "dub.sdl")
 :compile "dub compile"
 :test "dub test"
 :run "dub run")

But it doesn't work for me and I cannot figure out why.


The command is `dub build` which will build the project from 
the current work dir. You can set another work dir with arg 
`--root FOLDER` if needed. Same for `dub test` and `dub run`.


Kind regards
Andre


`dub build` - right, sorry for that. But the real problem (and 
the reason why I never noticed the compile/build mistake) is 
that projectile deigns not recognize the project type. Yet I 
did try it in directories containing a dub project, IOW a 
`dub.json` was present. I just lived with it, entering the 
commands manually when I need to restart emacs (which happens 
maybe once in a week). I should debug this, maybe I'll do that 
today...


OK, projectile checks for the presence of *all* the files in the 
list. So there:


(defun projectile-dub-project-p ()
  "Check if a project contains a dub.json or dub.sdl file."
  (or (projectile-verify-file "dub.json")
  (projectile-verify-file "dub.sdl")))

(projectile-register-project-type
 'dub #'projectile-dub-project-p
 :compile "dub build"
 :test "dub test"
 :run "dub run")



Re: DUB project type support for Emacs Projectile

2020-06-14 Thread Jean-Louis Leroy via Digitalmars-d-learn

On Sunday, 14 June 2020 at 09:11:58 UTC, Andre Pany wrote:
On Saturday, 13 June 2020 at 19:27:53 UTC, Jean-Louis Leroy 
wrote:

On Monday, 18 November 2019 at 23:06:14 UTC, Per Nordlöw wrote:
Have anybody written support for DUB project types in Emacs' 
projectile?


See: 
https://www.projectile.mx/en/latest/projects/#adding-custom-project-types


Normally it should be as easy as this:

(projectile-register-project-type
 'dub '("dub.json" "dub.sdl")
 :compile "dub compile"
 :test "dub test"
 :run "dub run")

But it doesn't work for me and I cannot figure out why.


The command is `dub build` which will build the project from 
the current work dir. You can set another work dir with arg 
`--root FOLDER` if needed. Same for `dub test` and `dub run`.


Kind regards
Andre


`dub build` - right, sorry for that. But the real problem (and 
the reason why I never noticed the compile/build mistake) is that 
projectile deigns not recognize the project type. Yet I did try 
it in directories containing a dub project, IOW a `dub.json` was 
present. I just lived with it, entering the commands manually 
when I need to restart emacs (which happens maybe once in a 
week). I should debug this, maybe I'll do that today...





Re: DUB project type support for Emacs Projectile

2020-06-13 Thread Jean-Louis Leroy via Digitalmars-d-learn

On Monday, 18 November 2019 at 23:06:14 UTC, Per Nordlöw wrote:
Have anybody written support for DUB project types in Emacs' 
projectile?


See: 
https://www.projectile.mx/en/latest/projects/#adding-custom-project-types


Normally it should be as easy as this:

(projectile-register-project-type
 'dub '("dub.json" "dub.sdl")
 :compile "dub compile"
 :test "dub test"
 :run "dub run")

But it doesn't work for me and I cannot figure out why.



Re: Aliasing current function template instance

2020-05-01 Thread Jean-Louis Leroy via Digitalmars-d-learn

On Friday, 1 May 2020 at 21:05:17 UTC, Adam D. Ruppe wrote:

On Friday, 1 May 2020 at 20:28:58 UTC, Jean-Louis Leroy wrote:

Something I have overlooked? Any ideas?


There's an old rule, that I can't find in the spec anymore but 
I'm still pretty sure it is there, where taking the address of 
a template inside a template yields the current instantiation.


Then you can fetch the type of that and do some reflection off. 
So try this in your test rig:


   pragma(msg, Parameters!(typeof()));

This rule was in there to ease callbacks and recursive 
functions iirc but it can also work with you thanks to typeof 
turning the runtime address back into a compile time alias.


It looks like it does the trick. Thanks! Trying to add support 
for method templates to openmethods.




Re: Aliasing current function template instance

2020-05-01 Thread Jean-Louis Leroy via Digitalmars-d-learn

On Friday, 1 May 2020 at 20:43:05 UTC, Steven Schveighoffer wrote:

On 5/1/20 4:28 PM, Jean-Louis Leroy wrote:


Something I have overlooked? Any ideas?



This trick works. No idea who came up with it:

alias thisFunction = __traits(parent, {});

-Steve


I think I get the idea. Alas it doesn't work inside a function 
template, because it returns the template, not the instance:


 void foo(T)(lazy T)
 {
   alias thisFunction = __traits(parent, {});
   pragma(msg, thisFunction.stringof);
   //pragma(msg, Parameters!thisFunction); // later
 }

 void main()
 {
   foo(0);
   foo("");
 }

prints:

  foo(T)(lazy T)
  foo(T)(lazy T)

Uncommenting the line that is (more or less) my real goal:

aliasthisfunction.d(7): Error: template instance 
`std.traits.Parameters!(foo)` does not match template declaration 
`Parameters(func...)`

  with `func = (foo(T)(lazy T))`
  must satisfy the following constraint:
`   isCallable!func`



Aliasing current function template instance

2020-05-01 Thread Jean-Louis Leroy via Digitalmars-d-learn
Is it possible, inside a function template, to create an alias to 
the instantiated function? IOW the equivalent of __FUNCTION__, 
but yielding an alias?


The closest I came is:

  import std.string;
  import std.traits;

  void foo(T)(lazy T)
  {
mixin(
  "alias thisFunction = ",
  __FUNCTION__[0..__FUNCTION__.lastIndexOf('.')],
  ";");
pragma(msg, Parameters!thisFunction);
  }

  void main()
  {
foo(0);
foo("");
  }

  dmd -c aliasthisfunction.d
  (lazy int)
  (lazy string)

...but (unsurprisingly) this fails in presence of overloads. I.e. 
if I throw in:


  void foo(T)(int, T);

...then I get:

  aliasthisfunction.d(6): Error: template `aliasthisfunction.foo` 
matches more than one template declaration:

  aliasthisfunction.d(4): `foo(T)(lazy T)`
  and
  aliasthisfunction.d(20): `foo(T)(int, T)`
  ...

Something I have overlooked? Any ideas?



Re: describe-d: an introspection library

2020-04-22 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Wednesday, 22 April 2020 at 17:32:33 UTC, Stefan Koch wrote:


It's going to be part of the compiler.
You can look at the ... expression DIP.
which Manu posted in General, for taste of where my stuff is 
going.


I think I see the point - I am familiar with C++ variadic 
templates.


Yes, speeding up `staticMap`, and often eliminating the need to 
use it, will hugely benefit meta-programming.


However, that will not solve the problem of unnecessary 
instantiations that my example above demonstrates (it has a bug 
btw, the parameters should have been wrapped in a 
bolts.meta.AliasPack, but it doesn't alter the spirit).


Thank you for the `-vcg-ast` switch! It looks like I am going to 
use it a lot.


I am rewriting my system to express the accessors in terms of 
free functions taking meta-objects, instead of meta-objects 
containing properties. I have a hunch that that will curb 
instantiation, compile time and .o size.





Re: describe-d: an introspection library

2020-04-22 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Wednesday, 22 April 2020 at 17:16:28 UTC, Stefan Koch wrote:

I am working on a much more powerful and efficient meta 
programming system.


Great! Is it going to be in a library, or part of the compiler? 
Can we get a preview somewhere?





Re: describe-d: an introspection library

2020-04-22 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Wednesday, 22 April 2020 at 05:20:18 UTC, Stefan Koch wrote:
On Tuesday, 21 April 2020 at 14:43:04 UTC, Jean-Louis Leroy 
wrote:



I wonder if templates are lazily expanded. I haven't looked at 
the compiler's code, my guess is: maybe not.


If the template gets used it gets instantiated (and cached).


I did not word my question precisely, I meant: is it instantiated 
in its *entirety*.


Consider:

import std.meta;

template Function(Attributes...)
{
  enum isPure = Attributes[0];
  enum isNogc = Attributes[1];
  alias parameters = Attributes[2];
}

template Parameter(int i)
{
  // static assert(false);
}

template reflectFunction(alias Fun)
{
  alias reflectFunction = Function!(
true, true, staticMap!(Parameter, 1, 2, 3));
}

void foo();
pragma(msg, reflectFunction!(foo).isPure);

Is `Parameter` instantiated in this example? If I uncomment the 
assert, it fires. This is what gives me the impression that more 
is instantiated than is really used. And that is probably why 
reflecting runtime entities as template meta-objects with 
properties for all aspects of them is slow.


I am way of my field of competence here, but I have the 
impression that speeding this up would not require a change in 
the language (unless it is stated that templates are greedily 
expanded, and common idioms rely on this).


you can use the -vcg-ast switch to look at how your souce code 
looks "expandend".


I tried compiling my example with `dmd -vcg-ast -c tmt.d` and I 
did got neither an AST nor an error, and the option is not in 
`dmd -h`, where can I read about it?



They already gained traction, unfortunately.


Well...Two things. I ended up developing this approach because I 
needed to copy function attributes, UDAs, function parameter 
storage classes and UDAs to a generated function. If the 
language, or Phobos, provided me a more direct way, trust me, I 
would have used it. For example, storage classes are not part of 
a parameter's type. OK. Now you can use `Parameter!F[0]` to 
declare a parameter in a new function (great!), but you cannot 
say `__traits(getStorageClasses, F)[0] Parameter!F[0]`.


Also, one of D's selling points is that it does templates and 
meta-programming better. It's only natural that people use these 
features then (note that in C++, sorry for mentioning it, in my 
example Parameter would *not* be instantiated).




Function aliasing problem

2020-04-21 Thread Jean-Louis Leroy via Digitalmars-d-learn

I can alias a function template:

T f(T)(T x) { return x; }

alias g = f;
int a = g(42);

I can alias a static function:

struct S
{
  static int f(int i) { return i; }
}

alias sf = S.f;
int b = sf(42);

I can alias to a static function in a template instance:

struct SS(T)
{
  static T f(T i) { return i; }
}

alias ssi = SS!int.f;
int c = ssi(42);

Of course an alias can be templatized:

alias SSS(T) = SS!T;

I would like to combine them all, e.g.:

alias sst(T) = SS!T.f;
int d = sst(42); // <=> SS!int.f(42)

But it fails like this:

aliasstaticfunction.d(23): Error: template 
`aliasstaticfunction.sst` cannot deduce function from argument 
types `!()(int)`, candidates are:

aliasstaticfunction.d(22):`sst(T)`

In fact this simpler attempt fails in the same fashion:

alias g2(X) = f!X;
int e = g(42);

aliasstaticfunction.d(25): Error: template 
`aliasstaticfunction.g2` cannot deduce function from argument 
types `!()(int)`, candidates are:

aliasstaticfunction.d(24):`g2(X)`

I tried with an eponymous template declaring an alias, in place 
of the alias template. Unsurprisingly, I get the same error (the 
latter is lowered to the former isn't it?).


I also tried std.meta.Alias, to no avail.

Is there a solution, other than building a templatized forwarder 
function, e.g.:


T sst(T)(T i) { return SS!T.f(i); }
int d = sst(42);

(and this is not good anyway, as it drops function attributes, 
parameter storage classes, UDAs etc).


Re: describe-d: an introspection library

2020-04-21 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Wednesday, 15 April 2020 at 08:00:12 UTC, bogdan wrote:

I use a similar approach in openmethods. With the added twist 
that I need to re-create functions from existing functions, with 
some modifications (e.g. change the parameter types, add a 
parameter), while preserving function and parameter attributes. 
That inevitably leads to constructing mixin code (which I call 
"mixtures"), and it has to  work across module boundaries (i.e. 
use `ReturnType!F` in the mixture, not the stringified type).


See here:
https://github.com/jll63/openmethods.d/blob/master/source/openmethods.d#L503, 
here: 
https://github.com/jll63/openmethods.d/blob/master/source/openmethods.d#L568 
and here: 
https://github.com/jll63/openmethods.d/blob/master/source/bolts/reflection/metafunction.d

I did not shy away from using templates and indeed there is a 
significant increase in compilation time. On the other hand, the 
code is much cleaner than a previous iteration that created the 
mixtures directly.


If these techniques get traction, it will incite compiler 
developers to improve template instantiation, hopefully.


I wonder if templates are lazily expanded. I haven't looked at 
the compiler's code, my guess is: maybe not.


Re: openmethods 1.3.0

2020-04-20 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Monday, 20 April 2020 at 08:17:24 UTC, Robert M. Münch wrote:

I just read your blog post [1] and wonder if it's still 
up-to-date or maybe an update would make sense?


The blog post is still current. I remember that, in 2017, some 
were annoyed by the need to call a setup function 
(updateMethods). As for support for attributes, it is nice to 
have, but it is hardly the focus of the module. I don't think the 
improvements deserve a new blog entry.


However, in the process of implementing support for attributes 
and storage classes, the internals became very ugly. Also I had a 
to address the same problems in a new library. Eventually I found 
a way of factoring the mixin generation code in a package that I 
am going to spin off, probably as part of bolts. But I need 
permission from my employer to do that. I hope to get it soon.


This stuff sounds like a very fundamental concept/pattern and 
IMO would be a good member of Phobos.


Andrei is not convinced ;-) Well at least not as part of the 
language, but probably not as part of Phobos either.


That is not a problem. If I was granted two wishes, they would 
be: 1/ reallocate 'ClassInfo.deallocator' to me ;-) and 2/ add a 
more general feature to the language, similar to Perl's 'import' 
function: if a module defines a 'string imported(alias Module)' 
or a 'mixin template imported(alias Module)', call it in the 
context of the importing module. That would allow me to get rid 
of the 'mixin(registerMethods)' after the 'import openmethods'.




Re: openmethods 1.3.0

2020-04-19 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Sunday, 19 April 2020 at 13:13:55 UTC, Jean-Louis Leroy wrote:

You can read more about openmethods on githubL 
https://github.com/jll63/openmethods.d


Available on DUBS here: 
https://code.dlang.org/packages/openmethods





openmethods 1.3.0

2020-04-19 Thread Jean-Louis Leroy via Digitalmars-d-announce
This release implements support for function attributes, except 
for `pure`. User-defined attributes on methods and method 
parameters are also supported.


It is no longer necessary to call `updateMethods` explicitly, 
except after dynamically loading or unloading shared libraries.


The internals got a major cleanup. All the mixin generating code 
has been moved to a separate set of modules, which I plan to 
contribute to the bolts library.


You can read more about openmethods on githubL 
https://github.com/jll63/openmethods.d


Re: Extracting user defined attributes on function parameters

2020-04-17 Thread Jean-Louis Leroy via Digitalmars-d-learn

On Friday, 17 April 2020 at 18:05:39 UTC, Jean-Louis Leroy wrote:

Interesting example, but all hope is not lost. `a` could 
(should?) be passed as an alias in __parameters.


Okay I take this back...



Re: Extracting user defined attributes on function parameters

2020-04-17 Thread Jean-Louis Leroy via Digitalmars-d-learn

On Friday, 17 April 2020 at 17:48:06 UTC, Adam D. Ruppe wrote:
On Friday, 17 April 2020 at 17:31:32 UTC, Jean-Louis Leroy 
wrote:
Well, can't do. I need this purely at compile time, and 
cross-module.


And the CTFE engine gets weird with it too dmd will have to 
fix this.


But default parameters might not be possible in general at CT 
anyway... it is actually possible to define it to a variable. 
Observe:


int a;

void f(int arg = a) { // default arg is to use the global...
import std.stdio; writeln(arg);
}

void main() {
f(); // 0 this time
a = 4; // and it can be changed at runtime!
f(); // will now say 4
}


Interesting example, but all hope is not lost. `a` could 
(should?) be passed as an alias in __parameters.





Re: Extracting user defined attributes on function parameters

2020-04-17 Thread Jean-Louis Leroy via Digitalmars-d-learn

On Friday, 17 April 2020 at 16:54:42 UTC, Adam D. Ruppe wrote:

void main() {
import std.stdio;
writeln(ParameterDefaults!f.stringof);
}

and it is fine.


Well, can't do. I need this purely at compile time, and 
cross-module. That's for supporting UDAs and default parameter 
values in openmethods. If you want a peek at what I am up to, see 
here: 
https://github.com/jll63/openmethods.d/blob/bolts-reflection/source/bolts/reflection/metafunction.d


Re: Extracting user defined attributes on function parameters

2020-04-17 Thread Jean-Louis Leroy via Digitalmars-d-learn
Alas the presence of parameter UDAs breaks 
std.traits.ParameterDefaults:


import std.traits;

struct attr;
void f(@attr int);

pragma(msg, ParameterDefaults!f.stringof);

Error:

dmd -c bug.d
bug.d(4): Error: undefined identifier `attr`, did you mean 
variable `ptr`?

/home/jll/dlang/dmd-2.090.1/linux/bin64/../../src/phobos/std/traits.d(1526): 
Error: template instance `std.traits.ParameterDefaults!(f).Get!0LU` error 
instantiating
/home/jll/dlang/dmd-2.090.1/linux/bin64/../../src/phobos/std/traits.d(1529):
instantiated from here: `Impl!0LU`
bug.d(6):instantiated from here: `ParameterDefaults!(f)`
bug.d(6):while evaluating `pragma(msg, 
ParameterDefaults!(f).stringof)`


I filed a bug report (20744). And examined the code of 
ParameterDefaults. I think I understand how it works, for the 
most part, but I haven't been able to find a fix yet.


I'd like to understand why taking a slice of __parameters vs 
fetching the first element matters. What is the (meta?) type of 
__parameters[0..1]? I think I'd need to make a copy of it, minus 
the UDAs tucked at the beginning. But I haven't found a way of 
splitting it into smaller components. I tried using indexation 
and variadic template parameters, but it always collapses into a 
string. Makes me think of wave functions in quantum mechanics ;-)




Re: Extracting user defined attributes on function parameters

2020-04-15 Thread Jean-Louis Leroy via Digitalmars-d-learn

Thanks to both of you!

As part of implementing full support for attributes in 
openmethods, I am developing a reflection library. That helped a 
lot.


is() is a bit weird, but I described it in my "D Cookbook" to 
some success...


I am going to order it...even though it is not available on 
Kindle ;-)




Re: Extracting user defined attributes on function parameters

2020-04-14 Thread Jean-Louis Leroy via Digitalmars-d-learn

On Tuesday, 14 April 2020 at 21:44:51 UTC, Adam D. Ruppe wrote:
On Tuesday, 14 April 2020 at 21:35:12 UTC, Jean-Louis Leroy 
wrote:

I can see them:


There's some weird tricks to it. Check out my old blog sidebar 
about it here:


http://dpldocs.info/this-week-in-d/Blog.Posted_2019_02_11.html#how-to-get-uda-on-a-function-param


O.kay. It looks like `is` is D's Swiss army chainsaw. Yeah I 
never read the `is` doc properly. Now I am beginning to 
understand how `std.traits.Parameters` works.


Thanks!



Extracting user defined attributes on function parameters

2020-04-14 Thread Jean-Louis Leroy via Digitalmars-d-learn

I can see them:

import std.traits;

struct foo;
struct bar;

void f(@foo int, @foo @bar @("baz") real);

pragma(msg, Parameters!f);
// (@(foo) int, @(tuple(tuple(foo), tuple(bar)), 
tuple("baz")) real)


...but I cannot find how to get hold of them:

pragma(msg, (Mystery!f)[0]); // foo
pragma(msg, __traits(mystery, f)[0]); // foo

And besides the structure looks weird for the second argument. 
It's as if the UDAs were applied to one another, from left to 
right.


I did search the documentation and google for 1/2 hour.




Is-expression and immutable interface

2020-04-14 Thread Jean-Louis Leroy via Digitalmars-d-learn

How comes?

immutable struct Foo
{
}

pragma(msg, is(Foo == immutable)); // true

immutable interface Bar
{
}

pragma(msg, is(Bar == immutable)); // false



Re: ./install.sh dmd broken?

2018-08-21 Thread Jean-Louis Leroy via Digitalmars-d

On Monday, 13 August 2018 at 17:10:13 UTC, Jonathan Marler wrote:
The problem is downloading "install.sh" directly to 
"~/dlang/install.sh".  This causes the install script to think 
that it has already downloaded the "d-keyring.gpg" so it never 
downloads it, causing the "invalid signature" error.  The fix 
is to download "install.sh" if the d-keyring is not downloaded, 
even if install.sh already is.


Spot on! Thanks...


Re: ./install.sh dmd broken?

2018-08-10 Thread Jean-Louis Leroy via Digitalmars-d

On Friday, 10 August 2018 at 13:52:19 UTC, bachmeier wrote:
On Friday, 10 August 2018 at 13:19:21 UTC, Jean-Louis Leroy 
wrote:

jll@euclid:~/dlang$ ./install.sh dmd
Downloading and unpacking 
http://downloads.dlang.org/releases/2.x/2.081.1/dmd.2.081.1.linux.tar.xz

# 100.0%
Invalid signature 
http://downloads.dlang.org/releases/2.x/2.081.1/dmd.2.081.1.linux.tar.xz.sig


Same problem with 'install update'. But not when installing 
ldc or gdc.


It may be this:
https://issues.dlang.org/show_bug.cgi?id=19100


Probably not. I am trying to install dmd on a new machine I got 
in June.


./install.sh dmd broken?

2018-08-10 Thread Jean-Louis Leroy via Digitalmars-d

jll@euclid:~/dlang$ ./install.sh dmd
Downloading and unpacking 
http://downloads.dlang.org/releases/2.x/2.081.1/dmd.2.081.1.linux.tar.xz

# 100.0%
Invalid signature 
http://downloads.dlang.org/releases/2.x/2.081.1/dmd.2.081.1.linux.tar.xz.sig


Same problem with 'install update'. But not when installing ldc 
or gdc.


Re: Declaring a pointer to a function returning a ref

2018-07-31 Thread Jean-Louis Leroy via Digitalmars-d

On Tuesday, 31 July 2018 at 21:29:26 UTC, Jean-Louis Leroy wrote:
How do I declare a variable that contains a pointer to a 
function returning a reference?


  import std.stdio;

  int foo(return ref int a)
  {
a = 42;
return a;
  }

  ref int bar(return ref int a)
  {
a = 42;
return a;
  }

  void main()
  {
int x;
auto apf = 
writeln(typeid(apf)); // int function(return ref int)*
int function(return ref int) xpf = 

auto apb = 
writeln(typeid(apb)); // int function(return ref int) ref*

// int function(return ref int) ref xpb =  // Error: 
no identifier for declarator `int function(return ref int)`
// ref int function(return ref int) xpb =  // Error: 
variable `castfunc.main.xpb` only parameters or `foreach` 
declarations can be `ref`

  }


I know I could use `typeof() xpb = ` but I wonder if 
there is an explicit syntax.


Declaring a pointer to a function returning a ref

2018-07-31 Thread Jean-Louis Leroy via Digitalmars-d
How do I declare a variable that contains a pointer to a function 
returning a reference?


  import std.stdio;

  int foo(return ref int a)
  {
a = 42;
return a;
  }

  ref int bar(return ref int a)
  {
a = 42;
return a;
  }

  void main()
  {
int x;
auto apf = 
writeln(typeid(apf)); // int function(return ref int)*
int function(return ref int) xpf = 

auto apb = 
writeln(typeid(apb)); // int function(return ref int) ref*

// int function(return ref int) ref xpb =  // Error: no 
identifier for declarator `int function(return ref int)`
// ref int function(return ref int) xpb =  // Error: 
variable `castfunc.main.xpb` only parameters or `foreach` 
declarations can be `ref`

  }



Mysterious identifier in std.traits.ParameterStorageClassTuple

2018-07-24 Thread Jean-Louis Leroy via Digitalmars-d
What is `PT` here: 
https://github.com/dlang/phobos/blob/master/std/traits.d#L1224

Where does it come from?


static foreach and function generation

2018-07-23 Thread Jean-Louis Leroy via Digitalmars-d

Consider:

module genfun;

  import std.stdio, std.format, std.traits;

  void foo(int a) { writeln("foo(%s)".format(a)); }
  void foo(int a, int b) { writeln("foo(%s, %s)".format(a, b)); }

  static foreach (fun; __traits(allMembers, genfun)) {
static if (fun == "foo") {
  static if (is(typeof(__traits(getOverloads, genfun, fun 
{
static foreach (ovl; __traits(getOverloads, genfun, fun)) 
{

  void foobar(Parameters!ovl args) { // HERE
write("calling ");
foo(args); // HERE
  }
}
  }
}
  }

  void main()
  {
foobar(1); // calling foo(1)
foobar(1, 2); // calling foo(1, 2)
  }

Now I would like to change `foo` and `foobar` to calculated 
symbols where marked. I would also like to use as little string 
mixin as possible. I tried:


  static foreach (fun; __traits(allMembers, genfun)) {
static if (fun == "foo") {
  static if (is(typeof(__traits(getOverloads, genfun, fun 
{
static foreach (ovl; __traits(getOverloads, genfun, fun)) 
{

  void mixin(fun + "bar")(Parameters!ovl args) { // 1
write("calling ");
mixin(fun)(args); // 2
  }
}
  }
}
  }

This gets me halfway there: #2 works but #1 does not.

This works:

  static foreach (fun; __traits(allMembers, genfun)) {
static if (fun == "foo") {
  static if (is(typeof(__traits(getOverloads, genfun, fun 
{
static foreach (ovl; __traits(getOverloads, genfun, fun)) 
{

  void internal(Parameters!ovl args) {
mixin(fun)(args);
  }
  mixin("alias %sbar = internal;".format(fun));
}
  }
}
  }


Does anyone see a potential problems with this? Or a better 
solution? I would like to avoid the alias.




Re: D mentioned in Infoworld

2018-03-26 Thread Jean-Louis Leroy via Digitalmars-d

On Monday, 26 March 2018 at 16:13:17 UTC, Joakim wrote:
On Monday, 26 March 2018 at 15:52:11 UTC, Jean-Louis Leroy 
wrote:
...as a "programming languages you should learn now" - albeit 
somewhat dismissively ;-)


https://www.infoworld.com/article/3263395/application-development/the-programming-languages-you-should-learn-now.html


Eh, never bad to be mentioned in articles like that, could 
encourage some to try D.


Indeed!


D mentioned in Infoworld

2018-03-26 Thread Jean-Louis Leroy via Digitalmars-d
...as a "programming languages you should learn now" - albeit 
somewhat dismissively ;-)


https://www.infoworld.com/article/3263395/application-development/the-programming-languages-you-should-learn-now.html


Going from string to identifier

2018-02-21 Thread Jean-Louis Leroy via Digitalmars-d-learn

Here's what I am trying to do:

mixin template MakeFun(string ID, int X)
{
  int mixin(ID)() { return X; }
}

mixin MakeFun!("one", 1); // int one() { return 1; }

Alas I get:
makefunc.d(3): Error: no identifier for declarator `int`
makefunc.d(3): Error: found `{` when expecting `;`
makefunc.d(3): Error: declaration expected, not `return`
makefunc.d(4): Error: unrecognized declaration

Is there a shorter way than building the entire function 
definition as a string mixin? As in:


mixin template MakeFun(string ID, int X)
{
  import std.format;
  mixin(format("int %s() { return %s; }", ID, X));
}

mixin MakeFun!("one", 1);



Re: Alias vs templates

2018-02-21 Thread Jean-Louis Leroy via Digitalmars-d-learn
On Wednesday, 21 February 2018 at 20:27:29 UTC, Steven 
Schveighoffer wrote:

On 2/21/18 1:46 PM, Jean-Louis Leroy wrote:

[...]


I think because one is a function, which is allowed to be 
overloaded, the other is a symbol.


But clearly, there are some liberties taken when you are 
overloading function templates, as overloading them works just 
fine. I think this may have been a patch at some point (you 
didn't use to be able to overload template functions with 
normal functions).


It seems like a reasonable request that this code should work.



I just discovered that this works:

int baz(T)();

struct Baz {
  static int baz(T)(T x) { return x; }
}

alias baz(T) = Baz.baz!T;


Alias vs templates

2018-02-21 Thread Jean-Louis Leroy via Digitalmars-d-learn
I am trying to figure out a crispier syntax for templatized open 
methods. I am stumbling on this (see comments):


// dmd -run conflict.d
int foo();

struct Foo {
  static int foo(int x) { return x; }
}

alias foo = Foo.foo; // overload with an alias - OK

int bar(T)();
int bar(T)(T x) { return x; } // overloaded function templates - 
OK


int baz(T)();

struct Baz {
  static int baz(T)(T x) { return x; }
}

//alias baz = Baz.baz; // Error: alias conflict.baz conflicts 
with template conflict.baz(T)() at conflict.d(11)


void main()
{
  import std.stdio;
  writeln(foo(42)); // 42
  writeln(bar(666)); // 666
}

Why?


Re: nested module problem

2017-12-25 Thread Jean-Louis Leroy via Digitalmars-d-learn

On Sunday, 24 December 2017 at 22:17:23 UTC, Luís Marques wrote:
On Saturday, 2 September 2017 at 20:03:48 UTC, Jean-Louis Leroy 
wrote:

jll@ORAC:~/dev/d/tests/modules$ tree
.
├── foo
│   └── bar.d
└── foo.d


I think that shouldn't be allowed. You have a package foo, but 
use a normal module instead of foo/package.d. I'm going to file 
a bug on that.


Monkey testing haha!


Re: Multiple inheritance D entry on rosettacode.org

2017-12-25 Thread Jean-Louis Leroy via Digitalmars-d

On Thursday, 21 December 2017 at 04:15:14 UTC, user1234 wrote:
Do you refer to static inheritance using multiple alias this ? 
If so, maybe you don't know yet that this feature is not 
implemented for now.


Yes. I didn't realize it was still science fiction ;-) Ah, good 
think I passed the baton on this.


Multiple inheritance D entry on rosettacode.org

2017-12-20 Thread Jean-Louis Leroy via Digitalmars-d

See http://rosettacode.org/wiki/Inheritance/Multiple#D

I feel that the entry is incomplete. I am a supported of 
full-fledged MI, à la Common Lisp or C++, and the argument that 
interfaces solve most problems that MI solves, for less of a 
hassle, leaves me completely cold, even cynical.


However, D is the first language that I have encountered that 
offers a real, manageable alternative to MI, as described in 
Andrei's book.


So I think it would be good if someone - Ali? - could expand that 
entry a bit. I could do it but I am still a rookie in D and I 
prefer it to be done by someone who is more seasoned than me.




Re: Cyclic dependencies vs static constructors

2017-12-19 Thread Jean-Louis Leroy via Digitalmars-d

On Tuesday, 19 December 2017 at 18:30:22 UTC, Luís Marques wrote:
On Tuesday, 19 December 2017 at 17:43:46 UTC, Jean-Louis Leroy 
wrote:

class Role
{
  Role[] companies;


I think he meant Company[] companies


Yes thanks.


Cyclic dependencies vs static constructors

2017-12-19 Thread Jean-Louis Leroy via Digitalmars-d
This has come up in a private discussion with Luís Marques. 
Consider:


import std.stdio;

import openmethods;
mixin(registerMethods);

class Company
{
  Employee[] employees;

}

class Startup : Company
{

}

class Role
{
  Role[] companies;
}

class Founder : Role
{

}

class Employee : Role
{

}

void main()
{
// blah blah blah
}

As the program grows bigger, I want to split it into several 
modules, e.g. one per class or one per hierarchy. Now I have 
cyclic dependencies between modules because role.d must 'import 
company' and 'company.d' must 'import role'.


It seems that at this point I have forgone a language feature: 
static constructors. They may be needed if I want to implement 
e.g. a global registry in Role and Company that tracks all the 
instances of the classes in their respective hierarchy.


At this point the only workaround I see is to add base interfaces 
under Role and Company and establish the bi-directional 
relationship in terms of the said interfaces.


...or I can throw in that flag that allows cyclic deps in 
presence of static constructors. Eventually I may run into 
trouble.


Have I overlooked something?


Re: Extending D to support per-class or per-instance user-defined metadata

2017-12-11 Thread Jean-Louis Leroy via Digitalmars-d
I realize that I focused too much on the how, and not enough on 
the why.


By "metadata" I mean the data that is "just there" in any object, 
in addition to user defined fields.


An example of per-class metadata is the pointer to the the 
virtual function table. It is installed by the compiler or the 
runtime as part of object creation. It is the same for all the 
instances of the same class.


Just like virtual functions, my openmethods library uses "method 
tables" and needs a way of finding the method table relevant to 
an object depending on its class. I want the library to work with 
objects of any classes, without requiring modifications to 
existing classes. Thus, there is a need to add that information 
to any object, in an orthogonal manner. Openmethods has two ways 
of doing this (one actually hijacks the deprecated 'deallocator' 
field in ClassInfo) but could profit from the ability to plant 
pointers right inside objects.


Examples of per-object metadata could be: a reference count, a 
time stamp, an allocator, or the database an object was fetched 
from.




Extending D to support per-class or per-instance user-defined metadata

2017-12-11 Thread Jean-Louis Leroy via Digitalmars-d
I just had a discussion with Walter, Andrei and Ali about open 
methods. While Andrei is not a great fan of open methods, he 
likes the idea of improving D to better support libraries that 
extend the language - of which my openmethods library is just an 
example. Andrei, correct me if I misrepresented your opinion in 
this paragraph.


Part of the discussion was about a mechanism to add user-defined 
per-object or per-class metadata (there's another part that I 
will discuss in another thread).


Andrei's initial suggestion is to put it in the vtable. If we 
know the initial size of the vtable, we can grow it to 
accommodate new slots. In fact we can already do something along 
those lines...sort of:


import std.stdio;

class Foo {
  abstract void report();
}

class Bar : Foo {
  override void report() { writeln("I'm fine!"); }
}

void main() {
  void*[] newVtbl;
  auto initVtblSize = Bar.classinfo.vtbl.length;
  newVtbl.length = initVtblSize + 1;
  newVtbl[0..initVtblSize] = Bar.classinfo.vtbl[];
  newVtbl[initVtblSize] = cast(void*) 0x123456;
  byte[] newInit = Bar.classinfo.m_init.dup;
  *cast(void***) newInit.ptr = newVtbl.ptr;
  Bar.classinfo.m_init = newInit;
  Foo foo = new Bar();
  foo.report(); // I'm fine!
  writeln((*cast(void***)foo)[initVtblSize]); // 123456
}

This works with dmd and gdc, not with ldc2. But it gives an idea 
of what the extension would like.


A variant of the idea is to allocate the user slots *before* the 
vtable and access them via negative indices. It would be faster.


Of course we would need a thread safe facility that libraries 
would call to obtain (and release) slots in the extended vtable, 
and return the index of the allocated slot(s). Thus a library 
would call an API to (globally) reserve a new slot; then another 
one to grow the vtable of the classes it targets (automatically 
finding and growing all the vtables is unfeasible because nested 
classes are not locatable via ModuleInfo).


Walter also reminded me of the __monitor field so I played with 
it too. Here is prototype of what per-instance user defined slots 
could look like.


import std.stdio;

class Foo {
}

void main() {
  byte[] init;
  init.length = Foo.classinfo.m_init.length;
  init[] = Foo.classinfo.m_init[];
  (cast(void**) init.ptr)[1] = cast(void*) 0x1234;
  Foo.classinfo.m_init = init;
  Foo foo = new Foo();
  writeln((cast(void**) foo)[1]); // 1234 with dmd and gdc, null 
with ldc2

}

This works with dmd and gdc but not with ldc2.

This may be useful for implementing reference-counting schemes, 
Observers, etc.


In both cases I use the undocumented 'm_init' field in ClassInfo. 
The books and docs do talk about the 'init' field that is used to 
initialize structs, but I have found no mention of 'm_init' for 
classes. Perhaps we could document it and make it mandatory that 
an implementation uses its content to pre-initialize objects.


Also here I am using the space reserved for the '__monitor' 
hidden field. This is a problem because 1/ it will go away some 
day 2/ it is only one word. Granted, that word could store a 
pointer to a vector of words, where user-defined slots would 
live; but that would be at the cost of performance.


Finally, note that if you have per-instance user slots and a way 
of automatically initializing them when an object is created, 
then you also have per-class user-defined metadata: just allocate 
a slot in the object, and put a pointer to the data in it.


Please send in comments, especially if you are a library author 
and have encountered a need for this kind of thing. Eventually 
the discussion may lead to the drafting of a DIP.






Re: Posting in DLang Study

2017-12-08 Thread Jean-Louis Leroy via Digitalmars-d
On Friday, 8 December 2017 at 15:57:02 UTC, Steven Schveighoffer 
wrote:

On 12/8/17 10:47 AM, Jean-Louis Leroy wrote:
I notice that all thread subjects are formatted 
[Dlang-study][topic] Description. Is the [Dlang-study] tag 
automatically added by the forum, or should I add it myself?


Hmm.. I don't thing many people look at that forum.

I have no idea whether [Dlang-study] is added automatically, I 
would expect not.


-Steve


Yeah last post dates from almost one year ago. Maybe not the best 
place to start a topic to which I want to attract library writers 
(it's about an API for extending/manipulating the vtable).


Posting in DLang Study

2017-12-08 Thread Jean-Louis Leroy via Digitalmars-d
I notice that all thread subjects are formatted 
[Dlang-study][topic] Description. Is the [Dlang-study] tag 
automatically added by the forum, or should I add it myself?


Re: minimal object.d implementation that allows classes

2017-12-08 Thread Jean-Louis Leroy via Digitalmars-d

On Friday, 8 December 2017 at 14:59:12 UTC, Jacob Carlborg wrote:

On 2017-12-07 16:09, Jean-Louis Leroy wrote:

This experiment is related to an ongoing discussion with 
Walter, Andrei and Ali on extending D with general mechanisms 
to better support libraries like openmethods. I will post in 
Studies soon.


Modifying the vtable can be useful for mocking and stubbing 
methods as well.


Indeed. The initial vtable is in read only memory, but the 
re-allocated one is writeable.


Re: minimal object.d implementation that allows classes

2017-12-07 Thread Jean-Louis Leroy via Digitalmars-d
On Thursday, 7 December 2017 at 15:34:09 UTC, Steven 
Schveighoffer wrote:

On 12/7/17 10:21 AM, Jean-Louis Leroy wrote:
Bar.classinfo.vtbl.ptr[Bar.classinfo.vtbl.length] = 
cast(void*) 0x123456;


This is a buffer overflow, why are you doing this specifically?

-Steve


It's not an overflow because of the call to `reserve`. It is part 
of an experiment related to supporting user-defined per-class 
metadata by extending the vtable.


Re: minimal object.d implementation that allows classes

2017-12-07 Thread Jean-Louis Leroy via Digitalmars-d
On Thursday, 7 December 2017 at 15:09:45 UTC, Jean-Louis Leroy 
wrote:
On Thursday, 7 December 2017 at 14:59:57 UTC, Steven 
Schveighoffer wrote:

The object is constructed here: [...]


Thanks for the pointers, you've saved me a lot of time :)

On a side note however, you really shouldn't change data in a 
ClassInfo at all, and probably the compiler shouldn't let you!


This experiment is related to an ongoing discussion with 
Walter, Andrei and Ali on extending D with general mechanisms 
to better support libraries like openmethods. I will post in 
Studies soon.


Cool:

import std.stdio;

class Foo {
  abstract void report();
}

class Bar : Foo {
  override void report() { writeln("I'm fine!"); }
}

void main() {
  auto oldPtr = Bar.classinfo.vtbl.ptr;
  Bar.classinfo.vtbl.reserve(1000);
  Bar.classinfo.vtbl.ptr[Bar.classinfo.vtbl.length] = cast(void*) 
0x123456;

  writeln(oldPtr != Bar.classinfo.vtbl.ptr); // true
  *cast(void***) Bar.classinfo.m_init.ptr = 
Bar.classinfo.vtbl.ptr;

  Foo foo = new Bar();
  writeln(oldPtr == *cast(void***)foo); // false
  foo.report(); // I'm fine!
  writeln((*cast(void***)foo)[Bar.classinfo.vtbl.length]); // 
123456

}



Re: minimal object.d implementation that allows classes

2017-12-07 Thread Jean-Louis Leroy via Digitalmars-d
On Thursday, 7 December 2017 at 14:59:57 UTC, Steven 
Schveighoffer wrote:

The object is constructed here: [...]


Thanks for the pointers, you've saved me a lot of time :)

On a side note however, you really shouldn't change data in a 
ClassInfo at all, and probably the compiler shouldn't let you!


This experiment is related to an ongoing discussion with Walter, 
Andrei and Ali on extending D with general mechanisms to better 
support libraries like openmethods. I will post in Studies soon.


Re: minimal object.d implementation that allows classes

2017-12-07 Thread Jean-Louis Leroy via Digitalmars-d

On Thursday, 7 December 2017 at 13:08:09 UTC, Luís Marques wrote:

On Thursday, 7 December 2017 at 08:59:08 UTC, Wild wrote:
You could modify the one I use for PowerNex[1]. It is a hacked 
version of Adam D. Ruppes
minimal.zip. There are only a few imports for strlen, 
mem{set,move,cpy}, etc.


This one seems to be the one for me. For instance, 
typeid(ClassName) seems to work, which I need.


For completeness, I had looked into minlibd but it didn't 
seemed compatible with LDC and difficult for me to fix, IIRC. 
Regarding Mike's question of what my use case is, I wanted my 
program to run in webassembly/asmjs. Since druntime/phobos 
haven't been ported to that target, I was being careful with my 
design to not depend on the runtime, but then I found out I 
love the openmethods package. So I decided to check if I could 
implement just enough of druntime to allow a forked version of 
openmethods to work. As far as I can  tell that's feasible.


I am currently trying to understand how the compiler and the 
runtime interact. ClassInfo contains a vtbl array whose ptr 
property is the same as the vptr found in an instance of that 
class. However, when I modify that pointer (e.g. by reserving 
1000 more entries) and create a new instance, it still contains 
the old pointer. So it looks like the compiler sets the vptr 
without consulting the ClassInfo but somehow reflects it there. 
I'd appreciate if anybody can explain how it works, or sends me 
links to relevant info.


Example:

import std.stdio;

class Foo {
  void foo() {}
}

void main() {
  auto oldPtr = Foo.classinfo.vtbl.ptr;
  Foo.classinfo.vtbl.reserve(1000);
  writeln(oldPtr != Foo.classinfo.vtbl.ptr); // true
  Object foo = new Foo();
  writeln(oldPtr == *cast(void***)foo); // true, alas
}

...at least that's what I get with dmd.



[openmethods] Support for templatized methods

2017-10-08 Thread Jean-Louis Leroy via Digitalmars-d
Following a request from a couple of users to make it possible to 
use open methods and templates together, I toyed with a couple of 
ideas, until I discovered that the current implementation 
supports method and override templates already...well, almost, 
because there is a need to navigate around a couple of bugs (or 
limitations) in the various D compilers.


I have an example in a branch 
(https://github.com/jll63/openmethods.d/tree/method-template-example) that adds a new mixin for manually registering classes - to be used for class template instantiations, which do not appear on ModuleInfo.localClasses. Apart from that the existing machinery is up to the task - although it requires some help from the user. Here is the gist of it (complete example here: https://github.com/jll63/openmethods.d/blob/method-template-example/tests/methodtemplates.d):


  class Matrix(T) {}
  class DenseMatrix(T) : Matrix!(T) {}
  class DiagonalMatrix(T) : Matrix!(T) {}

  template declareMatrixMethods(T)
  {
mixin registerClasses!(Matrix!T);
mixin registerClasses!(DenseMatrix!T);
mixin registerClasses!(DiagonalMatrix!T);

Matrix!T times(virtual!(Matrix!T), T);
Matrix!T times(T, virtual!(Matrix!T));
  }

  mixin(registerMethods("declareMatrixMethods!double"));
  mixin(registerMethods("declareMatrixMethods!int"));

  template matrixMethods(T)
  {
@method DenseMatrix!T _times(Matrix!T m, T s) { return new 
DenseMatrix!T; }
@method DenseMatrix!T _times(T s, Matrix!T m) { return new 
DenseMatrix!T; }
@method DiagonalMatrix!T _times(DiagonalMatrix!T m, T s) { 
return new DiagonalMatrix!T; }
@method DiagonalMatrix!T _times(T s, DiagonalMatrix!T m) { 
return new DiagonalMatrix!T; }

  }

  mixin(registerMethods("matrixMethods!double"));
  mixin(registerMethods("matrixMethods!int"));

Now it would be nice if we could do away with the explicit 
instantiations...in theory it could be done - any time a method 
template is called, trigger the instantiation of all the 
templatized overrides -, but this is beyond the power of a 
library. Even with support at language level, it would probably 
require a pre-link phase.


I am going to sleep on this a couple more times before 
documenting it and officially support it. I will probably add an 
overload to registerMethods so we can say 
'registerMethods!(matrixMethods!double)'; I don't like passing 
types as strings very much.


As always, comments and suggestions are encouraged.



Re: Compile-time reflection and templates

2017-09-27 Thread Jean-Louis Leroy via Digitalmars-d

On Wednesday, 27 September 2017 at 20:04:42 UTC, jmh530 wrote:
On Wednesday, 27 September 2017 at 19:47:32 UTC, Jean-Louis 
Leroy wrote:


I'd like to go further: find the template arguments and the 
function arguments and return types. Looking at __traits and 
std.traits, it doesn't seem feasible, but maybe I overlooked 
something?


You can use TemplateArgsOf
https://dlang.org/phobos/std_traits.html#TemplateArgsOf
to get the template arguments.

For the stuff below, I think you can't just use foo, it has to 
be a specific foo!T.


You can test if it's a function
https://dlang.org/phobos/std_traits.html#isFunction

You can get the Parameter and Return types
https://dlang.org/phobos/std_traits.html#Parameters
https://dlang.org/phobos/std_traits.html#ReturnType

You can get the names of parameters
https://dlang.org/phobos/std_traits.html#ParameterIdentifierTuple


I am aware of these but TemplateArgsOf takes a template 
*instantiation* and returns the arguments. I want to reflect the 
*template*.


Here what I am trying to achieve (for openmethods). Given:

  Matrix!T times(T, virtual!(Matrix!T));

...inject, at compile time (in 'mixin(registerMethods)'), the 
following code:


  Matrix!T times(T)(T s, Matrix!T m) {
return Method!("times", "deallocator", Matrix!T, T, 
virtual!(Matrix!T)).dispatcher(s, m);

  }

  Method!("times", "deallocator", Matrix!T, T, 
virtual!(Matrix!T)) times(T)(MethodTag, T s, Matrix!T m);






Compile-time reflection and templates

2017-09-27 Thread Jean-Louis Leroy via Digitalmars-d

I can identify the templates in a module:

  module modtemp;

  import std.stdio;
  import std.traits;

  void foo(T)(T x) {}

  void main()
  {
foreach (m; __traits(allMembers, modtemp)) {
  if (__traits(isTemplate, mixin(m))) {
mixin("alias F = " ~ m ~ ";");
writeln(m);
  }
}
  }
  // output:
  // foo

I'd like to go further: find the template arguments and the 
function arguments and return types. Looking at __traits and 
std.traits, it doesn't seem feasible, but maybe I overlooked 
something?






Re: Finding class template instantiations via runtime reflection (for openmethods)

2017-09-26 Thread Jean-Louis Leroy via Digitalmars-d

On Tuesday, 26 September 2017 at 04:55:46 UTC, b4s1L3 wrote:
On Thursday, 21 September 2017 at 20:32:38 UTC, Jean-Louis 
Leroy wrote:

[...]


Yeah. You can setup a custom registry that maps names to their 
TypeInfo_Class.
I do something similar in iz (though the real point in iz is a 
GC-free factory but the principle of the registry would be the 
the same for you)


Example:

---
/+ dub.sdl:
   name "dub_script"
   dependency "iz" version="0.6.0"
+/
module dub_script;

import iz.memory, std.stdio;

class Foo(T){this(){writeln("fooDeInt");}}
TypeInfo_Class[string] registry; // you need that...

static this()
{
registerFactoryClass!(Foo!int)(registry); // ...and that, 
maybe  with another name

}

void main()
{
auto fooDeInt = iz.memory.factory(registry, "Foo!int");
destruct(cast(Object) fooDeInt);
}
---


Yeah that's what I implemented yesterday (not pushed yet).

I have a prototype of a solution for using open methods and 
templates together - although the syntax is not light: it 
requires guidance from the user (a la C++ explicit template 
instantiation).


Re: Finding class template instantiations via runtime reflection (for openmethods)

2017-09-26 Thread Jean-Louis Leroy via Digitalmars-d
On Tuesday, 26 September 2017 at 15:59:01 UTC, Jacob Carlborg 
wrote:

On 2017-09-25 16:24, Jean-Louis Leroy wrote:
On Monday, 25 September 2017 at 14:17:13 UTC, Jacob Carlborg 
wrote:
Of course, that's a bit of a PITA, but you would not be 
dependent on any bugs getting fixed or new 
features/improvements implemented.


How do you do that?


On Posix you use "dlopen", passing in null as the filename to 
get a handle to the current executable. Then you iterate the 
sections until you find the symbol table. For macOS there's 
this reference for the Mach-O binary format [1]. For Mach-O 
files there's this helper function as well [3].


[1] 
https://web.archive.org/web/20090901205800/http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html


[2] getsectbynamefromheader_64


Ah, I suspected that. I don't want to go down that path, what of 
Windows? But thanks anyway...


Re: Finding class template instantiations via runtime reflection (for openmethods)

2017-09-25 Thread Jean-Louis Leroy via Digitalmars-d
On Monday, 25 September 2017 at 14:17:13 UTC, Jacob Carlborg 
wrote:
Of course, that's a bit of a PITA, but you would not be 
dependent on any bugs getting fixed or new 
features/improvements implemented.


How do you do that?


Re: Finding class template instantiations via runtime reflection (for openmethods)

2017-09-25 Thread Jean-Louis Leroy via Digitalmars-d

On Monday, 25 September 2017 at 13:57:55 UTC, Biotronic wrote:
On Monday, 25 September 2017 at 13:45:05 UTC, Jean-Louis Leroy 
wrote:

Thank you all for your input. I will file a bug report.


Just reopen the old one:
https://issues.dlang.org/show_bug.cgi?id=2484

--
  Biotronic


Done, thanks.


Re: Finding class template instantiations via runtime reflection (for openmethods)

2017-09-25 Thread Jean-Louis Leroy via Digitalmars-d

Thank you all for your input. I will file a bug report.



Re: Finding class template instantiations via runtime reflection (for openmethods)

2017-09-25 Thread Jean-Louis Leroy via Digitalmars-d

On Sunday, 24 September 2017 at 04:30:26 UTC, user1234 wrote:
aliases are not symbol so it's expected that 'BarInt' doesn't 
appear in the items.


I didn't really expect that either.




Finding class template instantiations via runtime reflection (for openmethods)

2017-09-21 Thread Jean-Louis Leroy via Digitalmars-d
It did not take long! Someone tried to create templatized open 
methods and it didn't work right of the box. I expected that, but 
in fact there may be a bit of hope. You cannot have virtual 
function templates in C++ or in D because the layout of the 
vtables have to be known at compile time - but openmethods 
creates its method tables at runtime so maybe it can be made to 
work.


I stumbled upon a problem very quickly: it seems that classes 
that come from class template instantiations are not registered 
in ModuleInfo - see below,


import std.stdio;

class Foo {}

class Bar(T) : Foo
{
  int i;
}

alias BarInt = Bar!int;

const barInt = new BarInt;

void main()
{
  foreach (mod; ModuleInfo) {
foreach (c; mod.localClasses) {
  writeln(c);
}
  }
}

...output:
modtemp.Foo
core.exception.RangeError
core.exception.AssertError
etc...

Neither 'Bar!int' nor 'BarInt' appear in 'localClasses'.

Ideas?



Re: Testing whether static foreach is available

2017-09-09 Thread Jean-Louis Leroy via Digitalmars-d

On Saturday, 9 September 2017 at 16:53:19 UTC, jmh530 wrote:
On Saturday, 9 September 2017 at 16:30:51 UTC, Jean-Louis Leroy 
wrote:


Also, is it possible to conditionally compile depending on the 
compiler's version, not only the compiler (I mean, not compile 
a block if it's GDC version 5.4.1 or lower)?


What you really need is a version statement based on the 
version of the D language, not the version of DMD or LDC or GDC 
per se.


Something like

version(DLANGSEMVER >= 2.076.0)
{
   //include static foreach code.
}

but we can't do conditionals in version blocks, so you'd need a 
static if. Alternately, we'd also need a trait or something to 
get the semver of the compiler.


For some of my needs (like here 
https://github.com/jll63/openmethods.d/blob/v1.0.0-rc.2/source/openmethods.d#L1509) 'static if' would work. But I'd really like to provide a template mixin alternative to the string mixin I use in openmethods ('mixin(registerMethods)'). Hmmm...Generally speaking, the lack of [your suggestion] will slow down the adoption of new cool features like 'static foreach'.


Testing whether static foreach is available

2017-09-09 Thread Jean-Louis Leroy via Digitalmars-d
Is there a way to test whether 'static foreach' is available, 
e.g. via a version symbol?


Also, is it possible to conditionally compile depending on the 
compiler's version, not only the compiler (I mean, not compile a 
block if it's GDC version 5.4.1 or lower)?


I did look at the docs, several times, couldn't find it...



Re: nested module problem

2017-09-02 Thread Jean-Louis Leroy via Digitalmars-d-learn
On Saturday, 2 September 2017 at 21:42:59 UTC, Moritz Maxeiner 
wrote:
On Saturday, 2 September 2017 at 21:24:19 UTC, Jean-Louis Leroy 
wrote:

[...]


Yes, these now both fail because you cannot have a module `foo` 
and a package `foo` at the same time (they share a namespace), 
I forgot about that.



[...]


(same as before, no issue here)


[...]


You created the 'foo' package by specifying `module foo.bar` in 
foo/bar.d.



[...]


AFAIK you can't; consider:

-- baz.d ---
import foo;


in the same directory as foo.d. If foo/package.d exists (with 
`module foo` inside), what should baz.d import? foo.d or 
foo/package.d?
The point being that we could have either used foo/package.d or 
foo.d for a package file, but not both (as that would allow 
ambiguity) and package.d was chosen.


[1] https://dlang.org/spec/module.html#package-module


Hmmm I see...I was thinking of spinning the runtime part of my 
openmethods library into its own module (like here 
https://github.com/jll63/openmethods.d/tree/split-runtime/source/openmethods) but it looks like a bad idea...


Re: nested module problem

2017-09-02 Thread Jean-Louis Leroy via Digitalmars-d-learn
On Saturday, 2 September 2017 at 20:48:22 UTC, Moritz Maxeiner 
wrote:
So the compiler wants you to import it by the name it has 
inferred for you (The fix being either specifying the module 
name in foo/bar.d as `module foo.bar`, or importing it as via 
`import bar;` in foo.d).

[1] https://dlang.org/spec/module.html


I thought of doing that, it merely changed the error. OK now I 
have:


in foo.d:
module foo;
import foo.bar;

in foo/bar.d:
module foo.bar;

$ dmd -c foo.d foo/bar.d
foo/bar.d(1): Error: package name 'foo' conflicts with usage as a 
module name in file foo.d


If I compile separately:
jll@ORAC:~/dev/d/tests/modules$ dmd -I. -c foo.d
foo/bar.d(1): Error: package name 'foo' conflicts with usage as a 
module name in file foo.d

jll@ORAC:~/dev/d/tests/modules$ dmd -I. -c foo/bar.d

It believes that 'foo' is a package...because there is a 'foo' 
directory?


I see that a workaround is to move foo.d to foo/package.d but I 
would like to avoid that.






Re: Open Methods: From C++ to D

2017-09-02 Thread Jean-Louis Leroy via Digitalmars-d-announce
On Saturday, 2 September 2017 at 20:55:13 UTC, EntangledQuanta 
wrote:


This is when I have the mixin(registerMethods) in a module that 
doesn't use any open methods. It says add once per module in 
the help, but I think it means once per module where open 
methods are used?


Yes I meant that. The README.md says "Every module that declares 
methods or define implementations must include the following 
line". Ah yes the ddoc. I should update it.


Also I think I should allow the mixin to silently do nothing in 
this case. Good catch.


You might look in to adding updateMethods in a static this() 
since it will be ran per process and do everything necessary, I 
think.


Alas it won't work. Method registration is done via static ctors 
and they have to run - all of them - before updateMethods can do 
its work. In simple, one-module programs updateMethods in a 
static ctor will work, but in general it won't.


Strangely enough, I had a protected member that I was using and 
it works, I guess because I defined the openmethod in the same 
module. I changed it to private and it worked too. So the 
issues about encapsulation I thought about before may be 
irrelevant as long as the openmethods are used in the same 
module(which is a nice feature of D).


Neither the methods nor their overrides enjoy special privileges. 
Unless the override (i.e. the thing preceded by @method) is a 
static member function? But I don't think so. Currently my code 
just scans the direct member of the module in which 
mixin(registerMethods) is called. Although I could change that, 
thus giving privileged access to some overrides. Could be useful 
for 1-methods.


But anyway, probably there's something you don't 
notice...hmmm...can you share that code?


Thanks for the feedback.



nested module problem

2017-09-02 Thread Jean-Louis Leroy via Digitalmars-d-learn

So I have:

jll@ORAC:~/dev/d/tests/modules$ tree
.
├── foo
│   └── bar.d
└── foo.d

foo.d contains:
import foo.bar;

bar.d is empty.

Now I try compiling:
jll@ORAC:~/dev/d/tests/modules$ dmd -c foo.d
jll@ORAC:~/dev/d/tests/modules$ dmd -c foo/bar.d

So far so good. Now I try it the way dub does it:
jll@ORAC:~/dev/d/tests/modules$ dmd -c foo.d foo/bar.d
foo.d(1): Error: module bar from file foo/bar.d must be imported 
with 'import bar;'


What's up?



Re: Open Methods: From C++ to D

2017-09-02 Thread Jean-Louis Leroy via Digitalmars-d-announce
On Thursday, 31 August 2017 at 23:37:03 UTC, EntangledQuanta 
wrote:

[Windows]
I'll try again at some point. I haven't got around to messing 
with it again.


Did you get a chance?


Re: Open Methods: From C++ to D

2017-08-31 Thread Jean-Louis Leroy via Digitalmars-d-announce
On Thursday, 31 August 2017 at 21:42:50 UTC, EntangledQuanta 
wrote:

It's fixed now, in master and in release v1.0.0-rc.2.


I'll check it out. I don't think the last errors I was getting 
were due to the sizing issues though, so is that all you fixed 
or was there some other stuff related to windows?


Only size issues. Two lines in fact, see 
https://github.com/jll63/openmethods.d/commit/b63a88132e639bb23bb7cb305f4457450f865c6a but errors can cascade. I ran a few examples using the current dmd on Windows. Worked OK.


It would be nice to have the Windows equivalent of 
dev/run-everything, maybe someone can PR me that?


Yeah, but one should always be allowed to shoot themselves in 
the foot.


I agree, wholeheartedly. In C++, yomm11 has macros that you can 
use to make a specific override or an entire method friend of a 
class. But alas no friendship in D.




Re: Open Methods: From C++ to D

2017-08-31 Thread Jean-Louis Leroy via Digitalmars-d-announce
On Thursday, 31 August 2017 at 20:42:36 UTC, EntangledQuanta 
wrote:

On Wednesday, 30 August 2017 at 18:16:47 UTC, jmh530 wrote:
On Wednesday, 30 August 2017 at 15:59:32 UTC, Jean-Louis Leroy 
wrote:
What happens here is that kick(Animal) is shadowed by 
kick(Dog). kick(Animal) is a method but it appears to the 
user and the compiler as an ordinary function - which is 
generally good. As such it is eligible for UFCS. I would not 
recommend this sort of coding, but it's everyone's choice, 
methods or not.


Likewise, methods can be overloaded (like here 
https://github.com/jll63/openmethods.d/blob/1.0.0-rc.1/examples/matrix/source/matrix.d#L12).


A current limitation is that default arguments are not 
supported (yet), although I think it's just a matter of 
putting the effort in.


UFCS interacts nicely with methods because you can say 
a.plus(b) even if 'plus' is an open method.


I can submit this as an issue on the github page, but I 
figured I'd mention it here in case there was some easy fix.


I tried installing the latest release from github. Compiling 
(Windows 7 on DMD with default options) the simple program 
below


import openmethods;
mixin(registerMethods);

void main()
{
}

gives me the errors:

..\..\dubFolder\openmethods.d-1.0.0-rc.1\source\openmethods.d(970,21): Error: ca
nnot implicitly convert expression h of type ulong to uint
..\..\dubFolder\openmethods.d-1.0.0-rc.1\source\openmethods.d(1076,34): Error: c
annot implicitly convert expression dim of type ulong to uint
..\..\dubFolder\openmethods.d-1.0.0-rc.1\source\openmethods.d(1177,23): Error: c
annot implicitly convert expression h of type ulong to uint
dmd failed with exit code 1.

The error at line 1076 can be fixed by changing the type of 
dim in the function to size_t. I couldn't fix the other 
errors. I tried having the hash function return size_t also, 
but that just causes other problems.


I was getting similar errors and simply added a 
cast(size_t)[used in the indexing, as he used ulongs for 
indexes rather than size_t] to all those you mention. After 
that I got more errors that I can't recall now but was much 
more cryptic. I did updateMethods and added the mixin but 
things wern't working so I gave up. Seems like a nice idea, 
although, the downside that I see is one doesn't get 
encapsulation.


It's fixed now, in master and in release v1.0.0-rc.2.

Actually not getting encapsulation is good. With vfuncs, if you 
want polymorphism you get access to private parts, need it or 
not. And most of the time you neither need nor want it.


If you need polymorphism and privileged access, you should use a 
vfunc but it's usually a sign of bad design, because a vfunc is 
meant to be overridden. And the override won't have access to the 
private parts so you may end up changing access from private to 
protected and usually trouble follows.


I can imagine legitimate cases though. Fox example, the 
DiagonalMatrix addition example. In that case you can write a 
public final member function that performs addition using 
privileged access and call that from the 2-method 'plus'.




ANother approach is to write the fvunc - or the 1-method - in 
terms of the public interface. Usually it's feasible and yields a 
better design.


Re: Open Methods: From C++ to D

2017-08-31 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Thursday, 31 August 2017 at 14:52:43 UTC, jmh530 wrote:
On Wednesday, 30 August 2017 at 15:59:32 UTC, Jean-Louis Leroy 
wrote:


What happens here is that kick(Animal) is shadowed by 
kick(Dog). kick(Animal) is a method but it appears to the user 
and the compiler as an ordinary function - which is generally 
good. As such it is eligible for UFCS. I would not recommend 
this sort of coding, but it's everyone's choice, methods or 
not.


Likewise, methods can be overloaded (like here 
https://github.com/jll63/openmethods.d/blob/1.0.0-rc.1/examples/matrix/source/matrix.d#L12).


A current limitation is that default arguments are not 
supported (yet), although I think it's just a matter of 
putting the effort in.


UFCS interacts nicely with methods because you can say 
a.plus(b) even if 'plus' is an open method.


I had a chance to try out what I had suggested above and it 
behaves exactly as I would have expected (i.e. it prints the 
line "lassie.kick(): ctbark").


You seemed to emphasize UFCS in your response, but that really 
wasn't what I was intending to focus on. I just as easily could 
have re-written Dog as below and compiled the program and it 
would have printed the same thing. Similarly, any Dog or 
Pitbull type that call kick would return "ctbark", just Animals 
would return the original results.


class Dog : Animal
{
final string kick()
{
return "ctbark";
}
}

My point is one can easily mix your openmethods's dynamic 
dispatch and D's static dispatch. That seems like a great thing 
that you could emphasize. Simply stated: if you use 
openmethods, you're not forced to only use openmethods. If you 
know the type at compile-time, then you can use it. It's only 
if you want to dynamically dispatch it that you would need 
openmethods.


Indeed I misunderstood.

Well, I am very pleased that my stuff interacts well with the 
rest of the language - I strive for that. However, I found that 
it is difficult to get people to open their mind to the idea of 
open methods, initially. Unless they come from Lisp, polymorphism 
and membership are almost indissociable for them. I often have to 
jump three hurdles.


1/ They're multi-methods, and I never actually had a use for 
that. That is why I insist so much on openness in the article, 
and throw multiple dispatch in as a bonus only half way through. 
That's also why I call them "open methods" and not 
"multi-methods" or "open multi-methods".


2/ It's just function overloading. Hmmm, polymorphism? But once I 
get past that, it's actually a good thing. People know (more or 
less) how overload resolution (or partial template specialization 
for the more expert) works. So I don't need to explain the rules 
governing dispatch and ambiguities in an abstract way. Usually I 
just say "you already know which override will be picked - it's 
the same as with compile-time overload resolution".


3/ This one is specific to D - UFCS gives me the same thing. 
Hmmm, polymorphism again? But you see why I am very careful with 
anything that may obscure or confuse the message.


I find the interaction of open methods and UFCS particularly cool 
when implementing the "call chain" idiom (e.g. 
a.plus(b).times(c).invert()).




Re: Article: Writing Julia style multiple dispatch code in D

2017-08-31 Thread Jean-Louis Leroy via Digitalmars-d-announce
On Thursday, 31 August 2017 at 06:58:53 UTC, Petar Kirov 
[ZombineDev] wrote:
The workaround is to cast to Object before getting the typeid. 
The cause for this behavior is that if you have an interface 
reference to an object it points to the interface vtbl and not 
to the Object base class vtbl.


Yeah I know. And in my openmethods lib I simply follow the 
pointers, without relying on typeid. It does look to me like a 
bug though. D has all the info it needs to implement the process 
you describe.




Re: Open Methods: From C++ to D

2017-08-31 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Thursday, 31 August 2017 at 11:39:30 UTC, aberba wrote:
Thanks for this library. Just a suggestion. Would it possible 
to use `@openmethod` instead of `@method`?


alias openmethod = method;

Atila


What happens when there is UDA name collision? if its 
catastrophic, then @openmethods makes it unique.


After tightening a few screws, the library now supports static 
and selective imports.


Re: Open Methods: From C++ to D

2017-08-30 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Wednesday, 30 August 2017 at 18:16:47 UTC, jmh530 wrote:

..\..\dubFolder\openmethods.d-1.0.0-rc.1\source\openmethods.d(970,21): Error: ca
nnot implicitly convert expression h of type ulong to uint
..\..\dubFolder\openmethods.d-1.0.0-rc.1\source\openmethods.d(1076,34): Error: c
annot implicitly convert expression dim of type ulong to uint
..\..\dubFolder\openmethods.d-1.0.0-rc.1\source\openmethods.d(1177,23): Error: c
annot implicitly convert expression h of type ulong to uint
dmd failed with exit code 1.

The error at line 1076 can be fixed by changing the type of dim 
in the function to size_t. I couldn't fix the other errors. I 
tried having the hash function return size_t also, but that 
just causes other problems.


Fixed. Committed to master and it should show up in dub soon.

Gosh, all that mind bending meta polymorphic mixin reflection 
multi-dimensional fu and then fall prey to ints and uints and 
size_ts. Sobering...




Re: Article: Writing Julia style multiple dispatch code in D

2017-08-30 Thread Jean-Louis Leroy via Digitalmars-d-announce
On Wednesday, 30 August 2017 at 22:30:12 UTC, data pulverizer 
wrote:
On Wednesday, 30 August 2017 at 22:10:38 UTC, Jean-Louis Leroy 
wrote:
On Wednesday, 30 August 2017 at 21:30:29 UTC, data pulverizer 
wrote:
In the light of this I think your package just became more 
interesting to me.


I think that your work and mine are complementary :-)


Here is one strange difference between inheriting from an 
interface and a class:


```
interface Animal{}
class Dog: Animal{}
class Cat: Animal{}


void main()
{
Animal[] x;
x ~= new Cat();
x ~= new Dog();
x ~= new Cat();
writeln(typeid(x[0])); // Gives Animal
}
```

But if Animal is set to a class the typeid gives Cat, why does 
this happen? Does this mean that inheriting from an interface 
is not really polymorphism?


I noticed that too. Still scratching my head.


Re: Article: Writing Julia style multiple dispatch code in D

2017-08-30 Thread Jean-Louis Leroy via Digitalmars-d-announce
On Wednesday, 30 August 2017 at 21:30:29 UTC, data pulverizer 
wrote:
In the light of this I think your package just became more 
interesting to me.


I think that your work and mine are complementary :-)




Re: Article: Writing Julia style multiple dispatch code in D

2017-08-30 Thread Jean-Louis Leroy via Digitalmars-d-announce
On Wednesday, 30 August 2017 at 17:16:59 UTC, data pulverizer 
wrote:
On Wednesday, 30 August 2017 at 17:14:37 UTC, data pulverizer 
wrote:
On Wednesday, 30 August 2017 at 16:45:19 UTC, data pulverizer 
wrote:
You mentioned Julia in your article, however for clarity I 
would point out that Julia doesn't have OOP-type 
polymorphism. There is no notion of being able to do 
something like:


Animal snoopy = new Dog();


p.s. my bad, I was wrong about that! Turns out you can do 
something like this in Julia (apologies for the Julia code in 
a D forum):


abstract type Animal end
struct Dog <: Animal end
struct Cat <: Animal end

x = Array{Animal}(3)
x[1] = Cat(); x[2] = Dog(); x[3] = Cat();
x # returns
3-element Array{Animal,1}:
 Cat()
 Dog()
 Cat()


p.p.s

typeof(x[1]) # returns Cat

so it isn't really polymorphism - the object is never converted 
to the "parent" type! Lol ... sorry for the confusion!

Which is polymorphism


After mulling over this example, I don't see how this proves that 
Julia does *not* support run time polymorphism. On the contrary. 
If you translate this to D you get the same result by the way:


import std.stdio;

class Animal {}
class Cat : Animal {}

void main()
{
  Animal[] array;
  array ~= new Cat();
  writeln(typeid(array[0])); // typeid.Cat
}



Re: Open Methods: From C++ to D

2017-08-30 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Wednesday, 30 August 2017 at 18:16:47 UTC, jmh530 wrote:
I tried installing the latest release from github. Compiling 
(Windows 7 on DMD with default options) the simple program below


import openmethods;
mixin(registerMethods);

void main()
{
}

gives me the errors:


Gosh Windows I completely forgot about that...I'll take a look 
tonight.


Re: Open Methods: From C++ to D

2017-08-30 Thread Jean-Louis Leroy via Digitalmars-d-announce
On Wednesday, 30 August 2017 at 18:20:46 UTC, Jean-Louis Leroy 
wrote:

On Wednesday, 30 August 2017 at 18:05:38 UTC, jmh530 wrote:
On Wednesday, 30 August 2017 at 17:24:55 UTC, Jean-Louis Leroy 
wrote:


We had a discussion about automating the call to 
updateMethods but I don't think that anybody thought of 
putting it in registerMethods. It might work. I'll look into 
it. Thanks for the suggestion...


Ali had suggested something similar[1]. I think your concern 
was that it would get called multiple times, but shared static 
module constructors runs once a program (static module 
constructor runs once per thread).


[1] http://forum.dlang.org/post/okljj1$ktb$1...@digitalmars.com


Ah yes...So the problem is that registerMethods emits static 
ctors that fill data structures representing the methods and 
the specializations. They have to run - all of them - before 
updateMethods. Thus, sadly Q's suggestion won't work.


Yes I remember now...even if we arrange to put the call to 
updateMethods in its own static ctor, coming after all the other 
static ctors, we don't know if there will be more modules with 
more methods afterwards. So we would have to do the updateMethods 
work each time, lest this module is the last. And updateMethods 
is costly: not only does it figure out all the dispatch tables, 
it also calculates a perfect hash (if @mptr is used) using a 
random algorithm.


Re: Open Methods: From C++ to D

2017-08-30 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Wednesday, 30 August 2017 at 18:05:38 UTC, jmh530 wrote:
On Wednesday, 30 August 2017 at 17:24:55 UTC, Jean-Louis Leroy 
wrote:


We had a discussion about automating the call to updateMethods 
but I don't think that anybody thought of putting it in 
registerMethods. It might work. I'll look into it. Thanks for 
the suggestion...


Ali had suggested something similar[1]. I think your concern 
was that it would get called multiple times, but shared static 
module constructors runs once a program (static module 
constructor runs once per thread).


[1] http://forum.dlang.org/post/okljj1$ktb$1...@digitalmars.com


Ah yes...So the problem is that registerMethods emits static 
ctors that fill data structures representing the methods and the 
specializations. They have to run - all of them - before 
updateMethods. Thus, sadly Q's suggestion won't work.


Re: Article: Writing Julia style multiple dispatch code in D

2017-08-30 Thread Jean-Louis Leroy via Digitalmars-d-announce
On Wednesday, 30 August 2017 at 17:16:59 UTC, data pulverizer 
wrote:


p.p.s

typeof(x[1]) # returns Cat

so it isn't really polymorphism - the object is never converted 
to the "parent" type! Lol ... sorry for the confusion!

Which is polymorphism


Haha what I know of Julia is what wikipedia says. Confusing 
indeed...


Re: Article: Writing Julia style multiple dispatch code in D

2017-08-30 Thread Jean-Louis Leroy via Digitalmars-d-announce
On Wednesday, 30 August 2017 at 16:45:19 UTC, data pulverizer 
wrote:

One thing that confused me was examples like this ...

@method
Matrix _plus(DiagonalMatrix a, DiagonalMatrix b)
{
  // just add the elements on diagonals
  // return a DiagonalMatrix
}

Which is marked as returning a DiagonalMatrix rather than a 
Matrix by polymorphism however the function is marked Matrix 
return type.


Indeed returning a DiagonalMatrix would work, and is marginally 
more useful (in case you want to call the specialization 
directly). I'll update the example. Thanks.




Re: Open Methods: From C++ to D

2017-08-30 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Wednesday, 30 August 2017 at 16:37:20 UTC, Q. Schroll wrote:

In the article it says:
Finally, main calls updateMethods. This should be done before 
calling any method (typically first thing in main) and each 
time a library containing methods is dynamically loaded or 
unloaded.


If the something has to be done at the beginning, we have a 
tool for that: static this (on module level). The 
mixin(registerMethods); at the top should therefore mix in.


  static this() { updateMethods(); }

It's never wrong: Calling it in main, too, will at most be 
redundant. You can still call it manually, but for the part of 
main, you cannot inadvertently forget it. You can still have 
static this in that module as you may have multiple static this.


We had a discussion about automating the call to updateMethods 
but I don't think that anybody thought of putting it in 
registerMethods. It might work. I'll look into it. Thanks for the 
suggestion...


Re: Open Methods: From C++ to D

2017-08-30 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Wednesday, 30 August 2017 at 15:42:09 UTC, jmh530 wrote:
One thing you didn't really cover is how seamlessly interacts 
with normal polymorphism. For instance, what if to your first 
example, I add the following function (note: without @method) 
and adjust main as below. I see no reason why this shouldn't 
work. But you wouldn't be able to create a string kick(Animal 
animal) function since that is created by the mixin.


string kick(Dog dog) { return "ct bark"; }

void main()
{
  updateMethods();
  import std.stdio : writeln;
  Animal snoopy = new Dog, hector = new Pitbull;
  writeln("snoopy.kick(): ", snoopy.kick()); // bark
  writeln("hector.kick(): ", hector.kick()); // bark an dbite
  Dog lassie = new Dog;
  writeln("lassie.kick(): ", lassie.kick()); // ct bark
}


What happens here is that kick(Animal) is shadowed by kick(Dog). 
kick(Animal) is a method but it appears to the user and the 
compiler as an ordinary function - which is generally good. As 
such it is eligible for UFCS. I would not recommend this sort of 
coding, but it's everyone's choice, methods or not.


Likewise, methods can be overloaded (like here 
https://github.com/jll63/openmethods.d/blob/1.0.0-rc.1/examples/matrix/source/matrix.d#L12).


A current limitation is that default arguments are not supported 
(yet), although I think it's just a matter of putting the effort 
in.


UFCS interacts nicely with methods because you can say a.plus(b) 
even if 'plus' is an open method.





Re: Open Methods: From C++ to D

2017-08-30 Thread Jean-Louis Leroy via Digitalmars-d-announce
On Wednesday, 30 August 2017 at 15:14:04 UTC, rikki cattermole 
wrote:

On 30/08/2017 4:10 PM, Jean-Louis Leroy wrote:
On Wednesday, 30 August 2017 at 14:37:14 UTC, Arun 
Chandrasekaran wrote:

[...]


I sort of agree, and somewhat regret not picking 'openmethod'. 
I considered both. Also @specialize. If anyone had pushed for 
@openmethod before the article, I would almost certainly have 
given in.


My reasoning was, I hope to promote the term 'method' as the 
standard name for polymorphism from outside, as opposed to 
vfunc. We usually say "virtual functions", rarely "virtual 
member functions". Membership is implicit.




Rename, alias to old and have it deprecated.
Keep around for a couple of releases, done!


Deprecated, already? :-D Hmmm maybe...Let's see if anyone speaks 
in favor of just @method.


Re: Open Methods: From C++ to D

2017-08-30 Thread Jean-Louis Leroy via Digitalmars-d-announce
On Wednesday, 30 August 2017 at 14:37:14 UTC, Arun Chandrasekaran 
wrote:
On Wednesday, 30 August 2017 at 13:35:22 UTC, Jean-Louis Leroy 
wrote:
On Wednesday, 30 August 2017 at 04:48:11 UTC, Arun What was 
your rationale for `openmethod` instead of just `method`?


Just that `openmethod` precisely expresses it's intent and 
`method` is too generic.


I sort of agree, and somewhat regret not picking 'openmethod'. I 
considered both. Also @specialize. If anyone had pushed for 
@openmethod before the article, I would almost certainly have 
given in.


My reasoning was, I hope to promote the term 'method' as the 
standard name for polymorphism from outside, as opposed to vfunc. 
We usually say "virtual functions", rarely "virtual member 
functions". Membership is implicit.




Re: Open Methods: From C++ to D

2017-08-30 Thread Jean-Louis Leroy via Digitalmars-d-announce
On Wednesday, 30 August 2017 at 04:48:11 UTC, Arun Chandrasekaran 
wrote:
On Tuesday, 29 August 2017 at 12:45:50 UTC, Jean-Louis Leroy 
wrote:

On Tuesday, 29 August 2017 at 12:09:01 UTC, Mark wrote:

Nice. This does seem superior to the visitor pattern.


Here is another example - AST traversal: 
https://github.com/jll63/openmethods.d/blob/master/examples/acceptnovisitors/source/app.d


Thanks for this library. Just a suggestion. Would it possible 
to use `@openmethod` instead of `@method`?


Ah, I think it's a little late for that. A while ago I asked if 
anyone had suggestions regarding that sort of things...But now 
that the article has been published I think it would be a very 
bad idea to break all the exmaples in it.


What was your rationale for `openmethod` instead of just `method`?

I will push a commit tonight that will make this work:

  import openmethods : virtual, openmethod = method, next, 
registerMethods, updateMethods;


  // ...

  @openmethod // implement 'kick' for dogs
  string _kick(Dog x) // note the underscore
  {
return "bark";
  }



Re: Open Methods: From C++ to D

2017-08-29 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Tuesday, 29 August 2017 at 12:09:01 UTC, Mark wrote:

Nice. This does seem superior to the visitor pattern.


Here is another example - AST traversal: 
https://github.com/jll63/openmethods.d/blob/master/examples/acceptnovisitors/source/app.d


Re: Open Methods: From C++ to D

2017-08-28 Thread Jean-Louis Leroy via Digitalmars-d-announce

On Monday, 28 August 2017 at 12:31:20 UTC, rikki cattermole wrote:

On 28/08/2017 1:19 PM, Mike Parker wrote:
Jean-Louis Leroy posted about his open methods library here in 
the forums some time ago. Now, he's written a blog post that 
explains what open methods are, and describes the D 
implementation and how it compares to his C++ library.


The blog:
https://dlang.org/blog/2017/08/28/open-methods-from-c-to-d/

Reddit:
https://www.reddit.com/r/programming/comments/6wj0ev/open_methods_from_c_to_d/


Neat. Good to see articles in support of TypeInfo/ClassInfo!
I do wish we extended it for full reflection capabilities 
though...


Agreed.

Andrei suggested using rtlInfo but AFAICT this requires building 
a custom druntime. It would be easy to support this method in 
addition to 'deallocator' and 'hash' but I suspect it would not 
be a very popular option.


Maybe we could have a void*[] in TypeInfo and a global integer 
index that extensions could use to allocate entries?




Re: Article: Writing Julia style multiple dispatch code in D

2017-08-28 Thread Jean-Louis Leroy via Digitalmars-d-announce
On Thursday, 24 August 2017 at 23:50:21 UTC, data pulverizer 
wrote:
I find OOP-polymorphic types ultimately unsatisfying, but I 
don't know of anyway to write, compile and load a D script with 
new types and methods on the fly into the same session.


That is why binding membership and polymorphism together is a 
historical wrong turn. CLOS had it right but the world followed 
the Simula/Smalltalk path because of a nice metaphor (objects 
sending messages to each other).


My openmethods library allows you to add methods "from outside" 
and also supports dynamic loading: you can add new methods to 
existing classes and new classes to hierarchies that have 
methods. See the blog post that just came up.




Re: Article: Writing Julia style multiple dispatch code in D

2017-08-28 Thread Jean-Louis Leroy via Digitalmars-d-announce
On Thursday, 24 August 2017 at 23:50:21 UTC, data pulverizer 
wrote:
I find OOP-polymorphic types ultimately unsatisfying, but I 
don't know of anyway to write, compile and load a D script with 
new types and methods on the fly into the same session.


That is why binding membership and polymorphism together is a 
historical wrong turn. CLOS had it right but the world followed 
the Simula/Smalltalk path because of a nice metaphor (objects 
sending messages to each other).


My openmethods library allows you to add methods "from outside" 
and also supports dynamic loading: you can add new methods to 
existing classes and new classes to hierarchies that have 
methods. See the blog post that just came up.






Re: Mixin templates vs interface files

2017-08-07 Thread Jean-Louis Leroy via Digitalmars-d

On Tuesday, 8 August 2017 at 01:04:30 UTC, Jean-Louis Leroy wrote:
On Sunday, 6 August 2017 at 13:24:23 UTC, Jean-Louis Leroy 
wrote:

Consider:

// app.d

[...]


I see no reason why this() is kept and ~this() not. Should I 
report this as a bug?


It seems to be happening here: 
https://github.com/dlang/dmd/blob/master/src/ddmd/hdrgen.d#L1982


Maybe

if (hgs.hdrgen)
return;

should read:

if (hgs.hdrgen && !hgs.tpltMember)
return;

When I make that change I get my static ~this in the .di file. 
Beyond that, I don't see the reason why 
visit(StaticDtorDeclaration d) is not a copy-paste of 
visit(StaticCtorDeclaration d) with one tilde added.


PR?



Re: Mixin templates vs interface files

2017-08-07 Thread Jean-Louis Leroy via Digitalmars-d

On Sunday, 6 August 2017 at 13:24:23 UTC, Jean-Louis Leroy wrote:

Consider:

// app.d

[...]


I see no reason why this() is kept and ~this() not. Should I 
report this as a bug?


Mixin templates vs interface files

2017-08-06 Thread Jean-Louis Leroy via Digitalmars-d

Consider:

// app.d

import std.stdio;
import tracemodule;

mixin traceModule;

void main()
{
  writeln("main");
}

// tracemodule.d

module tracemodule;

import std.stdio;

mixin template traceModule(string moduleName = __MODULE__)
{
  import std.stdio;

  static this()
  {
writeln("init " ~ moduleName);
  }

  static ~this()
  {
writeln("deinit " ~ moduleName);
  }
}

When I compile like this:

$ rm -f *.o *.di
$ dmd -c tracemodule.d
$ dmd -c app.d
$ dmd app.o tracemodule.o -of=app

...and run 'app' I get the expected output:

$ ./app
init app
main
deinit app

Now if I throw -H in, things get weird:

$ rm -f *.o *.di
$ dmd -c -H tracemodule.d
$ dmd -c app.d
$ dmd app.o tracemodule.o -of=app
$ ./app
init app
main

Indeed when I look at the content of the interface file, I see:

// D import file generated from 'tracemodule.d'
module tracemodule;
import std.stdio;
template traceModule(string moduleName = __MODULE__)
{
import std.stdio;
static this()
{
writeln("init " ~ moduleName);
}
}

'static this()' is there, but no 'static ~this()'.

What's happening here?





  1   2   >