И калькуляторы тут не причем, я вам привел пример наиболее распространенного разрешения на ноутбуках. И большинство ноутов старых моделей именно с таким разрешением. И именно 80 символов позволяют на таком разрешении делать 2 колоночный просмотр кода без переноса строк. И это одна из причин такого выбора
Ну с таким подходом непонятно, почему все должны под вас подстраиваться) А почему не взять тогда уж все 320 символов? И больше ж кода то влезет на экран и будет стимул всем мониторы обновить. Я вам так скажу. Есть рекомендации (например, pep8 в Python), которые не с потолка взяты, а следовать им или нет — ваше личное дело. В команде, как правило, code conventions принимают либо на базе общепринятых рекомендаций, либо на базе мнения большинства. Если в вашем случае большинству удобнее со 120 символами — ради бога. А в статье приводятся общепринятые рекомендации, а следовать им или нет — каждый сам решает
Коллеги с экранами ноутбуков 1280x800 (стандарт на ноутах старых моделей) скажут вам "спасибо" за 120 и более символов. Потому что 80 символов позволяют открыть два файла с кодом на таком экране и ничего не будет переноситься)
В языках с динамической типизацией одна и та же переменная может иметь разный тип, в результате ошибки или явно, но это факт и от наверного типа никто не застрахован. Более того, есть такое понятие, как duck typing, так что тут больше по интерфейсу матчинг, а не по типу объекта. Ну и Null, None, null, undefined и так далее никто не отменял, их как минимум нужно проверять.
А ещё если вы пишете библиотечную функцию и есть внешний клиентский код, который может передать в нее все, что угодно, проверки входных параметров все же стоит делать)
В статье имеется ввиду преждевременная оптимизация производительности. Это писать код сначала понятно и просто, не заморачиваясь на оптимизации, просто потому, что код ещё несколько раз может поменяться. И вот когда код уже написан, он работает, покрыт тестами и выполняет задачу, для который написан, профилирование показало, что этот код работает медленно, вот только тогда стоит браться за оптимизацию. Да и то, тут ещё стоит рассмотреть систему в целом, а то может у вас больше тормоза даёт I/O, недели ваш код, и даже его оптимизация не даст ощутимого прироста.
Почитал про push_back, время вставки — константа, в общем случае, ну и на выделение памяти ещё время может потребоваться. Сложность вставки в вектор зависит от того, куда вставляем, если я правильно понял подвох) Или вы про то, что время отработки цикла не имеет ничего общего с единичной вставкой в вектор?
Ну я в геймдеве проработал 4 с половиной года, и у меня другой опыт) Все стабильно, и ЗП по рынку, и выплачивали вовремя и переработок было не больше, чем в других местах) Компании видимо разные и менеджмент соотв-но тоже. Так что не все так однозначно.
Я думаю, что все намного проще. Пиратство тут не причем, скорее, необходимость пощупать почву, потому что нужен фидбэк от живых людей сразу после игры. Ну и дома не у каждого есть шлем)
А про ЗП и рабочий день, всегда можно сменить работу, если что-то не устраивает)
В данный момент a хранит ссылку на 1 и b хранит ссылку на 1. Дальше Вы в a присваиваете ссылку на 2. Но в b так и осталась ссылка на 1.
Ваша правда. Напутал все на свете) Мутабельность объекта перепутал с иммутабельностью строк и чисел) Ну вроде того
let a = {"k": 1};
let b = a;
a["k"] = 2;
b["k"] == 2; // true
Вечер пятницы) Голова уж плохо соображает, прошу прощения)
Как вы и указали, это просто синтаксический сахар, поэтому ожидать от него поведения, отличающегося от оригинала "без сахара" глупо. Это все объясняет. Мне почему-то сначала показалось, что новую возможность завезли.
Ну хорошо, перепишу пример, чтобы было понятно, что это именно ПЕРЕМЕННАЯ, а не значение именно 1, которые вы пишете) Вот так понятнее?
let a = $input.val();
let fn = function (c = a) {
return c + 1;
}
И вы кстати так и решили поставленную задачу)
В примере выше функция всегда будет выдавать разное значение при изменении переменной a. Если бы присвоение аргументу значения по умолчанию выполнялось единожды при создании функции, то этой проблемы бы не было) Но оно через замыкание выполняется каждый раз при вызове фукнции. Впрочем, выше уже написали, что это синтаксический сахар, а не новая конструкция языка. А я уж думал...
В js все объекты передаются по ссылке вне зависимости от сложности.
Если бы было так, как вы написали, то было бы так
let a = 1;
let b = a;
a = 2;
b == 2; // true
однако, оно не так) Потому что это присвоение по значению и работает оно только для объектов простых типов. Для сложных типа array, object передается по ссылке. Хотя, мне кажется, это вам итак известно, и почему вы такую чушь написали, для меня загадка.
Что? Как можно взять значение из a, не обратившись к нему?
Я разве вам предлагал не обращаться к нему? Если я такое написал, позор мне, ткните меня пальцем в мой же текст)
Эм, вообще-то аргументы по умолчанию — это просто синтаксический сахар.
Ааа, ну вот сразу бы так и написали, что это обычный синтаксический сахар для костылей, а не нормальное определение значений по умолчанию, как в других языках. Тогда вопрос закрыт)
Задача сделать чистую функцию fn, чтобы она взяла значение из 'a' и использовала его всегда в дальнейшем, независимо от дальнейшего изменения 'а', то есть не зависела от внешнего контекста. Внимание, нужно именно первоначальное значение из 'а', потому что функция должна быть чистая, то есть независимо от внешнего контекста всегда возвращать один и то же результат при одинаковых входных параметрах. Иначе функция подвержена сайд эффекту из контекста выше, а нам это не нужно по задаче.
let a = 1;
let fn = function (c = a) {
return c + 1;
}
fn() == 1;
a = 10;
fn() == 11;
Представьте, что значение в 'а' нам не известно на этапе написания кода, что вполне логично, это ж переменная.
Потому что в качестве значения по умолчанию может передаваться массив или объект, и если он будет тем же самым, это совсем не то, что ожидает программист.
Вот тут не совсем я вас понял. Разве в JS все сложные объекты передаются не по ссылке? То есть при указании объекта в качестве параметра по умолчанию это будет один и тот же объект в любом случае. Ну просто потому, что сложные объекты иначе не передаются, только по ссылке. А теперь это поведение добавлено еще и для простых типов в качестве значений по умолчанию (через замыкание, как вы и написали ниже).
Ну а если нужны те же самые, никто не мешает сохранить во внешнюю переменную.
Можете привести пример кода. Не совсем понятно, кусочек кода многое бы прояснил) Спасибо
А те минусы, которые Вы привели — это просто от плохого знания замыканий.
Я представляю, как работают замыкания) Но есть подход, когда замыкание используется явно, то есть
let a = 1;
let fn = function () {
let c = a + 1;
}
тут программист явно говорит "дай мне переменную из области видимости вне функции" и иначе как через замыкание это не решается. А в случае аргументов по умолчанию у программиста нет выбора. Если ему хочется передать именно значение из переменной как значение аргумента по умолчанию, а не как ссылку на объект из внешней области, то ему придется писать костыли типа
let a = 1;
let independentA = a;
let fn = function (k = independentA) {
...
}
А взять именно значение из 'a', не привязываясь к 'a' по ссылке никак по-другому нельзя без копирования значения в отдельную переменную и уже использование ее в качестве значения по умолчанию.
Если вы напишете код, которые берет именно значение из 'а', при этом не привязываясь к самой ссылке 'a', я буду вам благодарен.
Ну и если Вы боитесь, что значение переменной может измениться, слово const вместо let тоже никто не отменял.
Я правильно понимаю, что чтобы задать именно значение по умолчанию для аргумента, вы предлагаете скопировать значение из переменной в константу и уже эту константу использовать в качестве значения по умолчанию?) Что-то вроде этого?
const argA = a;
fn = function (b = argA) {
...
}
В Python это без всяких костылей делается
a = 1
def fn(b = a):
return b
fn() == 1
a = 10
fn() == 1
и без всяких временных констант. Если мне нужно привязаться к переменной в области выше, именно привязаться, то это тоже делается через замыкание, но явно
a = 1
def fn(b = None):
if b is None:
b = a
return b
fn() == 1
a = 10
fn() == 10
Да, вы правы. Все выражение вычисляется каждый раз по-новому, а не только при создании функции. Мне почему-то казалось, что это делается только для функций. Вот такая конструкция работает ожидаемо
let a = 1;
let b = 2;
let fn = (c = a + b) => c;
fn() == 3
a = 2
fn() == 4
Но у такого подхода есть и обратная сторона. Переменные, которые использовались в качестве значений по умолчанию для аргументов, далее в коде менять нужно с большой осторожностью (если вообще стоит это делать), иначе при следующем вызове функции результат вычисления может быть совсем не тот, что ожидается. Другими словами,
let a = 1;
let b = 2;
let argA = a; // только так безопасно далее менять a
let fn = (c = argA + b) => c;
...
a = 2; // не скажется на результате вычисления функции
Выглядит, как костыль. Ну, а с вложенными функциями вообще беда получается
let fn = function (c = a + b) {
let fn1 = (k = c + a) => k;
... // тут мы что-то могли сделать с 'c'
return fn1();
}
... // ну и тут мы что-то могли сделать с 'a' и 'b' дополнительно
Что в итоге получится, никому не известно.
Как мне кажется, было бы удобнее и очевиднее, если бы значение вычислялось единожды при создании функции. А если нужна динамика, просто передаете в качестве аргумента функцию, указывая ее с новым синтаксисом, типа
let argFn = () => 1;
let fn = (c = @argA) => c;
или разделить выполнение сразу и на каждый вызов, типа
let fn = (c = a + b) => c; // сразу
let fn = (c = {a + b}) => c; // на каждый вызов
Это примеры, синтаксис можно придумать любой. Основная суть в том, чтобы добавить гибкости. Но все вышеперечисленное — это конечно, ИМХО.
Я про то, что поведение в данном контексте совсем неочевидно. В данном случае каждая функция, привязанная к аргументу как значение по умолчанию, выполняется каждый раз (или один раз?) при необходимости посчитать значение по умолчанию для аргумента, а не единожды в момент создания искомой функции с этими аргументами. И если в любом другом контексте выражение имя_функции() имеет однозначную трактовку, а именно исполнение кода этой функции сразу, как только интерпретатор добирается до этого места в коде, то в данном контексте оно так не работает.
Вдвойне запутывает ситуация, когда надо вычислить значения аргументов сразу при инициализации функции. Предположу, что это делается как-то так
const required = (p1, p2) => {...};
defaultA = required(v1, v2);
defaultB = required(v3, v4);
const add = (a = defaultA, b = defaultB) => a + b;
Но почему не тем синтаксисом, что описан в статье? Казалось бы, это же поведение конструкции по умолчанию.
По сути тут меняется поведение базовой конструкции в зависимости от контекста, что-то типа "оно работает так, но вот в этом конкретном случае — по-другому". Это ведёт к тому, что вам нужно ещё и контекст контролировать, что добавляет дополнительную бессмысленную сложность при чтении кода. И это при том, что во всех остальных языках, в которых такая конструкция именно вызывает функцию, это поведение соблюдается везде, независимо от контекста. И нет никакой двоякой трактовки, конструкция везде работает одинаково — выполняет функцию в том месте, где встречается это выражение.
Почему например, нельзя было придумать новый синтаксис для выполнения функции в контексте аргументов по умолчанию? Такое же уже делали (arrow functions, например). Тогда бы каждая конструкция однозначно трактовалась независимо от контекста. Как пример,
const required = () => {...};
const add = (a = @required, b = @required) => a + b;
И кстати, я не припомню больше таких конструкций в языке, которые так кардинально меняют свое поведение в зависимости от контекста, в котором выполняются.
Доки доками конечно, но когда одна и та же конструкция работает в разных контекстах по-разному — не очень хороший подход, как мне кажется. Просто потому, что это действительно запутывает. Ожидается одно поведение, а на практике оно другое, только из-за того, что контекст другой. По мне, лучше такие вещи не использовать, чтобы не запутывать ни себя, ни коллег, которые потом в таком коде будут разбираться.
И калькуляторы тут не причем, я вам привел пример наиболее распространенного разрешения на ноутбуках. И большинство ноутов старых моделей именно с таким разрешением. И именно 80 символов позволяют на таком разрешении делать 2 колоночный просмотр кода без переноса строк. И это одна из причин такого выбора
Ну с таким подходом непонятно, почему все должны под вас подстраиваться) А почему не взять тогда уж все 320 символов? И больше ж кода то влезет на экран и будет стимул всем мониторы обновить. Я вам так скажу. Есть рекомендации (например, pep8 в Python), которые не с потолка взяты, а следовать им или нет — ваше личное дело. В команде, как правило, code conventions принимают либо на базе общепринятых рекомендаций, либо на базе мнения большинства. Если в вашем случае большинству удобнее со 120 символами — ради бога. А в статье приводятся общепринятые рекомендации, а следовать им или нет — каждый сам решает
Правильно пишете. Это должно быть привычкой и на уровне автоматизма. А ещё проверяться линтерами)
Коллеги с экранами ноутбуков 1280x800 (стандарт на ноутах старых моделей) скажут вам "спасибо" за 120 и более символов. Потому что 80 символов позволяют открыть два файла с кодом на таком экране и ничего не будет переноситься)
В языках с динамической типизацией одна и та же переменная может иметь разный тип, в результате ошибки или явно, но это факт и от наверного типа никто не застрахован. Более того, есть такое понятие, как duck typing, так что тут больше по интерфейсу матчинг, а не по типу объекта. Ну и Null, None, null, undefined и так далее никто не отменял, их как минимум нужно проверять.
А ещё если вы пишете библиотечную функцию и есть внешний клиентский код, который может передать в нее все, что угодно, проверки входных параметров все же стоит делать)
В статье имеется ввиду преждевременная оптимизация производительности. Это писать код сначала понятно и просто, не заморачиваясь на оптимизации, просто потому, что код ещё несколько раз может поменяться. И вот когда код уже написан, он работает, покрыт тестами и выполняет задачу, для который написан, профилирование показало, что этот код работает медленно, вот только тогда стоит браться за оптимизацию. Да и то, тут ещё стоит рассмотреть систему в целом, а то может у вас больше тормоза даёт I/O, недели ваш код, и даже его оптимизация не даст ощутимого прироста.
Более того, не у всех десктоп с большим монитором и экран ноутбука с высоким разрешением)
Можете расшифровать, что такое DM и DoE для тех, кто не в теме?
Я думаю, что автор статьи следовал общепринятой практике в оформлении коммитов. Хорошо это описано тут https://chris.beams.io/posts/git-commit/.
Я думаю, что все намного проще. Пиратство тут не причем, скорее, необходимость пощупать почву, потому что нужен фидбэк от живых людей сразу после игры. Ну и дома не у каждого есть шлем)
А про ЗП и рабочий день, всегда можно сменить работу, если что-то не устраивает)
Ваша правда. Напутал все на свете) Мутабельность объекта перепутал с иммутабельностью строк и чисел) Ну вроде того
Вечер пятницы) Голова уж плохо соображает, прошу прощения)
Как вы и указали, это просто синтаксический сахар, поэтому ожидать от него поведения, отличающегося от оригинала "без сахара" глупо. Это все объясняет. Мне почему-то сначала показалось, что новую возможность завезли.
Ну хорошо, перепишу пример, чтобы было понятно, что это именно ПЕРЕМЕННАЯ, а не значение именно 1, которые вы пишете) Вот так понятнее?
И вы кстати так и решили поставленную задачу)
В примере выше функция всегда будет выдавать разное значение при изменении переменной a. Если бы присвоение аргументу значения по умолчанию выполнялось единожды при создании функции, то этой проблемы бы не было) Но оно через замыкание выполняется каждый раз при вызове фукнции. Впрочем, выше уже написали, что это синтаксический сахар, а не новая конструкция языка. А я уж думал...
Если бы было так, как вы написали, то было бы так
однако, оно не так) Потому что это присвоение по значению и работает оно только для объектов простых типов. Для сложных типа array, object передается по ссылке. Хотя, мне кажется, это вам итак известно, и почему вы такую чушь написали, для меня загадка.
Я разве вам предлагал не обращаться к нему? Если я такое написал, позор мне, ткните меня пальцем в мой же текст)
Ааа, ну вот сразу бы так и написали, что это обычный синтаксический сахар для костылей, а не нормальное определение значений по умолчанию, как в других языках. Тогда вопрос закрыт)
Задача сделать чистую функцию fn, чтобы она взяла значение из 'a' и использовала его всегда в дальнейшем, независимо от дальнейшего изменения 'а', то есть не зависела от внешнего контекста. Внимание, нужно именно первоначальное значение из 'а', потому что функция должна быть чистая, то есть независимо от внешнего контекста всегда возвращать один и то же результат при одинаковых входных параметрах. Иначе функция подвержена сайд эффекту из контекста выше, а нам это не нужно по задаче.
Представьте, что значение в 'а' нам не известно на этапе написания кода, что вполне логично, это ж переменная.
Вот тут не совсем я вас понял. Разве в JS все сложные объекты передаются не по ссылке? То есть при указании объекта в качестве параметра по умолчанию это будет один и тот же объект в любом случае. Ну просто потому, что сложные объекты иначе не передаются, только по ссылке. А теперь это поведение добавлено еще и для простых типов в качестве значений по умолчанию (через замыкание, как вы и написали ниже).
Можете привести пример кода. Не совсем понятно, кусочек кода многое бы прояснил) Спасибо
Я представляю, как работают замыкания) Но есть подход, когда замыкание используется явно, то есть
тут программист явно говорит "дай мне переменную из области видимости вне функции" и иначе как через замыкание это не решается. А в случае аргументов по умолчанию у программиста нет выбора. Если ему хочется передать именно значение из переменной как значение аргумента по умолчанию, а не как ссылку на объект из внешней области, то ему придется писать костыли типа
А взять именно значение из 'a', не привязываясь к 'a' по ссылке никак по-другому нельзя без копирования значения в отдельную переменную и уже использование ее в качестве значения по умолчанию.
Если вы напишете код, которые берет именно значение из 'а', при этом не привязываясь к самой ссылке 'a', я буду вам благодарен.
Я правильно понимаю, что чтобы задать именно значение по умолчанию для аргумента, вы предлагаете скопировать значение из переменной в константу и уже эту константу использовать в качестве значения по умолчанию?) Что-то вроде этого?
В Python это без всяких костылей делается
и без всяких временных констант. Если мне нужно привязаться к переменной в области выше, именно привязаться, то это тоже делается через замыкание, но явно
Да, вы правы. Все выражение вычисляется каждый раз по-новому, а не только при создании функции. Мне почему-то казалось, что это делается только для функций. Вот такая конструкция работает ожидаемо
Но у такого подхода есть и обратная сторона. Переменные, которые использовались в качестве значений по умолчанию для аргументов, далее в коде менять нужно с большой осторожностью (если вообще стоит это делать), иначе при следующем вызове функции результат вычисления может быть совсем не тот, что ожидается. Другими словами,
Выглядит, как костыль. Ну, а с вложенными функциями вообще беда получается
Что в итоге получится, никому не известно.
Как мне кажется, было бы удобнее и очевиднее, если бы значение вычислялось единожды при создании функции. А если нужна динамика, просто передаете в качестве аргумента функцию, указывая ее с новым синтаксисом, типа
или разделить выполнение сразу и на каждый вызов, типа
Это примеры, синтаксис можно придумать любой. Основная суть в том, чтобы добавить гибкости. Но все вышеперечисленное — это конечно, ИМХО.
Я про то, что поведение в данном контексте совсем неочевидно. В данном случае каждая функция, привязанная к аргументу как значение по умолчанию, выполняется каждый раз (или один раз?) при необходимости посчитать значение по умолчанию для аргумента, а не единожды в момент создания искомой функции с этими аргументами. И если в любом другом контексте выражение имя_функции() имеет однозначную трактовку, а именно исполнение кода этой функции сразу, как только интерпретатор добирается до этого места в коде, то в данном контексте оно так не работает.
Вдвойне запутывает ситуация, когда надо вычислить значения аргументов сразу при инициализации функции. Предположу, что это делается как-то так
Но почему не тем синтаксисом, что описан в статье? Казалось бы, это же поведение конструкции по умолчанию.
По сути тут меняется поведение базовой конструкции в зависимости от контекста, что-то типа "оно работает так, но вот в этом конкретном случае — по-другому". Это ведёт к тому, что вам нужно ещё и контекст контролировать, что добавляет дополнительную бессмысленную сложность при чтении кода. И это при том, что во всех остальных языках, в которых такая конструкция именно вызывает функцию, это поведение соблюдается везде, независимо от контекста. И нет никакой двоякой трактовки, конструкция везде работает одинаково — выполняет функцию в том месте, где встречается это выражение.
Почему например, нельзя было придумать новый синтаксис для выполнения функции в контексте аргументов по умолчанию? Такое же уже делали (arrow functions, например). Тогда бы каждая конструкция однозначно трактовалась независимо от контекста. Как пример,
И кстати, я не припомню больше таких конструкций в языке, которые так кардинально меняют свое поведение в зависимости от контекста, в котором выполняются.