Re: Range checked assignment
On Tuesday, 8 September 2020 at 14:18:14 UTC, Cecil Ward wrote: What I would like to do is (in pseudo-code) : declare_var my_var : int range 0..7; // i.e. 0 <= val <= 7; my_var = 6; // ok my_var = 8; // bang ! static assert fail or assert fail at runtime my_var = 6; my_var += 2; // bang ! value 8 is > 7 So every assignment is range-checked at either compile-time if at all possible or else at runtime. This includes things like += and initialisers of course, not just straight assignment. I assumed I would have to create a struct type definition and handle various operators. How many will I have to handle? I would of course make it a template so I can reuse this otherwise horribly repetitive code. If you want to define an integral-like type which is more-or-less interchangeable with the native integral types, you'll need to provide the following overloads and members: * An enum member named `min` which provides an instance of the lowest possible value of the type. * An enum member named `max` which provides an instance of the highest possible value of the type. * A constructor. * `opAssign`. * `opOpAssign` for the operators: `-`; `+`; `/`; `*`; `%`; `^^`; `&`; `|`; `^`; `<<`; `>>`; `>>>`. * `opEquals`, which should be a const member function. * `opCmp`, which should be a const member function. * `opUnary` for the operators: `-`; `+`; `~`, which should be a const member function. * `opUnary` for the operators: `--`; `++`, which should be a mutable member function. * `opBinary` for the operators: `-`; `+`; `/`; `*`; `%`; `^^`; `&`; `|`; `^`; `<<`; `>>`; `>>>`, which should be a const member function. * `opCast`, which should be a const member function. Although in your specific case, implementing the bitwise operators may not make sense. Ideally, all the operator overloads, and the constructor, should be able to take any native integral type, and any instances of your type, as arguments. Here's a skeleton implementation of an integral-like type: import std.algorithm; import std.traits; template isConstrainedInt (Instance) { enum bool isConstrainedInt = __traits( isSame, TemplateOf!Instance, ConstrainedInt ); } template ConstrainedInt (long lower, long upper) if (lower <= upper) { struct ConstrainedInt { enum typeof(this) min = typeof(this)(lower); enum typeof(this) max = typeof(this)(upper); this (Integer) (const Integer value) if (isIntegral!Integer || isConstrainedInt!Integer) {} void opAssign (Integer) (const Integer value) if (isIntegral!Integer || isConstrainedInt!Integer) {} void opOpAssign (string operator, Integer) (const Integer value) if ( canFind( operator, "-", "+", "/", "*", "%", "^^", "&", "|", "^", "<<", ">>", ">>>" ) && (isIntegral!Integer || isConstrainedInt!Integer) ) {} bool opEquals (Integer) (const Integer value) const if (isIntegral!Integer || isConstrainedInt!Integer) {} int opCmp (Integer) (const Integer value) const if (isIntegral!Integer || isConstrainedInt!Integer) {} typeof(this) opUnary (string operator) () const if ( canFind( operator, "-", "+", "~" ) ) {} typeof(this) opUnary (string operator) () if (canFind(operator, "--", "++")) {} typeof(this) opBinary (string operator, Integer) (const Integer value) const if ( canFind( operator, "-", "+", "/", "*", "%", "^^", "&", "|", "^", "<<", ">>", ">>>" ) && (isIntegral!Integer || isConstrainedInt!Integer) )
Re: How to get the element type of an array?
On Tuesday, 25 August 2020 at 03:41:06 UTC, Jon Degenhardt wrote: What's the best way to get the element type of an array at compile time? Something like std.range.ElementType except that works on any array type. There is std.traits.ForeachType, but it wasn't clear if that was the right thing. --Jon One way (maybe not the best way) is to use the type of the array's ptr property when dereferenced, e.g. import std.traits : isArray; template ArrayElementOf (Array) if (isArray!Array) { alias ArrayElementOf = typeof(*Array.init.ptr); }
Re: How to use GET_X_LPARAM in D ?
On Thursday, 21 May 2020 at 18:42:47 UTC, Vinod K Chandran wrote: Hi all, I need to use the macro GET_X_LPARAM. But compiler says that "undefined identifier GET_X_LPARAM". I cant find any modules with GET_X_LPARAM defined. Do i miss something ? GET_X_LPARAM isn't defined in Phobos's Windows bindings, so you'll need to provide the definition yourself. GET_X_LPARAM is defined as a macro in the windowsx.h header of the Windows SDK, as: #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) Which can trivially be translated to D as a function, like so: int GET_X_LPARAM (T) (T lp) { import core.sys.windows.windef : LOWORD; return cast(int) cast(short) LOWORD(lp); } Hope this helps :)
Re: countUntil with negated pre-defined predicate?
On Sunday, 3 May 2020 at 12:19:30 UTC, Robert M. Münch wrote: I'm doing some cursor-movement in a text-field. So, need to find out where the cursor should be positioned. The Unicode Consortium has some documentation related to segmenting text that you may find useful (notably, section 3): https://unicode.org/reports/tr29 size_t drawableCharacterCount (CodePoints) (auto ref CodePoints codePoints) What does this line do? I'm unsure as to which part is unclear, but an `auto ref` parameter[1] in a function template is essentially a parameter that receives the argument by reference if the templated type is a value-type, whereas if the templated type is a reference-type, it receives the argument by value. An explanation as code: struct SomeValueType {} class SomeReferenceType {} void theFunction (Type) (auto ref Type thing) {} /+ theFunction!SomeValueType expands to: +/ void theFunction (ref SomeValueType thing) {} /+ theFunction!SomeReferenceType expands to: +/ void theFunction (SomeReferenceType thing) {} One advantage of auto ref parameters is that they accept literals as arguments, unlike a regular `ref` parameter. [1]: https://dlang.org/spec/template.html#auto-ref-parameters
Re: countUntil with negated pre-defined predicate?
On Saturday, 2 May 2020 at 18:23:30 UTC, Robert M. Münch wrote: Or is there an even better way to search for all "drawable unicode characters"? This depends on what you classify as drawable, and what you consider to be a character (the joys of Unicode), and why you want to search for them anyway. One way (I haven't verified this) could be to check if any of the code-points within a grapheme are graphical[1], and not white-space (and are not any other code-point you consider non-drawable). Which could look like so: import std.algorithm; import std.range; import std.uni; size_t drawableCharacterCount (CodePoints) (auto ref CodePoints codePoints) if (isInputRange!CodePoints && is(ElementType!CodePoints : dchar)) { bool isDrawableCodePoint (dchar c) { return c.isGraphical() && !c.isWhite(); } return codePoints.byGrapheme().count!( g => g[].any!isDrawableCodePoint ); } [1]: https://www.unicode.org/versions/Unicode13.0.0/ch02.pdf#G286941 --- The source-code in this reply is available for use under the terms of Creative Commons CC0 1.0 Universal.
Re: countUntil with negated pre-defined predicate?
On Saturday, 2 May 2020 at 18:23:30 UTC, Robert M. Münch wrote: This works: countUntil!(std.uni.isWhite)("hello world")) How can I switch this to (not working); countUntil!(!std.uni.isWhite)("hello world")) without having to write my own predicate? Or is there an even better way to search for all "drawable unicode characters"? std.functional.not can do this: https://dlang.org/phobos/std_functional.html#not
Is the behaviour of shift expressions with negative left operands defined / portable?
The spec doesn't seem to explicitly mention what happens when the left operand of a shift expression is signed and negative. [1] But I know that D follows C's semantics for this sort of stuff, and the C standard specifies that the result of a negative left operand is undefined for `<<`, and implementation-defined for `>>`. [2][3] Is D's behaviour the same as C in this regard? [1]: https://dlang.org/spec/expression.html#shift_expressions [2]: https://port70.net/~nsz/c/c89/c89-draft.html#3.3.7 [3]: https://port70.net/~nsz/c/c11/n1570.html#6.5.7
Re: Using the functions "map" and "any" on tuples in compile time.
On Sunday, 12 April 2020 at 11:17:39 UTC, realhet wrote: Hello, anyone can help me make this better? The functionality I want to achieve is: While serializing the fields of a struct, I want it to check the @STORED UDA on every field. If there is no fields are marked with @STORED, that means every field must be serialized. Otherwise only the marked one. I had problems using map and any, so I come up with this lame foreach version: It works, but I think it does it in runtime. bool anySTORED = false; static foreach(fieldName; FieldNameTuple!T) mixin("anySTORED |= hasUDA!(data.*, STORED);".replace("*", fieldName)); static foreach(fieldName; FieldNameTuple!T){{ mixin("const thisSTORED = hasUDA!(data.*, STORED);".replace("*", fieldName)); if(thisSTORED || !anySTORED) mixin("streamAppend_json!(dense, fieldName)(st, data.*, nextIndent);".replace("*", fieldName)); }} Thanks in advance! (ps: I just love string mixins, I know :D) Using a compile-time tuple as a range is easy, turn it into an array via an array literal (surround it in square bracket), e.g. struct Foo { int a; int b; } pragma(msg, [FieldNameTuple!Foo].map!(f => f ~ "_").array()); However, if you were to try that with `any` for `hasUDA`, wherein the arguments for `any`'s predicate are used for `hasUDA`'s template parameters, you'll find that it won't compile. That's because `any`'s predicate is a runtime function, executed at compile-time via CTFE, so the argument technically isn't known at compile-time for the `hasUDA` template, e.g. struct Foo { int a; int b; } enum STORED; enum bool anyStored = [FieldNameTuple!Foo].any!( f => hasUDA!(__traits(getMember, Foo, f), STORED) ); The solution to that is to define a template predicate, and use std.meta.anySatisfy, instead of `any`. Which would accomplish what you want to do, with something like so: string serialiseFields (T) (auto ref T instance) { enum bool hasStored (string fieldName) = hasUDA!(__traits(getMember, T, fieldName), STORED); enum fields = FieldNameTuple!T; static if (anySatisfy!(hasStored, fields)) { enum fieldsToSerialise = Filter!(hasStored, fields); } else { enum fieldsToSerialise = fields; } string serialise (string name, T) (auto ref T value) { return format!(name ~ " = %s")(value); } string serialised; static foreach (field; fieldsToSerialise) { serialised ~= serialise!field(__traits(getMember, instance, field)) ~ "\n"; } return serialised; } --- This source code in this reply is licensed under the terms of Creative Commons CC0 1.0.