Re: R and D interop with saucer
Unfortunately, your statements are, by and large, simply wrong. Not to mention openly hostile. On Tuesday, 9 January 2024 at 21:25:30 UTC, Lance Bachmeier wrote: That's not "unverified pre-compiled code". As I said, it's an import library for Windows, from an attempt long ago to call R from D on Windows. You don't call the .dll file directly on Windows, you call the .lib file. It's the same thing you do with OpenBLAS and many other popular libraries. The `R.lib` file in this folder (https://github.com/bachmeil/embedrv2/tree/main/inst/embedr) is unverified. As a user, I have no real way of verifying what it is. As far as I am concerned as a responsible user, it posses a cyber security threat, and a habit of downloading such files onto my system would result in me getting hacked. You are not a recognised software distributor such as Microsoft or a recognised Linux distributor, therefore downloading such file in a business could result in exposing one's self to unlimited liability with regards to one's computer systems. OpenBlas library (https://github.com/OpenMathLib/OpenBLAS), does not contain precompiled code. But some of the releases do, and they have checksums (which your library does not), you can run procedures on your system to verify that they are the same as those on the repo. HOWEVER, there is trust here, and despite the fact that OpenBlas is a well recognised library, lots of workplaces would insist on compiling from source (including verifying the checksum) to ensure that they are getting what they expect. I'm familiar with Rcpp/RInside/cpp11. If you go to the CRAN page for RInside, you'll see I'm one of the authors. If you check out Dirk's 2013 book, you'll see that one of the sections in it was based on an example I gave him. ... This doesn't change anything. ... You write your D function and metaprogramming is used to create a wrapper that you can call from R without further modification. I'm not sure what you are trying to say here, but my package does what it says it does. Since you've clearly never used it and don't know how it works, why are you trashing it? I'll let anyone else judge how awkward, complicated and lacking in style it is. Here's the example from the landing page: The first part of your first statement is right. I've never used betterr because I literally just found out about it, but I didn't trash it. I simply said that it's not how I would go about things. People have preferences about how they go about doing things. I can see that the way you do things is very different mine, and that is okay. I don't care that you're not using it. Have fun creating your own project. That doesn't excuse writing falsehoods about the work I've done. I AM having fun with my implementation, but I'm NOT trafficking in falsehoods.
Re: R and D interop with saucer
On Friday, 5 January 2024 at 16:16:49 UTC, bachmeier wrote: On Saturday, 30 December 2023 at 00:50:54 UTC, data pulverizer wrote: Here is the updated version of embedr: https://github.com/bachmeil/embedrv2 The old version you're referencing is from ages ago. I don't know what you mean by Weka code. There was an old import library from when I tried to get embedding of R inside D to work on Windows. The updated library generates the R bindings for the user. There might be something useful there, and the code isn't very long: https://github.com/bachmeil/embedrv2/blob/main/inst/embedr/r.d#L1228 There's an extern_R attribute to specify which functions to export to R. Here's an example from the readme: ``` @extern_R ar1irf(double alpha, double shock, int h) { double[] result; result ~= shock; foreach(ii; 1..h) { result ~= alpha * result.last; } return result; } mixin(exportRFunctions); double last(double[] v) { if (v.length > 0) { return v[$-1]; } else { return 0.0; } } ``` I honestly don't use D much as a replacement for Rcpp any longer. I mostly work in the other direction these days: https://bachmeil.github.io/betterr/ I've been adding Windows support lately so I can share my code with others. There are possibly things in there that are useful to you (whether D calls R or R calls D is not relevant for working with the API). For instance, if you want to pass a function to R without creating a shared library (one example being an objective function for optimization): https://bachmeil.github.io/betterr/funcptr.html Another is using a custom allocator to pass data to R even if it was allocated in D: https://github.com/bachmeil/betterr/blob/main/testing/testalloc.d There are pieces of knowledge I gained by debugging segfaults, like the fact that certain operations will change the pointer of an array and that sort of thing. Thank you for your comments. I shall bear them in mind going forward. I should however make a correction and some clarifications. Regarding your `R.lib` file (embedrv2 and the previous version), I thought it might have something to do with Weka, the machine learning library - I got my wires crossed there. Perhaps I was reading something to do with the ML library before/while I was reading your repo. My point still stands though. I've never worked anywhere that would allow a developer to install unverified pre-compiled code from an online repo. It would pose too much of a security issue. As I explained my approach is to mirror the 'design language' of Rcpp/RInside/cpp11 libraries, because its a great approach, I'm familiar with it, and so are many others. A user (including myself) will be sensitive to on-boarding and usage friction, so I my library will present a clear, familiar, and easy to use interface. I didn't know about your betterr R package. I think it is a different approach from the one I would take. I think both Rcpp and in particular cpp11 have very good design approaches and continuous improvements to their design that gives me plenty to think about. They are at the cutting edge and are pushing the boundaries, and I think it would be cool to show that D can play in the same space with ease, finesse, and style. I'm pretty happy hacking the C API of R and have become quite familiar with its usage and foibles, though there is of course always more to learn. It's fun, as is using the power of D with R. As with many things it is a matter of patience, diligence, and continuous improvement. My focus is to bring the package up to scratch to a point where I am happy with it. To be clear, regarding saucer; at this stage (and for the foreseeable future), I'm monomaniacally focused on where I want to take the library.
Re: R and D interop with saucer
On Saturday, 30 December 2023 at 00:50:54 UTC, data pulverizer wrote: I have updated the package to include a reference to EmbedR outlining these points. Interestingly enough, there is a Rust package for R and D interop called embedr as well (https://docs.rs/extendr-api/latest/extendr_api/). Obvious mistake here, the Rust package called extendr rather than embedr.
Re: R and D interop with saucer
On Friday, 29 December 2023 at 23:51:44 UTC, Sergey wrote: Hi! Thanks for open sourcing the project I remember some time ago I asked in Twitter about it :) I remember you previously mentioned, that you are familiar with EmbedR project, and that your library has different approach: it will be cool to have comparison or a note on GitHub page about differences with the second solution. That's a great point. I really can't remember what stage I was writing saucer when I became aware of EmbedR, but one thing I didn't understand was why it had to have pre-compiled weka? code within the package this is the `R.lib` file, which is a nonstarter security-wise. I also felt that such a project should have strong syntactic similarities with Rcpp to facilitate adoption, that it should have a nicer easier interface, that it would be a good learning experience for me, and that I could (probably) do a decent job at it. I have updated the package to include a reference to EmbedR outlining these points. Interestingly enough, there is a Rust package for R and D interop called embedr as well (https://docs.rs/extendr-api/latest/extendr_api/).
R and D interop with saucer
Hi, Announcing my saucer project (https://github.com/chibisi/saucer) that allows D to be called from R in a similar way that Rcpp allows C++ code to be called from R. At the moment it targets only Linux machines but in time should gain Mac OS and Windows support. Information about the current work on the project can be found on the Milestones page: https://github.com/chibisi/saucer/milestones, though there is also a TODO document. If anyone in the community uses R, I'd appreciate bug reports filed in the repository issues section and suggestions here. The package is not yet on CRAN, but that is one of the milestones. Thanks
Re: Beerconf October 2022
On Tuesday, 1 November 2022 at 15:05:48 UTC, Mike Parker wrote: I don't think anyone involved in organizing BeerConf knew that was there. That's the first I've seen it. I'd suggest that it is either removed or replaced with something more informative, so that people know what is coming and what events that have taken place. The only reason I noticed is because I was looking for prospective D events, and went to the most obvious place. To a stranger a calendar like that gives the impression that nothing has been happening in the community and there is no interaction within the D community, or outreach. There should also be details of DConf and such things. I'd contrast this with the Rust community page and calendar. Right now I don't even know how to find out about DConf from the dlang website. I might get lucky and find out through Twitter or something, but if I didn't know it existed, it would be pretty difficult for me to find out. Don't underestimate the power of FOMO! If on the events page you're seeing pictures and details of things from the conference and events you've missed, for those interested (and there will be some) it will make them more determined to take part next time.
Re: Beerconf October 2022
On Sunday, 16 October 2022 at 12:04:23 UTC, Steven Schveighoffer wrote: # BEERCONF! Beerconf this month is on October 29-30, one day before Halloween. Feel free to wear your D costume, might I suggest a beerconf T shirt? https://www.zazzle.com/store/dlang_swag/products?cg=196874696466206954 ## What is beerconf? Check out the [wiki article](https://wiki.dlang.org/Beerconf). ## Presentations? As usual, anyone who wants to reserve some time to talk about something, let me know. Cheers! -Steve It might just be my browser (Chrome) but I've noticed that there's nothing in the events calendar (https://dlang.org/calendar.html). Wouldn't it be helpful to include these sorts of things in the calendar so that people visiting the site would be aware of them? The empty calendar gives the impression that it is broken or that there are no events at all. If there is technical maintenance required even a simple list of event titles, dates, times and locations would suffice.
Re: Catching C errors
On Thursday, 20 October 2022 at 13:02:52 UTC, bachmeier wrote: I've done an initial release of the second version: https://github.com/bachmeil/embedrv2 The two biggest changes are - Moving to Dub as the default for compilation, which allows the use of any other Dub libraries - It writes the wrappers for you. You write a D function and it converts it to R. The part I haven't finished is in the other direction. For instance, suppose you have a D function that sends data to R many times. If you don't release the memory on the R side, your program's going to crash quickly. I haven't worked on this recently because I've mostly been calling D functions from R. Haven't see this update, good to know!
Re: Catching C errors
On Thursday, 20 October 2022 at 12:14:38 UTC, jmh530 wrote: On Thursday, 20 October 2022 at 11:59:45 UTC, data pulverizer wrote: [snip] Mine is also private for now till it reaches an acceptable state when I'll think about whether it should be publicly released or jealously guarded. It's a project I'm building for my own use really. It can't hurt to publicly release (when ready) so that other users work through any kinks. Those are good points. I'll give it some thought when the time comes. Thanks!
Re: Catching C errors
On Thursday, 20 October 2022 at 10:13:41 UTC, Sergey wrote: On Thursday, 20 October 2022 at 09:52:05 UTC, data pulverizer wrote: I'm currently writing a D interop with R, the dynamic statistical programming language. There's a function called How is your project related to EmbedR? The description of the project could be found here: https://dlang.org/blog/2020/01/27/d-for-data-science-calling-r-from-d/ AFAIK Lance wants to re-write it to the second version with some improvements in the code. I know about the EmbedR project. I'm doing a "full-throated" R<->D API aiming to be on the scale of Rcpp (https://cran.r-project.org/web/packages/Rcpp/index.html) all built with native D code, which is more full-featured than EmbedR - which ships with a DLL that some end users will probably not accept and does not have the full capability and convenience of something like Rcpp. The architecture of my library and my approach is also quite different to EmbedR. I also have structures like `alias NumericVector = RVector!(SEXPTYPE);` and so on, which builds in all the D-lang ops, and so on to allow a full interop with the R API. Mine is also private for now till it reaches an acceptable state when I'll think about whether it should be publicly released or jealously guarded. It's a project I'm building for my own use really.
Re: Catching C errors
On Wednesday, 19 October 2022 at 16:48:10 UTC, Ali Çehreli wrote: On 10/19/22 07:05, data pulverizer wrote: > I am calling code from a C API, and would like to know how to catch exit > errors If you are talking about the exit() Posix function, you can't do anything about that because its purpose is to cause "normal process termination". Ali Yes it is the `exit()` function in the end I figured that it couldn't be sidestepped like an exception so I did something else. As it happens, the situation turned out to be a bit trivial, not even sure if it's worth going into. But for those interested the description is below. I'm currently writing a D interop with R, the dynamic statistical programming language. There's a function called `Rf_initEmbeddedR()` which allows you to call the full R C API from D without having to compile a DLL and call code from R. There is also a function called `Rf_endEmbeddedR(int fatal)`, which I assumed terminates the R session, but it doesn't, after seeing the code it only cleans some things up and looks as if it is intended to be used just before you exit main. I have unit tests in D that begin with the init function and finish with the end function, and when I tried re-initialising I get an exit() error saying the R session was already initialized. So all I did was create a static init flag, and a wrapper function to only call init if the flag is false. As I said in the end it was trivial.
Re: Catching C errors
On Wednesday, 19 October 2022 at 14:05:35 UTC, data pulverizer wrote: Hi all, I am calling code from a C API, and would like to know how to catch exit errors so that they can be handled and make them more like an exceptions so that the computation can continue. I've tried something similar to what is outlined here: https://dlang.org/phobos/object.html#.Error but it doesn't work, the process dies in the try block. Thanks It's okay, I've found a work around.
Catching C errors
Hi all, I am calling code from a C API, and would like to know how to catch exit errors so that they can be handled and make them more like an exceptions so that the computation can continue. I've tried something similar to what is outlined here: https://dlang.org/phobos/object.html#.Error but it doesn't work, the process dies in the try block. Thanks
Re: Stop writeln from calling object destructor
On Monday, 3 October 2022 at 11:08:00 UTC, Steven Schveighoffer wrote: On 10/2/22 12:21 PM, data pulverizer wrote: I've noticed that `writeln` calls the destructor of a struct multiple times and would like to know how to stop this from happening. It has become a very serious problem when working with objects that have memory management external to D. I know you already solved the problem, but just for future reference, if you use something like `RefCounted`, you can avoid copying and destruction until everyone is done with the object. This is how my io library works, the IO objects are non-copyable, and you wrap them in `RefCounted` if you want to copy them. -Steve Just seen this. Nice one. The docs link: https://dlang.org/library/std/typecons/ref_counted.html
Re: Stop writeln from calling object destructor
On Sunday, 2 October 2022 at 18:24:51 UTC, Ali Çehreli wrote: I've just tested. That is used only for explicit constructor syntax ... Many thanks. Knowledgeable as always!
Re: Stop writeln from calling object destructor
On Sunday, 2 October 2022 at 17:51:59 UTC, Ali Çehreli wrote: What I noticed first in your original code was that it would be considered buggy because it was not considering copying. Every struct that does something in its destructor should either have post-blit (or copy constructor) defined or simpler, disallow copying altogether. Thanks for the advice, for a while now I didn't know what was creating the issue. The code I'm running is my D connector to the R API and for ages I didn't know where the multiple destructor calls to allow an object to be garbage collected by the R API was coming from, and it was breaking the whole thing. I think I'll have to play it by ear whether to disable the copy constructor altogether or to use it now it is working. Thanks both of you.
Re: Stop writeln from calling object destructor
On Sunday, 2 October 2022 at 17:28:51 UTC, data pulverizer wrote: Sorry I'll need to implement all the overloaded copy constructors and see if that fixes it. I've got it, something weird happened to my copy constructor. This was my original attempt and was ignored (didn't run in the copy constructor): ``` this(T)(ref return scope T original) if(is(T == RVector!(Type))) { //... code ... } ``` But this now works: ``` this(ref return scope RVector!(Type) original) { //... code ... } ``` No idea why. `Type` is a template parameter of the object.
Re: Stop writeln from calling object destructor
On Sunday, 2 October 2022 at 17:19:55 UTC, data pulverizer wrote: Any reason why this could be? Sorry I'll need to implement all the overloaded copy constructors and see if that fixes it.
Re: Stop writeln from calling object destructor
On Sunday, 2 October 2022 at 16:44:25 UTC, Paul Backus wrote: It's because `writeln` is copying the object, and each of the copies is being destroyed. If you add a copy constructor to your example, you can see it happening: ... I thought something like this could be happening in my original implementation and tried implementing a copy constructor using this reference https://dlang.org/spec/struct.html#struct-copy-constructor but it did not work. Both your's and the manual's suggestion works for my baby example but not for my actual code. Any reason why this could be?
Stop writeln from calling object destructor
I've noticed that `writeln` calls the destructor of a struct multiple times and would like to know how to stop this from happening. It has become a very serious problem when working with objects that have memory management external to D. Here is a repeatable example, where the destructor appears to have been called 4 times with one call of `writeln` before the object actually goes out of scope: Code: ``` import std.stdio: writeln; struct MyObject { int id; this(int id) @nogc { this.id = id; } ~this() { writeln("Object destructor ..."); } } void main() { auto obj = MyObject(42); writeln("MyObject: ", obj); writeln("Goodbye:\n"); } ``` Output: ``` $ rdmd gc.d MyObject: MyObject(42)Object destructor ... Object destructor ... Object destructor ... Object destructor ... Goodbye: Object destructor ... ``` Thank you
Re: dub import local D package
On Thursday, 21 April 2022 at 03:59:26 UTC, Steven Schveighoffer wrote: OK, so reviewing with that in mind, it looks like you're trying to import `myPackage.modules.mymodule`, but the file `../myPackageName/source/myPackageName/modules/mymodule.d` doesn't exist. Is there one too many "myPackageName" packages here? Yes, looks like that it works if I change to `import modules.mymodule;`.
Re: dub import local D package
On Thursday, 21 April 2022 at 00:14:16 UTC, Steven Schveighoffer wrote: Did you substitute something real with `...` to hide it from your post? Because that's not a real path. I used it to hide my actual paths.
dub import local D package
Hi all, I'm trying to import a local dub package into a dub project (`json` format). I have added the package I'm trying to import with `dub add-local` and `dub add-path` and including it within the json file, but I get the error ``` $ dub build Performing "debug" build using /.../ldc2/bin/ldc2 for x86_64. myPackageName 0.1.0: target for configuration "library" is up to date. test ~master: building configuration "application"... source/app.d(1,8): Error: module `mymodule` is in file 'myPackageName/modules/mymodule.d' which cannot be read import path[0] = source/ import path[1] = ../myPackageName/source/ import path[2] = /.../ldc2/bin/../import /.../ldc2/bin/ldc2 failed with exit code 1. ``` The dependencies in the dub.json file looks like this: ``` "dependencies": { "myPackageName": { "path": "/.../myPackageName", "version": "0.1.0" } } ``` Thanks in advance
Re: Setting SQLite compile time parameters from etc.c.sqlite3
On Tuesday, 1 March 2022 at 20:59:46 UTC, data pulverizer wrote: Hello all, I'm not sure how to set the compile time parameters in D's SQLite module particular the items that take multiple parameters, for example in the C API manual `SQLITE_CONFIG_MMAP_SIZE` takes two `sqlite3_int64`. How do I set these? Okay it seems like you are supposed to use the function `sqlite3_config` to configure those elements, for example: ``` sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, 10_000_000_000, 30_000_000_000); ```
Setting SQLite compile time parameters from etc.c.sqlite3
Hello all, I'm not sure how to set the compile time parameters in D's SQLite module particular the items that take multiple parameters, for example in the C API manual `SQLITE_CONFIG_MMAP_SIZE` takes two `sqlite3_int64`. How do I set these? Do I just write something like ``` enum SQLITE_CONFIG_MMAP_SIZE = [10_000_000_000, 30_000_000_000]; ``` ? Writing this doesn't cause an error but I don't think it works because its supposed to speed up write times and I'm not observing any performance change. Thanks in advance!
Re: function(pointer) as template argument, explicit template instantiation
On Friday, 31 December 2021 at 00:57:26 UTC, kdevel wrote: ```dptr.d class R { } void foo (R r) { } alias fn = void function (R); void lyr (fn F) (R r) { } immutable fn foo_ptr = // line 14 pragma (msg, typeof (foo_ptr)); auto ptr = lyr!(foo_ptr);// line 17 ``` dmd reports: ``` immutable(void function(R)) dptr.d(14): Error: expression `& foo` is not a valid template value argument ``` If I comment out line 17 the code compiles. I want to put the explicitly instantiated function template into an immutable AA. How can that be phrased such that dmd compiles it? Pointers are runtime entities and are not suitable template parameters (compile time). So assuming that you are trying to either pass a function constant of a specific type signature as a template argument, or a function pointer as an argument with either a template specialisation or constraint: ``` class R {} void foo(R r){} alias fn = void function(R); //function compile time constant void lyr(fn fp_type)(R r){} //As template constraint void con(T)(T fun, R r) if(is(T == fn)) { fun(r); } /* //As template specialisation void con(T: fn)(T fun, R r) { fun(r); } */ //Function constant enum fn foo_ptr = (R r){}; pragma(msg, typeof(foo_ptr)); //Declared at compile time but only executable at runtime auto ptr = !(foo_ptr); void main() { //auto ptr = !(foo_ptr);//could declare this here ptr(new R()); fn new_ptr = con(new_ptr, new R()); } ```
Re: Ambiguity issue with expanding and evaluating single template type parameter enums
On Tuesday, 28 December 2021 at 00:57:27 UTC, Paul Backus wrote: ```d enum instantiate(string type, string expr) = type ~ "(" ~ expr ~ ")"; pragma(msg, instantiate!("RVector!(SEXPTYPE.REALSXP)", "x")); ``` One possibility is to generate a collection of compile time strings that denote the types and then to a comparison with the type something like `is(T == mixin(CString)`, where `CString = "RVector!(SEXPTYPE.REALSXP)"` to discover the correct string which I can then use to generate the code without having to use `T.stringof` anywhere in the code at all.
Re: Ambiguity issue with expanding and evaluating single template type parameter enums
On Tuesday, 28 December 2021 at 00:32:03 UTC, Paul Backus wrote: The result of `.stringof` is completely implementation-defined, may change arbitrarily between compiler releases, and is not even guaranteed to be valid D code in the first place. Wow, I didn't know this. In this case, the simplest solution is to have your code generator accept a string as its input, rather than a type. For example: ```d enum instantiate(string type, string expr) = type ~ "(" ~ expr ~ ")"; pragma(msg, instantiate!("RVector!(SEXPTYPE.REALSXP)", "x")); ``` Well the code needs to be responsive from parameter types `T` generated from other code. I'm allowing the user to create functions select those they wish to access in R by UDA decorators in the D script which I then filter for and wrap the necessary functions generating any type conversion code I need at compile time to create functions callable in R.
Re: Ambiguity issue with expanding and evaluating single template type parameter enums
On Monday, 27 December 2021 at 23:04:40 UTC, Adam Ruppe wrote: On Monday, 27 December 2021 at 21:21:30 UTC, data pulverizer wrote: alias T = MyType!(INTEGER); What is MyType? enum code = "writeln(\"instance: \", adder(" ~ T.stringof ~ "(), " ~ U.stringof ~ "()" ~ "));"; And why is this a string mixin instead of a plain simple function? prolly need more context Sorry the example is a bit contrived but basically I'm generating a whole bunch of code using string mixins. The types I'm generating are a template type I've constructed for R's SEXP, so that my wrapped numeric vector (struct) type is denoted `RVector!(REALSXP)`. But `alias REALSXP = SEXPTYPE.REALSXP` where `SEXPTYPE` is an `enum`. So if I start using `T.stringof` where `T = RVector!(SEXPTYPE.REALSXP)` to generate code it starts to create chaos because `T.stringof = "RVector!SEXPTYPE.REALSXP"`, so if I'm trying to convert or instantiate a type using `T.stringof ~ "(x)"`, I'll get `RVector!SEXPTYPE.REALSXP(x)` which gives an error, and various types like this can occur many times in a script. The new template allows me to safely paste the type and get what I want `RVector!(SEXPTYPE.REALSXP)(x)`. There are various requirements, sometimes I have to cast or type convert, so I **need** the type to paste correctly and explicitly. Which is what the `safe_stringof` template does for my baby example - the same methodology will work just as well for my `RVector` code.
Re: Ambiguity issue with expanding and evaluating single template type parameter enums
On Monday, 27 December 2021 at 22:52:58 UTC, data pulverizer wrote: I think the only thing to do for now is probably for me to construct a template that creates a proper string for this type. It would look something like this: ``` enum safe_stringof(T) = T.stringof; template safe_stringof(T: MyType!U, alias U) { enum string safe_stringof = "MyType!(" ~ U.stringof ~ ")"; } ``` So this ``` alias DOUBLE = MyEnum.DOUBLE; alias STRING = MyEnum.STRING; alias INTEGER = MyEnum.INTEGER; void main() { alias T = MyType!(INTEGER); alias U = MyType!(STRING); enum code = "writeln(\"instance: \", adder(" ~ safe_stringof!(T) ~ "(), " ~ safe_stringof!(U) ~ "()" ~ "));"; pragma(msg, code); } ``` Which works. Now back to my very late dinner.
Re: Ambiguity issue with expanding and evaluating single template type parameter enums
On Monday, 27 December 2021 at 21:31:03 UTC, Adam Ruppe wrote: if you can paste teh code where you generate this I can prolly show you a much easier way to do it. stringof sucks really hard. I think the only thing to do for now is probably for me to construct a template that creates a proper string for this type.
Re: Ambiguity issue with expanding and evaluating single template type parameter enums
On Monday, 27 December 2021 at 21:31:03 UTC, Adam Ruppe wrote: if you can paste teh code where you generate this I can prolly show you a much easier way to do it. stringof sucks really hard. Will the above `mixin` example suffice? It expands to the code that I described.
Re: Ambiguity issue with expanding and evaluating single template type parameter enums
On Monday, 27 December 2021 at 21:05:51 UTC, data pulverizer wrote: Hello, ... ... an equivalent mixin error would be ``` //... alias DOUBLE = MyEnum.DOUBLE; alias STRING = MyEnum.STRING; alias INTEGER = MyEnum.INTEGER; void main() { alias T = MyType!(INTEGER); alias U = MyType!(STRING); enum code = "writeln(\"instance: \", adder(" ~ T.stringof ~ "(), " ~ U.stringof ~ "()" ~ "));"; mixin(code); } ```
Ambiguity issue with expanding and evaluating single template type parameter enums
Hello, I'm generating code using mixins and one of my mixins expands to something like this: ``` adder(MyType!MyEnum.INTEGER(), MyType!MyEnum.STRING()); ``` `MyType!MyEnum.STRING` is generated with `T.stringof `. I get the error: ``` Error: template instance `MyType!(MyEnum)` does not match template declaration `MyType(MyEnum type) ``` and if I manually amend the code to this: ``` adder(MyType!(MyEnum.INTEGER)(), MyType!(MyEnum.STRING)()); ``` It runs fine. It looks like the ambiguity of UFCS and type is messing things up. This is a simplified example. Since the code is being generated automatically in many places I can't go round adding the brackets. A simplified functional example is given below: ``` import std.stdio: writeln; enum MyEnum { DOUBLE = 0, STRING = 1, INTEGER = 2 } struct MyType(MyEnum type) {} auto getValue(T: MyType!U, alias U)(T x) { return U; } auto adder(T, U)(T x, U y) { return getValue(x) + getValue(y); } void main() { writeln("instance: ", adder(MyType!MyEnum.INTEGER(), MyType!MyEnum.STRING())); } ```
Re: Double bracket "{{" for scoping static foreach is no longer part of D
On Wednesday, 22 December 2021 at 16:10:42 UTC, Adam D Ruppe wrote: So OUTSIDE a function, static foreach() {{ }} is illegal because a plain {} is illegal outside a function. But INSIDE a function, static foreach() {{ }} is legal, but it isn't magic about static foreach - it is just a body with its optional {} present as well as a scope statement inside. Just seen this. Thanks - I should have been more patient.
Re: Double bracket "{{" for scoping static foreach is no longer part of D
On Wednesday, 22 December 2021 at 16:01:49 UTC, rikki cattermole wrote: Seems to be working just fine as of 2.098. ```d import std; void main() { static foreach(Foo; ["Abc", "def"]) {{ string str = Foo; writeln("Hello D ", str, __VERSION__); }} } ``` ``` Hello D Abc2098 Hello D def2098 ``` I see, It looks like I remembered incorrectly about using `{{` in templates! It seems that it doesn't work in templates or in "global" (outside main), so for instance neither this ``` // compiled with -o- flag static foreach(Foo; ["Abc", "def"]) {{ enum str = Foo; pragma(msg, "Hello D ", str, __VERSION__); }} ``` nor this ``` template Demo() { static foreach(Foo; ["Abc", "def"]) {{ enum str = Foo; pragma(msg, "Demo: Hello D ", str, __VERSION__); }} enum Demo = null; } void main() { Demo!() } ``` will run. It gives an error `Error: declaration expected, not {`.
Double bracket "{{" for scoping static foreach is no longer part of D
Hi All, I noticed that the double bracket `{{` for scoping `static foreach` is no longer part of D and it looks like it has been replaced with https://dlang.org/changelog/2.098.0.html#AliasAssign. Could someone confirm this with a link to the DIP and any other tools that we should be using (I guess it's now more reliance on CTFE)? I tend to avoid CTFE for small amounts of meta-programming since it is resolved at "soft compile time" and being cautious by nature I tend to rely more on templates. The change is not a big deal, I just didn't see any news about it. Many thanks
Re: How to return a reference to structs?
Hi, It looks to me like `A*[]` would require extra allocation of memory and `ref` would not, am I wrong? If so it may be something to consider if relevant for your application. Thanks.
Re: The type inference everywhere
On Sunday, 31 October 2021 at 18:51:09 UTC, user1234 wrote: To me it is the right answer. Maybe that OP wanted the TemplateType parameter to be implicitly added (and that's why Ali interpreted the question as a language proposal)? Ah, I see. Interesting proposal.
Re: The type inference everywhere
On Sunday, 31 October 2021 at 17:35:35 UTC, Ali Çehreli wrote: On 10/31/21 7:07 AM, Salih Dincer wrote: > ```d > auto foo(int value, auto s = Section(2, 60)) { > int max; /* ^--- ? > ...*/ > return Section (0, max) > } > ``` > Is possible something like above pointed. OK, I know it isn't because I > tried! Well, wouldn't it be nice if it did? Makes sense because e.g. the following works: struct S { auto i = 42; } I bet the problem with your proposal is "auto" in that position is a part of the two-word "auto ref" parameters. I don't know how hard or impossible it would be to allow just "auto" there. In any case, although it would be nice for completeness, the use case is so rare that I wouldn't mind repeating the type twice in that usage. But I agree with you... Ali This is a teachable moment for me, so I'll ask the question. Why isn't something like this the answer? ``` import std.stdio: writeln; struct Section { int x; int y; } auto foo(T)(int value, auto ref T s = Section(2, 60)) { //... return Section(0, 60); } void main() { foo(5).writeln; } ```
Re: Bitfileds Error: no identifier for declarator
On Thursday, 28 October 2021 at 05:51:27 UTC, Imperatorn wrote: Try renaming debug to something else Many thanks guys. I should have spotted that one!
Re: Bitfileds Error: no identifier for declarator
On Thursday, 28 October 2021 at 05:20:35 UTC, data pulverizer wrote: Hi, I am trying to compile the following items ... Sorry forgot to prepend: ``` enum SEXPTYPE { NILSXP = 0, SYMSXP = 1, LISTSXP = 2, CLOSXP = 3, ENVSXP = 4, PROMSXP = 5, LANGSXP = 6, SPECIALSXP = 7, BUILTINSXP = 8, CHARSXP = 9, LGLSXP = 10, INTSXP = 13, REALSXP = 14, CPLXSXP = 15, STRSXP = 16, DOTSXP = 17, ANYSXP = 18, VECSXP = 19, EXPRSXP = 20, BCODESXP = 21, EXTPTRSXP = 22, WEAKREFSXP = 23, RAWSXP = 24, S4SXP = 25, NEWSXP = 30, FREESXP = 31, FUNSXP = 99 } ``` In case someone is trying to replicate the error.
Bitfileds Error: no identifier for declarator
Hi, I am trying to compile the following items: ``` import std.bitmanip: bitfields; enum TYPE_BITS = 5; enum NAMED_BITS = 16; struct sxpinfo_struct { mixin(bitfields!( SEXPTYPE, "type", TYPE_BITS, uint, "scalar", 1, uint, "obj", 1, uint, "alt", 1, uint, "gp", 16, uint, "mark", 1, uint, "debug",1, uint, "trace",1, uint, "spare",1, uint, "gcgen", 1, uint, "gccls", 3, uint, "named", NAMED_BITS, uint, "extra", 32 - NAMED_BITS)); } ``` But I get the error: ``` Error: no identifier for declarator `uint` Error: identifier or integer expected inside `debug(...)`, not `)` Error: found `@` when expecting `)` Error: no identifier for declarator `safe` Error: declaration expected, not `return` Error: no identifier for declarator `void` Error: identifier or integer expected inside `debug(...)`, not `uint` Error: found `v` when expecting `)` Error: declaration expected, not `)` Error: declaration expected, not `assert` Error: basic type expected, not `cast` Error: found `cast` when expecting `;` Error: declaration expected, not `(` ``` All referencing the `bitfields` `mixin`, more specifically the last two lines but I think it's actually referencing the expanded `mixin` rather than my declaration. Thanks
Re: Can we use "ImportC" used yet?
On Sunday, 24 October 2021 at 05:54:43 UTC, data pulverizer wrote: Actually it's more complicated than that. On construction I do need to call `protect` and call `unprotect` or `unprotect_ptr` when the function in which the object is created returns. At the moment, I'm not even sure (or more likely do not think) that it is suitable to call it as part of the destructor. Anyway, that's an aside. Okay since it's stack allocated it's okay to call `unprotect` in the destructor if the object is a `struct` but not if it is a `class`.
Re: Can we use "ImportC" used yet?
On Saturday, 23 October 2021 at 17:42:32 UTC, data pulverizer wrote: On Saturday, 23 October 2021 at 16:39:08 UTC, data pulverizer wrote: ``` ... this(R_xlen_t n) { SEXPTYPE _real_ = SEXPTYPE.REALSXP; _data = protect(allocVector(_real_, n)); unprotect(1); } ... ``` Looking at that code, I realise didn't need the un/protect. Actually it's more complicated than that. On construction I do need to call `protect` and call `unprotect` or `unprotect_ptr` when the function in which the object is created returns. At the moment, I'm not even sure (or more likely do not think) that it is suitable to call it as part of the destructor. Anyway, that's an aside.
Re: Can we use "ImportC" used yet?
On Saturday, 23 October 2021 at 16:39:08 UTC, data pulverizer wrote: ``` ... this(R_xlen_t n) { SEXPTYPE _real_ = SEXPTYPE.REALSXP; _data = protect(allocVector(_real_, n)); unprotect(1); } ... ``` Looking at that code, I realise didn't need the un/protect.
Re: Can we use "ImportC" used yet?
On Friday, 22 October 2021 at 16:16:22 UTC, Dave P. wrote: I think you ran into this [issue](https://issues.dlang.org/show_bug.cgi?id=22404). The bug fix isn’t part of a released dmd yet. Yes that's the same error. When I try this: ``` ... this(R_xlen_t n) { SEXPTYPE _real_ = SEXPTYPE.REALSXP; _data = protect(allocVector(_real_, n)); unprotect(1); } ... ``` I get a slightly more interesting error message: ``` types.d(43): Error: cannot implicitly convert expression `14` of type `int` to `__tag28` ``` So it's not recognising `REALSXP` as an `SEXPTYPE`, it's as if it is treating `SEXPTYPE` like a `struct` rather than an `enum`. Also I was wandering, how long will it take release a fix for ImportC? I am aware that it is a new feature, the reason I ask is not to try to rush anyone but to plan my time better. Many thanks
Re: Can we use "ImportC" used yet?
On Thursday, 21 October 2021 at 23:06:18 UTC, jfondren wrote: On Thursday, 21 October 2021 at 22:23:50 UTC, data pulverizer wrote: I'd first check that the type names look OK in the processed C. If they do, then it's an importc bug. Those are still getting reported, but yours might be new. Worth checking out. I've double-checked and the types names are fine in translated C file. It might also be a bug that's been fixed since release--try dmd master on it. I have the latest compiler installed and I just double-checked by compiling dmd-master with the same result. The specific error is: ``` Error: function `Rf_allocVector(__tag28, long)` is not callable using argument types `(int, long)` cannot pass argument `REALSXP` of type `int` to parameter `__tag28` ``` Here `__tag28` should be `SEXPTYPE` which is an `enum int` containing `REALSXP`. Another (superficial by maybe related) issue is that `REALSXP` is an `SEXPTYPE` which is an `enum int` under the hood but dmd skips the `SEXPTYPE` description altogether, even though SEXPTYPE is correctly converted in the imported C file. Also, with some definitions in the C file, when I try to `#undef` something to get some conditional C definitions to be converted with `gcc -E -P ...`, nothing happens. d doesn't do any C preprocessing, so any problem here is with gcc. Your `#undef`s may be coming before the C preprocessor's own `#define`s and have no effect. I thought I'd ask anyway, it looks like a question for the R community, where `#undef R_NO_REMAP` in the script has no effect. This is unrelated to the first issue. As @Imperatorn said (and I was aware as I asked the question) this is a new feature that is currently being worked on, and we should expect and report stuff like this. It's a great feature and lots of people will use it heavily. Including myself.
Re: Can we use "ImportC" used yet?
Hi, I'm getting an odd issue with ImportC when I import a header converted with `gcc -E -P ...` some of the types signatures in functions don't come through with their proper names but as `__tagXX` where `XX` is some number. It's got to the point where the type itself might get imported correctly, but the same type in a function might be `__tag28` or some other mangled name so when I create an instance of the proper type and try to call the respective function, I get a type error. Also, with some definitions in the C file, when I try to `#undef` something to get some conditional C definitions to be converted with `gcc -E -P ...`, nothing happens. Thanks.
Re: Can we use "ImportC" used yet?
On Sunday, 17 October 2021 at 10:46:30 UTC, data pulverizer wrote: Okay wow, this is amazing, I can now call R's standalone math library `Rmath.h` by converting ... Sorry you don't need `-lRmath` so the initial call should be: ``` gcc -E -P -I"/usr/share/R/include" r2d_con.c > r2d.c ```
Re: Can we use "ImportC" used yet?
Okay wow, this is amazing, I can now call R's standalone math library `Rmath.h` by converting: ``` //r2d_con.c #define __restrict restrict #define __asm__ asm #define __extension__ #define __inline #define __builtin_bswap16 #define __builtin_bswap32 #define __builtin_bswap64 #define MATHLIB_STANDALONE 1 typedef struct _Float128 {unsigned long long x[2];} _Float128; #include "Rmath.h" #include "R_ext/Random.h" ``` ``` //callr import r2d; import std.random: unpredictableSeed; import std.stdio: writeln; void main() { set_seed(unpredictableSeed(), unpredictableSeed()); writeln("rgamma (2, 3): ", rgamma(2, 3)); } ``` Using: ``` gcc -E -P -I"/usr/share/R/include" -lRmath r2d_con.c > r2d.c dmd callr.d -L-lRmath -L-lm && ./callr ``` Okay it's only the standalone library which is a small part of R, but this rocks. The PAHWAHR! Lol.
Re: Can we use "ImportC" used yet?
On Sunday, 17 October 2021 at 04:45:26 UTC, data pulverizer wrote: I ended up defining `typedef struct __float128__ {unsigned long long x[2];} __float128__;` and doing a find and replace for `__float128` which is totally overkill since I won't be using it and according to the documentation, the D compiler doesn't support 128-bit floats yet though it has reserved keywords for it. Many thanks. Decided the best idea to just to comment it out altogether.
Re: Can we use "ImportC" used yet?
I ended up defining `typedef struct __float128__ {unsigned long long x[2];} __float128__;` and doing a find and replace for `__float128` which is totally overkill since I won't be using it and according to the documentation, the D compiler doesn't support 128-bit floats yet though it has reserved keywords for it. Many thanks.
Re: Can we use "ImportC" used yet?
Okay I'm definitely trying to use `importC` rather than the regular `extern(C)` way. I can see where I went wrong. The steps for importC for header files are: 1. Prepend the following directives to `test_og.c` or whatever your interface c script is: ``` #define __restrict restrict #define __asm__ asm #define __extension__ #define __inline #define __builtin_bswap16 #define __builtin_bswap32 #define __builtin_bswap64 ``` 2. Run the commands: ``` gcc -E -P test_og.c > test_c.c dmd test.d test_c.c && ./test ``` which works. Now I've tried the same thing with library `fftw3` and getting: ``` Error: undefined identifier `__float128` ``` Which I guess I have to define somehow in the original c directives?
Re: Can we use "ImportC" used yet?
On Saturday, 16 October 2021 at 08:19:41 UTC, rempas wrote: On Saturday, 16 October 2021 at 07:09:16 UTC, jfondren wrote: If I understand correctly you mean compile the original file with gcc (`gcc test_og.c -o test_og.o`) and then link it with DMD (`dmd test.d test_og.o`)? ... While we're on this subject, I've been having similar issues now tried compiling @rempas's example file with: ``` gcc test_og.c -c -o test_og.o dmd test.d test_og.o ``` and get the response: ``` test_og.c(1): Error: identifier or `(` expected test_og.c(6): Error: identifier or `(` expected ``` Platform is Ubuntu 20.04 gcc version 9.30 and dmd version v2.098.0. At first I tried compiling a script with fftw3 and thought it was something wrong with my script but when I tried it with your example, the same thing happened.
Presentation on D in Insurance Data Science Conference
Hi Guys, I recently gave a presentation (7 minutes since the conference became very popular) introducing the D programming language to the insurance industry: https://insurancedatascience.org/downloads/London2021/Session_4a/Chibisi_Chima-Okereke.pdf Thanks
Re: How to compile Phobos with other D code to create a shared library?
On Friday, 4 June 2021 at 15:19:17 UTC, bachmeier wrote: It requires an R package if you want to call D functions from R. You need to link to R itself if you want to do something like pass a vector from R to D and then access that data from D. Since R is aware of the location of all the underlying libraries, it's easiest to let it generate the dub.sdl for you. I guess you're using the older .C interface [as done here](http://users.stat.umn.edu/~geyer/rc/). Good enough if passing double* and int* pointers to D functions will suffice. Only thing you need to do to initialize the D runtime is add this to your D code ``` struct DllInfo; extern(C) void R_init_libfoo(DllInfo * info) { Runtime.initialize(); } ``` where foo is the name of the library you're loading (foo.so). I've just read the documentation and had a go, **compiling with GDC worked for both `.C` and `.Call`**. I tried with all three compilers DMD, LDC, and GDC, and looked at the outputs with the nm tool. I don't think this matters much but DMD and LDC are more likely to list functions (DMD) or symbols in referenced modules (LDC) as weak symbols. I think the more likely the reason GDC worked is because it is a GNU compiler this has full GLIBC compatibility with reference to the `librt.so.1` `GLIBC_PRIVATE` error. The R ext documentation you kindly referenced says: *"By default, R uses the operating-system-specific dynamic loader to lookup the symbol in all loaded DLLs and the R executable or libraries it is linked to."* and that: *"Registering routines has two main advantages: it provides a faster way to find the address of the entry point via tables stored in the DLL at compilation time, and it provides a run-time check that the entry point is called with the right number of arguments and, optionally, the right argument types."* So registering symbols is not the issue. The error was specific to GLIBC which is probably why the GNU compiler worked. Thank you.
Re: How to compile Phobos with other D code to create a shared library?
On Wednesday, 2 June 2021 at 23:23:58 UTC, bachmeier wrote: Are you aware of my embedr project, which handles all that for you, and does a lot of other stuff? https://embedr.netlify.app If you want to do it yourself, you can see the boilerplate you need to add to call a shared library from R here: https://bitbucket.org/bachmeil/embedr/src/bebf67e5b30cd4163214c7f44f9907e7d7490dc0/R/compile.R#lines-99 If you want to read the R manual, the relevant section is here: https://cran.r-project.org/doc/manuals/r-release/R-exts.html#dyn_002eload-and-dyn_002eunload If you don't do that, it's unlikely to work unless you get lucky. If you want to load foo.so, you need a corresponding R_init_foo function where you call Runtime.initialize. Thanks. Looks like I have some more reading to do. I did know about embedr, but I saw it had dependencies and I wanted a standalone and fully transparent D solution. I'm already calling R routines from D using standalone Rmath and being able to call D from R and D have independent full access to R's internals would be awesome. But your package certainly provides very useful information. The reference to R's dyn.load internals looks useful and relevant and I'll be trying those once I get the time. Probably during the weekend.
Re: How to compile Phobos with other D code to create a shared library?
On Wednesday, 2 June 2021 at 17:49:49 UTC, Steven Schveighoffer wrote: What's happening is that the dynamic linker is trying to resolve that symbol, but cannot find it in the given library. Try `ldd code/rbasic.so` and see if it tells you the things it is looking for. Many times, you will see "Not found" or something and you know what library to install/look for. I ran `ldd`, it looks as if all the symbols are resolved ``` $ ldd rbasic.so linux-vdso.so.1 (0x7ffe7af56000) libR.so => /lib/libR.so (0x7f269adb8000) libdruntime-ldc-shared.so.94 => /snap/ldc2/170/bin/../lib/libdruntime-ldc-shared.so.94 (0x7f269ac0c000) libblas.so.3 => /lib/x86_64-linux-gnu/libblas.so.3 (0x7f269920d000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x7f26990be000) libreadline.so.8 => /lib/x86_64-linux-gnu/libreadline.so.8 (0x7f269906e000) libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x7f2698fdc000) liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x7f2698fb3000) libbz2.so.1.0 => /lib/x86_64-linux-gnu/libbz2.so.1.0 (0x7f2698fa) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x7f2698f84000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x7f2698f7e000) libicuuc.so.66 => /lib/x86_64-linux-gnu/libicuuc.so.66 (0x7f2698d98000) libicui18n.so.66 => /lib/x86_64-linux-gnu/libicui18n.so.66 (0x7f2698a97000) libgomp.so.1 => /lib/x86_64-linux-gnu/libgomp.so.1 (0x7f2698a55000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x7f2698a32000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x7f269884) /lib64/ld-linux-x86-64.so.2 (0x7f269b29e000) librt.so.1 => /snap/core/current/lib/x86_64-linux-gnu/librt.so.1 (0x7f2698638000) libgcc_s.so.1 => /snap/core/current/lib/x86_64-linux-gnu/libgcc_s.so.1 (0x7f269842) libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x7f26983f) libicudata.so.66 => /lib/x86_64-linux-gnu/libicudata.so.66 (0x7f269692f000) libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x7f269674e000) ``` Otherwise, it might be that librt.so.1 seemed to have __clock_nanosleep when it was built, but the librt.so.1 it is loading during runtime does not have it. Are you building on one machine and then running on another? I am building and running on the same machine.
Re: How to compile Phobos with other D code to create a shared library?
Doing `Runtime.initialize` is working with Julia but not yet R, I'm getting a clock/GLIBC error ``` Error in dyn.load("rbasic.so") : unable to load shared object 'code/rbasic.so': lib/x86_64-linux-gnu/librt.so.1: undefined symbol: __clock_nanosleep, version GLIBC_PRIVATE ``` do I need to import anything else?
Re: How to compile Phobos with other D code to create a shared library?
On Monday, 31 May 2021 at 21:26:15 UTC, Steven Schveighoffer wrote: You need to call it wherever you think it might not have been called yet. It's reentrant, so if you call it more than once, it will only initialize once, and count how many times you have to call `Runtime.terminate`. Best to use a `scope(exit)` to call `Runtime.terminate` if you are calling it periodically. Many thanks! Something interesting is using arrays. I can see that if you instantiate an array within the D function using `new`, for instance ``` auto result = new double[n]; ``` you can't return that array to Julia (or whatever) if your function does ``` scope(exit) Runtime.terminate(); ``` and it segfaults. But while you can do: ``` auto result = cast(double*)malloc(double.sizeof * n); ``` you're left with the issue of not being able to free the memory since you've terminated the runtime. So I guess you have to appropriately pair up `initialize` and `terminate` as appropriate to kind of *startup* and and *shutdown* the connection with druntime with your allocations if they stay within D?
Re: How to compile Phobos with other D code to create a shared library?
On Monday, 31 May 2021 at 21:01:19 UTC, Steven Schveighoffer wrote: ticksPerSecond is initialized in the runtime just before static constructors are run. See https://github.com/dlang/druntime/blob/2d8b28da39e8bc3bc3172c69bb96c35d77f40d2a/src/rt/dmain2.d#L130 Are you calling Runtime.initialize()? Nope, I guess I'm supposed to be? if so where do I place the call(s) for initialize() and terminate()?
Re: How to compile Phobos with other D code to create a shared library?
On Monday, 31 May 2021 at 20:32:11 UTC, kinke wrote: On Monday, 31 May 2021 at 19:21:52 UTC, data pulverizer wrote: ldc2 jbasic.d -O3 -link-defaultlib-shared --betterC --boundscheck=off -nogc -shared -of=jbasic.so The problem is almost certainly `-betterC`, which disables linking against Phobos and druntime. Thanks - I should have know that one! I've removed the flag but now I'm getting the following error when I try to call the function: ``` Aborting from src/core/time.d(2131) MonoTimeImpl!(ClockType.normal) failed to get the frequency of the system's monotonic clock. signal (6): Aborted in expression starting at REPL[2]:1 gsignal at x86_64-linux-gnu/libc.so.6 (unknown line) abort at x86_64-linux-gnu/libc.so.6 (unknown line) _D4core8internal5abortQgFNbNiNfMAyaMQemZv at /lib64/libphobos2.so.0.90 (unknown line) _D4core4time__T12MonoTimeImplVEQBdQBb9ClockTypei0ZQBj8currTimeFNbNdNiNeZSQCtQCr__TQCpVQCei0ZQCz at dmd/current/lib64/libphobos2.so.0.90 (unknown line) _D3std6random13bootstrapSeedFNbNiZm at dmd/current/lib64/libphobos2.so.0.90 (unknown line) _D3std6random__T17unpredictableSeedTmZQwFNbNdNiNeZm at dmd/current/lib64/libphobos2.so.0.90 (unknown line) _D3std6random17unpredictableSeedFNbNdNiNeZk at dmd/current/lib64/libphobos2.so.0.90 (unknown line) ```
How to compile Phobos with other D code to create a shared library?
Hi, I am trying to compile D code to a shared library to be called by another language (in this case Julia). I can get a basic call to work but I can't call functions that use Phobos (I have no idea how to compile against it). I have found some documentation [here](https://github.com/mesonbuild/meson/issues/6786) and [here](https://dlang.org/articles/dll-linux.html) that lists compilation against specific flags so for instance I have tried: ``` ldc2 jbasic.d -O3 -link-defaultlib-shared --betterC --boundscheck=off -nogc -shared -of=jbasic.so ``` But in Julia (and the equivalent thing happens in R), when I attempt to load the function I get an error: ``` ERROR: could not load library "./jbasic.so" ./jbasic.so: undefined symbol: _D3std6random__T21MersenneTwisterEngineTmVmi64Vmi312Vmi156Vmi31VmN5403634167711393303Vmi29Vmi6148914691236517205Vmi17Vmi8202884508482404352Vmi37VmN2270628950310912Vmi43Vmi6364136223846793005ZQGt6__initZ ``` I tried the equivalent with `dmd`: ``` dmd jbasic.d -O -defaultlib=libphobos2.so -betterC -fPIC -boundscheck=off -shared -of=jbasic.so ``` with the same result. Thank you.
Re: Passing lots of C flas to the D compilers and DUB
On Thursday, 27 May 2021 at 01:55:15 UTC, Witold Baryluk wrote: try: ```bash dmd "-L$(pkg-config --libs libR)" main.d ``` if that doesn't work there are some other tricks (with `sed` for example), but I think the above should work. Thanks
Re: Naming issue importing different function overloads
On Sunday, 30 May 2021 at 18:50:25 UTC, Adam D. Ruppe wrote: On Sunday, 30 May 2021 at 18:42:34 UTC, data pulverizer wrote: I wonder if it is a purposeful design It is by design: https://dlang.org/articles/hijack.html Basically the idea behind it is to make sure that a change in a lib you import doesn't change your existing code without you realizing it. You can merge them at the import site by doing import funs; doubme myfun(...) {} alias myfun = funs.myfun; // this line merges them You can also use a selective import to merge them: import funs : myfun; double myfun(...) {} now both myfuns work. this works because the `import x : y;` is actually shorthand for a local alias. Many thanks
Naming issue importing different function overloads
Hi, There's issue in importing functions I came across some time ago that I wonder if it is a purposeful design or if it is something that will be changed in the future. Say I have module like this: ```d module funs; double myfun(double x) { return x*x; } ``` and I call `myfun` in a function in another module: ```d module call; import funs; double myfun(double y, double x) { return myfun(x)/y; } void main() { import std.stdio: writeln; writeln("Demo myfun(2, 3): ", myfun(2, 3)); } ``` If I attempt to compile this I shall get the error: ``` $ dmd call.d funs.d call.d(8): Error: function call.myfun(double y, double x) is not callable using argument types (double) call.d(8):missing argument for parameter #2: double x ``` Even though the function signatures are different I have to call `myfun` with `funs.myfun(...)` in the `call.d` module. I understand sometimes it's is good practice to do this, but shouldn't I expect the D compiler to be "clever enough" to ignore correct use but detect when function signatures clash and throwing an error with an appropriate message when they do, rather than a cryptic message telling me that the function signature is wrong? In the current situation, you can import `funs.d` and call `myfun` with no issue until you decide to overload it in that module, when you suddenly get errors. If you are not aware of this issue and you are writing a large and highly detailed module, it's an error that seems to come out of nowhere, the module has suddenly lost visibility of the imported function. I guess an alternative is to use `mixin(import("funs.d"));` but you then lose the functionality of the formal `import` statement. Thank you
Passing lots of C flas to the D compilers and DUB
Hi, A [previous post](https://forum.dlang.org/post/hxlhyalzqmzzzihdj...@forum.dlang.org) shows how to link individual C flags with `-L`, but is there a convenient way of linking lots of C flags? I've tried variations of ``` dmd `pkg-config --libs libR` `pkg-config --cflags libR` main.d dmd `pkg-config --cflags --libs libR` main.d dmd -L`pkg-config --cflags --libs libR` main.d ... ``` for linking the R library C backend on Ubuntu Linux and it hasn't worked. I'm getting the usual unrecognized switch errors: ``` Error: unrecognized switch '-Wl,--export-dynamic' Error: unrecognized switch '-fopenmp' Error: unrecognized switch '-Wl,-Bsymbolic-functions' Error: unrecognized switch '-Wl,-z,relro' Error: unrecognized switch '-lR' ... ``` If there is a method, it would be really useful to know if and how it changes for the LDC compiler and also for DUB. Many thanks
Re: Silicon Valley D Meetup - March 18, 2021 - "Templates in the D Programming Language" by Ali Çehreli
On Wednesday, 17 March 2021 at 21:54:27 UTC, Ali Çehreli wrote: I will explain templates in a beginner-friendly way. Although this is announced on Meetup[1] as well, you can connect directly at https://us04web.zoom.us/j/2248614462?pwd=VTl4OXNjVHNhUTJibms2NlVFS3lWZz09 March 18, 2021 Thursday 19:00 Pacific Time Ali [1] https://www.meetup.com/D-Lang-Silicon-Valley/events/kmqcvqyccfbxb/ I turned up to this online meetup and I have to say that I got an enormous amount out of it! Conversations like this once a month or so a few years ago would have made me a much better programmer (and maybe even a different person) now. Ali spent a lot of time dissecting code in such an informative, cogent, and enlightening way, I'm kicking myself for not getting involved in these kinds of meetings before. Even though the scheduled time for me was 2:00am in the morning, I feel energised for what I learned. It's a bit like I was groping around in the semi-darkness and someone switched on a light bulb. Many thanks to Ali for setting this one up! There was one other person who made a useful comment that helped my understanding whose name I don't recall - thank you too.
Re: Mir vs. Numpy: Reworked!
On Monday, 7 December 2020 at 02:14:41 UTC, 9il wrote: I don't know. Tensors aren't so complex. The complex part is a design that allows Mir to construct and iterate various kinds of lazy tensors of any complexity and have quite a universal API, and all of these are boosted by the fact that the user-provided kernel(lambda) function is optimized by the compiler without the overhead. I agree that a basic tensor is not hard to implement, but the specific design to choose is not always obvious. Your benchmarks shows that design choices have a large impact on performance, and performance is certainly a very important consideration in tensor design. For example I had no idea that your ndslice variant was using more than one array internally to achieve its performance - it wasn't obvious to me. I think literature that discuss various design choices and approaches would be useful and informative. There is plenty of literature on creating tree structures, linked lists, stacks, queues, hash tables and so forth, but virtually nothing on tensor data structures. It isn't as if implementing a linked list is any more complex than a tensor. I just think it's a bit strange that there is so little on the topic - given the widespread use of tensors in computational science.
Re: Mir vs. Numpy: Reworked!
On Saturday, 5 December 2020 at 07:44:33 UTC, 9il wrote: sweep_ndslice uses (2*N - 1) arrays to index U, this allows LDC to unroll the loop. For example, for 2D case, withNeighboursSum [2] will store the pointer to the result, and the pointer at rows above and below. matrix: -- --a--- above iterator --r--- the result --b--- below iterator -- Also, for AVX-512 targets it allows vectorizing the loop [1]. The benchmark has been run on the AVX2 CPU. [1] https://github.com/typohnebild/numpy-vs-mir/issues/4 [2] http://mir-algorithm.libmir.org/mir_ndslice_topology.html#.withNeighboursSum Very interesting, thank you for the explanations. Are there journal/book other implementation references for these approaches to implementing tensor-like multidimensional arrays? Tensor-like multidimensional arrays data structures is one of the worst covered in research/conventional literature compared to almost anything else, which can be rather frustrating.
Re: Mir vs. Numpy: Reworked!
On Friday, 4 December 2020 at 14:48:32 UTC, jmh530 wrote: It looks like all the `sweep_XXX` functions are only defined for contiguous slices, as that would be the default if define a Slice!(T, N). How the functions access the data is a big difference. If you compare the `sweep_field` version with the `sweep_naive` version, the `sweep_field` function is able to access through one index, whereas the `sweep_naive` function has to use two in the 2d version and 3 in the 3d version. Also, the main difference in the NDSlice version is that it uses *built-in* MIR functionality, like how `sweep_ndslice` uses the `each` function from MIR, whereas `sweep_field` uses a for loop. I think this is partially to show that the built-in MIR functionality is as fast as if you tried to do it with a for loop yourself. I see, looking at some of the code, field case is literally doing the indexing calculation right there. I guess ndslice is doing the same thing just with "Mir magic" an in the background? Still, ndslice is able to get a consistent higher rate of flops than the field case - interesting. One thing I discovered about these kinds of plots is that introducing log scale or two particularly for timed comparisons can make the differences between different methods that look close clearer. A log plot might show some consistent difference between the timings of ndslice and the field case. Underneath they should be doing essentially the same thing so teasing out what is causing the difference would be interesting. Is Mir doing some more efficient form of the indexing calculation than naked field calculations? I'm still not sure why slice is so slow. Doesn't that completely rely on the opSlice implementations? The choice of indexing method and underlying data structure? Isn't it just a symbolic interface that you write whatever you want?
Re: Mir vs. Numpy: Reworked!
On Thursday, 3 December 2020 at 21:28:04 UTC, jmh530 wrote: The document says: Slice: Python like. Uses D Slices and Strides for grouping (Red-Black). Naive: one for-loop for each dimension. Matrix-Access via multi-dimensional Array. Field: one for-loop. Matrix is flattened. Access via flattened index. NdSlice: D like. Uses just MIR functionalities. It's quite interesting because it says that it's well worth implementing a field index as supposed to naive access - at least for this algorithm. It makes sense because in the field case at least you know that all the data is on the same array - and therefore in close proximity in memory, whereas individual arrays in multidimensional array could be far apart in the memory. NDSlice is even faster for this case - cool. Am I correct in assuming that the data in the NDSlice is also a single array?
Re: Mir vs. Numpy: Reworked!
On Thursday, 3 December 2020 at 21:28:04 UTC, jmh530 wrote: The document says: Slice: Python like. Uses D Slices and Strides for grouping (Red-Black). Naive: one for-loop for each dimension. Matrix-Access via multi-dimensional Array. Field: one for-loop. Matrix is flattened. Access via flattened index. NdSlice: D like. Uses just MIR functionalities. Thanks, evidently I should have been more thorough in reading the document. :-)
Re: Mir vs. Numpy: Reworked!
On Thursday, 3 December 2020 at 16:27:59 UTC, 9il wrote: Hi all, Since the first announcement [0] the original benchmark [1] has been boosted [2] with Mir-like implementations. ... [SNIP] Kind regards, Ilya Very interesting work. What is the difference between Mir's field, slice, native and ndslice? Looks like your packages are really hotting up. I wonder how the performance compares with an equivalent Julia implementation.
Re: How to construct a tree data structure with differently static nodes types
On Monday, 23 November 2020 at 01:24:54 UTC, Max Haughton wrote: If you want to keep things simple, use OOP (classes). If you need to use structs, the "sumtype" may be just what you need (it's a bit more lightweight than std.algebraic in the standard library). If you want to implement this yourself then you need to write something called a tagged union. I'm looking for a data structure that is fully specified at compile time and statically dispatched rather than dynamically dispatched like OOP and so forth.
Re: How to construct a tree data structure with differently static nodes types
On Monday, 23 November 2020 at 01:20:04 UTC, data pulverizer wrote: Hi all, I am trying to construct a tree data structure composed of differently (statically) typed nodes. The basic case is a binary tree. So you have a node like: ``` struct Node(T) { T value; Node* next; Node* prev; } void main() { auto x = Node!(int)(2); auto y = Node!(double)(3.2); x.next = //gives error } ``` Error: cannot implicitly convert expression & y of type Node!double* to Node!int* So implicity Node!(T) will produce an object with prev, and next type Node!(T)*. But once I give them different types: ``` struct Node(T, P, N) { T value; Node!(P...)* prev; Node!(N...)* next; } ``` I can no longer specify the types at all, they become circularly referenced. Would appreciate the solution to this. Many thanks. p.s. Something equivalent can be built using tuples but it's less convenient to write code for.
How to construct a tree data structure with differently static nodes types
Hi all, I am trying to construct a tree data structure composed of differently (statically) typed nodes. The basic case is a binary tree. So you have a node like: ``` struct Node(T) { T value; Node* next; Node* prev; } void main() { auto x = Node!(int)(2); auto y = Node!(double)(3.2); x.next = //gives error } ``` Error: cannot implicitly convert expression & y of type Node!double* to Node!int* So implicity Node!(T) will produce an object with prev, and next type Node!(T)*. But once I give them different types: ``` struct Node(T, P, N) { T value; Node!(P...)* prev; Node!(N...)* next; } ``` I can no longer specify the types at all, they become circularly referenced. Would appreciate the solution to this. Many thanks.
Re: Issue with opening files on VSCode "D Language utility extension pack"
On Monday, 16 November 2020 at 08:16:44 UTC, WebFreak001 wrote: On Monday, 16 November 2020 at 01:38:10 UTC, data pulverizer wrote: Hi All, On VS Code "D Language utility extension pack", I notice that if I open a random D file, on the bottom left of the IDE, a message says "D: workspace/(0.0%): starting up...". It stays at 0.0% and doesn't go away and gives the impression that it is broken. Opening a file through a folder in explorer mode however works. Thanks I can't reproduce this with the master branches of code-d/serve-d so this might be something already fixed with the nightly serve-d build and ~master code-d I have no idea how to install the ~master extension in VS Code. Under extensions when I go to "Manage" -> "Install Another Version ..." I can't see the master branch. Only the current and previous released version tags.
Re: Issue with opening files on VSCode "D Language utility extension pack"
On Monday, 16 November 2020 at 08:04:24 UTC, frame wrote: On Monday, 16 November 2020 at 01:38:10 UTC, data pulverizer wrote: Hi All, On VS Code "D Language utility extension pack", I notice that if I open a random D file, on the bottom left of the IDE, a message says "D: workspace/(0.0%): starting up...". It stays at 0.0% and doesn't go away and gives the impression that it is broken. Opening a file through a folder in explorer mode however works. Thanks There could be many reasons. You will see the actual error by opening the Developer Tools Window (under Help Menu). Not seeing an error in Developer Tools. I don't expect to because the loading sign remains there as if it is continuously trying to load and doesn't display any errors.
Issue with opening files on VSCode "D Language utility extension pack"
Hi All, On VS Code "D Language utility extension pack", I notice that if I open a random D file, on the bottom left of the IDE, a message says "D: workspace/(0.0%): starting up...". It stays at 0.0% and doesn't go away and gives the impression that it is broken. Opening a file through a folder in explorer mode however works. Thanks
Re: Can we do compile time reading part of a file using import?
On Sunday, 25 October 2020 at 12:16:36 UTC, Jacob Carlborg wrote: On 2020-10-23 18:42, data pulverizer wrote: You could always have the build tool split up the file in multiple smaller files and read one of the smaller files with the import expression. Thanks. My current solution is to have a metadata file where all the type information is stored and then the data file separately. I should have been clearer when I asked if there was something I was missing, like whether there is another way to do compile time read without reading the whole file. I think the feature I suggested is a useful one to bear in mind for future versions of D. It would save on preprocessing large files before reading them. I don't know how `import` for file reads works at the moment, and correct me if I'm wrong but it doesn't seem to me that it would be a big deal to make the change.
Can we do compile time reading part of a file using import?
Hi all, the `import` function allows a file to be read at compile time, which opens up great opportunities for (mostly binary) file IO, where data types can be coded into files - the user doesn't need to know data types ahead of time. As specified in my old blog article: https://www.active-analytics.com/blog/reading-idx-files-in-d/. Binary files can be very large and reading the whole file at compile time is often unnecessary. This isn't exactly the intended use for the function, but there it is. Since compile time read capability already exists and is useful, adding capability to be able to read only a portion of the file at compile time in a given location is advantageous and has utility. For me it's not make-or-break, it just something very useful and I think has clear use case. Please let me know if there are aspects or alternatives I am missing. Thanks
Re: How can I test at compile time whether T is an instance of an interface ?
On Wednesday, 23 September 2020 at 20:19:04 UTC, data pulverizer wrote: Thinking more about it this ... class Middle: Node { Node prev; Node next; } won't work because the I've told the compiler that the static type is "Node", my original design was something like this: ``` struct Middle(P, N) { P prev; N next; } ``` which also won't work because it can't actually be instantiated (recursive), and the start and end nodes must be different types (and you can't substitute the middle node for the start and end node). It's the simplest case because there could be more than one type of middle node. More generally, correct me if I'm wrong, but I don't think these kinds of statically multityped tree structures can be formed in static languages so I've been using tuples - at least for the simple case I outlined.
Re: How can I test at compile time whether T is an instance of an interface ?
On Wednesday, 23 September 2020 at 20:19:04 UTC, data pulverizer wrote: This has prompted me to write a data structure that I thought would be impossible until now False alarm: ``` writeln("typeof(x.next): ", typeof(x.next).stringof); ``` gives: ``` typeof(x.next): const(Node) ``` Oh well.
Re: How can I test at compile time whether T is an instance of an interface ?
On Wednesday, 23 September 2020 at 20:19:04 UTC, data pulverizer wrote: This has prompted me to write a data structure that I thought would be impossible until now. [...SNIP...] Here is the function with the correct template constraint: ``` auto makeChain(Args...)(Args args) if(Args.length > 2 && is(Args[0] == Start) && is(Args[Args.length - 1] == End)) { args[0].next = args[1]; static foreach(i; 1..(Args.length - 1)) { args[i].prev = args[i - 1]; args[i].next = args[i + 1]; } args[$ - 1].prev = args[$ - 2]; return args[0]; } ```
Re: How can I test at compile time whether T is an instance of an interface ?
On Wednesday, 23 September 2020 at 19:27:13 UTC, wjoe wrote: Appologies if you took offense. Your replies are very much appreciated. No offense taken.
Re: How can I test at compile time whether T is an instance of an interface ?
On Wednesday, 23 September 2020 at 19:16:13 UTC, H. S. Teoh wrote: Of course the compiler knows. And of course it can use this information for static dispatch. That's why D is so awesome at metaprogramming. ;-) What the compiler *doesn't* know is whether a variable of some supertype of Foo (say Object) implements IFoo, because that's something that can only be determined at runtime (effectively, you need to downcast to Foo / IFoo and test if it's null). But that's not what the OP is asking for in this case. T This has prompted me to write a data structure that I thought would be impossible until now. It's a data structure with a Start node with a link to next, then any number of Middle nodes with previous and next links, and an End node with a previous link all inheriting from a common interface Node. This is of course possible using runtime polymorphism, but I wanted it available for static dispatch rather than everything being listed as "Node" static type. The implementation is below and works. Interestingly when I wrote it down with a pen and paper I thought that it would lead to infinitely recursive unwriteable data type and so didn't even bother trying to implement it. But D actually forms the correct static type, it prints the gobbledygook type I expect at compile time but the actual static type at runtime. Amazing! I have been using structs with tuples because I thought this data structure was impossible! ``` import std.stdio: writeln; interface Node{} class Start: Node { Node next; } class Middle: Node { Node prev; Node next; } class End: Node { Node prev; } auto makeChain(Args...)(Args args) if(Args.length > 3) { args[0].next = args[1]; static foreach(i; 1..(Args.length - 1)) { args[i].prev = args[i - 1]; args[i].next = args[i + 1]; } args[$ - 1].prev = args[$ - 2]; return args[0]; } void main() { static const x = makeChain(new Start(), new Middle(), new Middle(), new Middle(), new Middle(), new End()); pragma(msg, "x.next: ", x.next, "\n"); writeln("x.next: ", x.next); } ``` output: ``` x.next: Middle(Start(Middle()), Middle(Middle(Start(Middle()), Middle()), Middle(Middle(Middle(Start(Middle()), Middle()), Middle()), Middle(Middle(Middle(Middle(Start(Middle()), Middle()), Middle()), Middle()), End(Middle(Middle(Middle(Middle(Start(Middle()), Middle()), Middle()), Middle()), End())) x.next: node.Middle ```
Re: How can I test at compile time whether T is an instance of an interface ?
On Wednesday, 23 September 2020 at 18:56:33 UTC, wjoe wrote: It doesn't occur to me that the compiler doesn't know at compile time that interface IFoo{} class Foo: IFoo {} class Foo implements interface IFoo. Didn't think that the compiler didn't know but wasn't aware that you could use that information to statically dispatch. My mistake, I'll shut up now!
Re: How can I test at compile time whether T is an instance of an interface ?
On Wednesday, 23 September 2020 at 18:37:45 UTC, wjoe wrote: I have some similar functions: void register(C: IFoo)() { _insert!C(); } void register(C)() if (behavesLikeFoo!C) { _insert!C(); } There are more overloads with parameters so I want to merge them void register(C, ARGS...)(ARGS args) if (behavesLikeFoo!C || isInstanceOf!(C, IFoo)) { _insert!C(args); } I found a lot of information on how to do this at runtime but not at compile time. std.traits: isInstanceOf doesn't work. Neither did anything I tried with typeid etc. The behavesLikeFoo constraint works as expected but it accepts any class no matter whether or not it implements the interface. A class at compile time is it's own static type, OOP polymorphism is a runtime feature not compile time. You have to write your own traits for specific objects to get them to relate to each other using static overloading.
Re: Type inference for constructors
On Friday, 18 September 2020 at 06:43:12 UTC, Simen Kjærås wrote: On Friday, 18 September 2020 at 05:43:56 UTC, data pulverizer That's issue 1997: https://issues.dlang.org/show_bug.cgi?id=1997 D's templates are turing complete, and there may be arbitrary amounts of logic obscuring the mapping between type template parameters and the specific argument types of the type's constructor, so the problem is intractable in the general case. E.g: template Foo(T) { static if (is(T == int)) { struct Foo { this(int i) {} // int-specific code } } else { struct Foo { this(T t) {} // generic code } } } The above example is a simple one, yet mapping from a constructor call to the correct template parameters is difficult. Thank you for the explanation and the reference. That's a template this parameter (https://dlang.org/spec/template.html#template_this_parameter). It takes on the type of 'this' at the point of instantiation. That is: struct S { void fun(this T)() { pragma(msg, T); } } unittest { S s; const S sc; immutable S si; shared S ss; s.fun(); // prints S sc.fun(); // prints const(S) si.fun(); // prints immutable(S) ss.fun(); // prints shared(S) } This allows the return type to have the same constness as 'this', or for specific code to be executed when operating on e.g. a non-mutable instance, where lazy initialization couldn't be performed. In many cases, this is better served by using inout: https://dlang.org/spec/function.html#inout-functions After reading your explanation and looking at the part of the manual you referred to, it looks as if this pattern could have a lot of utility, the `Addable` example in the manual looks like polymorphism with dynamic dispatch but retains static type a bit like Rust's (runtime) traits. Many thanks.
Type inference for constructors
I’d like to know if constructors of classes and structs can have type inference. So far, I am using a separate function for this purpose, for example: ``` import std.stdio: writeln; struct Pair(T, U) { T first; U second; this(T first, U second) { this.first = first; this.second = second; } } Pair!(T, U) pair(T, U)(T first, U second) { return Pair!(T, U)(first, second); } void main() { auto mp = pair("Michael", 32);//standard function inference works //auto m0 = Pair("Michael", 32); //I’d like to be able to do this writeln("pair: ", mp); } ``` On a slightly different note, I was doing some reading in std.typecons (https://github.com/dlang/phobos/blob/3754e92341a393331bd6b0bc9e70335d34e42016/std/typecons.d#L6838) on Github and wondered what `this` in the code below does: ``` auto ref opIndex(this X, D...)(auto ref D i) { return a[i]; } ```
Re: Introduction to programming with compile time sequences in D
On Tuesday, 25 August 2020 at 15:58:46 UTC, Petar Kirov [ZombineDev] wrote: I think your article is quite valuable is it covers many aspects of template programming in D, while being quite approachable as well. May I suggest contributing it in some form to https://tour.dlang.org? Contributing is as easy as opening a pull request to this repo: https://github.com/dlang-tour/english. Just check the format of some of the other *.md and *.yml files there and you'll figure it out. We already have a section on templates there, but I think it's way too brief and doesn't do justice to the D's extensive template features. Perhaps it could be organized as a fully separate section with different articles, corresponding to each paragraph in your article. I've written a more comprehensive tutorial for generic and compile time programming in D, and submitted a pull request to replace the current template material in the tour: https://github.com/dlang-tour/english/pull/341 Thanks.
Re: Introduction to programming with compile time sequences in D
On Tuesday, 1 September 2020 at 17:12:05 UTC, data pulverizer wrote: ii. Runnable code areas for actual scripts, the same width and in line with the text like the "dumb code" fences but as you said with a few buttons on the top for running the code (I'm not really bothered if they can pop out to another window/tab and so on). They should be scrollable because you don't want a huge amount of code just pasted in going potentially over one or more pages long. p.s. The nice thing about having something like this is that you build up a theme throughout the writing and regular code areas and then have the live demo area and carry on with another related theme and have another live demo in the same page and so forth - a bit like a Jupyter notebook where it flows nicely with the text for the reader who can scroll up and down to view different things.
Re: Introduction to programming with compile time sequences in D
On Tuesday, 1 September 2020 at 16:24:29 UTC, Petar Kirov [ZombineDev] wrote: Yeah, I think we should add the following feature: Whenever there's a snippet of code (fenced code block in markdown), a button should appear under, which when clicked would replace the content of the text editor with the code snippet. There two challenges with this: 1. Many of the code snippets that appear throughout the articles are not meant to be runnable, so we would need a way to provide the necessary scaffolding (e.g. wrap them in `void main() { /+ ... +/ }`) I think there should be two kinds of code area. i. The regular "dumb code" fences (as we already have) which is just for displaying code. I have lots of these throughout my text, the code they contain are in general not runnable because they are designed to show only part of it or some output for discussion. ii. Runnable code areas for actual scripts, the same width and in line with the text like the "dumb code" fences but as you said with a few buttons on the top for running the code (I'm not really bothered if they can pop out to another window/tab and so on). They should be scrollable because you don't want a huge amount of code just pasted in going potentially over one or more pages long. I wonder if that is doable? 2. It may surprising and inconvenient for users to have the code they have potentially modified disappear. This could be solved by adding proper support for multiple open files to the editor (along the lines of commercial solutions like codesandbox, github workspaces, etc.). What would happen is that click [Edit] on a code-block would simply open another file. I leave that to your expertise. The main thing is that people should be able to run and/or modify the code, and that the original content comes back on reload. I'm not sure it needs to be super-robust in terms of storing everything from the user because it's not a proper development area, only for learning. [:shrug:]
Re: Introduction to programming with compile time sequences in D
On Saturday, 29 August 2020 at 04:41:36 UTC, Petar Kirov [ZombineDev] wrote: On Friday, 28 August 2020 at 11:05:09 UTC, data pulverizer wrote: On Tuesday, 25 August 2020 at 15:58:46 UTC, Petar Kirov [ZombineDev] wrote: [...] Just to keep you updated, I've begun to write a fresh section on templates for dlang-tour quite separate from the blog article - something more appropriate for the website, though I'll take some elements of what I've already done. Once it's finished I'll do a pull request. Thanks Sounds great, thank you! I've finished writing the fresh section and checked it through a few times. It is pretty detailed and long and before releasing it and doing a pull request I'll check it through once or twice more over the next day or two. The document content structure is: ``` # Templates and Compile Time Programming in D ## Contents * Introduction * Templates in D * Function templates * Longhand and shorthand declarations * Inference of parameters * Access patterns for template internals * Alias template parameter * Variadic template functions * The is() directive * More on template constraints and partial specialization * Struct, class, and interface templates * Struct template longhand and shorthand declarations * Variadic template objects * Template constraints and specialization * Enumeration templates * Alias templates * static if * Traits * Metaprogramming in D * Introduction * AliasSeq!(T) compile time sequences * Append, prepend and concatenating compile time lists * Replacing items in compile time sequences * Replacing multiple items with an individual type * String mixins * static foreach * Replacing multiple items by a tuple of items * Contained type sequences * Template mixins, CTFE, and import * Template mixins * CTFE * import("file.d") ``` I have written lots of code examples in the text but there are also lots of runnable files that can be in code demo "play" sections. The only thing is when I look at the current coding area it is quite large and separate from the text. Sometime in the future, I guess it would be great to have it inline with the text and smaller like the regular fenced code so that multiple files can be included in separate scrollable "play" areas. Thanks
Re: Introduction to programming with compile time sequences in D
On Tuesday, 25 August 2020 at 15:58:46 UTC, Petar Kirov [ZombineDev] wrote: I think your article is quite valuable is it covers many aspects of template programming in D, while being quite approachable as well. May I suggest contributing it in some form to https://tour.dlang.org? Contributing is as easy as opening a pull request to this repo: https://github.com/dlang-tour/english. Just check the format of some of the other *.md and *.yml files there and you'll figure it out. We already have a section on templates there, but I think it's way too brief and doesn't do justice to the D's extensive template features. Perhaps it could be organized as a fully separate section with different articles, corresponding to each paragraph in your article. Just to keep you updated, I've begun to write a fresh section on templates for dlang-tour quite separate from the blog article - something more appropriate for the website, though I'll take some elements of what I've already done. Once it's finished I'll do a pull request. Thanks
Re: Introduction to programming with compile time sequences in D
On Thursday, 27 August 2020 at 20:56:43 UTC, Twilight wrote: On Tuesday, 25 August 2020 at 02:11:42 UTC, data pulverizer wrote: I have a draft new blog article "Introduction to programming with compile time sequences in D", it's on Github and I would appreciate feedback before it goes live https://gist.github.com/dataPulverizer/67193772c52e7bd0a16414cb01ae4250 Comment welcome. Many thanks Not being a Dlang expert, I probably qualify as the intended target audience for this article and having absorbed your previous article so readily, I thought I would try to expound a little where I stumbled with this article. I was clipping along until I reached the "Replacing a single item by index" section. Having mentioned earlier that AliasSeq was defined in std.meta, I thought this section started out by saying that this was the implementation of the Replace meta-function in the internals of std.meta, and consequently, because it is marked as private (to the std.meta module), I can not use this function (confusingly). As you can see, the wording took me down a path you did not intend. When I reached the bottom of this section, it was helpful to see the intended call with 3 arguments. The earlier 4 arguments was puzzling. I now think that the "internal" implementation was meant to convey the role that "ReplaceImpl" would if this were C++ templates (with the extra argument used to count to the match). Anyway, this particular section seems to be better digested for me from the bottom upwards, i.e., starting with an example of its use. Also, the Join function might be better placed in the previous section. Do consider that I may just be a little off in my reading comprehension today so please weigh my thoughts accordingly. I have greatly appreciated the recent articles by you and others. Thanks authors! Thanks for your feedback, when I look at my introduction I clearly mention the `text` function that I imported from `std.conv` but not `AliasSeq`, and `Nothing` that I implemented from `std.meta`, I have now put these in the introduction along with `text` which should make things clearer.
Re: Introduction to programming with compile time sequences in D
On Tuesday, 25 August 2020 at 16:01:25 UTC, data pulverizer wrote: On Tuesday, 25 August 2020 at 14:02:33 UTC, Petar Kirov [ZombineDev] wrote: ... You can find a full example of this here: https://run.dlang.io/gist/run-dlang/80e120e989a6b0f72fd7244b17021e2f There is an issue with `AliasTuple` though, you can't directly print its collections with pragma: ```d alias coll = AliasSeq!(s1, s2, s3, s7); pragma(msg, coll); ``` I get the following error: ```d onlineapp.d(29): Error: cannot interpret AliasTuple!1 at compile time onlineapp.d(29): Error: cannot interpret AliasTuple!(1, 2) at compile time ... tuple((__error), (__error), (__error), (__error)) ``` p.s. I did include a `Tuple` - like implementation in my article at the later sections, but it was based on a template struct.
Re: Introduction to programming with compile time sequences in D
On Tuesday, 25 August 2020 at 14:02:33 UTC, Petar Kirov [ZombineDev] wrote: ... You can find a full example of this here: https://run.dlang.io/gist/run-dlang/80e120e989a6b0f72fd7244b17021e2f There is an issue with `AliasTuple` though, you can't directly print its collections with pragma: ```d alias coll = AliasSeq!(s1, s2, s3, s7); pragma(msg, coll); ``` I get the following error: ```d onlineapp.d(29): Error: cannot interpret AliasTuple!1 at compile time onlineapp.d(29): Error: cannot interpret AliasTuple!(1, 2) at compile time ... tuple((__error), (__error), (__error), (__error)) ```