ਕੀ ਤੁਸੀਂ ਉਹ ਅਹਿਸਾਸ ਜਾਣਦੇ ਹੋ ਜਦੋਂ ਤੁਸੀਂ ਇੱਕ ਨਵੀਂ ਭਾਸ਼ਾ ਸਿੱਖਣੀ ਸ਼ੁਰੂ ਕਰਦੇ ਹੋ ਅਤੇ ਉਮੀਦ ਕਰਦੇ ਹੋ ਕਿ ਤੁਸੀਂ ਤੇਜ਼ੀ ਨਾਲ ਦੌੜੋਗੇ, ਪਰ ਇਸ ਦੀ ਬਜਾਏ ਤੁਸੀਂ ਪਹਿਲੇ ਕਦਮ 'ਤੇ ਹੀ ਡੋਲ ਜਾਂਦੇ ਹੋ? ਮੇਰੇ ਨਾਲ Rust ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇਹੀ ਹੋਇਆ। ਮੇਰੇ ਕੋਲ ਇੱਕ ਬਿਲਕੁਲ ਠੀਕ JavaScript utility ਸੀ — ਕੁਝ ਅਜਿਹਾ ਜੋ ਕੁਝ arrays ਨੂੰ parse ਅਤੇ mutate ਕਰਦਾ ਸੀ — ਅਤੇ ਮੈਂ ਸੋਚਿਆ ਕਿ ਮੈਂ ਇਸਨੂੰ ਇੱਕ ਕੌਫੀ ਬ੍ਰੇਕ ਦੌਰਾਨ ਦੁਬਾਰਾ ਲਿਖ ਲਵਾਂਗਾ। ਮੈਂ ਆਪਣਾ editor ਖੋਲ੍ਹਿਆ, ਉਹ ਲਿਖਿਆ ਜੋ ਕੁਦਰਤੀ ਲੱਗ ਰਿਹਾ ਸੀ, ਅਤੇ compiler ਚਲਾਇਆ। ਇਹ ਫਟ ਗਿਆ। Syntax errors ਕਰਕੇ ਨਹੀਂ। ਮਿਸਿੰਗ semicolons ਕਰਕੇ ਨਹੀਂ। ਇਸਨੇ ਮੈਨੂੰ ਦੱਸਿਆ ਕਿ ਮੈਂ ਇੱਕ ਅਜਿਹੀ value ਦੀ ਵਰਤੋਂ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਸੀ ਜੋ ਪਹਿਲਾਂ ਹੀ move ਹੋ ਚੁੱਕੀ ਸੀ। ਮੈਂ ਸਕ੍ਰੀਨ ਵੱਲ ਦੇਖਦਾ ਰਿਹਾ। Moved? ਮੈਂ ਕੁਝ ਵੀ move ਨਹੀਂ ਕੀਤਾ ਸੀ। ਮੈਂ ਤਾਂ ਬੱਸ ਇਸਨੂੰ ਦੂਜੇ variable ਨੂੰ assign ਕਰ ਦਿੱਤਾ ਸੀ।
JavaScript ਦਾ ਆਰਾਮਦਾਇਕ ਖੇਤਰ
JavaScript ਤੁਹਾਨੂੰ ਡਾਟਾ ਨਾਲ ਇੱਕ ਸਾਂਝੇ ਵ੍ਹਾਈਟਬੋਰਡ ਵਾਂਗ ਵਰਤਣ ਦੀ ਆਦਤ ਪਾਉਂਦੀ ਹੈ। ਤੁਸੀਂ ਇੱਕ object ਜਾਂ array ਘੋਸ਼ਿਤ ਕਰਦੇ ਹੋ, ਉਸਨੂੰ ਇੱਕ function ਨੂੰ ਦਿੰਦੇ ਹੋ, ਉਸ function ਨੂੰ ਇੱਕ property push ਕਰਨ ਦਿੰਦੇ ਹੋ, ਅਤੇ ਫਿਰ ਉਸਨੂੰ ਕਿਤੇ ਹੋਰ ਭੇਜ ਦਿੰਦੇ ਹੋ। Garbage collector ਪਿਛੋਕੜ ਵਿੱਚ ਇੱਕ ਅਦਿੱਖ ਸਫਾਈ ਕਰਮਚਾਰੀ ਵਾਂਗ ਬੈਠਾ ਰਹਿੰਦਾ ਹੈ, ਜੋ ਤੁਹਾਡੇ ਦੁਆਰਾ ਛੱਡੀ ਗਈ ਕਿਸੇ ਵੀ ਚੀਜ਼ ਨੂੰ ਸਾਫ਼ ਕਰਨ ਲਈ ਤਿਆਰ ਰਹਿੰਦਾ ਹੈ। ਤੁਸੀਂ ਕਦੇ ਨਹੀਂ ਪੁੱਛਦੇ, "ਇਸ string ਦਾ ਮਾਲਕ ਕੌਣ ਹੈ?" ਤੁਸੀਂ ਪੁੱਛਦੇ ਹੋ, "ਕੀ ਮੈਂ ਇਸਨੂੰ ਪੜ੍ਹ ਸਕਦਾ ਹਾਂ?" ਜੇਕਰ ਜਵਾਬ ਹਾਂ ਹੈ, ਤਾਂ ਤੁਸੀਂ ਇਸਨੂੰ ਛੂਹ ਲੈਂਦੇ ਹੋ। ਜੇਕਰ ਤੁਹਾਨੂੰ ਇੱਕ ਹੋਰ reference ਦੀ ਲੋੜ ਹੈ, ਤਾਂ ਤੁਸੀਂ ਬੱਸ let b = a ਕਹਿੰਦੇ ਹੋ ਅਤੇ ਅੱਗੇ ਵਧਦੇ ਹੋ। ਦੋਵੇਂ variables ਇੱਕੋ ਮੈਮੋਰੀ ਪੈਚ ਵੱਲ ਇਸ਼ਾਰਾ ਕਰਦੇ ਹਨ, ਅਤੇ ਜੇਕਰ a ਇਸਨੂੰ mutate ਕਰਦਾ ਹੈ, ਤਾਂ b ਤੁਰੰਤ ਬਦਲਾਅ ਦੇਖਦਾ ਹੈ। ਇਹ ਸੁਵਿਧਾਜਨਕ ਹੈ। ਇਹ ਅਰਾਜਕਤਾ (chaos) ਵਾਲਾ ਵੀ ਹੈ, ਪਰ ਇਹ ਅਰਾਜਕਤਾ ਤੁਹਾਨੂੰ ਸ਼ਾਇਦ ਹੀ ਕਦੇ ਨੁਕਸਾਨ ਪਹੁੰਚਾਉਂਦੀ ਹੈ ਕਿਉਂਕਿ runtime ਸਫਾਈ ਦਾ ਕੰਮ ਸੰਭਾਲ ਲੈਂਦਾ ਹੈ।
ਪਹਿਲਾ Compiler Shock
Rust ਤੁਹਾਡੇ 'ਤੇ ਭਰੋਸਾ ਨਹੀਂ ਕਰਦਾ। ਇਹ ਸੁਣਨ ਵਿੱਚ ਕਠੋਰ ਲੱਗ ਸਕਦਾ ਹੈ, ਪਰ ਇਹ ਪਹਿਲੀ ਚੀਜ਼ ਹੈ ਜੋ ਤੁਸੀਂ ਸਿੱਖਦੇ ਹੋ। ਇਹ ਭਾਸ਼ਾ ਤਿੰਨ ਸਖ਼ਤ ਨਿਯਮਾਂ ਵਾਲੇ ownership system ਦੇ ਆਲੇ-ਦੁਆਲੇ ਬਣੀ ਹੈ। ਪਹਿਲਾ, ਹਰ value ਦਾ ਬਿਲਕੁਲ ਇੱਕ ਹੀ ਮਾਲਕ ਹੁੰਦਾ ਹੈ। ਦੂਜਾ, ਇੱਕ ਸਮੇਂ 'ਤੇ ਸਿਰਫ਼ ਇੱਕ ਹੀ ਮਾਲਕ ਹੁੰਦਾ ਹੈ। ਤੀਜਾ, ਜਦੋਂ ਉਹ ਮਾਲਕ scope ਤੋਂ ਬਾਹਰ ਜਾਂਦਾ ਹੈ, ਤਾਂ Rust ਉਸ value ਨੂੰ ਆਪਣੇ ਆਪ drop ਕਰ ਦਿੰਦਾ ਹੈ। ਕੋਈ garbage collector ਨਹੀਂ। ਕੋਈ reference counting ਪਿਛੋਕੜ ਵਿੱਚ ਨਹੀਂ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਸਪੱਸ਼ਟ ਤੌਰ 'ਤੇ ਇਸਨੂੰ ਚੁਣਦੇ ਨਹੀਂ ਹੋ। ਬੱਸ ਇਹ ਤਿੰਨ ਨਿਯਮ, ਜੋ ਤੁਹਾਡੇ ਕੋਡ ਦੇ ਚੱਲਣ ਤੋਂ ਪਹਿਲਾਂ ਹੀ compiler ਦੁਆਰਾ ਲਾਗੂ ਕੀਤੇ ਜਾਂਦੇ ਹਨ।
ਜਦੋਂ ਮੈਂ ਉਸ JavaScript utility ਦਾ ਆਪਣਾ Rust version ਲਿਖਿਆ, ਤਾਂ ਮੈਂ ਉਹੀ ਕੀਤਾ ਜੋ ਕੁਦਰਤੀ ਲੱਗ ਰਿਹਾ ਸੀ। ਮੈਂ ਇੱਕ vector ਬਣਾਇਆ, ਜੋ array ਦਾ Rust ਦਾ ਜਵਾਬ ਹੈ, ਅਤੇ ਇਸਨੂੰ ਦੂਜੇ variable ਨੂੰ assign ਕਰ ਦਿੱਤਾ। ਫਿਰ ਮੈਂ ਪਹਿਲੇ ਦੀ ਵਰਤੋਂ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। Compiler ਨੇ ਇਨਕਾਰ ਕਰ ਦਿੱਤਾ। JavaScript ਵਿੱਚ, let b = a reference ਦੀ ਕਾਪੀ ਕਰਦਾ ਹੈ। Rust ਵਿੱਚ, ਇਹ ownership ਨੂੰ move ਕਰ ਦਿੰਦਾ ਹੈ। ਅਸਲ variable ਅਵੈਧ (invalid) ਹੋ ਜਾਂਦਾ ਹੈ। Compiler ਇਹ ਇਸ ਲਈ ਕਰਦਾ ਹੈ ਤਾਂ ਜੋ ਇਹ ਯਕੀਨੀ ਬਣਾਇਆ ਜਾ ਸਕੇ ਕਿ ਤੁਸੀਂ ਕਦੇ ਵੀ ਗਲਤੀ ਨਾਲ ਇੱਕੋ ਮੈਮੋਰੀ 'ਤੇ ਦੋ ਰਸਤੇ ਨਹੀਂ ਪਾ ਰਹੇ, ਜਿਸ ਕਾਰਨ ਹੋਰ ਸਿਸਟਮਾਂ ਵਿੱਚ data races ਅਤੇ use-after-free bugs ਹੁੰਦੇ ਹਨ।
Rust ਤੁਹਾਡੇ ਖਿਡੌਣੇ ਕਿਉਂ ਖੋਹ ਲੈਂਦਾ ਹੈ
JavaScript ਵਿੱਚ ਇਸ ਪੈਟਰਨ ਨੂੰ ਦੇਖੋ:
let a = [1, 2, 3];
let b = a;
a.push(4);
// Both a and b see 4.
ਇਹ ਤੁਹਾਡੀ ਕੁਦਰਤੀ ਆਦਤ ਹੈ। ਤੁਸੀਂ ਦੋ ਵਾਰ ਨਹੀਂ ਸੋਚੋਗੇ। Rust ਵਿੱਚ, ਉਹੀ ਅੰਦਾਜ਼ਾ ਤੁਹਾਨੂੰ ਟਾਈਪ ਕਰਨਾ ਖਤਮ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਹੀ compiler ਦੁਆਰਾ ਰੱਦ ਕਰ ਦਿੱਤਾ ਜਾਵੇਗਾ। ਇੱਕ ਵਾਰ ਜਦੋਂ b vector ਦਾ ਮਾਲਕ ਬਣ ਜਾਂਦਾ ਹੈ, ਤਾਂ a ਇੱਕ ਖਾਲੀ ਨਾਮ ਬਣ ਜਾਂਦਾ ਹੈ। ਤੁਸੀਂ ਇਸ ਵਿੱਚ push ਨਹੀਂ ਕਰ ਸਕਦੇ। ਤੁਸੀਂ ਇਸਨੂੰ ਦੇਖ ਵੀ ਨਹੀਂ ਸਕਦੇ। ਮੈਮੋਰੀ ਹੁਣ b ਦੀ ਹੈ।
ਇਹ ਇੱਕ ਸਜ਼ਾ ਵਾਂਗ ਲੱਗਦਾ ਹੈ ਜਦੋਂ ਤੱਕ ਤੁਹਾਨੂੰ ਇਹ ਅਹਿਸਾਸ ਨਹੀਂ ਹੁੰਦਾ ਕਿ ਇਹ ਕਿਸ ਚੀਜ਼ ਨੂੰ ਰੋਕਦਾ ਹੈ। ਜੇਕਰ ਦੋ variables ਤਾਲਮੇਲ ਤੋਂ ਬਿਨਾਂ ਇੱਕੋ heap data ਨੂੰ mutate ਕਰ ਸਕਦੇ ਸਨ, ਤਾਂ ਤੁਹਾਨੂੰ memory corruption ਦਾ ਖ਼ਤਰਾ ਹੁੰਦਾ। Rust ਇਸ ਤਬਦੀਲੀ ਨੂੰ ਸਪੱਸ਼ਟ ਬਣਾ ਕੇ ਬੱਗਾਂ (bugs) ਦੀ ਪੂਰੀ ਸ਼੍ਰੇਣੀ ਨੂੰ ਖਤਮ ਕਰ ਦਿੰਦਾ ਹੈ। Compiler ਬਹੁਤ ਜ਼ਿਆਦਾ ਨਿਯਮਾਂ ਵਾਲਾ (pedantic) ਨਹੀਂ ਹੋ ਰਿਹਾ। ਇਹ ਇੱਕ ਦਰਵਾਜ਼ੇ ਦੀ ਰਾਖੀ ਕਰਨ ਵਾਲਾ (gatekeeper) ਬਣ ਰਿਹਾ ਹੈ। ਇਹ ਤੁਹਾਨੂੰ ਹਰ ਕਦਮ 'ਤੇ ਇਹ ਫੈਸਲਾ ਕਰਨ ਲਈ ਮਜਬੂਰ ਕਰਦਾ ਹੈ ਕਿ ਤੁਹਾਡੇ ਕੋਡ ਦਾ ਕਿਹੜਾ ਹਿੱਸਾ ਕਿਸ ਡਾਟਾ ਲਈ ਜ਼ਿੰਮੇਵਾਰ ਹੈ।
Borrowing: ਇੱਕ ਅਜਿਹਾ ਤਰੀਕਾ ਜੋ ਅਸਲ ਵਿੱਚ ਇੱਕ Feature ਹੈ
ਬੇਸ਼ੱਕ, ਜੇਕਰ ਹਰ assignment ਹਮੇਸ਼ਾ ਲਈ ownership ਨੂੰ ਤਬਦੀਲ ਕਰ ਦਿੰਦਾ, ਤਾਂ ਪ੍ਰੋਗਰਾਮ ਲਿਖਣਾ ਬਹੁਤ ਥਕਾਊ ਹੋ ਜਾਂਦਾ। ਤੁਹਾਨੂੰ ਹਰ ਚੀਜ਼ ਨੂੰ clone ਕਰਨ ਦੀ ਲੋੜ ਪੈਂਦੀ, ਜਿਸ ਨਾਲ ਮੈਮੋਰੀ ਅਤੇ ਰਫ਼ਤਾਰ ਬਰਬਾਦ ਹੁੰਦੀ। Rust ਇਸ ਨੂੰ borrowing ਨਾਲ ਹੱਲ ਕਰਦਾ ਹੈ।
Borrowing ਤੁਹਾਨੂੰ ਕਿਸੇ value ਨੂੰ ਲਏ ਬਿਨਾਂ ਵਰਤਣ ਦੀ ਇਜਾਜ਼ਤ ਦਿੰਦਾ ਹੈ। ਇਸਦੇ ਦੋ ਪ੍ਰਕਾਰ ਹਨ, ਅਤੇ ਇਹ ਅੰਤਰ ਮਹੱਤਵਪੂਰਨ ਹੈ।
- Immutable borrows, ਜਿਨ੍ਹਾਂ ਨੂੰ
&Tਲਿਖਿਆ ਜਾਂਦਾ ਹੈ: ਇਹ ਤੁਹਾਨੂੰ ਡਾਟਾ ਪੜ੍ਹਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿੰਦੇ ਹਨ। ਤੁਸੀਂ ਇੱਕੋ ਸਮੇਂ ਜਿੰਨੇ ਚਾਹੋ ਉਨੇ ਰੱਖ ਸਕਦੇ ਹੋ at the same
