Re: Mixin helper help
On Friday, 13 January 2023 at 16:54:34 UTC, Ali Çehreli wrote: On 1/13/23 00:48, bauss wrote: > 1. Change your mixin template to something like this: There was a technique as a workaround for this template mixin limitation but I can't find it right now. > 2. Change the place where you instantiate to this: I think the workaround I am trying to remember would not require any change for the users. Ok, it was something like this: mixin template myStatement() { auto doIt() { import std.stdio : writeln; writeln("hi"); return 0; } auto ignoreThis = doIt(); } void main() { mixin myStatement!(); mixin myStatement!(); } Ali That's a good one!
Re: Failed to archive JPEG (ArchiveMember): Invalid UTF-8 sequence (at index 1)
On Saturday, 14 January 2023 at 01:13:33 UTC, Adam D Ruppe wrote: On Saturday, 14 January 2023 at 01:08:25 UTC, Ki Rill wrote: a JPEG image. member.expandedData(file.readText().dup().representation()); A jpeg image is not a text file. Read it with `std.file.read()` instead of `readText`. Then you can get rid of those useless dup.representation calls too. Thank you for such a quick reply! It solved my issue!
Re: Failed to archive JPEG (ArchiveMember): Invalid UTF-8 sequence (at index 1)
On Saturday, 14 January 2023 at 01:08:25 UTC, Ki Rill wrote: a JPEG image. member.expandedData(file.readText().dup().representation()); A jpeg image is not a text file. Read it with `std.file.read()` instead of `readText`. Then you can get rid of those useless dup.representation calls too.
Failed to archive JPEG (ArchiveMember): Invalid UTF-8 sequence (at index 1)
Please, help me solve the annoying error above. I've been refactoring and rewriting code for my archive utility called [zippo](https://github.com/rillki/zippo) and I face this error when it tries to archive a JPEG image. I tracked it down to the following function that helps me add a new member to `ZipArchive`. ```D void zipAddArchiveMember(ref ZipArchive zip, in string file) { import std.conv: to; import std.file: readText; import std.string: representation; ArchiveMember member = new ArchiveMember(); member.name = file; writefln("%s", file); member.expandedData(file.readText().dup().representation()); member.compressionMethod = CompressionMethod.deflate; zip.addMember(member); } ``` Am I missing something?
Re: Creating a pointer/slice to a specific-size buffer? (Handing out a page/frame from a memory manager)
On Friday, 13 January 2023 at 19:16:17 UTC, H. S. Teoh wrote: On Fri, Jan 13, 2023 at 08:31:17AM -0800, Ali Çehreli via Digitalmars-d-learn wrote: On 1/13/23 07:07, Gavin Ray wrote: > This is "valid" D I hope? Yes because static arrays are just elements side-by-side in memory. You can cast any piece of memory to a static array provided the length and alignment are correct. [...] Or to be more precise, cast the memory to a *pointer* to a static array of the right size. Static arrays are by-value types; passing around the raw array will cause the array to be copied every time, which is probably not what is intended. T Thanks Teoh and Ali, I wound up passing a pointer to a static array. If anyone is curious, here's the full WIP implementation -- it's for a toy database (Postgres-like) I'm writing for a hobby and learning project: https://ldc.godbolt.org/z/Kvh7dv96c
Re: Coding Challenges - Dlang or Generic
On Friday, 13 January 2023 at 18:59:01 UTC, matheus wrote: Unfortunately it's not working for me Yeah, it was an old development version. I also implemented another version the same day: * [Nested Class](https://forum.dlang.org/thread/vkjhkftvyprsivozy...@forum.dlang.org) * [Only One Struct](https://forum.dlang.org/post/thxvuddjimgswalzo...@forum.dlang.org) SDB@79 Sory...
Re: Unittests on a module
On Friday, 13 January 2023 at 19:07:46 UTC, DLearner wrote: Is this intended? It is by design, though opinions differ on whether it's a good design. It's not a problem to add temporary ``` void main() { } ``` to the bottom of the module, You can add the `-main` flag to make dmd automatically add such an empty main function when there isn't a `main` already.
Re: Creating a pointer/slice to a specific-size buffer? (Handing out a page/frame from a memory manager)
On Fri, Jan 13, 2023 at 08:31:17AM -0800, Ali Çehreli via Digitalmars-d-learn wrote: > On 1/13/23 07:07, Gavin Ray wrote: > > > This is "valid" D I hope? > > Yes because static arrays are just elements side-by-side in memory. > You can cast any piece of memory to a static array provided the length > and alignment are correct. [...] Or to be more precise, cast the memory to a *pointer* to a static array of the right size. Static arrays are by-value types; passing around the raw array will cause the array to be copied every time, which is probably not what is intended. T -- "You are a very disagreeable person." "NO."
Unittests on a module
If unittest run without a main() being present, crashes on link error: ``` lld-link: error: subsystem must be defined Error: linker exited with status 1 ``` Is this intended? It's not a problem to add temporary ``` void main() { } ``` to the bottom of the module, but seems wrong as not then testing _exactly_ what is to be imported elsewhere.
Re: Coding Challenges - Dlang or Generic
On Thursday, 12 January 2023 at 19:06:49 UTC, Salih Dincer wrote: ... Now, I wrote a nested class using range and copying from Matheus' code. Of course not as comprehensive as [your dcal](https://github.com/quickfur/dcal/blob/master/dcal.d). I like this one and even thought of a new challenge! ... Hi Salih, Unfortunately it's not working for me: .d(79): Error: found `End of File` when expecting `}` following compound statement So I think it's missing a "}" in main, and after I added that, it gives: .d(46): Error: undefined identifier `replicated`, did you mean template `replicate(S)(S s, size_t n) if (isDynamicArray!S)`? Matheus.
Re: Mixin helper help
On 1/13/23 00:48, bauss wrote: > 1. Change your mixin template to something like this: There was a technique as a workaround for this template mixin limitation but I can't find it right now. > 2. Change the place where you instantiate to this: I think the workaround I am trying to remember would not require any change for the users. Ok, it was something like this: mixin template myStatement() { auto doIt() { import std.stdio : writeln; writeln("hi"); return 0; } auto ignoreThis = doIt(); } void main() { mixin myStatement!(); mixin myStatement!(); } Ali
Re: Creating a pointer/slice to a specific-size buffer? (Handing out a page/frame from a memory manager)
On 1/13/23 07:22, Gavin Ray wrote: > Maybe it would be better to wrap the slice in a new class with an > invariant? Possibly but please check before using because I think 'invariant' requires presence of member functions: https://dlang.org/spec/struct.html#Invariant > Because what I want to do is: > > 1. Ensure that the length of the underlying referenced/pointed-to data > is `PAGE_SIZE` My first thought was why not use a slice anyway? Worth noting that static arrays are value types. Also, they all have different types from each other and have the potential to cause template bloat. > class BufferPool Off-topic, most D programmers use struct unless they need class. > Frame[BUF_POOL_NUM_PAGES] frames; Makes sense to me. Ali
Re: Creating a pointer/slice to a specific-size buffer? (Handing out a page/frame from a memory manager)
On 1/13/23 07:07, Gavin Ray wrote: > This is "valid" D I hope? Yes because static arrays are just elements side-by-side in memory. You can cast any piece of memory to a static array provided the length and alignment are correct. However, such a cast is not allowed in @safe code. Ali
Re: Why not allow elementwise operations on tuples?
On Fri, Jan 13, 2023 at 02:22:34PM +, Sergei Nosov via Digitalmars-d-learn wrote: > Hey, everyone! > > I was wondering if there's a strong reason behind not implementing > elementwise operations on tuples? > > Say, I've decided to store 2d points in a `Tuple!(int, int)`. It would > be convenient to just write `a + b` to yield another `Tuple!(int, > int)`. I've written a Vec type that implements precisely this, using tuples behind the scenes as the implementation, and operator overloading to allow nice syntax for vector arithmetic. ---snip /** * Represents an n-dimensional vector of values. */ struct Vec(T, size_t n) { T[n] impl; alias impl this; /** * Per-element unary operations. */ Vec opUnary(string op)() if (is(typeof((T t) => mixin(op ~ "t" { Vec result; foreach (i, ref x; result.impl) x = mixin(op ~ "this[i]"); return result; } /** * Per-element binary operations. */ Vec opBinary(string op, U)(Vec!(U,n) v) if (is(typeof(mixin("T.init" ~ op ~ "U.init" { Vec result; foreach (i, ref x; result.impl) x = mixin("this[i]" ~ op ~ "v[i]"); return result; } /// ditto Vec opBinary(string op, U)(U y) if (isScalar!U && is(typeof(mixin("T.init" ~ op ~ "U.init" { Vec result; foreach (i, ref x; result.impl) x = mixin("this[i]" ~ op ~ "y"); return result; } /// ditto Vec opBinaryRight(string op, U)(U y) if (isScalar!U && is(typeof(mixin("U.init" ~ op ~ "T.init" { Vec result; foreach (i, ref x; result.impl) x = mixin("y" ~ op ~ "this[i]"); return result; } /** * Per-element assignment operators. */ void opOpAssign(string op, U)(Vec!(U,n) v) if (is(typeof({ T t; mixin("t " ~ op ~ "= U.init;"); }))) { foreach (i, ref x; impl) mixin("x " ~ op ~ "= v[i];"); } void toString(W)(W sink) const if (isOutputRange!(W, char)) { import std.format : formattedWrite; formattedWrite(sink, "(%-(%s,%))", impl[]); } } /** * Convenience function for creating vectors. * Returns: Vec!(U,n) instance where n = args.length, and U is the common type * of the elements given in args. A compile-time error results if the arguments * have no common type. */ auto vec(T...)(T args) { static if (args.length == 1 && is(T[0] == U[n], U, size_t n)) return Vec!(U, n)(args); else static if (is(typeof([args]) : U[], U)) return Vec!(U, args.length)([ args ]); else static assert(false, "No common type for " ~ T.stringof); } /// unittest { // Basic vector construction auto v1 = vec(1,2,3); static assert(is(typeof(v1) == Vec!(int,3))); assert(v1[0] == 1 && v1[1] == 2 && v1[2] == 3); // Vector comparison auto v2 = vec(1,2,3); assert(v1 == v2); // Unary operations assert(-v1 == vec(-1, -2, -3)); assert(++v2 == vec(2,3,4)); assert(v2 == vec(2,3,4)); assert(v2-- == vec(2,3,4)); assert(v2 == vec(1,2,3)); // Binary vector operations auto v3 = vec(2,3,1); assert(v1 + v3 == vec(3,5,4)); auto v4 = vec(1.1, 2.2, 3.3); static assert(is(typeof(v4) == Vec!(double,3))); assert(v4 + v1 == vec(2.1, 4.2, 6.3)); // Binary operations with scalars assert(vec(1,2,3)*2 == vec(2,4,6)); assert(vec(4,2,6)/2 == vec(2,1,3)); assert(3*vec(1,2,3) == vec(3,6,9)); // Non-numeric vectors auto sv1 = vec("a", "b"); static assert(is(typeof(sv1) == Vec!(string,2))); assert(sv1 ~ vec("c", "d") == vec("ac", "bd")); assert(sv1 ~ "post" == vec("apost", "bpost")); assert("pre" ~ sv1 == vec("prea", "preb")); } unittest { // Test opOpAssign. auto v = vec(1,2,3); auto w = vec(4,5,6); v += w; assert(v == vec(5,7,9)); } unittest { int[4] z = [ 1, 2, 3, 4 ]; auto v = vec(z); static assert(is(typeof(v) == Vec!(int,4))); assert(v == vec(1, 2, 3, 4)); } unittest { import std.format : format; auto v = vec(1,2,3,4); assert(format("%s", v) == "(1,2,3,4)"); } ---snip T -- Never ascribe to malice that which is adequately explained by incompetence. -- Napoleon Bonaparte
Re: Creating a pointer/slice to a specific-size buffer? (Handing out a page/frame from a memory manager)
Maybe it would be better to wrap the slice in a new class with an invariant? Because what I want to do is: 1. Ensure that the length of the underlying referenced/pointed-to data is `PAGE_SIZE` 2. Benefit from the features of D that I can The bounds-checking of slices saves a lot of headaches during development. So maybe doing something like this might be better? ```d struct Frame { ubyte[] data; invariant { assert(data.length == PAGE_SIZE); } } class BufferPool { align(PAGE_SIZE) ubyte[PAGE_SIZE * BUF_POOL_NUM_PAGES] data; Frame[BUF_POOL_NUM_PAGES] frames; this() { // mmap foreach (i; 0 .. BUF_POOL_NUM_PAGES) { frame_idx_t frame_idx = cast(frame_idx_t) i; frames[frame_idx].data = data[frame_idx * PAGE_SIZE .. (frame_idx + 1) * PAGE_SIZE]; } } } ```
Re: Creating a pointer/slice to a specific-size buffer? (Handing out a page/frame from a memory manager)
On Friday, 13 January 2023 at 14:57:40 UTC, Ali Çehreli wrote: On 1/13/23 06:49, Gavin Ray wrote: > I am curious if you can return something like `ubyte[PAGE_SIZE]*` or > `ref ubyte[PAGE_SIZE]`? A simple cast seems to work: enum PAGE_SIZE = 4096; enum BUF_POOL_NUM_PAGES = 1024; alias frame_idx_t = size_t; ubyte[10_000] data; ubyte[PAGE_SIZE]* get_page(frame_idx_t frame_idx) { auto ptr = data.ptr + frame_idx * PAGE_SIZE; return cast(ubyte[PAGE_SIZE]*)ptr; } void main() { } Ali Ah, much thanks Ali! This is "valid" D I hope? I searched Github for `"ubyte[4096]*"` and I found two uses of it, in the `xtrix` repo which seems to be an Operating System written in D: ![screenshot-of-ubyte-sized-ptr-on-github](https://i.imgur.com/WaAklbq.png)
Re: Creating a pointer/slice to a specific-size buffer? (Handing out a page/frame from a memory manager)
On 1/13/23 06:49, Gavin Ray wrote: > I am curious if you can return something like `ubyte[PAGE_SIZE]*` or > `ref ubyte[PAGE_SIZE]`? A simple cast seems to work: enum PAGE_SIZE = 4096; enum BUF_POOL_NUM_PAGES = 1024; alias frame_idx_t = size_t; ubyte[10_000] data; ubyte[PAGE_SIZE]* get_page(frame_idx_t frame_idx) { auto ptr = data.ptr + frame_idx * PAGE_SIZE; return cast(ubyte[PAGE_SIZE]*)ptr; } void main() { } Ali
Re: Creating a pointer/slice to a specific-size buffer? (Handing out a page/frame from a memory manager)
I probably should have mentioned, the equivalent in C++ is the below: ```cpp #include #include #include static constexpr size_t PAGE_SIZE = 4096; static constexpr size_t BUF_POOL_NUM_PAGES = 1024; class BufferPool { private: alignas(PAGE_SIZE) std::byte data[BUF_POOL_NUM_PAGES * PAGE_SIZE]; public: BufferPool() { mmap(data, BUF_POOL_NUM_PAGES * PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); } // Return a fat-pointer of PAGE_SIZE bytes over the page, containing { T* ptr, len } std::span get_page(size_t page_num) { return std::span(data + page_num * PAGE_SIZE, PAGE_SIZE); } }; ```
Creating a pointer/slice to a specific-size buffer? (Handing out a page/frame from a memory manager)
Suppose that you have a memory manager, or arena-like class, which contains a buffer used to store memory. And you want to hand out chunks of this memory to other parts of your program. These chunks should all be `PAGE_SIZE`. You might have something like: ```d enum PAGE_SIZE = 4096; enum BUF_POOL_NUM_PAGES = 1024; class BufferPool { align(PAGE_SIZE) ubyte[PAGE_SIZE * BUF_POOL_NUM_PAGES] data; this() { mmap(&data, data.sizeof, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); } } ``` Now there should be a function, like `get_page()`, that returns a `PAGE_SIZE` pointer of `ubyte`. But I can only figure out how to return a `ubyte[]`: ```d ubyte[] get_page(frame_idx_t frame_idx) { return data[frame_idx * PAGE_SIZE .. (frame_idx + 1) * PAGE_SIZE]; } ``` I am curious if you can return something like `ubyte[PAGE_SIZE]*` or `ref ubyte[PAGE_SIZE]`? Thank you =)
Re: Mixin helper help
On Thursday, 12 January 2023 at 08:03:34 UTC, John Chapman wrote: Why does the commented code work but the mixin not? Thanks for any pointers. Why not directly use the mixin template for opDispatch()? ```d mixin template helper() { void opDispatch(string name)() { import std.stdio; writeln(12); } } struct Foo { mixin helper; // ... } void main() { Foo.init.opDispatch!"bar"(); } ``` SDB@79
Why not allow elementwise operations on tuples?
Hey, everyone! I was wondering if there's a strong reason behind not implementing elementwise operations on tuples? Say, I've decided to store 2d points in a `Tuple!(int, int)`. It would be convenient to just write `a + b` to yield another `Tuple!(int, int)`. I can resort to using `int []` arrays and write elementwise operations as `c[] = a[] + b[]` which is almost fine - but it uses dynamic allocation and forces the user to create an explicit destination variable. It seems a bit awkward given that it's fairly straightforward to write smth as ``` T opBinary(string op, T)(T lhs, T rhs) if (isTuple!T) { T result; static foreach (i; 0 .. T.Types.length) { mixin("result.field[i] = lhs.field[i]"~op~"rhs.field[i];"); } return result; } ``` You only need to turn it into a member function to make it work. You can even make it more general and allow such operations for different, but compatible tuple types (there's a function `areCompatibleTuples` to check for such compatibility). Yet, there's only a specialization for tuple concatenation of `opBinary` (and an implementation of `opCmp` and `opAssign`). So, to repeat the question - is this a deliberate decision to not implement the default elementwise operation?
Re: Should importC fail on invalid C code?
On Friday, 13 January 2023 at 12:50:44 UTC, kdevel wrote: Should importC fail on invalid C code? In general, no. The purpose is to build / interface with existing C code, not to develop new C code with it. ImportC also has its own extensions by borrowing D features such as __import, CTFE, and forward references. A strict C compiler would reject those.
Should importC fail on invalid C code?
After reading Walter's remark "ImportC sees those macro definitions and transforms them into manifest constant declarations" in Issue 23622 - ImportC #defines conflict with declarations I wondered how it was implemented: `myccode.c` ``` int getx () { return X; #define X 1 } ``` `imc.d` ``` unittest { import myccode; assert (false, "Should img.c really compile?"); } ``` ``` dmd -O -checkaction=context -unittest -main myccode.c -run imc.d imc.d(3): [unittest] Should img.c really compile? 1/1 modules FAILED unittests ```
Re: Why does the importC example not compile?
On Friday, 13 January 2023 at 12:33:28 UTC, kdevel wrote: What must be added or changed in order to test every example which is intended to produce an executable? Support for separate compilation / ImportC would need to be added to dspec_tester: https://github.com/dlang/dlang.org/blob/master/tools/dspec_tester.d
Re: Why does the importC example not compile?
On Friday, 13 January 2023 at 12:20:23 UTC, Dennis wrote: I don't think there's a way to test examples of separate compilation in the spec currently. What must be added or changed in order to test every example which is intended to produce an executable?
Re: Why does the importC example not compile?
Thanks for reporting this. PR: https://github.com/dlang/dlang.org/pull/3489 On Friday, 13 January 2023 at 11:10:23 UTC, kdevel wrote: I would have expected that each and every piece of code in the documentation is automatically compiled with any new compiler release. Individual D snippets can be tested when given the right DDoc macro, such as `SPEC_RUNNABLE_EXAMPLE_RUN` or `SPEC_RUNNABLE_EXAMPLE_FAIL`. (Thanks to Nick Treleaven for adding it to many examples that didn't have it before!) I don't think there's a way to test examples of separate compilation in the spec currently.
Re: Why does the importC example not compile?
try to rename function to distinguish from source module
Why does the importC example not compile?
https://dlang.org/spec/importc.html `square.c` ``` int square(int i) { return i * i; } ``` `demo.d` ``` import std.stdio; import square; void main() { int i = 7; writefln("The square of %s is %s", i, square(i)); } ``` ``` $ dmd --version DMD64 D Compiler v2.101.1 Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved written by Walter Bright $ dmd demo.d square.c demo.d(6): Error: function expected before `()`, not `module square` of type `void` ``` I would have expected that each and every piece of code in the documentation is automatically compiled with any new compiler release.
Re: Mixin helper help
On Thursday, 12 January 2023 at 08:03:34 UTC, John Chapman wrote: I'm obviously doing something wrong, but don't quite understand. ```d mixin template helper() { mixin("writeln(12);"); } struct Foo { void opDispatch(string name)() { import std.stdio; mixin helper!(); //mixin("writeln(12);"); } } void main() { Foo.init.opDispatch!"bar"(); } ``` The compiler emits these errors about the mixin ("writeln(12);"): unexpected `(` in declarator basic type expected, not `12` found `12` when expecting `)` no identifier for declarator `writeln(_error_)` semicolon expected following function declaration declaration expected, not `)` Why does the commented code work but the mixin not? Thanks for any pointers. Mixin templates cannot have statements directly, so you need two changes for your code to work: 1. Change your mixin template to something like this: ```d mixin template helper() { // we place the statements in this function instead void helper() { mixin("writeln(12);"); } } ``` 2. Change the place where you instantiate to this: ```d struct Foo { void opDispatch(string name)() { import std.stdio; mixin helper!(); helper(); // calling the function in the mixin template } } ```