главная новое лучшее написать
7

Лишь спустя 20+ лет опыта я осознал, что всё это время писал неправильный hello-world.
А вот правильно будет как-то так:

#include <iostream>

int main() {
    std::cout << "Hello, World!" << std::endl;
    return std::cout ? 0 : 1;
}

Пояснения на ангельском

UPD: Как указал finder есть ещё такой вариант

#include <iostream>

int main() {
    std::cout.exceptions(std::cout.badbit);
    std::cout << "Hello, World!" << std::endl;
    return EXIT_SUCCESS;
}

3 finder 02-02-2024

Вот это мощь :)
Ситуация напоминает std::bad_alloc, с которым вообще совсем полностью непонятно, что делать, мозг взрывается.

ответить
2 1e9y 02-02-2024

Дякую тобі, Боже, що я не сишник!

ответить
1 finder 02-02-2024

Не, это не про си. Там внизу по ссылке табличка. В Nodejs, Java, Ruby и Haskell (лол) такой же баг. В третьем питоне его исправили, во втором был.

ответить
1 heni 02-02-2024

В go, кстати, та же фигня

heni@Eugene-XPS-13:~/tests/hello$ cat hello.go 
package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}
heni@Eugene-XPS-13:~/tests/hello$ go build hello.go
heni@Eugene-XPS-13:~/tests/hello$ ./hello >/dev/full ; echo $?
0

И исправление не лучше выглядит, чем в плюсах

heni@Eugene-XPS-13:~/tests/hello$ cat hello-fix.go 
package main

import "fmt"

func main() {
    if _, err := fmt.Println("Hello, World!"); err != nil {
        panic(err)
    }
}
heni@Eugene-XPS-13:~/tests/hello$ go build hello-fix.go 
heni@Eugene-XPS-13:~/tests/hello$ ./hello-fix >/dev/full; echo $?
panic: write /dev/stdout: no space left on device

goroutine 1 [running]:
main.main()
    /home/heni/tests/hello/hello-fix.go:7 +0x68
2
ответить
1 anonymous 02-02-2024

Учи плюсы, говорили они, удобно писать на них всякое, говорили они, в UB нет ничего страшного, говорили они, плюсы не топ-1 причина багов, говорили они

ответить
1 finder 02-02-2024

Нет, правда, а как так? Я еще чуть почитал вокруг и конкретно в плюсах это выглядит буквально как бага проектирования стандартной библиотеки: std::cout по умолчанию настроен так, что при рядовых ошибках не кидает исключений. При этом переключатель "кидать или нет" все равно существует, почему его по умолчанию не поставить в безопасное положение-то.

ответить
1 heni 02-02-2024

Ну здесь, то как раз понятно (читай как "очевидно для меня")
Настройки "по умолчанию" выкручены в производительность: проверять ошибки можно через bool cast и это ответственность разработчика

Уносить же все на уровень exception'ов - просто дорогое с точки зрения производительности решение, которое в коммитете никогда не пройдёт как решение "по умолчанию".

ответить
1 finder 02-02-2024

Помимо того, что эта логика в 2024 слегка сомнительна в целом, я еще и не понимаю, как она здесь помогает.
Ладно бы std::cout не кидался эксепшнами никогда, это было бы понятно. Так ведь нет, он ведет себя следующим образом:

  • встретили ошибку
  • в рантайме проверили, установлен ли у нас флаг "кидаться эксепшнами при этой ошибке"
  • если не установлен, записали себе, что мы в broken state, иначе кинули

Тут, кажется, никакой экономии не возникает. Я чего-то не понимаю?

ответить
1 heni 02-02-2024

Я скорее про то, что проверка ошибок через exception'ы - антипаттерн в C++, от того и растут корни проблемы.

В питоне - нормальное явление использовать конструкцию try ... except для проверки ошибок, - и потому в этом мире смогли позволить себе нормальное решение внедрить.

ответить
1 heni 02-02-2024

Но, в питон мире, с ответственным проектированием тоже так себе дела обстоят.
У меня вот, например, не получилось убедить сообщество в том, что согласно PEP'ам должно быть

(None | None) == None

а не runtime-исключение, как сейчас - см. issue

ответить
1 finder 02-02-2024

Это оффтоп, но я с ними, скорее, согласен. None более фундаментальная часть языка, чем typing hints. Вполне верится, что от изменившегося поведения None | None какой-нибудь легаси код может сломаться, особенно с учетом всяких возможных приколов с reflection типа '__or__' in dir(x)

Оффтоп^2: консистентности тут тоже, конечно, никакой, например, в dir(None) есть '__lt__', и я не смог быстро понять или нагуглить, зачем

ответить
2 heni 02-02-2024

Я бы принял твою точку зрения, если бы гвидо в PEP'e про систему типов NoneType вместо None исходно ввёл. Тогда всё легко бы встало на свои места.
Но Гвидо решил пойти на шаг:

When used in a type hint, the expression None is considered equivalent to type(None)

не задумываясь о том, что невозможно разделить type hint context от всего остального ;)

ответить
2 finder 02-02-2024

Так это Гвидо просто лажанулся, значит. type(x) = x, хмммм, что же может пойти не так, давайте спросим у Кантора, что ли.

ответить
1 asandler2 02-02-2024

Мацумото тоже лажанулся?

irb(main):001:0> Class.class
=> Class
irb(main):002:0> Class.class == Class
=> true

ответить
1 finder 02-02-2024

Сильно подозреваю, что да, но сам не могу сказать, в каких случаях это должно навернуться (не писал на Руби и не знаю, что там позволяет рефлекшн и зачем используется).

ответить
1 asandler2 02-02-2024

А что ответил бы господин Кантор, в чём тут будет проблема? Есть объекты и есть типы, почему объект не может иметь тип "тип"? Это же не множество, являющееся своим собственным элементом

ответить
1 heni 02-02-2024

Конкретно в случае предложения Гвидо более очевидноe противоречие существует.

type(type(X)) = type
type(None) = None
type = type(type(None)) = type(None) = None

ответить
1 asandler2 05-02-2024

А, ну да, невнимательно читал тред выше. Если с None такое выполнено, то плохо. Мацумото тут, кстати, не лажанулся:
irb(main):001:0> nil.class
=> NilClass
irb(main):002:0> NilClass.class
=> Class

ответить