• На собеседовании сказали, что не все функции - замыкания. Так ли это?

    @Arlekcangp
    Разработчик, Лид, Архитектор ПО
    Похоже вас поймали на том что в js кто-то решил переопределить термин "замыкание"... Т к javascript далеко не первый язык, в котором есть нечто, претендующее называться термином "замыкание", то следует в первую очередь рассмотреть общее определение. Возьмём его из википедии:

    Замыкание (англ. closure) в программировании — функция первого класса, в теле которой присутствуют ссылки на переменные, объявленные вне тела этой функции в окружающем коде и не являющиеся её параметрами. Говоря другим языком, замыкание — функция, которая ссылается на свободные переменные в своей области видимости.
    Замыкание, так же как и экземпляр объекта, есть способ представления функциональности и данных, связанных и упакованных вместе.
    Замыкание — это особый вид функции. Она определена в теле другой функции и создаётся каждый раз во время её выполнения. Синтаксически это выглядит как функция, находящаяся целиком в теле другой функции. При этом вложенная внутренняя функция содержит ссылки на локальные переменные внешней функции. Каждый раз при выполнении внешней функции происходит создание нового экземпляра внутренней функции, с новыми ссылками на переменные внешней функции.
    В случае замыкания ссылки на переменные внешней функции действительны внутри вложенной функции до тех пор, пока работает вложенная функция, даже если внешняя функция закончила работу, и переменные вышли из области видимости.[1]
    Замыкание связывает код функции с её лексическим окружением (местом, в котором она определена в коде). Лексические переменные замыкания отличаются от глобальных переменных тем, что они не занимают глобальное пространство имён. От переменных в объектах они отличаются тем, что привязаны к функциям, а не объектам.


    Как видим из этого длинного определения (а не только его первого предложения) интервьюер оказался формально прав (что является неожиданностью и для меня самого. Кто знает, возможно это веяние нового или всё же творчество чрезмерного ЧСВ js-кодерков, но не будем предвзятыми) Посмотрим дальше...Переходим в английскую версию той же страницы в википедии:

    In programming languages, a closure, also lexical closure or function closure, is a technique for implementing lexically scoped name binding in a language with first-class functions. Operationally, a closure is a record storing a function[a] together with an environment.[1] The environment is a mapping associating each free variable of the function (variables that are used locally, but defined in an enclosing scope) with the value or reference to which the name was bound when the closure was created.[b] Unlike a plain function, a closure allows the function to access those captured variables through the closure's copies of their values or references, even when the function is invoked outside their scope.


    О! А тут нет никаких "функций, вложенных в функцию" и нет никаких "создающихся каждый раз" Хм... Интересно. Ну за то есть абзац о том как появились замыкания:

    The concept of closures was developed in the 1960s for the mechanical evaluation of expressions in the λ-calculus and was first fully implemented in 1970 as a language feature in the PAL programming language to support lexically scoped first-class functions.[2]

    Peter J. Landin defined the term closure in 1964 as having an environment part and a control part as used by his SECD machine for evaluating expressions.[3] Joel Moses credits Landin with introducing the term closure to refer to a lambda expression whose open bindings (free variables) have been closed by (or bound in) the lexical environment, resulting in a closed expression, or closure.[4][5] This usage was subsequently adopted by Sussman and Steele when they defined Scheme in 1975,[6] a lexically scoped variant of Lisp, and became widespread.


    Ага. Оказывается первоначально они появились в такой не конвенциональной, с сегодняшней точки зрения VM, как SECD... И их создатель прямо говорит, что это код плюс данные. Далее термин применяют к лямбда-выражениям. Ничего не говорится, должны ли эти выражения возвращаться функцией, или достаточно того, что бы они захватывали переменные из своего лексического (или динамического, как в common lisp) окружения. Далее нам сообщают, что некие мистеры, Сасман и Стил, спустя каких то 11 лет добавили это в свой язык Scheme... Ну что же. Посмотрим замыкания в Scheme... А именно откроем книгу Сасмана и соавторов "Структура и интерпретация компьютерных программ" или "SICP" Первый раз (исключая содержание) слово "замыкание" встречается в главе 2 "Поcтроение абстракций c помощью данных"


    Важная идея в работе с составными данными — понятие замыкания (closure): клей для
    сочетания объектов данных должен позволять нам склеивать не только элементарные
    объекты данных, но и составные.


    Но, как выяснилось, это не те замыкания... Это замыкание в том смысле, что структуру одного типа (в данном случае пары) могут ссылаться на самих себя. И это то как термин "замыкание" понимают математики. Далее в SICP никаких других определений замыканий нет (несмотря на то, что само их использование конечно же есть) Ну ничего не остаётся как посмотреть что же сегодня называют замыканиями в языке Scheme... Гугл по этому запросу выдал первой ссылкой: https://www.cs.utexas.edu/ftp/garbage/cs345/schint....
    Цитирую:

    Procedures are Closures
    Scheme procedure's aren't really just pieces of code you can execute; they're closures.

    A closure is a procedure that records what environment it was created in. When you call it, that environment is restored before the actual code is executed. This ensures that when a procedure executes, it sees the exact same variable bindings that were visible when it was created--it doesn't just remember variable names in its code, it remembers what storage each name referred to when it was created.

    Since variable bindings are allocated on the heap, not on a stack, this allows procedures to remember binding environments even after the expressions that created those environments have been evaluated. For example, a closure created by a lambda inside a let will remember the let's variable bindings even after we've exited the let. As long as we have a pointer to the procedure (closure), the bindings it refers to are guaranteed to exist. (The garbage collector will not reclaim the procedure's storage, or the storage for the let bindings.)

    Here's an example that may clarify this, and show one way of taking advantage of it.

    Suppose we type the following expression at the Scheme prompt, to be interpreted in a top-level environment:

    Scheme> (let ((count 0))
               (lambda ()
                  (set! count (+ count 1))
                  count)))

    ##

    Evaluating this let expression first creates a binding environment with a binding for count. The initial value of this binding is 0. In this environment, the lambda expression creates a closure. When executed, this procedure will increment the count, and then return its value. (Note that the procedure is not executed yet, however--it's just created.) This procedure, returned by the lambda expression, is also returned as the value of the let expression, because a let returns the value of its last body expression. The read-eval-print loop therefore prints a representation of the (anonymous) procedure.


    Что имеем ? В Scheme - вообще любая функция - это замыкание! Т к она всегда захватывает контекст, даже если там пусто!. Что видим в коде ? Ну с точки зрения Scheme тут конечно вложенная функция, т к let - это на самом деле lambda, но так происходит потому, что в Scheme нет переменных в понимании js. В js же можно считать, что глобальный контекст - результат действия нечто, что эквивалентно let. Захватывает ли любая функция в js этот контекст ? Не знаю. Но точно знаю, что в вашем примере это определенно так - х часть контекста, который захватывается функцией. Кто хочет поспорить - идите спорьте с создателями Scheme (скажите, когда попкорн покупать, я посмотрю как вас пороть будут. Набежало тут вайтишников =)) Кто то может сказать "а вот у нас в js замыкания определяются не так" На что я отвечу: знаете, товарищи, а идите ка вы лесом! Если есть однажды созданный и определенный термин, нужны весьма веские причины что бы менять его определение. Желания левой ноги очередного вайтишника тут не достаточно.
    Ответ написан
    30 комментариев
  • Лучший клиент git ( unity )?

    vabka
    @vabka
    Токсичный шарпист
    Почти все доступные gui-клиенты перечислены тут:
    https://git-scm.com/download/gui/windows
    Есть много бесплатных. А у платных есть как минимум триальный период, так что пробуй.

    А лучше/хуже - это дело вкуса.

    Любой конкретный ответ под таким вопросом будет просто навязыванием своего выбора.

    Но раз для юнити, то я бы посмотрел в сторону Fork, тк у него есть пара фич, которые пригодятся при разработке игр (например diff по картинкам)
    Ответ написан
    Комментировать
  • Как настроить переадресацию почты с домена?

    yakovmanshin
    @yakovmanshin
    Software Engineer
    Я для таких задач уже пару лет использую сервис ImprovMX. Там есть и catch-all (когда перенаправляются письма, отправленные на несуществующие адреса), но можно добавлять и отдельные пересылки (удобно, если какой-то сервис спамит, перенаправлять письма от него на null).
    Ответ написан
    Комментировать
  • GitLab Почему из одной ветки одного и того же Repo скачивается artifact, а из другой нет?

    drno-reg
    @drno-reg Автор вопроса
    см не кратко
    не скачивается потому что в ветке dev не было ни одного завершенного пайплайна
    и это означает что пользоваться API методом
    GET /projects/:id/jobs/artifacts/:ref_name/downloa...
    нельзя
    НО есть другой метод который я описал в статье

    Gitlab CI «Smart» Pipeline: родители и дети

    ставить или не ставить свой голос решать вам, но каждый + помогает вылезти из минуса)
    Ответ написан
    Комментировать
  • Почему не пушится проект через GIT Bаsh?

    Grapeoff
    @Grapeoff
    В чём концепция...?
    Вы, скорее всего, вместо специальной SSH ссылки на ваш репозиторий скопировали HTTP ссылку и вставили её, когда писали git remote add origin
    Ответ написан
    1 комментарий
  • Какой настольный клиент использовать для работы с Git?

    Dier_Sergio_Great
    @Dier_Sergio_Great
    Увлеченный человек
    SmartGit
    Ответ написан
    Комментировать
  • Появляется ошибка при вводе git push -u Error: failed to push some refs to...?

    @VDone Автор вопроса
    Помогло это: Как сменить/удалить пользователя в GIT

    61f1aef0e667a255039826.png

    Всем спасибо
    Ответ написан
    Комментировать
  • Какие есть вариант ускорить работу Докера на Macbook?

    gbg
    @gbg
    Любые ответы на любые вопросы
    Предлагаю пораскинуть мозгами (не буквально), и сообразить, что автономность достигается в том числе за счет значительного урезания напряжений, частот, отправки ядер в отключку и других фокусов. Поэтому, о какой-то скорости можно говорить только при работе от розетки (чемодана с повербанками) и отключении всего энергосбережения.
    Ответ написан
    3 комментария
  • Как уменьшить дисковый кеш на linux?

    xotkot
    @xotkot
    хорошо есть и хорошо весьма
    для начала убедитесь что проблема действительно в дисковом кеше(не swap), попробуйте его сбросить когда всё начинает тормозить:
    sync && echo 1 > /proc/sys/vm/drop_caches
    запуск от суперпользователя

    еще с кешем можно сразу почистить inode и dentrie
    sync && echo 3 > /proc/sys/vm/drop_caches
    (данная команда включает в себя и команду приведенную выше)

    п.с.
    если проблема действительно окажется в дисковом кеше, то можно настроить систему так чтобы она более агрессивно его очищала установив параметр vfs_cache_pressure больше 100(по дефолту), например:
    echo 500 > /proc/sys/vm/vfs_cache_pressure
    (будет действовать до перезагрузки)
    чтобы зафиксировать данный параметр в системе и после перезагрузки создайте, например, файл /etc/sysctl.d/60-sysctl.conf с таким содержимым:
    vm.vfs_cache_pressure=500
    затем перезагрузите систему или просто перезагрузите сам файл конфигурации:
    sudo sysctl -p /etc/sysctl.d/60-sysctl.conf
    Чтобы убедиться что изменения вступили в силу посмотрите вывод команды:
    sudo sysctl -a | grep vfs_cache_pressure
    Ответ написан
    Комментировать
  • Планирую перейти с 1С на Golang на сколько реально в 42 года?

    alexgp13
    @alexgp13
    Руководитель ИТ-проектов
    Есть разные способы перейти на другой язык без просадки по ЗП, но работать придется много. Возможно все.
    И 42 года - не тот возраст, чтобы сильно переживать за восприятие возраста.

    Важный момент - Вы не новичок, у Вас уже есть большой опыт в предметной области, а новая технология - это всего лишь инструмент.

    И еще, со стороны нанимателя скажу. не скромничайте по ЗП - уверенный в себе человек с опытом даже в относительно новой для себя области производит хорошее впечатление, а вот, например, неплохой php-шник, просящий зарплату ниже рынка в области 1С (оказывается, бывает и такое), на днях вызвал у меня много вопросов.
    Ответ написан
    2 комментария
  • Как грамотно скрыть токен?

    igorzakhar
    @igorzakhar
    Пункт меню "Settings" в админке Heroku:

    61e838a57aeaa032563790.png

    Жмем кнопку "Reveal Config Vars ", добавляем переменные окружения:

    61e8392da7e75577329883.png

    Или через Heroku CLI (https://devcenter.heroku.com/articles/config-vars):
    heroku config:set GITHUB_USERNAME=joesmith
    Adding config vars and restarting myapp... done, v12
    GITHUB_USERNAME: joesmith


    В коде, для примера:
    access_token = os.getenv("ACCESS_TOKEN")
    ...
    Ответ написан
    Комментировать
  • Что выбрать: Syncthing vs nextCloud vs Seafile vs OwnCloud vs Другой сервис?

    fdroid
    @fdroid
    press any key
    mike153: пробовал все варианты. Nextcloud - это форк Owncloud. По сути, одно и то же, хоть и NC считается более продвинутым и вообще вся опенсорсная тусовка туда ушла. Поэтому пишу о нём. Всё исключительно на правах IMHO. Плюсы:
    - Самый главный - это работа с файлами именно в файловом варианте. То есть, если предположить, что "всё упало", вы можете подключить диск с рухнувшего сервера к любому линуксу и вытащить инфу из /var/www или где она там у вас храниться будет. Также можно подключать внешние хранилища, то есть, предположим, есть у вас на сервере папка с фильмами и музыкой - их можно просто подключить в NC.
    - CardDAV, CalDAV из коробки.
    Минусы:
    - Тормозит всегда, рандомно, в любой момент времени. Независимо от того Apache или Nginx, MySQL или MariaDB, тормозит на любом софте.
    - Интерфейс - УГ, ШГ

    Теперь о Seafile. Плюсы:
    - Турбореактивный просто. Работает очень быстро.
    - Интерфейс очень приятный.
    - Продвинутое версионирование.
    - Умеет открывать docx, odt, xlsx и т.д. без дополнительного софта. Но без редактирования. Если нужно редактирование - нужен отдельный Document Server от Collabora или Onlyoffice.
    - PRO-версия бесплатна для 3-х пользователей, но смысла особого нет, т.к. enterprise-фишки заключаются в 1. полнотекстовому поиску по документам с помощью elasticsearch, у которого просто чудовищное потребление ресурсов 2. двух-факторной авторизации 3. и что-то там ещё, не особо нужное дома
    - Есть клиенты для всех основных платформ
    - Устанавливать можно как вручную по мануалу на сайте, так и воспользовавшись установочным скриптом, который сам всё сделает.
    Минусы:
    - Файлы хранятся в собственном формате, как это правильно называется? - на уровне блоков, что ли. Доступ к инфе только через веб-интерфейс, WebDAV, ну и приложения для синхронизации. То есть, вся информация в Seafile на диске представляет просто кучу мала из папок и файлов, которые нельзя так просто взять и использовать - нужен ещё дамп базы данных. То есть, в случае проблем с системой, достать информацию будет затруднительно. Но выход есть - seaf-cli - это безгуёвый клиент для синхронизации. Смысл в том, что на сервере, на котором крутится Seafile, дополнительно можно установить seaf-cli, натравить его на директорию, и он в эту самую директорию будет складывать синхронизированную копию инфы основной базы Seafile, причём в виде нормальных файлов, которые можно расшаривать как угодно, бэкапить и т.д. Минус решения с seaf-cli в том, что нужно вдвое больше дискового пространства для хранения инфы.
    - Ну и как следствие такой организации файлов - невозможность подключить внешние хранилища, в отличие от тёплого лампового Nextcloud.

    В общем, лично я остановился на Seafile.
    Ответ написан
    Комментировать
  • Как откатиться назад на стабильный commit и при этом сохранить полезный код, который ты сделал после допущенной ошибки?

    На практике редко ошибки правятся "выдиранием" одного коммита из истории, но такая операция вполне себе возможна.
    Вариант номер один - интерактивный ребейз, и в нем указываешь какие коммиты дропнуть. Если коммитов много, то можно задолбаться решать конфликты
    Вариант номер два - просто делаешь новый коммит с реверсом изменений из коммита, который привел к проблемам
    Вариант третий - делаешь новый бранч, откатываешся до проблемного коммита, потом из полного бранча накатываешь остальные изменения.

    Все сценарии приблизительные, потому что каждая проблема требует комплексоного подхода и знания возможностей инструмента, поэтому не поленись, а почитай вот это внимательно и полностью
    https://git-scm.com/book/en/v2
    Ответ написан
    Комментировать
  • Как заигнорить файл .gitignore?

    delphinpro
    @delphinpro
    frontend developer
    Я правильно понимаю, что цель - исключить какие-то файлы, нужные только вам, локально, а про файл .gitignore вы уже сами додумали?

    Мне было бы удобнее всё-таки иметь в проекте файл .gitignore (наверняка он у вас есть).
    Подобные файлы складывать в отдельную папку, которую и добавить в игнор.

    Но если всё же ничего трогать не хочется, то можно использовать глобальный список игнорирования.

    Откройте файл %USERPROFILE%/.gitconfig
    Добавьте строку в секцию core

    [core]
    	excludesfile = C:\\path_to\\.gitignore


    Создайте файл в указанном месте и пропишите там нужное.
    Этот файл будет применяться ко всем репозиториям, открываемым на вашем компьютере.

    Можно использовать консоль, для добавления глобального игнор-списка в конфиг

    git config --global core.excludesFile "%USERPROFILE%\.gitignore"
    Ответ написан
    Комментировать
  • Бот должен отпровлять сообщение в чат когда кто то кликнул на эмоджи, как это сделать?

    SoreMix
    @SoreMix Куратор тега Python
    yellow
    on_reaction_add вызывается только тогд , когда сообщение было отправлено при запущенном боте (грубо)
    https://discordpy.readthedocs.io/en/async/api.html...

    Лучше использовать on_raw_reaction_add
    https://discordpy.readthedocs.io/en/latest/api.htm...
    В случае с on_raw_reaction_add(payload) id канала лежит в payload.channel_id

    Ну и подобное условие вряд ли сработает, пытаетесь сравнить объект класса Channel с числом. Если сравниваете id - то сравнивайте ID, не нужно получить канал в таком случае
    Ответ написан
    2 комментария
  • Apache и кириллица?

    nowm
    @nowm
    Судя по скриншоту в комментариях к вопросу, у вас файл в кодировке UTF-8.

    В Apache

    Первый способ: в файле httpd.conf самого апача, либо в файле .htaccess, который находится в той же папке, что и HTML-файл (если его там нет, то создайте) можно прописать такую директиву:

    AddDefaultCharset utf-8

    Или так (если кодировку нужно устанавливать только для HTML-файлов):

    AddCharset utf-8 .html

    В HTML

    Второй способ: в самом HTML-файле в блоке <head> можно добавить тег, который скажет браузеру, что это UTF-8.

    <meta charset="UTF-8"/>
    Ответ написан
    Комментировать
  • Как отменить два последних комита без потери локальных изменений?

    Можно ещё просто объединить эти комиты через rebase:
    git rebase -i HEAD~2

    И пометить один из комитов на squash.
    В данном случае это ничем не лучше чем reset --soft, просто более гибкий инструмент.
    Ответ написан
    Комментировать