प्रश्न दो भागों में है। पहला वैचारिक है। अगला स्कैला में इसी सवाल पर अधिक सहमति से दिखता है।
- एक प्रोग्रामिंग भाषा में केवल अपरिवर्तनीय डेटा संरचनाओं का उपयोग करने से कुछ एल्गोरिदम / तर्क को लागू करना स्वाभाविक रूप से व्यवहार में अधिक कम्प्यूटेशनल रूप से महंगा हो जाता है? यह इस तथ्य की ओर आकर्षित करता है कि अपरिवर्तनीयता विशुद्ध रूप से कार्यात्मक भाषाओं का एक मुख्य सिद्धांत है। क्या ऐसे अन्य कारक हैं जो इसे प्रभावित करते हैं?
- आइए एक अधिक ठोस उदाहरण लेते हैं। क्विकॉर्ट को आम तौर पर इन-मेमोरी डेटा संरचना पर म्यूटेबल ऑपरेशन का उपयोग करके सिखाया और कार्यान्वित किया जाता है। म्यूरेबल संस्करण में तुलनीय कम्प्यूटेशनल और स्टोरेज ओवरहेड के साथ PURE में इस तरह की चीज़ को कैसे लागू किया जाता है। विशेष रूप से स्काला में। मैंने नीचे कुछ कच्चे बेंचमार्क शामिल किए हैं।
अधिक जानकारी:
मैं एक अनिवार्य प्रोग्रामिंग पृष्ठभूमि (C ++, जावा) से आता हूं। मैं कार्यात्मक प्रोग्रामिंग की खोज कर रहा हूं, विशेष रूप से स्काला।
शुद्ध कार्यात्मक प्रोग्रामिंग के कुछ प्राथमिक सिद्धांत:
- कार्य प्रथम श्रेणी के नागरिक हैं।
- कार्यों के दुष्प्रभाव नहीं होते हैं और इसलिए ऑब्जेक्ट / डेटा संरचनाएं अपरिवर्तनीय होती हैं ।
भले ही आधुनिक जेवीएम वस्तु निर्माण के साथ बेहद कुशल हैं और कचरा संग्रह बहुत कम समय तक जीवित वस्तुओं के लिए बहुत सस्ती है, फिर भी वस्तु निर्माण अधिकार को कम से कम करना अभी भी बेहतर है? कम से कम एक एकल-थ्रेडेड एप्लिकेशन में जहां कॉन्सेप्ट और लॉकिंग कोई समस्या नहीं है। चूंकि स्काला एक हाइब्रिड प्रतिमान है, इसलिए यदि आवश्यक हो, तो उत्परिवर्तनीय वस्तुओं के साथ अनिवार्य कोड लिखना चुन सकते हैं। लेकिन, किसी ऐसे व्यक्ति के रूप में जिसने वस्तुओं के पुन: उपयोग और आवंटन को कम करने के लिए बहुत साल बिताए हैं। मुझे लगता है कि ऐसा भी नहीं होने दिया जाएगा सोचा था कि स्कूल की एक अच्छी समझ चाहते हैं।
एक विशिष्ट मामले के रूप में, मुझे इस ट्यूटोरियल 6 में इस कोड स्निपेट से थोड़ा आश्चर्य हुआ । इसका क्विकॉर्ट का जावा संस्करण है, जिसके बाद उसी का एक साफ सुथरा स्कैला कार्यान्वयन है।
यहां कार्यान्वयनों को बेंचमार्क करने का मेरा प्रयास है। मैंने विस्तृत रूपरेखा नहीं बनाई है। लेकिन, मेरा अनुमान है कि स्काला संस्करण धीमा है क्योंकि आवंटित वस्तुओं की संख्या रैखिक है (प्रति पुनरावृत्ति कॉल)। क्या कोई तरीका है जिससे टेल कॉल ऑप्टिमाइज़ेशन खेलने में आ सकता है? अगर मैं सही हूं, तो स्लाला स्व-पुनरावर्ती कॉल के लिए टेल कॉल अनुकूलन का समर्थन करती है। इसलिए, इसे केवल मदद करनी चाहिए। मैं स्काला 2.8 का उपयोग कर रहा हूं।
जावा संस्करण
public class QuickSortJ {
public static void sort(int[] xs) {
sort(xs, 0, xs.length -1 );
}
static void sort(int[] xs, int l, int r) {
if (r >= l) return;
int pivot = xs[l];
int a = l; int b = r;
while (a <= b){
while (xs[a] <= pivot) a++;
while (xs[b] > pivot) b--;
if (a < b) swap(xs, a, b);
}
sort(xs, l, b);
sort(xs, a, r);
}
static void swap(int[] arr, int i, int j) {
int t = arr[i]; arr[i] = arr[j]; arr[j] = t;
}
}
स्काला संस्करण
object QuickSortS {
def sort(xs: Array[Int]): Array[Int] =
if (xs.length <= 1) xs
else {
val pivot = xs(xs.length / 2)
Array.concat(
sort(xs filter (pivot >)),
xs filter (pivot ==),
sort(xs filter (pivot <)))
}
}
कार्यान्वयन की तुलना करने के लिए स्काला कोड
import java.util.Date
import scala.testing.Benchmark
class BenchSort(sortfn: (Array[Int]) => Unit, name:String) extends Benchmark {
val ints = new Array[Int](100000);
override def prefix = name
override def setUp = {
val ran = new java.util.Random(5);
for (i <- 0 to ints.length - 1)
ints(i) = ran.nextInt();
}
override def run = sortfn(ints)
}
val benchImmut = new BenchSort( QuickSortS.sort , "Immutable/Functional/Scala" )
val benchMut = new BenchSort( QuickSortJ.sort , "Mutable/Imperative/Java " )
benchImmut.main( Array("5"))
benchMut.main( Array("5"))
परिणाम
लगातार पांच रनों के लिए मिलीसेकंड में समय
Immutable/Functional/Scala 467 178 184 187 183
Mutable/Imperative/Java 51 14 12 12 12
O(n)
सूची के बीच का उपयोग करता है । हालांकि यह