|
Макросы
|
|||
---|---|---|---|
#18+
Есть 3 вопроса по макросам 1. Можно как-то генерировать многострочные макросы? 2. Использую#define TestMacro ##SafeExpression($$aa^B())для генерирации COS кода. Как достичь аналогичного результата с использованием методов классов? Например (не компилируется):#define TestMacro2 ##SafeExpression(##class(App.Gen).GenCOS()))Есть вариант с#define TestMacro3 ##function($ClassMethod("App.Test","GenCOS"))Но хотелось бы просто писать ##class(App.Gen).GenCOS() 3. Возможно передать в макрос произвольное количество аргументов? Как args... только для макросов. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.05.2015, 17:48 |
|
Макросы
|
|||
---|---|---|---|
#18+
eduard931. Можно как-то генерировать многострочные макросы? ##continue 2. ##expression и ##safeexpression с использованием кода из класса в mac коде работает, из другого класса кстати тоже без проблем. Может все таки ошибку компиляции приложишь, а так только гадание на кофейной гуще получается. eduard933. Возможно передать в макрос произвольное количество аргументов? Как args... только для макросов. # def1arg ... |
|||
:
Нравится:
Не нравится:
|
|||
11.05.2015, 21:56 |
|
Макросы
|
|||
---|---|---|---|
#18+
DAiMor, 1. Ошибся, имеется в виду в коде, вызываемом макросом. Хочу, чтобы он возвращал несколько строк кода, а не одну как в методе GetString. 2. Код:Class App.Test Extends %RegisteredObject { ClassMethod Test() { #define Hello(%in) ##safeexpression(##class(App.Test).GetString(%in)) w $$$Hello("abc") } ClassMethod GetString(str) { q "Hello "_str } }Выдает ошибку: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8.
Код: sql 1.
Как это исправить? Попробовал добавить ##Quote над ##safeexpression, но тогда генерируется w "##safeexpression(##class(App.Test).GetString(""abc""))" Думал, что решилС помощью модификации метода GetString: ClassMethod GetString(str) { q """Hello "_str_"" } Но при компиляции вылезают ошибки. Сравнить с компиляцией после ClassMethod GetString(str) { q """Hello "_str_"""" } 3. Спасибо, то что надо. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.05.2015, 23:07 |
|
Макросы
|
|||
---|---|---|---|
#18+
ClassMethod GetString(str) { quit """Hello: "_str_"""" }#define hello(%str) ##expression(##class(User.Test).GetString(%str)) w $$$hello("John") ... |
|||
:
Нравится:
Не нравится:
|
|||
11.05.2015, 23:25 |
|
Макросы
|
|||
---|---|---|---|
#18+
DAiMor, Заработало, но разве ##safeexpression и ##expression не должны иметь одинаковое поведение при одном классе? Docs - http://docs.intersystems.com/cache20151/csp/docbook/DocBook.UI.Page.cls?KEY=GCOS_macros#GCOS_C5959 When a method contains an ##Expression this is detected when the class is compiled. Because the compiler does not parse the content of the ##Expression, this ##Expression could generate different code in a subclass. To avoid this, Cache causes the compiler to regenerate the method code for each subclass. For example, ##Expression(%classname) inserts the current classname; when you compile a subclass, the code expects it will insert the subclass classname. Cache forces this method to be regenerated in the subclass to ensure that this occurs. If you know that the code will never be different in a subclass, you can avoid regenerating the method for each subclass. To do this, substitute the ##SafeExpression preprocessor directive for ##Expression. These two preprocessor directives are otherwise identical. Добавление ещё одной кавычки в GetString вижу. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.05.2015, 23:50 |
|
Макросы
|
|||
---|---|---|---|
#18+
eduard931. Ошибся, имеется в виду в коде, вызываемом макросом. Хочу, чтобы он возвращал несколько строк кода, а не одну как в методе GetString.похоже, что так сделать не получится почему то компилятор при получении многострочного результата ругается на то что ожидается конец строки. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.05.2015, 07:59 |
|
Макросы
|
|||
---|---|---|---|
#18+
eduard93Заработало, но разве ##safeexpression и ##expression не должны иметь одинаковое поведение при одном классе?а разве это не так ? ... |
|||
:
Нравится:
Не нравится:
|
|||
12.05.2015, 07:59 |
|
Макросы
|
|||
---|---|---|---|
#18+
eduard931. Ошибся, имеется в виду в коде, вызываемом макросом. Хочу, чтобы он возвращал несколько строк кода, а не одну как в методе GetString.Используйте CodeMode = objectgenerator eduard932.Class App.Test Extends %RegisteredObject { ClassMethod Test() { #define Hello1(%in) ##safeexpression(##class(App.Test).GetString1(%in)) #define Hello2(%in) ##safeexpression(##class(App.Test).GetString2(%in)) w $$$Hello1("abc") w $$$Hello2("abc") } ClassMethod GetString1(str) As %String [ CodeMode = expression ] { $$$quote("Hello ")_"_"_$$$quote(str) } ClassMethod GetString2(str) As %String [ CodeMode = expression ] { $$$quote("Hello "_str) } }РезультатzTest() public { w "Hello "_"abc" w "Hello abc" } ... |
|||
:
Нравится:
Не нравится:
|
|||
12.05.2015, 09:19 |
|
Макросы
|
|||
---|---|---|---|
#18+
servitИспользуйте CodeMode = objectgeneratorКак его использовать для генерации кода в макросе? Вот например нужен макрос - написать строку n раз:Class App.Test Extends %RegisteredObject { ClassMethod Test() { #define WriteNTimes(%str,%cnt) ##safeexpression(##class(App.Test).GenStrings(%str,%cnt)) $$$WriteNTimes("Hello World!",2) } ClassMethod GenStrings(string As %String = "", count As %Integer = 1) [ CodeMode = objectgenerator ] { For i = 1:1:$g(count,0) { Do %code.WriteLine(" Write """ _ $g(string) _ """,!") } Quit $$$OK } }При компиляции ошибка:Studio Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
Ещё такой вопрос: возможны ли необязательные аргументы в макросах:ClassMethod UnrequiredArgs() { #define Log(%lvl,%msg) w "Level: ",%lvl,!,"Message: ",$g(%msg),! $$$Log(0,"It's a message!") $$$Log(0) }Ошибка.Studio Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
do ##class(App.Test).UnrequiredArgs() ... |
|||
:
Нравится:
Не нравится:
|
|||
13.05.2015, 21:10 |
|
Макросы
|
|||
---|---|---|---|
#18+
eduard93Как его использовать для генерации кода в макросе?В макросе - никак. Генерация нескольких строк - это уже целая программа, что противоречит концепции простой одностроковой подстановки: Conventions for Macro Values . К тому же в этом случае возникают доп. вопросы, например с метками.eduard93Вот например нужен макрос - написать строку n раз:У Вас вперемешку run-time и compile-time. Например, так:Class App.Test [ Abstract ] { Parameter count = 2; Parameter string = "Hello World!"; ClassMethod Test() { d ..WriteNTimes1(),..WriteNTimes2(),..WriteNTimes3(),..UnrequiredArgs() } /// управление через параметры класса ClassMethod WriteNTimes1() [ CodeMode = objectgenerator ] { For i = 1:1:$G(%parameter("count"),0) { Do %code.WriteLine($$$FormatText(" Write %1,!",$$$quote($G(%parameter("string"))))) } } /// управление непосредственно ClassMethod WriteNTimes2() [ CodeMode = objectgenerator ] { For i = 1:1:4 { Do %code.WriteLine($$$FormatText(" Write %1,!",$$$quote(i_" : "_i))) } } /// управление через глобалы ClassMethod WriteNTimes3() [ CodeMode = objectgenerator ] { #Execute s ^count=5,^string="test" /* до компиляции ^count и ^string должны уже содержать нужные значения */ For i = 1:1:$G(^count,0) { Do %code.WriteLine($$$FormatText(" Write %1,!",$$$quote($G(^string)))) } } ClassMethod UnrequiredArgs() [ PlaceAfter = WriteNTimes3 ] { #def1arg Log(%args) ##safeexpression("w "_##Quote("Level: ")_","_$li(%literalargs,1)_",!,"_##Quote("Message: ")_","_$s($ll(%literalargs)>1:$li(%literalargs,2),1:##Quote(""))_",!") #def1arg Log1(%args) ##safeexpression(##class(App.Test).Log(%literalargs)) $$$Log(0,"It's a message!") $$$Log(0) $$$Log1(,,,"asd") $$$Log1("","",,,,,"asd") } ClassMethod Log(list As %List) As %String [ PlaceAfter = UnrequiredArgs ] { s lvl=$li(list,1) s msg=$s($ll(list)>1:$li(list,2),1:"") s:lvl="" lvl=$$$quote(lvl) s:msg="" msg=$$$quote(msg) q "w "_##Quote("Level: ")_","_lvl_",!,"_##Quote("Message: ")_","_msg_",!" } }Результат компиляции:zTest() public { d ..WriteNTimes1(),..WriteNTimes2(),..WriteNTimes3(),..UnrequiredArgs() } zWriteNTimes1() public { Write "Hello World!",! Write "Hello World!",! } zWriteNTimes2() public { Write "1 : 1",! Write "2 : 2",! Write "3 : 3",! Write "4 : 4",! } zWriteNTimes3() public { Write "test",! Write "test",! Write "test",! Write "test",! Write "test",! } zUnrequiredArgs() public { w "Level: ",0,!,"Message: ","It's a message!",! w "Level: ",0,!,"Message: ","",! w "Level: ","",!,"Message: ","",! w "Level: ","",!,"Message: ","",! } ... |
|||
:
Нравится:
Не нравится:
|
|||
14.05.2015, 13:45 |
|
Макросы
|
|||
---|---|---|---|
#18+
servit Макросы в InterSystems Caché eduard93Компилятор классов использует определение класса для генерации MAC кодаДокументация
... |
|||
:
Нравится:
Не нравится:
|
|||
29.05.2015, 12:33 |
|
Макросы
|
|||
---|---|---|---|
#18+
Alexey MaslovСтоило бы упомянуть и о том, что команда $$$Многострочного_Макроса должна быть единственной в строке. <...> Попробуйте, например, вернуть значение из многострочного макроса (как его может вернуть однострочный макрос-выражение). <...> Понятно, что через переменную вернуть можно (нарушая все правила приличия ))). Не увидел в вашем примере конструкций вида: set result=$$$SomeMacro(...) Например:test.MAC n a,b,c #Define MyAdd(%a,%b) $$%mmmuMyAdd(%a,%b) ##continue #IfNDef 0 ##continue #Define 0 ##continue g ##Unique(new) ##continue %mmmuMyAdd(a,b) {##continue q a+b ##continue } ##continue ##Unique(old) ##continue #EndIf ##continue ##Lit() s a=$$$MyAdd(1,2) w a,! s b=$$$MyAdd(2,3) w b,! s c=$$$MyAdd(3,4) w c,! s a=$$%mmmuMyAdd(1,2) g %mmmu1 %mmmuMyAdd(a,b) { q a+b } %mmmu1 w a,! s b=$$%mmmuMyAdd(2,3) w b,! s c=$$%mmmuMyAdd(3,4) w c,!Результат Код: plaintext 1. 2. 3.
... |
|||
:
Нравится:
Не нравится:
|
|||
29.05.2015, 15:06 |
|
Макросы
|
|||
---|---|---|---|
#18+
MAC генерируется в очень редких случаях: например, если в классе есть методы-генераторы и наличествует флаг компиляции "k" ( Keep Generated Source Code ). ПримерClass my.a Extends %RegisteredObject { /// w ##class(my.a).MyAdd1(1,2) ClassMethod MyAdd1( a, b) As %Integer [ CodeMode = generator, PlaceAfter = MyAdd2 ] { $$$GENERATE(" #Define c1 11") $$$GENERATE(" Quit a+b+$$$c1+$$$c2") } /// w ##class(my.a).MyAdd2(1,2) ClassMethod MyAdd2( a, b) As %Integer [ CodeMode = objectgenerator ] { Do %code.WriteLine(" #Define c2 22") Do %code.WriteLine(" Quit a+b+$$$c2") } } ... |
|||
:
Нравится:
Не нравится:
|
|||
29.05.2015, 16:04 |
|
Макросы
|
|||
---|---|---|---|
#18+
servit#Define MyAdd(%a,%b) $$%mmmuMyAdd(%a,%b) ##continue ... Всё ждал, когда подобный пример предложит Эдуард, но так и не дождался... Как говорится, "типа круто", но итог проделанных ухищрений: в макроопределение упрятана функция. В чём полезность сего деяния? Чем это лучше (гибче, etc), чем просто написать такую же точно функцию и явно её вызывать? ... |
|||
:
Нравится:
Не нравится:
|
|||
29.05.2015, 16:27 |
|
Макросы
|
|||
---|---|---|---|
#18+
Alexey MaslovКак говорится, " типа круто ", но итог проделанных ухищрений <...> В чём полезность сего деяния? Чем это лучше (гибче, etc) <...>? - Папа, сделай мне iPhone. По прошествии времени ... - На, сынок. - В чём полезность сего деяния? Чем это лучше стандартного iPhone? - ?! Вывод: папе раньше нужно было спрашивать: "А тебе это зачем, сынок?" Собственно сам вопрос не с этой ли целью задавался, не ради ли "возможно/невозможно/как"? Инструмент предоставляет возможности. Как ими распорядиться или не распорядиться - решать разработчику. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.05.2015, 17:30 |
|
Макросы
|
|||
---|---|---|---|
#18+
Вы, похоже, лучше меня знаете, что и зачем я спрашиваю. Даже когда спрашиваю в другом месте и другого человека ))) ... |
|||
:
Нравится:
Не нравится:
|
|||
29.05.2015, 18:09 |
|
Макросы
|
|||
---|---|---|---|
#18+
servitAlexey Maslovпропущено... А вы проверьте на практике…В WRC тоже считают, что INT. Обещали поправить документацию.Официальный ответ WRC (от разработчиков):"When you compile a class we generate MAC code in a temporary array, but this is never saved as a MAC routine and in fact it is not even valid as a MAC routine as it is just a series of method fragments which we stitch together. Then we ask the macro processor to turn these fragments into INT code and this INT code may be saved if the 'k' flag is present when we combine these fragments into a routine. So cls->int->obj is probably the correct order, with the mac piece being hidden from users so it should not be documented as such." So the mac part is more of an internal process and the documentation will be changed accordingly. eduard93 , Исправлять ли статью решать Вам. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.06.2015, 09:12 |
|
Макросы
|
|||
---|---|---|---|
#18+
Документация<...> Generated routines are routines which are derived or created by compiling other routines or classes. There are two types of generated routines: 1. .INT code which is created when Caché compiles a .MAC file, or a class. 2. .MAC code which is created when Caché compiles certain types of classes. источник servit How These Code Elements Work Together Во вчерашнем билде 2015.2.FT документацию в обоих случаях уже исправили и картинку заменили. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.06.2015, 09:09 |
|
|
start [/forum/topic.php?fid=39&msg=38955847&tid=1556647]: |
0ms |
get settings: |
9ms |
get forum list: |
16ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
77ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
53ms |
get tp. blocked users: |
1ms |
others: | 269ms |
total: | 446ms |
0 / 0 |