Assuming 'static' for 'let' with initial value

#1

A let field with initial value specified in declaration (rather than obtained in a constructor) will retain this value for all instances of the class. For this reason it looks logical to assume this field to be static, even if static keyword is not coded explicitly.

Does Swift currently implement that, or I should post it as a suggestion? Please, answer, if you know it certainly.

As a benefit of dropping static keyword (while the field is actually static) is accessing a field without an explicit class name. The need to code ClassName.filedName for a static field in Swift is really frustrating. I don't know the arguments for that (maybe merely to discourage static), but here are the contra-arguments: firstly this makes difficult porting the code to another class, secondly, given that class name is typically quite long, the lines get longer and not clearly readable, thirdly, it's just annoying. :yum:

1 Like
SE-0260: Library Evolution for Stable ABIs
(Thomas Roughton) #2

Swift doesn’t do this. One reason against it - and a binary compatibility concern - is that since stored lets take up space within each instance, this would change the size and layout of structs and class instances. For example, I often pass structs to the GPU* which have constant let properties, and having those bytes be missing would cause serious issues

*

I know that I really should be defining these structs in C - however, since the Swift struct layout is now fixed in ABI for fixed_layout types and the layout algorithm does what I want anyway/matches the GPU code it’s not an issue in practice.

3 Likes
(Daniel Höpfl) #3

There might still be wanted side effects, e.g. the constructor might open a logfile with the current date. (Or things like let instanceID = UUID())

(Xiaodi Wu) #4

These are not the same thing if the value is not of a value type, or if the value is a collection of elements that are not of a value type, or if the value has a member that is not of a value type, etc.

1 Like
#5

Indeed, I've overlooked some issues.

Well, it could be some restrictions, e.g. a let property defined as a literal. Still better than nothing :)

(Tellow Krinkle) #6

Personally, I think the right solution would be to make it so that static variables (and functions) are accessible without the class name prefix. It's been discussed a long time ago though I would like it if the issue was revisited, since that discussion feels very unfinished IMO.

Edit:
For the time being, if you want a global static variable but also want to treat it like an instance variable, make it a computed property:

var a: Int { return 1 }
// Instead of
let a = 1

If you needed the global-ness, make a global variable and an instance property that accesses it:

class MyClass {
	static let a: Type = { code you want to only run once }()
	var a: Type { return MyClass.a }
}

It has the minus of making it possible to do myObject.a which you probably didn't want but that may be a tradeoff you're willing to take (and sounds like a tradeoff you already decided to take).

1 Like
#7

As a compromising solution, allow using Self instead of class name for static properties and functions

1 Like
#8

Your wish is granted(in the next swift version): https://github.com/apple/swift-evolution/blob/master/proposals/0068-universal-self.md

1 Like
(Ben Rimmington) #9

@cukr The following hack also seems to work (in Swift 4.2):

struct MyStruct {

    #if !compiler(>=5.1)
    private typealias `Self` = MyStruct // FIXME: SE-0068
    #endif

    static func staticMethod() {
        /* ... */
    }

    func instanceMethod() {
        Self.staticMethod()
    }
}

I haven't tried it with classes, or in other Swift versions.

2 Likes
#10

Better later than never :)

(Slava Pestov) #11

FWIW, SE-0068 is implemented on master and swift-5.1-branch thanks to @johnno1962.

3 Likes
(Spencer Kohan) #12

I would really like this to become a specific part of the spec, or at least have explicit ways to define memory layouts in Swift. It is extremely convenient to be able to declare Structs natively in Swift and pass them to the GPU.

2 Likes