Swift protocol with lazy property requirement
You don't need the additional _footype variable and a computer “wrapper” property. The protocol requirement can be satisfied with a lazy stored property:

struct Bar: Foo {
    lazy var footype = calculateFoo()

    func calculateFoo() -&gt; Double {
        print("calc")
        return 3.453
    }
}


Now footype is read-only for instances of type Foo 

var foo: Foo = Bar()
print(foo.footype)
foo.footype = 12.3 // Error: Cannot assign to property: 'footype' is a get-only property


but as a property of Bar it is read-write:

var bar = Bar()
print(bar.footype)
bar.footype = 12.3 // OK


If assigning to the footype property should be inhibited then you can mark it with a private(set) access modifier:

struct Bar: Foo {
    private(set) lazy var footype = calculateFoo()

    func calculateFoo() -&gt; Double {
        print("calc")
        return 3.453
    }
}

var bar = Bar()
print(bar.footype)
bar.footype = 12.3 // Cannot assign to property: 'footype' setter is inaccessible


With respect to


  However, I would not put calculateFoo in the protocol because it sounds like an implementation detail.


Yes, in your current code it is an implementation detail of the Bar class. The only use would be that a caller can “enforce” the evaluation:

var foo: Foo = Bar()
foo.calculateFoo()


The situation would be different if there were a way to provide a default implementation in an extension method:

protocol Foo {
    var footype: Double { mutating get }

    func calculateFoo() -&gt; Double
}

extension Foo {
    var footype: Double {
        // Call calculateFoo() on first call only ...
    }
}


so that conforming to the protocol is sufficient, i.e. Bar only has to implement the calculateFoo() method, but not the footype property.

But I am not aware of a way to do this lazily so that the function is called only once. The reason is that extensions cannot add stored properties to a type.

For subclasses of NSObject you can come around this problem with “associated objects,” but not for structs.