Глубинный котер
95 subscribers
60 photos
7 videos
4 files
71 links
Download Telegram
Всегда думал, что Java слишком вербозная, а Python такой выразительный и краткий.

Но вот в случае функционального стиля Python явно проигрывает API стримов в Java. Вместо лаконичного пайплайна, получаем скобочный ад
👍32
Прикольно автор книги с кабанчиком раздает бесплатно избранные главы на сайте, как понимаю, его NoSQL СУБД ScyllaDB
👍1
Виртуальная машина СPython позволяет легко менять значения даже у литералов.

Например, мы легко можем заменить значение литерала a в нашей виртуальной машине. После замены a на z в нашей программе больше не осталось первой буквы алфавита, теперь в a лежит “z”


from ctypes import c_byte
from sys import getsizeof


def set_value(old: object, new: object) -> None:
src_s, des_s = getsizeof(new), getsizeof(old)
src_arr = (c_byte * src_s).from_address(id(new))
des_arr = (c_byte * des_s).from_address(id(old))
des_arr[:] = src_arr[:]


set_value('a', 'z')

assert 'a' == 'z'
🤬32😁1
Как до жизни такой докатился? 🤡
🥴32😁1
Поколение Юпитера 🪐
😁61
Forwarded from Wazowski Recommends
Попав в Яндекс, мы получили проект от Ильи Сегаловича. Илья умел очень классно делиться идеями и объяснять суть. Он нам рассказал, что на самом деле Гугл в своё время выиграл у всех предыдущих поисковиков за счёт хорошо сделанных сниппетов. А теперь для нас самое главное — сделать так, чтобы поисковые результаты не были сплошь одинаковыми. Надо бороться с полу-дублями.

Только сделать это у нас не удалось. Зато мне удалось получить свою первую психологическую травму на работе.

В Яндексе тогда не было почти никакой документации. Даже как собирать проект — было тайным знанием, передающимся из уст в уста.

Когда нужно было разобраться в каком-то куске поискового кода, Макс сказал:
— Ну давай посмотрим, кто автор этого кода... Ага, некий Антон с ником pg@. Просто сходи и спроси у него, что здесь происходит.

Я сходил и спросил. Антон с ником pg@ ответил мне, чтобы я просто прочитал код.

Прочитать и понять код у меня не получилось. А так как работали мы на четверть ставки, то в следующий раз мы с Максом встретились примерно через неделю. Узнав, что прогресса особо нет, Макс сказал:
— Нет, ну так дело не пойдёт. Пойдём вместе сходим и спросим.

Сходили и спросили. На что Антон с ником pg@ просто накричал на нас обоих: какого чёрта какие-то стажёры его отвлекают и не могут даже за неделю самостоятельно прочитать код?!

С тех пор ни я, ни Макс уже больше никогда не хотели работать в Яндекс.Поиске.

#lifestories
5🦄1
Ну разве не так?
3🤓2
Для меня такое откровение, что тайп чекер и интерпретатор — суть одно и тоже
4🍌1
В Python 3.12 подвезли события виртуальной машины и API для работы с ними. В PEP 669 – Low Impact Monitoring for CPython описываются эти события, главная мотивация их добавить — профилирование приложения на проде без влияния на производительность

C++ and Java developers expect to be able to run a program at full speed (or very close to it) under a debugger. Python developers should expect that too.


API довольно низкоуровневый, но если поиграться, можно лучше понять исполнение python программ. Например, если прикрутить коллбеки на события PY_YIELD и STOP_ITERATION, то можно понаблюдать за работой корутин:

import sys
import random
import asyncio

from types import CodeType
from contextlib import contextmanager


@contextmanager
def log_cpython_vm_events(events_callbacks: dict):
if len(events_callbacks) > 5:
raise ValueError("Too many events callbacks")

try:
for tool_id, (event, callback) in enumerate(events_callbacks.items(), start=1):
sys.monitoring.use_tool_id(tool_id, "test")
sys.monitoring.register_callback(tool_id, event, callback)
sys.monitoring.set_events(tool_id, event)
yield
finally:
for tool_id, (event, callback) in enumerate(events_callbacks.items()):
sys.monitoring.register_callback(tool_id, event, None)
sys.monitoring.free_tool_id(tool_id)


def callback_on_yield(code: CodeType, instruction_offset: int, retval: object):
next_frame = sys._getframe(1)
print(
f'Yield from "{code.co_name}" with locals={next_frame.f_locals} witch return instance id={id(retval)} of type {type(retval).__name__}'
)


def callback_on_stop_iteration(
code: CodeType, instruction_offset: int, exception: object
):
next_frame = sys._getframe(1)
print(
f'Stop iteration from "{code.co_name}" with locals={next_frame.f_locals} witch raise exc "{type(exception).__name__}"'
)


EVENTS_CALLBACKS_MAPPING = {
sys.monitoring.events.PY_YIELD: callback_on_yield,
sys.monitoring.events.STOP_ITERATION: callback_on_stop_iteration,
}


async def run(idx: int):
await asyncio.sleep(random.random())


async def main():
await asyncio.gather(*map(run, range(2)))


with log_cpython_vm_events(EVENTS_CALLBACKS_MAPPING):
asyncio.run(main())
👍21🤷‍♂1
Краем уха слышал про акторную модель в Erlang и в Akka (фреймворк на Scalla), но не понимал, как обстоят дела с гарантиями доставки. Если сообщения между акторами хранятся в памяти, то мы их потеряем при перезапуске/падении нашего приложения.

В Akka нашел возможность хранить сообщения в базе с помощью плагинов персистентного хранения. Как понимаю, работают на основе snapshot, и как с snapshot в Redis, некоторые данные можем потерять в случае перезапуска.

В докладе Никита Мельников рассказывает про альтернативный подход в построение акторной модели, который отчасти решает проблему потери сообщений при перезапусках. Вместо того, чтобы использовать готовую инфраструктуру, но не очень популярную, можно самим сварить на основе Kafka, Outbox и CDC. Минусы очевидны — велосипедостроение, из плюсов, что решение на Kafka масштабируется и лучше проверено сообществом.

Еще из доклада узнал неочевидный для меня плюс акторной модели — это уход от состояния гонок и явное описание состояний актора
7
Приблизительно понимал, что такое каррирование, но не понимал связи с кортежем (tuple). Но теперь все стало на место.

Кортеж является типом-произведения, а его значения принадлежат уже к декартовому (?) произведению множеств значений. Соотвественно, мы можем всегда найти функцию, которая принимает один из множителей. Повторяя поиск такой функции для других множителей, мы сможем найти последовательность функций от одного типа эквивалентную функции от типа-произведения, то есть кортежа
31👍1
Увидел красоту реактивного программирования в докладе Ахтяма Сакаева

Главный вывод: бизнес-процессы можно моделировать через стримы, ака стрелочки на диаграмме у архитекторов
4👎1
Ознакомился со статьей Understanding Real-World Concurrency Bugs in Go о которой узнал из Блог*. Главный вывод: добавление новых семантических конструкций в языке увеличивает количество багов.

Так одной из отличительных особенностей Go являются каналы, которые по результатам исследования стали причиной больше половины блокирующих багов. При этом встроенный детектор блоков толком не помогает найти эти баги.

Из статьи можно сделать вывод, что Go не обеспечивает достаточный уровень проверок на этапе компиляции. Как в том же Rust на уровне теории типов были выявлены и устранены баги в корутинах. Но статья была написана в 2019 году, на текущий момент многие примеры из статьи поднимают ошибки во время исполнения, что уже неплохо.
2👍2
Ох уж этот escape анализ
😁2
package main

import "fmt"

type SelfReferential struct {
r *SelfReferential
field int
}

func make_self_referential() SelfReferential {
s := SelfReferential {
r: nil,
field: 1,
}
s.r = &s
return s
}

func main() {
s := make_self_referential()
s.r.field = 2
fmt.Println(s.field)
fmt.Println(s.r.field)
fmt.Println(s.r.r.field)
}


Ваши догадки, что случится при запуске этой программы:

1. (lawful good) Выведется 2 2 2 без UB (структура аллоцировалась на куче)
2. (lawful evil) Произойдет UB или паника (структура аллоцируется на стеке, в s.r окажется dangling pointer)
3. (chaotic neutral) Выведется 1 2 2 без UB (🤷‍♀️)

#dev #go
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🥰2
Когда глаз дёргается от «функционалов» и «функций» в постановке задачи от бизнеса
🥰3😁21