Войти
ФлеймФорумПрограммирование

Революционные идеи в сфере языков программирования (2 стр)

Страницы: 1 2 3 426 Следующая »
#15
18:45, 19 сен. 2018

kvakvs
> Синтаксис в котором можно что-то убрать и ничего не изменится - корявый, и
> избыточный.
Статическая типизация - корявая и избыточная. Мы тебя поняли.


#16
19:13, 19 сен. 2018

Delfigamer
> Я очень за тебя рад.
То есть язык ты делаешь только для себя любимого?

#17
20:06, 19 сен. 2018

romgerman
> То есть язык ты делаешь только для себя любимого?
Скажем так, я не делаю язык для тех, кто хочет увидеть ещё один плюсплюс/раст/эрланг/хаскелл/ю/пайтон, ибо это настолько же бессмысленно, как и убийца коллофдюти - даже если у тебя всё получится и будет красиво, целевая аудитория всё равно будет с разинутым ртом дрочить на очередную версию своего любимого изделия, считая все его недостатки фичами и категорически отказываясь воспринимать что-то другое.
Если у тебя есть критика - приведи её так, чтобы я поверил в ошибочность своих решений и захотел сделать по-другому. Можешь взять пример с Кваквса - он хотя бы пытается привести аргументы и указывает на контекст, в котором мои решения кажутся сомнительными.
Если же ты просто выражаешь своё мнение в виде "нравится/ненравится" - то не надо удивляться, что тебя гладят по головке и показывают пальцем на полку. Мнений у нас тут каждую неделю вагонами привозят, а истину нужно выбирать какую-то одну.

#18
20:43, 19 сен. 2018

Заметил что ключевое слово requires не помогает сформировать английское предложение в коде.
Когда у тебя оно задаёт охранные проверочные выражения в шапке функции, то лучше подходит что-то вроде слова where
И по-математически так лучше читается

функция жопа(параметр ы), ГДЕ ы равно 0...

А когда это ключевое слово задаёт методы в интерфейсе, то слово requires (ТРЕБУЕТСЯ) вообще не подходит, или означает совсем не то, что я бы ожидал там увидеть. Скажем так, оно там просто лишнее, и заменять его ничем не надо.

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

Ещё заметил, что все скобки квадратные. Это для чего так?

#19
22:12, 19 сен. 2018

А вообще, если есть перегрузка по значениям, то можно

state name: type

диспатчить как
operator init[type]

и перегрузка по выходным значениям, в принципе, и не нужна.

Операторы сделаны по мотивам генерик методов. Семантически, все операторы проходят позднее связывание. Как уже упоминалось, это позволяет использовать этот же механизм в том числе и для реализации объектного полиморфизма.
Сам по себе state - частными случаями которого являются локальные пемеренные, поля класса, значения аргументов и текущее состояние актёра - может не только хранить, но и свободно переключаться между любыми возможными в языке значениями. Можно ввести понятие вселенной значений как множества всех состояний, которые в принципе может принять валидный state.
В таком формализме, тип - это подмножество значений.
Между типами устанавливается частичный порядок - некоторые типы считаются более специфичными по сравнению с другими. Более специфичный тип всегда является подмножеством более общего типа, хотя обратное не всегда верно - отношения специфичности не устанавливаются автоматически везде, где они применимы.
У некоторых типов есть множество собственных значений - которые принадлежат данному типу, но не принадлежат ни одному из доступных в языке подтипов. Генерируемый рантаймом operator newinstance[type: Type] создаёт собственное значение типа type. Понятие собственных значений позволяет ввести гарантию, что экземпляры базового класса никогда не будут случайно приняты за наследника.
Выбор конкретной перегрузки происходит аналогично плюсам - собираются все доступные реализации оператора, отсеиваются не подходящие по типу, оставшиеся сравниваются попарно в поисках прототипа с самыми специфичными типами.

#20
22:26, 19 сен. 2018

kvakvs
> Когда у тебя оно задаёт охранные проверочные выражения в шапке функции, то
> лучше подходит что-то вроде слова where
Operator 'factorial' that takes 'i' as an 'Integer', returns 'Integer' and requires that 'i > 0':
    operator definition follows.

kvakvs
> А когда это ключевое слово задаёт методы в интерфейсе, то слово requires
> (ТРЕБУЕТСЯ) вообще не подходит
Concept template 'IndexedContainer' with a parameter 'Elem' as a 'Type', when applied to 'T':
- requires operator 'count' that takes a 'T' and returns 'Integer',
- requires operator 'get' that takes a 'T', an 'Integer' and returns 'Elem',
- requires operator 'set' that modifies a 'T' and takes an 'Integer' and an 'Elem'.
Кроме того, повсеместное добавление префикса requires позволяет однозначно отличить определение от описания.

kvakvs
> Заметил на третий день что твой код возвращает типы.
> Это скользкая дорожка, потому что на типах хотя и можно программировать во
> многих языках, не спускаясь в код, и можно нагородить огромную программу чисто
> в типах, и потом просто создать результат нужного типа и типы сделают всё
> остальное, такая программа очень плохо отлаживается и поиск ошибок в ней полон
> страданий и боли. Это просто получается язык поверх языка, очень нехорошо,
> когда этот второй верхний язык не имеет нормальных сообщений об ошибках,
> отладчика, и прочих нужных средств.
Это тоже одно из ключевых отличий от многих других языков - поскольку описания типов являются обычными значениями, то и метакод так же работает по тем же правилам, что и обычный код; в частности - подвергается тем же статическим проверкам, может быть выполнен по шагам в отладчике, может даже дёргать io и выводить отладочную информацию прямо во время синтеза типа.

kvakvs
> Ещё заметил, что все скобки квадратные. Это для чего так?
Чтобы не было путаницы с круглыми - круглые используются только для группировки выражений, квадратные означают вызов.

#21
14:48, 20 сен. 2018

Delfigamer
> Признайтесь, у каждого из нас были идеи нового языка.
> У меня тоже есть ряд идей.
> И у меня возникла трудность.
:) возникла трудность -> ряд идей

Delfigamer
> Признайтесь, у каждого из нас были идеи нового языка.
нет , не было никогда это все выдумки : язык одни и он называется Алгоритмический Язык
брось быть кодером и стань программистом : короче radix complement тебе

Delfigamer
вообще должен быть не столько "Язык Кодинга" сколько должен стать Командный Язык в Игре
то есть и при Разработке Игры и в самой Игре как терминальный ввод команд на консоли управления в игре
.. вот это нужное и полезное : в Юнити схожий с дельфи язык си-шарп
читай мой мануал Фантомная Система Сущности находится по Поиску наверняка
.. может создашь Ассет Юнити и сможешь выставить в Ассет Стор

Delfigamer
вообщем тебе проще объяснить обычными словами и понять архитектуру как структуру программы
и решают таблицами и процедурами , а не команд ком энтертеймент нового языка

kvakvs
> Delfigamer
> Поздравляю, ты изобрёл traits из руста (и что-то подобное было в руби).
> Они ведут себя приблизительно как интерфейсы из ООП,
> но по сути не являются интерфейсами
http://gamedev.ru/flame/forum/?id=238878#m12

Delfigamer
во-во , тебе kvakvs уже пытался сказать че-то не раз в теме

#22
16:09, 29 сен. 2018

Идей много, а в порядок привести всё никак не получается.

По значениям:
Все значения неизменны, в том числе и составные.
Операторы всегда являются чистыми функциями. Некоторые конструкции языка упрощают работу с сайд-эффектами, на нижнем уровне они транслируются в вызов оператора с дополнительными параметрами.
Присваивание значений полю класса - это операция вида new_value = set_field[old_value, field_value]. Вообще, мутаторы никогда не изменяют значения на месте; будучи операторами, они так же получают исходные данные как бы копией и возвращают совершенно новое значение, которое соответствует результату работы.
У значения невозможно взять ссылку. Как следствие - сами по себе значения невозможно завернуть в цикл. Любое выражение вида root = set_child[root, root] скопирует в поле "child" старое значение "root"; поэтому вместо цикла root.child=root получится линия root1.child=root0, root0.child=null.
Значения можно рассматривать как в виде ациклического графа, так и в виде множества индивидуальных, совершенно не связанных объектов. Поскольку значения неизменны, эти точки зрения равнозначны.

По системе типов:
Есть концепты - перечисление операций, которые должны поддерживать все значения этого типа.
Есть классы - шаблоны значений. Классы также могут быть использованы как концепты.
Типы определяют только поведение. Физическая форма значения в памяти, в общем случае, ортогональна его положению в системе типов. Переменные могут быть ограничены по типу, но они никогда не ограничены физической формой - присваивание происходит как бы по значению.
Для любого значения и любого типа имеет смысл запрос V is instance of T - выражение истинно, если значение V принадлежит типу T.

Между концептами может быть установлена связь вида B subsets A. Последствие один - все требования, определённые в A, распространяются также и на B. Последствие два - если для какого-то значения V is instance of B, то автоматически V is instance of A. Последствие три - если для какого-то оператора есть две перегрузки, берущие A и B, то, если V is instance of B, то из этих вариантов будет выбрана перегрузка, берущая аргумент типа B. Связь транзитивная - если C subsets B и B subsets A, то C subsets A.
Кроме того, для любого типа T subsets T.

Главное отличие класса от концепта - для любого класса K определена операция create instance of K, результатом которой является значение этого класса - (create instance of K) is instance of T тогда и только тогда, когда K subsets T.
Для класса K и концепта A может быть установлена связь K implements A. Последствие один - автоматически K subsets A. Последствие два - если в момент закрытия типа K останется какая-то операция, которую требует A, но которая не реализована в K, то это будет определено как семантическая ошибка.
Для двух классов K и L может быть установлена связь L extends K. Последствие один - автоматически L subsets K. Последствие два - все поля, объявленные в K, так же становятся полями L.
Методы не являются составной частью класса или объекта. Вместо этого, методы реализуются как операторы, принимающие аргумент типа K. Наследование и переопределение методов срабатывает как часть общего механизма перегрузки операторов. Вызовы методов всегда полиморфны.

Для работы с параметрическими типами, так же объявляется subset of T - возвращает специальный концепт. B is instance of (subset of A) равнозначно B subsets A.
Параметрические типы - это семейство типов вида parametric [param: ParamType] typeword Family. Каждый потенциальный инстанс этого семейства Family[arg] - это тип.
Кроме того, семейство так же снабжается дополнительным концептом Family[common T] для любого T subsets ParamType.
Если ParamType subsets Type и B subsets A, то Family[B] subsets Family[A]. Кроме того, если V is instance of T, то Family[V] subsets Family[common T].
В частности, Family[common ParamType] - это концепт, охватывающий всё семейство целиком.
Для семейства концептов, все описанные Family[x] - это концепты.
Для семейства классов, Family[common type] - это концепты, а для V is instance of ParamType, Family[V] - это класс.

Параметрические операторы вида parametric [x: Q] operator [a: x, b: D[x]]: E[x] проверяются и ранжируются как operator [a: common Q, b: D[common Q]]: E[common Q]. В месте вызова, из статических типов аргументов формируются Q1 и D[Q2], из них по subsets-графу находится ближайший общий предок Qr (который в худшем случае окажется Value) и статическим типом результата принимается E[Qr].
Для корректной работы этого механизма, логично определить common (subset of T) == T.

Для работы с common-значениями, определяется выражение extended set of T. Если B subsets A, то (common B) is instance of (extended set of A).
Параметрические типы получают от рантайма сразу несколько перегрузок в ответ на попытку вызвать их как функцию. Для типа вида parametric [param: ParamType] class Family, рантайм генерирует две перегрузки, которые ведут себя как operator Family[: ParamType]: Class и operator Family[: extended set of ParamType]: Type.

Концепт, описывающий все возможные значения - это Value. Концепт, описывающий все возможные типы - это Type. Концепт, описывающий классы - это Class. Class subsets Type subsets Value. Value, Type, Class is instance of Type.

#23
16:09, 29 сен. 2018

В момент определения оператора, его тело проходит статическую проверку. В теле оператора допустимы только те операции, которые явно прописаны в описании статического типа. В первую очередь - это объединение всех operator и requires operator, описанных внутри типа и его subsets-предках.

parametric [Elem: Type] concept Sequence for T
end

parametric [Elem: Type] concept FullSequence for T
    T subsets Sequence[Elem]
    requires operator first[: T]: Elem
    requires operator rest[: T]: Sequence[Elem]
end

concept Numeric for T
    requires operator add[: T, : T]: T
    requires operator zero[: subset of T]: T
end


-- самый корректный вариант
parametric [T: subset of Numeric] operator sum[seq: Sequence[T]]: T
    -- внутри T == common (subset of Numeric) == Numeric
    return zero[T]
end

parametric [T: subset of Numeric] operator sum[seq: FullSequence[T]]: T
    -- внутри T == common (subset of Numeric) == Numeric
    return first[seq] + sum[rest[seq]]
end


-- технически верный вариант
operator sum_typeless[seq: FullSequence[Numeric]]: Numeric
    return first[seq] + sum[rest[seq]]
end


-- ошибки
operator sum_err1[seq: Sequence[Numeric]]: Numeric
    -- семантическая ошибка: operator first[: Sequence[Numeric]] не определён
    -- семантическая ошибка: operator rest[: Sequence[Numeric]] не определён
    return first[seq] + sum[rest[seq]]
end

parametric [T: subset of Numeric] operator sum_err1p[seq: Sequence[T]]: T
    -- внутри T == common (subset of Numeric) == Numeric
    -- семантическая ошибка: operator first[: Sequence[Numeric]] не определён
    -- семантическая ошибка: operator rest[: Sequence[Numeric]] не определён
    return first[seq] + sum[rest[seq]]
end

operator sum_err2[seq: FullSequence[Value]]: Value
    -- семантическая ошибка: operator add[: Value] не определён
    return first[seq] + sum[rest[seq]]
end

parametric [T: subset of Value] operator sum_err2p[seq: FullSequence[T]]: T
    -- внутри T == common (subset of Value) == Value
    -- семантическая ошибка: operator add[: Value, : Value] не определён
    return first[seq] + sum[rest[seq]]
end


-- индикатор
operator add_ten_to_integer[i: Integer]: Integer
    return i + 10
end


-- пример использования
procedure main[]
    state list = make_sequence[1, 2, 3, 4]
    -- статический тип list - Sequence[Integer]

    state total = sum[list]
    -- снаружи T == Integer
    -- статический тип total - Integer

    state total_plus_ten = add_ten_to_integer[total]
    -- статический тип total_plus_ten - Integer

    state total_typeless = sum_typeless[list]
    -- статический тип total_typeless - Numeric

    -- семантическая ошибка: operator add_ten_to_integer[: Numeric] не определён
    state total_typeless_plus_ten = add_ten_to_integer[total_typeless]
end

#24
16:10, 29 сен. 2018

Кажется, в процессе написания я всё-таки привёл систему типов в какой-никакой, но всё же порядок.

#25
19:50, 1 окт. 2018

Я ещё подумал, и осознал, что фигня это и ничерта не работает.
Пример один:

parametric [Elem: Type] concept MutableList for T
    requires operator set[: T, : Integer, : Elem]: T
    requires operator length[: T]: Integer
end

concept Float4 for T
    T subsets MutableList[Float]
end

operator set_typeless[list: MutableList[Value], index: Integer, value: Value]: MutableList[Value]
    return set[list, index, value]
end

operator bad[list: Float4]: Value
    return set_typeless[list, 1, "asdf"]
end


set_typeless проходит статическую проверку, bad вызывает set_typeless, происходит расширение типа Float4 -> MutableList[Float] -> MutableList[Value] и String -> Value, внутри вызывается set[: Float4, : Integer, : String] и только в рантайме обнаруживается, что под такой запрос перегрузки не предусмотрено.

Пример два:

concept Ordered for T
    requires operator less[: T, : T]: Testable
end

operator greater[a: Ordered, b: Ordered]: Testable
    return less[b, a]
end

operator bad[]: Testable
    return greater[10, "bar"]
end


Внутри greater статический анализатор находит operator less[: Ordered, : Ordered] и приходит к выводу, что функция корректная. Integer и String оба наследуют от Ordered и поэтому подставляются в greater. В рантайме же происходит обращение к operator less[: String, : Number], на который реализация не предусмотрена (типа у нас нормальный язык, а не жескрипт), и опять всё ломается

#26
20:25, 1 окт. 2018

Итак, начнём с начала. Что можно утверждать точно?
Если B на самом деле subsets A - то есть, любое значение B может быть подставлено на место A; то из этого следуют две вещи:
1. (T -> B) subsets (T -> A). Любую лямбду можно безопасно заменить на альтернативу, результат которой удовлетворяет более строгим ограничениям.
2. (A -> T) subsets (B -> T). Любую лямбду можно безопасно заменить на альтернативу, которая справляется с более широким множеством аргументов.
Иллюстрация:

const DiscreteFunction = lambda type [: Integer]: Numeric
const QuantizedFunction = lambda type [: Numeric]: Integer


operator discrete_delta[f: DiscreteFunction, x1: Integer, x2: Integer]: Numeric
    return f[x2] - f[x1]
end

operator quantized_delta[f: QuantizedFunction, x1: Numeric, x2: Numeric]: Integer
    return f[x2] - f[x1]
end


const integer_lambda = lambda [x: Integer]: Integer
    return x
end

const continuous_lambda = lambda [x: Numeric]: Numeric
    return x
end

const quantized_lambda = lambda [x: Numeric]: Integer
    return round[x]
end


operator test[]
    state a = discrete_delta[integer_lambda, 10, 20] -- ок, возвращает 10
    state b = discrete_delta[continuous_lambda, 30, 50] -- ок, возвращает 20.0
    state c = discrete_delta[quantized_lambda , 100, 500] -- ок, возвращает 400
    state d = quantized_delta[integer_lambda, 0.1, 2.3] -- плохо, integer_lambda не умеет работать с Numeric
    state e = quantized_delta[continuous_lambda, 4.5, 6.7] -- плохо, continuous_lambda не всегда возвращает Integer
    state f = quantized_delta[quantized_lambda , 8.9, 10.1] -- ок, возвращает 1
end

#27
22:00, 1 окт. 2018

Delfigamer
> Я ещё подумал, и осознал, что фигня это и ничерта не работает
а подумал ли ты над тем зачем тебе в командном языке
вот те самые пере-определения самих команд на другие типы
.. это если внтури терминального режима команда_Акс равна типу_команд_Зет (допустим "открыть двери")
и зачем-то понадобиться переопределить на новый тип это же Название_Команды (family)
(а здесь что патч новый что ли без совместимости со старой версией)
тогда понадобиться инструментарий переопределения который позволит переопределить (команду)
команда_Акс равна типу_команд_Альфа ((допустим "открыть двери паролем"))
тогда , да : но это же не есть само-суть .. просто определение/переопределение Типа Команды и Суть Команды
что есть ли Сущность Команды : тут уже структура Команды в кодинге : можно разные структуры
для разных Типов Команд и для одинкаковых Типов КОманд тоже можно же
.. здесь всего пара основных кодо-свойств команды по типу определение-переопределение
и присвоение и переприсвоение нового смысла данной команды оно может работать и как присвоение
а переприсвоение дополнительная тулза-инструментарий

Delfigamer
вот есть же писание что желательно иметь процедурный вопрос

команда_1_1 команда_2_1
команда_1_2 команда_2_2
команда_1_3 команда_2_3

Тип Команды 1 тчк Суть Команды 2

а сами команды 1 -го типа и 2 -го типа как разные типы команд
если команда состоит из кОманды "Стыковка"

Стыковка.Саттелит1 Открыть.Док1
Стыковка.Саттелит2 Открыть.Док2
Стыковка.Саттелит3 Открыть.Док3

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

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

в монолитной команде
Стыковка.Саттелит1 Открыть.Док1
может быть вариация
Стыковка.Саттелит1 Открыть.Док3

или
Стыковка.Саттелит2 Открыть.Док3
а первого саттелита вообще может и не быть , да и док два подраздолбали лазерами
где еще и это проверить : это же Верификация Команд
уже сразу в рентабельности Списка Команд в Индикаторе Команды

..

в в динамической команде
Стыковка.Саттелит1 Открыть.Док1
может быть вариация когда док1 ^ занят/ нет контакта-связи / перегружен / временно не доступен / док / лаунч
.. потому заменить на доступнй , если есть отдельное условие Тру (ну есть оно где-то там на Корабле
когда размер дока подходит размеру корабля Тру Валу) и заменить же на другой валидный док
Стыковка.Саттелит1 Открыть.Док3

док открыт можете стыковаться : можно идти на стыковку заранее , а открыть Док по Дельте (при подлете)

Delfigamer
> Любую лямбду можно безопасно заменить на альтернативу, результат которой
> удовлетворяет более строгим ограничениям.

> Любую лямбду можно безопасно заменить на альтернативу, которая справляется с
> более широким множеством аргументов

уж наверняка здесь ты должен уже достичь просветления :)
тем более что это все больше похоже в расширении как Множества Vs Множества
хотя теория множеств в самой своей теории более плоский юмор

#28
22:08, 1 окт. 2018

Delfigamer
Ты же слышал про ковариантность и контравариантность?

#29
9:21, 2 окт. 2018

Morphia
> а подумал ли ты над тем зачем тебе в командном языке
Я подумал и решил, что мне не нужен командный язык.

kipar
> Ты же слышал про ковариантность и контравариантность?
Конечно, я их и пытаюсь описать так, чтобы компилятор мог их самостоятельно вывести и проверить.

Страницы: 1 2 3 426 Следующая »
ФлеймФорумПрограммирование