How can I reserve all values of an enum in proto3? - proto3

I have a field of an enum type that I would like to deprecate. No clients use this field or its enum type. I want to reserve all of the values in this enum so that it cannot be reused.
message Example {
...
enum Foo {
BAR = 0;
BAZ = 1;
}
Foo foo = 42;
}
My first thought was to try reserving the values from 0 to max as follows:
message Example {
...
enum Foo {
reserved "BAR", "BAZ";
reserved 0 to max;
}
reserved "foo";
reserved 42;
}
However, I get an error stating that Foo must contain at least one value. Is there any way to deprecate an entire enum like this in order to make sure it isn't reused?

Although you can't reserve an entire enum (as far as I know since a zero value is required), you can reserve anything that ever was in it, and every use of it.
message Example {
...
enum Foo {
reserved "BAR", "BAZ";
reserved 1 to max;
RESERVED = 0;
}
reserved "foo";
reserved 42;
}

Related

How are Swift enums implemented internally?

I recently asked a question around sort of generic enum/structs in C and realized that although I brought up a comparison with the enum possibilities in e.g. Swift and Rust, I don't really understand how those are handled internally to those languages.
For Rust, I found a (rather roundabout) article titled Peeking inside a Rust enum
— look for the "But Rust enums aren't just that." heading and then keep scrolling until the "In Rust, it's called a discriminant." part. Eventually that part gets around to basically saying that Rust enums are sort of equivalent to something like this in C:
struct {
enum actual_options discriminant;
union {
/* … various data types/sub-structs corresponding to each option's need… */
};
};
Is it basically the same with a Swift enum under the hood? I.e. that I should expect an enum to have basically the same memory overhead as a struct of the largest possible option in my enum, plus at least one extra byte to store the tag/discriminant of the overarching case?
I'm also interested in what code gets generated to use whatever sort of underlying structure. I'm assuming it can't really much more fancy/optimized than what you'd do in C for the structure shown above? E.g.
struct raw_enum {
enum { case1, case2, case3 } tag;
union {
struct { int x; int y; } case1_data;
const char* case2_data;
struct { float a; double b; void* c; char d; } case3_data;
};
};
struct raw_enum d;
fill_in_some_value(&d);
if (d.tag == case1) {
// use `d.case1_data`…
} else if (d.tag == case2) {
// use `d.case2_data`…
} else if (d.tag == case3) {
// use `d.case3_data`…
} else {
// any runtime assertion for an unknown tag that could somehow sneak in???
}
Is that a reasonable approximation to what Swift does in the code it generates around enums?

Why outside of block swift can't see value assigned to a uninitialized variable in the block?

What is the mechanism of declaring w/o value in Swift5 ? Does the first assign become the real declaration ?
And, should we avoid to declare without value in Swift?
var v:String;
if true {
v = "Hello"
print(v) // print "Hello" when without the print below
}
print(v) // variable 'v' used before being initialized
var v:String="";
if true {
v = "Hello"
print(v) // print "Hello"
}
print(v) // print "Hello"
Well, the message is not very helpful, and that's the problem. This pattern (which I call computed initialization) is perfectly legal and useful and — amazingly — you can even use let instead of var. But you must initialize the uninitialized variable by all possible paths before you use it. So you have:
var v:String
if true {
v = "Hello"
}
print(v) // error
But hold my beer and watch this:
var v:String
if true {
v = "Hello"
} else {
v = "Goodbye"
}
print(v) // fine!
Or even:
let v:String
if true {
v = "Hello"
} else {
v = "Goodbye"
}
print(v) // fine!
Amazing, eh?
Now, you might say: OK, but true will always be true so it's silly to make me fulfill the "all paths" rule. Too bad! The compiler insists anyway, and then lets you off later with a warning that the else won't be executed. But a warning lets you compile; an error doesn't. The truth is that your example is very artificial. But this is a real-life possibility:
let v:String
if self.someBoolProperty {
v = "Hello"
} else {
v = "Goodbye"
}
print(v) // fine!
Not only is this sort of thing legal, it is actually the pattern that Apple recommends under certain slightly tricky circumstances. For instance, it is used in Apple's own example code showing how to use the Swift 5 Result struct:
let result: Result<Int, EntropyError>
if count < AsyncRandomGenerator.entropyLimit {
// Produce numbers until reaching the entropy limit.
result = .success(Int.random(in: 1...100))
} else {
// Supply a failure reason when the caller hits the limit.
result = .failure(.entropyDepleted)
}
So this is because swift compiles your code and notices that your value var v:String; is undeclared before being used which makes it an "optional" value. Even though you are assigning it within the if statement, if you were to get rid of the true value it is possible that the if statement would never run therefore no value will ever be stored in v, thus it would be used before "assigned".
So to answer your question if you want your value to be an optional and possible empty value declare v as the following var v:String? if you would like it to be a non-optional value with a value always stored within v you should declare it as the following var v = "". Swift will interpret this declaration as a String.
To answer your second question, defining without values in swift is 100% allowed, it really just depends on how you want to handle your code. I use optional values in my code all the time, but I don't necessarily like optionals so i usually like to declare my values such as var v = "" that way if the value is empty my UI or whatever else i'm manipulating won't break. But if i need to ensure a value is present i will have to make my value optional so i can use an if statement to check whether it's a valid value or not.
Shorter version of what I'm trying to say is, you are receiving the compiler warning because you are declaring v as a non-optional value rather than an optional value.

How do I define a constrained type in Swift?

I keep bumping onto this problem repeatedly. In real life I see sets of numbers that represent a particular quality but I have difficulties to express them as distinct type in Swift.
For example the percent type. Let says I would want to have a Percent type with only integers. Also this percent would never be able to go over 100 or below zero.
I could express that in pure C as a union, with members ranging from 0 to 100. However using the Swift enum for that with underlying value type doesn't seem to me like to correct approach. Or is it?
Let's pick another one. Bribor Interbank Interest rate. I know it will always be a range between 0 and 20 percent. But the number itself will be a decimal with two decimal places.
What's the correct way to deal with this problem in Swift? Generics perhaps?
As Michael says in the comment, probably something like this:
struct IntPercent {
let value : Int8
init?(_ v : Int) {
guard v >= 0 && v <= 100 else { return nil }
value = Int8(v)
}
}
(Note: use a struct, not a class for a base value like that)
If you do that a lot, you can improve that a little using protocols, like so:
protocol RestrictedValue {
associatedtype T : Comparable
static var range : ( T, T ) { get }
var value : T { set get }
init() // hack to make it work
}
extension RestrictedValue {
init?(v: T) {
self.init()
guard Self.range.0 <= v && Self.range.1 >= v else { return nil }
value = v
}
}
struct IntPercent : RestrictedValue {
static var range = ( 0, 100 )
var value : Int = 0
init() {}
}
I don't think you can use Generics to limit base type values.
But I bet there is an even better solution - this one is definitely not awezome :-)
Constraining the value of an object is not the same as a constrained type. Constraining values of numbers doesn't really make sense, as the things you are talking about are just numbers -- there is no such thing as a percent-number or a Bribor-Interbank-Interest-rate-number; they are just numbers. If you want to constrain their value, you do it wherever you get or use the numbers. It doesn't make sense to define a new type simply to constrain the values of an existing type.

Assign conditional expression in Swift?

Is there a way in Swift to assign conditional expressions similar to this
let foo = if (bar == 2) {
100
} else {
120
}
(or with a switch case).
(Don't want to have to use ternary operator for this).
This kind of assignement is good for functional style / immutability. The expressions have a return value in this case.
Note: it's a general question, this is just simplified example, imagine e.g. a switch case with a lot of values, pattern matching, etc. You can't do that with ternary operator.
Btw also note that there are languages that don't support ternary operator because if else returns a value, so it's not necessary, see e.g. Scala.
You can use a closure to initialize an immutable:
let foo: Int = {
if bar == 2 {
return 100
} else {
return 120
}
}()
The advantage of using a closure is that it's a function, so you can use any complex logic inside, implemented in a clean way and not through nested ternary operators. It can be a switch statement, it can be obtained as the return value of a function followed by some calculations, it can be a pattern matching case, it can be a combination of them all, etc.
Said in other words, it's the same as initializing with the return value of a function, but the difference is that the function is inline and not somewhere else, with readability benefits.
Just for completeness, if the variable is mutable, you can use deferred initialization:
var foo: Int
// Any statement here
if bar == 2 {
foo = 100
} else {
foo = 120
}
// Other statements here
myFunc(foo)
so you can declare a mutable variable, and initialize it anywhere in the same scope, but before using it the variable must be initialized.
Update: Since Swift 2.0, deferred initialization also works with immutables.

What are 'get' and 'set' in Swift?

I'm learning Swift and I'm reading The Swift Programming Language from Apple. I don't have any Objective-C background (only PHP, JavaScript, and others, but not Objective-C).
On page 24-25 I see this code:
//...Class definition stuff...
var perimeter: Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
}
//...Class continues...
This part is not specified in the book, and I can't get what those are for.
What are get and set?
The getting and setting of variables within classes refers to either retrieving ("getting") or altering ("setting") their contents.
Consider a variable members of a class family. Naturally, this variable would need to be an integer, since a family can never consist of two point something people.
So you would probably go ahead by defining the members variable like this:
class family {
var members: Int
}
This, however, will give people using this class the possibility to set the number of family members to something like 0 or 1. And since there is no such thing as a family of 1 or 0, this is quite unfortunate.
This is where the getters and setters come in. This way you can decide for yourself how variables can be altered and what values they can receive, as well as deciding what content they return.
Returning to our family class, let's make sure nobody can set the members value to anything less than 2:
class family {
var _members: Int = 2
var members: Int {
get {
return _members
}
set (newVal) {
if newVal >= 2 {
_members = newVal
} else {
println('error: cannot have family with less than 2 members')
}
}
}
}
Now we can access the members variable as before, by typing instanceOfFamily.members, and thanks to the setter function, we can also set it's value as before, by typing, for example: instanceOfFamily.members = 3. What has changed, however, is the fact that we cannot set this variable to anything smaller than 2 anymore.
Note the introduction of the _members variable, which is the actual variable to store the value that we set through the members setter function. The original members has now become a computed property, meaning that it only acts as an interface to deal with our actual variable.
A simple question should be followed by a short, simple and clear answer.
When we are getting a value of the property it fires its get{} part.
When we are setting a value to the property it fires its set{} part.
PS. When setting a value to the property, Swift automatically creates a constant named "newValue" = a value we are setting. After a constant "newValue" becomes accessible in the property's set{} part.
Example:
var A:Int = 0
var B:Int = 0
var C:Int {
get {return 1}
set {print("Recived new value", newValue, " and stored into 'B' ")
B = newValue
}
}
// When we are getting a value of C it fires get{} part of C property
A = C
A // Now A = 1
// When we are setting a value to C it fires set{} part of C property
C = 2
B // Now B = 2
You should look at Computed Properties.
In your code sample, perimeter is a property not backed up by a class variable. Instead its value is computed using the get method and stored via the set method - usually referred to as getter and setter.
When you use that property like this:
var cp = myClass.perimeter
you are invoking the code contained in the get code block, and when you use it like this:
myClass.perimeter = 5.0
You are invoking the code contained in the set code block, where newValue is automatically filled with the value provided at the right of the assignment operator.
Computed properties can be read/write if both a getter and a setter are specified, or read-only if the getter only is specified.
A variable declares and is called like this in a class:
class X {
var x: Int = 3
}
var y = X()
print("value of x is: ", y.x)
//value of x is: 3
Now you want the program to make the default value of x more than or equal to 3. Now take the hypothetical case if x is less than 3: your program will fail.
So, you want people to either put in 3 or more than 3. Swift got it easy for you and it is important to understand this bit - it is an advanced way of dating the variable value, because they will extensively use it in iOS development. Now let's see how get and set will be used here.
class X {
var _x: Int = 3
var x: Int {
get {
return _x
}
set(newVal) { // Set always take one argument
if newVal >= 3 {
_x = newVal // Updating _x with the input value by the user
print("new value is: ", _x)
}
else {
print("error must be greater than 3")
}
}
}
}
let y = X()
y.x = 1
print(y.x) // The error must be greater than 3
y.x = 8 // // The new value is: 8
If you still have doubts, just remember the use of get and set is to update any variable the way we want it to be updated. get and set will give you better control to rule your logic. It is a powerful tool, hence not easily understandable.