LINUX.ORG.RU

Си с классами

 , ,


0

7

Тупнячка принёс, извиняйте.

Начинаю проект (личный), выбираю на чём писать: C или C++.

Ситуация такая: с плюсами возиться не хочется, да и не знаю я их толком, учил ещё в школе, до сих пор не выучил, но и на чистой сишечке, с другой стороны, писать как-то лениво.

Хотелось бы какой-то сабсет C++ или суперсет над C. Чтобы библиотеки плюсовые можно было при необходимости заюзать, класс-другой написать, а то и во все тяжкие пуститься, обмазавшись строками. Но без хардкорного плюсового упорина от которого у одних глаза с первого взгляда вытекают, а другие в дурке после прочтения оказываются.

Насколько такой суперсет C / сабсет C++ ака «Си с классами» может быть кошерен?

Объясните почему так делать не стоит, либо даже наоборот, предложите уже существующие сабсеты плюсов, которые можно перенять.

Ответ на: комментарий от eao197

Просто «за державу обидно», когда всезнайки несут чушь про вывод типов, а сами даже хелловорлд не осилили.

anonymous
()
Ответ на: комментарий от anonymous

let func1 x = x*x + 3
let i = func1 1
// после func1 - это функция принимающая только целый тип
// эта строка не скомпилируется, так как передается float
let f = func1 1.1 // error

func1 становится a'->int еще раньше, при своем определении:

let func1 x = x*x + 3
let f = func1 1.1 // Тип "int" не совпадает с типом "float"
byko3y ★★★★
()
Ответ на: комментарий от eao197

Примеры из вас клещами вытягивать нужно или вы в очередной раз тупо звиздите?

Я тебе давал линк на огромный модуль с кучей функций. И ты даже прошел по ссылке, судя по всему. Но все равно тебе «не то»?

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Я тебе давал линк на огромный модуль с кучей функций.

И я у вас спрашивал, на что там смотреть.

Походу, для вас, как уже было сказано, «уровень» определяется только необходимостью декларации типов.

Вот для этого утверждения – «компилятор позволяет автоматизировать те вещи, которые в более примитивном языке не автоматизировались» – какие-то примеры привести можете?

eao197 ★★★★★
()
Ответ на: комментарий от byko3y

func1 становится a’->int еще раньше, при своем определении:

Да, не уследил за вами, экспертами вывода типов. + 3 и запрет неявных кастов выводит конкретный тип уже при определении.

См. Си с классами (комментарий)

anonymous
()
Ответ на: комментарий от byko3y

Нет. ТС спросил, я ответил. Тред не читал, поскольку плюсами не интересуюсь и, соответственно, дискутировать на эту тему не собираюсь.

Там, по ссылкам, есть и конкретно, и по тезисам. А уж годится ли ему «си с классами», которые предлагает Столяров, это ТС пусть сам решает.

aeralahthu
()
Ответ на: комментарий от eao197

В F# есть Generic Numeric тип. Но там есть ограничения чтобы функция обязана быть inline. (Примерно такие же ограничения есть и в Kotlin, inline generic могут чуть больше чем обычные). Ограничения виртуальной машины…

let inline func1 x=
  x * x + 3G

let res  = func1 5.0  // double
let res2 = func1 5.0f // float32
let res3 = func1 5.0M // decimal
let res4 = func1 5    // int

https://imgur.com/a/9mbq3EF

https://fsprojects.github.io/FSharpPlus/numerics.html

fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 1)
Ответ на: комментарий от fsb4000

+ 3G

Молодец, тебе удалось вывести конкретный тип Generic Numeric.

Хочу заметить, я пишу по памяти (окамл, хаскель и т.п. языков). А не ломаю компилятор F# хитроумными закорючками.

anonymous
()
Ответ на: комментарий от eao197

Вот для этого утверждения – «компилятор позволяет автоматизировать те вещи, которые в более примитивном языке не автоматизировались» – какие-то примеры привести можете?

Ты можешь руками выделять/высвобождать память вместо автоматического RAII? Можешь. Можешь сделать подтипизацию структур данных через приведение типов указателей? Можешь. Можешь делать лямбды через определение отдельной функции? Можешь.

Выходит, что смысл C++, как качественного скачка по сравнению с Си, заключается только в упрощении описания программы, автоматизации формирования конструкций. Ну?

byko3y ★★★★
()
Ответ на: комментарий от anonymous

Молодец, тебе удалось вывести конкретный тип Generic Numeric.

Не совсем. Если нужны разные типы, то нужен inline, тогда компилятор постарается вывести самый общий тип который он может.

Если без inline, то будет выведен тип по первому использованию

Вот несколько выводов типа компилятором, и какие он вывел ограничения:

https://imgur.com/a/K1iJ6Pv

fsb4000 ★★★★★
()
Ответ на: комментарий от byko3y

Блин, на вопрос ответьте. Хватит демагогией заниматься.

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

Иметь возможность сделать func1, которая работает только с int-ами без явного указания int… Ну такое. Экономия на символах без каких-либо явных выгод.

Если вы эти выгоды видите, то покажите на конкретных примерах.

Если не можете, то хватит уже звиздеть.

eao197 ★★★★★
()
Ответ на: комментарий от byko3y

Выходит, что смысл C/C++, как качественного скачка по сравнению с ассемблером/машинным кодом, заключается только в упрощении описания программы, автоматизации формирования конструкций.

Исправил.

X512 ★★★★★
()
Ответ на: комментарий от fsb4000

Если нужны разные типы, то нужен inline, тогда компилятор постарается вывести самый общий тип который он может.

Мое субъективное мнение (т.к. я знаю как там работает)

Нет. Скорее всего, с inline компилятор не выводит тип, он просто делает как С++ - утиная типизация, что было известно еще в прошлом веке.

anonymous
()
Ответ на: комментарий от anonymous

он просто делает как С++ - утиная типизация, что было известно еще в прошлом веке.

Может и так, но из-за того что язык проще(для IDE и всяких парсеров), если я захочу вызвать что-то не то, то IDE мне зачеркнёт всё красным ещё до компиляции.

let inline square x = x * x
let res = square "hi"

IntelliSence для С++ недостаточно хорош. Ошибки показываются только при сборке…

https://imgur.com/a/sjitldb

fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 1)
Ответ на: комментарий от fsb4000

IntelliSence для С++ недостаточно хорош. Ошибки показываются только при сборке…

Я не знаю ваши оффтопик-проблемы, но мой консольный(!) (neo)vim с парой-тройкой плагинов умеет показывать ошибки во время редактирования кода с достаточно сложными шаблонами.

anonymous
()
Ответ на: комментарий от anonymous

после первого применения на конкретном типе и вторая функция станет такой же для этого конкретного типа, не совсем понятно к чему это уточнение.

по сути это какое-то масло масляное, механизм может и разный, но по факту конечного использования он одинаков, так какая разница тогда?

anonymous
()
Ответ на: комментарий от anonymous

после первого применения на конкретном типе и вторая функция станет такой же для этого конкретного типа, не совсем понятно к чему это уточнение.

Нет. Используется конкретная специализация обобщенной (шаблонной) функции func1, что не запрещает использовать другую специализацию для другого типа. В то время как в F# ты не сможешь применить синтаксический символ func1 для двух разных типов.

по факту конечного использования он одинаков

Вот именно «по факту конечного использования» придется явно указывать конкретный общий тип (класс типов в хаскель). Что обесценивает громкое заявление про «волшебный вывод типов». Или придумывать хак «inline».

anonymous
()
Ответ на: комментарий от anonymous

Так ты бы нам тоже скриншоты кидал, что ты как не родной.

Зачем мне кидать, то что я не смотрю? Родниться с форумом я не собираюсь.

anonymous
()
Ответ на: комментарий от anonymous

Или придумывать хак «inline».

inline наше всё, про это и в документации пишут:

https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/functions/inline-functions#inline-functions-and-type-inference

https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/generics/statically-resolved-type-parameters

fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 2)
Ответ на: комментарий от fsb4000

inline наше всё

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

anonymous
()
Ответ на: комментарий от aeralahthu

предисловие к той книге начисто отбивает охоту читать что-либо от этого аффтара

anonymous
()
Ответ на: комментарий от eao197

Иметь возможность сделать func1, которая работает только с int-ами без явного указания int… Ну такое. Экономия на символах без каких-либо явных выгод

Тебя ввели в некоторое заблуждение, потому что на самом деле в F# вполне себе есть обобщения: как явные тайпхинты обобщенных типов, так и инлайны, так и автоматически обобщаемые функции.

Блин, на вопрос ответьте. Хватит демагогией заниматься
Если вы эти выгоды видите, то покажите на конкретных примерах

Его величество не будет уточнять вопрос — я попытаюсь угадать ответы.

Начнем с арифметики. Испокон веков арифметика в сях — это сплошное UB. Смотрим сюда:

[<Measure>] type m
[<Measure>] type s

let genericSumUnits ( x : float<'u>) (y: float<'u>) = x + y

let v1 = 3.1<m/s>
let v2 = 2.7<m/s>
let x1 = 1.2<m>
let t1 = 1.0<s>

let result1 = genericSumUnits v1 v2
let result2 = genericSumUnits v1 x1 // Error: mismatched units

Ты не можешь ошибиться в вычислениях, потому что компилятор тебе сам найдет ошибку. Я понимаю, что есть ad-hoc реализация единиц измерения под буст, только во-первых юниты там прибиты гвоздями, а во-вторых выглядит это вырвиглазно:

https://www.boost.org/doc/libs/1_55_0/doc/html/boost_units/Quick_Start.html

Далее, ADT, оно же «discriminated unions» в терминологии F#, часто позиционируется как замена наследованию. Типа «сахарок для паттерна Посетитель». Вспоминая обсуждение выше по треду про возврат ошибок — вот вам конкретный пример по поводу того, как делается возврат ошибки в развитых языках с полным контролем процесса, а не в прибитом гвоздями к компилятору и платформе виде:

Предварительное определение

type ResultBuilder() =
    member __.Bind(x, f) =
        match x with
        | Error e -> Error e
        | Ok x -> f x
    member __.Return x = Ok x
    member __.ReturnFrom x = x

let result = ResultBuilder()

Вызов с возвратом ошибки

let res arg =
    result {
        let! r = doJob arg
        let! r2 = doJob2 r
        let! r3 = doJob3 r2
        return r3
    }

Чистейший яснейший код, при этом ошибка вернулась наверх, и ее можно прокидывать дальше так же. То есть, это уже не просто ветвление — это сквозное ветвление через функции. Это аналог монад из хаскеля, только в F# это называется «вычислительные выражения». Расскажите мне, как это сделать на передовых разработках паттерн матчинга для крестов от Страуструпа:

https://github.com/solodon4/Mach7

Это та причина, почему я не верю в будущее Rust с его конскими описаниями типов. Этот код можно переписать на Rust, на C++, на C, да хоть на фортране, но полученный код по сравнению с F# будет как небо и земля. Внимание человека ограничено, и если что-то его отвлекает, если он вынужден выполнять лишнюю работу при написании кода — он будет делать ошибки. Хотя бы в твой самой рутинной работе, которую вынужден выполнять.

Я не спорю с тем, что лично ты напишешь код на крестах, и заставишь его работать. Более того, я напишу его на Си, заставлю его работать, и там не будет повреждений памяти и UB... скорее всего. Но написать его на F# тупо намного быстрее со сравнимой гарантией работоспособности — для чего и нужен весь прогресс разработки инструментов разработки.

Еще я хотел бы вспомнить про неизменяемые структуры данных. В 2020 году на первый план выходят многопоточные приложения, но использование C/C++ часто значит, что использование потоков в проекте формально запрещено сверху. Почему? Потому что кто-то обязательно где-то запишет не в ту ячейку, создав тяжело отслеживаемые гонки. Один из эффективных способов решения проблемы — отказ от изменяемых ячеек. Между прочим, именно в форму Static Single Assignment транслируется код компиляторами C/C++ — потому что это именно тот вид, в котором код предсказуем, его эффекты ясны и контролируемы. И таки SSA является родной формой для семейства ML — хоть это само по себе не значит неизменяемости ячеек, но хотя бы неизменяемости ссылок. Описание же самих неизменяемых структур данных в ML делается намного, намного проще и чище многих императивных языков, при этом он сохраняет возможность таки сделать структуру изменяемой данных и частично изменяемой. Что-то вот такое абстрактное можно привести:

type dataItem =
   { ID : int;
      mutable IsRegistered : bool;
      mutable RegisteredText : string; }

let getItem id =
   { ID = id;
      IsRegistered = false;
      RegisteredText = null; }

let register (items : dataItem list) =
   items  |> List.iter(fun st ->
      st.IsRegistered <- true
      st.RegisteredText <- sprintf "Registered %s" (DateTime.Now.ToString("hh:mm:ss")))

let printData (items : dataItem list) =
   items  |> List.iter (fun x -> printfn "%A" x)

let main() =
   let items = List.init 3 getItem
   printData items
   register items
   printData items

main()

Если очень хочется, то я могу привести пример и на многопотоках. Но я для начала предлагаю рассказать мне, что вы пишете многопоток на крестах, как лузгаете семки. Я вообще выдвигаю тезис, что проклятие однопоточных программ вызвано исключительно наследием C/C++ и ничем иным.

byko3y ★★★★
()
Ответ на: комментарий от X512

Выходит, что смысл C/C++, как качественного скачка по сравнению с ассемблером/машинным кодом, заключается только в упрощении описания программы, автоматизации формирования конструкций.

Исправил

Не исправил. Тыж вроде присутствовал при обсуждении истории создания Си. Си — это нашлепка над ассемблером, препроцессор для генерации асмового кода под конкретную машину из кроссплатформенного представления. Отсюда все его особенности и странности. Он уже в первом своем релизе представлял свобой эдак три слоя совместимости.

А асмы того времени умели в макросы, между прочим. Кто бы мог подумать, откуда взяли K&R «свою» идею макросов.

byko3y ★★★★
()
Ответ на: комментарий от anonymous

Нет. Скорее всего, с inline компилятор не выводит тип, он просто делает как С++ - утиная типизация, что было известно еще в прошлом веке

И какая разница? Отсутствие ограничения типа — это и есть обобщение, разве нет?

byko3y ★★★★
()
Ответ на: комментарий от fsb4000

IntelliSence для С++ недостаточно хорош. Ошибки показываются только при сборке

У C/C++ принципиально плохая читаемость, как для человека, так и для машины. Когда-то в молодости я серьезно считал, что причина популярности Си заключалась в том, что он чрезмерно неудобен, и потому притягивал любителей острых ощущений, среди которых оказывалось много талантливых кодеров.

byko3y ★★★★
()
Ответ на: комментарий от fsb4000

В С++23 есть пропозал по включению этой библиотеки в стандартную библиотеку:
https://github.com/mpusz/units

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

https://github.com/mpusz/units/blob/master/src/include/units/physical/si/deri...

По сравнению с ренжами это еще норм, на самом деле.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Си — это нашлепка над ассемблером, препроцессор для генерации асмового кода под конкретную машину из кроссплатформенного представления.

Если Си - это нашлёпка над ассемблером, тогда почему в нём полно undefined behavior и он не ведёт себя так как написано и занимается отсебятиной? В общем плохой генератор асмового кода, тот же паскаль лучше справляется с этой задачей.

X512 ★★★★★
()
Ответ на: комментарий от anonymous

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

Вывод типа может контролироваться программистом. Вот так новость. Главное — никому больше не рассказывай.

byko3y ★★★★
()
Ответ на: комментарий от X512

Если Си - это нашлёпка над ассемблером, тогда почему в нём полно undefined behavior и он не ведёт себя так как написано и занимается отсебятиной?

Ащет многие UB сей произошли напрямую от асма: переполнение буфера, переполнение стэка, доступ по некорректному указателю, доступ за пределами объекта, неинициализированные ячейки, арифметическое переполнение.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Ащет многие UB сей произошли напрямую от асма

В отличии от Си, в ассемблере поведение строго документировано и детерминировано, иногда вплоть до количества циклов. Например в случае целочисленного переполнения переполненные биты отбрасываются и устанавливается флаг. Программа делает ровно то, что написано. А в Си компилятор может заниматься отсебятиной, например при *ptr = 1; полагать что ptr != NULL и что-нибудь пропустить или считать что a < a + 1 всегда истинно, хотя это не так.

X512 ★★★★★
()
Последнее исправление: X512 (всего исправлений: 3)
Ответ на: комментарий от X512

А в Си компилятор может заниматься отсебятиной, например при *ptr = 1; полагать что ptr != NULL и что-нибудь пропустить или считать что a < a + 1 всегда истинно, хотя это не так

А, ты про это... Я уже неоднократно на лоре писал, что в среде Си еще в 80-е годы получили широкое распространение некорректные оптимизации, которые ломали отдельный работавший до этого код. Самая фундаментальная некорректная оптимизация — это упрощение указателя до передачи по ссылке. Ты примерно этого рода оптимизации и приводишь. Бедная семантика является довольно характерной чертой асма, которая перекочевала в Си, но изначально описываемых тобой проблем в Си от K&R не было. По хорошему, в Си пространства для оптимизаций очень мало, а возникает оно после трансляции в совершенно другую программу.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Кстати, кроме паттерн матчинга в С++23 войдёт и |> из F# Elixir

The particular form of the operator this paper is proposing comes from the Elixir programming language

https://wg21.link/p2011

fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 2)
Ответ на: комментарий от byko3y

Его величество не будет уточнять вопрос — я попытаюсь угадать ответы.

Вопрос был задан давным давно: показать на примерах, где F# сильно выше уровнем C++.

Начнем с арифметики. Испокон веков арифметика в сях — это сплошное UB. Ты не можешь ошибиться в вычислениях, потому что компилятор тебе сам найдет ошибку.

У вас каша в голове. Вы путаете UB (например, последствия переполнения знаковых целых чисел) и результат непреднамеренной ошибки разработчика, который умудрился сложить метры с секундами.

Возможность введения собственных типов для представления различных единиц измерений активно использовалась еще в C++98 задолго до появления F#. И библиотека из Boost-а не единственная такого рода.

Более того, в C++11/14 подобные библиотеки стали намного удобнее, т.к. в язык добавили user-defined-literals. Специально для этих целей. Пример можно найти даже в stdlib, благодаря которой сейчас можно писать 100ms или 10s.

Но если вам шашечки, а не ехать, и главное – это сахарок прямо в языке, то OK, поставим плюсик.

Далее, ADT, оно же «discriminated unions» в терминологии F#, часто позиционируется как замена наследованию.

Скорее AlgDT, т.к. ADT намного раньше стали расшифровывать как Abstract Data Types.

AlgDT в C++17 прямо из коробки в виде std::variant.

Чего в C++ пока нет, так это паттерн-матчинга. И на это преимущество F# я указывал ранее. Если бы вы читали то, что вам пишут, то не пришлось бы ходить по кругу.

Предложения по добавлению в C++ паттерн-матчинга уже есть. И это направление было признано одним из приоритетных для C++23/26.

Пока же народ пользуется не Mach7, а std::visit с трюком под названием overloaded. Ссылку привожу не для того, чтобы показать, как C++ хорош в этом (на самом деле нет). А для того, чтобы у вас было более-менее адекватное представление о C++.

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

Вы так говорите, как будто в C++ нет const. Может просто не в курсе?

В 2020 году на первый план выходят многопоточные приложения,

В 2020? В 2020, Карл?

Да знаменитой статье Саттера «Free lanch is over» уже больше 15 лет. Или вы тогда еще в школе учились?

но использование C/C++ часто значит, что использование потоков в проекте формально запрещено сверху.

Ахринеть, вы в какой вселенной живете?

Я лично связан с разработкой многопоточки на C++ уже лет 25. И в последние десятилетие-полтора однопоточные программы приходилось видеть разве что в следующих ситуациях:

  • программа слишком мелкая и простая;
  • программа специально написана в однопоточном режиме дабы избежать накладных расходов на распараллеливание;
  • многопроцессное приложение из однопоточных процессов сделанное таковым из соображений надежности (+ безопасности).

Но я для начала предлагаю рассказать мне, что вы пишете многопоток на крестах, как лузгаете семки.

В общем-то так и есть. Но я высокоуровневые инструменты применяю, которые позволяют мне использовать Actor Model и/или CSP.

Я вообще выдвигаю тезис, что проклятие однопоточных программ вызвано исключительно наследием C/C++ и ничем иным.

Да после таких высказываний можно выдвинуть тезис, что вы малолетний дебил, который живет в каком-то совсем уж тесном мирке собственных фантазий.


Итого, по факту, всего два плюсика пока что.

eao197 ★★★★★
()
Ответ на: комментарий от byko3y

Ну тогда и C++11 тоже 2015 года.

Головка совсем бо-бо?

2015-й – это уже C++14, причем уже доступный в компиляторах.

А Rust официально зарелизился в 2015 (а стабилизировался перед этим, насколько помню, во второй половине 2014). Rust 2010-го и Rust 2015 – это две большие разницы.

eao197 ★★★★★
()
Ответ на: комментарий от X512

Потому что это не совсем нашлепка + разная кодогенерация в зависимости от разной степени оптимизации кода. Хотя ты это и сам знаешь же.

anonymous
()
Ответ на: комментарий от anonymous

Нет. Используется конкретная специализация обобщенной (шаблонной) функции func1, что не запрещает использовать другую специализацию для другого типа.

Это никто не оспаривал. Но работая уже с конкретной «специализацией» получается тоже самое.

В то время как в F# ты не сможешь применить синтаксический символ func1 для двух разных типов.

Так там под ковром совсем иной механизм, это не шаблоны.

Вот именно «по факту конечного использования» придется явно указывать конкретный общий тип (класс типов в хаскель). Что обесценивает громкое заявление про «волшебный вывод типов». Или придумывать хак «inline».

Так и есть, волшебства там тоже нет, и очень часто вывод типов в хаскеле при достаточной полиморфности просто садится в лужу и ему нужно помочь и подсказать явным указанием типа. Тем не менее он и правда здорого решает целый пласт проблем, правда добавляет такой же пласт :\ (он делает больно, но немного иначе)

anonymous
()
Ответ на: комментарий от wandrien

Ну так си нашлепка на асм, а кресты нашлепка на си.

F# нашлепка над MS © .NET ®

Всё правильно.

anonymous
()
Ответ на: комментарий от eao197

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

anonymous
()
Ответ на: комментарий от anonymous

Это никто не оспаривал.

То есть, ты гоняешь из пустого в порожнее. Лишь бы поспорить, неважно о чём.

Так там под ковром совсем иной механизм, это не шаблоны.

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

Потом, чтобы удовлетворить недовольную этим обманом толпу, придумывают inline, работающий как с++ прошлого века. И назавают это каким нибудь забористым словосочетанием - «статический супер-пупер вывод типов».

Бедный «inline». Везде с ним извращаются: и в си его смысл извратили до бессмысленности, и эфшарписты издеваются, как хотят.

anonymous
()
Ответ на: комментарий от wandrien

И сверху нашлепка в виде прокладки между стулом монитором.

Главное, чтобы эта прокладка не взумала перегружать компьютер во время очередного неожиданого обновления. Никогда такого не было и вот опять. Любой наш каприз за ваши деньги. См. лицензионное соглашение.

anonymous
()
Ответ на: комментарий от anonymous

То есть, ты гоняешь из пустого в порожнее. Лишь бы поспорить, неважно о чём.

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

anonymous
()
Ответ на: комментарий от anonymous

Скорее ты воспринимаешь любой комментарий как попытку с тобой поспорить.

Если не споришь, то твои замечения должны вносить полезную информацию в дискуссию. Что полезного ты сказал мне, остальным участникам? Или ты просто пустышка?

anonymous
()
Ответ на: комментарий от anonymous

Я вношу уточнение в то что сказал ты, чтобы тебя точно поняли как надо, а не как обычно.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.