From 8a67d30d089235c66469db9b6a80ada62914b91d Mon Sep 17 00:00:00 2001 From: Jonathan M Davis Date: Sun, 24 Nov 2024 01:59:53 -0700 Subject: [PATCH] Add notes related to phobos.sys.meta and std.meta. It seemed like it would be a good idea to document which symbols in Phobos v2 map to which ones in Phobos v3, as well as to document which symbols are _not_ being ported to Phobos v3 (and why). In addition, it seems sensible to document at least some of the design decisions. And it will also help me keep track of where things stand for myself when figuring out what I still need to do - though who knows whether anyone else will be doing this kind of documentation later for the stuff that they work on. Either way, when Phobos v3 gets released, we _are_ going to need to put together information for users somewhere for what ended up where in Phobos v3 so that they can port their Phobos v2 code to v3 if they so desire (and generally find stuff in v3 that they're familiar with in v2). And documentation like this commit has can at least provide the basis for that even if it's not what we're going to give to users (presumably, that will need to be in ddoc on dlang.org). So, I've started a section of the repo for providing notes for each module as we add them (as well as notes for the old modules so that we can provide links to the new symbols and provide information about symbols that are not getting ported over). So, the intention at least is that each public module in Phobos v2 and each public module in Phobos v3 will eventually end up with a corresponding file under module_notes, but we'll see. --- module_notes/phobos/sys/meta.md | 158 +++++++++++++++++++++++++++++++ module_notes/std/meta.md | 160 ++++++++++++++++++++++++++++++++ 2 files changed, 318 insertions(+) create mode 100644 module_notes/phobos/sys/meta.md create mode 100644 module_notes/std/meta.md diff --git a/module_notes/phobos/sys/meta.md b/module_notes/phobos/sys/meta.md new file mode 100644 index 0000000..7895fb0 --- /dev/null +++ b/module_notes/phobos/sys/meta.md @@ -0,0 +1,158 @@ +# Overview + +This provides some notes on the design of phobos.sys.meta. + +phobos.sys.meta is a port of Phobos v2's std.meta with changes where +appropriate. The basic goal of the module is the same in that it's supposed to +be providing templates that do metaprogramming on `AliasSeq`s - essentially a +std.algorithm for `AliasSeq`s instead of ranges. + +phobos.sys.meta has fewer symbols than std.meta primarily because it's best to +use CTFE rather than template metaprogramming where possible and because a +number of the templates in std.meta are of questionable utility. Clearly, +_someone_ thought that they would be useful, or they wouldn't have been added, +but Phobos either doesn't use them at all or barely uses them, making it +questionable that we want them in the standard library. So, while we may add +some of those symbols later, for now at least, if a symbol doesn't seem like +it's generally useful, it's not being ported. + +A major functionality change between std.meta and phobos.sys.meta is that +various templates in std.meta compare the elements in an `AliasSeq` - typically +using a private template which tries to do a bunch of different kinds of +comparisons with the behavior changing depending on whether the element can be +compared with `==`, an `is` expression, or `__traits(isSame, ...)`. This has +proven to be incredibly error-prone with some weird and unexpected behaviors +(e.g. whether a no-argument function is treated as a value or as a symbol +depends on what it's being compared against as well as which side of the +comparison it's on). And in general, operating on an `AliasSeq` that's a +mixture of types, values, and symbols is just a mess. So, instead of having +phobos.sys.meta's templates provide any sort of comparison, they instead now +take template predicates (typically a trait from phobos.sys.traits) so that the +programmer can decide how the comparison is done. So, ultimately, the same +functionality is provided, but it's under the control of the programmer, making +it much more flexible and less error-prone. + +Another functionality change is that std.meta is inconsistent about whether a +template that does a comparison short-circuits evaluation, whereas +phobos.sys.meta's templates do not short-circuit evaluation - both for the sake +of consistency, and because it allows for more efficient implementations. Also, +given that some of the elments in an `AliasSeq` might not even compile if they +are evaluated (e.g. because the predicate assumes a type, and an element is a +value), it's arguably better to evaluate all of the elements and catch such +bugs. + +With regards to the name changes, to better follow the official style guide, +any templates that evaluate to a value are camelCased, any templates which +evaluate to a type are PascalCased, and any templates which evaluate to an +`AliasSeq` (and thus could contain a combination of values, types, or symbols) +are PascalCased. Also, various names have been changed in order to improve +consistency. "static" and "template" have been removed from all of the names, +since they're not necessary, and neither is a convention that has ever been +followed consistently (even within std.meta). Presumably, in at least some of +the cases, it was done to prevent conflicts with symbols in std.algorithm, but +the module system already gives us a clean way to distinguish between symbols +with the same name but which are in different modules. + +--- +# Symbols + +## Alias + +* The Phobos v2 equivalent is [`std.meta.Alias`](../../std/meta.md#alias). +* Its functionality is unchanged. + +## AliasSeq + +* The Phobos v2 equivalent is [`std.meta.AliasSeq`](../../std/meta.md#aliasseq). +* Its functionality is unchanged. + +## all + +* The Phobos v2 equivalent is [`std.meta.allSatisfy`](../../std/meta.md#allsatisfy). +* It's been renamed to better match std.algorithm's `all`, and because having + "Satisfy" in the name is redundant, since that's true of any template which evaluates + to `true` or `false` based on a predicate. +* Its functionality is unchanged. + +## And + +* The Phobos v2 equivalent is [`std.meta.templateAnd`](../../std/meta.md#templateand). +* It's been renamed to better follow the official naming conventions. +* Its functionality is essentially the same. However, unlike + [`templateAnd`](../../std/meta.md#templateand), `And` does not short-circuit its + evaluation (something which std.meta in general is inconsistent about). + +## any + +* The Phobos v2 equivalent is [`std.meta.anySatisfy`](../../std/meta.md#anysatisfy). +* It's been renamed to better match std.algorithm's `any`, and because having + "Satisfy" in the name is redundant, since that's true of any template which evaluates + to `true` or `false` based on a predicate. +* Its functionality is unchanged. + +## ApplyLeft + +* The Phobos v2 equivalent is [`std.meta.ApplyLeft`](../../std/meta.md#applyleft). +* Its functionality is unchanged. + +## ApplyRight + +* The Phobos v2 equivalent is [`std.meta.ApplyRight`](../../std/meta.md#applyright). +* Its functionality is unchanged. + +## Filter + +* The Phobos v2 equivalent is [`std.meta.Filter`](../../std/meta.md#filter). +* Its functionality is unchanged. + +## indexOf + +* The Phobos v2 equivalent is [`std.meta.staticIndexOf`](../../std/meta.md#staticindexof). +* It's been renamed to better follow the official naming conventions. +* It now takes a template predicate to use for the comparison. + +## Instantiate + +* The Phobos v2 equivalent is [`std.meta.Instantiate`](../../std/meta.md#instantiate). +* Its functionality is unchanged. + +## Map + +* The Phobos v2 equivalent is + [`std.meta.staticMap`](../../std/meta.md#staticmap). +* It's been renamed to better follow the official naming conventions. +* Its functionality is unchanged. + +## Not + +* The Phobos v2 equivalent is [`std.meta.templateNot`](../../std/meta.md#templatenot). +* It's been renamed to better follow the official naming conventions. +* Its functionality is essentially the same. However, unlike + [`templateNot`](../../std/meta.md#templatenot), `Not` does not short-circuit its + evaluation (something which std.meta in general is inconsistent about). + +## Or + +* The Phobos v2 equivalent is [`std.meta.templateOr`](../../std/meta.md#templateor). +* It's been renamed to better follow the official naming conventions. +* Its functionality is essentially the same. However, unlike + [`templateOr`](../../std/meta.md#templateor), `Or` does not short-circuit its + evaluation (something which std.meta in general is inconsistent about). + +## Reverse + +* The Phobos v2 equivalent is [`std.meta.Reverse`](../../std/meta.md#reverse). +* Its functionality is unchanged. + +## Stride + +* The Phobos v2 equivalent is [`std.meta.Stride`](../../std/meta.md#stride). +* Its functionality is unchanged. + +## Unique + +* The Phobos v2 equivalent is [`std.meta.NoDuplicates`](../../std/meta.md#noduplicates). +* It's been renamed to be more in line with std.algorithm's `uniq`, which will + probably be renamed to `unique` due to Adam Wilson being against truncated + names. +* It now takes a template predicate to use for the comparison. diff --git a/module_notes/std/meta.md b/module_notes/std/meta.md new file mode 100644 index 0000000..a3683a9 --- /dev/null +++ b/module_notes/std/meta.md @@ -0,0 +1,160 @@ +# Overview + +This provides information on the symbols in std.meta with regards to what's +happening to them in Phobos v3. Either it indicates which Phobos v3 symbol +should be used instead, or it explains why that symbol hasn't been ported to +Phobos v3. + +[`phobos.sys.meta`](../phobos/sys/meta.md) is the Phobos v3 replacement for +std.meta, so in general, that's where the symbols from std.meta have been +ported to, but not all are getting ported, and some of them have had their +names and/or functionality changed in the process. + +--- +# Symbols + +## Alias + +* See [`phobos.sys.meta.Alias`](../phobos/sys/meta.md#alias). + +## AliasSeq + +* See [`phobos.sys.meta.AliasSeq`](../phobos/sys/meta.md#aliasseq). + +## aliasSeqOf + +* There are no plans to port it over to Phobos v3. +* Its usefulness is questionable, and it's barely used in Phobos v2. +* Also, even if we do decide to port it over, the current implementation + requires std.array.array, which has not yet been ported to Phobos v3. + +## allSatisfy + +* See [`phobos.sys.meta.all`](../phobos/sys/meta.md#all). + +## anySatisfy + +* See [`phobos.sys.meta.any`](../phobos/sys/meta.md#any). + +## ApplyLeft + +* See [`phobos.sys.meta.ApplyLeft`](../phobos/sys/meta.md#applyleft). + +## ApplyRight + +* See [`phobos.sys.meta.ApplyRight`](../phobos/sys/meta.md#applyright). + +## DerivedToFront + +* There are no plans to port it over to Phobos v3. +* Its usefulness is questionable, and it's not used anywhere in Phobos v2 + outside of std.meta. + +## Erase + +* There are no plans to port it over to Phobos v3. +* Its usefulness is questionable, and it's currently used in only one place in + Phobos v2 outside of std.meta. +* It's arguably a trivial wrapper around [`staticIndexOf`](#staticindexof), + which would arguably still be useful if it were needed frequently, but it + isn't. +* If we do decide to add it, it will need to be reworked to take a template + predicate (which [`phobos.sys.meta.indexOf`](../phobos/sys/meta.md#indexof) + would require, unlike [`staticIndexOf`](#staticindexof)). So, it would + essentially become a version of [`Filter`](../phobos/sys/meta.md#filter) that + stopped after matching a single element (or after encountering an element + which didn't match). So, if we _do_ decide to add something along these lines + to Phobos v3, we should probably add something like `FilterUntil` rather than + actually port over `Erase`. Ultimately though, it's probably better to have + code that wants `Erase` to just use + [`indexOf`](../phobos/sys/meta.md#indexof), particularly since it does not + appear to be a common use case. + +## EraseAll + +* There are no plans to port it over to Phobos v3. +* [`Filter`](../phobos/sys/meta.md#filter) can be used instead, since `EraseAll` is + essentially [`Filter`](../phobos/sys/meta.md#filter) with a predicate for + comparing the elements which is supplied by std.meta (and it's a predicate + that we really don't want to continue to use given how quirky and error-prone + it is). + +## Filter + +* See [`phobos.sys.meta.Filter`](../phobos/sys/meta.md#filter). + +## Instantiate + +* See [`phobos.sys.meta.Instantiate`](../phobos/sys/meta.md#instantiate). + +## MostDerived + +* There are no plans to port it over to Phobos v3. +* Its usefulness is questionable, and it's currently used in only one place in + Phobos v2 outside of std.meta. + +## NoDuplicates + +* See [`phobos.sys.meta.Unique`](../phobos/sys/meta.md#unique). + +## Repeat + +* There are no plans to port it over to Phobos v3. +* Its usefulness is questionable, and it's not used anywhere in Phobos v2 + outside of std.meta. + +## Replace + +* There are no plans to port it over to Phobos v3. +* Its usefulness is questionable, and it's currently used in only one place in + Phobos v2 outside of std.meta. + +## ReplaceAll + +* There are no plans to port it over to Phobos v3. +* Its usefulness is questionable, and it's not used anywhere in Phobos v2 + outside of std.meta. + +## Reverse + +* See [`phobos.sys.meta.Reverse`](../phobos/sys/meta.md#reverse). + +## staticIndexOf + +* See [`phobos.sys.meta.indexOf`](../phobos/sys/meta.md#indexof). + +## staticMap + +* See [`phobos.sys.meta.Map`](../phobos/sys/meta.md#map). + +## staticIsSorted + +* There are no plans to port it over to Phobos v3. +* It does seem like it _might_ be useful under some set of circumstances, but + it's not actually used anywhere in Phobos v2 outside of std.meta. So, it's + certainly not something that seems like it fundamentally shouldn't be + included, but it also doesn't seem to be particularly useful in practice. + +## staticSort + +* There are no plans to port it over to Phobos v3. +* It does seem like it _might_ be useful under some set of circumstances, but + it's not actually used anywhere in Phobos v2 outside of std.meta. So, it's + certainly not something that seems like it fundamentally shouldn't be + included, but it also doesn't seem to be particularly useful in practice. + +## Stride + +* See [`phobos.sys.meta.Stride`](../phobos/sys/meta.md#stride). + +## templateAnd + +* See [`phobos.sys.meta.And`](../phobos/sys/meta.md#and). + +## templateNot + +* See [`phobos.sys.meta.Not`](../phobos/sys/meta.md#not). + +## templateOr + +* See [`phobos.sys.meta.Or`](../phobos/sys/meta.md#or).