Помощь новичкам


#166

:= имеет особый смысл для размерных и ссылочных типов. Нельзя. И в C# нельзя


#167

Спасибо, я понял. Сбила с толку “Справка”.

Перегружать можно все операции за исключением @ (взятие адреса), as, is, new. Кроме того, можно перегружать специальные бинарные операции +=, -=, *=, /=, не возвращающие значений.

На самом деле также нельзя перегружать операцию ^, теперь еще выяснили с =. А что еще нельзя из списка?

@, not, ^, +, - (унарные), new *, /, div, mod, and, shl, shr, as, is +, - (бинарные), or, xor =, <>, <, >, <=, >=, in ?:

А то я планирую делать реализацию векторов и матриц для линейной алгебры и думаю перегружать операции, в частности, хочу для скалярного произведения взять *, а для векторного думаю про and


#168

Всё можно. Нельзя ?: new as is := не операция!!!


#169

А ведь и правда…это оператор! А у меня на ^ ругалось… хотел его выбрать для векторного произведения вначале.


#170

оператор := перегружать можно


#171

Ох… а почему тогда не работает код в этом сообщении?


#172

Опишите operator:= как функцию. И P лучше записью сделать (в сущности для этого перегрузка и предназначена). Иначе не получится объект pp.


#173

Спасибо, понял. Попробую…


#174

function GetTArr<T>(c:integer) := new T[c];

пару недель нашёл такого типа функцию где то в system или PABCSystem, в общем где то… попробовал сам - действительно компилятор принимает, но как её надо вызывать? ещё при описании всплывает логический вопрос “откуда паскаль узнает что за тип T?” и при вызове GetTArr(5); или даже var a:array of integer := GetTArr(5); выскакивает соответствующая ошибка… так как же это можно вызывать?

P.S. нашёл! PABCSystem строка 10466:

function GetRuntimeSize<T>: integer;
var val: T;
begin
  result := System.Runtime.InteropServices.Marshal.SizeOf(val);
end;

просто так использовать как и мою GetTArr не получается


#175

Попробуйте так: var a:= GetTArr&<integer>(5);


#176

Пусть проектируется некий модуль, содержимое которого пользователь впоследствии не сможет менять. Модуль вызывается из пользовательской программы и получает от нее набор параметров, в том числе и имя некоторой процедуры или функции, также определяемой пользователем.

Вызов может иметь вид A(p1,p2,p3,f(x,y,z,…),p4,…), т.е. количество и тип параметров вызова А определяется интерфейсом модуля. Функция (или процедура) f может вызываться непосредственно из пользовательской программы и тут все понятно: вызов организует пользователь. Но она также должна передаваться на любую глубину вызова и внутри модуля. Если это некая f(x), то тут все понятно, потому что интерфейс функции известен. Но если интерфейс может меняться (например, меняется тип и количество параметров, то как тут поступить? params предполагает передачу переменного числа параметров но в виде массива из однотипных элементов. А если аргументами являются переменные разных типов, часть параметров - это вообще массивы… Конечно, совсем ничего не знать об интерфейсе внутри модуля - так не бывает, поскольку тогда непонятно, что с этой функцией делать. У меня есть мысль реализовать функцию, как объект некоего класса и передать в качестве параметров ссылку на такой объект. Но для этого пользователь должен уметь работать с классами. А нет ли более простого решения? Хочется, чтобы как в Фортране (например) было - передаем в списке только имя функции f, но её интерфейс не расписываем, поскольку он пока что неизвестен. Вариант type=function f(…) мне не представляется удачным: такой тип нельзя определить при создании модуля все по той же причине неконкретности интерфейса на момент написания модуля.


#177

Вы рассказываете сложные вещи. Очевидно, и реализуются они непросто.

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

Насколько я понял, Вы хотите вызывать инициализацию модуля (процедура A) извне этого модуля - из пользовательский программы. Это, разумеется, плохо и противоречит принципу модульности.

Теперь давайте отвлечемся от абстрактной критики, и Вы приведёте конкретный простой (очень простой) пример того, что бы хотелось сделать и для чего. Конкретный. Потому что решать такую задачу в общем случае может оказаться сложно, а в частном - достаточно просто.

Кто вызывает процедуру A? Функция f вызывается в самой A и Вы передаете в A лишь процедурную переменную или Вы передаете в A результат вызова f с конкретными параметрами?


#178

Ну конечно, большие сложности… Почему-то в гораздо более примитивном Fortran-IV еще пятьдесят (!) лет назад можно было писать про функцию или подпрограмму external f и не думать о наборе параметров этой функции, просто указывая f в списке параметров или вызова. А уж там вообще не было динамических объектов. Эти сложности возникли в Паскале из-за того, что Н.Вирт не пожелал включить в него неэффективно реализуемый на тот момент алголовский “вызов по наименованию”, но ничего не предложил взамен. В фортране - чего уж проще - вместо функции передается ссылка на некий dope-vector - таблицу с управляющей информацией. Более того, там функция может содержать вызов другой функции… и все равно мы пишем лишь некое f.

Удивительно. К примеру, модуль вычисляет значение определенного интеграла. “Плохо и противоречит”, что подинтегральную функцию я определяют вне модуля и передаю её в этот модуль? А мне казалось, что это обычная практика работы с готовыми библиотеками… Да, это функция одного аргумента с точки зрения интеграла, но она сама может оказаться зависимой еще от ряда параметров, часть из которых также зависят от х, например, быть кусочной, содержать вызов вложенной функции и .т.д

Чем больше пишу кода в рамках создания библиотеки численных методов, тем больше понимаю, что или я некомпетентен в этой реализации Паскаля, или эта реализация не ориентирована на подобные проекты. Каждый численный метод предполагает свои типы данных, интерфейсы… и в рамках одного модуля их крайне сложно сдружить.


#179

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

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

Я говорил про инициализацию модуля, а не про это. [quote=“RAlex, post:178, topic:263”] Чем больше пишу кода в рамках создания библиотеки численных методов, тем больше понимаю, что или я некомпетентен в этой реализации Паскаля, или эта реализация не ориентирована на подобные проекты [/quote] Думаю, скорее, первое. Но может быть и нельзя. Я бы попросил Вас ссылаться не на Фортран, который всё-таки старый язык и в нём можно делать много вещей, которые с точки зрения безопасного программирования и контроля типов катастрофичны. Например, приведите пример на C или C++ или Delphi. Про “эту реализацию Паскаля” я не понял вовсе - а что, в других реализациях Паскаля есть то, что Вы хотите? Тогда смело об этом говорите. С примерами - еще раз подчеркну. Иначе я не смогу Вам помочь.

В C++ например есть объекты-функции для вызова функций с разным количеством аргументов - здесь можно сделать что-то подобное, используя классы или лямбды - в зависимости от того, что Вам надо. Пишите код.

И еще раз повторю свои вопросы, на которые не получил ответа:

Кто вызывает процедуру A? Функция f вызывается в самой A и Вы передаете в A лишь процедурную переменную или Вы передаете в A результат вызова f с конкретными параметрами?


#180

Это где нельзя? В fortran 95 можно по-прежнему. И чего же тут “слава богу”, если это затрудняет программирование?[quote=“Admin, post:179, topic:263”] Я бы попросил Вас ссылаться не на Фортран, который всё-таки старый язык и в нём можно делать много вещей, [/quote] Да, но переношу программы-то я все же в основном из фортрана… Я и так воюю, простите, с механизмами, А) которых вообще нет в Паскале: общие области, разовая инициализация части данных при первом входе и последующее сохранение этих данных для следующего входа (в Algol-60 это было own), передача функций по имени и кое-что еще, Б) на которые наложен запрет в этой реализации Паскаля: метки, внутриблочные определения функций и процедур…В) отсутствием возможности собрать библиотеку из отдельных модулей с тем, чтобы можно использовать единый uses

Я имел в виду, что “эта реализация” во многом уже не Паскаль в традиционном понимании, а скорее С# в синтаксисе Паскаля с некоторыми вкусняшками из Python и Haskell. И что ДАЖЕ В НЕЙ нет таких механизмов.

В целом проблема такая. Изначально было понятно, что нужно подключение пакета единым uses ИМЯ; Уже сейчас в программах пакетов начались коллизии. Многие программы пакета хотят получать ссылки на процедуры и функции, которые они затем будут вызывать и делегировать на более низкие уровни. Определение некоего типа Type f=function(x:real);real; не годится, поскольку для большинства программ пакета эти функции отличаются набором параметров. Определять function1, function2, function n -это садизм по отношению к пользователям. Если бы пакет можно было собрать из отдельных модулей, в каждом бы определилась своя function и вопрос решен. То же и с переменными. Есть некие программные единицы, которые должны помнить историю предыдущего входа, т.е. при первом входе некие переменные инициализировать, после выхода их сохранять (т.е. некая глобальная область переменных?), а при последующем входе использовать сохраненные значения. Например, так поступают итераторы при решении систем дифференциальных уравнений. Если вынести такие переменные в общую область пакета (что я и делаю), то их там уже много накопилось и начинаются коллизии имен. Локализация в модуле могла бы решить проблему. Чтобы скомпоновать библиотеку в единый модуль все её программы не должны конфликтовать друг с другом. А если там будет сто программных единиц? Двести? Для всех пытаться сделать какую-то локализацию? Но Паскаль этого ТЕПЕРЬ не умеет, потому что @ibond объявил нелегитимными внутриблочные процедуры.

Другим решением могла бы стать автоматическая компоновка из различных модулей. К примеру, сейчас мы создаем и отлаживаем 50 модулей: mod1, mod2, … mod50, затем их копируем в общий файл, с огромной головной болью устраняем возникшие коллизии и получаем некий модуль, который пользователь может подключить по uses. Куда проще было бы откомпилировать каждый из этих модулей, но не подключать потом их по конкретному списку uses, а по-прежнему сослаться на некую “библиотеку”, содержащую список всех модулей и уже через нее выполнить необходимую компоновку. Возможно, для этого “библиотека” должна содержать какие-то директивы…[quote=“Admin, post:179, topic:263”] Кто вызывает процедуру A? Функция f вызывается в самой A и Вы передаете в A лишь процедурную переменную или Вы передаете в A результат вызова f с конкретными параметрами? [/quote]

Процедуру А, как видно из рисунка, вызывает написанная пользователем программа. Также, пользователь пишет процедуру/функцию, которую нужно передать в модуль… Эту функцию пользователь может также (при необходимости) вызвать непосредственно. Далее, мы передаем в модуль процедурную переменную с тем, чтобы уже внутри модуля процедура А могла вызвать написанную пользователем функцию, а также передать её процедурам В и С с тем, чтобы и те могли вызывать эту функцию. Пример. Мы интегрируем систему дифференциальных уравнений методом Рунге-Кутты и нам нужна для этого процедура, вычисляющая значения функции и её производной. Мы вызываем модуль, решающий данную задачу и передаем ему упомянутую процедуру F. Процедура А использует вызов процедуры F на каждой итерации, а затем вызывает одношаговый интегратор B, который получает определяет решение на заданном шаге с нужной точностью, для чего ему тоже нужно обращаться к F. Понятно, что интерфейс для вызова F нужен как в А, так и в В, иначе будет невозможно откомпилировать модуль. Но в то же время на момент компиляции модуля мы не знаем окончательного набора параметров, который потребуется для F (например, может понадобиться проверка граничных условий, а тогда нужно передать эти границы…). Следовательно, интерфейс должен допускать некоторую абстракцию, иначе непонятно, что делать.

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


#181

Не надо бояться работать с классами и интерфейсами. Они сильно облегчают нам жизнь.


#182

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

И да, может не сюда с этим надо, но все же: нельзя ли многострадальный отладчик (уже писали, что часто его “заглючивает” и он то не желает остановиться на точке прерывания, то наоборот, продолжает останавливаться на уже отмененной точке. Лечится перезапуском среды), так вот, нельзя ли этот отладчик научить останавливаться по изменению содержимого указанных простых переменных и по достижению ими какого-то конкретного значения или условию, например, х=8, a<5 и т.п.? Очень сильно этого не хватает… в сложных итерационных алгоритмах тяжело на сотнях и тысячах итераций понять, где ошибка.


#183

В связи в тем, что олимпиады пишутся на FPC, где встроенной сортировки вроде как нету, а я заинтересован в быстроте работы, то хочу поинтересоваться:

какой алгоритм используется в процедуре Sort ?


#184

Никита, олимпиады уже не пишутся на FPC. У нас есть статистика, показывающая, что FPC был за последние три года вытеснен PascalемABC.NET.

Sort реализует какой-то вариант быстрой сортировки с асимптотической сложностью n*log(n). Писать его самому нельзя: ошибётесь и будет неэффективно.


#185

Новички сейчас, знаете ли, другие пошли. Семиклассники вполне осваивают классы, ТАК ЧТО НЕ БОЙТЕСЬ ИХ. Давайте я всё-таки буду приводить код, а то мы вертимся в замкнутом кругу. Вы пытаетесь придумывать для PascalABC какие-то мифические вещи, которых там нет.

Вот то, что есть. Я говорил уже про объекты-функции:

type Fun = auto class
  a,b: real;
  function f(x: real) := a*x+b;
end;

begin
  var ff := Fun.Create(2,3);
  var g: real->real := ff.f;
  Print(g(3));
end.

ff - объект-функция, при ее создании в конструктор передаются все параметры, которые Вам нужны. g - процедурная переменная, которая хранит ссылку на метод конкретного объекта, инициализированного конкретными параметрами. Обратите внимание, что тип у g - человеческий: real->real.

Код приведите

Давайте договоримся: в .NET библиотека - это dll, модуль - это в Паскале unit, который затем подключается в секции uses

Этого нет в современных языках

Внутриблочные - это внутри begin-end - Вы ничего не путаете? В паскале этого нет. В C#, Java, C++ и подавно. Механизмы фортрана и алгола - они для фортрана и алгола. Не надо пытаться перенести сюда их опыт. Тут надо пользоваться классами и интерфейсами для аналогичных целей.[quote=“RAlex, post:178, topic:263”] в гораздо более примитивном Fortran-IV еще пятьдесят (!) лет назад можно было писать про функцию или подпрограмму external f и не думать о наборе параметров этой функции, просто указывая f в списке параметров или вызова [/quote] Приведите код пожалуйста чтобы мы поняли, о чем речь

У меня голова дымится от этого текста. Видимо, вместо “программы” Вы имеете в виду “подпрограммы”. А что Вы подразумеваете под пакетом? Пакетов в PascalABC.NET нет.

Что такое более низкие уровни? Не заставляйте меня расшифровывать Ваши фразы - приведите код.

@ibond ничего такого не делал. Внутриблочных процедур у нас как не было так и нет. вложенные подпрограммы - есть, но они ограничены в возможностях. Например, их нельзя передавать по ссылке. Их одновременное использование с лямбдами чисто технически затруднительно реализовать, хотя и возможно. Кроме того, использование вложенных подпрограмм нами считается плохим стилем программирования и не рекомендуется к использованию. Надо в частности понимать, что код .NET, в который это всё переводится, не содержит такого примитива как вложенные подпрограммы.