FreeBasic
Главная
Вход
Регистрация
Четверг, 18.04.2024, 23:07Приветствую Вас Гость | RSS
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Форум » Freebasic » Вопросы по языку FreeBasic » Пространства имён
Пространства имён
DarkDemonДата: Воскресенье, 08.07.2018, 05:43 | Сообщение # 1
Полковник
Группа: Друзья
Сообщений: 188
Репутация: -2
Статус: Offline
Стас, приветствую! Здарова всем! 
Когда последний раз садился за компилятор, а было это пару месяцев назад, помню поймал много гемора,
когда попытался в пространствах имён использовать REDIM. Да было некоторое, такое лёгкое удивление.
Вообще забавно всё это. Есть ли у кого идеи, что могло разработчикам помешать реализовать данный
функционал, может быть какие-то существенные логические противоречия-парадоксы?
Просто из-за подобной штуки приходится довольно сильно изворачиваться, всё пилить руками через
ALLOCATE и указатели, не то чтобы сложно, просто лишние хлопоты.

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

Кто что думает по поводу пространств имён и всей этой ситуёвины?

P.S: тема поболтать, разнюхать обстановку в кодерской среде, обсудить в 100500 раз холёную FB-шечку)))
 
haavДата: Воскресенье, 08.07.2018, 15:50 | Сообщение # 2
Генералиссимус
Группа: Администраторы
Сообщений: 1361
Репутация: 49
Статус: Offline
Привет Леха!

Цитата DarkDemon ()
Когда последний раз садился за компилятор, а было это пару месяцев назад, помню поймал много гемора,
когда попытался в пространствах имён использовать REDIM. Да было некоторое, такое лёгкое удивление.


Я не в теме , можешь пример привести , где этот гимор прослеживается?

Цитата DarkDemon ()
Кто что думает по поводу пространств имён и всей этой ситуёвины?


Так че тут думать? Хочешь в последствии использовать код повторно , сразу думай о модульности и пространствах имен. Я несколько раз использовал namespace , пока ни разу не пожалел.

Если модулей задумывается много , лучше сразу подумать о makefile (на моем сайте есть небольшая статья как по быстрому их использовать). Сэкономишь кучу времени!

Пространства имен дают огромное преимущество при соединении различных кодов (даже от разных авторов).


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
DarkDemonДата: Воскресенье, 08.07.2018, 17:42 | Сообщение # 3
Полковник
Группа: Друзья
Сообщений: 188
Репутация: -2
Статус: 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 рубит прогу на куски(как будто на отдельные исходники - для человека, который использует ассемблер
и видит листинги с именами переменных, сегментов и т.п. это крайне логично), а доступ предоставляет через
имя пространства с точкой, а как полез тестить, припух перепух))) ну я всегда припухаю, ты знаешь))) подвох
жеж на ровном месте.

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

Выходит 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
Репутация: 49
Статус: 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
Репутация: -2
Статус: 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


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

Кстати форум искажает код(!!!), ничего не могу с этим поделать(закрепил исходник вложением).
Прикрепления: TestString.bas (2.6 Kb)


Сообщение отредактировал DarkDemon - Понедельник, 09.07.2018, 10:59
 
DarkDemonДата: Вторник, 10.07.2018, 13:30 | Сообщение # 6
Полковник
Группа: Друзья
Сообщений: 188
Репутация: -2
Статус: Offline
Допилил код, потестировал и оформил. Всё во вложении. Вариант простецкий.

Добавлено (10.07.2018, 13:30)
---------------------------------------------
Ещё у меня была дурацкая идея сделать специально для этой цели транслятор поверх FBC,
который бы парсил оператор NAMESPACE, убирал его, переименовывал все переменные
+ давал доступ так же через точку к ним и далее запускал FBC. Т.е. преобразовать исходник.
Идея так себе, т.к. код бы прилично обфусцировался при необходимости передавать его
другим людям с FBC, но без данной надстройки.

Прикрепления: 1112959.bas (6.8 Kb)
 
VitaminДата: Пятница, 12.04.2019, 11:28 | Сообщение # 7
Лейтенант
Группа: Пользователи
Сообщений: 55
Репутация: 4
Статус: 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
Репутация: -2
Статус: 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


Хоть и был написан велосипед, не жалею об этом, оно всё равно на пользу. Всем и каждому рекомендую
решать вопросы своими силами в любом случае.
 
Форум » Freebasic » Вопросы по языку FreeBasic » Пространства имён
  • Страница 1 из 1
  • 1
Поиск: