美文网首页
[01]-函数式思想

[01]-函数式思想

作者: 快乐捣蛋鬼 | 来源:发表于2019-06-17 15:44 被阅读0次
屏幕快照 2019-06-17 下午3.40.33.png
import Foundation

// 定义两种类型: Distance 和 Position
typealias Distance = Double

struct Position {
    var x: Double
    var y: Double
    var length: Double {
        return sqrt(x*x + y*y)
    }
}

extension Position {
    // 用于检验一个点是否在图2.1中的灰色区域里
    func inRange(range: Distance) -> Bool {
        return sqrt(x*x + y*y) <= range
    }
    
    func minus(p: Position) -> Position {
        return Position(x: x - p.x, y: y - p.y)
    }
}
屏幕快照 2019-06-17 下午3.41.44.png
// 允许船有自己的位置,不一定在原点,引入一个结构体,它有一个属性为 position
struct Ship {
    var postion: Position
    var firingRange: Distance
    var unsafeRange: Distance
}
屏幕快照 2019-06-17 下午3.46.37.png 屏幕快照 2019-06-17 下午3.46.48.png
extension Ship {
    func canEngageShip(target: Ship, friend: Ship) -> Bool {
        let dx = target.postion.x - postion.x
        let dy = target.postion.y - postion.y
        let targetDistance = sqrt(dx*dx + dy*dy)
        
        let friendDx = friend.postion.x - target.postion.x
        let friendDy = friend.postion.y - target.postion.y
        let friendDistance = sqrt(friendDx*friendDx + friendDy*friendDy)
        return targetDistance <= firingRange && targetDistance > unsafeRange && (friendDistance > unsafeRange)
        // 目标在开火范围内 && 避免与过近的敌方交战 && 避免敌方过于接近友方
    }
    
    // 添加辅助函数之后代码更清晰易读
    func canEngageShip1(target: Ship, friend: Ship) -> Bool {
        let targetDistance = target.postion.minus(p: postion).length
        let friendDistance = friend.postion.minus(p: target.postion).length
        return targetDistance <= firingRange && targetDistance > unsafeRange && (friendDistance > unsafeRange)
    }
  
}

使用 Region 类型

// Region 类型将指代把 Position 转化为 Bool 的函数
// 函数式编程的核心理念就是函数是值,它和结构体、整型或是布尔型没有什么区别
typealias Region = (Position) -> Bool

// summary: 使用一个能判断给定点是否在区域的函数来代表一个区域,而不是定义一个对象或结构来表示它

// 定义的第一个区域: 以原点为圆心的圆(circle)
func circle(radius: Distance) -> Region {
    return { point in point.length <= radius }
}

// 定义的第二个区域: 圆心为任意点的圆 (circle2)
func circle2(radius: Distance, center: Position) -> Region {
    return { point in point.minus(p: center).length <= radius }
}

// 区域变换函数,按一定的偏移量移动一个区域: 可以对更多的组件(圆/矩形等)作出同样的改变
func shift(region: @escaping Region, offset: Position) -> Region {
    return { point in region(point.minus(p: offset)) }
}

// 一个圆心为 (5, 5) 半径为 10 的圆,可以用下面的方式表示:
shift(region: circle(radius: 10), offset: Position(x: 5, y: 5))

// summary: 为了避免创建像 circle2 这样越来越复杂的函数,我们编写了一个 shift(_:offset:) 函数来改变另一个函数


// 反转一个区域以定义另一个区域,这个新产生的区域由原区域以外的所有点组成:
func invert(region: @escaping Region) -> Region {
    return { point in !region(point)}
}

// 计算参数中两个区域的交集
func intersection(region1: @escaping Region, _ region2: @escaping Region) -> Region {
    return { point in region1(point) && region2(point)}
}

// 计算参数中两个区域的并集
func union(region1: @escaping Region, region2: @escaping Region) -> Region {
    return  { point in region1(point) || region2(point)}
}

// 所有在第一个区域中但不在第二个区域中的点构成的区域:
func difference(region1: @escaping Region, region2: @escaping Region) -> Region {
    return intersection(region1: region1, invert(region: region2))
    
}

extension Ship {
    // 将一些小型函数装配起来, 使用 Region 函数重构
    func canEngageShip2(target: Ship, friend: Ship) -> Bool {
        let safeRegion = difference(region1: circle(radius: firingRange), region2: circle(radius: unsafeRange))
        let firingRegion = shift(region: safeRegion, offset: postion)
        let friendRegion = shift(region: circle(radius: unsafeRange), offset: friend.postion)
        let resultRegion = difference(region1: firingRegion, region2: friendRegion)
        return resultRegion(target.postion)
    }
}

完整代码

import Foundation

// 定义两种类型: Distance 和 Position
typealias Distance = Double

struct Position {
    var x: Double
    var y: Double
    var length: Double {
        return sqrt(x*x + y*y)
    }
}

extension Position {
    // 用于检验一个点是否在图2.1中的灰色区域里
    func inRange(range: Distance) -> Bool {
        return sqrt(x*x + y*y) <= range
    }
    
    func minus(p: Position) -> Position {
        return Position(x: x - p.x, y: y - p.y)
    }
}

// 允许船有自己的位置,不一定在原点,引入一个结构体,它有一个属性为 position
struct Ship {
    var postion: Position
    var firingRange: Distance
    var unsafeRange: Distance
}

extension Ship {
    func canEngageShip(target: Ship, friend: Ship) -> Bool {
        let dx = target.postion.x - postion.x
        let dy = target.postion.y - postion.y
        let targetDistance = sqrt(dx*dx + dy*dy)
        
        let friendDx = friend.postion.x - target.postion.x
        let friendDy = friend.postion.y - target.postion.y
        let friendDistance = sqrt(friendDx*friendDx + friendDy*friendDy)
        return targetDistance <= firingRange && targetDistance > unsafeRange && (friendDistance > unsafeRange)
        // 目标在开火范围内 && 避免与过近的敌方交战 && 避免敌方过于接近友方
    }
    
    // 添加辅助函数之后代码更清晰易读
    func canEngageShip1(target: Ship, friend: Ship) -> Bool {
        let targetDistance = target.postion.minus(p: postion).length
        let friendDistance = friend.postion.minus(p: target.postion).length
        return targetDistance <= firingRange && targetDistance > unsafeRange && (friendDistance > unsafeRange)
    }
  
}

// Region 类型将指代把 Position 转化为 Bool 的函数
// 函数式编程的核心理念就是函数是值,它和结构体、整型或是布尔型没有什么区别
typealias Region = (Position) -> Bool

// summary: 使用一个能判断给定点是否在区域的函数来代表一个区域,而不是定义一个对象或结构来表示它

// 定义的第一个区域: 以原点为圆心的圆(circle)
func circle(radius: Distance) -> Region {
    return { point in point.length <= radius }
}

// 定义的第二个区域: 圆心为任意点的圆 (circle2)
func circle2(radius: Distance, center: Position) -> Region {
    return { point in point.minus(p: center).length <= radius }
}

// 区域变换函数,按一定的偏移量移动一个区域: 可以对更多的组件(圆/矩形等)作出同样的改变
func shift(region: @escaping Region, offset: Position) -> Region {
    return { point in region(point.minus(p: offset)) }
}

// 一个圆心为 (5, 5) 半径为 10 的圆,可以用下面的方式表示:
shift(region: circle(radius: 10), offset: Position(x: 5, y: 5))

// summary: 为了避免创建像 circle2 这样越来越复杂的函数,我们编写了一个 shift(_:offset:) 函数来改变另一个函数


// 反转一个区域以定义另一个区域,这个新产生的区域由原区域以外的所有点组成:
func invert(region: @escaping Region) -> Region {
    return { point in !region(point)}
}

// 计算参数中两个区域的交集
func intersection(region1: @escaping Region, _ region2: @escaping Region) -> Region {
    return { point in region1(point) && region2(point)}
}

// 计算参数中两个区域的并集
func union(region1: @escaping Region, region2: @escaping Region) -> Region {
    return  { point in region1(point) || region2(point)}
}

// 所有在第一个区域中但不在第二个区域中的点构成的区域:
func difference(region1: @escaping Region, region2: @escaping Region) -> Region {
    return intersection(region1: region1, invert(region: region2))
    
}

extension Ship {
    // 将一些小型函数装配起来, 使用 Region 函数重构
    func canEngageShip2(target: Ship, friend: Ship) -> Bool {
        let safeRegion = difference(region1: circle(radius: firingRange), region2: circle(radius: unsafeRange))
        let firingRegion = shift(region: safeRegion, offset: postion)
        let friendRegion = shift(region: circle(radius: unsafeRange), offset: friend.postion)
        let resultRegion = difference(region1: firingRegion, region2: friendRegion)
        return resultRegion(target.postion)
    }
}


//          ___
//        //|||\\
//       //|-_-|\\
//          |||
//           |
//           |
//          / \

相关文章

  • [01]-函数式思想

    使用 Region 类型 完整代码

  • 函数响应式编程思想 & RxSwift 核心逻辑(一)

    函数响应式编程思想 函数响应式编程思想即是将函数式编程和响应式编程相结合。 函数式编程 顾名思义,就是像函数一样的...

  • 《JavaScript 函数式编程指南》 - 阅读索引

    [toc] 第一部分 函数式思想 第 1 章 走近函数式 函数式思想什么是函数式编程以及为什么要进行函数式编程不变...

  • RxSwift初探(1)

    一、前提:函数响应式编程思想 简单来说 函数响应式编程 = 函数式编程 + 响应式编程 (1)函数式 函数式编程是...

  • 2018-10-17 Day14类和对象

    01-面向对象编程 编程思想:1.面向过程编程 ---> 算法,逻辑(数学逻辑) 2.函数式编程 ---> 函数...

  • Scala 入门

    1 函数式编程思想 1.1 介绍 1.2 scala函数式编程思想 2 环境搭建 3 实战 4 变量 函数 函数定...

  • 函数式思想

    函数在 Swift 中是一等值 ( rst-class-values),换句话说,函数可以作为参数被传递到其它函 ...

  • python面向对象1

    编程思想 编程思想:面向过程编程(穷人思想)、函数式编程、面向对象编程(富豪) 面向过程编程: 算法和逻辑 函数式...

  • 类和对象

    01-面向对象编程 ----编程思想 ✈ 1、面向过程编程 --> 算法,逻辑(数学逻辑)✈ 2、函数式编程 --...

  • 函数式编程思想简介

    函数式编程思想简介

网友评论

      本文标题:[01]-函数式思想

      本文链接:https://www.haomeiwen.com/subject/vegafctx.html