是否Future/promise 实现原理模式 能实现的FRP都能更好的实现

,INTP,软件手艺人,诺铁@新浪微博,ThoughtWorks咨询师
资深咨询师
题主别匿名啊,让我拉黑你
题主别匿名啊,让我拉黑你
减少全局变量。。。
减少全局变量。。。
当年德国人的军队也是训练有素、装备精良、将领智勇。。。。。。&br&它如何被人评价不是看它内部的组织如何,而是看它做出来的事情,比如屠杀犹太人
当年德国人的军队也是训练有素、装备精良、将领智勇。。。。。。它如何被人评价不是看它内部的组织如何,而是看它做出来的事情,比如屠杀犹太人
你描述的智能时代还没到来
你描述的智能时代还没到来
以后会有很多种&b&主流web开发语言。&/b&&br&go也可能会是其中之一。
以后会有很多种主流web开发语言。go也可能会是其中之一。
我们也有啊,别墅不是吗?
我们也有啊,别墅不是吗?
歌唱行业是什么?
歌唱行业是什么?
现在吵这些没用,到了那个收入价值观自然会变化的。。。
现在吵这些没用,到了那个收入价值观自然会变化的。。。
av啊。。。
av啊。。。
都重要。&br&很多时候只读书不造一下轮子其实没有真懂。&br&所以拿造轮子作为读书的辅助手段好了。
都重要。很多时候只读书不造一下轮子其实没有真懂。所以拿造轮子作为读书的辅助手段好了。
不写代码的架构师容易变得保守。&br&&br&架构是考虑了各种因素(尤其是业务安全方面)之后做出的妥协,对于开发团队来说是种种要求和限制。 这种限制往往是限制开发团队的开发效率和创造力的。&br&&br&脱离编码的架构师容易失去对一线业务环境和技术环境变化的敏感,沾沾自喜于自己设计的架构和制定的规范阻挡了一次又一次潜在的错误和损失。偶尔发生的事故往往也会发现是开发团队某些方面没有贯彻架构要求,结果往往是更进一步的加强约束,体会不到其对开发效率的副作用。&br&&br&这些都是以前亲身体会到的事实,遗憾的是离职去另一家公司后才发现,当时真的是当局者迷。 其实我都还是一直有编码的,只是编的少了就会犯这种错,更别说不编码了。&br&&br&在当今这个精益创业时代,快速试错和创新才能生存,在一线参与编码的架构师更能够随时想着哪些地方可以给团队“松绑”,哪些新技术可以突破以前设计架构时的一些限制。躲在后方就只会拖前线的后腿了。
不写代码的架构师容易变得保守。架构是考虑了各种因素(尤其是业务安全方面)之后做出的妥协,对于开发团队来说是种种要求和限制。 这种限制往往是限制开发团队的开发效率和创造力的。脱离编码的架构师容易失去对一线业务环境和技术环境变化的敏感,沾沾自…
haskell&br&c++&br&go&br&scala&br&javascript&br&这下无所不能了~~~
haskellc++goscalajavascript这下无所不能了~~~
没说被包围啊,如果地形可以,还是有机会拉散对手阵型,逐个击倒的。当然还要看一群到底是多少人,持械到底持的什么械。
没说被包围啊,如果地形可以,还是有机会拉散对手阵型,逐个击倒的。当然还要看一群到底是多少人,持械到底持的什么械。
我是先学haskell的,学到MonadTransformer卡住了。。。&br&后转投Scala,掌握无压力。&br&《Functional Programming in Scala》 就是给想学scala的OO程序员补上haskell那课的~~
我是先学haskell的,学到MonadTransformer卡住了。。。后转投Scala,掌握无压力。《Functional Programming in Scala》 就是给想学scala的OO程序员补上haskell那课的~~
医院内部都不能组织起游行,还指望别人能救吗?
医院内部都不能组织起游行,还指望别人能救吗?
看快播案怎么判吧,你就知道能不能要求赔偿了
看快播案怎么判吧,你就知道能不能要求赔偿了
我是FRP粉&br&----------------------
的回答----------------------------------&br&frp表现出能够“消除回调”的能力。但是我用frp来设计系统的时候和我用future来解决问题的时候完全不是一种思维方式。也不觉得在所有场景下FRP的实现都“更好”&br&-------------------------------------------------------------------------------&br&也许随着对FRP理解和应用的深入,我会改变答案,或许FRP确实都能实现的更好,从目前的经验(scala widok, elm-lang,scala future/promise)还不足以让我认为FRP“都更好”
我是FRP粉----------------------
的回答----------------------------------frp表现出能够“消除回调”的能力。但是我用frp来设计系统的时候和我用future来解决问题的时候完全不是一种思维方式。也不觉得在所有场景下FRP的实现都“更好”------…
我觉得是精力管理的问题。人的精力有限,那边增加投入,这边就要减少投入。&br&视频沟通需要付出额外的精力,比如你男朋友一不小心就让你觉得他敷衍了,实际上他可能正在百度你的问题。&br&文字沟通消耗精力少得多,面部反应的精力可以省下来了(面瘫脸?) 反而可以投入更多精力到解决问题上。&br&&br&&br&&br&当然也可能只是碰巧你男朋友正在处理别的事情,偶尔一次个案实在没有多大分析的价值~~~
我觉得是精力管理的问题。人的精力有限,那边增加投入,这边就要减少投入。视频沟通需要付出额外的精力,比如你男朋友一不小心就让你觉得他敷衍了,实际上他可能正在百度你的问题。文字沟通消耗精力少得多,面部反应的精力可以省下来了(面瘫脸?) 反而可…
这玩意出来很久了,没看到什么人用,我现在想不到什么场景必须要用这种技术来搞。
这玩意出来很久了,没看到什么人用,我现在想不到什么场景必须要用这种技术来搞。
已有帐号?
社交帐号登录
无法登录?
社交帐号登录Scala(12)
Functional Programming(12)
译者注:原文出处,翻译:
在中,我介绍了Future类型,它的内在逻辑,以及如何使用它来写出可读性强且可可组合的异步执行代码。在文章里,我也提到Future只是完整拼图的一部分:它是一种只读类型,让你可以以一种优雅的方式来引用将被计算出的结果并且处理异常。为了让你能够从Future中读取到计算好的值,还需要让负责计算的代码有办法把计算好的值存起来。在本文中,我就会来说明如何借助Promise类型来实现,并提供一个如何在实际代码中使用Future和Promise的指南。
在前篇关于Future的文章中,我们写过一组传递给Future的伙伴对象的apply方法的代码,并且导入了ExecutionContext作为默认执行上下文,它就神奇的异步执行了那些代码,并且返回包装在Future中的结果。
虽然这是一种简单易行的方法来构造一个Future,还是有另外一种方法来生成Future实例并最终以成功或失败结束。Future提供一个仅用于查询的接口,Promise作为伙伴类型让你通过将结果置入来完成一个Future。这仅可以被完成一次。一旦Promise完成了,它就不能够被修改。
Promise实例总是被关联到一个Future实例。试着在REPL里再一次调用Future的apply试试,你一定会注意到Future返回的是Promise类型:
import concurrent.Future
import concurrent.ExecutionContext.Implicits.global
val f: Future[String] = Future { &Hello world!& }
// REPL output:
// f: scala.concurrent.Future[String] = scala.concurrent.impl.Promise$DefaultPromise@793e6657
你得到的对象是一个DefaultPromise,它同时实现了Future和Promise。当然,Future和Promise可以被分别实现的。
上面的小小的例子表明除了通过Promise,显然没有其他途径完成一个Future - Future的apply方法仅仅作为助手方法方便你实现。
现在让我们来看看如何直接用Promise类型来做。
承诺一个光明的未来
当讨论承诺能否会被兑现时,生活中有一个明显的例子,关于政治家,选举,竞选宣言及立法过程。
假设获胜的政治家承诺过减税,这可以用一个Promise[TaxCut]来表示,通过调用Promise的伙伴对象的apply来生成,如下面的例子:
import concurrent.Promise
case class TaxCut(reduction: Int)
// 在apply方法中提供类型参数:
val taxcut = Promise[TaxCut]()
// 或者明确常量的类型,以便让Scala的类型推断系统能工作:
val taxcut2: Promise[TaxCut] = Promise()
一旦你生成了Promise,你可以通过调用Promise实例的future方法获得属于它的Future:
val taxcutF: Future[TaxCut] = taxcut.future
返回的Future可能和Promise不是同一对象,但是多次调用Promise的future方法确定无疑的总是返回同样的对象,这维持了Promise和Future的一对一关系。
完成一个Promise
一旦你做出了一个Promise并且告诉世人你将在可见的Future来达成,你最好尽其所能确保能实现诺言。
在Scala里,你可以成功或失败的完成一个Promise。
交付你的Promise
要成功地完成一个Promise,你调用它的success方法并传递一个结果值,值是对应的Future应该拥有的:
taxcut.success(TaxCut(20))
一旦你这样做了,Promise实例就会变成只读,任何试图写的操作都会抛出异常。
并且这样的方式完成Promise也会同时让相关联的Future成功完成。任何成功或完成的处理器都将被调用,或者当你在map那个Future时,map方法将被执行。
通常,完成Promise和完成Future的操作不会发生在同一个线程上。更多的场景是你生成了Promise并且在另一个线程开始进行结果的计算,立刻返回尚未完成的Future给调用者。
为了演示,我们来拿减税承诺举例:
object Government {
def redeemCampaignPledge(): Future[TaxCut] = {
val p = Promise[TaxCut]()
println(&Starting the new legislative period.&)
Thread.sleep(2000)
p.success(TaxCut(20))
println(&We reduced the taxes! You must reelect us!!!!1111&)
请不要被例子里的Future的apply方法的用法而困扰。我这样用它只是因为它让我很方便的异步执行一段代码。我也可以在一个Runnable里实现计算过程(包含了sleep的那段代码),并让Runnable异步的跑在ExecutorService,当然代码会冗余一些。这里的重点是Promise不再调用者线程里完成。
让我们来兑现竞选承诺并且为Future注册一个onComplete的回调函数:
import scala.util.{Success, Failure}
val taxCutF: Future[TaxCut] = Government.redeemCampaignPledge()
println(&Now that they're elected, let's see if they remember their promises...&)
taxCutF.onComplete {
case Success(TaxCut(reduction)) =&
println(s&A miracle! They really cut our taxes by $reduction percentage points!&)
case Failure(ex) =&
println(s&They broke their promises! Again! Because of a ${ex.getMessage}&)
如果你执行这段代码几次,你会发现屏幕的输出是不可预测的。最终完成的处理器会被执行并且命中success的分支。
像个绅士一样违反承诺
作为一个政治家,你大部分情况下是不会遵守承诺的。作为Scala开发者,你有时候也没有其它选择。如果真的有不幸发生了,你仍然可以通过调用failure方法并传递一个异常给它来有好的结束Promise:
case class LameExcuse(msg: String) extends Exception(msg)
object Government {
def redeemCampaignPledge(): Future[TaxCut] = {
val p = Promise[TaxCut]()
println(&Starting the new legislative period.&)
Thread.sleep(2000)
p.failure(LameExcuse(&global economy crisis&))
println(&We didn't fulfill our promises, but surely they'll understand.&)
redeemCampaignPledge()将会最终违反承诺。一旦你通过调用failure来完成了一个Promise,它就会变得不可写,和调用success的情形一样。相关联的Future现在也会以Failure结束,因此上面的回调函数将会进入failure的场景。
如果你的结算结果是Try类型,你可以通过调用complete来完成一个Promise,如果Try是一个Success,那么相关联的Future将会成功完成,并包含了Success里的值,如果Try是个Failure,Future将会以失败完成。
基于Future的编程实践
如果你为了提高应用的可扩展性而采用基于Future的架构,你必须设计你的程序从下至上都为非阻塞,之基本上意味着你应用的所有层级的函数都要为异步且返回Future。
现如今一个很好地场景就是开发web应用。如果你采用了现代的Scala Web框架,它会让你返回类似Future[Response]类型的响应而不用阻塞直到返回完成了的Response。这很重要因为它让你的web服务器以相对较少的线程来处理巨量的连接。通过确保使用Future[Response],你可以最大效率的使用web服务器的线程池资源。
最后,你的应用中的一些服务可能会多次访问数据库层以及/或者一些外部的webservice,接收到一些Future,然后将这些Future组合并返回一个新的Future,所有这些都在一个可读性很好地for语句里实现,就像你在前篇文章中看到的一样。web层再将这Future转化成Future[Response]。
那么在实践中你究竟应该如何来实现呢?下面有三个不同的场景必须考虑:
你的应用基本上一定会涉及到很多的IO操作。例如,访问数据库,或者作为客户端访问别的webservice。
只要有可能,就应该使用基于Java 非阻塞IO实现的函数库,可以是直接采用Java的NIO API的或者是通过类似Netty来实现的。这样的函数库也能以有限数量的线程池实现大量的访问连接。
自己开发类似的函数库是少数几个有理由直接使用Promise类型的地方之一。
有时候没有基于NIO的函数库可用。例如,目前在Java世界大多数数据库驱动还是使用的阻塞式IO。如果你在响应一个HTTP请求的过程需要通过这样的驱动来查询数据库,这样的调用会在web服务器的线程中执行。为了避免那样做,将和数据库打交道的代码封装在一个Future块中,类似:
// get back a Future[ResultSet] or something similar:
queryDB(query)
到目前为止,我们一直在用隐式的全局ExecutionContext来执行类似的Future代码块。也许为这样的数据库访问创建一个专用的ExecutionContext是一个不错的想法。
你可以从Java的ExecutorService中创建一个ExecutionContext,这意味着你可以为这个线程池做一些特定的优化和调优而不影响其他线程池:
import java.util.concurrent.Executors
import concurrent.ExecutionContext
val executorService = Executors.newFixedThreadPool(4)
val executionContext = ExecutionContext.fromExecutorService(executorService)
长周期的计算
有赖于你的应用的特性,也许会存在执行时间比较久的计算任务,它们完全没有IO请求而是CPU消耗型。这些计算也不应该在web服务器的线程池里执行。因此你也应该将它们置入Future:
longRunningComputation(data, moreData)
同样的,如果存在执行时间久的计算,为它们创建一个单独的ExecutionContext也是个好主意。如何调优不同的线程池是高度依赖于不同应用特点的,也不是本文的所要讨论的范畴。
在本篇中,我们探索了Promise,它是基于Future的并行架构的可写的部分,讨论了如何用Promise来完成一个Future,最后讲到实践中如何使用Future。
在下一篇中,我们会回头再看看并发的问题并且检验Scala的函数式编程如何帮助你写出可读性更好地代码。
作者:Daniel Westheide,
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:2704次
排名:千里之外
译文:13篇,理想主义码农,非战斗人员请迅速撤离
Scala工程师
&a href=&///?target=http%3A//www.slideshare.net/InfoQ/embedded-java-and-mqtt& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&slideshare.net/InfoQ/em&/span&&span class=&invisible&&bedded-java-and-mqtt&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&br&&a href=&///?target=https%3A///andsel/moquette& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&GitHub - andsel/moquette: Java MQTT lightweight broker&i class=&icon-external&&&/i&&/a&&br&或构建于Netty之上的私有协议
或构建于Netty之上的私有协议
以下纯属个人理解,如有雷同,那就雷同吧!&br&首先得先确定我们的讨论的状态是什么&br&有状态是指:&blockquote&我可以把我的眉毛摘下来,( ??ω?)ノ??摘下,( ??ω??)安上, ( ??ω?)ノ??摘下,( ??ω??)安上,╰??( ?ω?)ノ??两边都摘下, ( ??ω??)安上。。&br&&/blockquote&无状态是指:&br&&blockquote&( ??ω??)卧槽,摘不下来&/blockquote&--------------------&br&卖萌结束,回到正常,&br&一般所说的状态可视为&reference, store, value& 这样的三元组(引用,存储, 值),reference也可以叫index或pointer或location,store则可看做是一个接受一个reference返回value的函数(具体实现可以是内存单元,或外部文件等),value就是存储的值了;&br&状态变化则是指两方面了1.reference的改变,2.reference所指的value改变,一般情况下指后者(将名称绑定机制和赋值机制分开,如Java等语言);&br&为什么要有上面的状态?这和为毛往数据库里插数据是一样的:共享状态,它是一个程序不同部分之间的“隐式通信通道”&br&&br&那函数式编程的无状态就是指,以上两者都是不可变的,那么上面的三元组也可以不需要了,也就是变量名称绑定和赋值是一起的,你不能搞一个a 是 undefine。&br&为什么?根源如此。稍微了解一点历史和lambda calculi就知道,lambda 演算中项只能做规约和代换,或者说数学上就是如此,求解一个复杂表达式如 y = [非常复杂的表达式] 到最后得到:y = 2x,那么y就是一个Nat -& Nat的函数,如果得到y = 2,那么y就是2,很自然,是不是?无状态,是不是?&br&无状态/不共享状态的好处是啥?网上宣传的太多了,什么一个函数同样的参数不管调用多少次都会是返回一样的结果(测试与调试),并行计算(这里尤其多),推理优化等。。。&br&那么无状态真的大丈夫?当然不是,所以才会有CPS,Monad等东西出来,要么通过膜法去模拟有状态,要么就直接上(如:Scala的var关键字)&br&----------------------&br&“副作用” 和上面所说的状态不是一个东西,状态的改变可视为副作用,它是一种“计算效应”
以下纯属个人理解,如有雷同,那就雷同吧!首先得先确定我们的讨论的状态是什么有状态是指:我可以把我的眉毛摘下来,( ??ω?)ノ??摘下,( ??ω??)安上, ( ??ω?)ノ??摘下,( ??ω??)安上,╰?…
不会C++模板元,但是你的问题其实相当于在问什么是functional programming?&br&FP并没有明确的定义,只能通过个人(浅显的)理解来回答了:&br&&br&函数式编程是指一种编程范式,其first-class-value是函数,并有如下properties:&br&1. 因为函数为first-class-value,所以函数可以当参数和返回值传递&br&(这就产生了lambda表达式/匿名函数)&br&2. immutable,也可叫purity或 referentially transparent&br&referentially transparent可由以下两条规则概括:&br&&blockquote&&p&An expression e is &em&referentially transparent&/em& if for all programs p, every occurrence of e in p can be replaced with the result of evaluating e without changing the result of evaluating p.&/p&&p&A function f is &em&pure&/em& if the expression f(x) is referentially transparent for all referentially transparent x.&/p&&/blockquote&3. (我不知道,欢迎补充)&br&支持函数式编程的语言(或称函数式语言)至少要实现/支持以上properties&br&(没有显式支持以上特性的语言,也可通过函数指针等来做非语言层面的支持)&br&(函数式编程源于lambda calculus,这点楼上说的很清楚了;也正是lamdba calculi 才使得其具有以上特性,不然就不可做规约与代换了)&br&&br&其它的如Generalizing Functions,ADT,Pattern Matching,Lazy Evaluation,CPS...都可视为上面特性的扩展/附加,也是FP及type theory不断发展的产物,为了更加类型安全,为了更好的Functional Composition(函数/计算的组合)&br&到后面各语言引入各种Side Effect机制,也是为了更好的函数组合;category theory和abstract algebra里面的一些东西(如:Functor, Monad...)也被拿过来用于实现更好的FP(并且first-class-value 也慢慢转变为了type)&br&&br&函数式编程的思想就是上面所说的Functional Composition&br&谢@&a href=&/people/lz1996& class=&internal&&骆铮&/a&邀
不会C++模板元,但是你的问题其实相当于在问什么是functional programming?FP并没有明确的定义,只能通过个人(浅显的)理解来回答了:函数式编程是指一种编程范式,其first-class-value是函数,并有如下properties:1. 因为函数为first-class-value,所以函…
我是Scala粉&br&其实题主问的问题很有价值,学习本身就是将一个个离散的点(概念)联系起来的过程,问出这样的问题并不奇怪,希望能解答题主的疑惑。&br&首先还是得写点科普的东西&br&&br&Scala的Future是个Monad(twitter的Future也是),抽象为Monad有2个好处(我能想到的):&br&1. 通过Monad的语义(dependent computation)将多个异步操作串联起来,这样可以有效避免/隐藏回调(onSuccess/onComplete/onFailure...),其次就是隐藏Promise(Scala实现了完整的Future&Promise&Callback模型)&br&2. 可以与其它的Monad(如List, Option)更好的组合(Monad Transformers), 来实现更好的monadic programming,具体的对一个Web应用来说HTTP Request取出的参数无非就是List或Option,对于后端RPC/数据库请求返回的数据无非也是List/Option&br&(对于轮子哥指出的C# Task是个comonad,我还是不理解,为什么要对Tasks做coKleisli composition 对下游计算暴露all substructures的好处是啥?世界之大,希望有人来科普。)&br&Scala的Future虽然没有提供Applicative的实现,但是有sequence组合子,可实现future的横向组合&br&&br&Scala的Future其语义是代表强异步计算,也就是每次flatMap组合的future都会被提交到ExecutionContext(默认是forkjoinpool)中,如果希望下游的计算都在同一个线程内完成,可以使用可控性更高的scalaz.concurrent.Task,它需要显式调用Task.fork才会被提交到池(当然你也可以实现single thread的ExecutionContext)。&br&(scalaz.concurrent.Task内部实现了trampoline,可控性非常高,可以做Explicit Continuation(自己造的词),关于这个我还没仔细研究,有坑回来再填)&br&&br&js的Promise 也是一个Monad(直觉告诉我)&br&&br&FRP 是一种编程范式,FRP system是对signals的 processors,其first class values是time-varying values (每时每刻都在变化的值),不敢多写了,怕被邵成大大教育,希望题主也区分一下FRP和RP(否则也会被教育的)。&br&除了Haskell的FRP库以及一些语言支持FRP外,其实我们大部分接触的是RP。&br&&br&RP 可简单的视为面向事件流的编程的范式,没有FRP那么严格(还要求behaviors具有明确的指称语义),下面我也只讨论RP&br&对于形如 a := b + c 指 a的值会随着b,c不断变化而变化,如何传递变化?那就是把b,c视为被观察者(Observable),a视为观察者(Observer),观察者a收集导致被观察者b, c的发生改变的事件,a可通过重演事件流确定当前时刻的值,这个事件流的获取可以是poll/push,同步/异步,而first class values是event stream&br&一些框架(如Rx*)中的Observable也是一个Monad, 使得我们可以对Observable做combination&br&&br&科普到此就行了,下面来回答问题&br&&br&&br&&blockquote&是否Future/Promise模式 能实现的FRP都能更好的实现?&/blockquote&&br&引用Rxjs book中的一句话:&br&&br&&blockquote& Observable is Promise++. A Promise is simply an Observable with one single emitted value. Rx streams go beyond promises by allowing many returned values.&/blockquote&&br&其实这句话已经很好的回答了你的问题,首先解释Observable is Promise++,从范式和模式的角度来说,Promise去实现RP当然是可行的,而且Promise就是单值(单个离散的事件)的Observable,说白了就是一个一次性的,一个是一直存在的,对于Future也是一样的,剥离其Monad的语义,Future就是代表这单次的异步计算,对于下游的计算它就是个Observable&br&我想它们的关系和区别也已经显现出来了,一个计算是单次的,一个计算是延续的,后者概念上涵盖前者,前者是模式,后者是范式,模式可以一定程度上支持范式&br&&br&这也解释了为啥Finagle (Twitter 的异步RPC)是响应式的,每个RPC调用都返回一个Twitter的Future,对于RPC的语境(场景),必定是单次计算(request -& response),Twitter的Future可视为后续计算的Observable&br&&br&下面讨论所谓的“更好”,其实已经没有必要讨论了,因为他们不是对立关系,但是我想说的,所谓的“更好”应该是针对需求方,需求方的使用场景,对于GUI肯定用RP爽,对于简单的单次异步计算不需要非用RP&br&&br&最后说一句,FRP/RP is the future&br&谢邀&br&(本身对这个问题感兴趣,最近太忙,拖了好久才答,我不是大神,我只是刚好手头上的项目是Reactive的,我司也在大量使用Future编程)
我是Scala粉其实题主问的问题很有价值,学习本身就是将一个个离散的点(概念)联系起来的过程,问出这样的问题并不奇怪,希望能解答题主的疑惑。首先还是得写点科普的东西Scala的Future是个Monad(twitter的Future也是),抽象为Monad有2个好处(我能想到的)…
众所周知Scala没有非常好的IDE支持(因为Scala太NB了),idea已经很不错了(都是Scala的错),但有时还是会:&br&&img src=&/78ae81437c60ccebbeafe5_b.png& data-rawwidth=&414& data-rawheight=&111& class=&content_image& width=&414&&&br&或&br&&img src=&/140ebdc9b05de7122e81c_b.png& data-rawwidth=&597& data-rawheight=&172& class=&origin_image zh-lightbox-thumb& width=&597& data-original=&/140ebdc9b05de7122e81c_r.png&&&br&然而上面都是可以编译过并且正常跑的,(有时候写出编辑器不认的代码反而会觉得莫名的爽,停下来吐槽一下,然后继续写代码。。。)&br&然而并不需要慌张,一般情况下不会写出很妖(ide不认)的代码,其次编译器说对才对。&br&&br&强类型的语言重构都不会有太多问题,idea这方面也很好(至少对Java,我看的广告)。&br&&br&调试的话,除了普通的debug,idea并不够,比如一个Akka Actor的程序,必须无法用普通的调试方法(我都是看的日志,有什么好工具求推荐),还有没记错的话macro是没法调试的,得用特殊的工具。&br&&br&工具如SBT,Maven的集成也还可以吧,Git的集成很不错&br&&br&不能期望一个语言插件去对刚世界上最好的IDE吧!&br&F#没用过,貌似ML系的,显然没有Scala有特色。&br&谢邀
众所周知Scala没有非常好的IDE支持(因为Scala太NB了),idea已经很不错了(都是Scala的错),但有时还是会:或然而上面都是可以编译过并且正常跑的,(有时候写出编辑器不认的代码反而会觉得莫名的爽,停下来吐槽一下,然后继续写代码。。。)然而并不需要…
隔壁Typesafe家 Play Framework欢迎您!
隔壁Typesafe家 Play Framework欢迎您!
刷离散数学-命题逻辑与谓词逻辑,看定义就行,转述一下就变味了
刷离散数学-命题逻辑与谓词逻辑,看定义就行,转述一下就变味了
并发编程网,知乎也不错
并发编程网,知乎也不错
哈哈,这个问题真是满是槽点啊! &br&首先AOP是编程范式,和运不运行时没关系; DI和你说的链式过滤器(应该是指node.js框架的那一套,类似J2EE的Filter)顶多是模式。&br&DI和链式过滤器可以实现或支持部分AOP编程,说取代那就是不对了,链式过滤器也没法做到细粒度的AOP,它针对的是Request P DI只是解决依赖对象的构造松耦合,散落在世界各地的代码还是需要龙珠雷达去收集的,谢邀
哈哈,这个问题真是满是槽点啊! 首先AOP是编程范式,和运不运行时没关系; DI和你说的链式过滤器(应该是指node.js框架的那一套,类似J2EE的Filter)顶多是模式。DI和链式过滤器可以实现或支持部分AOP编程,说取代那就是不对了,链式过滤器也没法做到细粒度的A…
1. IR node不是编译出来的,而是通过覆盖Rep[T]创建出来的,
Expressions.scala就是一个具体的IR.&br&2. Optimizations 在cs443-lms.pdf第32页列出了,CSE+
Domain-specific pattern rewriting + Loop hoisting & fusing 可通过
conversion +
PDG(IR is similar to a PDG) +
pattern matching + magic(未提到的技术) 实现,因为IR和传统AST不同,它是&for free&的,和原始代码很接近,你可以随意操作。(这部分没细看,没看错的话应该你自己去实现优化的,写Scala代码)&br&3. Code generator&br&&blockquote& All you (the DSL author) has to do is define code generators for your IR nodes&/blockquote&所以,你懂的&br&细节请研读源码:&a href=&///?target=https%3A///TiarkRompf/virtualization-lms-core& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&TiarkRompf/virtualization-lms-core · GitHub&i class=&icon-external&&&/i&&/a&&br&&br&谢邀 毕设祝好
1. IR node不是编译出来的,而是通过覆盖Rep[T]创建出来的,
Expressions.scala就是一个具体的IR.2. Optimizations 在cs443-lms.pdf第32页列出了,CSE+
Domain-specific pattern rewriting + Loop hoisting & fusing 可通过
conversion +
我在Scala项目里用AspectJ去hack过Lift代码(往事不堪回首),我当时的想法是用这个比用ASM总要好吧,学习资料那本《AspectJ In Action》就够了,一般正常项目应该不会用到,除非特殊需求&br&&br&Download: &a href=&///?target=http%3A///files/Manning.AspectJ.in.Action.2nd.Edition.Sep.2009.pdf& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&/&/span&&span class=&invisible&&files/Manning.AspectJ.in.Action.2nd.Edition.Sep.2009.pdf&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&
我在Scala项目里用AspectJ去hack过Lift代码(往事不堪回首),我当时的想法是用这个比用ASM总要好吧,学习资料那本《AspectJ In Action》就够了,一般正常项目应该不会用到,除非特殊需求Download:
1. 主从方式:存在Master Actor里,task分发和result汇总都交给Master Actor来做,Worker Actor(子Actor)负责接收任务执行和返回结果,Master 需要mark哪些Worker做完了。&br&2. Scala Future:直接用?的方式 请求所有子Actor,返回一个Future的List,然后用Future.sequence方法把List[Future[Result]]变成Future[List[Result]]去apply你最终的结果函数,而在何处用?都没关系。&br&谢邀
1. 主从方式:存在Master Actor里,task分发和result汇总都交给Master Actor来做,Worker Actor(子Actor)负责接收任务执行和返回结果,Master 需要mark哪些Worker做完了。2. Scala Future:直接用?的方式 请求所有子Actor,返回一个Future的List,然后用Fu…
是,只要在语法上支持return lambda就行
是,只要在语法上支持return lambda就行
那就用Scala吧,不一定能让你喜欢,但是绝对不会让你觉得无聊
那就用Scala吧,不一定能让你喜欢,但是绝对不会让你觉得无聊
1. 从Scala的集合操作移步到Spark的RDD操作很自然,而Java则是跨过去的,容易扯到蛋,这就是Spark平台下的优势&br&&br&1.5 Scala的优势&br&优势非常多:&br&a. 静态强类型加类型推导,类型安全,打字还少&br&b. Scala是一门图灵完备的语言,Scala类型系统也是一门图灵完备的语言&br&c. 函数式编程和面向对象的有机结合,既可以装高冷,又可以做实事&br&d. 可以用任何的Java库,JVM一家亲&br&e. 编译速度慢,但是开发效率高啊 (呵呵)&br&f. 生态系统构建的不错,各种库都有&br&g. 等等等&br&&br&2. 任何地方都可以用,任何Java能用的地方都可以用Scala (都是通用语言)&br&&br&3. 会不会取代Java?&br&光从语言上看:肯定是能取代Java了,都可以看出是不同时代的产物了(求Java同僚放过)&br&然而我想说的是,不要只是观望啊!大家都只是观望而不去实际学一学,用一用的话,如何来得取代之说呢?
1. 从Scala的集合操作移步到Spark的RDD操作很自然,而Java则是跨过去的,容易扯到蛋,这就是Spark平台下的优势1.5 Scala的优势优势非常多:a. 静态强类型加类型推导,类型安全,打字还少b. Scala是一门图灵完备的语言,Scala类型系统也是一门图灵完备的语言…
谢邀,希望能解答你的疑惑:&br&如下代码:&br&&div class=&highlight&&&pre&&code class=&language-scala&&&span class=&k&&object&/span& &span class=&nc&&Test&/span& &span class=&o&&{&/span&
&span class=&k&&def&/span& &span class=&n&&a&/span&&span class=&o&&[&/span&&span class=&kt&&T&/span&&span class=&o&&](&/span&&span class=&n&&i&/span&&span class=&k&&:&/span& &span class=&kt&&T&/span&&span class=&o&&)&/span& &span class=&k&&=&/span& &span class=&n&&i&/span&
&span class=&k&&val&/span& &span class=&n&&b&/span& &span class=&k&&=&/span& &span class=&n&&a&/span& &span class=&k&&_&/span&
&span class=&k&&val&/span& &span class=&n&&c&/span&&span class=&k&&:&/span& &span class=&kt&&Nothing&/span& &span class=&o&&=&/span& &span class=&n&&b&/span&&span class=&o&&(&/span&&span class=&kc&&null&/span&&span class=&o&&.&/span&&span class=&n&&asInstanceOf&/span&&span class=&o&&[&/span&&span class=&kt&&Nothing&/span&&span class=&o&&])&/span& &span class=&c1&&//JVM里null算是bottom type实例&/span&
&span class=&k&&val&/span& &span class=&n&&d&/span& &span class=&k&&=&/span& &span class=&n&&a&/span&&span class=&o&&[&/span&&span class=&kt&&Int&/span&&span class=&o&&](&/span&&span class=&n&&c&/span&&span class=&o&&)&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&b的类型是b: (Nothing) =& Nothing&br&javap一下:&br&&div class=&highlight&&&pre&&code class=&language-text&&$ javap Test
Compiled from &Test.scala&
public final class Test {
public static int d();
public static scala.runtime.Nothing$ c();
public static scala.Function1&scala.runtime.Nothing$, scala.runtime.Nothing$& b();
public static &T extends java/lang/Object& T a(T);
&/code&&/pre&&/div&我们看到的是Nothing变成了scala.runtime.Nothing$类型&br&在Scala源码里:&br&&div class=&highlight&&&pre&&code class=&language-scala&&&span class=&k&&package&/span& &span class=&nn&&scala.runtime&/span&
&span class=&cm&&/**&/span&
&span class=&cm&& * Dummy class which exist only to satisfy the JVM. It corresponds&/span&
&span class=&cm&& * to `scala.Nothing`. If such type appears in method&/span&
&span class=&cm&& * signatures, it is erased to this one.&/span&
&span class=&cm&& */&/span&
&span class=&k&&sealed&/span& &span class=&k&&abstract&/span& &span class=&k&&class&/span& &span class=&nc&&Nothing$&/span& &span class=&k&&extends&/span& &span class=&nc&&Throwable&/span&
&/code&&/pre&&/div&⊥就是在编译阶段推导出来,然后用这种伪类的方式写入字节码&br&(在Type checking时保证Nothing是所有类的subtype就行了,它只需要保证类型安全)&br&所以:如果你试图通过反射什么的想拿到scala.Nothing这样的类型,根本取不到,因为不存在,Nothing和Null只存在于编译期&br&&br&PS&br&minimal core calculus for Scala type checking: &br&&a href=&///?target=http%3A//lampwww.epfl.ch/%7Eodersky/papers/mfcs06.pdf& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&lampwww.epfl.ch/~odersk&/span&&span class=&invisible&&y/papers/mfcs06.pdf&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&
谢邀,希望能解答你的疑惑:如下代码:object Test {
def a[T](i: T) = i
val b = a _
val c: Nothing = b(null.asInstanceOf[Nothing]) //JVM里null算是bottom type实例
val d = a[Int](c)
}b的类型是b: (Nothing) =& Nothingjavap一下:$ javap Test…
请读<> 第三章,支持递归查询表达式用递归查询,不支持的用闭包表的设计吧
请读<> 第三章,支持递归查询表达式用递归查询,不支持的用闭包表的设计吧
其实Scala的lazy关键字是很常用的(非常常见),比如:在有些资源没有必要一开始就加载的情况下就会声明为lazy的,在用到时再去初始化;比如:同一份code可能需要按role初始化不同类型实例的时候也会声明为lazy (如Akka Cluster 按role需要启动不同的Actor时),在某种程度上Scala的lazy是来Fix val关键字(因为是final)的立即求值特点的。&br&&br&不过Lazy computation 在Scala里不止是lazy关键字, 更重要的是call-by-name (记得翻译为:传名函数)&br&&div class=&highlight&&&pre&&code class=&language-scala&&&span class=&k&&def&/span& &span class=&n&&pair&/span&&span class=&o&&(&/span&&span class=&n&&x&/span&&span class=&k&&:&/span& &span class=&o&&=&&/span& &span class=&nc&&Int&/span&&span class=&o&&)&/span&&span class=&k&&:&/span&&span class=&o&&(&/span&&span class=&kt&&Int&/span&&span class=&o&&,&/span& &span class=&kt&&Int&/span&&span class=&o&&)&/span& &span class=&k&&=&/span& &span class=&o&&(&/span&&span class=&n&&x&/span&&span class=&o&&,&/span& &span class=&n&&x&/span&&span class=&o&&)&/span&
&/code&&/pre&&/div&(注:class构造函数参数不可以是non-strict, 所以要lazy必须传函数() =& ???)&br&&br&那么就来说说传名函数的实际应用吧!&br&常见的一种情况就是Infinite Stream无穷数据流(或叫Generator)了,而很多东西都可以视为无穷数据流,比如数据库查询分页操作,为其定义一个getMore操作(比如前端瀑布流):&br&&div class=&highlight&&&pre&&code class=&language-scala&&&span class=&k&&def&/span& &span class=&n&&getData&/span&&span class=&o&&(&/span&&span class=&n&&s&/span&&span class=&k&&:&/span&&span class=&kt&&Int&/span&&span class=&o&&,&/span& &span class=&n&&l&/span&&span class=&k&&:&/span&&span class=&kt&&Int&/span&&span class=&o&&)&/span& &span class=&k&&=&/span& &span class=&nc&&Option&/span&&span class=&o&&(&/span&&span class=&s&&s&sql...skip=&/span&&span class=&si&&$s&/span&&span class=&s&& limit=&/span&&span class=&si&&$l&/span&&span class=&s&&&&/span&&span class=&o&&)&/span&
&span class=&k&&def&/span& &span class=&n&&getMore&/span&&span class=&o&&(&/span&&span class=&n&&skip&/span&&span class=&k&&:&/span& &span class=&kt&&Int&/span&&span class=&o&&,&/span& &span class=&n&&limit&/span&&span class=&k&&:&/span& &span class=&kt&&Int&/span&&span class=&o&&)&/span& &span class=&k&&=&/span& &span class=&nc&&Stream&/span&&span class=&o&&.&/span&&span class=&n&&unfold&/span&&span class=&o&&(&/span&&span class=&n&&skip&/span&&span class=&o&&){&/span&
&span class=&n&&s&/span& &span class=&k&&=&&/span& &span class=&nc&&Some&/span&&span class=&o&&(&/span&&span class=&n&&getData&/span&&span class=&o&&(&/span&&span class=&n&&s&/span&&span class=&o&&,&/span& &span class=&n&&limit&/span&&span class=&o&&),&/span& &span class=&n&&s&/span&&span class=&o&&+&/span&&span class=&n&&limit&/span&&span class=&o&&)&/span&
&span class=&o&&}&/span&
&span class=&n&&println&/span&&span class=&o&&(&/span&&span class=&nc&&Stream&/span&&span class=&o&&.&/span&&span class=&n&&getMore&/span&&span class=&o&&(&/span&&span class=&mi&&0&/span&&span class=&o&&,&/span&&span class=&mi&&10&/span&&span class=&o&&).&/span&&span class=&n&&take&/span&&span class=&o&&(&/span&&span class=&mi&&3&/span&&span class=&o&&).&/span&&span class=&n&&toList&/span&&span class=&o&&)&/span&
&span class=&c1&&//&&& List(Some(sql...skip=0 limit=10), Some(sql...skip=10 limit=10), Some(sql...skip=20 limit=10))&/span&
&/code&&/pre&&/div&Stream的unfold方法定义为: &br&S -& (A, S)
//A为前一个值,S为下一个值:自增数列可表示为(s -&(s, s+1))(0)&br&&br&其次就是其本意推迟计算了,比如:把所有的网络请求都延迟到最后返回值时计算,比如:将多个计算函数分配到不同的线程中去执行,实现这些依靠non-strict则会很简单&br&&br&不管是用mechanism 还是 通过() =& ??? 去模拟non-strict,lazy computation 在Scala中是很普遍的,也是必须的,甚至与higher-order functions一样常见&br&谢邀
其实Scala的lazy关键字是很常用的(非常常见),比如:在有些资源没有必要一开始就加载的情况下就会声明为lazy的,在用到时再去初始化;比如:同一份code可能需要按role初始化不同类型实例的时候也会声明为lazy (如Akka Cluster 按role需要启动不同的Actor…
谢 &a data-hash=&e90f6efeaf55ac1394a9cd& href=&///people/e90f6efeaf55ac1394a9cd& class=&member_mention& data-tip=&p$b$e90f6efeaf55ac1394a9cd&&@用心阁&/a& 邀, 理解的不深啊,只能浅出了&br&&a href=&///?target=http%3A///cspbook.pdf& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&/cspbook.pd&/span&&span class=&invisible&&f&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a& 这本书也算是CSP的官方教材了吧!从两个方面来说:&br&&b&1.从代数角度来说:&/b&&br&&b&communicating sequential processes&/b& (&b&CSP&/b&) 其实是简单(清晰)的,和任何一种数理逻辑中的XX逻辑一样:&br&CSP process algebra 的基本代数对象:event 和 process (有种参数和函数的感觉)&br&CSP process algebra 的基本代数操作符:&br&看论文有很多,我把它分为三类:&br&1. dependence computing: -&,choice, or, &&, ; ... 表示后续(求值产生的)Process是依赖于其前置(initials)条件(Event或Process)&br&2. independence computing: ||,|||,interface, ...也就是所谓可以parallel求值&br&3. other: hiding,
interrupted...&br&在此基础上加上几条Laws的代数系统就可以描述process交互模型了(比如论文里的自动贩卖机),Helloworld 达人说的model checking指的就是这方面吧&br&&br&&b&Traces&/b&: porcess所表示的行为的有限(输入)事件序列,主要是用来对某个process求其事件序列,我们可以得到一个多个process交互模型的所有事件输入,对研究其行为更有帮助(去研究traces本身我觉得就是普通的集合论了)&br&&br&&b&Communication&/b&:是一种特殊的Event,用二元组c.v表示,c是channel的名字,v是传递过来的message的值&br&process P可以写入和读取channel的messge集合表示为:&br&&img src=&/2be007e5dcc15c10e9f834_b.png& data-rawwidth=&230& data-rawheight=&36& class=&content_image& width=&230&&P从c读取和写入分别定义为:&br&output: &img src=&/fe3f7c797bff5ab2d5ba726ca82adf8c_b.png& data-rawwidth=&196& data-rawheight=&32& class=&content_image& width=&196&&input:&br&&img src=&/a3202dcf8c1cbc0c3bd077_b.png& data-rawwidth=&482& data-rawheight=&27& class=&origin_image zh-lightbox-thumb& width=&482& data-original=&/a3202dcf8c1cbc0c3bd077_r.png&&看都可以转化为基本(上面所说)的CSP process algebra的形式&br&&br&&b&Sequential Process&/b&: 为了区分process是STOP(不再响应事件,有可能是死锁)还是terminate successfully,引入符号“√”,表示正常终结,而Sequential Process就是表示正常终结的process们。&br&你们眼里的并发模型,应该是指Communication和Sequential Process部分,它们只是CSP代数系统的special case, 或者说是具体特化场景&br&然后,然后就没有然后了(我也没看完)&br&&br&&b&2.从程序员角度来说:&/b&&br&&b&&a href=&///?target=http%3A//www.cs.kent.ac.uk/projects/ofa/jcsp/cpa2007-jcsp.pdf& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&cs.kent.ac.uk/projects/&/span&&span class=&invisible&&ofa/jcsp/cpa2007-jcsp.pdf&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/b&PPT 搞起&br&为不管Go是不是真的基于CSP,反正我也不会Go,常常看大神讨论,觉得确实是像的啊。&br&在代码上,就是抽象出Process和channel了,至于底层实现并没有关系
邀, 理解的不深啊,只能浅出了 这本书也算是CSP的官方教材了吧!从两个方面来说:1.从代数角度来说:communicating sequential processes (CSP) 其实是简单(清晰)的,和任何一种数理逻辑中的XX逻辑一样:CSP process alg…
&blockquote&在哪些具体情况下,业务系统仍然需要自己管理『多线程并发』?&/blockquote&容器只提供了最基本的connector线程池(具体容器实现略有不同,不在本处探讨),除此之外的事情(多线程并发)都需要自己去解决,只不过简单的业务系统不需要,而复杂的则肯定有框架支持,基本上很少需要自己直接管理『多线程并发』&br&&br&然而需要更正的是:即使业务系统不需要直接管理『多线程并发』,并不意味着可以不了解并发,上面那个故事要告诉我们的其实是这一点(也有可能是我曲解了
_(:3 」∠)_ )。&br&&br&除了容器的Acceptors,业务系统上多线程并发问题是真实普遍存在的:&br&&br&当有(线程不安全的)共享资源(全局变量)时,容器的多个server线程并没有提供安全的访问方式,但是框架可能提供了,如果没提供你会怎么做?&br&当业务上有竞态条件时你会怎么做?比如: 查询数据库判断状态,再执行更新操作是否有问题?&br&为何mongo要提供upsert等为数不多的原子操作?&br&当有一坨rpc调用时如何更好的compose service?&br&当有同步请求太慢改为Servlet3.0 异步时,如何管理后台线程池?&br&业务系统间为何引入消息队列服务器?&br&&br&我们在把并发问题推给框架、库、服务时,一旦库或者服务不能很好的避免或保证你滥用/误用时就会出现『多线程并发』问题&br&&br&比如Actor这种已经帮你解决并发问题的模型下,如果依然使用共享资源的方式,那就还是会出现『多线程并发』问题&br&&br&谢邀
在哪些具体情况下,业务系统仍然需要自己管理『多线程并发』?容器只提供了最基本的connector线程池(具体容器实现略有不同,不在本处探讨),除此之外的事情(多线程并发)都需要自己去解决,只不过简单的业务系统不需要,而复杂的则肯定有框架支持,基本…
已有帐号?
社交帐号登录
无法登录?
社交帐号登录

我要回帖

更多关于 promise js 实现 的文章

 

随机推荐