Re: Limits of implicit conversion of class arrays
On Thursday, 28 March 2024 at 01:53:52 UTC, Steven Schveighoffer wrote: ```d class Base {} class Derived : Base {} @safe pure nothrow unittest { Base b; Derived d; b = d; // pass Base[] bs; Derived[] ds; bs ~= ds; // pass bs = ds; // fail [1], should pass bs = cast(Base[])ds; // fail [2], should pass } ``` Yes, it's unsafe, as you can replace an element of `ds` with something that has no relation to `Derived`. This is a suggested change that when _applied_ will make the code unsafe yes. But the code in its current form is safe and the compiler could be extended to prove it.
LDC Internal Compiler Error (ICE) mentioning attribute 'nocapture'
Does anybody recognize the error ``` Attribute 'nocapture' does not apply to function return values %12 = call noalias nocapture align 8 ptr @_D3xxx(ptr nonnull %10, { i64, ptr } %11) #2, !dbg !7978 Attribute 'nocapture' does not apply to function return values ptr @_D3xyz1 Attribute 'nocapture' does not apply to function return values ptr @_D3xyz2 Attribute 'nocapture' does not apply to function return values ptr @_D3xyz3 Attribute 'nocapture' does not apply to function return values ptr @_D3xyz4 Attribute 'nocapture' does not apply to function return values %164 = call noalias nocapture align 8 ptr @_D3xyz5(ptr nonnull %rS72) #0, !dbg !9872 Attribute 'nocapture' does not apply to function return values %285 = call noalias nocapture align 8 ptr @_D3xyz6(ptr nonnull %284) #0, !dbg !9949 LLVM ERROR: Broken module found, compilation aborted! #0 0x5ee4d001e927 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (~/.local/ldc2-1.37.0-beta1-linux-x86_64/bin/ldc2+0x6ad4927) Error ldc2 failed with exit code -6. ``` ? It's outputted when building and running a test application with ldc with the compiler flag `-fsanitize=address`.
Re: Limits of implicit conversion of class arrays
On Saturday, 23 March 2024 at 11:04:04 UTC, Dmitry Olshansky wrote: The first and second is unsound (infamously allowed in Java). In the general case, yes. But, do you see any errors with the code ```d class Base {} class Derived : Base {} @safe pure nothrow unittest { Base b; Derived d; b = d; // pass Base[] bs; Derived[] ds; bs ~= ds; // pass bs = ds; // fail [1], should pass bs = cast(Base[])ds; // fail [2], should pass } ``` Once you cast the slice you can populate it with Derived2 objects that are not Derived, hence breaking type safety of the ds slice. Again, in the general case, yes. So what is different in this code example compared to the general case? Hint: this has overlaps with a missing compiler optimization in dmd (and many other statically typed languages) enabled by a specific kind of data flow analysis. Which one?
Limits of implicit conversion of class arrays
Is there a reason why ```d class Base {} class Derived : Base {} @safe pure nothrow unittest { Base b; Derived d; b = d; // pass Base[] bs; Derived[] ds; bs ~= ds; // pass bs = ds; // fail [1], should pass bs = cast(Base[])ds; // fail [2], should pass } ``` fails as [1]: cannot implicitly convert expression `ds` of type `Derived[]` to `Base[]` [2]: cast from `Derived[]` to `Base[]` not allowed in safe code ?
Re: Defining classes with cyclic dependencies
On Sunday, 17 March 2024 at 20:38:16 UTC, Per Nordlöw wrote: I was surprised that the compiler cannot compile ```d class A { B b; } class B { C c; } class C { D d; } class D { A a; } ``` . Shouldn't it? Ahh, nevermind. I defined these inside a unittest scope so that's why it failed. Defining them at module scope works just fine.
Defining classes with cyclic dependencies
I was surprised that the compiler cannot compile ```d class A { B b; } class B { C c; } class C { D d; } class D { A a; } ``` . Shouldn't it?
Re: DUB error I can't make sense of
On Saturday, 16 March 2024 at 07:27:17 UTC, Richard (Rikki) Andrew Cattermole wrote: Do you? ``module nxt.algorithm.comparsion;`` comparsion doesn't look much like comparison to me ;) I know. I'm crushed. Am I getting dislyctic? ;)
Re: DUB error I can't make sense of
On Saturday, 16 March 2024 at 07:23:09 UTC, Per Nordlöw wrote: Do you? Fixed it. There was some invisible character that confused the compiler.
DUB error I can't make sense of
https://github.com/nordlow/phobos-next/releases/tag/v0.6.10 fails to build as ``` ../../.dub/cache/phobos-next/0.6.10/code/phobos-next-test-library-unittest-nyN4MEoglVgAJ1A9GyL6uA/dub_test_root.d(11,15): Error: module `nxt.algorithm.comparsion` from file src/nxt/algorithm/comparison.d must be imported with 'import nxt.algorithm.comparsion;' ``` and I have no clue how to fix it. Do you?
Re: Compile-time predicate for checking whether an aggregate field is static
On Saturday, 2 March 2024 at 19:09:23 UTC, kinke wrote: On Saturday, 2 March 2024 at 15:22:03 UTC, Per Nordlöw wrote: How do I at compile-time check whether an aggregate field is static? https://dlang.org/phobos/std_traits.html#hasStaticMember perhaps. Thanks. Neither my web searches nor ChatGPT plus couldn't figure that out.
Re: Why does disabling a struct's postblit increase its size in memory?
On Saturday, 2 March 2024 at 19:28:08 UTC, Per Nordlöw wrote: On Saturday, 2 March 2024 at 19:11:42 UTC, kinke wrote: Not according to run.dlang.io, for all available DMD versions. Perhaps your tested `S` was nested in some function/aggregate and so had an implicit context pointer. Ahh. Yes. Indeed. My mistake. Thanks. Thanks. Neither my websearches nor ChatGPT plus couldn't figure that out.
Re: Why does disabling a struct's postblit increase its size in memory?
On Saturday, 2 March 2024 at 19:11:42 UTC, kinke wrote: Not according to run.dlang.io, for all available DMD versions. Perhaps your tested `S` was nested in some function/aggregate and so had an implicit context pointer. Ahh. Yes. Indeed. My mistake. Thanks.
Why does disabling a struct's postblit increase its size in memory?
Why does disabling a struct's postblit increase its sizeof by one word? The following holds: ```d struct S { @disable this(this); int _; } struct T { int _; } static assert(S.sizeof == 16); static assert(T.sizeof == int.sizeof); ``` . Why is this needed?
Re: LDC Stacktrace with symbols instead of addresses
On Sunday, 11 February 2024 at 06:43:19 UTC, Per Nordlöw wrote: How do I make LDC stacktraces like ```test-library(+0x1fb232)[0x562230d82232] So it turns out that ldc2 doesn't show symbols in stack traces by default. IMHO, in debug mode D should adhere to what other languages do. Meaning a sane behavior like what ```d int main(string[] args) { import etc.linux.memoryerror : registerMemoryErrorHandler; registerMemoryErrorHandler(); int*x = null; *x = 42; return 0; } ``` does when using compiled and run via ```sh dmd -g -debug -run app ``` gives ``` etc.linux.memoryerror.NullPointerError@src/etc/linux/memoryerror.d(322) ??:? void etc.linux.memoryerror.sigsegvUserspaceProcess(void*) [0x55fd3461e4f6] ??:? void etc.linux.memoryerror.sigsegvDataHandler() [0x55fd3461e42e] ./app.d:4 _Dmain [0x55fd345e53e6] ``` . Doing the same thing with LDC via ```sh ldc2 -g --d-debug -run app ``` gives ``` ld: error: undefined symbol: _D3etc5linux11memoryerror26registerMemoryErrorHandlerFNbZb referenced by app.d:3 /tmp/objtmp-ldc-dec7a7/app.o:(D main) collect2: error: ld returned 1 exit status Error: /usr/bin/cc failed with status: 1 ``` .
LDC Stacktrace with symbols instead of addresses
How do I make LDC stacktraces like ```test-library(+0x1fb232)[0x562230d82232] test-library(+0x2a35b7)[0x562230e2a5b7] /lib/x86_64-linux-gnu/libc.so.6(+0x42520)[0x7f6ad2242520] test-library(+0x7521a)[0x562230bfc21a] test-library(+0x79083)[0x562230c00083] test-library(+0x2a35f5)[0x562230e2a5f5] test-library(+0x2b0627)[0x562230e37627] test-library(+0x2b0b59)[0x562230e37b59] test-library(+0x2b05cc)[0x562230e375cc] test-library(+0x2a7b9f)[0x562230e2eb9f] test-library(+0x2a34a4)[0x562230e2a4a4] test-library(+0x2aac5b)[0x562230e31c5b] test-library(+0x2aab87)[0x562230e31b87] test-library(+0x2aa9dd)[0x562230e319dd] test-library(+0xa71d2)[0x562230c2e1d2] /lib/x86_64-linux-gnu/libc.so.6(+0x29d90)[0x7f6ad2229d90] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80)[0x7f6ad2229e40] test-library(+0x4db45)[0x562230bd4b45] Error Program exited with code -11``` show symbols instead of adresses? I am compiling with `-g --d-debug -fsanitize=address`.
Re: Need help with 128bit integer ucent boolfilter
On Friday, 6 October 2023 at 13:44:14 UTC, d007 wrote: I am search for a fast 128bit integer ucent boolfilter, used for server side duplicate request filter. Is 128bit boolfilter a doable thing? or it will not work or will be much more slow compare to 64 bit solution? Can you describe or give a reference to what you mean by bool filter?
Autoformatter for SDLang
Does anybody know of an autoformatted of SDLang, specifically for dub.sdl?
Re: serve-d and emacs
On Wednesday, 19 April 2023 at 10:35:31 UTC, Per Nordlöw wrote: On Wednesday, 19 April 2023 at 09:39:19 UTC, Per Nordlöw wrote: On Wednesday, 19 April 2023 at 09:37:56 UTC, Per Nordlöw wrote: . Has anybody gotten these things to work? I'm gonna try `lsp-mode` instead of `eglot`. I believe this should work ```elisp (defun serve-d-command () "Shell command to start serve-d." '("dub" "run" "--vquiet" "serve-d")) (when (require 'lsp nil t) (dolist (mode '(d-mode d-ts-mode)) (add-hook mode #'lsp) (add-to-list 'lsp-language-id-configuration `(,mode . "d"))) (lsp-register-client (make-lsp-client :new-connection (lsp-stdio-connection #'serve-d-command) :major-modes '(d-mode d-ts-mode) :server-id 'serve-d))) ``` but unfortunately I get status disconncted in the mode-line and the call to dub run shuts down. Clues anyone? Hmm, it turns out that using this a call to lsp-mode with this never triggers a call to the elisp function `serve-d-command` . I don't see what's wrong.
Re: serve-d and emacs
On Wednesday, 19 April 2023 at 10:35:31 UTC, Per Nordlöw wrote: I believe this should work ```elisp (defun serve-d-command () "Shell command to start serve-d." '("dub" "run" "--vquiet" "serve-d")) (when (require 'lsp nil t) (dolist (mode '(d-mode d-ts-mode)) (add-hook mode #'lsp) (add-to-list 'lsp-language-id-configuration `(,mode . "d"))) (lsp-register-client (make-lsp-client :new-connection (lsp-stdio-connection #'serve-d-command) :major-modes '(d-mode d-ts-mode) :server-id 'serve-d))) ``` but unfortunately I get status disconncted in the mode-line and the call to dub run shuts down. Clues anyone? How do I most easily get the debug output from ``` '("dub" "run" "--vquiet" "serve-d") ``` ?
Re: serve-d and emacs
On Wednesday, 19 April 2023 at 09:39:19 UTC, Per Nordlöw wrote: On Wednesday, 19 April 2023 at 09:37:56 UTC, Per Nordlöw wrote: . Has anybody gotten these things to work? I'm gonna try `lsp-mode` instead of `eglot`. I believe this should work ```elisp (defun serve-d-command () "Shell command to start serve-d." '("dub" "run" "--vquiet" "serve-d")) (when (require 'lsp nil t) (dolist (mode '(d-mode d-ts-mode)) (add-hook mode #'lsp) (add-to-list 'lsp-language-id-configuration `(,mode . "d"))) (lsp-register-client (make-lsp-client :new-connection (lsp-stdio-connection #'serve-d-command) :major-modes '(d-mode d-ts-mode) :server-id 'serve-d))) ``` but unfortunately I get status disconncted in the mode-line and the call to dub run shuts down. Clues anyone?
Re: serve-d and emacs
On Wednesday, 19 April 2023 at 09:37:56 UTC, Per Nordlöw wrote: . Has anybody gotten these things to work? I'm gonna try `lsp-mode` instead of `eglot`.
Re: serve-d and emacs
On Wednesday, 28 April 2021 at 23:04:27 UTC, Christian Köstlin wrote: if you configure it yourself, feel free to share the configuration and maybe PR it to serve-d repo. Its a little tricky, because the basic setup works e.g. with emacs 27.2 or newer, but not with 27.1. All that is needed (if you have the right emacs version and use straight for installing packages) is: I'm having problems with serve-d + eglot in Emacs. All calls to ``` eglot-find-declaration eglot-find-implementation eglot-find-typeDefinition ``` answers as ``` eglot--error: [eglot] Sorry, this server doesn't do :textDocument/declaration ``` Are neither of ``` :textDocument/declaration ``` supported? If so what lsp request type should I use to lookup/navigate to definitions? Without such functionality I see no use of eglot. . I'm currently using ```elisp (use-package eglot ;; :straight t :ensure t :defer t :hook (d-mode . eglot-ensure) :config (progn ;; (add-hook 'd-mode-hook 'eglot-ensure) (let ((cmd '("dub" "run" "--vquiet" "serve-d"))) (add-to-list 'eglot-server-programs ;https://forum.dlang.org/post/s6cpls$pg3$1...@digitalmars.com `(d-mode . ,cmd)) (add-to-list 'eglot-server-programs ;https://forum.dlang.org/post/s6cpls$pg3$1...@digitalmars.com `(d-ts-mode . ,cmd ;; (remove-hook 'd-mode-hook 'eglot-ensure) ) ``` . Has anybody gotten these things to work?
Provisioning C libraries in Windows CI builds
I just tried activating Linux and Windows CI for https://code.dlang.org/packages/gmp-d via https://github.com/nordlow/gmp-d/.github/workflows/d.yml Linux passes but the Windows builds all fail because `gmp.lib` is not provisioned in the Windows CI. This is new to me so I need some initial guidance as I'm suspecting there are multiple package managers or direct sources download methods available for getting gmp.lib provisioned locally so linking finds `gmp.lib`. gmp is available via https://vcpkg.io/en/packages.html is that the preferred way?
Re: Is remove safe using foreach
On Monday, 12 December 2022 at 17:29:00 UTC, Steven Schveighoffer wrote: Removing keys while iterating is not supported. It will break, in confusing ways, and possibly include a null pointer dereference. IRC, the specs says that it's an error to modify a foreach aggregate but the compiler curretly doesn't diagnose it.
Re: Is remove safe using foreach
On Tuesday, 13 December 2022 at 11:22:35 UTC, Per Nordlöw wrote: IRC, the specs says that it's an error to modify a foreach aggregate but the compiler curretly doesn't diagnose it. I believe it should.
Re: LSP-server for D?
On Tuesday, 6 December 2022 at 01:48:54 UTC, ryuukk_ wrote: Have you tried this? https://github.com/Pure-D/serve-d/blob/master/editor-emacs.md It should be similar for lsp-mode make sure you provide the proper parameters Ok, thanks.
Re: LSP-server for D?
On Monday, 5 December 2022 at 12:38:07 UTC, Per Nordlöw wrote: On Monday, 5 December 2022 at 12:23:24 UTC, Per Nordlöw wrote: Is there a D lsp-server available? I couldn't find anything at https://code.dlang.org/search?q=lsp. Am I not using the correct search terms? Ahh, it's at https://code.dlang.org/packages/serve-d. Have anybody successfully used the LSP part of serve-d in conjunction with Emacs' lsp-mode as a frontend?
Re: LSP-server for D?
On Monday, 5 December 2022 at 12:23:24 UTC, Per Nordlöw wrote: Is there a D lsp-server available? I couldn't find anything at https://code.dlang.org/search?q=lsp. Am I not using the correct search terms? Ahh, it's at https://code.dlang.org/packages/serve-d.
LSP-server for D?
Is there a D lsp-server available? I couldn't find anything at https://code.dlang.org/search?q=lsp. Am I not using the correct search terms?
Re: __traits isCopyable vs isPOD
On Tuesday, 29 November 2022 at 00:50:54 UTC, Paul Backus wrote: If your goal is to avoid calling the copy constructor (and, I assume, to avoid unnecessary instantiations of `move`), then yeah, `isPOD` is the one you want. Thanks.
Re: __traits isCopyable vs isPOD
On Monday, 28 November 2022 at 22:59:13 UTC, Paul Backus wrote: Lots of types. For example, types with copy constructors or destructors are not POD but may still be copyable. This should be obvious if you read the definition of POD linked from the language spec: https://dlang.org/glossary.html#pod I guess I knew that, sorry for the dumb question - the real question I had is whether one should use `isPOD` instead of `isCopyable` in cases ```d static if (__traits(isCopyable, Element)) insertAt(element, index); else insertAt(move(element), index); ``` because that avoids any potential call to the copy-constructor and destructor of `Element`. Afaict, one should.
Re: __traits isCopyable vs isPOD
On Monday, 28 November 2022 at 20:58:43 UTC, Per Nordlöw wrote: For which types `T` does ```d __traits(isCopyable, T) ``` differ from ```d __traits(isPOD, T) ``` ? I'm asking because I have code like ```d static if (__traits(isCopyable, Element)) insertAt(element, index); else insertAt(move(element), index); ``` and I wonder if one in those cases should be using `isCopyable` or `isPOD`.
Re: Sorted Array (Container) Type
On Tuesday, 15 November 2022 at 22:15:36 UTC, Per Nordlöw wrote: On Tuesday, 15 November 2022 at 21:03:24 UTC, Per Nordlöw wrote: This is what I have so far. Found some issues but still cannot instantiate my solution at https://github.com/nordlow/phobos-next/blob/master/src/nxt/sorted.d#L15 when I uncomment the line containing ```d // TODO: completeSort!(less, ss)(_source[0 .. n].assumeSorted!(less), _source[n .. $]); ``` I made an adjustment to make better use of existing member functions of SortedRange. Still, does anybody understand why the line https://github.com/nordlow/phobos-next/blob/master/src/nxt/sorted.d#L52 fails to compile as ```sorted.d(52): Error: none of the overloads of template `std.algorithm.sorting.completeSort` are callable using argument types `!("a < b", SwapStrategy.unstable)(SortedRange!(int[], "a < b", SortedRangeOptions.assumeSorted), int[])` /home/per/.local/dlang/linux/bin64/src/phobos/std/algorithm/sorting.d(117):Candidate is: `completeSort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Lhs, Rhs)(SortedRange!(Lhs, less) lhs, Rhs rhs)` sorted.d(74): Error: template instance `nxt.sorted.Sorted!(int[], "a < b", SwapStrategy.unstable).Sorted.insert!int` error instantiating```
Re: Sorted Array (Container) Type
On Tuesday, 15 November 2022 at 21:03:24 UTC, Per Nordlöw wrote: This is what I have so far. Found some issues but still cannot instantiate my solution at https://github.com/nordlow/phobos-next/blob/master/src/nxt/sorted.d#L15 when I uncomment the line containing ```d // TODO: completeSort!(less, ss)(_source[0 .. n].assumeSorted!(less), _source[n .. $]); ```
Re: Sorted Array (Container) Type
This is what I have so far. ```d import std.algorithm.mutation : SwapStrategy; /** Wrapper container around array (slice) or array-like (container) `A`. * * See_Also: https://en.wikipedia.org/wiki/Sorted_array */ struct Sorted(A, alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable) if (is(A == U[], U) || // isDynamicArray __traits(isStaticArray, A)) { private alias E = typeof(A.init[0]); this(A source) { _source = source[]; import std.algorithm.sorting : sort; sort!(less, ss)(_source[]); } auto opSlice() return scope => _source[]; static if (is(A == U[], U)) // isDynamicArray bool insert(in E x) scope @trusted // TODO: @safe { import std.algorithm.sorting : completeSort; foreach (ref e; _source) if (e == x) return false; // indicate no insert const n = _source.length; _source.reserve(n + 1); // TODO: use template parameter `Growth` _source.length += 1; _source[n] = x; // TODO: enable: version(none) completeSort!(less, ss)(_source[0 .. n], _source[n .. $]); // this fails return true;// indicate insert } bool contains(in E x) const { foreach (ref e; _source) if (e == x) return true; return false; } private A _source; } /// constructor from dynamic array @safe pure nothrow unittest { scope int[] x = [3,2,1]; alias A = typeof(x); auto sx = Sorted!(A)(x); assert(sx[] == [1,2,3]); assert(sx[].isSorted); assert(!sx.insert(3)); // assert(sx.insert(4)); } /// constructor from static array @safe pure nothrow @nogc unittest { int[3] x = [3,2,1]; alias A = typeof(x); auto sx = Sorted!(A)(x); assert(sx[].isSorted); } version(unittest) { import std.algorithm.sorting : isSorted; } ``` . But I don't understand why my call to completeSort isn't allowed by the compiler and errors as ``` sorted.d(78): Error: none of the overloads of template `std.algorithm.sorting.completeSort` are callable using argument types `!("a < b", SwapStrategy.unstable)(int[], int[])` std/algorithm/sorting.d(117):Candidate is: `completeSort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Lhs, Rhs)(SortedRange!(Lhs, less) lhs, Rhs rhs)` sorted.d(98): Error: template instance `nxt.sorted.Sorted!(int[], "a < b", SwapStrategy.unstable)` error instantiating ``` What am I missing?
Re: Sorted Array (Container) Type
On Monday, 14 November 2022 at 00:29:40 UTC, Tejas wrote: He said on Discord he want contiguous data structure, rbtree allocates too much rbtree has it's uses cases. I wanted a sorted array because I want to include it in a benchmark suite and study it's time and space complexity. No application yet.
Sorted Array (Container) Type
Have anybody created a wrapper container ```d struct Sorted(ArrayLike, alias lessThanPred) ``` that wraps an array-like type `ArrayLike` so that it's always sorted according to the binary predicate `lessThanPred`?
public vs private alias this
When is it preferrable to use ```d struct S { private T t; alias t this; } ``` instead of ```d struct S { public T t; alias t this; } ``` for any given type `T`?
Re: Disabling All Inlining in DMD Debug Builds
On Monday, 24 October 2022 at 20:43:45 UTC, ryuukk_ wrote: I wish we could do ``version(DebugFast | Release)`` Moreover, I've been using, for instance, ```d version(D_Coverage) {} else pragma(inline, true); void foo() {} ``` to get correct coverage inclusion of `foo()`. Is this still neeed?
Supporting foreach (k, v; T.init) for a user-defined (container) type
What property of a container (type) `T` enables iteration as ```d foreach (k, v; T.init) { ... } ``` ? I thought it sufficed to define `T.byKeyValue` but its presence seem to have no effect.
Override dub dflags for a single source file only
In dub, is it possible to override the dflags, in my case `-cov`, for a single file only without it affecting the rest of the compiling and linking? Currently, dub enforces static linking of the dependencies when the `-cov` flag is set via `dflags "-cov"` in dub.sdl which makes our build fail.
Re: Compiling dynamic library but not its dependencies with specific dflags
On Sunday, 18 September 2022 at 08:24:27 UTC, Per Nordlöw wrote: Given shared library `X` depending on other shared libraries `Ys`, is it possible, using dub, to use extra `dflags` `F` when building the sources of `X` only and not have those extra flags `F` be used when (re)compiling `Ys`. In my specific case those flags are `-fsanitize=address` and `-cov`. The solution was to define a new build. For instance as ```json { "buildTypes": { "debug-cov": { "buildOptions": ["debugMode", "debugInfo", "coverage"] } } } ``` in `dub.json`.
Compiling dynamic library but not its dependencies with specific dflags
Given shared library `X` depending on other shared libraries `Ys`, is it possible, using dub, to use extra `dflags` `F` when building the sources of `X` only and not have those extra flags `F` be used when (re)compiling `Ys`. In my specific case those flags are `-fsanitize=address` and `-cov`.
Re: Index an AliasSeq with a run-time index
On Sunday, 14 August 2022 at 10:41:20 UTC, ag0aep6g wrote: On 14.08.22 12:08, Per Nordlöw wrote: How do I index an `AliasSeq` with an integer known at run-time? Thanks
Index an AliasSeq with a run-time index
How do I index an `AliasSeq` with an integer known at run-time?
Re: Phobos Unittest
On Friday, 3 September 2021 at 23:39:44 UTC, Per Nordlöw wrote: When is a phobos unittest supposed to be qualified with version `(StdUnittest)`? Ideally, always? I don't see that their current use is consistenly following a rule. If so, is the purpose of its presence to reduce the burden of the compiler when the application using phobos is compiled with -unittest? (edited). For reference, see my previous attempt at making dmd more flexible at compiling unittests at https://github.com/dlang/dmd/pull/6375
Re: Absence of isAllocator trait
On Monday, 6 September 2021 at 15:46:52 UTC, Paul Backus wrote: * `void allocate(size_t size)` Should be * `void[] allocate(size_t size)` Thanks. Here's what I have so far ```d enum isAllocator(T) = (is(typeof(T.allocate(size_t.init)) == void[]) && is(typeof(T.alignment) == uint)); ```
Re: Phobos Unittest
On Saturday, 4 September 2021 at 20:05:17 UTC, Per Nordlöw wrote: ```sh time dmd import_std.d -o- ``` should be ```sh time dmd -unittest import_std.d -o- ```
Re: Phobos Unittest
On Saturday, 4 September 2021 at 13:12:49 UTC, Steven Schveighoffer wrote: Note that lexing and parsing is extremely quick, and I wouldn't focus on trying to trim this out, you won't get much performance out of that. -Steve For the record, a D file containing only `import std;` type checks via ```sh time dmd import_std.d -o- ``` in 0.20s whereas ```sh time dmd import_std.d -o- ``` in 0.45s on my ThreadRipper.
Absence of isAllocator trait
Is there a reason for the absence of an `isAllocator` trait under `std.experimental.allocator`?
Re: Phobos Unittest
On Saturday, 4 September 2021 at 12:40:02 UTC, Per Nordlöw wrote: Omg. It really seems like it's motivated to do a benchmark with phobos unittests prefixed with Should have been a reply to The "never" is false, https://d.godbolt.org/z/c4oeYM7rG
Re: Phobos Unittest
On Saturday, 4 September 2021 at 12:40:02 UTC, Per Nordlöw wrote: then. I can make that refactoring in my favorite choice of editor and see the result differ. In terms of binary size, and speed and memory usage of check, build and link time. Automated that is. If we want this, shall we format as ```d version (StdUnittest) [QUALIFIER...] unittest ``` instead of current ```d version (StdUnittest) [QUALIFIER...] unittest ``` ?
Re: Phobos Unittest
On Saturday, 4 September 2021 at 12:31:33 UTC, Dennis wrote: On Saturday, 4 September 2021 at 09:42:46 UTC, Per Nordlöw wrote: Yes, but they are lexed and parsed, right? Right, but that's the case regardless of `version(StdUnittest)`. Omg. It really seems like it's motivated to do a benchmark with phobos unittests prefixed with version(StdUnittest) then. I can make that refactoring in my favorite choice of editor and see the result differ. In terms of binary size, and speed and memory usage of check, build and link time.
Re: Phobos Unittest
On Saturday, 4 September 2021 at 12:31:33 UTC, Dennis wrote: Right, but that's the case regardless of `version(StdUnittest)`. I don't think so. My guess is that `version(StdUnittest)` does maximum parsing, maybe only lexing. How can one easily determine if this is the fact? Behaviour of `pragma(msg)`?
Re: Phobos Unittest
On Saturday, 4 September 2021 at 03:18:01 UTC, Paul Backus wrote: As Steven Schveighoffer [pointed out][1], Phobos unittests are never included in user code, regardless of whether `StdUnittest` is used. Yes, but they are lexed and parsed, right?
Phobos Unittest
When is a phobos unittest supposed to be qualified with version `(StdUnittest)`? Ideally, always? I don't see that their current use is consistenly following a rule. If so, is the purpose of its presence to reduce the burden of the compiler when the application using phobos is compiled with -unittest? (edited). If we were to put a `version (StdUnittest)` in front of every `unittest` in phobos (via an automated refactoring of course) would that speed building large applications or tests-suites with the `-unittest` flag provide they import many/all phobos libraries via, for instance, import `std`? When compiling non-phobos modules with `-unittest` flag, how are the `unittest`-blocks in imported phobos modules processed by the compiler? Are they only lexed (and parsed) but nothing else?
Re: Need for std.meta.isSame over __traits(isSame)
On Wednesday, 1 September 2021 at 22:51:40 UTC, Per Nordlöw wrote: Can somebody explain the need for Ok, `__traits(isSame)` always returns false for values. This is very unfortunate as `std.traits.isSame` is one of the most used template instances in typical std.meta-programming and has a noticeable impact on time and space complexity now that AliasAssign-enabled versions of std.meta members have removed the need for other costly recursive template patterns. I suggest we add a new builtin trait that exactly mimics std.traits.isSame or inline the calls to `isSame` in `std.traits.meta`. This is gonna significantly speed up functions in std.meta, for instance `staticIndexOf`, `EraseAll`, `GenericReplace`, `ReplaceAll`, `Pack`.
Need for std.meta.isSame over __traits(isSame)
Can somebody explain the need for ```d private template isSame(alias a, alias b) { static if (!is(typeof( && )) // at least one is an rvalue && __traits(compiles, { enum isSame = a == b; })) // c-t comparable { enum isSame = a == b; } else { enum isSame = __traits(isSame, a, b); } } ``` when there is already ```d __traits(isSame, a, b) ``` ? Are there any cases where ```d __traits(isSame, a, b) ``` doesn't have the same value as ```d a == b ``` provided the static if expression above is true.
Re: Object.dup?
On Monday, 30 August 2021 at 20:32:28 UTC, Adam D Ruppe wrote: You can define one yourself of course with overrides in child classes to update those kinds of things. But doing it automatically is tricky. Yes, thanks. I was interested in the possibility of a single non-member function, though.
Object.dup?
Why doesn't `Object` have an auto-defined `.dup` property? It would be useful when dealing with, for instance, handling of `Throwable`'s in multi-threaded contexts.
Re: AA.values un-@safe?!
On Wednesday, 28 July 2021 at 21:39:43 UTC, jfondren wrote: I don't know, but .byValue is @safe and returns a forward range, so you could use `.init.byValue.array` instead. Great point. Thanks.
AA.values un-@safe?!
Why is call to `values` in, for instance, ```d auto _ = string[string].init.values; ``` not `@safe`?
Re: Cannot call find with haystack elements having a explicit copy constructors
On Thursday, 15 July 2021 at 11:08:25 UTC, Per Nordlöw wrote: The adding of copy construtors to `Service` defined as ```d @safe struct Service { this(ref return scope typeof(this) rhs) {} this(const ref return scope typeof(this) rhs) const {} } Using `inout` as ```d @safe struct Service { this(inout ref typeof(this) rhs) inout {} } ``` works.
Re: Cannot call find with haystack elements having a explicit copy constructors
On Thursday, 15 July 2021 at 11:08:25 UTC, Per Nordlöw wrote: fails in the same way. What's wrong? ```d @safe struct Service { this(ref typeof(this) rhs) {} this(const ref typeof(this) rhs) const {} } ``` also fails. On the other hand, using a postblit as ``` @safe struct Service { this(this) {} } ``` passes.
Cannot call find with haystack elements having a explicit copy constructors
The adding of copy construtors to `Service` defined as ```d @safe struct Service { this(ref return scope typeof(this) rhs) {} this(const ref return scope typeof(this) rhs) const {} } @safe struct Session { void openAndGetService(in string key) scope { import std.algorithm.searching : find; auto hit = _pairs.find!((x) => x.key == key)(); } private Pair[] _pairs; private struct Pair { string key; Service service; } } ``` makes a call to find error as ``` copy_ctor_find_fail.d(9): Error: template `std.algorithm.searching.find` cannot deduce function from argument types `!((x) => x.key == key)(Pair[])`, candidates are: auto hit = _pairs.find!((x) => x.key == key)(); ^ std/algorithm/searching.d(1559):`find(alias pred = "a == b", InputRange, Element)(InputRange haystack, scope Element needle)` InputRange find(alias pred = "a == b", InputRange, Element)(InputRange haystack, scope Element needle) ^ std/algorithm/searching.d(1827):`find(alias pred, InputRange)(InputRange haystack)` with `pred = __lambda2, InputRange = Pair[]` must satisfy the following constraint: ` isInputRange!InputRange` InputRange find(alias pred, InputRange)(InputRange haystack) ^ std/algorithm/searching.d(1881):`find(alias pred = "a == b", R1, R2)(R1 haystack, scope R2 needle)` R1 find(alias pred = "a == b", R1, R2)(R1 haystack, scope R2 needle) ^ std/algorithm/searching.d(2340):`find(alias pred = "a == b", Range, Ranges...)(Range haystack, Ranges needles)` with `pred = __lambda2, Range = Pair[], Ranges = ()` must satisfy the following constraint: ` Ranges.length > 1` Tuple!(Range, size_t) find(alias pred = "a == b", Range, Ranges...) ^ std/algorithm/searching.d(2455):`find(RandomAccessRange, alias pred, InputRange)(RandomAccessRange haystack, scope BoyerMooreFinder!(pred, InputRange) needle)` RandomAccessRange find(RandomAccessRange, alias pred, InputRange)( ^``` Using ```d auto hit = _pairs.find!((scope const ref x) => x.key == key)(); ``` fails in the same way. What's wrong?
Improved diagnostics for mismatched template constraints
Given ```d import std.range.primitives : isInputRange; enum isDumb(Args...) = (Args.length == 2 && Args.length == 3); void f(Args...)(Args args) if (isDumb!(Args)) { } void g(Arg)(Arg arg) if (isInputRange!(Arg)) { } @safe pure unittest { f(2, 3); g(2); } ``` `dmd` diagnoses the first level as ``` /home/per/f.d(18,6): Error: template `f.f` cannot deduce function from argument types `!()(int, int)`, candidates are: /home/per/f.d(6,6):`f(Args...)(Args args)` with `Args = (int, int)` must satisfy the following constraint: ` isDumb!Args` /home/per/f.d(19,6): Error: template `f.g` cannot deduce function from argument types `!()(int)`, candidates are: /home/per/f.d(11,6):`g(Arg)(Arg arg)` with `Arg = int` must satisfy the following constraint: ` isInputRange!Arg ``` I'm certain I've seen dmd be able to diagnose which sub-expression of `isDumb` and `isInputRange` that evaluated to false. Did I just dream this or is there a way? If there is a way does this improvement still reside in a dmd PR?
Re: What does @nogc do to a class?
On Thursday, 6 May 2021 at 01:04:02 UTC, Jack wrote: Does it allocate the object rather on stack, like auto scope a = new A or what? Further note that auto scope a = new A; can be written shorter as scope a = new A;
Re: Shared with synchronized
On Monday, 4 March 2019 at 00:07:39 UTC, r-const-dev wrote: I'm trying to implement a thread safe class, guarding data access with synchronized and atomicOp. To get more help with memory safety checking from the compiler, please instead use `@safe` as ```d import std.typecons : Nullable; @safe class SharedObject { private Nullable!int sharedValue; private int changeCount = 0; synchronized void modifyValue(int newValue) @trusted { (cast(SharedObject)this).unsafeModifyValue(newValue); } private void unsafeModifyValue(int newValue) { sharedValue = newValue; ++changeCount; } } @safe void main() { shared SharedObject data = new shared SharedObject(); data.modifyValue(3); } ```
Re: GC memory fragmentation
On Monday, 12 April 2021 at 20:50:49 UTC, Per Nordlöw wrote: more aggressive collections when nearing it. What is a more aggressive collection compared to a normal collection? Unfortunately we still have no move support in D's GC because of its impreciseness.
Re: GC memory fragmentation
On Monday, 12 April 2021 at 20:50:49 UTC, Per Nordlöw wrote: I'm surprised there is no such functionality available. It doesn't sound to me like it's that difficult to implement. Afaict, we're looking for a way to call `GC.collect()` when `GC.Status.usedSize` [1] reaches a certain threshold. I wonder how other GC-backed languages handle this. [1] https://dlang.org/phobos/core_memory.html#.GC.Stats.usedSize
Re: GC memory fragmentation
On Monday, 12 April 2021 at 07:03:02 UTC, Sebastiaan Koppe wrote: On side-note, it would also be good if the GC can be aware of the max memory it is allotted so that it knows it needs to do more aggressive collections when nearing it. I'm surprised there is no such functionality available. It doesn't sound to me like it's that difficult to implement.
Error when running dmd compilable tests
Inside dmd source tree, under sub-directory test, I do ./run.d compilable/ . This errors as ``` ... compilable/json.d -d -preview=dip1000 -o- -X -Xf/home/per/Work/dmd/test/test_results/compilable/json.out -fPIC ()== Test 'compilable/json.d' failed. The logged output: Executing post-test script: tools/postscript.sh compilable/extra-files/json-postscript.sh compilable json /home/per/Work/dmd/test/test_results/compilable/json.d.out0 tools/postscript.sh: line 18: /home/per/Work/dmd/test/tools /home/per/Work/dmd/test/tools/exported_vars.sh: No such file or directory /home/per/Work/dmd/generated/linux/release/64/dmd -conf= -m64 -Icompilable -d -preview=dip1000 -o- -X -Xf/home/per/Work/dmd/test/test_results/compilable/json.out -fPIC -od/home/per/Work/dmd/test/test_results/compilable -of/home/per/Work/dmd/test/test_results/compilable/json_0.o -c compilable/json.d == Test 'compilable/json.d' failed: Expected rc == 0, but exited with rc == 1 TARGET FAILED: compilable/json.d ... compilable/ddoc8.d -D -Dd/home/per/Work/dmd/test/test_results/compilable -o- -fPIC ()== ``` What's wrong?
Fastest Way to Append Multiple Elements to an Array
https://forum.dlang.org/post/rkxnfxsjvkffxufok...@forum.dlang.org On Thursday, 1 January 2015 at 19:18:34 UTC, Nordlöw wrote: Do we really need Append and Prepend (along with append and prepend) here? Doesn't [cC]hain already fulfill the needs of a lazy range in this case inplace of Append? Is there still a place for `append` in Phobos? What about reusing `chain(args)` for realizing append(Args...)(lhs, args)?
Re: Is dlang.slack.com down?
On Sunday, 4 April 2021 at 11:48:37 UTC, Imperatorn wrote: On Sunday, 4 April 2021 at 11:12:36 UTC, Per Nordlöw wrote: Trying to access https://dlang.slack.com/ hangs for minutes on my machine. I'm only using the app, same thing there for you? 樂 I was trying the desktop version. Works now. Seems to have been temporary.
Is dlang.slack.com down?
Trying to access https://dlang.slack.com/ hangs for minutes on my machine.
Re: Using onOutOfMemoryError in C wrappers
On Wednesday, 24 March 2021 at 10:25:21 UTC, Basile B. wrote: In now way. But in your question you mentioned @nogc nothrow and not @safe and pure. Ok, thanks. Note that core.exception.onOutOfMemoryError is already qualified as @nogc nothrow pure @trusted.
Re: Using onOutOfMemoryError in C wrappers
On Wednesday, 24 March 2021 at 08:31:19 UTC, Basile B. wrote: There are several ways to do that. In addition to onOutOfMemoryError, you can use a static instance void v() @nogc nothrow { __gshared oom = new OutOfMemoryError(); auto X* = X_create(); if (X is null) throw oom; } How is that better than void v() @nogc nothrow { auto X* = X_create(); if (X is null) onOutOfMemoryError(); } considering the fact that accessing `__gshared` state is neither `@safe` nor `pure`? Which, in turn, makes `v()` unconditionally unsafe and unpure regardless of safety and purity of `X_create()`.
Using onOutOfMemoryError in C wrappers
When wrapping C code that tries to allocate memory resources via functions such as X* X_create(); should one call `onOutOfMemoryError();` upon null return? Making more D wrappers `nothrow @nogc`.
Re: Implicit conversion of unique chars[] to string
On Tuesday, 23 March 2021 at 01:07:15 UTC, Steven Schveighoffer wrote: And the answer is complex. You can't accept a const range, because they don't work. The only way to have purity infer uniqueness is to accept paramters that the result could not have come from. Usually this means accepting const and returning mutable. How do we want this to work with and without the presence of `return` qualified parameters?
Re: Implicit conversion of unique chars[] to string
On Tuesday, 23 March 2021 at 01:07:15 UTC, Steven Schveighoffer wrote: const(char)[] x = "foo"; string chained = chainPath(x, "bar").array; that calls the template overload ForeachType!Range[] array(Range)(Range r) if (isIterable!Range && !isAutodecodableString!Range && !isInfinite!Range) should be able to implicitly convert to string because the .array expression is inferred `pure`. Or is the compiler pessimistically assuming that the slice returned from the .array call may reside from a reference reachable from the range parameter `r`? See for instance @safe pure unittest { import std.path : chainPath; import std.array : array; const(char)[] x1 = "foo"; const string x2 = "bar"; auto y1 = chainPath(x1, x2).array; pragma(msg, __FILE__, "(", __LINE__, ",1): Debug: ", typeof(y1)); auto y2 = chainPath(x2, x1).array; pragma(msg, __FILE__, "(", __LINE__, ",1): Debug: ", typeof(y2)); } printing /home/per/f.d(8,1): Debug: const(char)[] /home/per/f.d(10,1): Debug: const(char)[]
Re: Implicit conversion of unique chars[] to string
On Monday, 22 March 2021 at 20:38:36 UTC, Per Nordlöw wrote: chainPath(...).array To clarify, for instance, given string s; const(char)[] c; all the calls chainPath(s, s).array chainPath(c, c).array chainPath(s, c).array chainPath(c, s).array return a value of type const(char)[].
Implicit conversion of unique chars[] to string
Am I the only one being annoyed by the fact that chainPath(...).array doesn't implicit convert to string despite the array returned from .array is allocated by the GC. Yes, I know that I should do chainPath(...).array.assumeUnique but the uniqueness of .array (and in turn implicit conversion to immutable) should be inferred by the compiler. Inference could happen in the same compiler pass that checks (will infer) scope qualifiers. Are there plans for making this happen? Is having a @unique qualifier motivated for the sake of compiler performance to avoid the for need transitive inference across function calls?
Re: Make foreach element optional
On Tuesday, 16 March 2021 at 13:31:34 UTC, Imperatorn wrote: foreach(0..n) could work. Why though. When performing a side-effect n times.
Make foreach element optional
I find myself writing foreach (_; 0 .. n) doSomething(); // no using the variable `_` . What about relaxing the syntax to allow foreach (; 0 .. n) and/or foreach (0 .. n) ? Thereby making the `ForeachTypeList` of `AggregateForeach` in the grammar rule [1] optional. [1] https://dlang.org/spec/statement.html#foreach-statement
Re: GC.addRange in pure function
On Tuesday, 9 February 2021 at 03:05:10 UTC, frame wrote: On Sunday, 7 February 2021 at 14:13:18 UTC, vitamin wrote: Why using 'new' is allowed in pure functions but calling GC.addRange or GC.removeRange isn't allowed? Would making `new T[]` inject a call to `GC.addRange` based on `T` (and maybe also T's attributes) be a step forward?
Re: Type of string literal concatenated with non-immutable char array
On Monday, 1 February 2021 at 15:47:33 UTC, Steven Schveighoffer wrote: "Concatenation always creates a copy of its operands, even if one of the operands is a 0 length array" Btw, does x ~ y ~ z ~ ... result in a single allocation?
Re: Type of string literal concatenated with non-immutable char array
On Monday, 1 February 2021 at 16:30:31 UTC, Per Nordlöw wrote: Btw, does x ~ y ~ z ~ ... result in a single allocation? Provided all the operands has a `length` property.
Re: Type of string literal concatenated with non-immutable char array
On Monday, 1 February 2021 at 10:27:29 UTC, Jacob Carlborg wrote: Why isn't "Name " ~ name ~ " could not be found" implicitly convertible to `string`? Because if you have arrays of reference types, it's possible to change an element of the mutable array, which will affect the immutable array, those breaking the immutability. Example: I still don't understand why that restriction applies to arrays of values types (such as `char`). Having this limitation makes my code example more bloated or less efficient memorywise; I either have to define two separate ctors or force an .idup at the site of the exception construction.
Re: Why are multiple instances of the single enum created?
On Monday, 1 February 2021 at 10:24:59 UTC, Mike Parker wrote: There is no "extra" instance because there's no single instance of an enum value. They have no address. When you use one, it's just as if you were writing the literal instead of the enum name. In other words: enum ea = [1, 2, 3]; auto a0 = ea; auto a1 = ea; is identical to this: auto a0 = [1, 2, 3]; auto a1 = [1, 2, 3]; Ok, so then my follow-up question becomes, does the right hand sides of these two assignment share the same AST node? If not, why?
Re: Why are multiple instances of the single enum created?
On Monday, 1 February 2021 at 11:37:49 UTC, Per Nordlöw wrote: Ok, so then my follow-up question becomes, does the right hand sides of these two assignment share the same AST node? If not, why? Because such a shared AST node could be potentially mutated in different ways in different contexts during its passes?
Re: Why are multiple instances of the single enum created?
On Monday, 1 February 2021 at 09:52:07 UTC, Jacob Carlborg wrote: If you don't want a new instance, then don't use `enum`. Use `immutable` instead. Agreed. My question is why does an `enum` require an extra instance from a compiler architecture point of view? Do all compilers handle compile-time enum instances in that way?
Why are multiple instances of the single enum created?
An enum only exists at compile-time, and does not occupy any space. Each time it's referenced, a new instance of the value is created. Why is that? Seems like a waste of resources to the compiler.
Type of string literal concatenated with non-immutable char array
Given char x[]; why is typeof("a" ~ x) `char[]` when typeof("a" ~ x.idup) is `string`? My case is class NameLookupException : Exception { this(string name) { super("Name " ~ name ~ " could not be found"); } this(scope const(char)[] name) { super("Name " ~ name.idup ~ " could not be found"); } } where I instead would like to only need class NameLookupException : Exception { this(scope const(char)[] name) { super("Name " ~ name ~ " could not be found"); } } Why isn't "Name " ~ name ~ " could not be found" implicitly convertible to `string`? Would class NameLookupException : Exception { this(scope const(char)[] name) @trusted { super("Name " ~ cast(string)name ~ " could not be found"); } } be ok?
Re: Convert double to long if lossless
On Tuesday, 19 January 2021 at 21:04:51 UTC, kdevel wrote: And then? I mean: What do you want to do with the long what could not be done with the double in the first place? Motivated question. We want to propagate to our system locally that a double received from a network communication actually is an integer and should be stored and treated as such in an algebraic type.
Re: Convert double to long if lossless
On Tuesday, 19 January 2021 at 16:14:17 UTC, drug wrote: https://dlang.org/phobos/std_bitmanip.html#FloatRep Doesn't this pattern already cover all possible cases of `value` needed? void f(double value) { auto lvalue = cast(long)value; if (lvalue == value) // `value` lacks fraction and in range [long.min .. long.max] { // use long lvalue return; } // use double value }
Re: Convert double to long if lossless
On Tuesday, 19 January 2021 at 17:03:53 UTC, Ali Çehreli wrote: I think it would be a useful improvement. Indeed. Maybe Ilya could help out adding this to dmd.
Re: Convert double to long if lossless
On Tuesday, 19 January 2021 at 13:36:58 UTC, Steven Schveighoffer wrote: Use a cast instead. const lvalue = cast(long)value; Ahh, good point. Followd by a compare of the original value I presume.
Convert double to long if lossless
I want to convert a double to a long if conversion is lossless (without fractional part, non-nan, non-inf, within long-range, etc). I currently have void foo() { const double value = 10.1; try { import std.conv : to; const lvalue = value.to!long; if (lvalue == value) { writeln("lvalue:", lvalue); return; } } catch (Exception e) {} writeln("value:", value); } Can this be improved? For instance how do I check if a float/double/real has a fractional part and avoid entering try-catch for those cases?
Re: Recursively defined matcher function
On Sunday, 3 January 2021 at 18:26:44 UTC, Per Nordlöw wrote: alias Matcher = Match function(Matcher[] matchers...); but it errors as recursive alias declaration Preferrably I wanted a non-templated definition.
Recursively defined matcher function
How can I define a function type `Matcher` that takes an array of `Matcher`s and returns an instance of a `struct Match` defined as struct Match { @safe pure nothrow @nogc: static Match zero() { return typeof(return)(0); } static Match none() { return typeof(return)(_length.max); } /// Match length in number of UTF-8 chars or 0 if empty. @property uint length() { return _length; } bool opCast(U : bool)() const { return _length != _length.max; } this(size_t length) { assert(length <= _length.max); this._length = cast(typeof(_length))length; } const uint _length;// length == uint.max is no match } I've tried alias Matcher = Match function(Matcher[] matchers...); but it errors as recursive alias declaration