Пространства имён
|
|
DarkDemon | Дата: Воскресенье, 08.07.2018, 05:43 | Сообщение # 1 |
Полковник
Группа: Друзья
Сообщений: 188
Статус: Offline
| Стас, приветствую! Здарова всем! Когда последний раз садился за компилятор, а было это пару месяцев назад, помню поймал много гемора, когда попытался в пространствах имён использовать REDIM. Да было некоторое, такое лёгкое удивление. Вообще забавно всё это. Есть ли у кого идеи, что могло разработчикам помешать реализовать данный функционал, может быть какие-то существенные логические противоречия-парадоксы? Просто из-за подобной штуки приходится довольно сильно изворачиваться, всё пилить руками через ALLOCATE и указатели, не то чтобы сложно, просто лишние хлопоты.
Собственно, с чего всё это, тут наконец меня петух в жопу клюнул и типа осознал, что весь свой код надо бы уже приводить в порядок и оформлять отдельными пространствами для пущей "модульности".
Кто что думает по поводу пространств имён и всей этой ситуёвины?
P.S: тема поболтать, разнюхать обстановку в кодерской среде, обсудить в 100500 раз холёную FB-шечку)))
|
|
| |
haav | Дата: Воскресенье, 08.07.2018, 15:50 | Сообщение # 2 |
Генералиссимус
Группа: Администраторы
Сообщений: 1361
Статус: Offline
| Привет Леха!
Цитата DarkDemon ( ) Когда последний раз садился за компилятор, а было это пару месяцев назад, помню поймал много гемора, когда попытался в пространствах имён использовать REDIM. Да было некоторое, такое лёгкое удивление.
Я не в теме , можешь пример привести , где этот гимор прослеживается?
Цитата DarkDemon ( ) Кто что думает по поводу пространств имён и всей этой ситуёвины?
Так че тут думать? Хочешь в последствии использовать код повторно , сразу думай о модульности и пространствах имен. Я несколько раз использовал namespace , пока ни разу не пожалел.
Если модулей задумывается много , лучше сразу подумать о makefile (на моем сайте есть небольшая статья как по быстрому их использовать). Сэкономишь кучу времени!
Пространства имен дают огромное преимущество при соединении различных кодов (даже от разных авторов).
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
DarkDemon | Дата: Воскресенье, 08.07.2018, 17:42 | Сообщение # 3 |
Полковник
Группа: Друзья
Сообщений: 188
Статус: Offline
| Цитата haav ( ) можешь пример привести , где этот гимор прослеживается? Ну самый банальный пример, часто использую строковый массив. Ну а чё, удобно, нативно, завёл массив строк, где не хватило, сделал REDIM. Всё пахает, хотим завернуть в namespace, оно нам сразу вышибает что нельзя.
Код NAMESPACE MyModule DIM F(10) AS STRING 'REDIM F(10) AS STRING ' Заместо DIM выдаст ошибку
SUB MyProc () 'REDIM PRESERVE F(20) AS STRING ' Если сделать по массиву DIM - то массив сдохнет F(15) = "Bla bla bla" END SUB
END NAMESPACE
MyModule.MyProc PRINT MyModule.F(15), UBOUND(MyModule.F) SLEEP Более того, DIM вообще работает забавно, что пишешь SHARED, что не пишешь SHARED, функции и процедуры "видят" этот массив. Помню первоначально, когда я поверхностно ознакамливался, ну подумал мол просто NAMESPACE рубит прогу на куски(как будто на отдельные исходники - для человека, который использует ассемблер и видит листинги с именами переменных, сегментов и т.п. это крайне логично), а доступ предоставляет через имя пространства с точкой, а как полез тестить, припух перепух))) ну я всегда припухаю, ты знаешь))) подвох жеж на ровном месте.
Соответственно для такой простой штуки типа строкового массива начинаются огороды с собственным списком, что усложняет код, сказывается на читаемости программы и может нести потенциальные баги при кривой реализации списка. Помню в последний раз меня это просто задрало, я тупо, чтобы побыстрее протестить, завёл огромный нескончаемый массив но это сам понимаешь, такое себе решение, временное и предельно галимое. Ну просто реально лень было ковыряться, т.к. прога была писана изначально в виде отдельного исходника, думал просто оберну, а тут на тебе - компилятор мне по щам как даст с размаху.
Выходит NAMESPACE то, конечно, NAMESPACE, но всё предполагаемые преимущества списаны на нет, т.е. я как раз и хотел избавиться от возможного "перекрестия" имён переменных\массивов, потребность в уникальных именах функций например в разы меньше, т.к. всегда можно написать MyModule_MyProc ну или в таком духе и вероятность совпадения с уже имеющимся любым кодом снизится почти до нуля. С переменными такого гавна делать не хочется, люблю когда всё чистенько, а в коде они используются часто и увеличение даже на пару символов может раздуть код визуально очень прилично.
Я то конечно хомяк тот ещё, у меня всегда есть план прозапас - библиотеки + namespace(примеры есть в справке), там что-то типа Код Extern "c++" Lib "mylib" Namespace mylib Alias "mylib" Declare Function test() As Integer End Namespace End Extern но мы получаем гемор со сборкой библ + со сборкой такого типа исходников (я хотел от *.bi хедеров избавиться на совсем, задрали они ещё со времён QuickBasic постоянно подключать их в послеконстантной секции и дополнять отдельно по добавлении функционала) исходники конечно удобнее крутить вертеть во всех смыслах. Просто ну раз нельзя значит есть какие-то особенности при текущей реализации, может ООП мешает или что-то из c++ функционала(там же всё базируется на нём и билдится в него изначально).
Или может быть есть какие-либо ещё каверзные нюансы? Но на самом деле забавно, ведь по идее DIM - это и есть тот же самый ALLOCATE.Добавлено (08.07.2018, 17:42) --------------------------------------------- А ну да, есть ещё один вариант, разработчики решили таким образом "прокачать" новичкам скил по указателям.
Сообщение отредактировал DarkDemon - Воскресенье, 08.07.2018, 17:28 |
|
| |
haav | Дата: Воскресенье, 08.07.2018, 18:41 | Сообщение # 4 |
Генералиссимус
Группа: Администраторы
Сообщений: 1361
Статус: Offline
| Леха, вот отрывок из переведенной справки:
Цитата Переменная, объявленная внутри пространства имен, всегда неявно статическая и видна на протяжении всей программы даже если модификатор декларации Shared не указан (static и shared являются необязательными).
Судя по всему , слово статическая как бы намекает , что динамические REDIM невозможны , что и сообщает компиль. Так же тут указано , что все типы по любому shared. Вот такая петрушка. Как то я не сталкивался с этой проблемой , я обычно стараюсь объединять переменные в типах . То есть у меня почти всегда так:
type blabla все переменные end type
dim shared bla as blabla
или
dim bla as blabla ptr = new blabla
Такой способ дает возможность в IDE в "автозавершении" быстро выбирать\писать имена переменных.
Однако я согласен с тобой - эта реализация namespace фиговато выглядит. Я не знаю как в С++ , возможно так же , ведь разрабы FB все нововведения старались копировать из плюсов.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
DarkDemon | Дата: Понедельник, 09.07.2018, 10:43 | Сообщение # 5 |
Полковник
Группа: Друзья
Сообщений: 188
Статус: Offline
| Цитата haav ( ) Переменная, объявленная внутри пространства имен, всегда неявно статическая и видна на протяжении всей программы даже если модификатор декларации Shared не указан (static и shared являются необязательными). Цитата haav ( ) ведь разрабы FB все нововведения старались копировать из плюсов.
Ага понятно. Т.е. они так реализовали. Спасибо Стас, прояснил эту тему насколько возможно.
То что всё статично, кстати, заметил, даже попытался использовать разные режимы диалекта чтобы прописать $DYNAMIC, разумеется, нифига не вышло))), позабавил факт того что в процедуре функции REDIM таки написать можно, но он нишиша не сработает, разрушая массив, а UBOUND при этом показывает старую размерность.
Судя по справке они это делали больше для типов, что кстати к вышеозвученному хорошо подходит, но у меня другой стиль кодирования. Твой стиль интересен и похож на вариант инкапсуляции. У меня это бывает, но не так часто и только, когда какой-либо аспект хочется сгруппировать.
Думаю, чуть позже надо будет в этой теме написать минимальный код замены. Хотя бы строкового массива, с обычным массивом то там попроще, ALLOCATE\REALLOCATE.
Кстати REDIM внутри функций в NAMESPASE работает нормально, просто обычно требуется иметь значения динамич. размерностей на протяжении всей работы программы, а после отработки функции они не сохраняются.
Добавлено (09.07.2018, 10:43) --------------------------------------------- А ещё, последнее время, когда меня что-то задирает, стараюсь решать вопрос))), чтобы меньше задирало, полазал тут по справке гляжу NEW, с Паскаля холёного эта штука уплыла, а помню-то смутно, ну и полез шерстить что там к чему, в итоге минут за 30 накалякал такое, вопрос вроде решает, да и хлеба не просит.
Код '$LANG: "FB"
NAMESPACE Example
TYPE StringDIM LoIndex AS INTEGER HiIndex AS INTEGER PtrToStr AS STRING PTR END TYPE
' Строковый массив для долговременного использования DIM MySpis AS StringDIM
' Аналог функции резервирования массива SUB MakeDIM (BYREF NameDIM AS StringDIM, Lo AS INTEGER, Hi AS INTEGER) DIM LengthDIM AS INTEGER
' Если массив ещё не выделен - выделяем. IF NameDIM.PtrToStr = FALSE THEN ' Проверяем верность границ IF Lo < Hi THEN NameDIM.LoIndex = Lo: NameDIM.HiIndex = Hi ELSE NameDIM.LoIndex = Hi: NameDIM.HiIndex = Lo END IF ' Считаем длину массива LengthDIM = (NameDIM.HiIndex - NameDIM.LoIndex) + 1 NameDIM.PtrToStr = NEW STRING [LengthDIM]END IF
END SUB
' Пишем значение в массив SUB SetVal (BYREF NameDIM AS StringDIM, Index AS INTEGER, BYREF Value AS STRING) DIM NIndex AS INTEGER = Index
IF Index >= NameDIM.LoIndex AND Index <= NameDIM.HiIndex THEN NIndex -= NameDIM.LoIndex NameDIM.PtrToStr [NIndex]= Value END IF
END SUB
' Читаем значение из массива FUNCTION GetVal (BYREF NameDIM AS StringDIM, Index AS INTEGER) AS STRING DIM NIndex AS INTEGER = Index
IF Index >= NameDIM.LoIndex AND Index <= NameDIM.HiIndex THEN NIndex -= NameDIM.LoIndex COLOR 12: PRINT NIndex; ", "; : COLOR 7 ' >>> DEBUG <<< !!! RETURN NameDIM.PtrToStr [NIndex]END IF END FUNCTION
' Освобождаем память SUB KillDIM (BYREF NameDIM AS StringDIM) DELETE[] NameDIM.PtrToStr END SUB
' Функции для тестирования работы самопального массива ' Присвоить тестовые значения
SUB SetValues (BYREF NameDIM AS StringDIM) DIM i AS INTEGER, i2 AS INTEGER DIM RandSlov AS STRING FOR i = NameDIM.LoIndex TO NameDIM.HiIndex
RandSlov = "" FOR i2 = 1 TO (i - NameDIM.LoIndex) + 1 RandSlov = RandSlov + CHR(65 + (i - NameDIM.LoIndex)) NEXT
SetVal NameDIM, i, RandSlov
NEXT END SUB
' Распечатать массив SUB PrintSpis (BYREF NameDIM AS StringDIM) DIM i AS INTEGER FOR i = NameDIM.LoIndex TO NameDIM.HiIndex
WRITE i, GetVal(NameDIM, i)
NEXT END SUB
SUB Test () 'DIM MySpis AS StringDIM ' Можно и внутри процедуры это использовать MakeDIM (MySpis, -5, 3) SetValues MySpis PrintSpis MySpis KillDIM MySpis END SUB
END NAMESPACE
Example.Test ' Тестируем
SLEEP
Единственное чё, меня гложут смутные сомнения, что как-то жутко криво освобождаю память. Этот нюанс не тестировал, так что на страх и риск кодеров, проверяйте, перед юзанием.
Кстати форум искажает код(!!!), ничего не могу с этим поделать(закрепил исходник вложением).
Сообщение отредактировал DarkDemon - Понедельник, 09.07.2018, 10:59 |
|
| |
DarkDemon | Дата: Вторник, 10.07.2018, 13:30 | Сообщение # 6 |
Полковник
Группа: Друзья
Сообщений: 188
Статус: Offline
| Допилил код, потестировал и оформил. Всё во вложении. Вариант простецкий. Добавлено (10.07.2018, 13:30) --------------------------------------------- Ещё у меня была дурацкая идея сделать специально для этой цели транслятор поверх FBC, который бы парсил оператор NAMESPACE, убирал его, переименовывал все переменные + давал доступ так же через точку к ним и далее запускал FBC. Т.е. преобразовать исходник. Идея так себе, т.к. код бы прилично обфусцировался при необходимости передавать его другим людям с FBC, но без данной надстройки.
|
|
| |
Vitamin | Дата: Пятница, 12.04.2019, 11:28 | Сообщение # 7 |
Лейтенант
Группа: Пользователи
Сообщений: 55
Статус: Offline
| DarkDemon Если запихнуть динамический массив в Тип, то вроде как работает и дополнительного кода получается не много: Код Namespace MyModule
Type t s(Any) As String ' динамический массив End Type
Dim mas As t ' динамический массив внутри Типа
Sub MyProc () ReDim Preserve mas.s(20) ' меняем размер массива mas.s(15) = "Bla bla bla" End Sub
End Namespace
MyModule.MyProc ? MyModule.mas.s(15), UBound(MyModule.mas.s) Sleep
Сообщение отредактировал Vitamin - Пятница, 12.04.2019, 11:29 |
|
| |
DarkDemon | Дата: Пятница, 12.04.2019, 23:27 | Сообщение # 8 |
Полковник
Группа: Друзья
Сообщений: 188
Статус: Offline
| Vitamin, да подсказали уже давно. Никаких типов не надо. Была там одна слабо документированная фича. Прошаренные ребята откопали. В двух словах можно написать так:
Код NAMESPACE MyModule DIM s() AS STRING SUB Init (Num AS UINTEGER) DIM i AS UINTEGER REDIM s(Num) FOR i = 0 TO Num s(i) = STRING(i + 1, "*") NEXT END SUB END NAMESPACE
DIM i AS UINTEGER MyModule.Init 5 FOR i = 0 TO 5 WRITE MyModule.s(i) NEXT SLEEP
Хоть и был написан велосипед, не жалею об этом, оно всё равно на пользу. Всем и каждому рекомендую решать вопросы своими силами в любом случае.
|
|
| |
|