如果我有类似的东西List[Option[A]],我想将其转换为a List[A],标准方法是使用flatMap:
scala> val l = List(Some("Hello"), None, Some("World"))
l: List[Option[java.lang.String]] = List(Some(Hello), None, Some(World))
scala> l.flatMap( o => o)
res0: List[java.lang.String] = List(Hello, World)
Run Code Online (Sandbox Code Playgroud)
现在o => o只是一个身份功能.我原以为会有办法:
l.flatMap(Identity) //return a List[String]
Run Code Online (Sandbox Code Playgroud)
但是,我不能让这个工作,因为你不能生成一个object.我试了几件事无济于事; 有没有人有这样的工作?
我知道Monad可以在Scala中表达如下:
trait Monad[F[_]] {
def flatMap[A, B](f: A => F[B]): F[A] => F[B]
}
Run Code Online (Sandbox Code Playgroud)
我明白为什么它有用.例如,给定两个功能:
getUserById(userId: Int): Option[User] = ...
getPhone(user: User): Option[Phone] = ...
Run Code Online (Sandbox Code Playgroud)
我可以轻松编写函数,getPhoneByUserId(userId: Int)因为它Option是一个monad:
def getPhoneByUserId(userId: Int): Option[Phone] =
getUserById(userId).flatMap(user => getPhone(user))
Run Code Online (Sandbox Code Playgroud)
...
现在我Applicative Functor在Scala中看到:
trait Applicative[F[_]] {
def apply[A, B](f: F[A => B]): F[A] => F[B]
}
Run Code Online (Sandbox Code Playgroud)
我想知道何时应该使用它而不是 monad.我猜选项和列表都是Applicatives.你能给出使用applyOption和List的简单例子,并解释为什么我应该使用它而不是 flatMap?
因此,在面向对象的世界中花费了多年的代码重用,设计模式和最佳实践总是被考虑在内,我发现自己在Spark世界中的代码组织和代码重用方面有些挣扎.
如果我尝试以可重用的方式编写代码,它几乎总是带来性能成本,我最终会将其重写为适合我的特定用例的最佳代码.这个常量"为这个特定用例编写最佳内容"也会影响代码组织,因为当"它们真的属于一个整体"时,将代码拆分成不同的对象或模块是困难的,因此我最终只得到很少的"上帝"对象包含长复杂变换链.事实上,我经常认为,如果我在面向对象世界工作时看到我现在正在写的大部分Spark代码,我会畏缩并将其视为"意大利面条代码".
我上网试图找到某种等同于面向对象世界的最佳实践,但没有太多运气.我可以找到一些函数式编程的"最佳实践",但Spark只增加了一个额外的层,因为性能是这里的一个主要因素.
所以我的问题是,你们中的任何人都有Spark专家发现了一些你可以推荐的编写Spark代码的最佳实践吗?
编辑
正如评论中所写,我实际上并没有希望有人就如何解决这个问题发表答案,而是我希望这个社区中的某个人遇到一些Martin Fowler类型,他曾在某处写过som文章或博客帖子关于如何解决Spark世界中代码组织的问题.
@DanielDarabos建议我举一个代码组织和性能相互矛盾的例子.虽然我发现我在日常工作中经常遇到这方面的问题,但我觉得把它归结为一个很好的最小例子有点困难;)但我会尝试.
在面向对象的世界里,我是单一责任原则的忠实粉丝,所以我要确保我的方法只对一件事负责.它使它们可重复使用并且易于测试.因此,如果我不得不计算列表中某些数字的总和(匹配某些标准)并且我必须计算相同数字的平均值,我肯定会创建两个方法 - 一个计算总和,一个计算平均值.像这样:
def main(implicit args: Array[String]): Unit = {
val list = List(("DK", 1.2), ("DK", 1.4), ("SE", 1.5))
println("Summed weights for DK = " + summedWeights(list, "DK")
println("Averaged weights for DK = " + averagedWeights(list, "DK")
}
def summedWeights(list: List, country: String): Double = {
list.filter(_._1 == country).map(_._2).sum
}
def averagedWeights(list: List, country: String): Double = {
val filteredByCountry = list.filter(_._1 == country)
filteredByCountry.map(_._2).sum/ filteredByCountry.length
}
Run Code Online (Sandbox Code Playgroud)
我当然可以继续尊重Spark中的SRP:
def main(implicit …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个组成两个函数的函数,初始设计非常简单,它是一个函数,它接受两个函数并返回一个组合函数,然后我可以用其他函数组合,(因为rust没有rest参数).但是我遇到了一个很长的硬墙,内置了令人沮丧的无用的编译器错误.
我的撰写功能:
fn compose<'a, A, B, C, G, F>(f: F, g: G) -> Box<Fn(A) -> C + 'a>
where
F: 'a + Fn(A) -> B + Sized,
G: 'a + Fn(B) -> C + Sized,
{
Box::new(move |x| g(f(x)))
}
Run Code Online (Sandbox Code Playgroud)
我想怎么用它:
fn main() {
let addAndMultiply = compose(|x| x * 2, |x| x + 2);
let divideAndSubtract = compose(|x| x / 2, |x| x - 2);
let finally = compose(*addAndMultiply, *divideAndSubtract);
println!("Result is {}", finally(10));
}
Run Code Online (Sandbox Code Playgroud)
rustc不喜欢那样,无论我尝试什么,特质界限永远不会满足.错误是:
error[E0277]: the size …Run Code Online (Sandbox Code Playgroud) 考虑一个单链表.它看起来像
data List x = Node x (List x) | End
Run Code Online (Sandbox Code Playgroud)
定义折叠函数是很自然的
reduce :: (x -> y -> y) -> y -> List x -> y
Run Code Online (Sandbox Code Playgroud)
从某种意义上说,reduce f x0替代每一个Node有f一位End用x0.这就是Prelude所说的折叠.
现在考虑一个简单的二叉树:
data Tree x = Leaf x | Branch (Tree x) (Tree x)
Run Code Online (Sandbox Code Playgroud)
定义诸如的函数同样很自然
reduce :: (y -> y -> y) -> (x -> y) -> Tree x -> y
Run Code Online (Sandbox Code Playgroud)
请注意,这种减少具有完全不同的特征; 而基于列表的一个本质上是顺序的,这个新的基于树的一个具有更多的分而治之的感觉.你甚至可以想象par在那里扔几个组合器.(你会在列表版本中放置这样的东西?)
我的问题:这个功能是否仍被归类为"折叠",还是其他东西?(如果是的话,它是什么?)
基本上每当有人谈论折叠时,他们总是谈论折叠列表 …
mapGroovy中有方法吗?我想做一些像我使用以下Scala片段的事情:
scala> val l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)
scala> l.map(_ + 1)
res0: List[Int] = List(2, 3, 4)
Run Code Online (Sandbox Code Playgroud) 在R(感谢magritrr)中,您现在可以通过更多功能管道语法执行操作%>%.这意味着不是编码:
> as.Date("2014-01-01")
> as.character((sqrt(12)^2)
Run Code Online (Sandbox Code Playgroud)
你也可以这样做:
> "2014-01-01" %>% as.Date
> 12 %>% sqrt %>% .^2 %>% as.character
Run Code Online (Sandbox Code Playgroud)
对我来说,这更具可读性,这扩展到数据框之外的用例.python语言是否支持类似的东西?
为什么供应商只支持no-arg构造函数?
如果存在默认构造函数,我可以这样做:
create(Foo::new)
Run Code Online (Sandbox Code Playgroud)
但如果唯一的构造函数采用String,我必须这样做:
create(() -> new Foo("hello"))
Run Code Online (Sandbox Code Playgroud) java lambda functional-programming java-8 functional-interface
我已经开始使用C++进行函数式编程的基础知识.我正在尝试创建一个f(a)(b)(c)将返回的函数a + b + c.我成功实现了f(a)(b)返回a + b 的函数.这是它的代码:
std::function<double(double)> plus2(double a){
return[a](double b){return a + b; };
}
Run Code Online (Sandbox Code Playgroud)
我只是无法弄清楚如何实现f(a)(b)(c)我之前声明应该返回的功能a + b + c.
有人可以解释一下Scala上下文中Functor和Monad之间的区别吗?
scala ×4
apache-spark ×1
applicative ×1
c++ ×1
c++11 ×1
currying ×1
fold ×1
groovy ×1
haskell ×1
java ×1
java-8 ×1
lambda ×1
map ×1
pipeline ×1
python ×1
rust ×1
scala-option ×1
std-function ×1
terminology ×1