binary operator cannot be applied to operands - swift2

Recently, i am reading "functional programming in swift". In the book, the author does some extension of Int to meet a protocol Smaller. In order to get a thorough understanding of the author's idea, i copy the code to my own playground, but it reports error.
protocol Smaller {
static func smaller() -> Self?
}
extension Int: Smaller {
static func smaller() -> Int? {
//reporting error: Binary operator "==" cann't be applied to type of Int.type and Int
return self == 0 ? nil : self / 2
}
}
it seems that self == 0 is not allowed in the extension. Does anybody have an idea of the reason.

I don't think you wanted to use a static function as you need a instantiated integer to work on and check if it is smaller.
So there are 2 approaches:
Remove the static from the function and then call it normally:
let aInt = 4
aInt.smaller() //will be 2
or you change the signature of the static function to accept the instance as an argument
`
protocol Smaller {
static func smaller(selfToMakeSmall: Self) -> Self?
}
extension Int: Smaller {
static func smaller(selfToMakeSmall: Int) -> Int? {
//reporting error: Binary operator "==" cann't be applied to type of Int.type and Int
return selfToMakeSmall == 0 ? nil : selfToMakeSmall / 2
}
}
let theInt = 4
Int.smaller(theInt)
`
but I think this could be also improved with Generics

Related

Finding the type of a variable through static analysis? [duplicate]

This question already has an answer here:
Golang static identifier resolution
(1 answer)
Closed 4 months ago.
How can I determine the type of a variable through static analysis?
Suppose I have the following code:
func doSomething(x interface{}) {}
func main() {
p := Person()
doSomething(p)
}
And I want to analyze doSomething(person), is it possible to get the type of Person through static analysis?
What if there were multiple levels of assignment?
p1 := Person()
p2 := p1
doSomething(p2)
or
parent := Parent()
p := Parent.Child() // type Person
doSomething(p)
The use case is that I have a generic function that is commonly used throughout the (very large) codebase, and would like to introduce a new type safe version of this function. To do this, I hope to automatically determine the "type" of the function and refactor it accordingly:
// old
DB.InsertRow(person)
// new
Person.InsertRow(person)
Finding the type of an expression through static analysis is non-trivial, and sometimes not possible, for details see Golang static identifier resolution.
The use case is that I have a generic function that is commonly used throughout the (very large) codebase, and would like to introduce a new type safe version of this function. To do this, I hope to automatically determine the "type" of the function and refactor it accordingly:
// old
DB.InsertRow(person)
// new
Person.InsertRow(person)
Just for refactoring purposes, I don't think it is worth the hassle to implement it.
What you may do is change the signature of DB.InsertRow() temporarily to accept only a specific type such as int or your custom type you're sure is not used anywhere (e.g. type tempFoo struct{}).
To what end? Doing so, the compiler will do the hard work for you. You will see error messages showing exactly the types your codebase is trying to pass to DB.InsertRow(), so I'd say mission accomplished.
For example this code compiles:
func doSomething(x interface{}) {}
func main() {
doSomething(image.Pt(1, 2))
doSomething("abc")
doSomething(image.Rect) // image.Rect is a function which we don't call,
// so we're passing a value of a function type here
}
If we change doSomething():
func doSomething(x int) {}
We get the types we're seeking for from the compiler:
./prog.go:10:14: cannot use image.Pt(1, 2) (value of type image.Point) as type int in argument to doSomething
./prog.go:11:14: cannot use "abc" (untyped string constant) as int value in argument to doSomething
./prog.go:12:14: cannot use image.Rect (value of type func(x0 int, y0 int, x1 int, y1 int) image.Rectangle) as type int in argument to doSomething
Using the advice from Golang static identifier resolution to use golang.org/x/tools/go/types, I found that this was pretty straight forward to do with the golang.org/x/tools/go/analysis package, which has the types info available alongside the parsed ast.
This was my solution:
package rewriter
import (
"go/ast"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/ast/inspector"
)
func run(pass *analysis.Pass) (interface{}, error) {
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
nodeFilter := []ast.Node{
(*ast.CallExpr)(nil),
}
inspect.Nodes(nodeFilter, func(node ast.Node, push bool) bool {
callExpr, ok := node.(*ast.CallExpr)
if !ok {
return true
}
funcExpr, ok := callExpr.Fun.(*ast.SelectorExpr)
if !ok {
return true
}
// check method name
if funcExpr.Sel.Name != "doSomething" {
return true
}
for _, arg := range callExpr.Args {
// lookup type of the arg
argType := pass.TypesInfo.Types[arg].Type
if argType.String() == "*rewriter.Person" {
// do whatever you want here
}
}
return false
})
return nil, nil
}
One can augment this to look at the receiver of the method and add refactoring logic as needed (using analysis.Diagnostic).

golang comparing two structs that are implemented differently

I am new to go language, under learning. I have years OOP experience in C++. There is a stacker interface that is written in go and two implementations of it, one is slice base stack and another one is linkedlist base.
I find it is hard to compare two different structures and tell if they are containing the same data or not. The simple example code list below (notice a lot of functions/implementations are not listed because they are not relative with this question). The key function is stackEquals, I have tried different ways to approach it but they failed. Please see the comments in the code.
package main
import (
"fmt"
"errors"
)
// The interface is fixed, cannot be modified
type Stacker interface {
isEmpty() bool
size() int
push(x int)
peek() (int, error)
pop() (int, error)
copy() Stacker
}
type StackSlice struct {
slice []int
}
type StackLinked struct {
next *StackLinked
value int
// possible with other variables that is not relative
}
// There are interface function/method implementations did not paste
func (s StackSlice) String() string {
// return all the value inside the stack as string
// like [5 4]
}
func (s StackLinked) String() string {
// return all the value inside the stack as string
// like [5 4]]
}
// Pre-condition:
// none
// Post-condition:
// returns true if s and t have the same elements in the same order;
// both s and t have the same value after calling stackEquals as before
// Annoying constraint:
// Use only Stackers in the body of this functions: don't use arrays,
// slices, or any container other than a Stacker.
func stackEquals(s, t Stacker) bool {
// This implementation below always return false unless they are the same thing
return s == t
// I tried return s.String() == t.String() but gave an error said interface doesn't have String() method.
}
How can I compare two stacks that implemented in different way and tell if they are the same (same means same values in same order) in the stack.
If you need to compare two interfaces, you can only use the methods in that interface, so in this case, String does not exist in the interface (even though both of your implementations have it, the interface itself does not).
A possible implementation would be:
func stackEquals(s, t Stacker) bool {
// if they are the same object, return true
if s == t {
return true
}
// if they have different sizes or the next element is not the same,
// then they are different
if s.size() != t.size() || s.peek() != t.peek() {
return false
}
// they could be the same, so let's copy them so that we don't mess up
// the originals
ss = s.copy()
tt = t.copy()
// iterate through the values and check if each one is
// the same. If not, return false
for ; i, err := ss.pop(); err == nil {
if j, err := tt.pop(); err != nil || i != j {
return false
}
}
return true
}
This assumes that the only error pop would get is when there are no more values, otherwise you will need to do some better error checking and use isEmpty.

How to choose a random enumeration value

I am trying to randomly choose an enum value:
enum GeometryClassification {
case Circle
case Square
case Triangle
case GeometryClassificationMax
}
and the random selection:
let shapeGeometry = ( arc4random() % GeometryClassification.GeometryClassificationMax ) as GeometryClassification
but it fails.
I get errors like:
'GeometryClassification' is not convertible to 'UInt32'
How do I solve this?
In Swift there is actually a protocol for enums called CaseIterable that, if you add it to your enum, you can just reference all of the cases as a collection with .allCases as so:
enum GeometryClassification: CaseIterable {
case Circle
case Square
case Triangle
}
and then you can .allCases and then .randomElement() to get a random one
let randomGeometry = GeometryClassification.allCases.randomElement()!
The force unwrapping is required because there is a possibility of an enum having no cases and thus randomElement() would return nil.
Swift has gained new features since this answer was written that provide a much better solution — see "How to choose a random enumeration value" instead.
I'm not crazy about your last case there -- it seems like you're including .GeometryClassificationMax solely to enable random selection. You'll need to account for that extra case everywhere you use a switch statement, and it has no semantic value. Instead, a static method on the enum could determine the maximum value and return a random case, and would be much more understandable and maintainable.
enum GeometryClassification: UInt32 {
case Circle
case Square
case Triangle
private static let _count: GeometryClassification.RawValue = {
// find the maximum enum value
var maxValue: UInt32 = 0
while let _ = GeometryClassification(rawValue: maxValue) {
maxValue += 1
}
return maxValue
}()
static func randomGeometry() -> GeometryClassification {
// pick and return a new value
let rand = arc4random_uniform(_count)
return GeometryClassification(rawValue: rand)!
}
}
And you can now exhaust the enum in a switch statement:
switch GeometryClassification.randomGeometry() {
case .Circle:
println("Circle")
case .Square:
println("Square")
case .Triangle:
println("Triangle")
}
Since you're inside the enum class, having the random() method reference the highest value explicitly would eliminate having to count them every time:
enum GeometryClassification: UInt32 {
case Circle
case Square
case Triangle
static func random() -> GeometryClassification {
// Update as new enumerations are added
let maxValue = Triangle.rawValue
let rand = arc4random_uniform(maxValue+1)
return GeometryClassification(rawValue: rand)!
}
}
For Swift 5 there is "RandomNumberGenerator":
enum Weekday: CaseIterable {
case sunday, monday, tuesday, wednesday, thursday, friday, saturday
static func random<G: RandomNumberGenerator>(using generator: inout G) -> Weekday {
return Weekday.allCases.randomElement(using: &generator)!
}
static func random() -> Weekday {
var g = SystemRandomNumberGenerator()
return Weekday.random(using: &g)
}
}
You need to assign a raw type to your enum. If you use an integer type, then the enumeration case values will be auto-generated starting at 0:
enum GeometryClassification: UInt32 {
case Circle
case Square
case Triangle
case GeometryClassificationMax
}
Per Enumerations:
"Unlike C and Objective-C, Swift enumeration members are not assigned a default integer value when they are created."
Specifying the integer type lets it know to generate the values in the usual way.
Then you can generate the random value like this:
let randomEnum: GeometryClassification = GeometryClassification.fromRaw(arc4random_uniform(GeometryClassification.GeometryClassificationMax.toRaw()))!
This is a horribly ugly call, and all those fromRaw and toRaw calls are fairly inelegant, so I would really recommend generating a random UInt32 that is in the range you want first, then creating a GeometryClassification from that value:
GeometryClassification.fromRaw(someRandomUInt32)
You can put all the values into array and generate random,
extension GeometryClassification {
static func random() -> GeometryClassification {
let all: [GeometryClassification] = [.Circle,
.Square,
.Triangle,
.GeometryClassificationMax]
let randomIndex = Int(arc4random()) % all.count
return all[randomIndex]
}
}
The easiest thing to do is to create a global extension:
extension CaseIterable {
static func randomElement() -> AllCases.Element {
guard Self.allCases.count > 0 else {
fatalError("There must be at least one case in the enum")
}
return Self.allCases.randomElement()!
}
}
This way any enum which conforms to CaseIterable has the function automatically
Here's my Swift 1.2 take:
enum GeometryClassification : Int {
case Circle = 0
case Square = 1
case Triangle = 2
static func random() -> GeometryClassification {
let min = MutationType.Circle.rawValue
let max = MutationType.Triangle.rawValue
let rand = Int.random(min: min, max: max) // Uses ExSwift!
return self(rawValue: rand)!
}
}
I wrote a global extension using Andy's answer. Enjoy :)
extension CaseIterable {
static func random<G: RandomNumberGenerator>(using generator: inout G) -> Self.AllCases.Element {
return Self.allCases.randomElement(using: &generator)!
}
static func random() -> Self.AllCases.Element {
var g = SystemRandomNumberGenerator()
return Self.random(using: &g)
}
}
Just extend your enumeration to conform CaseIterable protocol and use like:
let state = YourEnum.random()

How to get an enumeration's value's value?

In Apple's "A swift Tour" they have this code snippet:
enum OptionalValue<T> {
case None
case Some(T)
}
var possibleInteger: OptionalValue<Int> = .None
possibleInteger = .Some(100)
How would you get the 100? You can't do possibleInteger == 100 to test if possibleInteger has the value 100 inside. I know you can put functions inside enumerations, but you can't have variables. Maybe I'm understanding enumerations wrong…
If I command click Optional when declaring an optional (var x:Optional<Int>), I can find
enum Optional<T> : Reflectable, NilLiteralConvertible {
case None
case Some(T)
init()
init(_ some: T)
/// Haskell's fmap, which was mis-named
func map<U>(f: (T) -> U) -> U?
func getMirror() -> MirrorType
static func convertFromNilLiteral() -> T?
}
But I do not understand what any of that means. Help?
You can use a switch statement to get the value, as described here. Relevant bit:
... the associated values can be extracted as part of the switch
statement. You extract each associated value as a constant (with the
let prefix) or a variable (with the var prefix) for use within the
switch case’s body:
For your case, you'd want something like:
switch possibleInteger {
case .Some(let value):
println(value)
case .None:
println("<None>")
}

The Swift Programming Language Enumerations Experiment

I'm making my way through The Swift Programming Language book, but I'm stuck on an experiment.
I'm given this code:
enum Rank: Int {
case Ace = 1
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King
func simpleDescription() -> String {
switch self {
case .Ace:
return "Ace"
case .Jack:
return "Jack"
case .Queen:
return "Queen"
case .King:
return "King"
default:
return String(self.toRaw())
}
}
}
For the experiment, I have to "Write a function that compares two Rank values by comparing their raw values.
I had a go:
func rankCompare(first: String, second: String) -> String {
let firstRank = Rank.first
}
But I ended up with errors because I don't know how to pass Enum values.
Can someone help?
Enum values can be passed just like other types. The following function is part of the Rank enum and compares one Rank to another.
func compareToOther(other:Rank) -> Bool { // other is of type Rank
return self.toRaw() == other.toRaw()
}
Here is a screenshot of the quick implementation and usage.
You can pass enums by just passing the enum name:
// someRank is a Rank enum value
func myFunction (someRank: Rank) -> () {
}
And then you can just call it:
myFunction(Rank.Ace)
I am also a beginner, but this is how I worked throughout the experiment. First I added this;
func compareTwoCards(card1: Rank, card2: Rank) -> String {
if card1.toRaw() == card2.toRaw() {
return "Cards are equal"
} else {
if card1.toRaw() > card2.toRaw() {
return "Card1 is greater"
} else {
return "Card2 is greater"
}
} }
Then I created two Rank objects
let ace = Rank.Ace
let queen = Rank.Queen
Finally, I called it three different ways to test it;
compareTwoCardsTake2(ace, queen)
compareTwoCardsTake2(queen, ace)
compareTwoCardsTake2(ace, ace)
Can some one with more experience please reply if there is a better/more elegant way of performing the compare?
I solved it like this:
func rankCompare(first: Rank, second: Rank) -> String {
if(first.rawValue > second.rawValue) {
return "\(first.simpleDescription()) beats \(second.simpleDescription())."
}
else if second.rawValue > first.rawValue {
return "\(second.simpleDescription()) beats \(first.simpleDescription())."
}
else {
return "\(first.simpleDescription()) equals \(second.simpleDescription())."
}
}
let king = Rank.King
let queen = Rank.Queen
let seven = Rank.Seven
rankCompare(king, queen)
rankCompare(seven, king)
rankCompare(queen, queen)
Use .rawValue for doing the comparisons and .simpleDescription() for writing out your answer.
This code can be used to determine if two enumeration values are equal or not. .toRaw() is obsolete, so .rawValue must be used to obtain the raw value for comparison. An edited version of this function (to make a full comparison with type string information, not just "true" or "false") should be used to complete the exercise. Hint For Editing: this function is of type Bool.
func compareRanks(rankA: Rank, rankB: Rank) -> Bool {
return rankA.rawValue == rankB.rawValue
}
To see the code and contributors that made this answer possible, please see the question: Explanation of The Swift Programming Language Enumerations Experiment

Resources