CPPLASTIC Telegram 377
Коли я тільки-но починав програмувати, то з величезним задоволенням писав на QBasic, а потім на Pascal. Згодом перейшов на 💻, яка вражала лаконічністю, та водночас мала в порівнянні певні незручності. Наприклад, ті ж нуль-терміновані рядки.

Але найбільше на початку дратувала робота з багатовимірними масивами. Якщо в тому ж паскалі можна дати змінній тип, наприклад, двовимірного масиву, щоб потім звертатися до його елементів як pixels[x,y], то в сішці таке не спрацює, і треба писати pixels[x][y].

Нічого страшного начебто — просто трохи інший запис. Але ця фішка перейшла і в 💻. А там доволі швидко зʼявляється бажання загорнути «сирі» масиви в якийсь клас з типобезпечнішою апішкою. Ну там матрицю ту ж зробити чи тензор якийсь, поперевантажувати оператори, щоб зручніше було, тощо.

Уявімо, що написали ви свій клас Matrix. Всередині у вас лежить якийсь масив; треба тепер визначити operator[], щоб можна було читати/писати конкретний елемент. Якби була багатовимірна індексація, то це суперлегко, причому дані всередині можна взагалі тримати в одновимірному масиві, а індекс обчислювати. Однак matrix[i][j] — це дві окремі операції, які можна записати як (matrix[i])[j]. Іншими словами, matrix[i] має повернути щось, на чому потім можна викликати .operator[](j).

Що це може бути? Ну, по-перше, можна повертати тупо вказівник на початок рядка, проте, я не почуваюся комфортно з цього приводу, бо забагато свободи: можна за межі піти, можна зберегти у змінну кудись, а потім навіть не дізнатися, що він інвалідувався (бо не володієш ним) тощо. При обережному використанні працюватиме, але наша мета ж знизити когнітивне навантаження, а не навпаки.

По-друге, можна повертати якийсь проксі-обʼєкт власного типу на кшталт Matrix::Row. Зробити, щоб створювати його могла тільки сама Matrix, по максимуму обмежити допустимі операції, перевизначити operator[]… Головняково якось, ще й сумнівно з погляду на швидкодію.

Натомість зазвичай перевантажують не індексацію, а операцію виклику функції operator(). Тоді є змога вказати довільну кількість параметрів. Але використання вже не настільки файне на вигляд, бо дужки круглі: matrix(i, j). Окрім неможливості в такому випадку зробити одночасно й індексацію, і виклик обʼєкта як функції (що все одно навряд чи комусь знадобиться), мені в цьому не подобається, що воно складніше сприймається. Око вже звикло, що квадратні дужки — доступ до елемента, круглі — виклик функції, тому натренований токенайзер у мозку даватиме хибні результати й сповільнюватиме читання й розуміння коду.

В інших, кращих мовах багатовимірна індексація вже присутня. Не тільки в спеціалізованих на кшталт 💻. Наприклад, у 💻 є, по-перше, багатовимірні масиви базових типів (int[,]), а по-друге, кастомний індексатор може приймати більше одного параметра: this[int row, int column]. (Так, мені дійсно подобається C# місцями). У Python 💻 метод __getitem__ завжди приймає тільки один параметр, проте, коли ви пишете matrix[i,j], то оці значення через кому запаковуються в кортеж, тобто викликається Matrix.__getitem__(matrix, (i, j)).

Щодо C++ же я давно змирився, що зручно тут не буває. І, уявіть собі, дарма!

Короч, починаючи з C++23 тепер є багатовимірна індексація, тобто це вже працює. Тепер operator[] може приймати довільну кількість параметрів різних типів:
m[0, 1, "shiii~"] = 42;

І до купи цей оператор тепер ще й статичним може бути.

Не вау яка фіча, і все ж мені до душі.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🤯5🔥2



tgoop.com/cpplastic/377
Create:
Last Update:

Коли я тільки-но починав програмувати, то з величезним задоволенням писав на QBasic, а потім на Pascal. Згодом перейшов на 💻, яка вражала лаконічністю, та водночас мала в порівнянні певні незручності. Наприклад, ті ж нуль-терміновані рядки.

Але найбільше на початку дратувала робота з багатовимірними масивами. Якщо в тому ж паскалі можна дати змінній тип, наприклад, двовимірного масиву, щоб потім звертатися до його елементів як pixels[x,y], то в сішці таке не спрацює, і треба писати pixels[x][y].

Нічого страшного начебто — просто трохи інший запис. Але ця фішка перейшла і в 💻. А там доволі швидко зʼявляється бажання загорнути «сирі» масиви в якийсь клас з типобезпечнішою апішкою. Ну там матрицю ту ж зробити чи тензор якийсь, поперевантажувати оператори, щоб зручніше було, тощо.

Уявімо, що написали ви свій клас Matrix. Всередині у вас лежить якийсь масив; треба тепер визначити operator[], щоб можна було читати/писати конкретний елемент. Якби була багатовимірна індексація, то це суперлегко, причому дані всередині можна взагалі тримати в одновимірному масиві, а індекс обчислювати. Однак matrix[i][j] — це дві окремі операції, які можна записати як (matrix[i])[j]. Іншими словами, matrix[i] має повернути щось, на чому потім можна викликати .operator[](j).

Що це може бути? Ну, по-перше, можна повертати тупо вказівник на початок рядка, проте, я не почуваюся комфортно з цього приводу, бо забагато свободи: можна за межі піти, можна зберегти у змінну кудись, а потім навіть не дізнатися, що він інвалідувався (бо не володієш ним) тощо. При обережному використанні працюватиме, але наша мета ж знизити когнітивне навантаження, а не навпаки.

По-друге, можна повертати якийсь проксі-обʼєкт власного типу на кшталт Matrix::Row. Зробити, щоб створювати його могла тільки сама Matrix, по максимуму обмежити допустимі операції, перевизначити operator[]… Головняково якось, ще й сумнівно з погляду на швидкодію.

Натомість зазвичай перевантажують не індексацію, а операцію виклику функції operator(). Тоді є змога вказати довільну кількість параметрів. Але використання вже не настільки файне на вигляд, бо дужки круглі: matrix(i, j). Окрім неможливості в такому випадку зробити одночасно й індексацію, і виклик обʼєкта як функції (що все одно навряд чи комусь знадобиться), мені в цьому не подобається, що воно складніше сприймається. Око вже звикло, що квадратні дужки — доступ до елемента, круглі — виклик функції, тому натренований токенайзер у мозку даватиме хибні результати й сповільнюватиме читання й розуміння коду.

В інших, кращих мовах багатовимірна індексація вже присутня. Не тільки в спеціалізованих на кшталт 💻. Наприклад, у 💻 є, по-перше, багатовимірні масиви базових типів (int[,]), а по-друге, кастомний індексатор може приймати більше одного параметра: this[int row, int column]. (Так, мені дійсно подобається C# місцями). У Python 💻 метод __getitem__ завжди приймає тільки один параметр, проте, коли ви пишете matrix[i,j], то оці значення через кому запаковуються в кортеж, тобто викликається Matrix.__getitem__(matrix, (i, j)).

Щодо C++ же я давно змирився, що зручно тут не буває. І, уявіть собі, дарма!

Короч, починаючи з C++23 тепер є багатовимірна індексація, тобто це вже працює. Тепер operator[] може приймати довільну кількість параметрів різних типів:

m[0, 1, "shiii~"] = 42;

І до купи цей оператор тепер ще й статичним може бути.

Не вау яка фіча, і все ж мені до душі.

BY Cіпласпластик


Share with your friend now:
tgoop.com/cpplastic/377

View MORE
Open in Telegram


Telegram News

Date: |

SUCK Channel Telegram It’s easy to create a Telegram channel via desktop app or mobile app (for Android and iOS): Informative Public channels are public to the internet, regardless of whether or not they are subscribed. A public channel is displayed in search results and has a short address (link). Telegram desktop app: In the upper left corner, click the Menu icon (the one with three lines). Select “New Channel” from the drop-down menu.
from us


Telegram Cіпласпластик
FROM American