Idea: Allow/require "let" in property setter name declarations


(Ian Partridge) #1

Currently, the syntax for explicitly naming property setters is:

class Square {
  var sideLength: Double = 0.0

  var perimeter: Double {
    get {
      return sideLength * 4.0
    }
    set(newPerimeter) { // declares newPerimeter parameter, "let" not
allowed
      sideLength = newPerimeter / 4.0
    }
  }
}

Compare this with how extraction of associated values from enumerations
looks:

enum ServerResponse {
  case Failure(String)
  case Result(Int)
}
let response = ServerResponse.Result(404)

switch response {
case .Failure(let reason): // let is required here
  print(reason)
case .Result(let code):
  print(code)
}

For consistency, would it be better to allow/require:

class Square {
  var sideLength: Double = 0.0

  var perimeter: Double {
    get {
      return sideLength * 4.0
    }
    set(*let* newPerimeter) { // declares newPerimeter parameter
        sideLength = newPerimeter / 4.0
    }
  }
}

The idea would apply to didSet{} and willSet{} too.

···

--
Ian Partridge


(Haravikk) #2

Actually a setter has more in common with a function, in which case the let implicit, the difference is that a setters type is also implicit. In fact, you don’t even need to specify a name in a setter at all, as the default is newValue and you can just use that.

I’m more curious whether we even need a named new value at all, or if setters should just look like the following instead:

  set { sideLength = $0 / 4.0 }

As this would be more consistent with anonymous closure arguments, rather than using newValue which is arbitrary. I’ve never encountered an occasion where I’ve needed a custom name, and I only use external vs internal names on functions where I can make an external name that flows better, but perhaps doesn’t mesh with my other internal variable names.

···

On 6 May 2016, at 12:09, Ian Partridge via swift-evolution <swift-evolution@swift.org> wrote:

Currently, the syntax for explicitly naming property setters is:

class Square {
  var sideLength: Double = 0.0

  var perimeter: Double {
    get {
      return sideLength * 4.0
    }
    set(newPerimeter) { // declares newPerimeter parameter, "let" not allowed
      sideLength = newPerimeter / 4.0
    }
  }
}

Compare this with how extraction of associated values from enumerations looks:

enum ServerResponse {
  case Failure(String)
  case Result(Int)
}
let response = ServerResponse.Result(404)

switch response {
case .Failure(let reason): // let is required here
  print(reason)
case .Result(let code):
  print(code)
}

For consistency, would it be better to allow/require:

class Square {
  var sideLength: Double = 0.0

  var perimeter: Double {
    get {
      return sideLength * 4.0
    }
    set(let newPerimeter) { // declares newPerimeter parameter
        sideLength = newPerimeter / 4.0
    }
  }
}

The idea would apply to didSet{} and willSet{} too.

--
Ian Partridge

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Chris Lattner) #3

I understand what you’re saying, and this would be a logical direction for ML or Haskell, which use patterns for their parameter grammars. In Swift, function parameters (including setter parameters, subscript indexes, etc) do not allow the general pattern matching or destructuring grammar that you can use in ‘case’ patterns, and thus you don’t have to write:

func f(let x : Int) {}

This is one of the reasons that led to SE-0003.

-Chris

···

On May 6, 2016, at 4:09 AM, Ian Partridge via swift-evolution <swift-evolution@swift.org> wrote:

Currently, the syntax for explicitly naming property setters is:

    set(newPerimeter) { // declares newPerimeter parameter, "let" not allowed
      sideLength = newPerimeter / 4.0
    }
Compare this with how extraction of associated values from enumerations looks:

switch response {
case .Failure(let reason): // let is required here
  print(reason)
case .Result(let code):
  print(code)
}


(Geordie J) #4

Comments below

Actually a setter has more in common with a function, in which case the let implicit, the difference is that a setters type is also implicit. In fact, you don’t even need to specify a name in a setter at all, as the default is newValue and you can just use that.

I’m more curious whether we even need a named new value at all, or if setters should just look like the following instead:

  set { sideLength = $0 / 4.0 }

This is great!
Why not have the opportunity to name the variable like in closures, but have it default to $0:

class Square {
  var sideLength: Double = 0.0
  var perimeter: Double {
    set { newPerimeter in
      sideLength = newPerimeter / 4.0
    }
  }
}

···

Am 06.05.2016 um 13:48 schrieb Haravikk via swift-evolution <swift-evolution@swift.org>:

As this would be more consistent with anonymous closure arguments, rather than using newValue which is arbitrary. I’ve never encountered an occasion where I’ve needed a custom name, and I only use external vs internal names on functions where I can make an external name that flows better, but perhaps doesn’t mesh with my other internal variable names.

On 6 May 2016, at 12:09, Ian Partridge via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Currently, the syntax for explicitly naming property setters is:

class Square {
  var sideLength: Double = 0.0

  var perimeter: Double {
    get {
      return sideLength * 4.0
    }
    set(newPerimeter) { // declares newPerimeter parameter, "let" not allowed
      sideLength = newPerimeter / 4.0
    }
  }
}

Compare this with how extraction of associated values from enumerations looks:

enum ServerResponse {
  case Failure(String)
  case Result(Int)
}
let response = ServerResponse.Result(404)

switch response {
case .Failure(let reason): // let is required here
  print(reason)
case .Result(let code):
  print(code)
}

For consistency, would it be better to allow/require:

class Square {
  var sideLength: Double = 0.0

  var perimeter: Double {
    get {
      return sideLength * 4.0
    }
    set(let newPerimeter) { // declares newPerimeter parameter
        sideLength = newPerimeter / 4.0
    }
  }
}

The idea would apply to didSet{} and willSet{} too.

--
Ian Partridge

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution