半函數式編程
『壹』 什麼是函數式編程思維
回答都有跑題,show概念之嫌,題主問的是函數式思維,這個問題我一直在思考,畢竟是方法論,能力有限,只能從切身實踐告訴你
1.表達式化
在
最初的時候,需要轉變觀念,去可變數,去循環,把命令式改成表達式,注意,這只是把你丟在荒山野嶺讓你感受一下,離開熟悉的環境,地球依然在轉,但是有個
重點,那就是一切都是表達式; 為什麼是表達式呢?這個問題就像為什麼魚在水裡?
因為函數式建立在lambda演算之上而非圖靈機,只不過兩者被證明等價,所以你可以在你的機器上跑全是表達式的代碼,就如有人證明天空適合魚生存,所以
魚可以在天上游
當你接受了魚可以在天上游之後,就該上正餐了
1.5 數據與行為分離
這也是和面向對象不一致的地方,面向對象強調數據與行為綁定,但函數式不是,確切的說函數式 函數與數據等價,所以你才可以將函數當參數與返回值,你在設計時,切勿讓數據自己長腿能跑,其次,行為必須消除副作用,不可以偷偷把數據改了,習慣第一條後,應該不會的
2.高階邏輯
用
了函數式,就不要在想循環,賦值這些低階邏輯了,而應該更高階的思考問題,這比轉化表達式更難,函數式又叫聲明式,也就是你要做什麼,只要說一下就行,而
非寫個遍歷,做個狀態判斷,用函數式你不需要考慮這些,你不知道函數式的列表是怎麼遍歷的,中間向兩邊?
從後往前?這也是為何函數式適合並發的原因之一,你想知道列表中大於3的數有多少,只要,list.count(_ > 3)
而不是寫循環,你可以直接寫你的業務,不要拘泥於細節,有點像sql, 你需要什麼告訴電腦就行,你或許會問,count foreach filter
這些函數怎麼來的? 因為有了他們你才不需要寫循環,他們把你留在高階邏輯中,這個問題的答案請看下面
3.組合子邏輯 或又叫 自底向上的設計
函
數式和OO是反的,面向對象是自頂向下的設計,函數式是自底向上的設計,也就是先定義最基本的操作,然後不斷組合,不斷堆積以滿足你的所有需要,如sql
定義了select, from, where...這幾個組合子,來滿足你的查詢需求,同理函數式語言會提供foreach,
map等組合子(操作)來滿足你的需求,所以你必須自下而上的設計你的代碼結構,並且滿足你的需求,當你只用組合子寫代碼時,你會發現你寫的全是高階邏輯
如
果這些已有組合子滿足不了你,你就得自己寫,foreach不行,你就自己寫遞歸,我告訴你,遞歸背後也是組合子,這里一些'大神'應該不知道,在圖靈機
里,遞歸就是方法不斷調用自己沒什麼好說的,但是在lambda演算中,匿名函數是沒法調用自己的,所以遞歸是用Y組合子(又叫不動點組合子)把遞歸函數
自己求解出來再調用的,這才可以實現遞歸,並與圖靈機的循環等價,有點跑題了,總之要想順手的寫函數式,最好用面向組合子的設計,注意,不是必須,組合子
演算和lambda演算可以相互轉化,也就是,你完全可以寫一堆雜亂的表達式,但沒有組合子邏輯來得清爽,Haskell大規模使用monad這個特殊組
合子,始其變得統一整潔
好了,總結一下
函數式思維,其實就是組合子邏輯,用簡單的幾個函數組合來構建復雜邏輯,始終以高階的角度去表達問題,而非依賴副作用。
知道這點,你用java也可以寫函數式代碼了
但是,這也只是本人積累得來的感悟,絕不敢大肆伸張這就是函數式,我也在不斷研究中,如有問題,還望大神指正
『貳』 在python常說的函數式編程是什麼意思
函數式編程相對應的是命令式編程
比方說你要定義一個方法
命令式編程如下:
deffunc1():
<expression()>
而同樣功能的函數式編程如下:
func1=lambda:<expression()>
『叄』 函數式編程的特點
其實函數式編程的話你也要學計算機就會知道。
『肆』 什麼是函數式編程
在維基網路中,已經對函數式編程有了很詳細的介紹。
那我們就來摘取一下Wiki上對Functional Programming的定義:
In
computer science, functional programming is a programming paradigm that
treats computation as the evaluation of mathematical functions and
avoids state and mutable data.
簡單地翻譯一下,也就是說函數式編程是一種編程模型,他將計算機運算看做是數學中函數的計算,並且避免了狀態以及變數的概念。
『伍』 求科普什麼是函數式編程語言
實際上,函數式編程沒有一個嚴格的官方定義。嚴格上來講,函數式編程中的「函數」,並不是指我們編程語言中的「函數」概念,而是指數學「函數」或者「表達式」(例如:y=f(x))。不過,在編程實現的時候,對於數學「函數」或「表達式」,我們一般習慣性地將它們設計成函數。所以,如果不深究的話,函數式編程中的「函數」也可以理解為編程語言中的「函數」。
『陸』 式編程,命令式編程()和函數式編程的區別
編程語言主要有四種類型
聲明式編程:專注於」做什麼」而不是」如何去做」。在更高層面寫代碼,更關心的是目標,而不是底層演算法實現的過程。
ex: css, 正則表達式,sql 語句,html, xml…命令式編程(過程式編程) : 專注於」如何去做」,這樣不管」做什麼」,都會按照你的命令去做。解決某一問題的具體演算法實現。
函數式編程:把運算過程盡量寫成一系列嵌套的函數調用。
函數式編程強調沒有」副作用」,意味著函數要保持獨立,所有功能就是返回一個新的值,沒有其他行為,尤其是不得修改外部變數的值。
所謂」副作用」(side effect),指的是函數內部與外部互動(最典型的情況,就是修改全局變數的值),產生運算以外的其他結果。
『柒』 函數式編程有什麼弊端
我接觸過Haskell、Clojure和其他語言,也做過PL的「研究」。可以淺談一下:
函數的復雜度
分析Haskell程序的時間和空間復雜度是很麻煩的。首先編寫Haskell程序往往是很多「重用」內置/自定義數據結構,以實現數據持久性(或「不變性」)可以增加空間和時間消耗(實現策略有很多,但採取臨時解決方案不影響永久治癒),優點是控制副作用。然後,函數組合和高階函數可能代價昂貴,可以生成額外的中間數據。其優點是抽象能力強,模塊化是有益的。最後,惰性評價使過程評價模型復雜,濫用可導致效率的降低。功能語言的分析工具也較少。
但是這些提供了細粒度的模塊化,程序員需要更多的「設計」。「使用函數式編程的程序員必須努力確保程序使用更小、更簡單、更通用的模塊,」Huges說。這是一個挑戰。
而且,模塊之間的交互也是一個問題。
『捌』 為什麼這兩年函數式編程又火起來了呢
函數式編程的好處
由於命令式編程語言也可以通過類似函數指針的方式來實現高階函數,函數式的最主要的好處主要是不可變性帶來的。沒有可變的狀態,函數就是引用透明(Referential transparency)的和沒有副作用(No Side Effect)。
一個好處是,函數即不依賴外部的狀態也不修改外部的狀態,函數調用的結果不依賴調用的時間和位置,這樣寫的代碼容易進行推理,不容易出錯。這使得單元測試和調試都更容易。
不變性帶來的另一個好處是:由於(多個線程之間)不共享狀態,不會造成資源爭用(Race condition),也就不需要用鎖來保護可變狀態,也就不會出現死鎖,這樣可以更好地並發起來,尤其是在對稱多處理器(SMP)架構下能夠更好地利用多個處理器(核)提供的並行處理能力。
3.cpu的性能提升將體現在核數增加,這樣並行的程序運行速度會越來越快。並行的程序的寫法就是找出不能並行的地方,其他地方都盡量並行。
如果要這樣寫,最需要避免的事情就是賦值。函數式編程的本質就是,規避掉「賦值」。
『玖』 到底什麼是函數式編程,能做什麼,是不是會崛
首先,比較被公認接受的,對於具體的語言來說,是指有一個「一等函數」(first class function)。不過函數這個概念本身就比較混亂。只能具體舉例。比如,C++的函數就不是一等的,因為對象類型的值能被傳參能被返回,函數類型的值就不行(會退化為函數指針)。換句話說C++的內建的「函數」是閹割的。這類函數式語言一開始以Lisp為代表,基本的理論基礎是λ演算。
其次,關於表達式和語句。語句一開始就是Fortran的語法。這種設計其實沒有必要,因為脫離更基本的表達式語法,也沒法表示計算。Lisp就沒有在語法上特意區分出語句。函數式語言的語法設計習慣上不使用語句,因為具有一等函數的表達式的表達能力通常已經足夠強。C這樣的語言的「語句」除了表達確定的求值順序外,也就是一種無謂地指令式風格的習慣罷了。
第三,關於存儲可變狀態。修改狀態(典型地,賦值)的程序是指令式範式的。函數式的範式通常避免無謂地修改狀態。
極端的情況是語義規則不提供修改狀態的介面,如Haskell以及C++的模板元編程,這樣的風格稱為所謂的「純函數式」。
純函數式的「函數」不具有修改值這類副作用(對於C/C++來說,讀volatile對象也是副作用),所以對於確定的輸入可以保證有確定的輸出,且求值時函數調用可以以任意次序被整個替換——非純函數式因為副作用順序的不同會導致程序行為的不同。這種性質被稱為引用透明性(referential transparency)。
但是注意,純函數式並不是實現引用透明的必要條件,保證內部狀態的修改不影響參數和返回值的關聯同樣能做到。考慮到和通用需求的差異造成的困難,對於自律的用戶來說,純函數式其實沒什麼必要,到頭來只是一種限制而已。『拾』 Scala的implicit如何使用需要注意什麼
習函數式編程
閱讀DDD巨著《Patterns, Principles, and Practices of Domain-Driven Design》程Scott第5章提使用函數式編程語言配合貧血模型實踐DDD種思路激發我限遐想
軟體發領域我已經擁許抽象論量實現技術我認切歸根結底都類思維軟體發領域具體表達式類認識析軟體所要解決業務領域問題思考內容外乎由兩部組:『業務流程』與『業務規則』前者答業務先做做問題;者則答遇情況應該做問題兩者結合我需要業務結或者叫作實現業務目標
再想想目前習掌握面向象系列何述思維結映射軟體呢我認:
於業務流程我其表達若干象間合作比UML序列圖象與消息進具化具體類及其職責比類及其若干業務
於業務規則我其表達若干判斷邏輯比UML流程圖判斷支進具化業務if-else語句或者再復雜點表達工廠、策略等設計模式實際運用
我認於復雜業務規則梳理象數歸納進行演繹:假設函數y=f(x)給定x定義域確定y值域特別排列組合等面些問題經採用遞歸式解決所角度講函數式編程更貼近類思維習慣所讓我自目光轉向
選擇Scala
選擇具體函數式編程語言我首先想同能支持面向象編程即便LISP作函數式編程語言先祖誕已達半世紀單純函數式編程語言與面向象編程語言相比抽象領域概念、組合系統模塊、實現信息隱蔽等面存定差距所直沒軟體發主流
信息隱蔽原理:西安電科蔡希堯與陳平師於1993合作版《面向象技術》書描述:需求求解離;相關信息——數據結構算集模塊其模塊隔離能隨便訪問模塊內部信息
其由於我語言路線Pascal → C → C++ → C#所我希望能選擇種風格近似於C、強類型函數式編程語言比較F#、R、ErLang等幾種見函數式編程語言我終選擇Scala
Scala何優勢
註:內容節選翻譯或參考自《Programming in Scala》第1章、第3章《Programming Scala》第6章算完整意義
函數式編程優勢
純函數沒副作用論何何於函數y=f(x)給定x必定y產二義結論於代碼測試並發由於給定輸入必定預期輸受其素干擾所能效減少Bug產
函數式編程量使用immutable值意味著函數運算結總創建新實例避免通並發環境防止數據共享沖突採取保護機制盡管需要額外Copy操作Scala針性提供高效Copy實現及延遲計算等彌補機制
函數等公民函數作表達式部藉由函數間嵌套、組合實現復雜判斷邏輯
Scala語言本身優勢
Scala面向象與函數式編程混合語言所能效結合二者優點
Scala屬於Java態圈JVM平台與Java起編譯運行所許Java框架、工具都直接應用於Scala語言編寫項目
Scala視切數據類型皆象且支持閉包、lambda、by-name參數等特性語簡潔明快
Scala使用Actor作並發模型與Akka框架自契合種區別於傳統、基於數據共享、鎖主要機制並發模型其特點於Actor基本單位、沒數據共享、基於消息傳遞實現Actor間協作效避免死鎖、減少競爭
朝要轉向數據領域Spark型框架作支撐知乎:與 Hadoop 比何看待 Spark 技術
Scala實踐DDD何意義
說我根本目要Scala作實現DDD主要武器試想Scala我實現DDD程能哪些幫助呢我暫且胡侃亂謅:
表示值象、領域事件等元素更直觀值象、領域事件DDD都應該immutable往採取POCO形式表示現改用Scalaval及case class表示語層面直觀表明修改
類層面實現CQRS語支持用ScalaFunction(返類型非Unit)應CQRSQuery保證類沒副作用;用Procere(返類型Unit)應CQRSCommand明確表明類產修改狀態等副作用同語層面能二者進行明確區
模式匹配豐富函數操作除則表達式Scala形式模式匹配語提取數據、完數據組聚合等運算、實現邏輯判斷提供強支持比定義def sum_count(ints:Seq[Int) = (ints.sum, ints.size)函數我調用1至6整數序列整數值合計及該序列尺寸:val(sum, count) = sum_count(List(1, 2, 3, 4, 5, 6))
實現DSL提供力支持Scala自帶解析框架加靈函數語支持要自實現套DSL及其相應語解析器再困難比配置文件條配置語句表示退休條件齡達60周歲或者工齡屆滿30:retire = (Age >= 60) || (ServiceLength >= 30)往式自寫語解析器條文本轉換相應Specification象扔給聚合使用現Scala幫助使編寫語解析器環節工作量減少
合理高階函數設計使規則編寫簡化比打折規則、費用報銷規則往能需要若干層if-else嵌套現則通高階函數幅簡化我強烈推薦劉光聰先視頻Refactoring to Functions劉先重構程發現高階函數強
Actor高效並發打基礎Actor
內部完全自治自帶用於存儲消息mailbox與其Actor能通消息進行交互每Actor都並發基本單位些特點非適合於
採取Event
Sourcing式實現DDD每聚合都比Actor聚合內部始終保持數據強致性聚合間交互領域事件則比Actor間
消息聚合間藉由領域事件Saga保證數據終致性
TraitAOP利器TraitScala另特色象AOP織入能態給某類型注入或者結構比配合類Circuitwith面4Trait定義val circuit = new Circuit with Adders with Multiplexers with Flipflops with MultiCoreProcessors創建帶加器、乘器、觸發器核處理器元件
隱式實現類型擴展提供支持應C#靜態擴展Scala通implicit實現數據類型擴展提供便捷Trait外另功能擴展手段
能降低見BDD框架習本盡管點能比較牽強我努力摸索何BDD與DDD結合見Cucumber、Spock等些BDD框架其語與Scala比較相近所我才說
哪些Scala習資料
我目前主要習資料並衷歡迎各位留言補充
書籍
Programming in Scala:由Scala語言設計師Martin Odersky編寫循序漸進配合量實例入門必讀吧
Programming Scala:視角與面本點沒Scala語言基礎覺困難適合掌握基本語溫故知新
線文檔與視頻
Scala 官文檔:Scala官網作尋找資料發點錯
Scala 課堂:文版Scala基本語線課堂
Scala Synatax Primer:由Jim McBeath整理Scala語概要字典用
The Neophyte』s Guide to Scala:名Scala入門指南Scala提取器Extractor作實例始
Scala 初指南:面本指南譯本
Effective Scala:文版Scala高效編程
SBT文入門指南:Scala Build Tool
社區
Scala 文社區:算躍原懂
Scala User:Scala入門者聚集沒Stack Overflow嚴格需要點爬牆身手
SDK及IDE
Java SE:先裝
Scala SDK:再裝
SBT:裝
IntelliJ IDEA:裝能比較便始Scala編程
寫
近讀書雜DDD、BDD、Scala、Cucumber及Java基礎等等都涉及真恨口吃胖由於間精力限所
現知識消化問題遲遲沒進入致用環節能先紙談兵歹先自習程些思考、看東西先記載備
需