原理
RxCocoa如何将Cocoa对象的消息转化为可被订阅的流
let button = UIButton()
button.rx.sentMessage(#selector(UIButton.setTitle(_:for:)))
.asObservable().subscribe { (event) in
print( "event : \(event)") //next([Title, 0])
}
.addDisposableTo(disposeBag)
button.setTitle("Title", for: UIControlState.normal)
像这样的一段代码,表示RxCocoa将Cocoa的对象消息全都拦截并转化成了可以被订阅的Observable
首先分析 UIButton 的rx的属性是怎么来的呢?
/// Extend NSObject with `rx` proxy.
extension NSObject: ReactiveCompatible { }
public protocol ReactiveCompatible {
associatedtype CompatibleType
static var rx: Reactive<CompatibleType>.Type { get set }
var rx: Reactive<CompatibleType> { get set }
}
extension ReactiveCompatible {
public static var rx: Reactive<Self>.Type {
get {
return Reactive<Self>.self
}
set {
// this enables using Reactive to "mutate" base type
}
}
public var rx: Reactive<Self> {
get {
return Reactive(self)
}
set {
// this enables using Reactive to "mutate" base object
}
}
}
public struct Reactive<Base> {
public let base: Base
public init(_ base: Base) {
self.base = base
}
}
给 NSObject 添加了一个 ReactiveCompatible 协议 ,并对这个协议作扩展了。也就是给所有NSObject都添加了 .rx 的属性,这个属性返回的是一个叫Reactive的容器,容器里就是原本的对象。 这个容器有意思了,不仅能把RxCocoa的api全都用 .rx. 这样的方式和Cocoa的api都区分开,还能为这个容器实现更多的协议,扩展出更多的方法。用where约束的办法,扩展出针对某个Cocoa对象独特的rx方法。
extension Reactive where Base: UIButton {
/// Reactive wrapper for `TouchUpInside` control event.
public var tap: ControlEvent<Void> {
return controlEvent(.touchUpInside)
}
}
接下来看看 sentMassage方法:
extension Reactive where Base: AnyObject {
public func sentMessage(_ selector: Selector) -> Observable<[Any]> {
return synchronized {
// in case of dealloc selector replay subject behavior needs to be used
if selector == deallocSelector {
return deallocating.map { _ in [] }
}
do {
let proxy: MessageSentProxy = try registerMessageInterceptor(selector)
return proxy.messageSent.asObservable()
}
catch let e {
return Observable.error(e)
}
}
}
}
这里先主要看它返回的是一个 MessageSentProxy 的类型 ,他有PublishSubject的功能,也就是可以对作为Observable,发送 .next(arguments) 等event事件。意味着被转化的事件流将由它向外发送。
然后继续看关键的函数 registerMessageInterceptor(selector) 为一个selector注册监听者。
fileprivate func registerMessageInterceptor<T: MessageInterceptorSubject>(_ selector: Selector) throws -> T {
let rxSelector = RX_selector(selector)
let selectorReference = RX_reference_from_selector(rxSelector)
let subject: T
if let existingSubject = objc_getAssociatedObject(base, selectorReference) as? T {
subject = existingSubject
}
else {
subject = T()
objc_setAssociatedObject(
base,
selectorReference,
subject,
.OBJC_ASSOCIATION_RETAIN_NONATOMIC
)
}
if subject.isActive {
return subject
}
var error: NSError?
let targetImplementation = RX_ensure_observing(base, selector, &error)
if targetImplementation == nil {
throw error?.rxCocoaErrorForTarget(base) ?? RxCocoaError.unknown
}
subject.targetImplementation = targetImplementation!
return subject
}
#endif
}
生成了一个 MessageInterceptorSubject 对象并将它用 objc_getAssociatedObject方法绑定到这个 button Cocoa的实例上,以 selectorReference 为Key。目的是为这个实例 保存一个向外发送event事件的 subject。 等RX_ensure_observing里面会用selectorReference重新取出这个 subject,然后将监听到的消息都发给他。
继续看关键方法 RX_ensure_observing
IMP __nullable RX_ensure_observing(id __nonnull target, SEL __nonnull selector, NSError ** __nonnull error) {
__block IMP targetImplementation = nil;
@synchronized(target) {
@synchronized([target class]) {
[[RXObjCRuntime instance] performLocked:^(RXObjCRuntime * __nonnull self) {
targetImplementation = [self ensurePrepared:target
forObserving:selector
error:error];
}];
}
}
return targetImplementation;
}
[RXObjCRuntime instance] 这个实例是RxCocoa 用来操作所有运行时的一个单例,可以在这个单例调用运行时api加上各种锁,保证线程安全。
继续看 ensurePrepared: forObserving: error: 要开始为这个target的selector真正的注入监听者了。
-(IMP __nullable)ensurePrepared:(id __nonnull)target forObserving:(SEL __nonnull)selector error:(NSError** __nonnull)error {
/* 一些安全代码 */
if (selector == deallocSelector) {
/* 一些针对dealloc特殊的处理代码 */
}
else {
Class __nullable swizzlingImplementorClass = [self prepareTargetClassForObserving:target error:error];
/* 一些优化消息监听性能的代码 */
// optimized interception method
if (optimizedIntercept != nil) {
/* 一些优化消息监听性能的代码 */
}
// default fallback to observing by forwarding messages
else {
if ([self forwardingSelector:selector forClass:swizzlingImplementorClass]) {
return RX_default_target_implementation();
}
if (![self observeByForwardingMessages:swizzlingImplementorClass
selector:selector
target:target
error:error]) {
return nil;
}
if ([self forwardingSelector:selector forClass:swizzlingImplementorClass]) {
return RX_default_target_implementation();
}
}
}
/* 一些处理错误代码 */
}
[self prepareTargetClassForObserving:target error:error] 方法为target 这个类准备一个中间类 swizzlingImplementorClass 。为了替换 target的 isa 指针以拦截消息
-(Class __nullable)prepareTargetClassForObserving:(id __nonnull)target error:(NSError **__nonnull)error {
/* 省略一些代码 */
Class __nullable dynamicFakeSubclass = [self ensureHasDynamicFakeSubclass:wannaBeClass error:error];
Class previousClass = object_setClass(target, dynamicFakeSubclass);//替换 *target*的 isa 指针以拦截消息
objc_setAssociatedObject(target, &RxSwizzlingTargetClassKey, dynamicFakeSubclass, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
return dynamicFakeSubclass;
}
-(Class __nullable)ensureHasDynamicFakeSubclass:(Class __nonnull)class error:(NSError **)error {
Class dynamicFakeSubclass = self.dynamicSubclassByRealClass[CLASS_VALUE(class)];
if (dynamicFakeSubclass != nil) {
return dynamicFakeSubclass;
}
NSString *dynamicFakeSubclassName = [RX_PREFIX stringByAppendingString:NSStringFromClass(class)];
const char *dynamicFakeSubclassNameRaw = dynamicFakeSubclassName.UTF8String;
dynamicFakeSubclass = objc_allocateClassPair(class, dynamicFakeSubclassNameRaw, 0); //!!!创建中间类
ALWAYS(dynamicFakeSubclass != nil, @"Class not generated");
if (![self swizzleClass:dynamicFakeSubclass toActAs:class error:error]) {
return nil;
}//!!!修改中间类的class方法,欺骗
objc_registerClassPair(dynamicFakeSubclass);//!!!动态注册生产好的中间类
[self.dynamicSubclassByRealClass setObject:dynamicFakeSubclass forKey:CLASS_VALUE(class)];
ALWAYS(self.dynamicSubclassByRealClass[CLASS_VALUE(class)] != nil, @"Class not registered");
return dynamicFakeSubclass;
}
目前为止中间类就成功接管了,UIButton的所有方法。这个原理类似KVO的实现。但是这里不是重写Cocoa方法 而是将要监听的 selector 的 IMP 改成 _objc_msgForward 让这个消息走消息转发流程。最后重写 forwardInvocation: 函数统一处理消息。
-(BOOL)observeByForwardingMessages:(Class __nonnull)swizzlingImplementorClass
selector:(SEL)selector
target:(id __nonnull)target
error:(NSError **__nonnull)error {
if (![self ensureForwardingMethodsAreSwizzled:swizzlingImplementorClass error:error]) {
return NO;
}
SEL rxSelector = RX_selector(selector);
Method instanceMethod = class_getInstanceMethod(swizzlingImplementorClass, selector);
IMP implementation = method_getImplementation(instanceMethod);
if (!class_addMethod(swizzlingImplementorClass, rxSelector, implementation, methodEncoding)) {
RX_THROW_ERROR([NSError errorWithDomain:RXObjCRuntimeErrorDomain
code:RXObjCRuntimeErrorSavingOriginalForwardingMethodFailed
userInfo:nil], NO);
}
if (!class_addMethod(swizzlingImplementorClass, selector, _objc_msgForward, methodEncoding)) {
if (implementation != method_setImplementation(instanceMethod, _objc_msgForward)) {
THREADING_HAZARD(swizzlingImplementorClass);
RX_THROW_ERROR([NSError errorWithDomain:RXObjCRuntimeErrorDomain
code:RXObjCRuntimeErrorReplacingMethodWithForwardingImplementation
userInfo:nil], NO);
}
}
[self registerForwardedSelector:selector forClass:swizzlingImplementorClass];
return YES;
}
ensureForwardingMethodsAreSwizzled 方法里替换了中间类的 forwardInvocation 为 新的IMP
-(BOOL)ensureForwardingMethodsAreSwizzled:(Class __nonnull)class error:(NSError ** __nonnull)error {
NSValue *classValue = CLASS_VALUE(class);
if ([self.classesThatSupportObservingByForwarding containsObject:classValue]) {
return YES;
}
if (![self swizzleForwardInvocation:class error:error]) { return NO; }
if (![self swizzleMethodSignatureForSelector:class error:error]) { return NO; }
if (![self swizzleRespondsToSelector:class error:error]) { return NO; }
[self.classesThatSupportObservingByForwarding addObject:classValue];
return YES;
}
swizzleForwardInvocation 使用宏定义实现的。
SWIZZLE_INFRASTRUCTURE_METHOD(
void,
swizzleForwardInvocation,
,
@selector(forwardInvocation:),
FORWARD_BODY,
NSInvocationRef
)
// RX_forward_invocation 将捕获到的方法和参数 发送给 之前用 selector为key的subject。
#define FORWARD_BODY(invocation)
if (RX_forward_invocation(self, NAME_CAT(_, 0, invocation))) { return; }
//宏展开的主要部分
id newImplementation = ^return_value(__unsafe_unretained id self DECLARE_ARGUMENTS(__VA_ARGS__)) { \
FORWARD_BODY(__VA_ARGS__) //这里调用 RX_forward_invocation 函数。
struct objc_super superInfo = {\
.receiver = self,
.super_class = class_getSuperclass(class)
};
return_value (*msgSend)(struct objc_super *, SEL DECLARE_ARGUMENTS(__VA_ARGS__)) // \
= (__typeof__(msgSend))objc_msgSendSuper; \
主要是 RX_forward_invocation 将捕获到的方法和参数 发送给 之前用 selector为key的subject。 将新的 newImplementation IMP 替换到原来的forwardInvocation:上。在 RX_forward_invocation 转发完消息后。也要把消息传给 父类 :UIButton。继续这个消息的任务。
static BOOL RX_forward_invocation(id __nonnull __unsafe_unretained self, NSInvocation *invocation) {
SEL originalSelector = RX_selector(invocation.selector);
id<RXMessageSentObserver> messageSentObserver = objc_getAssociatedObject(self, originalSelector);
if (messageSentObserver != nil) {
NSArray *arguments = RX_extract_arguments(invocation);
[messageSentObserver messageSentWithArguments:arguments];
}
if ([self respondsToSelector:originalSelector]) {
invocation.selector = originalSelector;
[invocation invokeWithTarget:self];
if (messageSentObserver != nil) {
NSArray *arguments = RX_extract_arguments(invocation);
[messageSentObserver methodInvokedWithArguments:arguments];
}
return YES;
}
return NO;
}
监听UIKit对象的Delegate的方法
let web = UIWebView()
web.loadRequest(URLRequest(url: URL(string:"baidu.com")!))
web.rx.didStartLoad
.asObservable()
.subscribe { (event) in
print("event : \(event)") //event : next(())
}.addDisposableTo(disposeBag)
self.view.addSubview(web)
上面的代码展示了RxCocoa获取原本UIWebView,delegate的方法 并转化为 Observable。
didStartLoad 的方法在这里
extension Reactive where Base: UIWebView {
public var delegate: DelegateProxy {
return RxWebViewDelegateProxy.proxyForObject(base)
}
public var didStartLoad: Observable<Void> {
return delegate
.methodInvoked(#selector(UIWebViewDelegate.webViewDidStartLoad(_:)))
.map {_ in}
}
原来 RxCocoa 先添加一个 DelegateProxy 类来做自己的代理。应该是用来监听原本 delegate 的回调方法的。看看 RxWebViewDelegateProxy.proxyForObject(base) 生成DelegateProxy的方法。
public protocol DelegateProxyType : AnyObject {
/* 一些方法列表 */
}
extension DelegateProxyType {
public static func proxyForObject(_ object: AnyObject) -> Self {
MainScheduler.ensureExecutingOnScheduler()
let maybeProxy = Self.assignedProxyFor(object) as? Self
let proxy: Self
if let existingProxy = maybeProxy {
proxy = existingProxy
}
else {
proxy = Self.createProxyForObject(object) as! Self
Self.assignProxy(proxy, toObject: object)
assert(Self.assignedProxyFor(object) === proxy)
}
let currentDelegate: AnyObject? = Self.currentDelegateFor(object)
if currentDelegate !== proxy {
proxy.setForwardToDelegate(currentDelegate, retainDelegate: false)
assert(proxy.forwardToDelegate() === currentDelegate)
Self.setCurrentDelegate(proxy, toObject: object)
assert(Self.currentDelegateFor(object) === proxy)
assert(proxy.forwardToDelegate() === currentDelegate)
}
return proxy
}
}
原来咱们的 DelegateProxy 实现了 DelegateProxyType 这个协议,得到了这个扩展方法。协议扩展中 proxy = Self.createProxyForObject(object) as! Self 就生成了一个 DelegateProxy! 之后设置这个 proxy 为 UIWebView的代理 Self.setCurrentDelegate(proxy, toObject: object) ,如果UIWebView本身已经有代理的话。将这个代理保存到 proxy.setForwardToDelegate(currentDelegate, retainDelegate: false)中。以便消息的继续传递。
再看看 DelegateProxy 的 methodInvoked 方法
open func methodInvoked(_ selector: Selector) -> Observable<[Any]> {
checkSelectorIsObservable(selector)
let subject = methodInvokedForSelector[selector]
if let subject = subject {
return subject
}
else {
let subject = PublishSubject<[Any]>()
methodInvokedForSelector[selector] = subject
return subject
}
}
原来在 methodInvoked 方法中,为 DelegateProxy 收集了一些需要监听的 Selector 在 methodInvokedForSelector里。
上一步,已经将生成的DelegateProxy 变成了UIWebView的代理,当有 delegate 到消息回调时,会看这个消息是否在监听列表里,如果是的话。就把它转化成 event 通过 subject 发送出去。
RxSwift的Observer和Observable实现原理
观察者 Observer
public protocol ObserverType {
associatedtype E
func on(_ event: Event<E>)
}
extension ObserverType {
public final func onNext(_ element: E) {
on(.next(element))
}
public final func onCompleted() {
on(.completed)
}
public final func onError(_ error: Swift.Error) {
on(.error(error))
}
}
作为观察者类型 ObserverType 是有能力处理next/error/completed事件的,例如UIKit所有用于展示数据的控件,他们可以绑定信号源的来时刻更新自己的数据。返回UIBindingObserver就是ObserverType类型,他们有处理next/error/completed的能力。
extension Reactive where Base: UILabel {
public var text: UIBindingObserver<Base, String?> {
return UIBindingObserver(UIElement: self.base) { label, text in
label.text = text
}
}
被观察者 Observerable
可以被其他人订阅的。
public protocol ObservableType : ObservableConvertibleType {
associatedtype E
func subscribe<O: ObserverType>(_ observer: O) -> Disposable where O.E == E
}
Observer 和 Observable 他们是如何连接在一起的?
class MyObserver :ObserverType{
typealias E = Int
func on(_ event: Event<E>){
print(" on event : \(event)")
}
}
Observable.of(1,2,3,4)
.asObservable()
.subscribe(o)
.addDisposableTo(disposeBag)
// on event : next(1)
// on event : next(2)
// on event : next(3)
// on event : next(4)
// on event : completed
断点停在 subscribe上可以看到
override func subscribe<O : ObserverType>(_ observer: O) -> Disposable where O.E == Element {
if !CurrentThreadScheduler.isScheduleRequired {
// The returned disposable needs to release all references once it was disposed.
let disposer = SinkDisposer()
let sinkAndSubscription = run(observer, cancel: disposer)
disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)
return disposer
}
else {
return CurrentThreadScheduler.instance.schedule(()) { _ in
let disposer = SinkDisposer()
let sinkAndSubscription = self.run(observer, cancel: disposer)
disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)
return disposer
}
}
CurrentThreadScheduler.isScheduleRequired表示当前线程的调度者CurrentThreadScheduler需要调度任务。 一般最开始用户订阅情况下,isScheduleRequired是YES,所以这里会走下面,意思是当前线程的调度者订阅一个 可执行的 block ,这个 block 的作用是将 1,2,3,4 这一组事件生产一个ScheduledItem到自己的调度队列 queue上。等待派发。
public func schedule<StateType>(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable {
if CurrentThreadScheduler.isScheduleRequired {
CurrentThreadScheduler.isScheduleRequired = false
let disposable = action(state) //这里就是开始向队列queue中添加*ScheduledItem*
defer {
CurrentThreadScheduler.isScheduleRequired = true
CurrentThreadScheduler.queue = nil
}
guard let queue = CurrentThreadScheduler.queue else {
return disposable
}
while let latest = queue.value.dequeue() { //这里就是从队列queue中取出*ScheduledItem*,依次派发
if latest.isDisposed {
continue
}
latest.invoke()
}
return disposable
}
let existingQueue = CurrentThreadScheduler.queue
let queue: RxMutableBox<Queue<ScheduledItemType>>
if let existingQueue = existingQueue {
queue = existingQueue
}
else {
queue = RxMutableBox(Queue<ScheduledItemType>(capacity: 1))
CurrentThreadScheduler.queue = queue
}
let scheduledItem = ScheduledItem(action: action, state: state)
queue.value.enqueue(scheduledItem)
return scheduledItem
}
//待续。。。。
DisposeBag 内存回收如何实现的呢?
RxSwift中 内存资源的回收全都靠一个。DisposeBag() 他就像一个垃圾袋儿。将RxSwift每次发生订阅事件 subscribe 时产生的 Disposable 都放到DisposeBag()里。在这个垃圾袋儿释放时,RxSwift链式调用所产生的资源将全都一起释放,请看代码。
public final class DisposeBag: DisposeBase {
// state
private var _disposables = [Disposable]() // 垃圾
private func dispose() { // deinit 时候就执行所有垃圾的清理方法
let oldDisposables = _dispose()
for disposable in oldDisposables {
disposable.dispose()
}
}
deinit {
dispose()
}
}
产生资源的方法都会返回一个实现 Disposable 协议的对象,对这个对象执行 dispose()就释放了它所有创建的资源,包括依赖它声明周期的其他Disposable对象也会在他的dispose()里一起被释放。
public protocol Disposable {
/// Dispose resource.
func dispose()
}
使用经验
ObservableType类型的doOn操作
可以理解为在订阅消息的同时,监听每一个消息,onError方法监听Error消息,就会触发onError的Block
Observable.of("🍎", "🍐", "🍊", "🍋")
.do(onNext: { print("Intercepted:", $0) }, onError: { print("Intercepted error:", $0) }, onCompleted: { print("Completed") })
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
RxSwift 里 map 和 flatMap?
先看看Swift里面两个函数的作用:
let arrayNested = [[1,2,3,4,5],[6,7]]
let maped2 = arrayNested.map { $0 }
print(maped2) // [[1, 2, 3, 4, 5], [6, 7]]
let flaped2 = arrayNested.flatMap { $0 }
print(flaped2) // [1, 2, 3, 4, 5, 6, 7]
flatMap 能将二维数组展开成一维数组。也就是 降维
flatMap 调用一次只能展开一层,也就是说,假如三维数组时调用一次flatMap会变为二维数组,调用两次才会变为一维数组
RxSwift中 也是同样的类似的概念.
let b = Observable.of( Observable.of("🐶", "🐱"),
Observable.of("🐭", "🐹"))
b.map{ $0 }
.subscribe(onNext: { element in
print(element)
//RxSwift.ObservableSequence<Swift.Array<Swift.String>>
//RxSwift.ObservableSequence<Swift.Array<Swift.String>>
})
.disposed(by: disposeBag)
b.flatMap{ $0 }
.subscribe(onNext: { element in
print(element)
//🐶
//🐱
//🐭
//🐹
})
.disposed(by: disposeBag)
举一个实际应用的例子
button
.rx
.tap
.map { URL(string: "http://httpbin/org")! }
.flatMap(URLSession.shared.rx.JSON)
.subscribe { event in
switch event {
// ...
}
}
.addDisposableTo(disposeBag)
可以理解为
Observable<Void> -> Observable<Foundation.URL> -> Observable<Observable<jsonData>>
这样的转换。
需要注意的是 第一map传入的闭包返回的是 URL
{ _ -> URL in
retrun URL(string: "http://httpbin/org")!
}
而第二步flatMap传入的闭包返回的是 Observable<jsonData>
public func json(url: Foundation.URL) -> Observable<jsonData> {
return json(request: URLRequest(url: url))
}
Rxswift 中 Observable 和 Swift 的 [] 数组 很像。
Swift 的 flatMap 可以使 [[1,2,3,4,5],[6,7]] -> [1,2,3,4,5,6,7]
Rxswift 的 flatMap 可以使 Observable<Observable
还可以理解为 第二个映射 (map/flatmap 都可以理解为映射) 是一个升维的过程 (从一维变二维) 需要用flatmap函数将这个升起的维度降回来,拿到咱们真正要想要的 *Observable
此外 flatMap 还有两个兄弟方法,flatMapFirst flatMapLatest ,比如在网络请求未完成时,再次点击了 Button ,flatMapFirst 会忽略第二次点击 Button 的事件,不会进行网络请求;而 flatMapLatest 会取消第一次的网络请求,以第二次的网络请求覆盖掉。
用Observable还是Driver
Driver 优势在使代码明显在主线程完成,相对切换线程就比较麻烦。
RxSwift中的错误机制
RxSwift中,多属于异步调用API,建议用范型枚举将错误和正确的结果包装起来传递下去。
enum Result<T> {
case value(T)
case error(ErrorProtocol)
}
provider.request(GitHubAPI.Authorize)
.map { result -> Result<String> in
switch result {
case .value(let value):
return Result.value(value["token"].stringValue)
case .error(let error):
return Result.error(error)
}
}
.flatMap { result -> Observable<Result<JSON>> in
switch result {
case .value(let token):
return provider.request(GitHubAPI.AccessToken(code: token))
case .error(let error):
return Observable.just(Result.error(error))
}
}
.subscribeNext { json in
// ...
}
总结
RxSwift 函数式编程:函数式思维,其实就是组合子逻辑,用简单的几个函数组合来构建复杂逻辑,始终以高阶的角度去表达问题,而非依赖副作用。严格意义上的函数式编程意味着不使用可变的变量,赋值,循环和其他命令式控制结构进行编程。 ReactiveX是Reactive Extensions的缩写,一般简写为Rx 。Rx是一个编程模型,目标是提供一致的编程接口,帮助开发者更方便的处理异步数据流
Rx的Observable模型让你可以像使用集合数据一样操作异步事件流,对异步事件流使用各种简单、可组合的操作。
过滤(filter)、选择(select)、变换(transform)、结合(combine)和组合(compose)多个Observable
性能上-高阶数据算法 可以讲任务分成小块儿 利用多核运算 性能快 。 安全上-因为不修改参数值,所以是线程安全 因为都是值类型 输入一样输出就一样 思想上-用简单的几个函数组合来构成复杂的逻辑,始终以高价的角度去表达问题,而非依赖副作用,异步操作primose
自我总结的函数式编程: 像以前服务器的api不是Restful风格一样,其实操作数据的方式可以抽象归纳为几种比如:增删改查就够了。而函数式编程则是把抽象归纳操作数据的几种方法 比如:Map 转换 Reduce 迭代 filter 筛选 connect 连接 combine 组合 等方法,具体的实现都用block封装起来,
Wiki 百科: 它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。函数编程语言最重要的基础是λ演算(lambda calculus)。而且λ演算的函数可以接受函数当作输入(引数)和输出(传出值)。