<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2017-08-16 10:37 GMT+02:00 Nathaniel Smith <span dir="ltr"><<a href="mailto:njs@pobox.com" target="_blank">njs@pobox.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Tue, Aug 15, 2017 at 11:53 PM, Jelle Zijlstra<br>
<<a href="mailto:jelle.zijlstra@gmail.com">jelle.zijlstra@gmail.com</a>> wrote:<br>
> Minor suggestion: Could we allow something like<br>
> `sys.set_new_context_item(<wbr>description='mylib.context',<br>
> initial_value='spam')`? That would make it easier for type checkers to infer<br>
> the type of a ContextItem, and it would save a line of code in the common<br>
> case.<br>
<br>
</span>This is a really handy feature in general, actually! In fact all of<br>
asyncio's thread-locals define initial values (using a trick involving<br>
subclassing threading.local), and I recently added this feature to<br>
trio.TaskLocal as well just because it's so convenient.<br>
<br>
However, something that you realize almost immediately when trying to<br>
use this is that in many cases, what you actually want is an initial<br>
value *factory*. Like, if you write new_context_item(initial_<wbr>value=[])<br>
then you're going to have a bad time. So, should we support something<br>
like new_context_item(initializer=<wbr>lambda: [])?<br>
<br>
The semantics are a little bit subtle. I guess it would be something<br>
like: if ci.get() goes to find the value and fails at all levels, then<br>
we call the factory function and assign its return value to the<br>
*deepest* LC, EC[0]. The idea being that we're pretending that the<br>
value was there all along in the outermost scope, you just didn't<br>
notice before now.<br>
<span class=""><br>
> With this modification, the type of new_context_item would be<br>
><br>
> @overload<br>
> def new_context_item(*, description: str, initial_value: T) -><br>
> ContextItem[T]: ...<br>
> @overload<br>
> def new_context_item(*, description: str) -> ContextItem[Any]: ...<br>
><br>
> If we only allow the second variant, type checkers would need some sort of<br>
> special casing to figure out that after .set(), .get() will return the same<br>
> type.<br>
<br>
</span>I'm not super familiar with PEP 484.<br>
<br>
Would using a factory function instead of an initial value break this<br>
type inference?<br>
<br>
If you want to automatically infer that whatever type I use to<br>
initialize the value is the only type it can ever have, is there a way<br>
for users to easily override that? Like could I write something like<br>
<br>
my_ci: ContextItem[int, str] = new_context_item(initial_<wbr>value=0)<br>
<br></blockquote><div>It would be `ContextItem[Union[int, str]]`, but yes, that should work.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
?<br>
<div class="HOEnZb"><div class="h5"><br>
-n<br>
<br>
--<br>
Nathaniel J. Smith -- <a href="https://vorpus.org" rel="noreferrer" target="_blank">https://vorpus.org</a><br>
</div></div></blockquote></div><br></div></div>