On Sunday, May 28, 2017 16:49:16 Brad Roberts via Digitalmars-d-learn wrote: > Is there a mechanism for declaring something pure when it's built from > parts which individually aren't? > > string foo(string s) > { > // do something arbitrarily complex with s that doesn't touch > globals or change global state except possibly state of the heap or gc > return s; > }
Either everything the function is doing is pure, or it can't be pure without cheating, and cheating is usually a bad idea. There is no @trusted equivalent for pure. Now, if you're absolutely sure that the function doesn't do anything that's actually going to run afoul of pure and what the compiler will assume about pure functions, but it's using stuff that wasn't properly marked as pure, or does something that can't be marked as pure for some reason but in this context would actually be fine, you can cast. For instance, std.datetime's LocalTime is a singleton which gets the timezone conversion from the system. Its operations can't be pure, but it can be constructed as pure, and because it's a singleton, it will return the same instance every time. Originally, a static constructor was used to initialize the singleton (which therefore worked great with pure), but because of circular dependency pain with static constructors, we had to get rid of the static constructors in std.datetime. The solution was to move the initialization into another function which was not pure, and then when we call it from theh singleton function, we cast it to pure: static immutable(LocalTime) opCall() @trusted pure nothrow { alias FuncType = @safe pure nothrow immutable(LocalTime) function(); return (cast(FuncType)&singleton)(); } static immutable(LocalTime) singleton() @trusted { import core.stdc.time : tzset; import std.concurrency : initOnce; static instance = new immutable(LocalTime)(); static shared bool guard; initOnce!guard({tzset(); return true;}()); return instance; } Now, in the vast majority of cases, I would strongly advise against cheating in this manner, because you need to be absolutely sure that you're not actually violating pure (particularly what the compiler will assume about pure) by what you're doing, and usually what it comes down to is that something that your function is calling needs to be fixed so that it can be inferred as pure, or it simply needs to be marked as pure. Casting is a horrible hack that should only be used as a last resort and only when you're 100% sure that it's fine. However, you _can_ use casting as a backdoor if you really have to. - Jonathan M Davis