D vs C++
    , почти сурковская пропаганда: не пора ли C++ потихоньку готовиться к пенсии?
  ![]()  | 
Наши проекты:
 Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту  | 
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS | 
| [216.73.216.5] | 
 
 | 
		
  | 
    Правила раздела:
  | Страницы: (56) « Первая ... 38 39 [40] 41 42 ... 55 56 ( Перейти к последнему сообщению ) | 
    D vs C++
    , почти сурковская пропаганда: не пора ли C++ потихоньку готовиться к пенсии?
  | 
         
         
         
          
           Сообщ.
           #586
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
         Цитата    Сообщить модератору о нарушении в этой теме Спам.  | 
    
| 
         
         
         
          
           Сообщ.
           #587
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
         Цитата korvin @  Цитата D_KEY @  Его проблема в том, скорее всего, придётся отказаться от оператора [](как и пришлось в scala), а это тоже неудобно. Я почти не знаком со Scala, поэтому не могу с ходу вообразить ситуацию, когда оператор [] будет конфликтовать с использованием [] для параметризации типа Ну а как ты на уровне грамматики это сделаешь? Цитата  Вот в D же параметры типа задаются в () и это не конфликтует с оператором () вызова процедуры. Так там же ! перед ними стоит.  | 
    
| 
         
         
         
          
           Сообщ.
           #588
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
         Цитата D_KEY @  Ну а как ты на уровне грамматики это сделаешь? Э-м... А как связаны грамматики типов и грамматика операторов? Ну например: ![]() ![]() type Array [T : Any] where {     val make : T -> Int -> @This     method get : Int -> T     method set : Int -> T -> ()     #implementation } type Map [Key : Hashable, Value : Any] where {     val make : () -> @This     val make : Int -> @This     method get : Key -> Value     method put : Key -> Value -> ()     #implementation } typeclass Indexable Container where {     type Index     type Value     operator _[_]      : Container -> Index -> Value     operator _[_] <- _ : Container -> Index -> Value -> () } instance Indexable Array [T] where {                               -- Array is a type, use "type grammar"     type Index = Int     type Value = T     operator array[index]           =  array.get index         -- array is a variable, use "operator grammar"     operator array[index] <- value  =  array.set index value } instance Indexable Map [K, V] where {     type Index = K     type Value = V     operator map[key]           =  map.get key     operator map[key] <- value  =  map.put key value } let arr = Array.make 3 "" let map : Map[String, Array[String]] =   -- Map is a type, use "type grammar"     if random.nextBool ()     then make ()     else make 2 do {     arr[1] <- "foo"                  -- arr and map are variables     map["bar"] <- arr                -- use "operator grammar"     print arr[1]     print arr     print map["bar"]     print map } => ![]() ![]() "foo" ["", "foo", ""] ["", "foo", ""] #{"bar" => ["", "foo", ""]} Где тут конфликт? Цитата D_KEY @  Так там же ! перед ними стоит. А разве ! не для этих их строковых "миксинов"?  | 
    
| 
         
         
         
          
           Сообщ.
           #589
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
         Цитата korvin @  А разве ! не для этих их строковых "миксинов"? Нет, он для шаблонов. Просто строка является аргументом шаблона. Цитата korvin @  map["bar"] <- arr                -- use "operator grammar" Вот как парсер здесь определит, что это оператор? Можно в парсере запоминать, какие идентификаторы являются именами переменных, а какие - типов. Но и это не всегда работает, поэтому в C++ используются приписки typename и template. Можно как у тебя - имена типов заглавной буквы, имена переменных - со строчной. Но конфликт то всё равно есть, и решается он какими-то дополнительными правилами или ограничениями грамматики.  | 
    
| 
         
         
         
          
           Сообщ.
           #590
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
         Цитата amk @  И кто-нибудь может объяснить, нафига в Perl'е столько долларов и процентов перед идентификаторами? Выбор нужного контекста. На предыдущем примере: ![]() ![]() my %data; #просто объявляется локальная переменная-хэш  # "парсим" пошагово выражение -  ${${$data{"зеленый"}}[6]}{"вес"} = [1,2,3,4,5]; # # $data{"зеленый"} - по ключу "зеленый" выбираем значение хэша # ${$data{"зеленый"}}[6] - выбранное ранее значение - это массив, выбираем его 7-й элемент # ${${$data{"зеленый"}}[6]}{"вес"} - а этот 7-й элемент сам хэш, выбираем в нем значение по ключу "вес" # ... ну и присваиваем этому элементу массив [1,2,3,4,5] Вроде все просто и ясно, не?   ЗЫ: В новой редакции Perl'a (6-я версия), будет немного по другому, вроде логичнее: ![]() ![]() %{@{%data{"зеленый"}}[6]}{"вес"} Потому, как элементы хэша уже не похожи на элементы массива, и предваряются неизменяемыми префиксами % и @. Но мне непривычно. Добавлено Именно.  | 
    
| 
         
         
         
          
           Сообщ.
           #591
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
         Цитата MyNameIsIgor @  Вот как парсер здесь определит, что это оператор? Наверное, по тому, что токен перед ним --- переменная? Цитата MyNameIsIgor @  Можно в парсере запоминать, какие идентификаторы являются именами переменных, а какие - типов. Почему бы и нет? Цитата MyNameIsIgor @  Но и это не всегда работает, поэтому в C++ используются приписки typename и template. Само собой у каждого языка свой синтаксис, где-то это делается легко, где-то --- нет. Я и говорил лишь про конкретно проблему в синтаксисе Scala и конкретно возможность её решения при использовании чуть более другого синтаксиса, а не про возможность разрешить её в любом синтаксисе. Цитата MyNameIsIgor @  Можно как у тебя - имена типов заглавной буквы, имена переменных - со строчной. Э-м. В моём примере это решается не за счёт регистра символов, а за счёт однозначности семантики [] в, так скажем, двух не пересекающихся видах выражений --- "типовых" и "переменных": ![]() ![]() type-decl   ::= "type" <id> "[" <type> ["," <type>]* "]" "where" "{" ... "}" value-decl  ::= "val" <id> ":" <type> method-decl ::= "method" <id> ":" <type> typeclass-type-variable-decl ::= "type" <id> instance-type-let ::= "type" <id> "=" <type> operator-decl ::= "operator" <syntax> ":" <type> let ::= "let" <id> ":" <type> let ::= "let" <id> "=" <expr> let ::= "let" <id> ":" <type> "=" <expr> --- упрощённо. Т.е. вполне себе легко определить, что в <type> [] --- параметры, а в <expr> --- оператор. Цитата MyNameIsIgor @  Но конфликт то всё равно есть, и решается он какими-то дополнительными правилами или ограничениями грамматики. Не вижу, в чём ограничение. Если строго разделить виды грамматик <type> и <expr>, то они никак не будут конфликтовать. В Хаскелле, например, нельзя объявить оператор ::, т.к. декларации типов можно использовать в тех же местах, что и выражения, например: ![]() ![]() x = y :: z -- это объявление x = y типа z или объявление x = результат применения оператора :: к переменным y и z? В ML по идее с этим лучше, но всё равно для декларации типа переменной используется : , а для операции cons списка --- :: т.к. есть как минимум одна неоднозначная ситуация: ![]() ![]() function (h : t) = ... -- это паттерн-матчинг аргумента-списка или декларация типа для аргумента? В моём примере никакой неоднозначности быть не может. А можно ли определить оператор : , чтобы он не конфликтовал с объявлением типа? --- Спросишь ты. А можно. И опять никаких неоднозначностей: ![]() ![]() let x : t : y                 -- syntax error let x : (t : class)           -- ok, not an operator in <type> expression let x = y : z                 -- ok, it's operator : in <expr> expression let x : (t : class) = y : z   -- ok, first two : --- <type>, third --- <expr> Как-то так. Добавлено Да собственно, что далеко ходить: в Java выражение дженерик-класса a<b> никогда не может быть спутано с использованием операторов сравнения А вот другие скобки уже используются в синтаксисе классов и только поэтому не могли быть использованы для параметров дженериков. Ну и плюс просто выбрали похожий на шаблоны C++ синтаксис.  | 
    
| 
         
         
         
          
           Сообщ.
           #592
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
         Цитата korvin @  Наверное, по тому, что токен перед ним --- переменная? Если ты запоминаешь идентификаторы или идентификаторы имеют разный вид для переменных и типов. А иначе ты получишь лишь идентификатор. Цитата korvin @  Почему бы и нет? Ну, например, потому что это применимо лишь в языках, где всё объявляется до использования. И нельзя, например, вызвать функцию, объявленную ниже. Цитата korvin @  Я и говорил лишь про конкретно проблему в синтаксисе Scala и конкретно возможность её решения при использовании чуть более другого синтаксиса Не вижу такой возможности. Цитата korvin @  Т.е. вполне себе легко определить, что в <type> [] --- параметры, а в <expr> --- оператор. Это всё хорошо либо при теоретизировании, либо для синтаксически нищего языка. Например, что такое a[b]© в каком-то выражении? Это я из массива a беру по индексу b функцию и вызываю её с аргументом c? Или это я прямо в выражении без объявления переменной конструирую значение параметрического типа a с параметром b и отдаю в конструктор аргумент c? А что такое a[b].c? Это я из массива a по индексу b получаю значение и читаю его поле c? Или это я у параметрического типа a с параметром b читаю статическое поле c? Цитата korvin @  Не вижу, в чём ограничение. ... В Хаскелле, например, нельзя объявить оператор :: ![]() Цитата korvin @  Да собственно, что далеко ходить: в Java выражение дженерик-класса a<b> никогда не может быть спутано с использованием операторов сравнения Навскидку: в Java аргументами обобщений не могут быть значения, в C++ - могут.  | 
    
| 
         
         
         
          
           Сообщ.
           #593
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
          В общем, мало видов скобочек  
        
        Можно, как в D, заюзать какой-то специальный символ перед обычными скобками. Но тоже не слишком изящно.  | 
    
| 
         
         
         
          
           Сообщ.
           #594
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
         Цитата MyNameIsIgor @  Это всё хорошо либо при теоретизировании, либо для синтаксически нищего языка. Например, что такое a[b]© в каком-то выражении? В каком "каком-то" выражении? Ты пишешь на языке произвольных абстрактных выражений? Perl что ли? =) И как разделение выражений на <type> и <expr> вдруг делают язык "синтаксически" нищим? Цитата MyNameIsIgor @  Это я из массива a беру по индексу b функцию и вызываю её с аргументом c? Или это я прямо в выражении без объявления переменной конструирую значение параметрического типа a с параметром b и отдаю в конструктор аргумент c? А где оператор new?   Цитата MyNameIsIgor @  А что такое a[b].c? Это я из массива a по индексу b получаю значение и читаю его поле c? Или это я у параметрического типа a с параметром b читаю статическое поле c? Вот это уже чуть интересней, но допустим у нас нет статических полей, у нас есть модули, где мы можем объявить статические переменные. Поэтому ответ: зависит от того, это <type> или <expr>, а это уже строго определено синтаксисом. Более того, зачем вообще явно указывать тип-параметр, если он выводится из контекста, как во всех нормальных языках? =) Цитата MyNameIsIgor @  ![]() Я и не говорил, что Хаскелл --- образец для подражания в этом вопросе. Цитата MyNameIsIgor @  Навскидку: в Java аргументами обобщений не могут быть значения, в C++ - могут. Т.е. вместо a можно подставить 1? Будет 1<b>? И что тогда в C++ означает выражение 1<2>(3)? Создание объекта шаблонного класса 1 с шаблонным параметром 2 и параметром конструктора равным 3? =) Ну, допустим, про 1 я утрировал, но a<1>(2)? Пара-пара-пам? Добавлено Цитата MyNameIsIgor @  Ну, например, потому что это применимо лишь в языках, где всё объявляется до использования. И нельзя, например, вызвать функцию, объявленную ниже. Отчего же? Разбор неоднозначного выражения (с несвязанным идентификатором) можно отложить, как это уже делается для рекурсивных функций. Цитата MyNameIsIgor @  ![]() Кстати, в Хаскелле параметры же пишутся просто через пробел и ведь не путаются с применением функций-конструкторов, которые так же, как и типы, пишутся с заглавной буквы. Т.е. их идентификаторы неотличимы, да и вообще часто совпадают, если конструктор один. Добавлено Цитата D_KEY @  В общем, мало видов скобочек    Можно, как в D, заюзать какой-то специальный символ перед обычными скобками. Но тоже не слишком изящно. А может наплевать на всех, и заюзать символы вне ASCII диапазона? =) Но вообще, в Джаве можно бы было использовать круглые скобки, если бы в своё время авторы пару вещей сделали бы по-другому: 1) вместо оператора new использовать new как специальный статический метод, new и так ключевое слово и определить такой метод нельзя. Кроме того, такой синтаксис и так поддерживается в некоторых ситуациях. Т.е. вместо ![]() ![]() new ArrayList<T>(); было бы ![]() ![]() ArrayList(T).new(); 2) при создании анонимного класса inplace передавать аргументы конструктора не после имени класса, а после фигурных скобок его тела, т.е. вместо ![]() ![]() new Foo(1) {     // ... } писать ![]() ![]() new Foo {     // ... }(1) Тогда после Foo в круглых скобках можно было бы указать типы. По-моему этому ничего особо не мешало, но, может, я что-то упускаю.  | 
    
| 
         
         
         
          
           Сообщ.
           #595
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
         Цитата korvin @  В каком "каком-то" выражении? В любом. Цитата korvin @  И как разделение выражений на <type> и <expr> вдруг делают язык "синтаксически" нищим? Вводом ограничений. Цитата korvin @  А где оператор new? В синтаксически нищих языках ![]() Так что я так и не понял, как ты будешь определять, что это не вызов конструктора. Цитата korvin @  Вот это уже чуть интересней, но допустим у нас нет статических полей, у нас есть модули, где мы можем объявить статические переменные Т.е. я не смогу иметь отдельные переменные для каждого инстанса параметрического типа a? Это уже семантическое, а не синтаксическое, нищенство. Цитата korvin @  Более того, зачем вообще явно указывать тип-параметр, если он выводится из контекста, как во всех нормальных языках? =) Не знаю как там в нормальных, а в самом лучшем так ![]() ![]() template<class T> struct a {   static constexpr bool s = sizeof(T) == sizeof(char); }; int main() {   return a<int>::s; } Как нормальные языки выведут, что я имел в виду именно int? Цитата korvin @  Т.е. вместо a можно подставить 1? Будет 1<b>? И что тогда в C++ означает выражение 1<2>(3)? Создание объекта шаблонного класса 1 с шаблонным параметром 2 и параметром конструктора равным 3? =) Нет. У тебя осталось две попытки ![]() Цитата korvin @  Ну, допустим, про 1 я утрировал, но a<1>(2)? Пара-пара-пам? Это боян. Например ![]() ![]() a.func<A>(b); // что здесь написано? Но проблема раскрывается здесь ![]() ![]() template<class T> void foo(T t) {   t.func<1>(2); // а здесь что написано? } Добавлено Цитата korvin @  Отчего же? Разбор неоднозначного выражения (с несвязанным идентификатором) можно отложить, как это уже делается для рекурсивных функций. Усложнения парсера - требуется определить конец откладываемой части. И не всегда осуществимо - например, ты разбираешь обобщение (как у меня в примере выше), но при этом тебе его надо положить в байт-код. Ещё может возникнуть веселуха с циклически ссылающимися друг на друга кусками разбираемого кода. Цитата korvin @  А может наплевать на всех, и заюзать символы вне ASCII диапазона? =) А набирать то их как?  | 
    
| 
         
         
         
          
           Сообщ.
           #596
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
          korvin, а обобщённые функции как тогда выглядели в такой Java? 	  
        
       | 
    
| 
         
         
         
          
           Сообщ.
           #597
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
         Цитата MyNameIsIgor @  Вводом ограничений. Как будто что-то плохое. Тебя же не смущает отсутствие возможности переопределения ключевых слов или использования их в качестве идентификаторов? А то в каком-то языке можно было легко получить код вроде ![]() ![]() if if begin begin Впрочем, ты так и не привёл ни одного нормального примера ограничения, а просто пытаешься навязать плюсовый синтаксис. =) Цитата MyNameIsIgor @  В синтаксически нищих языках Типа C++? Цитата MyNameIsIgor @  Так что я так и не понял, как ты будешь определять, что это не вызов конструктора. Как угодно, я выше D_KEY'ю написал пример про Жабу. Или так же, как парсер Хаскелла отличает идентификатор типа от идентификатора конструктора. Цитата MyNameIsIgor @  Как нормальные языки выведут, что я имел в виду именно int? В нормальных языках нет нужды в подобном коде. =) Цитата MyNameIsIgor @  Это боян. Это пример того, как Цитата MyNameIsIgor @  Усложнения парсера - требуется определить конец откладываемой части. Да какое ж тут усложнение? Я же приводил выше примерную грамматику, парсеру не нужно знать смысл []. Это смысл будет дальше определён вычислителем/компилятором. Парсер Java как отличает, где [] --- это указание размера создаваемого массива, а где --- обращение по индексу? Где {} --- инициализатор массива, а где --- блок кода? Где в () используется точка с запятой (for, try), а где --- запятая (аргументы)? У Java сложный парсер? Да уж, думаю, попроще, чем у C++, а уж "обогащённый" парсер, как я понимаю, умеет туеву кучу неоднозначностей разруливать. Или не умеет? Цитата D_KEY @  а обобщённые функции как тогда выглядели в такой Java?  Вот, так и знал, что что-то упущу. Навскидку могу предложить foo(T)(x), выглядит не ок, но логично, т.е. вначале мы передаём конкретный тип и как бы создаём замыкание на его основе, а потом применяем замыкание к аргументу x. Вообще же, тут тип мог бы просто выводиться из типа аргумента, но из-за субтипирования, он может оказаться более общим, чем нужно. Добавлено Цитата MyNameIsIgor @  Т.е. я не смогу иметь отдельные переменные для каждого инстанса параметрического типа a? В нормальных языках параметрический тип ---- это параметрический тип, а не хрен пойми что, плодящая кучу кода. =) Добавлено Цитата MyNameIsIgor @  А набирать то их как?  Compose+( например. В нормальных же операционных системах есть поддержка клавиши Compose =)  | 
    
| 
         
         
         
          
           Сообщ.
           #598
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
         Цитата korvin @  Впрочем, ты так и не привёл ни одного нормального примера ограничения, а просто пытаешься навязать плюсовый синтаксис. =) Т.е. обязательно new и отсутствие статических членов - это ненормальные ограничения ![]() Цитата korvin @  Типа C++? Нет, типа Go и Java. Впрочем, они не только синтаксически, они и семантически нищие. Цитата korvin @  Это пример того, как духовносинтаксически богатый язык превозмогает обсуждаемую трудность. С чем ты споришь? =) Нет, не превозмогает. И я привёл тебе код почему не превозмогает. Цитата korvin @  Да какое ж тут усложнение? Я же приводил выше примерную грамматику, парсеру не нужно знать смысл []. Эммм... Все твои рассуждения как раз и сводятся к тому, что мы при парсинге знаем смысл []. Цитата korvin @  Парсер Java как отличает, где [] --- это указание размера создаваемого массива, а где --- обращение по индексу? Где {} --- инициализатор массива, а где --- блок кода? Где в () используется точка с запятой (for, try), а где --- запятая (аргументы)? Это не означает, что все неоднозначности можно разрулить без дополнительных приседаний. Что ты и доказал с теми же статическими членами. Цитата korvin @  Да уж, думаю, попроще, чем у C++, а уж "обогащённый" парсер, как я понимаю, умеет туеву кучу неоднозначностей разруливать. Или не умеет? Неоднозначности потому и неоднозначности, что без дополнительных телодвижений не разруливаются. Естественно грамматика C++ однозначна, но она контекстно-зависимая и потребовала подпорок typename/template. Добавлено Цитата korvin @  В нормальных языках На самом деле ответить тебе просто нечего. Ты всё обсуждение сводишь к "в нормальных языках". А на самом деле ты хочешь сказать "в никем не используемых, никому не нужных поделках". Добавлено Цитата korvin @  В нормальных же операционных системах В нормальных операционных системах нормальное API, а не убожество типа epoll/kqueue...  | 
    
| 
         
         
         
          
           Сообщ.
           #599
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
         Цитата korvin @  Цитата D_KEY @  В общем, мало видов скобочек    Можно, как в D, заюзать какой-то специальный символ перед обычными скобками. Но тоже не слишком изящно. А может наплевать на всех, и заюзать символы вне ASCII диапазона? =) Это не слишком удобно   Проще добавить в язык end. Мне не очень нравится, но {} освободит. ![]() ![]() def foo{T}(T x)     ... end class A{T}     ... end ... foo{int}(10); A{T} a; map{string, int} dict; Добавлено Еще таки есть вариант с дополнительным символом ![]() ![]() map!(string, vector!int) map@(string, vector@int) Или чуть изменим скобки: ![]() ![]() map(:string, vector(:int)) Ну или что-то в таком роде. Эх, в любом случае получается отстой.  | 
    
| 
         
         
         
          
           Сообщ.
           #600
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
         Цитата MyNameIsIgor @  А что есть в нормальных ОС вместо epoll/kqueue? IOCP? 	 В нормальных операционных системах нормальное API, а не убожество типа epoll/kqueue...   |