Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issues 20301 and 20302 #7231

Merged
merged 3 commits into from
Oct 19, 2019
Merged

Conversation

PetarKirov
Copy link
Member

@PetarKirov PetarKirov commented Oct 16, 2019

This PR includes the following commits:

  • Fix issue 20302 - Support head const in memoize
    Make std.functional.memoize accept functions whose return types or parameters are head const.
  • [refactor]: Simplify memoize(alias fun) implementation
    • Use object.require to save one hash table lookup
    • [style] Consolidate imports
  • Fix Issue 20301 - Support const array of patterns in std.regex.regex

Make std.functional.memoize accept functions whose return type or
parameters are head const.
@dlang-bot
Copy link
Contributor

Thanks for your pull request, @ZombineDev!

Bugzilla references

Auto-close Bugzilla Severity Description
20301 normal std.regex.regex doesn't accept a const/immutable array of patterns
20302 normal std.functional.memoize doesn't accept a functions with const/immutable parameters

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub fetch digger
dub run digger -- build "stable + phobos#7231"

@PetarKirov PetarKirov force-pushed the fix-issue-20301 branch 4 times, most recently from 22c1247 to fdaccee Compare October 16, 2019 15:39
@PetarKirov
Copy link
Member Author

PetarKirov commented Oct 17, 2019

I'll drop commit df58d90 as it breaks users that assume memoize is nothrow friendly. The reason for the breakage is that object.require uses a lazy parameter, whose attributes can't be inferred (bug #12647). I'll also push a commit that ensures memoize!fib produces a nothrow function, in order to prevent accidental breakage down the line.

if (isSomeString!(S))
{
import std.array : appender;
import std.functional : memoize;
enum cacheSize = 8; //TODO: invent nice interface to control regex caching
S pat;
const(C)[] pat;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the only reason to introduce C is this, maybe ElemType would be better ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so (maybe I'm missing something?), because:

  1. regexImpl supports only string types (not ranges).
  2. ElemType (I assume you mean std.range.primitives.ElementType) will return dchar, given T = string, or T = wstring. In case we're called with such narrow strings, we would need to re-encode them to dchar[], which would be the type of pat.
  3. const-ness. Changing the parameter from S[] patterns to const S[] patterns is not strictly necessary here (but it is for regexImpl), but by doing this I'm saving on distinct template instances. Before for S = char[], S = const(char)[] and S = const(char[]) (ditto for immutable) we would get different template instances. Now there's only one.
    So, with this change in mind, when regex(const S[] patterns, ..) is called with a char[][], patterns is deduced to be const(char[][]), while S becomes char[] and we get the following error:
    Error: cannot implicitly convert expression patterns[0] of type const(char[]) to char[]
    
    (Because in the line pat = patterns[0], pat is S = char[] and patterns[0] is const(char[]).)
    Additionally, I can't define pat as const S as then I won't be able to assign to it.
    So what I need is the char type, so I can define pat as tail-const.
  4. Using the template specialization syntax S : C[], C is much shorter and readable then ElementEncodingType (from std.range.primitives). It's probably also slightly faster to compile.

std/functional.d Outdated Show resolved Hide resolved

static ReturnType!fun[Tuple!Args] memo;
static Unqual!(ReturnType!fun)[Tuple!Args] memo;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Unqual really shouldn't be necessary (in a perfect world), but I guess the compiler can't recognize that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given const(int) fun(int a, int b);, typeof(memoize!fun.memo) becomes: ReturnType!fun[Tuple!Args] -> const(int)!fun[Tuple!(int, int)]. Later on, for the line memo[t] = fun(args) you get:

Error: cannot modify const expression memo[t]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, but since this is insert-only, it should work.
However, it would take the compiler to recognize insert-only path (e.g. by handling require ?) to make this work.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know, I thought as well and I even tried using require and without Unqual change, but it has this line inside, which would fail because *p is const(int).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's said, I think it's a would be a good enhancement request.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unqual + emplace should work there, but I think that change is better left for the master branch, while this PR is targeting stable.

Copy link
Member

@Geod24 Geod24 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple nits, oLGTM

@trikko
Copy link
Contributor

trikko commented Oct 18, 2019

@PetarKirov
Copy link
Member Author

Hi @trikko, I didn't see your bug report so it's a nice coincidence that yours and mine have consecutive Bugzilla numbers. I'll take a look if it's something easy to fix.

@PetarKirov
Copy link
Member Author

@trikko I took a stab at implementing it and the good news is that it's definitely doable - see https://run.dlang.io/gist/ZombineDev/677cea7195209dec2e2b393bcf94ae24?compiler=dmd. However it wouldn't be trivial to turn my code into a proper Phobos pull request for the limited time I have today, so I'll leave it for a future PR.

@trikko
Copy link
Contributor

trikko commented Oct 18, 2019

Too bad (:

@PetarKirov
Copy link
Member Author

It looks like @dlang-bot is offline...

@PetarKirov PetarKirov merged commit 34b29a5 into dlang:stable Oct 19, 2019
@PetarKirov PetarKirov deleted the fix-issue-20301 branch October 19, 2019 06:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants