воскресенье, 5 июля 2020 г.

Swift, Access Control

Online Swift Playground 

- private
- fileprivate
- internal (default)
- public
- open

//weapon.swift
public protocol Weapon {
    var ammo: Int {get}
}

//gun.swift
internal class Gun: Weapon {
    private(set) var ammo: Int
    fileprivate(set) var isEmpty: Bool

    init(ammo: Int = 3){
        self.ammo = ammo
        self.isEmpty = false
    }

    func fire() {
        guard self.ammo > 0 else {
            print("Out of ammo!")
            self.isEmpty = true
            return
        }
        self.ammo -= 1
        print("Fire!")
    }

    func reload(ammo: Int = 3){
        self.ammo = ammo
        print("Reloading!")
        self.isEmpty = false
    }
}

//main.swift
var g1 = Gun()
print("ammo: \(g1.ammo)")
while !g1.isEmpty {
    g1.fire()
}
//g1.ammo = 3 //error
g1.reload()
print("ammo: \(g1.ammo)")

четверг, 2 июля 2020 г.

Swift, Generics, Constraints

Online Swift Playground 

//Generics
func add<T: AdditiveArithmetic>(a: T, b: T) -> T {
    return a + b
}
let sum = add(a: 5, b: 5)
print("5 + 5 = \(sum)")

class Point<T>{
    var x:T
    var y:T

    init(x:T, y:T){
        self.x = x
        self.y = y
    }
}

let p1 = Point<Int>(x: 1, y: 2)
let p2: Point<Float> = Point(x: 1.0, y: 2.0)
let p3 = Point(x: 1.0, y: 2.0)
print(p3)

//Constraints
protocol Shape{
    func area() -> Double
}

class Rect: Shape{
    var w: Double
    var h: Double

    init(w:Double, h: Double){
        self.w = w
        self.h = h
    }

    func area() -> Double {
        w * h
    }
}

class Figures<T: Shape>{
    var figures: [T]

    init(figures: [T]){
        self.figures = figures
    }
}

extension Array where Element: Rect {
    func area(){
        forEach { print("area: \($0.area())")}
    }
}

let arr1 = [Rect(w:1, h:1), Rect(w:2, h:2)]
let fig1 = Figures(figures: arr1)
fig1.figures.area()

//associatedtype
protocol Drawable {
    associatedtype Sprite where Sprite: Rect
    func draw(sprite: Sprite)
}

//conditional
protocol Updatable{
    func update()
}

extension Int: Updatable{
    func update(){
        print("update")
    }
}

extension Array: Updatable where Element: Updatable {
    func update(){
        forEach { $0.update()}
    }
}

let arr2 = [1, 2, 3]
1.update()
arr2[0].update()
arr2.update() //x3

//Array
let arr0 = [1, 2, 3] //inference
let arr3: [Int] = [1, 2, 3] //sugar
let arr4 = [Int]() //sugar
let arr5: Array<Int> = [1, 2, 3] //generic
let arr6 = Array<Int>() //generic

//Dictionaries
let dic0 = [1 : "Mike", 2 : "Tom"] //inference
let dic1: [Int : String] = [1 : "Mike", 2 : "Tom"] //sugar
let dic2: [Int : String] = [ : ] //sugar
let dic3: Dictionary<Int, String> = [1 : "Mike", 2 : "Tom"] //generic

//Optionals
enum Optional<T> {
    case some(T)
    case none
}

var op1: Optional<Int> = Optional.some(5)
var op2 = Optional<Int>.some(5)
var op3 = Optional.some(5)
//if op3 == Optional<Int>.none{print("nil")}

var op4: Int? = 5
if op4 == nil {print("nil")}

Swift, Protocols, Standard Library

Online Swift Playground 

//Equatable
struct Point{
    var x: Int
    var y: Int
}

extension Point: Equatable {
    static func ==(lhs: Point, rhs: Point) -> Bool {
        lhs.x == rhs.x && lhs.y == rhs.y
    }
}

var p1 = Point(x:1, y:1)
var p2 = p1
print("p1 equal p2: \(p1 == p2)")

//Comparable
extension Point: Comparable {
    static func <(lhs: Point, rhs: Point) -> Bool {
        if lhs.x == rhs.x {
        return lhs.y < rhs.y
        }
        return lhs.x < rhs.x
    }
}

var p3 = Point(x:3, y:3)
print("max: \(p1 < p3 ? p3 : p1)")

var p4 = Point(x:4, y:4)
var p5 = Point(x:5, y:5)

var pArr = [p5, p2, p1, p4, p3]
print(pArr)
pArr.sort()
print(pArr)
print(pArr.max()!)
print(pArr.min()!)
print(pArr.contains(p1))
print(pArr.starts(with: [p1, p2]))
pArr.reverse()
print(pArr)

//Hashable
class Person: Hashable{
    let name: String

    init(name: String){
        self.name = name
    }

    static func ==(lhs: Person, rhs: Person) -> Bool {
        lhs.name == rhs.name
    }
  
    func hash(into hasher: inout Hasher) {
        hasher.combine(name)
    }
}

let person = Person(name: "Mike")
let dic1 = [person: "1973"]
print(dic1)

//CustomStringConvertible, CustomDebugStringConvertible
extension Person: CustomStringConvertible {
    var description: String {
        "\(name)"
    }
}
print(dic1)

extension Person: CustomDebugStringConvertible {
    var debugDescription: String {
        "Person: \(name)"
    }
}
debugPrint(dic1)

среда, 1 июля 2020 г.

Swift, Protocols (interfaces)

Online Swift Playground 

//Protocols - value types (structs and enums) OR reference types (classes)
protocol Drawable {
    var image: String {get set}
    init?(image: String)
    func draw()
}

protocol Transform {
    associatedtype PosType
    var position: PosType {get set}
}

protocol Movable: Transform {
    var speed: Double {get set}
    func move(speed: Double)
}

class Sprite: Drawable, Movable{
    //typealias PosType = (x: Double, y: Double)
    var position: (x: Double, y: Double)
    var image: String
    var speed: Double = 0

    required init?(image: String){
        guard image != "" else {
            return nil
        }
        self.image = image
        self.position = (x:0, y:0)
    }

    func draw() {
        print("sprite: \(image)")
    }

    func move(speed: Double){
        self.speed = speed
        self.position.x += speed
        self.position.y += speed
        print("speed: \(self.speed)")
    }
}

var s1 = Sprite(image: "image.png")!
s1.draw()
s1.move(speed: 2.4)
print("position: \(s1.position)")

var drawType: Drawable.Type = Sprite.self
print(drawType)
let d1 = drawType.init(image: "image1.png")
d1?.draw()

var s2 = Sprite(image: "image2.png")!
var s3 = Sprite(image: "image3.png")!

let sprites:[Drawable] = [s1, s2, s3]

for sprite in sprites{
    sprite.draw()
}

//extensions, composition
protocol Sizable{
    var size: Double{get}
}

extension Sprite: Sizable{
    var size: Double { 1.0 }
}

func render(sprite: Drawable & Sizable){
     sprite.draw()
     print("size: \(sprite.size)")
}
render(sprite: s1)

//value types
protocol Weightable{
    var weight: Int {get set}
}

struct Box: Weightable{
    var size: String = "big"
    var weight: Int = 1
}

var sp1: Weightable = Box()
print(sp1.weight)
print((sp1 as! Box).size)
var sp2 = sp1 //copy
sp2.weight = 2
print(sp1.weight)
print(sp2.weight)

//ref types - only for classes
protocol RefWeightable: class{
    var weight: Int {get set}
}

//...

понедельник, 29 июня 2020 г.

Swift, Enumerations, Result

Online Swift Playground 

//enumeration - value type
import Foundation

enum Week: String {
    case monday = "first"
    case tuesday = "second"
    case wednesday = "third"
    case thursday = "forth"
    case friday = "fifth"
    case saturday = "sixth"
    case sunday = "seventh"

    var weekPart: String {
        switch self{
        case .monday, .tuesday, .wednesday, .thursday, .friday:
            return "workday \(rawValue) day"
        case .saturday, .sunday:
            return "weekend \(rawValue) day"
        }
    }
}

enum Workdays: Int, CaseIterable {
    case monday = 1, tuesday, wednesday, thursday, friday

    var daysUntilWeekend: Int {
        return 5 - self.rawValue
    }

    static func daysUntilWeekend(day: Self) -> Int{
        return 5 - day.rawValue
    }
}

func weekPart(for day: Week) -> String {
    switch day{
        case .monday, .tuesday, .wednesday, .thursday, .friday:
            return "workday"
        case .saturday, .sunday:
            return "weekend"
    }
}

print(Week.monday)
print(Week.friday.rawValue)
print(Week(rawValue: "fifth")!)
print(Workdays.friday.rawValue)
print(Workdays.thursday.daysUntilWeekend)
print(Workdays.daysUntilWeekend(day: Workdays.thursday))
print(weekPart(for: Week.monday))
print(Week.sunday.weekPart)


for day in Workdays.allCases{
    print(day)
}

//Result
enum intResult {
    case OK(_: Int)
    case Err(_: String)
}

func check(num: Int) -> intResult{
    if num <= 10 {
        return .OK(num)
    }else{
        return .Err("error message")
    }
}

let result = check(num: 5)
switch result {
    case .OK(let num):
        print(num)
    case .Err(let message):
        print(message)
}

func check2(res: intResult) -> Int{
    guard case .OK(let num) = res else { fatalError("error")}
    return num
}
print(check2(res: result))

//init
enum initCase{
    case on, off
    init(){
        self = .off
    }
}
var e1 = initCase()
print(e1)
e1 = initCase.on
print(e1)

enum noCase{
    static func hi(){
        print("no instance!")
    }
}
//var e2 = noCase() //error
noCase.hi()

//Optional
enum intOpt {
    case Some(_: Int)
    case None(_: Void)
}
var o1 = intOpt.Some(5)
print(o1)
o1 = intOpt.None(())
print(o1)
switch o1 {
    case .Some(let x):
        print(x)
    case .None(()):
        print("nil")
}

воскресенье, 28 июня 2020 г.

Swift, Classes, Polymorphism

Online Swift Playground 
 
//Classes (Reference type)
import Foundation

class Person {
    var firstName: String
    var lastName: String

    init(fName: String, lName: String){
        self.firstName = fName
        self.lastName = lName
    }

    func fullName() -> String {
        "Name: " + firstName + " " + lastName
    }
}

class Student: Person {
    var university: String
    //selfrefs - retain cycle problem!
    weak var friend: Student?

    required init(fName: String, lName: String, univer: String){
        self.university = univer
        super.init(fName: fName, lName: lName)
    }

    override func fullName() -> String {
        super.fullName() + ", university: " + university
    }
}

final class Employee: Person {
    var company: String

    init(fName: String, lName: String, comp: String){
        self.company = comp
        super.init(fName: fName, lName: lName)
    }

    deinit{
        print("freeing memory")
    }

    convenience init(another: Employee){
        self.init(fName: another.firstName, lName: another.lastName, comp: another.company)
    }

    override func fullName() -> String {
        super.fullName() + ", company: " + company
    }
}

let p1 = Person(fName: "Mike", lName: "Mikov")
let s1 = Student(fName: "Tom", lName: "Tomov", univer: "Oxford")
var e1 = Employee(fName: "Artem", lName: "Artemov", comp: "Toyota")
var e2 = Employee(another: e1)

//Type check - is
var persons: [Person] = [p1, s1, e1, e2]
for person in persons{
    switch (person){
        case is Student:
            print("student")
        case is Employee:
            print("employee")
        default:
            print("person")
    }
}

//Casting - as, as?, as!
func infoAbout(_ person: Person){
    if let _ = person as? Student {
        print(person.fullName() + " -> this is a Student subclass")
    } else if let _ = person as? Employee {
        print(person.fullName() + " -> this is an Employee subclass")
    } else {
        print(person.fullName() + " -> this is a Person superclass")
    }
}

infoAbout(p1)
infoAbout(s1)
infoAbout(e1)
infoAbout(e2)

//destructing e2
e2 = e1
persons[3] = e1

четверг, 25 июня 2020 г.

понедельник, 22 июня 2020 г.

Swift, Structures, Methods

Online Swift Playground 

//Structures (Value type)
struct Person {
    private var name: String
    private var age: Int

    // var name: String = "Ivan Ivanov"
    // var age: Int = 32

    // private init() {
    //     self.name = "Ivan Ivanov"
    //     self.age = 32
    // }

    init(name: String = "Ivan Ivanov", age: Int = 32) {
        self.name = name
        self.age = age
    }

    mutating func clear(){
        self.name = ""
        self.age = 0
    }

    static func clear(person: inout Self){
        person.name = ""
        person.age = 0
    }

    func isEmpty() -> Bool{
        if self.name == "" && self.age == 0 {
            return true
        } else {
            return false
        }
    }

    static func update(person: Self) -> Self{
        let newPerson = Person(name: person.name, age: person.age + 1)
        return newPerson
    }
}

var p1 = Person()
print(p1)
Person.clear(person: &p1)
print(p1)
p1 = Person(name: "Petr Petrov")
print(p1)
p1 = Person(age: 42)
print(p1)
p1 = Person(name: "Petr Petrov", age: 42)
print(p1)
var p2 = Person.update(person: p1)
print(p2)
p2.clear()
print(p2.isEmpty())

extension Person {
    // init(name: String, age: Int) {
    //     self.name = name
    //     self.age = age
    // }

    static func defPerson() -> Self{
        let defPerson = Person(name: "Ivan Ivanov", age: 32)
        return defPerson
    }
}

var p3 = Person.defPerson()
print(p3)

вторник, 16 июня 2020 г.

Swift, Structures, Properties

Online Swift Playground 

//Structures (Value type)
import Foundation

struct Point {
    var x: Int
    var y: Int
}

struct Line: CustomStringConvertible {
    var start: Point
    var end: Point
    var description: String {
        """
        Line [
            start: Point(x: \(start.x), y: \(start.y))
            end: Point(x: \(end.x), y: \(end.y))
        ]\n
        """
    }

    func length() -> Double{
        let X = Double(start.x - end.x)
        let Y = Double(start.y - end.y)
        return (X * X + Y * Y).squareRoot()
    }
}

let p1 = Point(x: 1, y: 1)
let p2 = Point(x: 5, y: 5)
var l1 = Line(start: p1, end: p2)
print("length of line: \(l1.length())\n")

var l2 = l1 //copy on assignment
l2.start.x = 3; l2.start.y = 3
l2.end.x = 8; l2.end.y = 8
print(l1)
print(l2)

//Stored properties
struct Contact {
    var name: String //mutable
    let email: String //immutable (const)
    var nation = "Z" //default value
}

var person1 = Contact(name: "Ivan Ivanov", email: "ivan@ivanov.com")
person1.name = "Petr Petrov"
//person1.email = "petr@petrov.com" // error
print("\nName: \(person1.name) \nEmail: \(person1.email) \nNation: \(person1.nation) \n")

var person2 = Contact(name: "Petr Petrov", email: "petr@petrov.com", nation: "alive")
print("\nName: \(person2.name) \nEmail: \(person2.email) \nNation: \(person2.nation) \n")

//Computed properties
import Foundation

struct Line {
    var start: (x: Int, y: Int)
    var end: (x: Int, y: Int)

    var length: Double { //read only by def
        let X = Double(start.x - end.x)
        let Y = Double(start.y - end.y)
        return (X * X + Y * Y).squareRoot().rounded()
    }
}

var line1 = Line(start: (x: 1, y: 1), end: (x: 5, y: 5))
print("length of the line: \(line1.length)")

//Getters and Setters
struct Person {
    var name: String
    var surname: String
    var age: Int

    var fullName: String {
        get {
            return name + " " + surname
        }
        set {
            let arr = newValue.split(separator: " ")
            name = String(arr[0])
            surname = String(arr[1])
        }
    }
}

var person1 = Person(name: "Ivan", surname: "Ivanov", age: 42)
print(person1.fullName)
person1.fullName = "Petr Petrov"
print(person1)

//Type properties (static)
struct TeamMember {
    static var memberCount: Int = 0
    let name: String
    let role: String
}

let tm1 = TeamMember(name: "Mike", role: "Artist")
TeamMember.memberCount += 1
let tm2 = TeamMember(name: "Tom", role: "Manager")
TeamMember.memberCount += 1
print(TeamMember.memberCount) //2

//Property observers
struct TeamMember {
    static var memberCount: Int = 0
    let name: String
    let role: String
    var active: Bool = false {
        didSet {
            if active {
                Self.memberCount += 1
            } else if Self.memberCount > 0 {
                Self.memberCount -= 1
            }
        }
    }
}

var tm1 = TeamMember(name: "Mike", role: "Artist")
tm1.active = true
var tm2 = TeamMember(name: "Tom", role: "Manager")
tm2.active = true
print(TeamMember.memberCount) //2
tm2.active = false
print(TeamMember.memberCount) //1

//Limiting a variable
struct Lamp {
    var on: Bool = false
    var maxWat: Int = 0 {
        didSet {
            if maxWat <= 35 && maxWat > 0{
                on = true
            }else if maxWat == 0 {
                on = false
            }else{
                maxWat = oldValue
            }
        }
    }

}

var l1 = Lamp()
print(l1)
l1.maxWat = 50
print(l1)

//Lazy properties
import Foundation

struct Line {
    var start: (x: Int, y: Int)
    var end: (x: Int, y: Int)

    lazy var length: Double = {
        let X = Double(start.x - end.x)
        let Y = Double(start.y - end.y)
        return (X * X + Y * Y).squareRoot()
    }()

    var middle: Double {
        mutating get {
            length / 2
        }
    }
}

var line1 = Line(start: (x: 1, y: 1), end: (x: 5, y: 5))
print("middle of the line: \(line1.middle)")

воскресенье, 14 июня 2020 г.

Swift, Strings, Characters

Online Swift Playground

//Strings
let str = "Swift"
for ch in str.unicodeScalars {
    print("char: \(ch), unicode: \(ch.value)")
}
print("chars count: \(str.count)")
print("reversed: \(String(str.reversed()))")
print(str.uppercased())
print(str.lowercased())

print("first: \(str[str.startIndex])")
print("second: \(str[str.index(str.startIndex, offsetBy: 1)])")
print("last: \(str[str.index(before: str.endIndex)])")

//strings equality
print("\"Swift\" == \"swift\":", str == "swift")

//Substrings
let str1 = "Swift is cool"
print("substr: \(str1[str1.startIndex ..< str1.firstIndex(of: " ")!])")
print("substr: \(str1[..<str1.firstIndex(of: " ")!])")
print("substr: \(str1[str1.index(after: str1.firstIndex(of: " ")!)...])")

//Split
print("split: \(str1.split() {$0 == " "})")
print(str1.split(separator: " "))
print(str1.components(separatedBy: " "))

//Chars
let ch1:Character = "5"
print("isASCII: \(ch1.isASCII)")
print("isLetter: \(ch1.isLetter)")
print("isWhitespace: \(ch1.isWhitespace)")
print("isNumber: \(ch1.isNumber)")
print("isWholeNumber: \(ch1.isWholeNumber)")
print("wholeNumberValue: \(ch1.wholeNumberValue)")

среда, 10 июня 2020 г.

Swift, Collections, Closures

Online Swift Playground  

//Array
var arr0 = [Int]()
let arr1 = [1,2,3]
print("arr1: \(arr1)")

let arr2 = Array(repeating: 0, count: 3)
print("arr2.count: \(arr2.count)")

var arr3:[String] = []
print("arr3.isEmpty: \(arr3.isEmpty)")
arr3.append("a")
arr3.append("b")
arr3 += ["c", "d"]
print("arr3: \(arr3)")

print("first: \(arr3[0])")
print("slice: \(arr3[1...2])")
print("first: \(arr3.first!)")
print("last: \(arr3.last!)")
print("min: \(arr3.min()!)")
print("max: \(arr3.max()!)")

let arr4 = Array(arr1[1...2])
print("arr4: \(arr4)")
print("arr4 has 2: \(arr4.contains(2))")
print("slice has b: \(arr3[1...2].contains("b"))")

let str1 = "Swift is cool"
print("split: \(str1.split() {$0 == " "})")

var arr5 = [2,1,3]
arr5.sort()
print("sort <: \(arr5)")
arr5.sort(by: >)
print("sort >: \(arr5)")
arr5.insert(0, at: 0)
print("arr5: \(arr5)")
let x = arr5.removeLast()
print("\(x) was removed from arr5: \(arr5)")
arr5.remove(at: 1)
print("arr5: \(arr5)")
print("index of 2 is: \(arr5.firstIndex(of: 2)!)")
arr5[1] = 1
print("arr5: \(arr5)")
arr5[0...1] = [1, 2, 3]
print("arr5: \(arr5)")
arr5.insert(arr5.remove(at: 2), at: 0)
print("arr5: \(arr5)")
arr5.swapAt(1, 2)
print("arr5: \(arr5)")
let arr6 = arr5.sorted()
print("old arr5: \(arr5)")
print("new arr6: \(arr6)")
print(Array(arr5.reversed()))

for i in arr6{
    print(i)
}

for (idx, item) in arr6.enumerated() {
    print("[\(idx)] - \(item)")
}

func sum(in arr: [Int]) -> Int {
    var sum = 0
    for num in arr {
        sum += num
    }
    return sum
}
print("sum: \(sum(in: arr6))")

//Dictionary
var dic1 = ["Mike":1993, "Tom":1998]
print(dic1)

var dic2:[String: Int] = [:]
dic2.reserveCapacity(10)
print(dic2)

print(dic1["Mike"]!)
print(dic1.count)
print(dic2.isEmpty)

var dic0:[Character:Int] = [:]
var l = dic0["a", default: 0]
print(l) //0

//add pair or modify value
let old:Int? = dic1.updateValue(2000, forKey: "Mike")
print("old value: \(old!)")
dic1["Tom"] = 1999
print(dic1)

//remove pair
dic1.removeValue(forKey: "Tom")
print(dic1)
dic1["Mike"] = nil
print(dic1)

let dic3 = ["name":"Mike", "age":"43"]
for (key, value) in dic3 {
    print("key: \(key) - value: \(value)")
}
print("keys: ", terminator: "")
for key in dic3.keys{
    print("\(key), ", terminator: "") // no newline
}
print() // newline
print("values: ", terminator: "")
for value in dic3.values{
    print("\(value), ", terminator: "")
}

//Set
var set1: Set<Int> = [1, 2, 3]
print(set1)
let arr:[Int] = [4, 5, 6, 6, 6]
var set2 = Set(arr)
print(set2)
print(set2.contains(4))
set1.insert(0)
print(set1)
let x = set1.remove(3)
print(x!)
print(set1)

//Closures
var cl1 = { (a: Int, b: Int) -> Int in
    return a + b
}
print(cl1(4, 2))

var cl2 = { (a: Int, b: Int) -> Int in
    a - b
}
print(cl2(4, 2))

var cl3: (Int, Int) -> Int = { (a, b) in
    a * b
}
print(cl3(4, 2))

var cl4: (Int, Int) -> Int = {
    $0 / $1
}
print(cl4(4, 2))

func foo(a: Int, b: Int, cl: (Int, Int) -> Int) -> Int{
    cl(a, b)
}
print(foo(a:4, b:2, cl:cl1))
print(foo(a:4, b:2, cl:cl2))
print(foo(a:4, b:2, cl:cl3))
print(foo(a:4, b:2, cl:cl4))

print(foo(a:4, b:2, cl:{(a:Int, b:Int) -> Int in return a + b}))
print(foo(a:4, b:2, cl:{(a:Int, b:Int) -> Int in a - b}))
print(foo(a:4, b:2, cl:{(a, b) in a * b}))
print(foo(a:4, b:2, cl:{$0 / $1}))

print(foo(a:4, b:2, cl: +))
print(foo(a:4, b:2, cl: -))
print(foo(a:4, b:2, cl: *))
print(foo(a:4, b:2, cl: /))

print(foo(a:4, b:2) {(a:Int, b:Int) -> Int in return a + b})
print(foo(a:4, b:2) {(a:Int, b:Int) -> Int in a - b})
print(foo(a:4, b:2) {(a, b) in a * b})
print(foo(a:4, b:2) {$0 / $1})

//Capturing
let str = "Hi!"
var cl5: () -> Void = {
   print(str)
}
cl5()

var i = 0
let cl6 = {
    i += 1
}
cl6()
cl6()
print("i = \(i)")

func foo() -> () -> Int {
    var i = 0
    let cl7: () -> Int = {
        i += 1
        return i
    }
    return cl7
}
let j = foo()
print(j())
print(j())

//Sorting
let arr = ["00000", "22", "1", "4444", "333"]
let arr1 = arr.sorted {$0.count > $1.count}
print(arr1)

//Functional
let arr1 = [1, 2, 3, 4, 5, 6]
arr1.forEach {
    print("\($0): \($0*$0)")
}

let arr2 = arr1.filter {
    $0 > 3
}
print(arr2)

let i = arr1.first {
    $0 < 3
}
print(i!)

let arr3 = arr1.map {
    $0 * 2
}
print(arr3)

let arr4 = ["a", "1", "c", "2"]
let arr5:[Int?] = arr4.map {
    Int($0)
}
print(arr5)
let arr6 = arr4.compactMap {
    Int($0)
}
print(arr6)

let sum = arr1.reduce(0) {
    $0 + $1
} //0+1,1+2,3+3,...=21
print(sum)

let dic1 = [100: 2, 50: 3, 200: 2]
let sum2 = dic1.reduce(0) {
    $0 + $1.key * $1.value
} //0+100*2,200+50*3,...=750
print(sum2)

let arr8 = dic1.reduce(into: []) {
    (result, this: (key: Int, value: Int)) in
    for _ in 0 ..< this.value {
        result.append(this.key)
    }
} //[200, 200, 100, 100, 50, 50, 50]
print(arr8)

let nums = [1, 2, 3, 4, 5]
let str = nums
    .filter{
        $0 < 4
    }
    .map{
        String($0)
    }
    .reduce("") {
        $0 + $1
    }
print(str) //"123"
 
var dic11 = ["A":1, "B":2, "C":3]
var arr11 = dic11.map {$0.value}
arr11.sort()
print(arr11) //[1, 2, 3]

var arr9 = [1, 2, 3, 4]
print(arr9.dropFirst())
print(arr9.dropFirst(2))
print(arr9.dropLast())
print(arr9.dropLast(2))
print(arr9.prefix(2))
print(arr9.suffix(2))
arr9.removeAll(where: {$0 >= 3})
print(arr9)
arr9.removeAll()

//Lazy
let first5even = (1...).lazy.filter{$0 % 2 == 0}.prefix(5)
first5even.forEach{print($0)}

воскресенье, 7 июня 2020 г.

Swift, Classes, Inheritance

Online Swift Playground 
 
//Classes (Reference type)
class Point: CustomStringConvertible{
    var x:Int
    var y:Int

    init(x:Int, y:Int){
        self.x = x
        self.y = y
    }

    var description: String {
        "Point [x: \(self.x), y: \(self.y)]"
    }
}

var p1 = Point(x: 1, y: 1)
var p2 = p1 //refs on assignment
print(p1)
print(p2)

p1.x = 3; p1.y = 3
p2.x = 8; p2.y = 8
print(p1)
print(p2)

//equality
print(p1.x == p2.x) //values
print(p1 === p2) //pointers

extension Point {
    func sub(p:Point){
        self.x -= p.x
        self.y -= p.y
    }
}

p2.sub(p: p1)
print(p2)
  
//Properties, Methods
class Point{
    //Properties
    var x:Int
    var y:Int
 
    //Initializer - constructor
    init(x:Int, y:Int) {
        self.x = x
        self.y = y
    }

    //Method
    func add(p:Point){
        self.x += p.x
        self.y += p.y
    }
}
   
var p1 = Point(x:5,y:5)
print(p1.x, p1.y)

var p2 = Point(x:5,y:5)
p1.add(p:p2)
print(p1.x, p1.y)

//Inheritance
class Character{
    private var name:String = ""
       
    internal init(name:String){
        self.name = name
    }

    public func getName() -> String {
        self.name
    }

    public func hi() -> String {
        " "
    }
}

final class Hero: Character{
    private var health:Int = 0

    public init(name:String, health:Int){
        //super init after self init!!!
        self.health = health
        super.init(name: name)
    }

    public func getHealth() -> Int {
        self.health
    }

    override func hi() -> String {
        "Hi there"
    }
}

let char = Hero(name:"Mike", health:3)
print("\(char.hi()), I'm \(char.getName()) with \(char.getHealth()) lives")

Swift, Functions, Optionals

Online Swift Playground 

//Functions
func greetings() {
    print("Hi!")
}
greetings()

func greetingsName(name str: String) {
    print("Hi " + str + "!")
}
greetingsName(name: "Mike")

func areaOfRect(_ w: Int = 1, h: Int = 1) -> Int {
    let area = w * h
    return area
}
let theArea = areaOfRect(5, h: 5)
print("area =", theArea)
print("default parameters", areaOfRect())

func greet(name: String) -> String {
    "Hi " + name + "!"
}
print(greet(name: "Mike"))

func rettup() -> (Int, Int) {
    let x = 5
    return(x, x)
}
print(rettup().0, rettup().1)

func notret() -> Never {
   //infinite
}

//Pass by value
func foo(value: Int) {
    value += 1  //error
    print("in foo +1: \(value)")
}

//Pass by ref
func foo(value: inout Int) {
    value += 1
    print("in foo +1: \(value)")
}

var x:Int  = 5
print("before foo: \(x)")
foo(value: &x)
print("after foo: \(x)")

//Overloading
func get() -> Int {
    42
}
func get() -> String {
    "str"
}
let valInt: Int = get()
let valStr: String = get()
print(valInt, valStr)

//Function pointer
func add(_ a: Int, _ b: Int) -> Int{
    a + b
}
func sub(_ a: Int, _ b: Int) -> Int{
    a - b
}
func foo(_ fn: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print(fn(a, b))
}
foo(add, 5, 2)
foo(sub, 5, 2)

//Doxygen
/// Calculates the sum of two values
/// - Parameters:
///    - a: The first value.
///    - b: The second value.
/// - Returns: The sum of the two values.

//Optional
var x: Int?
x = 10
x = Int("5")
//x = Int("Cat")
//x = nil
print(x)

//Unwrap
if x != nil {
    print(x! + 1)
}

var a: Int? = 5
//a = nil
var res = a ?? 0
//res = a != nil ? a! : 0
print(res)

//Binding
let p1:(Int?, Int?) = (5, 5)
if let x = p1.0,
   let y = p1.1 {
    print("x:\(x), y:\(y)")
}else{
    print("nil")
}

var z: Int? = 5
if let z = z, z <= 5 {
    print("z:\(z)")
}else{
    print("nil")
}

//Guard
func foo(_ str: String?) {
   guard let str = str, str.count != 0 else {
      print("exit")
      return
   }
   // code
   print("run \(str)")
}
var str:String? = "str"
//str = nil
foo(str)

func parse(str: String) -> Int? {
   if let num = Int(str) {
      return num
   }else{
      return nil
   }
}
func str2num(str: String) {
    guard let num = parse(str: str) else {
        print("exit")
        return
    }
    print("run \(num)")
}
str2num(str: "1")

суббота, 6 июня 2020 г.

Swift + CLI, Windows

WSL on Windows 10
 
1.Enable Developer Mode
in Settings/Update&Security/ForDevelopers

2.Install WSL (Windows Subsystem for Linux)
in ControlPanel/ProgramsAndFeatures/TurnWindowsFeaturesOn-Off

3.Install Ubuntu 20.04

4.Bash on Ubuntu
>ubuntu2004

4.1Terminal commands
Windows file system: /mnt/c 
Change Directory: cd
List Contents of Directory: ls
Move or Rename a File: mv
Copy a File: cp
Delete a File: rm
Create a Directory: mkdir

Clear terminal: clear
Use a Text Editor: vi or nano


5.Version info
> lsb_release -a

6.Install Swift

7.Swift + CLI, Linux


Add swift's path:
export PATH=/mnt/c/tmp/swift/usr/bin:"${PATH}"
to the end of:
\\wsl$\Ubuntu-20.04\home\vas\.bashrc

$ mkdir Hello
$ cd Hello
$ swift package init --type executable
$ swift run Hello 
  
//VS Code + WSL Extension
$ code Sources/Hello/main.swift


пятница, 5 июня 2020 г.

Swift, Basics

Online Swift Playground

//Math
import Foundation 
print(sin(45 * Double.pi / 180))
print((2.0).squareRoot())

//Ranges
let closed = 0...5
let halfOpen = 0..<6

//Random
var rnd = Int.random(in: 0 ..< 6+1)
//var rnd = Int.random(in: 0 ... 6)
print(rnd)

//Variables (inferred)
var meters = 5, km = 5
var PI = 3.14
meters += 5
print("meters: ", meters - 5)

//Interpolation
print("PI: \(PI)")

//Constants
let x = 5
// x += 5 error

//Tuples
let point: (Int, Int) = (5, 5)
let vector = (5.0, 5.0)
print(point.0, point.1)

let point = (x:5, y:5)
print(point.x, point.y)

//Alias
typealias Point = (x:Int, y:Int)
let p1: Point = (x:2, y:4)
print(p1.x, p1.y)
 
//Deconstructing
let point3d = (x: 2, y: 3, z: 1)
let (x3d, y3d, z3d) = point3d
let (x2d, y2d, _) = point3d
print(x3d, y3d, z3d)
print(x2d, y2d) 

//Operators
let y = 3 / 1
print("remainder: ", x % y)

let z = ( 2 > 1) ? true : false
//let z = max(2, 1)
print(z)

//Strings
let poem = """
           Hi, I am Mike.
           And you?
           How are you?
           """
print(poem)

print("str1" + " " + "str2")
var greet = "Hi"
greet += "!"
print("str: \(greet)")

//Explisit types
let chr: Character = "a"
let str: String = "my_string"
let zzz: Int = 5_000_000
let dbl: Double = 3.14
let flt: Float = 0.123
var bln: Bool = !true; bln.toggle()
 
//Casting
let c = 5
let d = Double (c) / 2
//let d = 5 as Double / 2
//let d = 5.0 / 2.0
print(d)

let a:Character = "!"
let str = "Hi" + String(a)
print(str)

//IF-ELSE
var age = 14
var citizen = true
if age >= 18 && citizen == true {
    print("Yes, you can vote!")
} else if age < 18 || citizen == false {
    print("No, you cannot!")
} else {
    print("Opps!")
}

//SWITCH
var grade = "B"
switch (grade) {
case "A","B":
   print("Good!")
default:
   break
}

var some = 2
switch (some) {
case 0..<5:
   print("a few")
case 5...10:
   print("a lot")
default:
   break
}

//PATTERN MATCHING
var number = 2
switch number {
case let x where x % 2 == 0:
    print("Even:", x)
default:
    print("Odd")
}

switch number {
case _ where number % 2 == 0:
    print("Even:", number)
default:
    print("Odd")
}

let point = (x: 2, y: 0)
switch point {
case (0, 0):
    print("origin")
case (let x, 0) where x <= 2:
    print("x = \(x)")
case (0, let y):
    print("y = \(y)")
case let (x, y):
    print("in_space = \(x), \(y)")}

let point = (x: 2, y: 0)
switch point {
case (0, 0):
    print("origin")
case (_, 0) where point.x <= 2:
    print("x_axis")
case (0, _):
    print("y_axis")
default:
    print("in_space")
}
 
//WHILE
var i = 0
while (i < 10) {
    i += 1
    if i == 3{
        continue
    }
    print(i)
    if i == 5{
        break
    }
}

//DO-WHILE
var j = 10
repeat {
    print(j)
    j -= 1
} while (j != 0)

//FOR
for i in 1...5 {
   print(i)
}

for _ in 1..<5 {
   print("+")
}

for i in 1...5 where i % 2 == 0 {
    print(i)
}

OUT: for row in 0...4 {
    IN: for col in 0...4 {
        if row == col {
            continue OUT
        }
        print(row * col)
    }
}

//Step
for i in stride(from: 0, to: 6, by: 2) {
    print(i)
}
for i in stride(from: 6, through: 0, by: -2) {
    print(i)
}

Swift + CLI, Linux

Command Line Interface, CLI

Dependencies

For current session:
$ export PATH=/path/to/swift/usr/bin:"${PATH}"

For all sessions:
$ gedit ~/.bashrc

and add to the end:
export PATH=~/Downloads/swift-5.2.4-RELEASE-ubuntu20.04/usr/bin:"${PATH}"

//or
//export PATH=~/Soft/swift/usr/bin:"${PATH}"

//Windows
export PATH=/mnt/c/tmp/swift/usr/bin:"${PATH}"

Version info
$ swift --version

REPL:
$ swift

For help:
> :help

To exit:
> :exit

Package Manager
$ swift package --help
 
$ mkdir Hello
$ cd Hello 
 
$ swift package init
├── Package.swift
├── README.md
├── Sources
│   └── Hello
│       └── Hello.swift
└── Tests
    ├── HelloTests
    │   └── HelloTests.swift
    └── LinuxMain.swift  

$ swift build
$ swift test
 
Building an Executable
$ mkdir Hello
$ cd Hello
 
$ swift package init --type executable
//main.swift
  
//$ swift build  
$ swift run Hello  

вторник, 2 июня 2020 г.

Swift + CLion, Linux.

0.Buy CLion

1.Install Ubuntu LTS
1.1 Install dependencies (Ubuntu 20.04):
 
$ sudo apt-get update 
$ sudo apt-get install \
          binutils \
          git \
          gnupg2 \
          libc6-dev \
          libcurl4 \
          libedit2 \
          libgcc-9-dev \
          libpython2.7 \
          libsqlite3-0 \
          libstdc++-9-dev \
          libxml2 \
          libz3-dev \
          pkg-config \
          tzdata \
          zlib1g-dev


2.Download Clion.
2.1 Extract: tar -xzf Clion.*.tar.gz
2.2 Run: .../bin/CLion.sh
2.3 Install Swift plugin for CLion

3.Download Swift.
3.1 Extract: tar -xzf swift.*.tar.gz
3.2 Setup Swift plugin for CLion

4.GO!

пятница, 17 апреля 2020 г.

C#, Strings

using System;
using System.Globalization;
using System.Text;

namespace ConsoleApp3
{
    internal class Program
    {
        public static void Main(string[] args)
        {
            var text = "I am a text";

            Console.WriteLine("String length: " + text.Length);
            Console.WriteLine("Uppercase: " + text.ToUpper());
            Console.WriteLine("Does it have \"am\"? " + (text.Contains("am") ? "yes" : "no"));
            Console.WriteLine("range: " + text[2..4]);
            Console.WriteLine("   trimmed".TrimStart());

            var words = text.Split(" ");
            foreach (var word in words)
            {
                Console.WriteLine(word);
            }

            foreach (var ch in text)
            {
                Console.WriteLine(ch + " - " + (int) ch);
            }

            int x = int.Parse("42");
            int y = Convert.ToInt32("42");
            if (int.TryParse("42", out var z))
            {
                Console.WriteLine("s2i: " + z);
            }

            CultureInfo usa = new CultureInfo("en-US");

            Console.WriteLine("usa format: " + 42.ToString("N2", usa));
            Console.WriteLine($"local format: {42:N2}");

            var fmt = String.Format("{0:N2} - {1} - {2}", x, y, z);
            Console.WriteLine(fmt);

            StringBuilder str = new StringBuilder(/* "x" */);
            str.Append("a");
            str.Insert(0, "b");
            str.Remove(0, 1);
            Console.WriteLine(str);
            Console.WriteLine("equal to 'a': " + str.Equals("a"));
            str.Clear();
            Console.WriteLine(str.Capacity);
        }
    }
}

четверг, 16 апреля 2020 г.

C#, Date, Time and Environment

using System;
using System.Diagnostics;

namespace ConsoleApp3
{
    internal class Program
    {
        public static void Main(string[] args)
        {
            var sw = new Stopwatch();
            sw.Start();

            var now = DateTime.Now;
            Console.WriteLine("Now is " + now);

            var today = DateTime.Today;
            Console.WriteLine("Today is " + today.ToLongDateString());
            Console.WriteLine("Tomorrow is " + today.AddDays(1).ToShortDateString());

            Console.WriteLine("Date: " + now.Date);
            Console.WriteLine("Day: " + now.Day);
            Console.WriteLine("Month: " + now.Month);
            Console.WriteLine("Year: " + now.Year);
            Console.WriteLine("Hour: " + now.Hour);
            Console.WriteLine("Minute: " + now.Minute);
            Console.WriteLine("Second: " + now.Second);

            Console.WriteLine("PC Name: " + Environment.MachineName);
            Console.WriteLine("Num of cores: " + Environment.ProcessorCount);
            Console.WriteLine("User: " + Environment.UserName);
            Console.WriteLine("Env var 'OS': " + Environment.GetEnvironmentVariable("OS"));
            Console.WriteLine("Path to MyDoc: " + Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));

            sw.Stop();
            //Console.WriteLine("Elapsed time: " + sw.Elapsed.ToString("s\\.ffff"));
            Console.WriteLine($"Speed: {sw.Elapsed:s\\.ffff}");
            sw.Reset();

            var rnd = new Random(DateTime.Now.Millisecond);
            for (var i = 0; i < 3; i++)
            {
                Console.WriteLine("1d6: " + rnd.Next(1, 6 + 1));
            }
        }
    }
}

пятница, 27 марта 2020 г.

.NET Core + CLI, Windows

Разворачиваем платформу для разработки на C# 8.

1. Сначала нам потребуется SDK, качаем текущую на данный момент сборку .NET Core 3.1. Устанавливаем. Проверяем: “dotnet --version”, наша версия 3.1.201.
 
2. Теперь давайте установим VSCode. Качаем, на данный момент версия 1.43.2. Устанавливаем, запускаем, добавляем расширение для поддержки C# 8. Еще можно поставить цветовую тему One Dark Pro.
 
3. Теперь можно шкодить. Создаем каталог нашего проекта в любом месте (имя каталога, будет именем нашего проекта). Заходим в него с помощью командной строки (или PowerShell) и запускаем “dotnet new console”, чтобы создать шаблон консольного приложения. Запускаем его с помощью “dotnet run”, получаем “Привет Мир!”. Круто, работает.
 
4. Настраиваем редактор. Из командной строки запускаем VSCode с помощью команды “code”. Указываем папку нашего проекта (можно указать текущую папку при запуске, с помощью “code .”), даем разрешение на настройку билдера и отладчика, после чего в проекте появляется папка “.vscode”, содержащая файлы настроек launch.json и tasks.json (или Ctrl+Shift+P: .NET: Generate Assets for Build and Debug). Пробуем: ставим “брейку” (F9), жмем F5 для отладки приложения, должно работать. Для простого запуска Ctrl+F5.
 
5. Настраиваем юнит-тестирование. Создаем новую папку рядом с папкой проекта, заходим, запускаем команду “dotnet new mstest” для создания шаблона. Теперь нужно добавить зависимость от нашего проекта с помощью команды “dotnet add reference ../project_name”. Проверяем, из командной строки запускаем: “dotnet test”. Должно работать! (может пригодиться расширение .NET Core Test Explorer)

Visual Studio Code - Keyboard shortcuts for Windows
 
Поздравляю, теперь можно открыть исходник проекта и.. ой, кажется вышла новая серия моего любимого сериала. :P

Vasili Perahud