OberonCore
https://forum.oberoncore.ru/

Проверка типов оператором IS
https://forum.oberoncore.ru/viewtopic.php?f=1&t=6863
Страница 1 из 1

Автор:  AlexBogy [ Вторник, 13 Сентябрь, 2022 07:50 ]
Заголовок сообщения:  Проверка типов оператором IS

Прошу вашей помощи в понимании следующего вопроса. Есть вот такой пример:
Код:
    MODULE TestExt;
    IMPORT Log;
    TYPE
       pbas=POINTER TO bas;
       bas=EXTENSIBLE RECORD
                a:INTEGER;
             END;
       pras=POINTER TO ras;
       ras=RECORD(bas)
                b:REAL;
             END;
    VAR
       a:pbas;
       b:pras;
    BEGIN
       NEW(a);
       NEW(b);
       a:=b;
       IF a^ IS ras THEN
                          Log.String("Проверка по типу");
       ELSE
       END;
    END TestExt.


При компиляции выдаётся ошибка Guarded or tested variable is neither a pointer nor a VAR- or IN-parameter record.
Проверка по указателю ошибок компиляции не вызывает:
Код:
MODULE TestExt;
IMPORT Log;
TYPE
   pbas=POINTER TO bas;
   bas=EXTENSIBLE RECORD
            a:INTEGER;
         END;
   pras=POINTER TO ras;
   ras=RECORD(bas)
            b:REAL;
         END;
VAR
   a:pbas;
   b:pras;
BEGIN
   NEW(a);
   NEW(b);
   a:=b;
   IF a IS pras THEN
                      Log.String("Проверка по указателю");
   ELSE
   END;
END TestExt.


Почему для проверки по типу записи необходимо делать процедуру с параметрами VAR или IN ?

Автор:  Comdiv [ Вторник, 13 Сентябрь, 2022 14:22 ]
Заголовок сообщения:  Re: Проверка типов оператором IS

AlexBogy писал(а):
Почему для проверки по типу записи необходимо делать процедуру с параметрами VAR или IN ?
Не совсем так, такой необходимости нет. Дело в другом - в языке была сделана попытка сделать недопустимыми бессмысленные проверки, которые всегда имеют одно и то же значение. В большинстве случаев для записей проверка имеет смысл только для ссылок, поставляющие данные извне, которые неявным образом задаются VAR и IN -параметрами. Отсутствие возможности проверки типа для разыменованного указателя - это побочный эффект такого ограничения и его можно считать упущением языка, так как здесь она тоже осмысленна. Это некритично, так как в таких случаях всегда можно проверить тип по указателю, не прибегая к разыменованию, хотя и может потребоваться объявить именованный указатель на соответствующую запись, если он не был предоставлен с самого начала.

Код:
MODULE TestExt; IMPORT Log;
TYPE
  bas=EXTENSIBLE RECORD a:INTEGER  END;
  ras=RECORD(bas) b:REAL; END;
VAR
  a:POINTER TO bas; b:POINTER TO ras;

PROCEDURE Go*;
TYPE pras = POINTER TO ras;(* Нужен исключительно для проверки IS *)
BEGIN
  NEW(b);
  a:=b;
  IF a IS pras THEN
    Log.String("a^ is ras"); Log.Ln
  END
END Go;

END TestExt.


Это, скорее, для раздела Почему в Обероне сделано так?

Автор:  AlexBogy [ Вторник, 13 Сентябрь, 2022 15:48 ]
Заголовок сообщения:  Re: Проверка типов оператором IS

Comdiv писал(а):
AlexBogy писал(а):
Почему для проверки по типу записи необходимо делать процедуру с параметрами VAR или IN ?
Не совсем так, такой необходимости нет. Дело в другом - в языке была сделана попытка сделать недопустимыми бессмысленные проверки, которые всегда имеют одно и то же значение. В большинстве случаев для записей проверка имеет смысл только для ссылок, поставляющие данные извне, которые неявным образом задаются VAR и IN -параметрами. Отсутствие возможности проверки типа для разыменованного указателя - это побочный эффект такого ограничения и его можно считать упущением языка, так как здесь она тоже осмысленна. Это некритично, так как в таких случаях всегда можно проверить тип по указателю, не прибегая к разыменованию, хотя и может потребоваться объявить именованный указатель на соответствующую запись, если он не был предоставлен с самого начала.

Код:
MODULE TestExt; IMPORT Log;
TYPE
  bas=EXTENSIBLE RECORD a:INTEGER  END;
  ras=RECORD(bas) b:REAL; END;
VAR
  a:POINTER TO bas; b:POINTER TO ras;

PROCEDURE Go*;
TYPE pras = POINTER TO ras;(* Нужен исключительно для проверки IS *)
BEGIN
  NEW(b);
  a:=b;
  IF a IS pras THEN
    Log.String("a^ is ras"); Log.Ln
  END
END Go;

END TestExt.


Это, скорее, для раздела Почему в Обероне сделано так?


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

Код:
MODULE TestExt;
IMPORT Log;
TYPE
   bas=EXTENSIBLE RECORD
            a:INTEGER;
         END;
   ras=RECORD(bas)
         b:REAL;
         END;
VAR
   c:bas;
   d:ras;
PROCEDURE Test (VAR x:bas);
BEGIN
   IF x IS ras THEN
                     Log.String("Расширенный тип");
                     Log.Ln;
   ELSE
            Log.String("Базовый тип");
            Log.Ln;
   END;
END Test;
BEGIN
   Test(c);
   Test(d);
END TestExt.


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

Правило типа для параметров VAR смягчено: тип фактических параметров может быть расширением типа формального параметра VAR.

Автор:  Comdiv [ Вторник, 13 Сентябрь, 2022 17:40 ]
Заголовок сообщения:  Re: Проверка типов оператором IS

Цитата:
По поводу бессмысленных проверок с заранее известным результатом - можно ли вот такой пример считать примером бессмысленных проверок:
Нельзя. Компилятор использует лишь простые проверки осмысленности, и закладывать в языке общего назначения большее - это глупость, потому что приведёт к более сложной минимальной реализации. В совокупности с другими схожими требованиями это может осложнить задачу на один-два порядка в зависимости от аппетита. Это уже задача для опционального анализатора. И это то, как реализация влияет на дизайн.

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

Автор:  AlexBogy [ Вторник, 13 Сентябрь, 2022 17:56 ]
Заголовок сообщения:  Re: Проверка типов оператором IS

Comdiv писал(а):
Цитата:
По поводу бессмысленных проверок с заранее известным результатом - можно ли вот такой пример считать примером бессмысленных проверок:
Нельзя. Компилятор использует лишь простые проверки осмысленности, и закладывать в языке общего назначения большее - это глупость, потому что приведёт к более сложной минимальной реализации. В совокупности с другими схожими требованиями это может осложнить задачу на один-два порядка в зависимости от аппетита. Это уже задача для опционального анализатора. И это то, как реализация влияет на дизайн.

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


Я заранее извиняюсь, поскольку не программист по образованию, поэтому могу некорректно употреблять термины. И мы, видимо, не совсем понимаем друг друга. Вот код:
Код:
MODULE TestExt;
IMPORT Log;
TYPE
   pbas=POINTER TO bas;
   bas=EXTENSIBLE RECORD
            a:INTEGER;
            END;
   pras=POINTER TO ras;
   ras=RECORD (bas)
            b:REAL;
            END;
VAR
   c:pbas;
   d:pras;
PROCEDURE Test(VAR x:bas);
BEGIN
   IF x IS ras THEN
                     Log.String('Расширенный тип');
                     Log.Ln;
   ELSE
            Log.String('Базовый тип');
            Log.Ln;
   END;
END Test;
BEGIN
   NEW(c);
   NEW(d);
   Test(c^);
   Test(d^);
END TestExt.


Он корректно работает. Мой вопрос такой - почему через процедуру сравнить разыменованный указатель с типом записи можно, а напрямую, в теле модуля, нельзя?

Автор:  Comdiv [ Вторник, 13 Сентябрь, 2022 18:17 ]
Заголовок сообщения:  Re: Проверка типов оператором IS

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

1. Можете сказать, зачем Вам нужна проверка типа записи у разыменованного указателя вместо проверки непосредственно указателя?

И вернёмся к примеру.
2. Понимаете, почему в процедуре проверка типа записи VAR-параметра осмысленна, так как фактический тип параметра в вызванной процедуре неизвестен?
3. Понимаете, почему проверка типа записи непосредственно объявленной переменной бессмысленна, так как её тип в момент проверки известен?

Автор:  AlexBogy [ Вторник, 13 Сентябрь, 2022 20:10 ]
Заголовок сообщения:  Re: Проверка типов оператором IS

Просто когда я стал изучать расширение записи, меня заинтересовала данная ошибка компиляции. Ваш ответ меня убедил, благодарю Вас.

Автор:  AlexBogy [ Среда, 14 Сентябрь, 2022 21:59 ]
Заголовок сообщения:  Re: Проверка типов оператором IS

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

1. Можете сказать, зачем Вам нужна проверка типа записи у разыменованного указателя вместо проверки непосредственно указателя?

И вернёмся к примеру.
2. Понимаете, почему в процедуре проверка типа записи VAR-параметра осмысленна, так как фактический тип параметра в вызванной процедуре неизвестен?
3. Понимаете, почему проверка типа записи непосредственно объявленной переменной бессмысленна, так как её тип в момент проверки известен?


Я Ваш ответ для себя интерпретировал следующим образом:
1. Разыменованный типовой указатель подобен статической записи, поэтому сравнение одной статической записи с другой бессмысленно.
2. Идентификаторы VAR и IN в процедурах описывают параметры-переменные, которые поэтому могут считаться динамическими типами.
3. Указатели считаются динамическими типами, поэтому проверка типов может осуществляться как в процедуре, так и в теле модуля.

Автор:  Comdiv [ Среда, 14 Сентябрь, 2022 22:26 ]
Заголовок сообщения:  Re: Проверка типов оператором IS

1. Разыменованный указатель не подобен статической записи, так как точный тип структуры разыменованного указателя в общем случае неизвестен статически и здесь, действительно, можно было бы проверять тип, но эта проверка легко заменяется на проверку указателя без его разыменования и это по сути ничего не меняет. Большинство людей никогда не встречается с необходимостью проверки типа разыменованного указателя, а не его самого. То есть, смысл есть, но насущной потребности нет.
2. Параметры-переменные для записей по своим свойствам частично подобны указателям на записи.
3. В КП указатели и VAR и IN-параметры и только они позволяют ссылаться как на непосредственно тот тип записи, что был указан в объявлении, так и на номинально расширенные от него записи, поэтому в этих и только в этих случаях проверка имеет смысл.

Автор:  AlexBogy [ Четверг, 15 Сентябрь, 2022 07:17 ]
Заголовок сообщения:  Re: Проверка типов оператором IS

Comdiv писал(а):
1. Разыменованный указатель не подобен статической записи, так как точный тип структуры разыменованного указателя в общем случае неизвестен статически и здесь, действительно, можно было бы проверять тип, но эта проверка легко заменяется на проверку указателя без его разыменования и это по сути ничего не меняет. Большинство людей никогда не встречается с необходимостью проверки типа разыменованного указателя, а не его самого. То есть, смысл есть, но насущной потребности нет.
2. Параметры-переменные для записей по своим свойствам частично подобны указателям на записи.
3. В КП указатели и VAR и IN-параметры и только они позволяют ссылаться как на непосредственно тот тип записи, что был указан в объявлении, так и на номинально расширенные от него записи, поэтому в этих и только в этих случаях проверка имеет смысл.

Благодарю вас за подробные ответы.

Автор:  AlexBogy [ Пятница, 16 Сентябрь, 2022 07:27 ]
Заголовок сообщения:  Re: Проверка типов оператором IS

Comdiv писал(а):
1. Разыменованный указатель не подобен статической записи, так как точный тип структуры разыменованного указателя в общем случае неизвестен статически и здесь, действительно, можно было бы проверять тип, но эта проверка легко заменяется на проверку указателя без его разыменования и это по сути ничего не меняет. Большинство людей никогда не встречается с необходимостью проверки типа разыменованного указателя, а не его самого. То есть, смысл есть, но насущной потребности нет.
2. Параметры-переменные для записей по своим свойствам частично подобны указателям на записи.
3. В КП указатели и VAR и IN-параметры и только они позволяют ссылаться как на непосредственно тот тип записи, что был указан в объявлении, так и на номинально расширенные от него записи, поэтому в этих и только в этих случаях проверка имеет смысл.


И я бы хотел прояснить отличия в операторах IS и WITH. Насколько я понял, результатом оператора p IS T будет то, что p является типом T или его расширениями, поэтому доступ к полям осуществляется в виде p(T).имя поля, а результатом оператора WITH p:T будет то, что p строго соответствует типу T и доступ к полям осуществляется обычной записью p.имя поля?

Автор:  Иван Денисов [ Пятница, 16 Сентябрь, 2022 07:59 ]
Заголовок сообщения:  Re: Проверка типов оператором IS

Нет, результат проверки одинаковый. IS также сработает и для предка. Однако IS не может трактовать, что потом будет с этой записью делаться, поэтому и тип автоматически не кастует для дальнейшего кода. Вы можете проверить тип, а потом запись использовать как угодно или вообще не использовать. А вот WITH предопределяет дальнейшее использование записи в своём теле однозначно, именно как наследника определённого типа.

Автор:  AlexBogy [ Пятница, 16 Сентябрь, 2022 09:37 ]
Заголовок сообщения:  Re: Проверка типов оператором IS

Иван Денисов писал(а):
Нет, результат проверки одинаковый. IS также сработает и для предка. Однако IS не может трактовать, что потом будет с этой записью делаться, поэтому и тип автоматически не кастует для дальнейшего кода. Вы можете проверить тип, а потом запись использовать как угодно или вообще не использовать. А вот WITH предопределяет дальнейшее использование записи в своём теле однозначно, именно как наследника определённого типа.


Я имел в виду, что IS рассматривает указанный объект p как динамический, который на момент проверки имеет тип T, поэтому и обращается к нему как p(T), а WITH рассматривает объект p как статический типа T, поэтому обращается к нему просто как p.

Автор:  Comdiv [ Пятница, 16 Сентябрь, 2022 22:38 ]
Заголовок сообщения:  Re: Проверка типов оператором IS

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

Конкретно WITH можно конструктивно выразить через IS и var(Type), ровно как и наоборот. Не стоит искать сложные интерпретации в духе того, как это может делать человек. Конструкцию языка ничего не рассматривают.

Автор:  AlexBogy [ Пятница, 16 Сентябрь, 2022 23:04 ]
Заголовок сообщения:  Re: Проверка типов оператором IS

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

Конкретно WITH можно конструктивно выразить через IS и var(Type), ровно как и наоборот. Не стоит искать сложные интерпретации в духе того, как это может делать человек. Конструкцию языка ничего не рассматривают.


Благодарю вас за разъяснения.

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/