tgoop.com/cpplastic/349
Last Update:
Класно бути програмістом на C++: захотів покодити іншою мовою — скомпілив її
От я сьогодні з цього почав, бо вирішив згадати мову io, але під arm64 на macOS її немає, бо там якийсь асемблерний код не компілюється. Автори кажуть, мовляв, треба окрему версію Homebrew поставити для цього, але то якогось занадто головняково, тож я просто скомпілював з сорців. Версія з master
одразу падала з помилкою, тому довелося трохи пострибати по теґах.
Першу сьогоднішню задачу з Advent of Code я розвʼязав дуже швидко, а от другу вже повертів туди-сюди, бо, як це часто буває, налажав десь у корнер-кейсах. А там якраз був ОДИН такий
Тепер про саму мову. Вона наче й не складна, але є там трохи дивні моменти, коли начебто схожі конструкції поводять себе трохи по-різному.
З класного: там все є виразом (expression), тобто у всього є результат, тому можна хоч цикл for
записати у змінну. Ну, насправді це й не цикл, а просто функція в Object
. Взагалі треба дуже уважно дивитися, що яка функція повертає, бо інколи це не те що ти очікуєш.
Ще з цікавого: вирішив я написати функцію mapPairs
, яка виконує блок коду на кожній парі зі списку та повертає список результатів. Мабуть, можна було цікавіше щось вигадати, але пох.
Використовую її потім якось отак (тут report
— це список):
increasing := true
decreasing := true
report mapPairs(l, r,
increasing = increasing and l < r
decreasing = decreasing and l > r
result := (increasing or decreasing) and (l - r) abs <= 3
"#{l}, #{r}: #{result}" interpolate println
result
)
Прикол тут наступний: якогось спеціального синтаксису для лямбд немає.
mapPairs
— це просто метод з трьома параметрами: l
, r
та блок коду. Причому l
та r
я до того ніде не створював, але в блоці коду їх використовую разом з іншими змінними з локального скоупа, звідки викликаю це. Як же це працює? А отак:List mapPairs := method(
left := call argAt(0) name
right := call argAt(1) name
body := call argAt(2)
context := Object clone prependProto(call sender)
if(call sender hasLocalSlot("self"),
context setSlot("self", call sender self)
)
result := List clone
for (i, 0, self size - 2,
context setSlot(left, self at(i))
context setSlot(right, self at(i + 1))
result append(context doMessage(body))
)
result
)
У
context
клонується все з sender
(так-так, в io методи — це надсилання повідомлень, як у SmallTalk), потім у ньому ж створюються l
та r
, а потім отой блок коду виконується вже в цьому контексті. Трошки винесло мені мозок короч.Працює io десь разів у 10 повільніше за Haskell. Файл на 1000 рядків у мене оброблявся 200 з копійками мілісекунд. З іншого боку, оптимізаціями там і не пахне. Не казатиму вам, яка складність у мого алгоритму, бо там треш ))