Как стать автором
Обновить
32
0

Пользователь

Отправить сообщение

А вы хотите с него слезть или нет?

Вот, кстати, ещё один вопрос для собеседования, если у вас его нет. «В чём разница кооперативной и вытесняющей многозадачности? Какая стратегия используется в go?». И если кандидат ответит, то можно дополнительно спросить: «Как в go реализуется вытесняющая многозадачность?».
$result = 0;
for ($v = 1; $v < 3; $v++)
    $result += $v * 2;


И чем это лучше чем

$result = 6;


Вообще ничем, лишний for, ++ и *, и компактнее код совсем не стал. Нафига козе боян. Простой и понятный язык превращают непонятно во что, только потому что модно, и в других языках есть.
Ладно, вот ваш же пример, но без вызова:

fn call<F>(_a: i64, _b: i64, _c: F) -> i64
where
    F: Fn(i64) -> i64,
{
    42
}

fn main() {
    let example_fn = |a| a;
    println!("{}", call(10, 10, example_fn));

    println!("{}", example_fn(String::from("hello"))); // ошибка
}


Вызова нет? Нет. Тип example_fn определён? Определён. Выводом типов, ровно из-за того, что мы передаём example_fn в функцию call с явной сигнатурой.

Запускаем. Компилятор нам любезно сообщает об ошибке о несоотвествии типов, он же в example_fn ожиадет получать i64, а мы ему String подсовываем:

error[E0308]: mismatched types
  --> src/main.rs:12:31
   |
12 |     println!("{}", example_fn(String::from("hello"))); // ошибка
   |                               ^^^^^^^^^^^^^^^^^^^^^ expected i64, found struct `std::string::String`
   |
   = note: expected type `i64`
              found type `std::string::String`


И прошу заметить что вызова с i64 не было, но он уже требует i64!
> Сейчас я еще больше запутался, чем тогда это отличается от Go?

На расте этот случай будет описан так.

fn main() {
    let example_fn = |x: String| -> String { x };
    println!("{}", example_fn("hello".into()));

    let example_fn2 = |x: i64| -> i64 { x };
    println!("{}", example_fn2(10));
}

Тут вывод типа у переменных example_fn, example_fn2. Это равносильно примеру го.

В примере выше вывод типа происходит у аргумента замыкания. В примере с функцией call, так же вывод типа происходит у аргумента замыкания за счёт того, что в сигнатуре функции явно указан тип аргумента замыкания.
Вот пример того, о чём я написал:

fn main() {
    let example_fn: &Fn(String) -> String = &|a| a;
    // example_fn Принимает только String
    println!("{}", example_fn("Hello, world!".into()));

    let example_fn2: &Fn(i64) -> i64 = &|a| a;
    // example_fn2 Принимает только i64
    println!("{}", example_fn2(64));
}

Конечно, если не указывать тип у переменной example_fn, то типы в замыкании будут выведены из его аргументов.

Чтобы ваш пример соответствовал моему, надо у переменной example_fn указать конкретный тип, тогда типы аргументов замыкания будут выведены из типа переменной и если при первом использовании замыкания передать ему в качестве аргумента неправильный тип, то компилятор выдаст ошибку.

Ваш пример не равнозначен моему. В моём примере типы аргументов замыкания выводятся из сигнатуры функции call, потому что там явно указаны типы, в вашем примере — при первом использовании, потому что у вас не указан тип переменной, которая владеет замыканием, и её тип так же выводится впоследствии.

Надеюсь понятно объяснил.
> UPD: хотя да, это вывод типа анонимной функции, но не потому что в аргументе c функции call указаны все необходимые типы для колбэка.

А почему?
Вы правда не видите разницу между фразами недоволен и не нравится?

Давайте тогда на примере, где нет go.

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

Так понятнее? Или вы напишете, что мне не нравится ездить на метро?

И если вернуться к go, то я недоволен языком go, но абсолютно спокойно отношусь к тому, чтобы что-то на нём сделать.
Как я понял, программирование на Go является частью вашей работы, если вам это не нравится (программировать на Go) — то вам не нравится ваша работа. Или вам нравится программировать на Go?

Я же написал что недоволен языком go, а не то что мне не нравится программировать на go.

Если появится задача для которой go будет подходящим решением, то я спокойно буду использовать его без нравится/не нравится.
Я разве написал что мне что-то не нравится на работе? Работой полностью доволен. А вот чем недоволен — написал в первом предложении.

> Почитайте посты про Go на хабре
Дайте, пожалуйста, ссылки на посты которые мне необходимо почитать.
> Остается непонятным почему недовольные люди о нем читают, почему недовольные люди на нем пишут? Но больше всего удивляет агрессивность Расто-поклонников, они просто адски ненавидят Го, хотя казалось бы пишите на чем нравится…

Я недоволен языком go. Пишу на нём потому что он используется на работе и у него есть объективные преимущества перед другими языками… и являюсь неагрессивным расто-поклонником. Кстати, по ощущениям, как-раз go-поклонники более агрессивны :P
> строгая статическая типизация с выводом типов

Честно, вывод типов в go достаточно слабый.

Простейший пример на go.
Простейший пример на rust.

В аргументе c функции call указаны все необходимые типы для колбэка. При этом, в коде на go всё равно приходится их указывать, тогда как в коде на rust в этом уже нет необходимости.
> Дедлоки в принципе возможны везде, где есть асинхронность, и в Go, в отличие от многих других экосистем, есть рейс-детектор в поставке по-умолчанию и отладка таких вещей намного проще, чем не в Go.

Не везде. Например в pony нет дедлоков за счёт специальных аннотаций типов.
> Зачем перереписали на Go?
> — Нуууу не будем нанимать Java программеров.

В самом начале они сказали что в Авито используются три языка: php, python, go. Java нет в этом списке, соответственно, компетенций мало и не хочется ещё один язык тащить только ради одного сервиса, лучше переписать его на то, с чем умеют работать в компании.
Получился бы отличный пост на первое апреля.
Спасибо! Не читал все комментарии, поэтому мои вопросы могут повторять то, что уже было выше.

Вместо лишней конкатенации используем подстановку переменных в двойных кавычках
Хорошо:
$string = «Object with type \»{$object->type()}\" has been removed";


Такой вариант у вас не приемлим?

$string = sprintf('Object with type "%s" has been removed', $object->type());


Методы и свойства в классе должны быть отсортированы по уровням видимости и по порядку использования сверху вниз

Это правило противоречит
Последовательным. Код должен читаться сверху вниз. Читающий не должен держать что-то в уме, возвращаться назад и интерпретировать код иначе.


public-методы обычно вызывают private/protected методы и соотвественно, код уже нельзя будет читать сверху вниз.

И тоже самое про абстрактные классы: мне кажется хорошо, когда абстрактные методы выносятся в самое начало класса (независимо от их области), до всех объявлений. Таким образом, сразу понимаешь что должен реализовать наследник и что будут вызывать public-методы этого абстрактного класса. Иначе, если абстрактный метод protected, то он уедет вниз после всех public-методов, что порой заставляет скакать по коду, чтобы понять абстрактное или нет вызывается из паблика.

Я бы ещё добавил правило про наследование:
наследование должно происходить только от абстрактного, каждый конкретный класс должен быть финальным.

Порой хорошо помогает понять что если хочешь поменять часть логики конкретного класса, то надо это делать не через наследование, а через композицию или вынесение общего куска в абстрактный класс.
За get есть устоявшийся смысл, что он получает именно некое состояние объекта. Если методы сервиса откуда-то получают данные, то лучше их называть начиная с fetch, чтобы не путаться.
1

Информация

В рейтинге
Не участвует
Работает в
Зарегистрирован
Активность