Re: CTFE, string mixins & code generation
On Friday, 24 January 2020 at 16:21:48 UTC, Jan Hönig wrote: I am looking for a detailed explanation or showcase regarding CTFE and string mixins. I want to play with D a little bit regarding code generation. I would like to have a pseudo-AST, consisting of a few classes, to represent some calculation. Think of a loop, some statements, and expressions. To do that, I want to be certain that this AST can be computed and generated during compile-time, with CTFE and string mixins. Are there limitations regarding CTFE (GC, global variables, static variables, templates, )? Are there any limitations regarding string mixins (which are not already included int the CTFE limitations)? For CTFE: functions should be pure. Therefore you cannot use global or static variables. Constants (enums) are perfectly fine to use though. I don't know the state of the GC and CTFE. I recall that there might be some complexity when using the `new` keyword. https://dlang.org/spec/function.html#interpretation Basically the only limitation of string mixins is that a single string should evaluate to valid D code, opposed to C macros. So int y mixin("= 6"); doesn't compile, while int y = mixin("6"); or mixin("int y = 6;"); does. You can use CTFE to compose the string.
Re: Anyway to compare function aliases? Or any ideas?
On Thursday, 4 July 2019 at 15:10:05 UTC, aliak wrote: Any ideas on how to be able to do something like this? struct S(alias _fun) { alias Fun = _fun; } void algorithm(alias f, T)(T s) { static if ( == ) { // trivial return } else { // must perform work, then return } } Can you use function addresses in some way? I've seen that some of them are resolved to __lambda0 and other times to a function type, i.e. Error: incompatible types for (& f) is (& __lambda1): void function(A!(function () => 3) t) and int function() pure nothrow @nogc @safe That comes from doing doing this: alias g = () => 3; algorithm!g(S!g()); I've thought of something along the lines of a function alias wrapper. But I'm not sure how to make that work either. Something like: struct Fun(alias _fun, string _id) { alias Fun = _fun; enum ID = _id; } Then maybe something like: alias g = () => 3; Fun!(g, "myid") gfun; algorithm!gfun(S!gfun()); Then inside algorithm the check becomes: static if ( == ) But then I'd like to generate the ID at instantiation point. So is using __LINE__, __FILE__ and applying some hash function a good idea here? Any other ideas? Cheers, - Ali PS: If you're curious of a semi working sample, to see what I'm actually trying to do, I've put up this gist that does not compile right now: https://gist.github.com/aliak00/fcdd4fa7512035405bb7015cf6d8016f I don't know if it will solve your whole problem, but have you tried __traits(isSame, W0.fun, fun)? Reduced example: struct Foo(alias fun){ alias bar = fun; } void stuff(alias fun, T)(T t) { static if(__traits(isSame, fun, T.bar)) { pragma(msg, "Yes"); } else { pragma(msg, "No"); } } void a(){} void b(){} void main() { stuff!a(Foo!a()); // Yes stuff!a(Foo!b()); // No }
Re: How to convert array of structs to JSON
On Tuesday, 25 June 2019 at 05:33:57 UTC, mark wrote: I have the following array of structs: struct Person { string name; int age; }; Person people[]; Person p; Person p1 = { "Bob", 12 }; Person p2 = { "Bob", 12 }; people ~= p1; people ~= p2; I've read through the std.json documentation, but I'm still confused as to how to create an array of objects, especially if the objects are structs. I've included this: JSONValue jj; jj["nodes"].array = []; But I get the error: JSONValue is not an object. Ideally, I'd like to have a json output that looks like this: [ { "name": "Bob", "age": 12 }, { "name": "Bob", "age": 12 }, ] Any help would be greatly appreciated. As far as I can tell, there's no "out of the box" support for serialization in std.json. You can work around that by manually supplying the serialization: https://run.dlang.io/is/AZqTJE struct Person { string name; int age; JSONValue toJson() { return JSONValue(["name": JSONValue(name), "age": JSONValue(age)]); } } auto json = JSONValue(people.map!(p => p.toJson).array); writeln(json); I use the data module from vibe.d, which supports data serialization: http://code.dlang.org/packages/vibe-d%3Adata https://vibed.org/api/vibe.data.json/ struct Person { string name; int age; } auto json = people.serializeToJson(); writeln(json);
Re: What is iota function full name
On Friday, 21 June 2019 at 19:18:02 UTC, KnightMare wrote: On Friday, 21 June 2019 at 12:02:10 UTC, Jonathan M Davis wrote: On Friday, June 21, 2019 5:10:03 AM MDT JN via Some folks argued a while back that iota was a terrible name and that it should be changed, but it was decided not to change it. auto terribleName( ... ) { } auto goodName( ... ) { pragma( inline, true ) return terribleName( ... ); } everyone is happy Good tip. I usually make a file for these kind of aliases and simple functions that do not end up in the standard library, eg std.algorithm oneliners.
Re: is there any micro-service library in D?
On Wednesday, 19 June 2019 at 08:29:15 UTC, dangbinghoo wrote: hi there, Does anyone know the micro-service oriented design library or framework in D? thanks! binghoo dang What do you need from such a library? Some suggestions: For networking, there is vibe.d[0] which provides both a client and a server REST (or web) interface. There is also GraphQL-D[1] that provides a server-side GraphQL interface that can be used by other services. For modelling, there is Depend[2], which visualises dependencies. [0] http://code.dlang.org/packages/vibe-d [1] http://code.dlang.org/packages/graphqld [2] http://code.dlang.org/packages/depend
Re: Component based programming in D
On Tuesday, 18 June 2019 at 09:17:09 UTC, Bart wrote: I'm new to component based programming. I've read it is an alternative to oop for speed. I don't understand how it is possible to have an alternative to oop and still have oop like behavior(polymorphism) nor how to do this. It seems all the great things oop offers(all the design patterns) would be impossible. The benefits are suppose to better reusability as components are more isolated in their dependencies. Can someone help me understand this a little better and how I'd go about using it in D? Specifically I'm looking at the pros and cons, what are the real similarities and differences to oop, and how one implements them in D(taking in to account D's capabilities). Thanks. I don't know a lot about component-based programming per se. (I might use it all the time, I just don't know the term.) OOP as implemented by Java, C# etc. use virtual functions and inheritance to compose behaviour, also known as polymorphism. This has a slight overhead at runtime. In like >90% of the cases however, you can deduce statically what override/implementation of a function will be called. In D, we have the means to make that deduction at compile time. The most simple means is duck typing: int fun(T)(T instance) { return instance.number(); } We have a templated function, that is: a function that takes an instance of any type. Think of generics, but more liberal. If we call the function with an object: class Dice { final int number() { return 6; } } fun(new Dice()); the compiler generates a template instance, that is, a `fun` that takes a `Dice` instance as its argument. It will then compile as if you have written the Dice type there yourself: int fun(Dice instance) { return instance.number(); } This compiles because the class Dice defines a method called `number`. However, we can put any type in there that defines a number() method. In classic OOP, one would use an interface for this interface Number { int number(); } class Dice : Number { int number() { return 6; } } Using duck typing, the compiler just checks whether the code compiles given the type. If we have other types that implement number, like a Roulette class, we can simply pass an instance of that class to the function and the compiler figures it out. We don't need to define an interface. For large methods, it can be quite unclear what methods a type need to define in order to be passed in. int fun(T)(T instance) // Only if T has number() method { // Large amount of code here return instance.number(); } In this example we can only pass in a T if it defines a `number()` method. We annotated it in a comment. However, D can also explicitly check it using traits (https://dlang.org/phobos/std_traits.html) or the nuclear option: __traits(compiles, ...), which checks if a certain expression compiles successfully. Doing it the quick and dirty way, we can explicitly define our desired instance interface: int fun(T)(T instance) if(__traits(compiles, {int x = instance.number()} )) { // Large amount of code here return instance.number(); } We add a constraint to our template: our function is valid for any T for which the number() method returns an integer. This is just the surface, you can read https://github.com/PhilippeSigaud/D-templates-tutorial for a technical introduction. One thing I really like about this is that we preserve the actual type during the whole function. This means that we can call other functions using a strongly-typed argument or do other things based on what type we get. In my personal project, I need to rewrite a bunch of functions that took one type (Card), but now need to take another, reduced type (SimpleCard) as well. The functions currently output cards grouped in sets. Card has some properties (e.g. isFolded, isShown), and SimpleCard is just the value representation (e.g. spades-4). I can use classic inheritance Card extends SimpleCard, but that means I lose my type info along the way. Using duck typing, my functions work for any Card-like object and preserve the type as well. If I need polymorphism, I can achieve that using normal overload rules, e.g. void fun(CardLike)(CardLike card) { foo(card); } void foo(Card card) {} void foo(SimpleCard card) {} void foo(FakedCard card) {} The classes can be kept small - new behaviour can be glued to classes without having impact on existing code. (I once though about why my pet project was progressing so much faster than regular projects. I figured because I rarely changed code - I just added code in different files and changed one line to activate it.)
Re: Proper desctructor for an class containing dynamic array of objects
On Thursday, 13 June 2019 at 16:08:52 UTC, Mike wrote: Hi, my name is Mike and I'm new to D (coming from a Javabackground) and for fun I'm trying to learn D now. I created a simple class class Block { int a, b; this() {} } And now I have a dynamic array of objects of this class in another class: class Foo { Block[] array = new Block[](10); this() { for (int i = 0; i < array.length; i++) { array[i] = new Block(); } } } How would a proper destructor of class Foo look like? Is it enough to set "array" to null? Or do I have to set every element of the array to null and then the array, or nothing of that at all because the garbage collecter collects it, if the reference to Foo is set to null? Opposed to Java, D's member variables are static initialised. There is one default value for "array" that is shared between all instances of Foo. This allows for compiler optimisations of primitives (baking in a int value of 5 into the class definition, but gives unexpected behaviour for reference types. https://run.dlang.io/is/UNp5Al In this example, two instances of Foo are created. The constructor is run both times. However, they act on the same array object. So initialisation of the second Foo will modify references data of the first Foo. As a check, the first object of both Foos are compared by reference. Java allows you to define a block of code in your class that is run on construction, e.g. public class JavaClass { { doStuff(); } int x = initializeX(); } It makes for fun questions on things like OCA certificates. However, D doesn't allow that. All initialisation code is placed in the constructor, e.g. this() { array = new Block[](10); // ... } (Of course you can call other methods from there. In fact, constructor rules are slightly relaxed compared to Java.)
Re: Where can I find a reference for compiler flags?
On Sunday, 9 June 2019 at 19:12:32 UTC, Mike Brockus wrote: On Wednesday, 5 June 2019 at 09:45:53 UTC, Jacob Carlborg wrote: On 2019-06-05 03:19, Mike Brockus wrote: Where can I find a reference for compiler flags? Here's the reference [1]. You can also run "dmd --help" to print out the available flags. [1] might not be up to date. [1] https://dlang.org/dmd-windows.html This bit of information was helpful. But do you know what this is -dip- followed by some number... I seen three of them in Mir Algorithm meson build. A DIP is a D improvement proposal. It is basically a request for a change of the language. Some of these can be implemented in one go, as they don't have any breaking changes. However, some DIPs break an unknown amount of code. To allow for a smooth transition, the new features are implemented, and are opt-in. Users can then gradually get their code base to compile with the new behaviour. The DIP flags indicate that the compiler will build your code with said improvement enabled. The three DIPs you are talking about are * dip25 which implements https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP25.md This is about sealed references. If I understand correctly, switching this flag requires that you annotate a ref function parameter with return if you want to return it from the function. * dip1000 which implements https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1000.md This implements more scope checking for pointers. It hands a few extra safety checks for when pointers may last longer than the data they actually point to. * dip1008 which implements https://github.com/dlang/DIPs/blob/master/DIPs/DIP1008.md This allows users to throw exceptions in @nogc code. For completeness, they correspond to the current "-preview=dipX" compiler flag. They have been grouped together under the "preview" option because they were cluttering the interface. In fact, I gathered the information in this post by running "-preview=?", listing all features here. Also, at some time in the future, a preview will become the default behaviour.
Re: Casting to interface not allowed in @safe code?
On Tuesday, 21 May 2019 at 05:51:30 UTC, Jim wrote: Hi, consider this: interface Base { void setup(); } interface FeatureX { void x(); } class Foo: Base, FeatureX { void setup(){}; void x(){}; } void main() { Base foo = new Foo(); // This would be the result of a factory class (cast(FeatureX)foo).x(); // 1 } 1) error: casting to interface FeatureX is not allowed in @safe code. Question: How to call foo.x in @safe code ? I got it compiling using `(cast(FeatureX)(cast(Foo)foo)).x();`, but I don't really recommend it. As far as the compiler is concerned, `Base` and `FeatureX` are not related in any way (I'd still expect it to work though). I don't know the circumstances of your problem (so some assumptions here), but usually casting is not the best option. You are basically overriding the type system manually. Some suggestions you can evaluate: - Extend the base interface: interface FeatureX : Base { /+...+/} or interface Combined : FeatureX, Base {} - Change the factory class to return either Foo, FeatureX or a templated type (if it's a more general factory class). This way we can leverage the type system. - You can also make the cast @trusted, but that seems like it kinda defeats the purpose of the function being @safe... --- Returning to the original point (the cast is disallowed in safe code), I don't think it is listed in the spec: https://dlang.org/spec/function.html#safe-functions Unless I am missing some implementation details about interfaces, I would expect it to work just like class casts (i.e. return null on a failed cast, thereby having defined behaviour, thereby being @safe).
Re: Stack-based @nogc dynamic array
Thank you both for the quick replies. On Thursday, 16 May 2019 at 12:55:34 UTC, Kagamin wrote: Try mach.d https://github.com/pineapplemachine/mach.d it uses explicit range accessors for iteration. Thank you. I've looked into it, and it appears to be quite a big library. I've looked into mach.collect and mach.range, but I didn't manage to find what I was looking for (a simple array data structure). Do you recommend to look into any specific module?
Re: Stack-based @nogc dynamic array
On Thursday, 16 May 2019 at 12:45:03 UTC, Adam D. Ruppe wrote: I think you have overcomplicated something quite simple. int[4] buffer; int bufferLength; buffer[bufferLength++] = item_to_append; buffer[bufferLength++] = item_to_append; int[] slice = buffer[0 .. bufferLength]; // you can use slice to any std.algorithm calls etc // just remember it is on the stack so don't store it beyond a function call Thanks. It's really a lot simpler than I thought. It's slightly error prone (i.e., the code doesn't work if I use ++bufferLength), but its simplicity might be worth the trade-off.
Stack-based @nogc dynamic array
Hey all, I want to create a small collection of items to store intermediate results of a calculation. It runs on a background thread, so it does not need to be the most efficient implementation. However, I want to prevent my background thread introducing a stop-the-world garbage collection. In my program (rules and an AI for a mahjong game), the collection size is at most 14 (tiles in hand). I figured it would be the most simple to just keep it stack based. MY first attempt looks like: ``` struct NoGcArray(size_t maxSize, T) { private T[maxSize] _buffer; private size_t _length; size_t length() pure const @nogc nothrow { return _length; } void opOpAssign(string op)(T element) pure @nogc nothrow in(_length < maxSize, "Cannot append if the buffer is fully filled.") { static if(op == "~") { _buffer[_length] = element; ++_length; } else { static assert(false, "Only concatenation supported"); } } T opIndex(size_t index) in(index < _length, "Cannot access index greater than length") { return _buffer[index]; } auto range() pure const @nogc nothrow { return Range(this); } alias range this; static struct Range { this(NoGcArray src) { _src = src; } private NoGcArray _src; private size_t _index; T front() pure @nogc nothrow { return _src[_index]; } void popFront() pure @nogc nothrow { _index++; } bool empty() pure @nogc nothrow { return _src._length <= _index; } } } ``` However, ``` unittest { import std.algorithm : sum, map; import fluent.asserts; NoGcArray!(4, int) array; array ~= 420; array ~= 42; array.map!(x => x*2).sum.should.equal(924); } ``` fails. The test will run in an infinite loop. After some digging, I realise that the `alias this` is foiling with my plan rather than helping it. Is there a recommended way to achieve - std.algorithm functions should Just Work (tm) - appending as if it were a dynamic array - preferably index-based access and .length should also work. Is there a dub package that achieves this? Or are there any tips to roll my own implementation?
Re: Dub fetch
On Saturday, 11 May 2019 at 14:27:50 UTC, Russel Winder wrote: Hi, Is there a way of asking which version of package XXX "dub fetch XXX" will actually fetch. I would like to avoid checking the contents of ~/.dub/packages before and after. Use the `--annotate` option: $ dub fetch dlangide --annotate Fetching dlangide 0.8.17... Please note that you need to use `dub run ` or add it to dependencies of your package to actually use/run it. dub does not do actual installation of packages outside of its own ecosystem.
Re: Pass template parameter into q{} string
On Monday, 1 April 2019 at 17:32:29 UTC, Andrey wrote: Hello, enum Key : string { First = "qwerty", Last = "zaqy" } void main() { enum decl(alias values1) = q{ static foreach(value; values1) mixin("bool " ~ value ~ " = false;"); }; enum qqq = [Key.First, Key.Last]; mixin(decl!qqq); } I don't understand how to pass template parameter "values1" into q{} string to get this output: static foreach(value; [Key.First, Key.Last]) mixin("bool " ~ value ~ " = false;"); or static foreach(value; qqq) mixin("bool " ~ value ~ " = false;"); A token string (q{}) is still a string literal[1] (but has autocomplete on individual tokens in many IDEs). It does not substitute the text for the values. As such, you'd need to format the string like usual. The following code worked: enum Key : string { First = "qwerty", Last = "zaqy" } void main() { import std.format; enum decl(alias values1) = q{ static foreach(value; %s) mixin("bool " ~ value ~ " = false;"); }.format(values1.stringof); enum qqq = [Key.First, Key.Last]; mixin(decl!qqq); import std.stdio; writeln(qwerty); } Here we use the format function from the standard library. We have a format token (%s) in the original string, and replace it with `values1.stringof`. `.stringof` in this case means the original text used in the call site passed to argument values1 ("qqq"). (When we don't use `.stringof`, "First" and "Last" are not defined, as the compiler thinks qqq is an array of Keys instead of strings.) You could also use a string interpolation library (e.g. [2]) from Dub. [1] https://dlang.org/spec/lex.html#token_strings [2] http://code.dlang.org/packages/stri
Re: Is there a way to replace Exception with as a macro in C?
On Tuesday, 19 February 2019 at 05:50:04 UTC, yisooan wrote: I wonder there is the way as I said in the title. For instance, in C, #define indexInvalidException Exception("The index is invalid") /* Do something with the macro here */ if (false) indexInvalidException; This is allowed. But I want to do the exact same thing in D. I have already tried some expressions with alias? but it doesn't work. alias indexInvalidException = Exception("The index is invalid"); /* Use the alias in somewhere */ if (false) throw new indexInvalidException; Would you help me, please? Alias is just a nickname for a symbol (i.e. alias string = immutable(char)[];) and lets you refer to that symbol with the nickname. You can't supply runtime parameters (like constructor parameters), but you can give compile-time template parameters (as the result of applying those parameters is a symbol rather than a value). Macros on the other hand, do a textual replacement, i.e. they alter the source code that goes into the compiler. Depending on how brief you want to make your code, you can either use classic inheritance class IndexInvalidException : Exception { this() { super("The index is invalid") } } or, closest as you can get to macros: enum throwNewIndexInvalidException = `throw new Exception("The index is invalid");`; void main() { mixin(throwNewIndexInvalidException); } String mixins transform a string into an expression, and paste the expression wherever it is mixed in. It gets precompiled rather than substituted in the source code. This means it's best to have the whole line into a string, instead of individual parts (you can't have a mixin with just `Exception("The index is invalid")` for example).
Re: Best practices of using const
On Wednesday, 13 February 2019 at 16:40:18 UTC, H. S. Teoh wrote: On Wed, Feb 13, 2019 at 11:32:46AM +, envoid via Digitalmars-d-learn wrote: Unfortunately, that guarantee also excludes a lot of otherwise useful idioms, like objects that cache data -- a const object cannot cache data because that means it's being mutated, or lazily-initialized objects -- because once the ctor has run, the object can no longer be mutated. Most notably, D's powerful range idiom is pretty much unusable with const because iteration over a range requires mutating the range (though having const *elements* in a range is fine). This doesn't seem as bad at first glance, but it wreaks havoc on generic code, another thing that D is purportedly good at. It's very hard (and often impossible) to write generic code that works with both const and mutable objects. So ironically, the iron-clad semantics of D's const system turns out to be also its own downfall. T I agree that const by nature unfortunately kills lazy initialization. However, I don't really understand why const is a problem with ranges. Const elements are not a problem. Iterating over a range consumes it (if I understand correctly). It does not make sense to be able to consume a const object, so from my point of view it's perfectly logical to disallow iterating const ranges. If I'm missing something, please correct me. I use const quite thoroughly in my project (a mahjong board game) and in fact I am writing a blog post explaining how it helped me understand what was happening in my code base. It enforces encapsulated mutations. In classic OOP languages, mutable objects propagate through the entire system, unless you actively create an immutable copy of it (which is a lot of work for little gain). If someone modifies your object on a place you don't expect (e.g. creating and persisting data when rendering a read-only view), it becomes hard to impossible to reason about the problem and debug it. Refactoring in const was a lot of work, but I think it made my code better in the end. I didn't run into any problems when using it, except when I tried to modify an object where I should not have (e.g. sorting a hand when rendering the view). I was able to untangle the spaghetti because the compiler poked me about it. As I didn't run into any problems and it helped clean up my code base, I would recommend trying it.
Re: Error: no property "someFont" for type int
This is not D. It should be giving you a compiler error. How are you compiling? Or did you type 'using' in the post by mistake? Anyway, what you want is: import style; I indeed made a typo while typing the post (and also on various occasions while writing the program, but compiler errors fixed that). That's what you get for using C# at work. In style.d: module style; (...) public static class Style { 'static class' has no meaning in module scope, only for inner classes. It's not the cause of your problem though. Thanks for the heads up :) I figured it was about time to dust my D-skills. The error is likley because of a symbol conflict. Assuming that Text is from the module dsfml.text.graphics, it has an enum type named Style. There's an unfortunate issue in D that allows both of the following to compile: auto e1 = Text.Style.Regular; _text.Style.Regular; The latter should not be allowed, IMO, but it is what it is. So in your case, accessing your Style class in the scope of with(_text) is causing the compiler to find _text.Style. The solution is to use the FQN (Fully Qualified Name) on your Style inside the with, i.e. style.Style, or to drop the with altogether. Dropping the with worked like a charm, thanks a lot for the fast reply!
Error: no property "someFont" for type int
I'm trying to build a small manga reader application (because why search the internet if you can build it yourself), using DSFML. However, I'm getting a weird compilation error that I can't decrypt. In directory.d: using style; (...) _text = new Text; with(_text) { setFont(Style.DirectoryFont); In style.d: module style; (...) public static class Style { private static Font _font; public static Font DirectoryFont() { if(!(_font is null)) return _font; _font = new Font; Load(_font); // Helper function that loads the font into _font return _font; } } I'm getting the error message that the compiler can't find source/directory.d(...) : Error: no property 'DirectoryFont' for type 'int'. When I change the line to actually contain the (iirc optional) brackets, the type changes to 'Style'. Am I missing something with regards to static classes and members in D? Thanks in advance.