scala :::
几乎所有学习Scala的人都会对上下文中使用的偏词感到困惑:
- 部分功能
- 部分应用的功能
让我们看看两者。
部分应用的功能
Scala从诸如Haskell(Haskell 1.0
于1990年与Depeche Mode的《 享受沉默》和Dee Lite的《 Groove in the Heart》一起出现。 在功能语言中,具有两个参数并返回一个参数的函数可以表示为具有输入参数之一的函数并返回具有另一个输入参数的函数并返回相同输出参数的函数。
f(x1, x2) = y
f(x1) = f(x2) = y
一个类似奶酪的类比是时光倒流回到1990年,并发现自己是一个准点播机。 将钱投入两个选择中,然后先选择“ Depeche模式”,然后再选择“ Dee Lite”,然后走开并扔出一些形状,一个接一个地玩。 或者,将您的钱投入两个选择中,选择Depeche模式,然后再不进行另一个选择。 暂时不要走开。 精心设计的Juxebox应该提示您进行其他选择(为您提供其他功能),然后您可以选择Dee Lite(传递第二个参数)。 因此,两种情况下的最终输出都是相同顺序的相同音乐。
在Scala中,当仅将一些参数传递给一个函数以创建另一个函数时,据说这是该函数的部分应用程序 。 因此,请考虑以下功能:
def minus(a: Int, b: Int) = 'answer=' + (a-b)
现在,让我们通过传入一些参数并创建另一个函数来部分应用此函数。
val minus50 = (a: Int) => minus(a, 50);
在这种情况下, minus50
是minus的部分应用 。 我们可以做的:
minus50(57); // outputs 7.
注意:我们也可以使用_表示法部分地应用,并且省去了一些手指输入的麻烦。
val minus50 = minus(_:Int, 50);
局部函数局部函数是仅对您可能传递给这些类型的值的子集有效的函数。 例如,考虑数学函数,其中x设置了从1到100的所有数字:
f(x)= x + 5;
如果该函数仅应用于x元素集中的子集,则称该函数为部分函数。 所以如果我们只想定义函数
f(x) = x + 5
对于数字1,2,3,4,5,6,7但不是8,9,10,…–我们定义了部分函数。
f(x')=x+5
其中x'= {1,2,3,4,5,6,7}
在Scala中,PartialFunction继承自Function并添加了两个有趣的方法:
-
isDefinedAt
–这使我们可以检查是否为部分函数定义了一个值。 -
orElse
–这允许链接部分功能。 因此,如果未为函数定义值,则可以将其传递给另一个函数。 这类似于GoF 的责任链模式。
好的,因此打开一个Scala REPL并创建以下部分函数,只要该整数小于7,该函数就会将5加到一个整数上。
val add5Partial : PartialFunction[Int, Int] = {
case d if (d > 0) && (d <= 7) => d + 5;
}
当您尝试使用小于或等于7的值时,您将看到结果没问题
scala > add5Partial(6);
res1: 11
当您尝试使用大于7的值时,您不会得到一个很好的明确答案。
scala> myPartial(42);
scala.MatchError: 42 (of class java.lang.Integer)
at $anonfun$1.apply$mcII$sp(<console>:7)
at .<init>(<console>:9)
at .<clinit>(<console>)
at .<init>(<console>:11)
at .<clinit>(<console>)
at $print(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
at scala.tools.nsc.interpreter.IMain$Request$$anonfun$14.apply(IMain.scala:920)
at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43)
at scala.tools.nsc.io.package$$anon$2.run(package.scala:25)
at java.lang.Thread.run(Thread.java:722)
</console></console></clinit></console></init></console></clinit></console></init></console>
现在应该很明显使用isDefinedAt()
。 在这种情况下,我们可以这样做:
add5Partial.isDefinedAt(4)
res3: Boolean = true
scala> add5Partial.isDefinedAt(42)
res4: Boolean = false
好吧那怎么办
orElse
? 好吧,让我们定义另一个处理大于7且小于100的部分函数。在这种情况下,我们只需加4。
val add4Partial : PartialFunction[Int, Int] = {
case d if (d > 7) && (d <= 100) => d + 5;
}
现在我们可以做:
scala> val addPartial = add5Partial orElse add4Partial;
addPartial : PartialFunction[Int,Int] = <function1>
scala> addPartial(42);
res6: Int = 46
好的,让我们看看如何使用责任链模式在Java中实现所有这些功能。 首先,让我们定义一个处理程序接口以及一个将实现该接口的add5和add4实现。
//Handler
public interface AdditionHandler {
//reference to the next handler in the chain
public void setNext(AdditionHandler handler);
//handle request
public void handleRequest(int number);
}
public class Add5Handler implements AdditionHandler {
private AdditionHandler nextAdditionHandler = null;
public void setNext(AdditionHandler hander) {
this.nextAdditionHandler = handler;
}
public int handleRequest(int number) {
if ((number > 0) && (number <= 7)) {
return number + 5;
} else {
return nextAdditionHandler.handleRequest(number);
}
}
}
public class Add4Handler implements AdditionHandler {
private AdditionHandler nextAdditionHandler = null;
public void setNext(AdditionHandler hander) {
this.nextAdditionHandler = handler;
}
public int handleRequest(int number) {
if ((number > 7) && (number <= 100)) {
return number + 4;
} else {
return nextAdditionHandler.handleRequest(number);
}
}
}
现在,让我们创建一个将链接处理程序的类。
public class AdditionProcessor {
private AdditionHandler prevHandler;
public void addHandler(AdditionHandler handler){
if(prevHandler != null) {
prevHandler.setNext(handler);
}
prevHandler = handler;
}
}
当然,客户实际上会调用该功能:
public class AdditionClient {
private AdditionProcessor processor;
public AdditionClient(){
createProcessor();
}
private void createProcessor() {
processor = new AdditionProcessor();
processor.addHandler(new Add5Handler());
processor.addHandler(new Add4Handler());
}
public void addRule(AdditionHandler handler) {
processor.addHandler(handler);
}
public void requestReceived(int value){
System.out.println('value=' + processor.handleRequest(value));
}
public static void main(String[] args) {
AdditionClient client = new AdditionClient();
}
}
因此,Scala在这里有一些明显的优势。 或者,当然,人们会说“ 啊,但是在Java中,您只是做……”
public int addFunction(int value) {
if ((value > 0) && (value <= 7)) {
return value + 5;
} else if ((value > 7) && (value < 100)) {
return value + 4;
} else {
// ...
}
}
是的,对于这种特定情况,这将起作用。 但是,如果您的功能/命令变得更加复杂,该怎么办。 你去闲逛吗
if / else
降落? 可能不是。 直到下一次,保重身体。
参考: Scala:您对此有部分了解吗? 从我们的JCG合作伙伴 Alex Staveley在都柏林的技术博客博客中获得。
翻译自: https://www.javacodegeeks.com/2013/01/scala-do-you-partially-understand-this.html
scala :::