لماذا جزئي <: وظيفة في scala؟
-
06-09-2019 - |
سؤال
في سكالا، PartialFunction[A, B]
فئة مشتقة من النوع Function[A, B]
(انظر مرجع scala، 12.3.3). ومع ذلك، يبدو هذا مضادا لي، منذ Function
(الذي يحتاج إلى تعريف للجميع A
) لديه متطلبات أكثر صرامة من PartialFunction
, ، والتي يمكن أن تكون غير محددة في بعض الأماكن.
المشكلة التي أحضرت accross كان ذلك عندما يكون لدي وظيفة جزئية، لا أستطيع استخدام Function
لتمديد الوظيفة الجزئية. على سبيل المثال لا أستطيع أن أفعل:
(pf orElse (_)=>"default")(x)
(نأمل أن يكون بناء الجملة على صواب على الأقل)
لماذا يتم ذلك الفرعي الفرعي عكسها؟ هل هناك أي أسباب تجاهلت، مثل حقيقة أن Function
أنواع مدمجة؟
راجع للشغل، سيكون لطيفا أيضا إذا Function1 :> Function0
لذلك لا أحتاج إلى حجة وهمية في المثال أعلاه :-)
تحرير لتوضيح المشكلة الفرعية
يمكن التأكيد على الفرق بين النهجين من خلال النظر إلى مثالين. أي منهم صحيح؟
واحد:
val zeroOne : PartialFunction[Float, Float] = { case 0 => 1 }
val sinc = zeroOne orElse ((x) => sin(x)/x) // should this be a breach of promise?
اثنين:
def foo(f : (Int)=>Int) {
print(f(1))
}
val bar = new PartialFunction[Int, Int] {
def apply(x : Int) = x/2
def isDefinedAt(x : Int) = x%2 == 0
}
foo(bar) // should this be a breach of promise?
لا يوجد حل صحيح
نصائح أخرى
لأنه في Scala (كما هو الحال في أي لغة تورينج كاملة) لا يوجد أي ضمان أن وظيفة كاملة.
val f = {x : Int => 1 / x}
لا يتم تعريف هذه الوظيفة عند 0. تعد جزءا من الجزئي مجرد وظيفة تعد بإخبارك أين لم يتم تعريفها. لا يزال، scala يجعل من السهل بما يكفي للقيام بما تريد
def func2Partial[A,R](f : A => R) : PartialFunction[A,R] = {case x => f(x)}
val pf : PartialFunction[Int, String] = {case 1 => "one"}
val g = pf orElse func2Partial{_ : Int => "default"}
scala> g(1)
res0: String = one
scala> g(2)
res1: String = default
إذا كنت تفضل ذلك، فيمكنك إجراء ضمني function2partial.
PartialFunction
لديه طرق التي Function1
لا، لذلك هو النوع الفرعي. تلك الطرق isDefinedAt
و orElse
.
مشكلتك الحقيقية هي ذلك PartialFunction
لا يستنتج S في بعض الأحيان عندما تحبهم حقا. أنا آمل أن يتم تناولها في تاريخ بعض المستقبل. على سبيل المثال، هذا لا يعمل:
scala> val pf: PartialFunction[String, String] = { case "a" => "foo" }
pf: PartialFunction[String,String] = <function>
scala> pf orElse { case x => "default" }
<console>:6: error: missing parameter type for expanded function
((x0$1) => x0$1 match { case (x @ _) => "default" })
ولكن هذا يفعل:
scala> pf orElse ({ case x => "default" } : PartialFunction[String,String])
res5: PartialFunction[String,String] = <function>
بالطبع يمكنك دائما القيام بذلك:
scala> implicit def f2pf[T,R](f: Function1[T,R]): PartialFunction[T,R] =
new PartialFunction[T,R] {
def apply(x: T) = f(x)
def isDefinedAt(x: T) = true
}
f2pf: [T,R](f: (T) => R)PartialFunction[T,R]
والآن أكثر وكأنك تريد:
scala> pf orElse ((x: String) => "default")
res7: PartialFunction[String,String] = <function>
scala> println(res7("a") + " " + res7("quux"))
foo default