Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.20.238.187] |
|
Страницы: (56) « Первая ... 38 39 [40] 41 42 ... 55 56 ( Перейти к последнему сообщению ) |
Сообщ.
#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... |