I get this error in the following code: "Type of expression is ambiguous without more context", on the DispatchQueue. But only if I mark it as "lazy", and not if I don't. I'm not sure why.
class
myClass
{
lazy var myQ = DispatchQueue(label: "Op", attributes: .concurrent) // <-- ERROR
^Type of expression is ambiguous without more context
}
This problem seems to occur when using an initializer with some default
argument values. The following code also exhibits the issue:
struct Bar {
init(x: Int, y: Int? = 42) { }
}
class Foo {
lazy var myQ = Bar(x: 3)
}
I'd recommend filing a bug at bugs.swift.org.
···
On Sun, Sep 11, 2016 at 10:19 PM, Rick Mann via swift-users < swift-users@swift.org> wrote:
I get this error in the following code: "Type of expression is ambiguous
without more context", on the DispatchQueue. But only if I mark it as
"lazy", and not if I don't. I'm not sure why.
class
myClass
{
lazy var myQ = DispatchQueue(label: "Op", attributes: .concurrent) //
<-- ERROR
^Type of expression is ambiguous without more context
}
On Sep 11, 2016, at 22:40 , Jacob Bandes-Storch <jtbandes@gmail.com> wrote:
This problem seems to occur when using an initializer with some default argument values. The following code also exhibits the issue:
struct Bar {
init(x: Int, y: Int? = 42) { }
}
class Foo {
lazy var myQ = Bar(x: 3)
}
I'd recommend filing a bug at bugs.swift.org.
On Sun, Sep 11, 2016 at 10:19 PM, Rick Mann via swift-users <swift-users@swift.org> wrote:
I get this error in the following code: "Type of expression is ambiguous without more context", on the DispatchQueue. But only if I mark it as "lazy", and not if I don't. I'm not sure why.
class
myClass
{
lazy var myQ = DispatchQueue(label: "Op", attributes: .concurrent) // <-- ERROR
^Type of expression is ambiguous without more context
}
lazy var myQ: DispatchQueue = DispatchQueue(label: "Op", attributes: .concurrent)
Also, with regards this specific example, be aware that lazy properties aren’t guaranteed to be initialised only once. To quote “The Swift Programming Language”:
If a property marked with the `lazy` modified is accessed by multiple
threads simultaneously and the property has not yet been initialized,
there is no guarantee that the property will be initialized only once.
I’m struggling to think of a case where that limitation is acceptable in the context of a dispatch queue (-:
Share and Enjoy
···
On 12 Sep 2016, at 06:40, Jacob Bandes-Storch via swift-users <swift-users@swift.org> wrote:
lazy var myQ: DispatchQueue = DispatchQueue(label: "Op", attributes: .concurrent)
Sure, it just didn't seem to make sense.
Also, with regards this specific example, be aware that lazy properties aren’t guaranteed to be initialised only once. To quote “The Swift Programming Language”:
If a property marked with the `lazy` modified is accessed by multiple
threads simultaneously and the property has not yet been initialized,
there is no guarantee that the property will be initialized only once.
I’m struggling to think of a case where that limitation is acceptable in the context of a dispatch queue (-:
Thank you for that explanation. I had assumed lazy worked like static, which I understand uses dispatch_once under the hood. Would that be a reasonable thing for lazy to do?
In the end I didn't use a property for the queue, but rather just created it at point of use (I'm testing to see whether or not the enqueued blocks retain the queue; that's all I need).
···
On Sep 12, 2016, at 00:02 , Quinn The Eskimo! via swift-users <swift-users@swift.org> wrote:
On 12 Sep 2016, at 06:40, Jacob Bandes-Storch via swift-users <swift-users@swift.org> wrote:
I had assumed lazy worked like static, which I understand uses dispatch_once under the hood.
Correct.
[I’m not sure if it actually /uses/ `dispatch_once` specifically, but it has the same semantics.]
Would that be a reasonable thing for lazy to do?
It certainly would be nice. I suspect that this would be hard to implement because the restrictions associated with `dispatch_once` are pretty tight. OTOH, if you’d like to see it work this way it wouldn’t hurt to file an enhancement request.
Share and Enjoy
···
On 12 Sep 2016, at 08:46, Rick Mann <rmann@latencyzero.com> wrote:
--
Quinn "The Eskimo!" <http://www.apple.com/developer/>
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
It is not a bug. You must explicitly specify the variable's type if you use
`lazy` keyword. `lazy` means the variable will be initialized later, but
the compiler needs its type right now.
Zhaoxin
···
On Mon, Sep 12, 2016 at 3:02 PM, Quinn "The Eskimo!" via swift-users < swift-users@swift.org> wrote:
On 12 Sep 2016, at 06:40, Jacob Bandes-Storch via swift-users < > swift-users@swift.org> wrote:
> I'd recommend filing a bug at bugs.swift.org.
Agreed.
Also, you can work around this by adding a type.
lazy var myQ: DispatchQueue = DispatchQueue(label: "Op", attributes:
.concurrent)
Also, with regards this specific example, be aware that lazy properties
aren’t guaranteed to be initialised only once. To quote “The Swift
Programming Language”:
If a property marked with the `lazy` modified is accessed by multiple
threads simultaneously and the property has not yet been initialized,
there is no guarantee that the property will be initialized only once.
I’m struggling to think of a case where that limitation is acceptable in
the context of a dispatch queue (-:
Share and Enjoy
--
Quinn "The Eskimo!" <http://www.apple.com/developer/>
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
I had assumed lazy worked like static, which I understand uses dispatch_once under the hood.
Correct.
[I’m not sure if it actually /uses/ `dispatch_once` specifically, but it has the same semantics.]
Would that be a reasonable thing for lazy to do?
It certainly would be nice. I suspect that this would be hard to implement because the restrictions associated with `dispatch_once` are pretty tight. OTOH, if you’d like to see it work this way it wouldn’t hurt to file an enhancement request.
Oh, right, because it seems to need a static or global variable for the flag. I've always wondered why that was the case. Seems like any flag would do (like a member variable), and if that results in a second dispatch because it's a second flag, that's okay.
In any case, thanks for all the clarification.
···
On Sep 12, 2016, at 00:53 , Quinn The Eskimo! via swift-users <swift-users@swift.org> wrote:
On 12 Sep 2016, at 08:46, Rick Mann <rmann@latencyzero.com> wrote:
Share and Enjoy
--
Quinn "The Eskimo!" <http://www.apple.com/developer/>
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
I had assumed lazy worked like static, which I understand uses dispatch_once under the hood.
Correct.
Re-reading the above I realise that it was ambiguous. Let’s try that again.
* * *
I had assumed lazy worked like static …
No, alas.
which I understand uses dispatch_once under the hood.
Your understanding of `static` is correct.
Share and Enjoy
···
On 12 Sep 2016, at 08:53, Quinn The Eskimo! via swift-users <swift-users@swift.org> wrote:
On 12 Sep 2016, at 08:46, Rick Mann <rmann@latencyzero.com> wrote:
On 12 Sep 2016, at 08:46, Rick Mann <rmann@latencyzero.com> wrote:
--
Quinn "The Eskimo!" <http://www.apple.com/developer/>
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
Implementing `dispatch_once` so that it’s fast on all CPU architectures, including those with a weak memory model, requires that ‘once token’:
* be initialised to 0 before `dispatch_once` sees it
* not modified by anything other than `dispatch_once`
That’s true for [switching to Obj-C terminology here] global variables, which are initialised by the linker to 0 before any instruction in the process runs, but it’s not true for ivars.
If you want to see how this really works, you can check out the source in Darwin.
On Sep 12, 2016, at 03:02 , Quinn The Eskimo! via swift-users <swift-users@swift.org> wrote:
On 12 Sep 2016, at 09:20, Rick Mann <rmann@latencyzero.com> wrote:
I've always wondered why that was the case.
Implementing `dispatch_once` so that it’s fast on all CPU architectures, including those with a weak memory model, requires that ‘once token’:
* be initialised to 0 before `dispatch_once` sees it
* not modified by anything other than `dispatch_once`
That’s true for [switching to Obj-C terminology here] global variables, which are initialised by the linker to 0 before any instruction in the process runs, but it’s not true for ivars.
If you want to see how this really works, you can check out the source in Darwin.