ਜਾਣੋ ਕਿ Martin Odersky ਨੇ Scala ਰਾਹੀਂ ਕਿਵੇਂ JVM 'ਤੇ functional ਤੇ object-oriented ਵਿਚਕਾਰ ਸੰਤੁਲਨ ਬਣਾਇਆ, ਅਤੇ ਇਸਨੇ APIs, ਟੂਲਿੰਗ ਅਤੇ ਆਧੁਨਿਕ ਭਾਸ਼ਾ ਡਿਜ਼ਾਇਨ ਲਈ ਕੀ ਸਬਕ ਦਿੱਤੇ।

Martin Odersky ਸਭ ਤੋਂ ਵੱਧ Scala ਦੇ ਰਚਨਾਕਰਤਾ ਵਜੋਂ ਜਾਣੇ ਜਾਂਦੇ ਹਨ, ਪਰ JVM ਪ੍ਰੋਗ੍ਰਾਮਿੰਗ 'ਤੇ ਉਹਨਾਂ ਦਾ ਪ੍ਰਭਾਵ ਇੱਕ ਭਾਸ਼ਾ ਤੱਕ ਸੀਮਿਤ ਨਹੀਂ। ਉਹਨਾਂ ਨੇ ਇਕ ਐਸਾ ਇੰਜੀਨੀਅਰਿੰਗ ਅੰਦਾਜ਼ ਸਧਾਰਨ ਕੀਤਾ ਜਿਸ ਵਿੱਚ ਅਭਿਵ্যਕਤੀਸ਼ੀਲ ਕੋਡ, ਮਜ਼ਬੂਤ ਟਾਈਪਸ ਅਤੇ Java ਨਾਲ ਵਿਵਹਾਰਕ ਅਨੁਕੂਲਤਾ ਇਕੱਠੇ ਹੋ ਸਕਦੇ ਹਨ।
ਭਾਵੇਂ ਤੁਸੀਂ ਹਰ ਰੋਜ਼ Scala ਨਾ ਲਿਖੋ, ਜਿਨ੍ਹਾਂ ਵਿਚਾਰਾਂ ਨੂੰ ਅੱਜ JVM ਟੀਮਾਂ "ਸਧਾਰਨ" ਮੰਨਦੀਆਂ ਹਨ—ਵੱਧ FP ਪੈਟਰਨ, ਵੱਧ immutable ਡੇਟਾ, ਅਤੇ ਮਾਡਲਿੰਗ 'ਤੇ ਵੱਧ ਜ਼ੋਰ—ਉਹਨਾਂ ਵਿਚਾਰਾਂ ਨੂੰ Scala ਦੀ ਸਫਲਤਾ ਨੇ ਤੇਜ਼ ਕੀਤਾ।
Scala ਦਾ ਮੂਲ ਵਿਚਾਰ ਸਿੱਧਾ ਹੈ: ਉਹ OO ਮਾਡਲ ਰੱਖੋ ਜਿਸ ਨੇ Java ਨੂੰ ਵਰਤਣਯੋਗ ਬਣਾਇਆ (classes, interfaces, encapsulation), ਅਤੇ ਉਹਨਾਂ ਵਿਚ ਫੰਕਸ਼ਨਲ ਪ੍ਰੋਗ੍ਰਾਮਿੰਗ ਦੇ ਉਪਕਰਣ ਜੋੜੋ ਜੋ ਕੋਡ ਨੂੰ ਟੈਸਟ ਅਤੇ ਸਮਝਣ ਵਿੱਚ ਆਸਾਨ ਬਣਾਉਂਦੇ ਹਨ (first-class functions, immutability ਦੇ ਰੁਝਾਨ, algebraic-ਸ਼ੈਲੀ ਡੇਟਾ ਮਾਡਲਿੰਗ)।
ਟੀਮਾਂ ਨੂੰ ਇੱਕ ਪਾਸੇ ਚੁਣਨ ਲਈ ਮਜਬੂਰ ਕਰਨ ਦੀ ਬਜਾਏ—ਸ਼ੁੱਧ OO ਜਾਂ ਸ਼ੁੱਧ FP—Scala ਦੋਹਾਂ ਵਰਤੋਂ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ:
Scala ਨੇ ਇਹ ਸਾਬਤ ਕੀਤਾ ਕਿ ਇਹ ਵਿਚਾਰ JVM 'ਤੇ ਪ੍ਰੋਡਕਸ਼ਨ ਸਕੇਲ 'ਤੇ ਕੰਮ ਕਰ ਸਕਦੇ ਹਨ—ਸਿਰਫ਼ ਅਕਾਦਮਿਕ ਸੈਟਿੰਗ ਵਿੱਚ ਨਹੀਂ। ਇਸ ਨੇ ਪ੍ਰਭਾਵਿਤ ਕੀਤਾ ਕਿ ਬੈਕਐਂਡ ਸਰਵਿਸਜ਼ ਕਿਵੇਂ ਬਣਦੇ ਹਨ (ਵਧੇਰੇ ਸਪਸ਼ਟ ਐਰਰ ਹੈਂਡਲਿੰਗ, ਵਧੇਰੇ immutable ਡੇਟਾ ਫਲੋ), ਲਾਇਬ੍ਰੇਰੀਆਂ ਦੀ ਡਿਜ਼ਾਇਨ ਕਿਵੇਂ ਹੁੰਦੀ ਹੈ (ਉਪਭੋਗਤਾ ਨੂੰ ਸਹੀ ਵਰਤੋਂ ਵੱਲ ਗਾਈਡ ਕਰਨ ਵਾਲੇ API), ਅਤੇ ਡੇਟਾ ਪ੍ਰੋਸੈਸਿੰਗ ਫਰੇਮਵਰਕ ਕਿਵੇਂ ਵਿਕਸਿਤ ਹੋਏ (Spark ਦੀ Scala ਜੜ੍ਹਾਂ ਇੱਕ ਜਾਣੀ-ਪਹਚਾਣੀ ਉਦਾਹਰਨ ਹੈ)।
ਇਸੇ ਤਰ੍ਹਾਂ, Scala ਨੇ ਇਹ ਪ੍ਰਾਇਕਟੀਕਲ ਗੱਲਬਾਤਾਂ ਨੂੰ ਜਨਮ ਦਿੱਤਾ ਜੋ ਅਜੇ ਵੀ ਆਧੁਨਿਕ ਟੀਮਾਂ ਨੂੰ ਆਕਾਰ ਦਿੰਦੀਆਂ ਹਨ: ਕਿਹੜੀ ਜਟਿਲਤਾ ਕਾਬਿਲ-ਏ-ਕਬੂਲ ਹੈ? ਇੱਕ ਪਾਵਰਫੁਲ ਟਾਈਪ ਸਿਸਟਮ ਕਿੱਥੇ ਸਪਸ਼ਟਤਾ ਵਧਾਉਂਦਾ ਹੈ ਅਤੇ ਕਿੱਥੇ ਕੋਡ ਪੜ੍ਹਨ ਲਈ ਔਖਾ ਕਰ ਦਿੰਦਾ ਹੈ? ਇਹ ਤਰਜੀਹਾਂ ਹੁਣ JVM 'ਤੇ ਭਾਸ਼ਾ ਅਤੇ API ਡਿਜ਼ਾਇਨ ਦੇ ਕੇਂਦਰੀ ਮਾਮਲੇ ਹਨ।
ਅਸੀਂ Scala ਦੇ ਆਏ ਸਮੇਂ ਵਾਲੇ JVM ਮਾਹੌਲ ਨਾਲ ਸ਼ੁਰੂ ਕਰਾਂਗੇ, ਫਿਰ FP-ਰੁੱਝਾਨ ਅਤੇ OO ਦੇ ਵਿਚਕਾਰ ਟੰਸ਼ਨ ਨੂੰ ਖੋਲ੍ਹਾਂਗੇ ਜੋ Scala ਨੇ ਸਮਾਧਾਨ ਕੀਤਾ। ਫਿਰ ਅਸੀਂ ਦੈਨਿੰਦਿਨੀ ਫੀਚਰਾਂ ਨੂੰ ਵੇਖਾਂਗੇ ਜਿਨ੍ਹਾਂ ਨੇ Scala ਨੂੰ "ਦੋਹਾਂ ਵਿਚੋਂ ਚੁਣਣ ਵਾਲਾ" ਟੂਲਕਿਟ ਬਣਾਇਆ (traits, case classes, pattern matching), ਟਾਈਪ-ਸਿਸਟਮ ਦੀ ਤਾਕਤ (ਅਤੇ ਇਸ ਦੀਆਂ ਲਾਗਤਾਂ), ਅਤੇ implicits ਅਤੇ type classes ਦੀ ਡਿਜ਼ਾਇਨ ਨੂੰ ਸਮਝਾਂਗੇ।
ਅਖੀਰ ਵਿੱਚ, ਅਸੀਂ concurrency, Java ਇੰਟਰਓਪਰੇਬਿਲਟੀ, Scala ਦਾ ਉਦਯੋਗੀ ਪੈਰੋਕਾਰ, Scala 3 ਨੇ ਕੀ ਸੁਧਾਰ ਕੀਤਾ, ਅਤੇ ਉਹ ਸਥਾਈ ਸਬਕ ਜੋ ਭਾਸ਼ਾ ਡਿਜ਼ਾਇਨਰਾਂ ਅਤੇ ਲਾਇਬ੍ਰੇਰੀ ਲੇਖਕਾਂ ਲਈ ਲਾਗੂ ਹੁੰਦੇ ਹਨ—ਚਾਹੇ ਉਹ Scala, Java, Kotlin, ਜਾਂ ਹੋਰ ਕੁਝ JVM 'ਤੇ ਭੇਜੇ ਜਾਣ।
ਜਦੋਂ Scala 2000 ਤੋਂ ਪਹਿਲਾਂ ਦੀ ਸ਼ੁਰੂਆਤ 'ਚ ਉਭਰੀ, JVM ਅਕਸਰ "Java ਦਾ ਰਨਟਾਈਮ" ਸੀ। Java ਕਾਰੋਬਾਰ ਸੌਫਟਵੇਅਰ ਉੱਤੇ ਹਾਕਮੇਤ ਸੀ: ਇੱਕ ਸਥਿਰ ਪਲੇਟਫਾਰਮ, ਮਜ਼ਬੂਤ ਵੈਂਡਰ ਸਮਰਥਨ, ਅਤੇ ਵੱਡਾ ਇਕੋਸਿਸਟਮ।
ਪਰ ਟੀਮਾਂ ਨੂੰ ਵੀ ਵੱਡੇ ਸਿਸਟਮ ਬਣਾਉਣ ਵਿੱਚ ਅਸਲ ਤਕਲੀਫ਼ਾਂ ਮਹਿਸੂਸ ਹੋ ਰਹੀਆਂ ਸਨ—ਖਾਸ ਕਰਕੇ ਬੋਇਲਰਪਲੇਟ ਭਰੇ ਮਾਡਲ, ਨਲ ਹੈਂਡਲਿੰਗ ਜਿਹੜੀ ਗਲਤੀਆਂ ਲਿਆਉਂਦੀ, ਅਤੇ concurrency primitives ਜੋ ਆਸਾਨੀ ਨਾਲ ਗਲਤ ਵਰਤੇ ਜਾਂਦੇ।
JVM ਲਈ ਨਵੀਂ ਭਾਸ਼ਾ ਡਿਜ਼ਾਇਨ ਕਰਨਾ ਨਵਾਂ ਸਫਾ ਸ਼ੁਰੂ ਕਰਨ ਵਰਗਾ ਨਹੀਂ ਸੀ। Scala-ਨੂੰ ਓਸ ਤਰੀਕੇ ਨਾਲ ਬਣਾਇਆ ਗਿਆ ਕਿ ਉਹ:
ਭਾਵੇਂ ਕੋਈ ਭਾਸ਼ਾ ਕਾਗਜ਼ 'ਤੇ ਚੰਗੀ ਲੱਗੇ, ਪਰ ਸੰਗਠਨਾਂ ਨੂੰ ਸੰਕੋਚ ਹੁੰਦਾ ਹੈ। ਨਵੀਂ JVM ਭਾਸ਼ਾ ਨੂੰ ਟ੍ਰੇਨਿੰਗ ਦੀ ਲਾਗਤ, ਭਰਤੀ ਦੀਆਂ ਚੁਣੌਤੀਆਂ, ਕਮਜ਼ੋਰ ਟੂਲਿੰਗ ਜਾਂ ਉਲਝਾਉਣ ਵਾਲੇ ਸਟੈਕ ਟ੍ਰੇਸ ਦੇ ਖਤਰੇ ਨੂੰ ਨਿਆਂਸ ਕਰਨਾ ਪੈਂਦਾ ਹੈ। ਇਸਦੇ ਨਾਲ-ਨਾਲ ਇਹ ਵੀ ਦਿਖਾਉਣਾ ਪੈਂਦਾ ਕਿ ਇਹ ਟੀਮਾਂ ਨੂੰ ਕਿਸੇ ਨਿੱਕ-ਇਕੋਸਿਸਟਮ ਵਿੱਚ ਫਸਾਏਗੀ ਨਹੀਂ।
Scala ਦਾ ਪ੍ਰਭਾਵ ਸਿਰਫ਼ ਸਿੰਟੈਕਸ ਤੱਕ ਸੀਮਿਤ ਨਹੀਂ ਸੀ। ਇਸਨੇ ਲਾਇਬ੍ਰੇਰੀ-ਪਹਿਲੇ ਨਵੀਨਤਾ ਨੂੰ ਉਤਸ਼ਾਹਿਤ ਕੀਤਾ (ਵਧੇਰੇ ਐਕਸਪ੍ਰੈਸਿਵ ਕਲੇਕਸ਼ਨ ਅਤੇ ਫੰਕਸ਼ਨਲ ਪੈਟਰਨ), ਬਿਲਡ ਟੂਲਿੰਗ ਅਤੇ ਨਿਰਭਰਤਾ ਵਰਕਫ਼ਲੋਅਜ਼ ਨੂੰ ਅੱਗੇ ਧਕੇਆ (Scala ਵਰਜਨ, cross-building, ਕੰਪਾਇਲਰ ਪਲੱਗਇਨ), ਅਤੇ ਐਸੇ API ਡਿਜ਼ਾਇਨ ਨਾਰਮ ਕਰਨ ਵਿੱਚ ਯੋਗਦਾਨ ਦਿੱਤਾ ਜੋ immutability, composability, ਅਤੇ ਸੁਰੱਖਿਅਤ ਮਾਡਲਿੰਗ ਨੂੰ ਤਰਜੀਹ ਦਿੰਦੇ—ਸਭ JVM ਦੇ ਆਪਰੇਸ਼ਨਲ ਆਰਾਮਦਾਇਕ ਖੇਤਰ ਵਿੱਚ ਰਹਿਣ ਦੇ ਨਾਲ।
Scala ਇੱਕ ਆਮ ਦਲਾਂਦਾਜ਼ੀ ਰੋਕਣ ਲਈ ਬਣਾਈ ਗਈ ਸੀ: ਕੀ ਇੱਕ JVM ਟੀਮ ਨੂੰ object-oriented ਡਿਜ਼ਾਇਨ 'ਤੇ ਜ਼ੋਰ ਦੇਣਾ ਚਾਹੀਦਾ ਹੈ, ਜਾਂ ਐਸਾ ਫੰਕਸ਼ਨਲ ਅੰਦਾਜ਼ ਅਪਨਾਉਣਾ ਜੋ ਬੱਗ ਘਟਾਏ ਅਤੇ ਦੁਬਾਰਲ استعمال ਵਧਾਏ?
Scala ਦਾ ਜਵਾਬ ਇਹ ਨਹੀਂ ਸੀ ਕਿ "ਇੱਕ ਚੁਣੋ," ਅਤੇ ਨਾ ਹੀ "ਸਭ ਕੁਝ ਮਿਲਾ ਦਿਓ." ਪੇਸ਼ਕਸ਼ ਵੱਧ ਪ੍ਰਗਟਿਕ ਸੀ: ਦੋਹਾਂ ਅੰਦਾਜ਼ਾਂ ਨੂੰ ਪਹਿਲ-ਕਲਾਸ ਟੂਲਾਂ ਨਾਲ ਸਮਰਥਨ ਦਿਓ, ਅਤੇ ਇੰਜੀਨੀਅਰਾਂ ਨੂੰ ਹਰ ਥਾਂ ਉਹੀ ਪਿਛਾਣ ਦਿੱਤੀ ਜਾਵੇ ਜਿੱਥੇ ਇਹ ਸੁਟੇਬਲ ਹੋ।
ਕਲਾਸਿਕ OO ਵਿੱਚ, ਤੁਸੀਂ ਇਕ ਸਿਸਟਮ ਨੂੰ classes ਨਾਲ ਮਾਡਲ ਕਰਦੇ ਹੋ ਜੋ ਡੇਟਾ ਅਤੇ ਵਿਹਾਰ ਨੂੰ ਇੱਕਠੇ ਰੱਖਦੀਆਂ ਹਨ। ਤੁਸੀਂ ਵੇਰਵੇ ਲੁਕਾਉਂਦੇ ਹੋ encapsulation ਰਾਹੀਂ (ਸਟੇਟ ਨੂੰ ਪ੍ਰਾਈਵੇਟ ਰੱਖ ਕੇ ਅਤੇ ਮੈਥਡਾਂ ਜ਼ਰੀਏ ਰਿਹਾੜੀ ਦੇ ਕੇ), ਅਤੇ ਤੁਸੀਂ ਕੋਡ ਨੂੰ ਦੁਬਾਰਾ ਵਰਤੋਂ ਲਈ interfaces (ਜਾਂ abstract types) ਰਾਹੀਂ ਦੁਹਰਾਉਂਦੇ ਹੋ।
OO ਉਸ ਵੇਲੇ ਚਮਕਦਾ ਹੈ ਜਦੋਂ ਤੁਸੀਂ ਲੰਬੇ ਸਮੇਂ ਰਹਿਣ ਵਾਲੇ ਇਕਾਈਆਂ ਵਰਤ ਰਹੇ ਹੋ ਜਿਨ੍ਹਾਂ ਦੀਆਂ ਜ਼ਿੰਮੇਵਾਰੀਆਂ ਸਪਸ਼ਟ ਹਨ—ਜਿਵੇਂ Order, User, ਜਾਂ PaymentProcessor।
FP ਤੁਹਾਨੂੰ immutability ਵੱਲ ਧਕਦਾ (ਮੁੱਲ ਬਣਨ ਤੋਂ ਬਾਅਦ ਬਦਲਦੇ ਨਹੀਂ), higher-order functions (ਜੋ ਹੋਰ ਫੰਕਸ਼ਨਸ ਲੈਂਦੇ ਜਾਂ ਵਾਪਸ ਕਰਦੇ ਹਨ), ਅਤੇ purity (ਫੰਕਸ਼ਨ ਦਾ ਆਉਟਪੁੱਟ ਸਿਰਫ਼ ਉਸਦੇ ਇਨਪੁੱਟ 'ਤੇ ਨਿਰਭਰ ਹੁੰਦਾ ਹੈ) ਵੱਲ।
FP ਉਸ ਵੇਲੇ ਚੰਗਾ ਹੈ ਜਦੋਂ ਤੁਸੀਂ ਡੇਟਾ ਨੂੰ ਰੂਪਾਂਤਰਿਤ ਕਰ ਰਹੇ ਹੋ, ਪਾਈਪਲਾਈਨਾਂ ਬਣਾ ਰਹੇ ਹੋ, ਜਾਂ concurrency ਹਾਲਾਤਾਂ ਵਿੱਚ ਭਰੋਸੇਯੋਗ ਵਿਹਾਰ ਚਾਹੁੰਦੇ ਹੋ।
JVM 'ਤੇ ਟਕਰਾਅ ਆਮ ਤੌਰ 'ਤੇ ਇਨ੍ਹਾਂ ਥਾਵਾਂ 'ਤੇ ਸਮne ਆਉਂਦਾ ਹੈ:
Scala ਦਾ ਉਦੇਸ਼ FP ਤਕਨੀਕਾਂ ਨੂੰ ਪ੍ਰਾਕ੍ਰਿਤਿਕ ਮਹਿਸੂਸ ਕਰਵਾਉਣਾ ਸੀ ਬਿਨਾਂ OO ਨੂੰ ਛੱਡੇ। ਤੁਸੀਂ ਹੇਠਾਂ ਵਰਤ ਸਕਦੇ ਹੋ:
Scala ਦੀ "ਦੋਹਾਂ ਵਿੱਚੋਂ ਚੰਗਾ" ਖਿਆਲ ਸਿਰਫ਼ ਫ਼ਲਸਫ਼ਾ ਨਹੀਂ—ਇਹ ਰੋਜ਼ਾਨਾ ਵਾਲੇ ਉਹ ਟੂਲ ਹਨ ਜੋ ਟੀਮਾਂ ਨੂੰ OO ਡਿਜ਼ਾਇਨ ਨੂੰ ਫੰਕਸ਼ਨਲ ਵਰਕਫਲੋਜ਼ ਨਾਲ ਮਿਲਾਉਣ ਦੇ ਯੋਗ ਬਣਾਉਂਦੇ ਹਨ ਬਿਨਾਂ ਹਰ ਵਾਰੀ ਉੱਤੇ ਵੱਡੀ ਪ੍ਰਕਿਰਿਆ ਦੇ।
ਤਿੰਨ ਮੁੱਖ ਫੀਚਰ ਜੋ Scala ਕੋਡ ਦਾ ਰੂਪ ਤੈਅ ਕਰਦੇ ਹਨ: traits, case classes, ਅਤੇ companion objects।
Traits Scala ਦਾ ਪ੍ਰਯੋਗਕਾਰੀ ਜਵਾਬ ਹੈ ਜਦੋਂ ਤੁਸੀਂ ਦੁਬਾਰਾ ਵਰਤਯੋਗ ਵਿਵਹਾਰ ਚਾਹੁੰਦੇ ਹੋ ਪਰ ਇਕ ਨਾਜ਼ੁਕ inheritance ਹਾਇਰਾਰਕੀ ਤੋਂ ਬਚਣਾ ਚਾਹੁੰਦੇ ਹੋ। ਇੱਕ class ਇੱਕ superclass ਨੂੰ extend ਕਰ ਸਕਦੀ ਹੈ ਪਰ ਬਹੁਤ ਸਾਰੇ traits ਨੂੰ mix in ਵੀ ਕਰ ਸਕਦੀ ਹੈ, ਜਿਸ ਨਾਲ logging, caching, validation ਵਰਗੀਆਂ ਕੈਪੈਬਿਲਿਟੀਜ਼ ਨੂੰ ਛੋਟੇ ਬਣੀ-ਬਣਾਈ ਇਲਾਕਿਆਂ ਵਜੋਂ ਮਾਡਲ ਕਰਨਾ ਆਸਾਨ ਹੋ ਜਾਂਦਾ ਹੈ।
OO ਦੀ ਦ੍ਰਿਸ਼ਟੀ ਤੋਂ, traits ਤੁਹਾਡੇ ਕੋਰ ਡੋਮੇਨ ਟਾਈਪਸ ਨੂੰ ਕੇਂਦਰੀ ਰੱਖਦੇ ਹਨ ਜਦਕਿ ਵਿਹਾਰ ਦੀ ਕੰਪੋਜ਼ੀਸ਼ਨ ਮੁਮਕਿਨ ਬਣਾਉਂਦੇ ਹਨ। FP ਦੀਆਂ ਵਿਰਾਸਤਾਂ ਵਿੱਚ, traits ਅਕਸਰ ਸ਼ੁੱਧ ਹੇਲਪਰ ਮੈਥਡਾਂ ਜਾਂ ਛੋਟੇ algebra-ਲਾਈਕ ਇੰਟਰਫੇਸ ਰੱਖਦੇ ਹਨ ਜੋ ਵੱਖ-ਵੱਖ ਤਰੀਕਿਆਂ ਨਾਲ ਲਾਗੂ ਕੀਤੇ ਜਾ ਸਕਦੇ ਹਨ।
Case classes "ਡੇਟਾ-ਪਹਿਲੇ" ਟਾਈਪ ਬਣਾਉਂਦੀਆਂ ਹਨ—ਕਨਸਟਰਕਟਰ ਪੈਰਾਮੀਟਰ ਖੇਤਰ ਬਣ ਜਾਂਦੇ ਹਨ, ਬਰਾਬਰੀ ਲੋਕਾਂ ਦੀ ਉਮੀਦ ਅਨੁਸਾਰ ਕੰਮ ਕਰਦੀ ਹੈ (by value), ਅਤੇ ਡੀਬੱਗ ਲਈ ਪੜ੍ਹਨਯੋਗ ਪ੍ਰਤਿਨਿਧਿਤਾ ਮਿਲਦੀ ਹੈ।
ਉਹ pattern matching ਨਾਲ ਬੇਹੱਦ ਵਧੀਆ ਤਰੀਕੇ ਨਾਲ ਕੰਮ ਕਰਦੀਆਂ ਹਨ, ਜਿਸ ਨਾਲ ਵਿਕਾਸਕਾਰਾਂ ਨੂੰ ਡੇਟਾ ਸ਼ੇਪਸ ਨੂੰ ਹੋਰ ਸੁਰੱਖਿਅਤ ਅਤੇ ਸਪਸ਼ਟ ਤਰੀਕੇ ਨਾਲ ਹੈਂਡਲ ਕਰਨ ਲਈ ਉਤਸ਼ਾਹ ਮਿਲਦਾ ਹੈ—null checks ਜਾਂ instanceof ਟੈਸਟ ਵੰਡਣ ਦੀ ਥਾਂ ਤੁਸੀਂ case class 'ਤੇ match ਕਰਕੇ ਲੋੜ ਦੀ ਚੀਜ਼ ਕੱਢ ਸਕਦੇ ਹੋ।
Companion objects (ਉਸੇ ਨਾਮ ਵਾਲਾ object ਜੋ class ਦੇ ਨਾਲ ਹੁੰਦਾ ਹੈ) API ਡਿਜ਼ਾਇਨ 'ਚ ਛੋਟਾ ਪਰ ਪ੍ਰਭਾਵਸ਼ਾਲੀ ਵਿਚਾਰ ਹੈ। ਇਹ ਤੁਹਾਨੂੰ factories, constants, ਅਤੇ utility methods ਲਈ ਇੱਕ ਘਰ ਦਿੰਦਾ ਹੈ—ਬਿਨਾਂ ਵੱਖ-ਵੱਖ “Utils” ਕਲਾਸ ਬਣਾਉਣ ਜਾਂ ਸਭ ਕੁਝ static ਮੈਥਡਾਂ ਵਿੱਚ ਰੱਖਣ ਲਈ।
ਇਸ ਨਾਲ OO-ਸ਼ੈਲੀ ਦਾ ਨਿਰਮਾਣ ਸੁੰਢਾ ਰਹਿੰਦਾ ਹੈ, ਜਦਕਿ FP-ਸ਼ੈਲੀ ਦੇ ਹੇਲਪਰ (ਜਿਵੇਂ apply for lightweight creation) ਉੱਸੇ ਟਾਈਪ ਦੇ ਨੇੜੇ ਰਹਿ ਸਕਦੇ ਹਨ।
ਇਕੱਠੇ, ਇਹ ਫੀਚਰ ਇੱਕ ਐਸੇ ਕੋਡਬੇਸ ਨੂੰ ਬਢਾਉਂਦੇ ਹਨ ਜਿੱਥੇ ਡੋਮੇਨ ਓਬਜੈਕਟ ਸਪਸ਼ਟ ਅਤੇ ਇੰਕੈਪਸੂਲੇਟਡ ਹੁੰਦੇ ਹਨ, ਡੇਟਾ ਟਾਈਪਸ ਰੂਪਾਂਤਰ ਕਰਨ ਲਈ ਸਹੂਲਤਯੋਗ ਹੁੰਦੇ ਹਨ, ਅਤੇ APIs ਇੱਕਸਾਰ ਮਹਿਸੂਸ ਹੁੰਦੇ ਹਨ—ਚਾਹੇ ਤੁਸੀਂ ਆਬਜੈਕਟ-ਵਿੱਚ ਸੋਚ ਰਹੇ ਹੋ ਜਾਂ ਫੰਕਸ਼ਨ-ਵਿੱਚ।
Scala ਦੀ pattern matching ਡੇਟਾ ਦੇ ਆਕਾਰ ਦੇ ਅਧਾਰ 'ਤੇ branching ਲਿਖਣ ਦਾ ਤਰੀਕਾ ਹੈ—ਸਿਰਫ਼ ਬੂਲੀਅਨ ਜਾਂ ਵਿਖਰੇ ਹੋਏ if/else ਚੈਨਾਂ ਦੀ ਥਾਂ। ਤੁਸੀਂ ਪੁੱਛਦੇ ਹੋ "ਇਹ ਕਿਸ ਕਿਸਮ ਦੀ ਚੀਜ਼ ਹੈ?"—ਅਤੇ ਕੋਡ ਇੱਕ ਸੈਟ ਸਪਸ਼ਟ, ਨਾਮਵਾਰ ਕੇਸ ਵਾਂਗ ਪੜ੍ਹਦਾ ਹੈ।
ਸਰਲ ਉਦਾਹਰਨ ਵਿੱਚ, pattern matching conditionals ਦੀਆਂ ਲੜੀਆਂ ਦੀ ਥਾਂ ਲੈ ਲੈਂਦਾ ਹੈ:
sealed trait Result
case class Ok(value: Int) extends Result
case class Failed(reason: String) extends Result
def toMessage(r: Result): String = r match {
case Ok(v) => s"Success: $v"
case Failed(msg) => s"Error: $msg"
}
ਇਹ ਅੰਦਾਜ਼ ਮਨਸੂਬਾ ਸਪਸ਼ਟ ਬਣਾਉਂਦਾ ਹੈ: Result ਦੇ ਹਰ ਸੰਭਵ ਫਾਰਮ ਨੂੰ ਇਕੱਠੇ ਲੱਭੋ ਅਤੇ ਹੈਂਡਲ ਕਰੋ।
Scala ਤੁਹਾਨੂੰ ਇਕ ਹੀ "one-size-fits-all" ਕਲਾਸ ਹਾਇਰਾਰਕੀ ਵਿੱਚ ਫਸਾਉਂਦੀ ਨਹੀਂ। sealed traits ਨਾਲ ਤੁਸੀਂ ਛੋਟਾ, ਬੰਦ ਵਿਕਲਪਾਂ ਦਾ ਸੈੱਟ ਪਰਿਭਾਸ਼ਿਤ ਕਰ ਸਕਦੇ ਹੋ—ਅਕਸਰ ਇਸਨੂੰ algebraic data type (ADT) ਕਹਿੰਦੇ ਹਨ।
"Sealed" ਦਾ ਮਤਲਬ ਹੈ ਕਿ ਸਾਰੇ ਮੰਨਿਆ ਗਿਆ variant ਇੱਕੱਠੇ ਪਛਾਣੇ ਜਾਣੇ ਚਾਹੀਦੇ ਹਨ (ਆਮ ਤੌਰ 'ਤੇ ਇੱਕੋ ਫਾਈਲ ਵਿੱਚ), ਤਾਂ ਜੋ ਕੰਪਾਇਲਰ ਪੂਰੀ ਸੰਭਾਵਨਾਵਾਂ ਨੂੰ ਜਾਣ ਸਕੇ।
ਜਦੋਂ ਤੁਸੀਂ ਇੱਕ sealed hierarchy 'ਤੇ match ਕਰਦੇ ਹੋ, Scala ਤੁਹਾਨੂੰ ਚੇਤਾਵਨੀ ਦੇ ਸਕਦੀ ਹੈ ਜੇ ਤੁਸੀਂ ਕੋਈ ਕੇਸ ਭੁੱਲ ਗਏ ਹੋ। ਇਹ ਇੱਕ ਵੱਡਾ ਅਮਲੀ ਫਾਇਦਾ ਹੈ: ਜਦੋਂ ਤੁਸੀਂ ਬਾਅਦ ਵਿੱਚ case class Timeout(...) extends Result ਸ਼ਾਮਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਕੰਪਾਇਲਰ ਹਰ(match) ਥਾਂ 'ਤੇ ਨਿਸ਼ਾਨੀ ਕਰ ਸਕਦਾ ਹੈ ਜਿੱਥੇ ਅਪਡੇਟ ਕਰਨ ਦੀ ਲੋੜ ਹੈ।
ਇਸ ਨਾਲ ਬੱਗ ਪੂਰੀ ਤਰ੍ਹਾਂ ਖਤਮ ਨਹੀਂ ਹੁੰਦੇ—ਤੁਹਾਡੀ ਲੋਜਿਕ ਫ਼ੌਲਤੀ ਹੋ ਸਕਦੀ ਹੈ—ਪਰ ਇਹ ਇਕ ਆਮ "ਅਨਹੈਂਡਲਡ ਸਟੇਟ" ਵਾਲੀ ਗਲਤੀ ਨੂੰ ਘਟਾਉਂਦਾ ਹੈ।
Pattern matching ਅਤੇ sealed ADTs APIs ਨੂੰ ਇਹੁ ਤਰੀਕੇ ਨਾਲ ਉਤਸ਼ਾਹਿਤ ਕਰਦੇ ਹਨ:
Ok/Failed (ਜਾਂ ਹੋਰ ਵਿਕਲਪ) ਵਾਪਸ ਕਰੋ, null ਜਾਂ ਧੁੰਦਲੇ exception ਦੀ ਥਾਂ।Loading/Ready/Empty/Crashed ਵਰਗੇ ਸਟੇਟਾਂ ਨੂੰ ਡੇਟਾ ਵਜੋਂ ਦਰਸਾਓ, ਨਾ ਕਿ ਵਿਖਰੇ ਹੋਏ ਫਲੈਗਸ ਵਜੋਂ।Create, Update, Delete) ਨੂੰ ਮਾਡਲ ਕਰੋ ਤਾਂ ਜੋ ਹੈਂਡਲਰ ਕੁਦਰਤੀ ਤਰ੍ਹਾਂ ਪੂਰੇ ਹਨ।ਨਤੀਜਾ ਇਹ ਹੁੰਦਾ ਹੈ ਕਿ ਕੋਡ ਪੜ੍ਹਨ ਵਿੱਚ ਅਸਾਨ, ਗਲਤ-ਵਰਤੋਂ ਲਈ ਮੁਸ਼ਕਲ ਅਤੇ ਸਮੇਂ ਦੇ ਨਾਲ ਰਿਫੈਕਟਰਿੰਗ-ਮਿੱਤਰ ਬਣ ਜਾਂਦਾ ਹੈ।
Scala ਦਾ ਟਾਈਪ ਸਿਸਟਮ ਇੱਕ ਵੱਡਾ ਕਾਰਣ ਹੈ ਕਿ ਭਾਸ਼ਾ ਕਿਵੇਂ ਸੁੰਦਰ ਤੇ ਗਹਿਰੀ ਮਹਿਸੂਸ ਕਰ ਸਕਦੀ ਹੈ। ਇਹ ਫੀਚਰ API ਨੂੰ ਐਕਸਪ੍ਰੈਸਿਵ ਅਤੇ ਦੁਹਰਾਏ ਜਾਣਯੋਗ ਬਣਾਉਂਦੇ ਹਨ, ਪਰ ਰੋਜ਼ਾਨਾ ਕੋਡ ਅਜੇ ਵੀ ਪੜ੍ਹਨਯੋਗ ਰਹਿਣ ਲਈ ਇਹ ਤਾਕਤ ਸਮਰਥਿਤ ਅਤੇ ਸੰਯਮਿਤ ਤਰੀਕੇ ਨਾਲ ਵਰਤੀ ਜਾਣੀ ਚਾਹੀਦੀ ਹੈ।
ਕੰਪਾਇਲਰ ਅਕਸਰ ਉਹ ਟਾਈਪਸ ਸਮਝ ਲੈਂਦਾ ਹੈ ਜੋ ਤੁਸੀਂ ਨਹੀਂ ਲਿਖਦੇ। ਬਜਾਏ ਦੁਹਰਾਉਣ ਦੇ, ਤੁਸੀਂ ਇਰਾਦਾ ਨਾਮ ਦੇ ਕੇ ਅੱਗੇ ਵੱਧ ਸਕਦੇ ਹੋ।
val ids = List(1, 2, 3) // inferred: List[Int]
val nameById = Map(1 -> "A") // inferred: Map[Int, String]
def inc(x: Int) = x + 1 // inferred return type: Int
ਇਸ ਨਾਲ ਕੋਡ ਵਿਚਲੇ ਸਮਰੂਪਾਂ ਨੂੰ ਲਘੂ ਰੱਖਣਾ ਆਸਾਨ ਹੁੰਦਾ ਹੈ—ਖਾਸ ਕਰਕੇ FP-ਸ਼ੈਲੀ ਪਾਈਪਲਾਈਨਾਂ ਵਿੱਚ।
Scala ਦੀਆਂ ਕਲੇਕਸ਼ਨ ਅਤੇ ਲਾਇਬ੍ਰੇਰੀਆਂ ਜਨਰੇਿਕਸ List[A], Option[A] ਵਰਗੀਆਂ 'ਤੇ ਭਰੋਸਾ ਕਰਦੀਆਂ ਹਨ। Variance ਐਨੋਟੇਸ਼ਨ (+A, -A) ਇਹ ਦਰਸਾਉਂਦੇ ਹਨ ਕਿ ਕਿਸ ਤਰ੍ਹਾਂ subtype ਹਰ parameter ਲਈ ਕੰਮ ਕਰਦਾ ਹੈ।
ਇੱਕ ਸਧਾਰਨ ਮਾਡਲ:
+A): "Cats ਵਾਲਾ container, Animals ਵਾਲੇ container ਦੀ ਥਾਂ ਵਰਤੀ ਜਾ ਸਕਦਾ ਹੈ" (immutable, read-only structures ਲਈ ਵਧੀਆ)-A): ਆਮ ਤੌਰ 'ਤੇ consumers ਜਿਹੜੇ function inputs ਲਈ ਹੁੰਦੇ ਹਨVariance ਇੱਕ ਕਾਰਨ ਹੈ ਕਿ Scala ਲਾਇਬ੍ਰੇਰੀ ਡਿਜ਼ਾਇਨ ਫਲਕਸਬਲ ਅਤੇ ਸੁਰੱਖਿਅਤ ਇੱਕੋ ਸਮੇਂ ਹੋ ਸਕਦੀ ਹੈ: ਇਹ ਤੁਹਾਨੂੰ Any ਵਰਗੇ ਸਭ ਕੁਝ ਨਹੀਂ ਬਣਾਉਣ ਦਿੰਦਾ।
ਉੱਚ-ਪੱਧਰੀ ਟਾਈਪਸ—higher-kinded types, path-dependent types, implicit-driven abstractions—ਬਹੁਤ ਐਕਸਪ੍ਰੈਸਿਵ ਲਾਇਬ੍ਰੇਰੀਆਂ ਦੀ ਆਗਿਆ ਦਿੰਦੀਆਂ ਹਨ। ਨੁਕਸਾਨ ਇਹ ਹੈ ਕਿ ਕੰਪਾਇਲਰ ਨੂੰ ਹੋਰ ਕੰਮ ਕਰਨਾ ਪੈਂਦਾ ਹੈ, ਅਤੇ ਜਦੋਂ ਉਹ ਫੇਲ ਹੁੰਦਾ ਹੈ ਤਾਂ ਸੁਨੇਹੇ ਭਿਆਨਕ ਹੋ ਸਕਦੇ ਹਨ।
ਤੁਸੀਂ ਐਸੇ ਐਰਰ ਵੇਖ ਸਕਦੇ ਹੋ ਜੋ inferred ਟਾਈਪਸ ਦਾ ਜ਼ਿਕਰ ਕਰਦੇ ਹਨ ਜੋ ਤੁਸੀਂ ਕਦੇ ਨਹੀਂ ਲਿਖੇ, ਜਾਂ ਲੰਮੇ constraint ਚੈਨ। ਕੋਡ ਆਤਮ-ਰੂਪ ਵਿੱਚ ਠੀਕ ਹੋ ਸਕਦਾ ਹੈ, ਪਰ ਕੰਪਾਇਲਰ ਨੂੰ ਠੀਕ ਰੂਪ 'ਚ ਨਾ ਮਿਲਣ ਕਾਰਨ ਤਰੀਕੇ ਨੂੰ ਸੁਚਿਤ ਕਰਨ ਵਿੱਚ ਮੁਸ਼ਕਲ ਆ ਸਕਦੀ ਹੈ।
ਇੱਕ ਪ੍ਰਗਟਿਕ ਨਿਯਮ: ਇਨਫਰੈਂਸ ਨੂੰ ਲੋਕਲ ਵੇਰਵਿਆਂ ਲਈ ਛੱਡੋ, ਪਰ ਮਹੱਤਵਪੂਰਨ ਬਾਊਂਡਰੀਆਂ 'ਤੇ ਟਾਈਪ ਐਨੋਟੇਸ਼ਨ ਦਿਓ।
ਸਪਸ਼ਟ ਟਾਈਪਾਂ ਵਰਤੋ ਜਦੋਂ:
ਇਸ ਨਾਲ ਕੋਡ ਮਨੁੱਖਾਂ ਲਈ ਪੜ੍ਹਨਯੋਗ ਰਹਿੰਦਾ ਹੈ, ਟ੍ਰੀਬਲਸ਼ੂਟਿੰਗ ਤੇ ਤੇਜ਼ੀ ਆਉਂਦੀ ਹੈ, ਅਤੇ ਟਾਈਪਸ ਇੱਕ ਪ੍ਰਕਾਰ ਦਾ ਡੌਕੂਮੈਂਟ ਬਣ ਜਾਂਦੇ ਹਨ—Scala ਦੀ ਸਹੂਲਤ ਨੂੰ ਘਟਾਏ ਬਿਨਾਂ।
Scala ਦੇ implicits ਇੱਕ ਬਹਾਦੁਰ ਜਵਾਬ ਸਨ ਇਸ ਆਮ JVM ਸਮੱਸਿਆ ਦਾ: ਮੌਜੂਦਾ ਟਾਈਪਸ (ਖਾਸ ਕਰਕੇ Java ਟਾਈਪਸ) ਨੂੰ ਬਿਨਾਂ inheritance, ਹਰ ਥਾਂ wrappers, ਜਾਂ ਸ਼ੋਰ-ਭਰੇ utility calls ਦੇ "ਥੋੜ੍ਹੀ ਜਿਹੀ" ਵਿਵਹਾਰ ਕਿਵੇਂ ਜੋੜਿਆ ਜਾਵੇ?
ਅਮਲੀ ਤੌਰ 'ਤੇ implicits ਕੰਪਾਇਲਰ ਨੂੰ ਉਹ ਪਾਰਾਮੀਟਰ ਸਪਲਾਈ ਕਰਨ ਦਿੰਦੇ ਹਨ ਜੋ ਤੁਸੀਂ ਸਪਸ਼ਟ ਤੌਰ 'ਤੇ ਨਹੀਂ ਦਿੱਤੇ, ਜੇ ਇਕ ਉਪਯੋਗਤਾ ਮੌਕਿਆਂ ਵਿੱਚ ਪੇਸ਼ ਕੀਤੀ ਗਈ ਹੋਵੇ। implicit conversions (ਅਤੇ ਬਾਅਦ ਵਿੱਚ ਹੋਰ ਸਪਸ਼ਟ extension-method ਪੈਟਰਨ) ਦੇ ਨਾਲ, ਇਹ ਇੱਕ ਸੁਚੱਜਾ ਤਰੀਕਾ ਦਿੱਤਾ ਕਿ ਤੁਸੀਂ ਉਹਨਾਂ ਟਾਈਪਸ 'ਤੇ ਨਵੀਂ ਮੈਥਡ ਅਟੈਚ ਕਰ ਸਕਦੇ ਹੋ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਸੀਂ ਕਾਬੂ ਨਹੀਂ ਕਰਦੇ।
ਇਸ ਤਰ੍ਹਾਂ ਤੁਸੀਂ fluent APIs ਮਿਲਾਓ: Syntax.toJson(user) ਦੀ ਥਾਂ user.toJson ਲਿਖ ਸਕਦੇ ਹੋ, ਜਿੱਥੇ toJson ਇੱਕ imported implicit class ਜਾਂ conversion ਦੁਆਰਾ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ। ਇਹ Scala ਲਾਇਬ੍ਰੇਰੀਆਂ ਨੂੰ ਇੱਕਠੇ ਮਹਿਸੂਸ ਕਰਵਾਉਂਦਾ—ਛੋਟੀ, ਕੰਪੋਜ਼ਬਲ ਪੀਸਾਂ ਤੋਂ ਬਣਿਆ ਹੋਇਆ ਵੀ।
ਵੱਧ ਮਹੱਤਵਪੂਰਨ ਗੱਲ ਇਹ ਸੀ ਕਿ implicits ਨੇ type classes ਨੂੰ ਅਰਾਮਦਾਇਕ ਬਣਾਇਆ। type class ਇਹ ਕਹਿਣ ਦਾ ਤਰੀਕਾ ਹੈ: "ਇਹ ਟਾਈਪ ਇਹ ਵਿਵਹਾਰ ਸਮਰਥਨ ਕਰਦਾ ਹੈ", ਬਿਨਾਂ ਉਸ ਟਾਈਪ ਨੂੰ ਬਦਲੇ। ਲਾਇਬ੍ਰੇਰੀਆਂ Show[A], Encoder[A], ਜਾਂ Monoid[A] ਵਰਗੀਆਂ abstractions ਪਰਿਭਾਸ਼ਿਤ ਕਰ ਸਕਦੀਆਂ ਹਨ, ਅਤੇ ਫਿਰ ਉਨ੍ਹਾਂ ਦੀਆਂ instances implicits ਰਾਹੀਂ ਪ੍ਰਦਾਨ ਕਰਨੀਆਂ।
ਕਾਲ ਸਾਈਟ ਸਾਦਾ ਰਹਿੰਦੇ ਹਨ: ਤੁਸੀਂ ਜਨਰਿਕ ਕੋਡ ਲਿਖਦੇ ਹੋ, ਅਤੇ ਠੀਕ implementation ਉਹਨਾਂ ਨਿਰਧਾਰਿਤ scope ਵਿੱਚੋਂ ਚੁਣੀ ਜਾਂਦੀ ਹੈ।
ਸਹੂਲਤ ਦੀ ਹੀ ਉਲਟ ਨੁਕਸਾਨ ਇਹ ਹੈ: ਵਿਵਹਾਰ imports ਜੋੜਣ ਜਾਂ ਹਟਾਉਣ 'ਤੇ ਬਦਲ ਸਕਦਾ ਹੈ। ਇਹ "action at a distance" ਕੋਡ ਨੂੰ ਹੈਰਾਨ ਕਰਨ ਵਾਲਾ ਬਣਾ ਸਕਦਾ ਹੈ, ambiguous implicit errors ਪੈਦਾ ਕਰ ਸਕਦਾ ਹੈ, ਜਾਂ ਇੱਕ ਐਸਾ instance ਚੁਣ ਸਕਦਾ ਹੈ ਜਿਸਦੀ ਤੁਸੀਂ ਉਮੀਦ ਨਹੀਂ ਕਰਦੇ।
given/using)Scala 3 ਸ਼ਕਤੀ ਨੂੰ ਰੱਖਦਾ ਹੈ ਪਰ ਮਾਡਲ ਨੂੰ ਸਪਸ਼ਟ ਬਣਾਉਂਦਾ ਹੈ given instances ਅਤੇ using ਪੈਰਾਮੀਟਰਾਂ ਨਾਲ। ਇਨ੍ਹਾ syntax ਨਾਲ ਰੁਝਾਨ—"ਇਹ ਮੁੱਲ implicity ਪ੍ਰਦਾਨ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"—ਹੋਰ ਸਪਸ਼ਟ ਹੋ ਜਾਂਦਾ ਹੈ, ਜੋ ਕੋਡ ਨੂੰ ਪੜ੍ਹਨ, ਸਿਖਾਉਣ ਅਤੇ ਰਿਵਿਊ ਕਰਨ ਲਈ ਆਸਾਨ ਬਣਾਉਂਦਾ ਹੈ, ਫਿਰ ਵੀ type-class-ਚਾਲਿਤ ਡਿਜ਼ાઇન ਨੂੰ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ।
Concurrency ਉਹ ਜਗ੍ਹਾ ਹੈ ਜਿਥੇ Scala ਦਾ "FP + OO" ਮਿਲਾਪ ਇੱਕ ਅਮਲੀ ਫਾਇਦਾ ਦਿੰਦਾ ਹੈ। ਪੈਰਲਲ ਕੋਡ ਦੀ ਸਭ ਤੋਂ ਮੁਸ਼ਕਲ ਗੱਲ ਸਿਰਫ ਥ੍ਰੇਡ ਸ਼ੁਰੂ ਕਰਨਾ ਨਹੀਂ—ਇਹ ਇਹ ਸਮਝਣਾ ਹੈ ਕਿ ਕੀ ਬਦਲ ਸਕਦਾ ਹੈ, ਕਦੋਂ, ਅਤੇ ਕੌਣ ਦੂਜਾ ਉੱਸ ਨੂੰ ਵੇਖ ਸਕਦਾ ਹੈ।
Scala ਟੀਮਾਂ ਨੂੰ ਐਸੇ ਅੰਦਾਜ਼ ਵੱਲ ਧਕਦੀ ਹੈ ਜੋ ਇਸ ਤਰ੍ਹਾਂ ਦੀਆਂ ਹੈਰਾਨੀਆਂ ਨੂੰ ਘਟਾਉਂਦੇ ਹਨ।
Immutability ਮਹੱਤਵਪੂਰਨ ਹੈ ਕਿਉਂਕਿ ਸਾਂਝਾ mutable state ਇੱਕ ਕਲਾਸਿਕ race-condition ਦਾ ਸਰੋਤ ਹੁੰਦਾ ਹੈ: ਦੋ ਪ੍ਰੋਗ੍ਰਾਮ ਹਿੱਸੇ ਇੱਕੋ ਡੇਟਾ ਨੂੰ ਏਕੱਠੇ ਅਪਡੇਟ ਕਰਦੇ ਹਨ ਅਤੇ ਨਤੀਜੇ ਦੁਹਰਾਏ ਨਹੀਂ ਜਾ ਸਕਦੇ।
Scala ਦੀ immutable ਵਲ ਰੁਝਾਨ (ਅਕਸਰ case classes ਨਾਲ) ਇੱਕ ਸਧਾਰਨ ਨਿਯਮ ਨੂੰ ਉਤਸ਼ਾਹਿਤ ਕਰਦੀ ਹੈ: ਇੱਕ objects ਨੂੰ ਬਦਲਣ ਦੀ ਥਾਂ ਨਵਾਂ ਬਣਾਓ। ਇਹ ਪਹਿਲੇ ਵੇਲੇ "ਫਜ਼ੂਲ" ਵੇਖ ਸਕਦਾ ਹੈ, ਪਰ ਅਕਸਰ ਇਹ ਘੱਟ ਬੱਗ ਅਤੇ ਆਸਾਨ ਡੀਬੱਗਿੰਗ ਦੇ ਰੂਪ ਵਿੱਚ ਵਾਪਸ ਆਉਂਦਾ ਹੈ—ਖਾਸ ਕਰਕੇ ਲੋਡ ਹੇਠਾਂ।
Scala ਨੇ Future ਨੂੰ JVM 'ਤੇ mainstream ਅਤੇ ਦੌਲਤਮੰਦ ਟੂਲ ਬਣਾਇਆ। ਮੁੱਦਾ "ਹਮੇਸ਼ਾ callbacks" ਨਹੀਂ ਹੁੰਦਾ, ਪਰ ਕੰਪੋਜ਼ੀਸ਼ਨ ਹੈ: ਤੁਸੀਂ ਇੱਕੋ-ਸਮਾਂ 'ਤੇ ਕੰਮ ਸ਼ੁਰੂ ਕਰ ਸਕਦੇ ਹੋ ਅਤੇ ਫਿਰ ਨਤੀਜਿਆਂ ਨੂੰ readable ਤਰੀਕੇ ਨਾਲ ਜੋੜ ਸਕਦੇ ਹੋ।
map, flatMap, ਅਤੇ for-comprehensions ਨਾਲ async ਕੋਡ ਉਸੇ ਅੰਦਾਜ਼ ਵਿਚ ਲਿਖਿਆ ਜਾ ਸਕਦਾ ਹੈ ਜੋ ਸਧਾਰਨ ਕਦਮ-ਦਰ-ਕਦਮ ਲਾਜਿਕ ਵਰਗਾ ਲੱਗਦਾ ਹੈ। ਇਸ ਨਾਲ dependencies ਨੂੰ ਸਮਝਣਾ ਅਤੇ ਜਿੱਥੇ failures ਨੂੰ ਹੈਂਡਲ ਕਰਨਾ ਹੈ, ਫੈਸਲਾ ਕਰਨਾ ਆਸਾਨ ਹੁੰਦਾ ਹੈ।
Scala ਨੇ actor-ਸ਼ੈਲੀ ਵਿਚਾਰਾਂ ਨੂੰ ਵੀ ਲੋਕਪ੍ਰිය ਕੀਤਾ: ਇੱਕ ਕੰਪੋਨੈਂਟ ਅੰਦਰ ਸਟੇਟ ਨੂੰ ਅਲੱਗ ਰੱਖੋ, ਸੰਦೇಶਾਂ ਰਾਹੀਂ ਸੰਚਾਰ ਕਰੋ, ਅਤੇ ਥ੍ਰੇਡਾਂ ਵਿੱਚ objects ਸਾਂਝੇ ਨਾ ਕਰੋ। ਤੁਸੀਂ ਕੋਈ ਇੱਕ ਫਰੇਮਵਰਕ ਨਹੀਂ ਲੈਣਾ ਪੈਂਦਾ ਹੀ ਲਾਭ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ—message passing ਕੁਦਰਤੀ ਤੌਰ 'ਤੇ ਸੀਮਿਤ ਕਰਦਾ ਹੈ ਕਿ ਕੀ mutate ਹੋ ਸਕਦਾ ਹੈ ਅਤੇ ਕਿਸ ਦ੍ਵਾਰਾ।
ਇਹ ਪੈਟਰਨ ਅਪਣਾਉਣ ਵਾਲੀਆਂ ਟੀਮਾਂ ਅਕਸਰ ਵੇਖਦੀਆਂ ਹਨ ਕਿ ਸਟੇਟ ਦੀ ਮਲਕੀਅਤ ਵਧਦੀ, ਪੈਰਲਲਿਸਮ ਲਈ ਸੁਰੱਖਿਅਤ ਡਿਫ਼ਾਲਟ ਬਣਦੇ ਹਨ, ਅਤੇ ਕੋਡ ਰਿਵਿਊਜ਼ ਅਕਸਰ ਡੇਟਾ ਫਲੋ 'ਤੇ ਜ਼ਿਆਦਾ ਧਿਆਨ ਕਰਦੇ ਹਨ ਬਜਾਏ ਸਖਤ ਲਾਕਿੰਗ ਵਿਹਾਰ 'ਤੇ।
Scala ਦੀ JVM 'ਤੇ ਸਫਲਤਾ ਇੱਕ ਸਧਾਰਨ ਸ਼ਰਤ ਨਾਲ ਅਟੁੱਟ ਨਜ਼ਦੀਕੀ ਰਹੀ: "ਤੁਹਾਨੂੰ ਬਿਹਤਰ ਭਾਸ਼ਾ ਵਰਤਣ ਲਈ ਦੁਨੀਆ ਨੂੰ ਦੁਬਾਰਾ ਲਿਖਣਾ ਨਹੀਂ ਪਏਗਾ।"
"ਚੰਗੀ interop" ਸਿਰਫ਼ ਕਾਲਾਂ ਨਹੀਂ—ਇਹ ਬੋਰਿੰਗ, ਭਰੋਸੇਯੋਗ interop ਹੈ: ਪੇਸ਼ ਕੀਤੀ ਪ੍ਰਦਰਸ਼ਨ, ਜਾਣ-ਪਛਾਣ ਵਾਲੀ ਟੂਲਿੰਗ, ਅਤੇ Scala ਅਤੇ Java ਕੋਡ ਨੂੰ ਇਕੋ ਪ੍ਰੋਡਕਟ ਵਿੱਚ ਮਿਲਾ ਕੇ ਚਲਾਉਣ ਦੀ ਸਮਰਥਾ—ਬਿਨਾਂ ਮਹਾਨ ਯਾਤਰਾ ਵਾਲੀ ਮਾਈਗ੍ਰੇਸ਼ਨ ਦੇ।
Scala ਤੋਂ ਤੁਸੀਂ ਸਿੱਧਾ Java ਲਾਇਬ੍ਰੇਰੀਆਂ ਨੂੰ ਕਾਲ ਕਰ ਸਕਦੇ ਹੋ, Java interfaces ਨੂੰ ਲਾਗੂ ਕਰ ਸਕਦੇ ਹੋ, Java classes ਨੂੰ ਵਿਰਾਸਤ ਕਰ ਸਕਦੇ ਹੋ, ਅਤੇ ਸਧਾਰਨ JVM ਬਾਈਟਕੋਡ ਸ਼ਿਪ ਕਰ ਸਕਦੇ ਹੋ ਜੋ ਕਿਸੇ ਵੀ ਜਗ੍ਹਾ Java ਚੱਲਦੀ ਹੈ।
Java ਤੋਂ ਵੀ ਤੁਸੀਂ Scala ਕੋਡ ਕਾਲ ਕਰ ਸਕਦੇ ਹੋ—ਪਰ "ਚੰਗਾ" ਆਮ ਤੌਰ 'ਤੇ Java-ਮਿੱਤਰ ਐਨਟਰੀ ਪੁਆਇੰਟ ਪ੍ਰਦਾਨ ਕਰਨ ਦਾ ਮਤਲਬ ਹੈ: ਸਧਾਰਨ ਮੈਥਡ, ਘੱਟ ਜਨਰੇਰਿਕਸ ਹੇਠ-ਉਤਾਰ-ਚੜ੍ਹਾਅ, ਅਤੇ ਸਥਿਰ ਬਾਈਨਰੀ ਸਾਈਨਚਰ।
Scala ਲਾਇਬ੍ਰੇਰੀ ਲੇਖਕਾਂ ਨੂੰ ਪ੍ਰਾਯੋਗਿਕ "ਸਰਫੇਸ ਏਰੀਆ" ਰੱਖਣ ਲਈ ਪ੍ਰੇਰਿਤ ਕੀਤਾ: ਸਧਾਰਨ constructors/factories ਦਿਓ, ਮੁੱਖ workflow ਲਈ ਅਚਕੇ implicit ਲੋੜਾਂ ਨੂੰ ਤਿਆਗੋ, ਅਤੇ ਉਹ ਟਾਈਪਸ ਪ੍ਰਦਾਨ ਕਰੋ ਜੋ Java ਸਮਝ ਸਕੇ।
ਸਧਾਰਨ ਪੈਟਰਨ ਇੱਕ Scala-ਪਹਿਲਾ API ਦੇ ਨਾਲ ਇੱਕ ਛੋਟਾ Java facade ਪ੍ਰਦਾਨ ਕਰਨਾ ਹੈ (ਉਦਾਹਰਨ ਲਈ, Scala ਵਿੱਚ X.apply(...) ਅਤੇ Java ਲਈ X.create(...))। ਇਸ ਨਾਲ Scala ਨੂੰ ਐਕਸਪ੍ਰੈਸਿਵ ਰੱਖਿਆ ਜਾ ਸਕਦਾ ਹੈ ਬਿਨਾਂ Java ਕਾਲਰਾਂ ਨੂੰ ਸਜ਼ਾ ਦਿੱਤੇ।
Interop ਘਰਿਆਂ ਵਿੱਚ ਕਈ ਮੁੜ-ਮੁੜ ਆਉਂਦੀਆਂ ਚੀਜ਼ਾਂ ਹੁੰਦੀਆਂ ਹਨ:
null ਵਾਪਸ ਕਰਦੇ ਹਨ, ਜਦਕਿ Scala Option ਤਰਜੀਹ ਦਿੰਦੀ ਹੈ। ਹੱਦ ਬਣਾ ਕੇ ਕਿੱਥੇ ਬਦਲ ਕਰਨਾ ਹੈ, ਫੈਸਲਾ ਕਰੋ।ਹੱਦਾਂ ਨੂੰ ਸਪਸ਼ਟ ਰੱਖੋ: ਸੀਮਾ 'ਤੇ null ਨੂੰ Option ਵਿੱਚ ਬਦਲੋ, ਕਲੇਕਸ਼ਨ ਰੂਪান্তਰਨ ਨੂੰ ਕੇਂਦਰੀਕ੍ਰਿਤ ਕਰੋ, ਅਤੇ exception ਵਿਵਹਾਰ ਦਾ ਦਸਤਾਵੇਜ਼ ਰੱਖੋ।
ਜੇ ਤੁਸੀਂ ਮੌਜੂਦਾ ਉਤਪਾਦ ਵਿੱਚ Scala ਲਿਆਉਣ ਜਾ ਰਹੇ ਹੋ ਤਾਂ ਪੱਤੇ ਮਾਡਿਊਲਾਂ (utilities, data transforms) ਨਾਲ ਸ਼ੁਰੂ ਕਰੋ ਅਤੇ ਫਿਰ ਅੰਦਰ ਵਧੋ। ਸੰਦੇਹ ਹੋਵੇ ਤਾਂ ਚੰਕਚੇਤੀ ਦੇ ਬਦਲੇ ਸਾਫ਼ਤਾ ਨੂੰ ਤਰਜੀਹ ਦਿਓ—interop ਉਹ ਜਗ੍ਹਾ ਹੈ ਜਿੱਥੇ "ਸਰਲ" ਹਰ ਰੋਜ਼ ਲਾਭ ਦਿੰਦਾ ਹੈ।
Scala ਨੂੰ ਉਦਯੋਗ ਵਿੱਚ ਅਸਲ ਪਾਸਾ ਮਿਲਿਆ ਕਿਉਂਕਿ ਇਹ ਟੀਮਾਂ ਨੂੰ ਸੰਕੁਚਿਤ ਕੋਡ ਲਿਖਣ ਦਿੰਦੀ ਸੀ ਬਿਨਾਂ ਮਜ਼ਬੂਤ ਟਾਈਪ ਸਿਸਟਮ ਦੀਆਂ ਸੁਰੱਖਿਅਤੀਆਂ ਨੂੰ ਛੱਡੇ। ਅਮਲੀ ਤੌਰ 'ਤੇ ਇਹ ਮਤਲਬ ਸੀ ਘੱਟ "stringly-typed" APIs, ਸਾਫ਼ ਡੋਮੇਨ ਮਾਡਲ, ਅਤੇ ਰਿਫੈਕਟਰ ਜਿਨਾਂ ਨੂੰ ਕਰਨਾ ਘੱਟ ਡਰਾਵਣਾ ਮਹਿਸੂਸ ਹੁੰਦਾ।
ਡੇਟਾ ਕੰਮ ਤਬਦੀਲੀਆਂ ਨਾਲ ਭਰਿਆ ਹੁੰਦਾ ਹੈ: parse, clean, enrich, aggregate, join। Scala ਦੀ ਫੰਕਸ਼ਨਲ ਸ਼ੈਲੀ ਇਹ ਸਟੈਪਾਂ ਨੂੰ ਪੜ੍ਹਨਯੋਗ ਬਣਾਉਂਦੀ ਹੈ ਕਿਉਂਕਿ ਕੋਡ ਪਾਈਪਲਾਈਨ ਨੂੰ ਅਕਸਰ ਦਰਸਾ ਸਕਦਾ ਹੈ—map, filter, flatMap, fold ਦੀ ਲੜੀ ਜੋ ਡੇਟਾ ਨੂੰ ਇੱਕ ਆਕਾਰ ਤੋਂ ਦੂਜੇ ਆਕਾਰ ਤੱਕ ਲਿਜਾਂਦੀ ਹੈ।
ਅਤਿਰਿਕਤ ਲਾਭ ਇਹ ਹੈ ਕਿ ਇਹ ਤਬਦੀਲੀਆਂ ਸਿਰਫ਼ ਛੋਟੀਆਂ ਨਹੀਂ ਹਨ; ਉਹ ਚੈਕ ਕੀਤੀਆਂ ਹੋਈਆਂ ਹੁੰਦੀਆਂ ਹਨ। Case classes, sealed hierarchies, ਅਤੇ pattern matching ਟੀਮਾਂ ਨੂੰ "ਰਿਕਾਰਡ ਕੀ ਹੋ ਸਕਦਾ ਹੈ" ਨੂੰ ਕੋਡ ਵਿੱਚ ਐਨਕੋਡ ਕਰਨ ਵਿੱਚ ਮਦਦ ਕਰਦੀਆਂ ਹਨ ਅਤੇ ਏਜ ਕੇਸਾਂ ਨੂੰ ਹੈਂਡਲ ਕਰਨ ਲਈ ਬਲਦੀਆਂ ਹਨ।
Scala ਨੂੰ ਸਭ ਤੋਂ ਵੱਡੀ ਦਿੱਖ Apache Spark ਤੋਂ ਮਿਲੀ, ਜਿਸਦੀ ਕੋਰ APIs ਮੁਲਤ: Scala ਵਿੱਚ ਡਿਜ਼ਾਇਨ ਕੀਤੀਆਂ ਗਈਆਂ ਸਨ। ਬਹੁਤ ਸਾਰੀਆਂ ਟੀਮਾਂ ਲਈ Scala Spark ਜੌਬਜ਼ ਨੂੰ ਪ੍ਰਕ੍ਰਿਤਿਕ ਤਰੀਕੇ ਨਾਲ ਦਰਸਾਉਂਦਾ ਸੀ, ਖਾਸ ਕਰਕੇ ਜਦੋਂ ਉਹ typed datasets, ਨਵੇਂ APIs ਪਹਿਲਾਂ ਪਹੁੰਚਾਉਣ, ਜਾਂ Spark ਦੀਆਂ ਅੰਦਰੂਨੀ ਚੀਜ਼ਾਂ ਨਾਲ ਸਹਿਯੋਗ ਲੈਣ ਚਾਹੁੰਦੇ ਸਨ।
ਹਾਲਾਂਕਿ ਇਹ ਇੱਕੋ ਇਕ ਵਿਕਲਪ ਨਹੀਂ ਹੈ—ਕਈ ਸੰਸਥਾਵਾਂ Spark ਨੂੰ ਮੁੱਖ ਤੌਰ 'ਤੇ Python ਰਾਹੀਂ ਚਲਾਉਂਦੀਆਂ ਹਨ, ਤੇ ਕੁਝ Java ਲਈ ਪਕੜ ਬਣਾਉਂਦੀਆਂ ਹਨ। Scala ਆਮ ਤੌਰ 'ਤੇ ਉਹ ਥਾਂ ਆਉਂਦੀ ਹੈ ਜਿੱਥੇ ਟੀਮਾਂ ਜ਼ਿਆਦਾ ਐਕਸਪ੍ਰੈਸਿਵਿਟੀ ਚਾਹੁੰਦੇ ਹਨ ਜਿਵੇਂ Java ਨਾਲੋਂ, ਅਤੇ ਡਾਇਨਾਮਿਕ ਸਕ੍ਰਿਪਟਿੰਗ ਨਾਲੋਂ ਜ਼ਿਆਦਾ compile-time ਗਰੰਟੀ ਚਾਹੁੰਦੇ ਹਨ।
Scala ਸਰਵਿਸਜ਼ ਅਤੇ ਜੌਬ JVM 'ਤੇ ਚੱਲਦੇ ਹਨ, ਜੋ ਉਨ੍ਹਾਂ ਦੇ ਡਿਪਲੋਇਮੈਂਟ ਨੂੰ ਉਹਨਾਂ ਮਾਹੌਲਾਂ ਵਿੱਚ ਸਹਿਜ ਬਣਾਉਂਦਾ ਹੈ ਜੇਹੜੇ ਪਹਿਲਾਂ ਤੋਂ Java 'ਤੇ ਆਧਾਰਤ ਹਨ।
ਤਰਜੀਹ ਇਹ ਹੈ कि ਬਿਲਡ ਜਾਂਕਟਪਲੈਕਸਿਟੀ: SBT ਅਤੇ ਡਿਪੈਂਡੈਂਸੀ ਰੀਜ਼ੋਲਿਊਸ਼ਨ ਅਣਜਾਣ ਹੋ ਸਕਦੇ ਹਨ, ਅਤੇ ਵਰਜਨ-ਵਾਰ ਬਾਈਨਰੀ ਕੌਂਪੇਟਿਬਿਲਿਟੀ ਧਿਆਨ ਦੀ ਮੰਗ ਕਰਦੀ ਹੈ।
ਟੀਮ ਦੇ ਦਕ੍ਸ਼ਤਾ ਮਿਕਸ ਦਾ ਭੀ ਮਹਤਵ ਹੈ। Scala ਉਸ ਵੇਲੇ ਚਮਕਦੀ ਹੈ ਜਦੋਂ ਕੁਝ ਵਿਕਾਸਕਾਰ ਨਿਯਮ (ਟੈਸਟਿੰਗ, 스타일, FP vs OO 컨벤ਸ਼ਨਾਂ) ਨਿਰਧਾਰਿਤ ਕਰ ਸਕਣ ਅਤੇ ਹੋਰਾਂ ਨੂੰ ਮੈਨਟਰ ਕਰ ਸਕਣ। ਇਸ ਤੋਂ ਬਿਨਾਂ, ਕੋਡਬੇਸ "ਕਲੀਵਰ" ਅਬਸਟ੍ਰੈਕਸ਼ਨਾਂ ਵਿੱਚ ਡਿੱਗ ਸਕਦਾ ਹੈ ਜੋ ਲੰਬੇ ਸਮੇਂ ਵਾਲੇ ਸਰਵਿਸਜ਼ ਅਤੇ ਡੇਟਾ ਪਾਈਪਲਾਈਨਾਂ ਵਿੱਚ ਰੱਖ-ਰਖਾਅ ਮੁਸ਼ਕਲ ਕਰ ਦਿੰਦੇ ਹਨ।
Scala 3 ਨੂੰ ਬਿਹਤਰ ਤੌਰ 'ਤੇ "ਸਾਫ਼-ਸੁਥਰਾ ਅਤੇ ਸਮਝਦੇਯੋਗ" ਰਿਲੀਜ਼ ਸਮਝਣਾ ਚਾਹੀਦਾ ਹੈ—ਇਹ ਕੋਈ ਪੁਨਰ-ਅਵਿਸ਼ਕਲਪ ਨਹੀਂ, ਬਲਕਿ ਰੋਜ਼ਾਨਾ ਕੋਡ ਨੂੰ ਪੜ੍ਹਨਯੋਗ, ਸਿਖਾਉਣਯੋਗ, ਅਤੇ ਰੱਖ-ਰੱਖਾਉ ਯੋਗ ਬਣਾਉਣ ਦਾ ਯਤਨ ਹੈ।
Scala 3 Dotty ਕੰਪਾਇਲਰ ਪ੍ਰੋਜੈਕਟ ਤੋਂ ਉਭਰਿਆ। ਇਹ ਮਤਲਬ ਰੱਖਦਾ ਹੈ: ਜਦੋਂ ਨਵਾਂ ਕੰਪਾਇਲਰ ਉਹਨਾਂ ਤਰੀਕਿਆਂ ਅਤੇ ਪ੍ਰੋਗ੍ਰਾਮ ਰਚਨਾ ਦੇ ਮਾਡਲ ਨਾਲ ਸਭਿਆਚਾਰਕ ਤੌਰ 'ਤੇ ਬਣਾਇਆ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਇਹ ਭਾਸ਼ਾ ਨੂੰ ਸਪਸ਼ਟ ਨਿਯਮਾਂ ਅਤੇ ਘੱਟ ਖਾਸ ਕੇਸਾਂ ਵੱਲ ਧੱਕਦਾ ਹੈ।
Dotty ਸਿਰਫ਼ "ਤੇਜ਼ ਕੰਪਾਇਲਰ" ਨਹੀਂ ਸੀ—ਇਹ ਇੱਕ ਮੌਕਾ ਸੀ ਕਿ Scala ਫੀਚਰਾਂ ਹੋਰ ਬਿਹਤਰ ਢੰਗ ਨਾਲ ਮਿਲਣ ਅਤੇ ਸੁਧਾਰੇ ਹੋਏ ਐਰਰ ਸੁਨੇਹੇ ਅਤੇ ਟੂਲਿੰਗ ਜੀ ਨੂੰ ਅਸਲ ਕੋਡ ਬਾਰੇ ਬੇਹਤਰ ਜਾਣਕਾਰੀ ਦੇਣ ਲਈ ਅਨੁਕੂਲ ਕੀਤਾ ਜਾਵੇ।
ਕੁਝ ਹੇਡਲਾਈਨ ਤਬਦੀਲੀਆਂ:
given / using ਨੇ ਬਹੁਤ ਹੱਦ ਤੱਕ implicit ਦੀ ਥਾਂ ਲੀ, ਜਿਸ ਨਾਲ type class ਵਰਤੋਂ ਅਤੇ dependency-like patterns ਹੋਰ ਸਪਸ਼ਟ ਹੋਏ।ਟੀਮਾਂ ਲਈ ਪ੍ਰਯੋਗਿਕ ਪ੍ਰਸ਼ਨ ਹੁੰਦਾ ਹੈ: "ਕੀ ਅਸੀਂ ਰੁਕਿਆ ਬਿਨਾਂ ਅਪਗਰੇਡ ਕਰ ਸਕਦੇ ਹਾਂ?" Scala 3 ਨੂੰ ਇਸ ਗੱਲ ਦਿਖਾ ਕੇ ਡਿਜ਼ਾਇਨ ਕੀਤਾ ਗਿਆ।
ਇਨਕਰਨਟਲ ਅਪਨਾਉਣ ਅਤੇ ਕ੍ਰਾਸ-ਬਿਲਡਿੰਗ ਸਾਹਮਣੇ ਰਿਹਾ ਹੈ। ਅਮਲੀ ਤੌਰ 'ਤੇ, ਮਾਈਗ੍ਰੇਸ਼ਨ ਵੱਡੇ ਕਾਰੋਬਾਰੀ ਲਾਜਿਕ ਨੂੰ ਦੁਬਾਰਾ ਲਿਖਣ ਬਾਰੇ ਨਹੀਂ ਹੁੰਦੀ; ਇਹ ਵੱਧਤਰੀਨ ਤੌਰ 'ਤੇ edge cases ਨੂੰ ਠੀਕ ਕਰਨ, macros-ਭਾਰੀ ਕੋਡ, implicit-ਭਰਪੂਰ ਚੇਨ, ਅਤੇ ਬਿਲਡ/ਪਲੱਗਿਨ ਨੂੰ ਅਨੁਕੂਲ ਬਣਾਉਣ ਬਾਰੇ ਹੁੰਦੀ ਹੈ।
ਇਸ ਦਾ ਨਤੀਜਾ ਇੱਕ ਐਸੀ ਭਾਸ਼ਾ ਹੈ ਜੋ JVM 'ਤੇ ਫ਼ਿਕਸ ਰਹਿੰਦੀ ਹੈ, ਪਰ ਰੋਜ਼ਾਨਾ ਵਰਤੋਂ ਵਿੱਚ ਹੋਰ ਸੰਗਠਿਤ ਤੇ ਸਮਝਣਯੋਗ ਮਹਿਸੂਸ ਹੁੰਦੀ ਹੈ।
Scala ਦਾ ਸਭ ਤੋਂ ਵੱਡਾ ਪ੍ਰਭਾਵ ਕੋਈ ਇੱਕ ਫੀਚਰ ਨਹੀਂ—ਇਹ ਇਹ ਸਬੂਤ ਹੈ ਕਿ ਤੁਸੀਂ ਇੱਕ ਮੈਜਰ ਇਕੋਸਿਸਟਮ ਨੂੰ ਅੱਗੇ ਵਧਾ ਸਕਦੇ ਹੋ ਬਿਨਾਂ ਉਸ ਚੀਜ਼ ਨੂੰ ਛੱਡਣ ਦੇ ਜੋ ਉਸਨੂੰ ਪ੍ਰਯੋਗਿਕ ਬਣਾਉਂਦਾ ਸੀ।
JVM 'ਤੇ functional programming ਅਤੇ object-oriented programming ਨੂੰ ਮਿਲਾ ਕੇ Scala ਨੇ ਦਿਖਾਇਆ ਕਿ ਭਾਸ਼ਾ ਡਿਜ਼ਾਇਨ ਮਹੱਤਵਕਾਂਕਸ਼ੀ ਹੋ ਸਕਦੀ ਹੈ ਅਤੇ ਫਿਰ ਵੀ ਸ਼ਿਪ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ।
Scala ਕੁਝ ਟਿਕਾਊ ਵਿਚਾਰਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰਦੀ ਹੈ:
Scala ਨੇ ਇਹ ਵੀ ਸਿੱਖਾਇਆ ਕਿ ਸ਼ਕਤੀ ਦੋ ਸਮੇਂ ਕੱਟ ਸਕਦੀ ਹੈ।
ਜਦੋਂ ਕੋਈ ਇੰਟਰਫੇਸ ਨਾਜ਼ੁਕ implicit conversions ਜਾਂ ਹੇਠ-ਹੇਠ stacked abstractions 'ਤੇ ਨਿਰਭਰ ਹੁੰਦਾ ਹੈ, ਉਪਭੋਗਤਾ ਅਣਉਮੀਦਿਤ ਤਰੀਕੇ ਨਾਲ ਹੈਰਾਨ ਹੋ ਸਕਦੇ ਹਨ। ਜੇ ਕੋਈ API implicit ਮਸ਼ੀਨਰੀ ਦੀ ਲੋੜ ਰੱਖਦਾ ਹੈ, ਤਾਂ ਇਹ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ:
ਪੜ੍ਹਨਯੋਗ ਕਾਲਸਾਈਟ ਅਤੇ ਪੜ੍ਹਨਯੋਗ ਕੰਪਾਇਲਰ ਐਰਰ ਅਕਸਰ ਲੰਬੀ ਮਿਆਦ ਦੀ ਦੇਖਭਾਲ ਨੂੰ ਉਹਨਾਂ ਫਲਕਾਂ ਨਾਲੋਂ ਵਧੀਆ ਬਣਾਉਂਦੇ ਹਨ ਜੋ ਸਿਰਫ਼ ਥੋੜ੍ਹੀ ਵੱਧ ਫਲੈਕਸਬਿਲਿਟੀ ਦਿੰਦੇ ਹਨ।
ਉਹ Scala ਟੀਮਾਂ ਜੋ ਚਮਕਦੀਆਂ ਹਨ ਆਮ ਤੌਰ 'ਤੇ consistency 'ਚ ਨਿਵੇਸ਼ ਕਰਦੀਆਂ ਹਨ: ਇਕ style guide, FP vs OO ਬਾਊਂਡਰੀਆਂ ਲਈ ਸਾਫ਼ "ਹਾਊਸ ਸਟਾਈਲ", ਅਤੇ ਸੇਮੀਨੀ ਜਿਹੀਆਂ ਟ੍ਰੇਨਿੰਗ ਜੋ ਕੇਵਲ ਕੀ ਪੈਟਰਨ ਹਨ ਉਹ ਨਹੀਂ ਦਿਖਾਉਂਦੀਆਂ, ਪਰ ਕਦੋਂ ਉਨ੍ਹਾਂ ਨੂੰ ਵਰਤਣਾ ਚਾਹੀਦਾ ਹੈ ਇਹ ਵੀ ਸਿੱਖਾਉਂਦੀਆਂ ਹਨ।Convention-ਜ਼ਿੰਦਗੀ ਕੋਡਬੇਸ ਨੂੰ ਇਸ ਗੱਲ ਤੋਂ ਬਚਾਉਂਦੀ ਹੈ ਕਿ ਉਹ incompatible mini-paradigms ਦੇ ਇੱਕ ਮਿਕਸ ਵਿੱਚ ਬਦਲ ਜਾਵੇ।
ਇੱਕ ਸੰਬੰਧਤ ਆਧੁਨਿਕ ਸਬਕ ਇਹ ਹੈ ਕਿ ਮਾਡਲਿੰਗ ਅਨੁਸ਼ਾਸਨ ਅਤੇ ਡਿਲਿਵਰੀ ਗਤੀ ਇਕ-ਦੂਜੇ ਨਾਲ ਟੱਕਰ ਨਹੀਂ ਖਾਣੇ ਚਾਹੀਦੇ। Koder.ai (ਇੱਕ vibe-coding ਪਲੇਟਫਾਰਮ ਜੋ ਸਟ੍ਰਕਚਰਡ ਚੈਟ ਤੋਂ ਅਸਲ ਵੈੱਬ, ਬੈਕਐਂਡ, ਅਤੇ ਮੋਬਾਈਲ ਐਪਲਿਕੇਸ਼ਨ ਜਨਰੇਟ ਕਰਦਾ ਹੈ, ਸਰੋਤ ਐਕਸਪੋਰਟ, ਡਿਪਲੋਇਮੈਂਟ, ਅਤੇ ਰੋਲਬੈਕ/ਸਨੇਪਸ਼ਾਟ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ) ਵਰਗੇ ਟੂਲ ਟੀਮਾਂ ਨੂੰ ਤੇਜ਼ੀ ਨਾਲ ਪ੍ਰੋਟੋਟਾਈਪ ਬਣਾਉਣ ਵਿੱਚ ਮਦਦ ਕਰ ਸਕਦੇ ਹਨ—ਫਿਰ ਵੀ Scala-ਪ੍ਰੇਰਿਤ ਸਿਧਾਂਤਾਂ ਵਰਗੇ ਸਪਸ਼ਟ ਡੋਮੇਨ ਮਾਡਲਿੰਗ, immutable ਡਾਟਾ ਸਟ੍ਰਕਚਰ, ਅਤੇ ਸਪਸ਼ਟ ਐਰਰ ਸਟੇਟ ਲਾਗੂ ਕਰਨ। ਚੰਗੇ ਢੰਗ ਨਾਲ ਵਰਤੇ ਜਾਣ 'ਤੇ, ਇਹ ਮਿਲਾਪ ਪ੍ਰਯੋਗਸ਼ੀਲਤਾ ਤੇਜ਼ ਰੱਖਦਾ ਹੈ ਬਿਨਾਂ ਆਰਕੀਟੈਕਚਰ ਨੂੰ "stringly-typed" ਹਾਲਤ 'ਚ ਛੱਡੇ।
Scala ਦਾ ਪ੍ਰਭਾਵ ਹੁਣ JVM ਭਾਸ਼ਾਵਾਂ ਅਤੇ ਲਾਇਬ੍ਰੇਰੀਆਂ ਵਿੱਚ ਦਿੱਖਦਾ ਹੈ: ਵਧੇਰੇ ਟਾਈਪ-ਚਾਲਿਤ ਡਿਜ਼ਾਇਨ, ਬਿਹਤਰ ਮਾਡਲਿੰਗ, ਅਤੇ ਰੋਜ਼ਾਨਾ ਇੰਜੀਨੀਅਰਿੰਗ ਵਿੱਚ ਵੱਧ ਫੰਕਸ਼ਨਲ ਪੈਟਰਨ। ਅੱਜ Scala ਸਭ ਤੋਂ ਵਧੀਆ ਉਸਥਾਂ ‘ਫਿੱਟ’ ਹੁੰਦੀ ਹੈ ਜਿੱਥੇ ਤੁਸੀਂ JVM 'ਤੇ ਐਕਸਪ੍ਰੈਸਿਵ ਮਾਡਲਿੰਗ ਅਤੇ ਪ੍ਰਦਰਸ਼ਨ ਚਾਹੁੰਦੇ ਹੋ—ਪਰ ਇਸ ਦੀ ਤਾਕਤ ਨੂੰ ਸਮਝਦਾਰੀ ਨਾਲ ਵਰਤਣ ਲਈ ਅਨੁਸ਼ਾਸਨ ਦੀ ਲੋੜ ਵੀ ਸੱਚੀ ਹੈ।
Scala ਅਜੇ ਵੀ ਮਹੱਤਵਪੂਰਨ ਹੈ ਕਿਉਂਕਿ ਇਸ ਨੇ ਦਰਸਾਇਆ ਕਿ ਇੱਕ JVM ਭਾਸ਼ਾ ਫੰਕਸ਼ਨਲ ਪ੍ਰੋਗ੍ਰਾਮਿੰਗ ਦੀ ਸੁਗਮਤਾ (immutability, higher-order functions, composability) ਅਤੇ ਆਬਜੈਕਟ-ਓਰੀਐਂਟਡ ਇੰਟੇਗ੍ਰੇਸ਼ਨ (classes, interfaces, ਜਾਣੀ-ਪਛਾਣ ਵਾਲਾ ਰਨਟਾਈਮ ਮਾਡਲ) ਦੋਹਾਂ ਨੂੰ ਇੱਕਠੇ ਕਰ ਸਕਦੀ ਹੈ ਅਤੇ ਪ੍ਰੋਡਕਸ਼ਨ ਸਕੇਲ 'ਤੇ ਕੰਮ ਕਰ ਸਕਦੀ ਹੈ।
ਜੇਕਰ ਤੁਸੀਂ ਅੱਜ Scala ਨਹੀਂ ਲਿਖਦੇ, ਫਿਰ ਵੀ ਇਸ ਦੀ ਸਫਲਤਾ ਨੇ ਉਹਨਾਂ ਪੈਟਰਨਾਂ ਨੂੰ ਸਧਾਰਨ ਬਣਾਇਆ ਜੋ ਅੱਜ ਅਨੇਕ JVM ਟੀਮਾਂ ਲਈ ਆਮ ਹਨ: ਸਪਸ਼ਟ ਡੋਮੇਨ ਮਾਡਲਿੰਗ, ਸੁਰੱਖਿਅਤ ਐਰਰ ਹੈਂਡਲਿੰਗ, ਅਤੇ ਐਸੇ ਲਾਇਬ੍ਰੇਰੀ ਏਪੀਆਈ ਜੋ ਸਹੀ ਵਰਤੋਂ ਵੱਲ ਪ੍ਰੇਰਿਤ ਕਰਦੀਆਂ ਹਨ।
ਉਨ੍ਹਾਂ ਦਾ ਪ੍ਰਭਾਵ "Scala ਬਣਾਉਣ" ਤੋਂ ਆਗੇ ਵੀ ਵਿਆਪਕ ਹੈ: Martin Odersky ਨੇ ਇੱਕ ਪ੍ਰਗਟਿਕ ਪਲੇਨਬੱਕ ਸਾਬਤ ਕੀਤਾ—ਜਿਆਦਾ ਐਕਸਪ੍ਰੈਸਿਵਿਟੀ ਅਤੇ ਟਾਈਪ-ਸੇਫਟੀ ਅੱਗੇ ਵਧਾਈ ਜਾ ਸਕਦੀ ਹੈ ਬਿਨਾਂ Java ਇੰਟਰਓਪਰੇਬਿਲਟੀ ਛੱਡੇ।
ਅਮਲੀ ਤੌਰ 'ਤੇ ਇਹ ਮਤਲਬ ਹੈ ਕਿ ਟੀਮਾਂ FP-ਸ਼ੈਲੀ ਵਿਚਾਰ (immutable ਡੇਟਾ, typed ਮਾਡਲਿੰਗ, composition) ਅਪਣਾ ਸਕਦੀਆਂ ਹਨ ਜਦੋਂ ਕਿ ਉਹ ਮੌਜੂਦਾ JVM ਟੂਲਿੰਗ, ਡਿਪਲੋਇਮੈਂਟ ਅਭਿਆਸ ਅਤੇ Java ਇਕੋਸਿਸਟਮ ਦਾ ਫਾਇਦਾ ਲੈ ਰਹੀਆਂ ਹਨ—ਇਸ ਨਾਲ "ਸਭ ਕੁਝ ਦੁਬਾਰਾ ਲਿਖਣ" ਵਾਲੀ ਰੁਕਾਵਟ ਘਟਦੀ ਹੈ ਜੋ ਨਵੀਆਂ ਭਾਸ਼ਾਵਾਂ ਨੂੰ ਅਪਣਾਉਣ ਵਿੱਚ ਰੁਕਾਵਟ ਪੈਦਾ ਕਰਦੀ ਹੈ।
Scala ਦਾ “blend” ਸਧਾਰਨ ਸ਼ਬਦਾਂ ਵਿੱਚ ਇਹ ਹੈ ਕਿ ਤੁਸੀਂ ਵਰਤ ਸਕਦੇ ਹੋ:
ਮਕਸਦ ਇਹ ਨਹੀਂ ਕਿ ਹਰ ਥਾਂ FP ਲਗਾਇਆ ਜਾਵੇ—ਇਸਦਾ ਮਕਸਦ ਇਹ ਹੈ ਕਿ ਟੀਮ ਇੱਕੋ ਭਾਸ਼ਾ ਅਤੇ ਰਨਟਾਈਮ ਵਿੱਚ ਰਹਿੰਦਿਆਂ ਵੀ ਹਰ ਮੋਡ ਲਈ ਸਭ ਤੋਂ ਉਚਿਤ ਅੰਦਾਜ਼ ਚੁਣ ਸਕੇ।
Scala ਨੂੰ JVM ਬਾਈਟ ਕੋਡ ਤੇ ਕੰਪਾਇਲ ਹੋਣਾ, ਏਂਟਰਪ੍ਰਾਈਜ਼ ਪ੍ਰਦਰਸ਼ਨ ਉਮੀਦਾਂ ਨੂੰ ਪੂਰਾ ਕਰਨਾ ਅਤੇ Java ਲਾਇਬ੍ਰੇਰੀਆਂ/ਟੂਲਿੰਗ ਨਾਲ ਇੰਟਰਓਪਰੇਬਿਲਟੀ ਰੱਖਣੀ ਪਈ—ਇਹ ਸਭ ਉਸ ਸਮੇਂ ਦੇ ਬਾਹਰੀ ਰੁਕਾਵਟ ਸਨ।
ਇਨ੍ਹਾਂ ਸੀਮਾਵਾਂ ਨੇ ਭਾਸ਼ਾ ਨੂੰ ਪ੍ਰਗਟਿਕ ਬਣਾਇਆ: ਫੀਚਰਾਂ ਨੂੰ ਰਨਟਾਈਮ ਨਾਲ ਸਧਾਰਨ ਤਰੀਕੇ ਨਾਲ ਮੇਪ ਹੋਣਾ ਚਾਹੀਦਾ ਸੀ, ਅਚਾਨਕ ਆਪਰੇਸ਼ਨ ਨਾ ਹੋਣੇ ਚਾਹੀਦੇ, ਅਤੇ ਅਸਲ-ਦੁਨੀਆ ਬਿਲਡ/IDE/ਡਿਬੱਗਿੰਗ/ਡਿਪਲੋਇਮੈਂਟ ਸਥਾਪਨਾ ਨੂੰ ਸਹਿਯੋਗ ਮਿਲਣਾ ਚਾਹੀਦਾ ਸੀ—ਇੰਨੀ ਮੁਹੱਈਆ ਹੋਏ ਬਿਨਾਂ ਅਡਾਪਸ਼ਨ ਰੁਕੀ ਰਹਿੰਦੀ।
Traits ਇੱਕ ਪ੍ਰੈਂਗਟੀਕ ਜਵਾਬ ਹਨ ਜਦੋਂ ਤੁਸੀਂ ਚਾਹੁੰਦੇ ਹੋ ਕਿ ਵਹ-ਵਹ ਰਿਹੈਵੇਅਰ ਦੁਬਾਰਾ ਵਰਤੀ ਜਾਵੇ ਬਿਨਾਂ ਇੱਕ ਭਰੋਸੇਯੋਗ inheritance ਦਰਖ਼ਤ ਬਣਾਏ।
ਅਮਲੀ ਤੌਰ 'ਤੇ ਉਹ ਵਰਕ ਆਉਂਦੇ ਹਨ:
ਇਹ composition-first OO ਲਈ ਇੱਕ ਸੰਦ ਹੈ ਜੋ functional ਹੇਲਪਰ ਮੇਥਡਸ ਨਾਲ ਚੰਗੀ ਤਰ੍ਹਾਂ ਜੋੜਦਾ ਹੈ।
Case classes ਡੇਟਾ-ਪਹਿਲੇ ਟਾਈਪ ਹਨ ਜਿਨ੍ਹਾਂ ਦੇ ਕੁਝ ਲਾਭਨਿਰਪੱਖ ਡਿਫਾਲਟ ਹੁੰਦਿਆਂ ਹਨ: ਵੈਲਿਊ-ਬੇਸਡ ਬਰਾਬਰੀ, ਆਸਾਨ ਨਿਰਮਾਣ, ਅਤੇ ਪੜ੍ਹਨਯੋਗ ਪ੍ਰਤিনিধਿਤਾ।
ਉਹ ਖ਼ਾਸ ਤੌਰ 'ਤੇ ਵਰਤੇ ਜਾਣ ਲਈ ਚੰਗੇ ਹਨ ਜਦੋਂ ਤੁਸੀਂ:
ਉਹ pattern matching ਨਾਲ ਸੋਹਣੇ ਤਰੀਕੇ ਨਾਲ ਕੰਮ ਕਰਦੇ ਹਨ, ਜੋ ਹਰ ਡੇਟਾ ਆਕਾਰ ਨੂੰ ਸਪਸ਼ਟ ਤਰੀਕੇ ਨਾਲ ਹੈਂਡਲ ਕਰਨ ਨੂੰ ਉਤਸ਼ਾਹ ਦਿੰਦਾ ਹੈ।
Pattern matching ਉਹ ਢੰਗ ਹੈ ਜੋ ਡੇਟਾ ਦੇ ਆਕਾਰ ਦੇ ਆਧਾਰ 'ਤੇ ਬ੍ਰਾਂਚਿੰਗ ਲਿਖਦਾ ਹੈ—ਸਿਰਫ਼ ਬੂਲੀਅਨ ਜਾਂ ਵਿਖਰੇ ਹੋਏ if/else ਚੈਨਾਂ ਦੀ ਥਾਂ।
ਜਦੋਂ sealed traits (ਬੰਦ ਵਰਾਓਂ ਦੀ ਇਜਾਜ਼ਤ ਦੇਣ ਵਾਲੇ) ਨਾਲ ਮਿਲਦਾ ਹੈ ਤਾਂ ਇਹ ਵਧੇਰੇ ਭਰੋਸੇਯੋਗ ਰੀਫੈਕਟਰਿੰਗ ਯੋਗ ਬਣਾਉਂਦਾ:
ਇਸ ਨਾਲ "ਭੁੱਲ ਗਈ ਘਟਨਾ" ਵਾਲੀਆਂ ਗਲਤੀਆਂ ਘਟਦੀਆਂ ਹਨ, ਭਾਵੇਂ ਲਾਡ਼ੀਕ ਲੋਜਿਕ अभी ਵੀ ਗਲਤ ਹੋ ਸਕਦੀ ਹੈ।
ਟਾਈਪ ਇਨਫਰੈਂਸ ਬਹੁਤ ਸਾਰਾ ਬੋਇਲਰਪਲੇਟ ਘਟਾਉਂਦੀ ਹੈ, ਪਰ ਮਹੱਤਵਪੂਰਨ ਬਾਊਂਡਰੀਆਂ 'ਤੇ ਐਨੋਟੇਸ਼ਨ ਰੱਖਣ ਨਾਲ ਟੀਮ ਲਈ ਪੜ੍ਹਨ ਅਤੇ ਡਿਬੱਗ ਕਰਨ ਵਿੱਚ ਆਸਾਨੀ ਹੁੰਦੀ ਹੈ।
ਏਕ ਆਮ ਗਾਈਡਲਾਈਨ:
ਇਸ ਨਾਲ ਕੋਡ ਮਨੁੱਖਾਂ ਲਈ ਪੜ੍ਹਨਯੋਗ ਰਹਿੰਦਾ ਹੈ ਅਤੇ ਟਾਈਪਸ ਇੱਕ ਤਰ੍ਹਾਂ ਦਾ ਡੌਕਿਊਮੈਂਟੇਸ਼ਨ ਬਣ ਜਾਂਦੇ ਹਨ।
Implicits ਕੰਪਾਇਲਰ ਨੂੰ ਉਹ ਆਰਗੂਮੈਂਟ ਮੁਹੱਈਆ ਕਰਵਾਉਂਦੇ ਹਨ ਜੋ ਤੁਸੀਂ ਸਪਸ਼ਟ ਤੌਰ 'ਤੇ ਨਹੀਂ ਦਿੱਤੇ—ਇਸ ਨਾਲ extension methods ਅਤੇ type-class-ਅਧਾਰਿਤ APIs ਆਸਾਨ ਬਣ ਜਾਂਦੇ ਹਨ।
ਫਾਇਦੇ:
Encoder[A], Show[A])ਖਤਰੇ:
Scala 3 ਨੇ Scala ਦੇ ਮੂਲ ਲਕਸ਼ਾਂ ਨੂੰ ਇਸਤੋਂ ਖਤਮ ਨਾ ਕਰਦੇ ਹੋਏ ਰੋਜ਼ਾਨਾ ਕੋਡ ਨੂੰ ਸਾਫ਼ ਅਤੇ ਸਮਝਣਯੋਗ ਬਣਾਉਣ 'ਤੇ ਧਿਆਨ ਦਿੱਤਾ।
ਮੁੱਖ ਤਬਦੀਲੀਆਂ ਵਿੱਚ ਸ਼ਾਮਲ ਹਨ:
implicit ਪੈਟਰਨਾਂ ਦੀ ਥਾਂ / ਆਏ ਹਨ, ਜਿਸ ਨਾਲ type class ਉਪਯੋਗ ਅਤੇ DI-ਬਹਿਭਾਵ ਹੋਰ ਸਪਸ਼ਟ ਹੁੰਦਾ ਹੈਅਮਲੀ ਅਭਿਆਸ: implicits ਨੂੰ ਖਾਸ ਤੌਰ 'ਤੇ ਇੰਪੋਰਟ ਕਰੋ, ਸਥਾਨਕ ਰੱਖੋ ਅਤੇ ਅਣਉਮੀਦਿਤ ਪ੍ਰਭਾਵ ਘੱਟ ਰੱਖੋ।
givenusingenum ਹੁਣ ਪਹਿਲ-ਸ਼੍ਰੇਣੀ ਫੀਚਰ ਹਨ, ਤਾਂ ਜੋ sealed-trait + case-object ਚਲਨ ਹੌਲੀ ਹੋ ਜਾਵੇਮਾਈਗ੍ਰੇਸ਼ਨ ਅਮਲ ਵਿੱਚ ਆਮ ਤੌਰ 'ਤੇ ਇਸ ਤਰ੍ਹਾਂ ਹੈ ਕਿ ਤੁਹਾਡਾ ਕਾਰੋਬਾਰੀ ਲਾਜਿਕ ਮੁੱਖ ਤੌਰ 'ਤੇ ਵਾਪਸ ਰਹਿੰਦਾ ਹੈ; ਵੱਡੇ ਕੰਮ ਹਨ macros-ਯੁਕਤ ਕੋਡ, জਟਿਲ implicit ਚੇਨ੍ਹਾਂ ਅਤੇ ਬਿਲਡ/ਪਲੱਗਿਨ ਅਨੁਪਾਤ।