Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« : 09-07-2013 11:26 » |
|
пока ещё не знаю, как точно вопрос задать
Одновременно в двух проектах на C++ потребовалась поддержка какого-нибудь языка (без наворотов, чтобы пользователь мог написать в виде текста небольшой отрывок кода, а программа могла бы понимать этот язык "на лету")
Пример, как это может понадобиться - "на вход" приходит значение, это значение обрабатывается функцией пользователя и выдаётся "на выход"
Входные параметры я могу передать функции в программе и сам - в текстовом виде. Затем интерпретатор это всё пережёвывает, после чего я забираю выходные данные
Подскажите, что имеется уже в природе или нет такое ?
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #1 : 09-07-2013 11:46 » |
|
Алексей++, посмотрите в сторону lua ( www.lua.org), очень неплохой, шустрый и компактный язык, довольно легко встраивается в программы на C/C++.
|
|
« Последнее редактирование: 09-07-2013 11:51 от darkelf »
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #2 : 09-07-2013 14:34 » |
|
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Sla
|
|
« Ответ #3 : 09-07-2013 18:55 » |
|
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
RXL
|
|
« Ответ #4 : 09-07-2013 19:34 » |
|
Многие скриптовые языки имеют возможность запуска себя из чужого кода. Сперва надо определить требования, поверх наложить маску пожеланий и результат в студию.
|
|
« Последнее редактирование: 09-07-2013 19:36 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #5 : 10-07-2013 03:35 » |
|
Dimka, у меня же не шарп. Не совсем понял, как мне тот пост поможет
darkelf, Sla, RXL, сейчас почитаю
|
|
|
Записан
|
|
|
|
zubr
Гость
|
|
« Ответ #6 : 10-07-2013 03:57 » |
|
Насколько я понимаю, для любого скриптового языка нужна виртуальная машина, которая будет интерпретировать скриптовый язык в байт-код и выполнять его. То есть это должна быть какая то внешняя программа, которую надо будет тягать вместе с программой или использовать какую то виртуальную машину, встроенную в систему.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #7 : 10-07-2013 04:23 » |
|
Tcl - сложный синтаксис, низкое быстродействие http://ru.wikipedia.org/wiki/Tclhttp://www.tcl.tk/Lua - на первый взгляд самое то (синтаксис терпимый, быстродействие по описанию неплохое, распространённость. Имеются исходники на C - вот самое интересное) http://ru.wikipedia.org/wiki/Luahttp://www.lua.org/about.htmlмануал http://www.lua.org/manual/5.1/zubr, да, это у меня ещё пока в тумане, ещё не вник, как вызвать "текстовую" функцию из своего кода и получить результат её работы. Виртуальная машина, я думаю, не обязательно должна быть запущена постоянно. Например, я вызываю функцию библиотеки движка, передаю ей текст программы, параметры, получаю ответ. Это тоже должно быть, мне кажется http://www.ibm.com/developerworks/ru/library/l-lua/-> http://lua-users.org/wiki/LuaBinaries--> http://luabinaries.sourceforge.net/---> http://sourceforge.net/projects/luabinaries/files/5.2.1/static, dynamic версии
|
|
« Последнее редактирование: 10-07-2013 05:16 от Алексей++ »
|
Записан
|
|
|
|
RXL
|
|
« Ответ #8 : 10-07-2013 06:08 » |
|
Интерпретатор может быть запущен постоянно в отдельном процессе, а можно запускать по необходимости. Все зависит от того, как в него можно подавать команды: через файл, через стандартный ввод процесса, через вызовы API. Производительнее, соотв., постоянно запущенный. Интерпретация может быть текста программы или байт-кода. Соотв., байт-код будет быстрее на этап синтаксического разбора и компиляции. Если скрипт использует библиотеки, постоянно запущенный интерпретатор может их подгрузить заранее. И не забудь о контроле ошибок интерпретатора.
|
|
« Последнее редактирование: 10-07-2013 06:11 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Sla
|
|
« Ответ #9 : 10-07-2013 06:08 » |
|
Tcl - сложный синтаксис, низкое быстродействие Ты че? с дуба свалился? 32к serial port почти в реалтайме. Какое тебе еще нужно быстродействие? Ты хочешь предоставить пользователю управлять чем-то, или автоматизировать какой-то процесс. Потерпит. 0.75сек (lua) ничем не отличается от 0,76сек(tcl) Синтаксис? Не сложнее бейсика
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #10 : 10-07-2013 06:29 » |
|
Sla, не всё сразу, я уже за Lua принялся ))
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #11 : 10-07-2013 06:36 » |
|
Алексей++, ну если ты внимательно прочитаешь, там написано, что вместо C# может быть любой язык. В том числе тобою любимый C++.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
zubr
Гость
|
|
« Ответ #12 : 10-07-2013 08:16 » |
|
Как вариант заюзать ява-скрипт или VB-скрипт, а в качестве виртуальной машины старый добрый осел IE, который запускать как COM-объект в невидимом режиме.
|
|
|
Записан
|
|
|
|
Kivals
|
|
« Ответ #13 : 10-07-2013 08:26 » |
|
Ну ежели дело дошло до VBScript/JScript то и я свои 5 копеек вставлю в 1С у себя использую объект MSScriptControl.ScriptControl (правда я использую для других целей, но в этой задаче тоже подойдет) - ИЕ не нужен...
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #14 : 10-07-2013 09:04 » |
|
не не, IE точно не нужно )) я разобрался, как статически слинковать lua библиотеку, тестовый пример прошёл. Щас с типом userdata разберусь - и дело практически в шляпе. Оказывается, при закачке нужно обращать внимание на версию студии, а то будет трах с линкером - я поначалу для vs11 качнул, а у меня 9 Dimka, тогда я не понимаю, как этим постом по ссылке воспользоваться Расскажи
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #15 : 10-07-2013 12:10 » |
|
Алексей++, всё, что на C# написано, написать на C++ - элементарно. Единственное, что там важно, это JScript - вот он такой, какой есть.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #16 : 11-07-2013 06:09 » |
|
я уж начал с LUA разбираться, я пока что с ним продолжу ) застопорился здесь: на стек не помещается результат работы функции. В чём загвоздка ? (click to show) int error=0; lua_State* L =luaL_newstate();
if(L) { std::string errortext; std::string chunk; int luaErr=0;
chunk="function f(a,b) return a+b end"; luaErr=luaL_loadbuffer(L, &chunk[0], chunk.size(), 0);
if(0==luaErr) {
lua_getglobal(L, "f");//функция для вызова lua_pushnumber(L, 3); lua_pushnumber(L, 6);
luaErr=lua_pcall(L,1+2,1,0);
if(0==luaErr) { int result=0;
//смотрю результат в стеке result=lua_tonumber(L, -1);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>> //result==0
lua_pop(L, 1);
} else { errortext=lua_tostring(L, -1); lua_pop(L, 1); //извлечь сообщение об ошибке из стека
} }
lua_close(L); }
тестовый проект прицепляю, чтобы было можно попробовать "не напрягаясь" - в архиве есть всё нужное вместе с библиотекой Приведённый код находится в файле tDlg.cpp Добавлено через 31 минуту и 35 секунд:ну и параллельно смотрю JScript, так как наличие классов тоже, возможно, потребуется
|
test.rar (216.6 Кб - загружено 870 раз.)
|
« Последнее редактирование: 11-07-2013 06:40 от Алексей1153 »
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #17 : 11-07-2013 07:04 » |
|
застопорился здесь: на стек не помещается результат работы функции. В чём загвоздка ?
тестовый проект прицепляю, чтобы было можно попробовать "не напрягаясь" - в архиве есть всё нужное вместе с библиотекой
Приведённый код находится в файле tDlg.cpp я уж начал с LUA разбираться, я пока что с ним продолжу )
К сожалению собрать не получается - при линковке выдаёт: 1>uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) already defined in LIBCMTD.lib(new.obj) 1>uafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) already defined in LIBCMTD.lib(dbgdel.obj) 1>LIBCMT.lib(invarg.obj) : error LNK2005: __initp_misc_invarg already defined in LIBCMTD.lib(invarg.obj) 1>LIBCMT.lib(invarg.obj) : error LNK2005: __call_reportfault already defined in LIBCMTD.lib(invarg.obj) 1>LIBCMT.lib(invarg.obj) : error LNK2005: __set_invalid_parameter_handler already defined in LIBCMTD.lib(invarg.obj) 1>LIBCMT.lib(invarg.obj) : error LNK2005: __get_invalid_parameter_handler already defined in LIBCMTD.lib(invarg.obj) 1>LIBCMT.lib(invarg.obj) : error LNK2005: __invoke_watson already defined in LIBCMTD.lib(invarg.obj) 1>LIBCMT.lib(invarg.obj) : error LNK2005: "void __cdecl _invoke_watson(unsigned short const *,unsigned short const *,unsigned short const *,unsigned int,unsigned int)" (?_invoke_watson@@YAXPBG00II@Z) already defined in LIBCMTD.lib(invarg.obj) 1>LIBCMT.lib(invarg.obj) : error LNK2005: __invalid_parameter already defined in LIBCMTD.lib(invarg.obj) 1>LIBCMT.lib(invarg.obj) : error LNK2005: "void __cdecl _invalid_parameter(unsigned short const *,unsigned short const *,unsigned short const *,unsigned int,unsigned int)" (?_invalid_parameter@@YAXPBG00II@Z) already defined in LIBCMTD.lib(invarg.obj) 1>LIBCMT.lib(invarg.obj) : error LNK2005: ___pInvalidArgHandler already defined in LIBCMTD.lib(invarg.obj) 1>LINK : warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs; use /NODEFAULTLIB:library
Visual Studio 2010
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #18 : 11-07-2013 07:10 » |
|
darkelf, это да, у меня студия 9 , а тебе, значит, нужны файлы для 10 . Вот тут http://sourceforge.net/projects/luabinaries/files/5.2.1/Windows%20Libraries/Static/либо lua-5.2.1_Win32_vc10_lib.zip либо lua-5.2.1_Win64_vc10_lib.zip (2010 - это ведь 10 ? А то там ещё для 11 есть версии) и файл *.hpp переименуй на *.cpp ------------------------------------------- а есть ли в природе готовые C++ классы, реализующие JScript ? В тырнете не нашёл. Пока что непонятно, как выполнить скрипт на JScript из C++ - функции . Кроме как, конечно, динамически подключить jscript.dll , интерфейс которой я пока ещё не знаю ))
|
|
« Последнее редактирование: 11-07-2013 07:14 от Алексей++ »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #19 : 11-07-2013 07:44 » |
|
Sla, смотрю ещё Incr tcl ---------- #include "itcl32\include\itcl.h" #include "itcl32\include\itclDecls.h" #include "itcl32\include\itclInt.h" #include "itcl32\include\itclIntDecls.h" #include "itcl32\include\itk.h" #include "itcl32\include\itkDecls.h" хм, ругается на отсутствие tcl.h , а такого там нет вообще Слава, куда бечь ?
|
|
« Последнее редактирование: 11-07-2013 07:59 от Алексей++ »
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #20 : 11-07-2013 08:23 » |
|
Даже с теми библиотеками всё-равно получились те-же ошибки. На базе Вашего примера написал свой - в итоге получилось следующим способом (для Visual Studio 6.0 и lua 5.1, думаю аналогично должно работать и для других студий/версий lua): #include <stdio.h> #include "lua.h"
#pragma comment(lib, "lua51.lib")
int main(int argc, char* argv[]) { char* chunk ="function f(a,b) return a + b end"; lua_State *L; int luaErr;
L = lua_open();
luaL_openlibs(L);
if (luaL_loadstring(L, chunk) || lua_pcall(L,0,0,0)) { printf("error: %s", lua_tostring(L, -1)); lua_close(L); return 1; }
lua_getglobal(L, "f");//функция для вызова lua_pushnumber(L, 3); lua_pushnumber(L, 6);
luaErr=lua_pcall(L,2,1,0);
if(0==luaErr) { int result=2;
//смотрю результат в стеке result=lua_tonumber(L, -1);
printf("%s -> %d\n", chunk, result);
lua_pop(L, 1); } else { char* errortext;
errortext=lua_tostring(L, -1);
printf("%s -> error %s\n", chunk, errortext);
lua_pop(L, 1); //извлечь сообщение об ошибке из стека } lua_close(L);
return 0; } как я понял - ключевым было выполнить само объявление функции (это там, где после luaL_loadstring(L, chunk) вызывается lua_pcall(L,0,0,0))
|
|
« Последнее редактирование: 11-07-2013 08:27 от darkelf »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #21 : 11-07-2013 08:49 » |
|
darkelf, спасибо, вононочо, оказывается. А где вычитал ? Я не видел упоминаний ну и 2 таки параметра, а не 3 (в доках сказано, что первый обязательно будет - имя функции) ну а так - получилось получить результат ---------------- ...по остальным вопросам тоже ещё актуально - поскольку в LUA классов нет, всё же хотелось бы разобраться и с JScript и/или tcl . Юзеры желают писать свои структуры данных в стиле, близком к C/C++
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #22 : 11-07-2013 08:52 » |
|
Алексей++, эксперименты ставил, а потом ещё поискал в интернетах - и нашел вроде рабочий пример: http://cc.byexamples.com/2008/07/15/calling-lua-function-from-c/ и по нём сравнивал - что и где отличается ...по остальным вопросам тоже ещё актуально - поскольку в LUA классов нет, всё же хотелось бы разобраться и с JScript и/или tcl . Юзеры желают писать свои структуры данных в стиле, близком к C/C++
В Lua вместо классов есть таблицы, и поверх них даже как-то делают ООП, но в этой области я не разбирался, и поэтому подсказать не могу, сорри. На вскидку нашлось: http://lua-users.org/wiki/ObjectOrientedProgramming
|
|
« Последнее редактирование: 11-07-2013 08:59 от darkelf »
|
Записан
|
|
|
|
Sla
|
|
« Ответ #23 : 11-07-2013 09:23 » |
|
Sla, смотрю ещё Incr tcl ---------- #include "itcl32\include\itcl.h" #include "itcl32\include\itclDecls.h" #include "itcl32\include\itclInt.h" #include "itcl32\include\itclIntDecls.h" #include "itcl32\include\itk.h" #include "itcl32\include\itkDecls.h" хм, ругается на отсутствие tcl.h , а такого там нет вообще Слава, куда бечь ? гы is an OO system for Tcl.Бечь за тиклем.... http://www.tcl.tk/software/tcltk/
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #24 : 11-07-2013 09:25 » |
|
darkelf, про таблицы я понял, ассоциировать можно всё и вся, но тут вопрос в другом - сделать возможность описания юзерских структур в "привычном виде" , на их языке это означает - "в стиле C или похоже"
|
|
|
Записан
|
|
|
|
Sla
|
|
« Ответ #25 : 11-07-2013 09:28 » |
|
сделать возможность описания юзерских структур в "привычном виде" Именно это.... тупо описываешь или переменные, или просто в строке, типа самопальный конфиг, потом отдаешь интерпретатору, а он сам разберется
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #26 : 11-07-2013 09:31 » |
|
Sla, оно мне предлагает инсталлер качать , а в виде lib / dll / h нету ? тупо описываешь или переменные, или просто в строке, типа самопальный конфиг, потом отдаешь интерпретатору, а он сам разберется это же городить надо . Ну посмотрим
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #27 : 11-07-2013 09:40 » |
|
darkelf, про таблицы я понял, ассоциировать можно всё и вся, но тут вопрос в другом - сделать возможность описания юзерских структур в "привычном виде" , на их языке это означает - "в стиле C или похоже" Если рассматривать применение таблиц в виде именно структур, то они получаются вполне похожие, особенно если сравнивать с C99: a = { field1 = 5, field2 = 10}
print(a.field1, a.field2) -- 5 10 в C99: #include <stdio.h> struct A { int field1; int field2; };
struct A a = { .field1 = 5, .field2 = 10 };
int main(int argc, char* argv[]) { printf("%d %d\n", a.field1, a.field2); return 0; }
|
|
« Последнее редактирование: 11-07-2013 09:47 от darkelf »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #28 : 11-07-2013 09:45 » |
|
darkelf, ну, я тоже уже понял. Только из-за отсутствия типов у народа крышу снесёт, наверное )
|
|
|
Записан
|
|
|
|
Sla
|
|
« Ответ #29 : 11-07-2013 09:47 » |
|
Sla, оно мне предлагает инсталлер качать , а в виде lib / dll / h нету ?
Проинсталь, чего боишься?
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #30 : 11-07-2013 09:49 » |
|
Алексей++, типы тоже есть, но вроде и в js тоже с типами плохо, точнее полностью аналогично - базовые типы есть числа, строки и булевские.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #31 : 11-07-2013 09:50 » |
|
Sla, ок
|
|
|
Записан
|
|
|
|
Sla
|
|
« Ответ #32 : 11-07-2013 10:02 » |
|
на в тикле тоже нет явных типов
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #33 : 11-07-2013 10:34 » |
|
darkelf, даже можно наборы функций добавлять ) chunk="function f1(a,b) return a+b end"; luaL_loadbuffer(L, &chunk[0], chunk.size(), 0); lua_pcall(L,0,0,0);
chunk="function f2(a,b) return a+b+10 end"; luaL_loadbuffer(L, &chunk[0], chunk.size(), 0); lua_pcall(L,0,0,0); и работает
|
|
|
Записан
|
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #34 : 11-07-2013 11:33 » |
|
darkelf, даже можно наборы функций добавлять ) chunk="function f1(a,b) return a+b end"; luaL_loadbuffer(L, &chunk[0], chunk.size(), 0); lua_pcall(L,0,0,0);
chunk="function f2(a,b) return a+b+10 end"; luaL_loadbuffer(L, &chunk[0], chunk.size(), 0); lua_pcall(L,0,0,0); и работает можно и зараз множество функций: chunk="function f1(a,b) return a+b end ; function f2(a,b) return a+b+10 end"; luaL_loadbuffer(L, &chunk[0], chunk.size(), 0); lua_pcall(L,0,0,0);
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #35 : 11-07-2013 14:38 » |
|
ООП можно соорудить на чём угодно. В JavaScript и Lua оно одинаковое - безклассовое на замыканиях и ассоциативных массивах.
Насчёт типизированности не понял. Зачем в интерпретируемом языке типизация? Она имеет смыл лишь при компиляции - когда весь текст заранее проверяешь на косяки. Алексей++, ты хочешь иметь раздельные стадии компиляции и исполнения?
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #36 : 17-07-2013 09:48 » |
|
darkelf, ага, уже понял ) Можно вообще любой синтаксически верный кусок текста добавить
Dimka, пока что потребовалось в таком виде: загружаю в "машину" все функции, по мере необходимости вызываю нужную, передаю ей числовые параметры, получаю ответ, делаю действие. Уже увидел, что, в принципе, можно все параметры сделать текстовыми.
Когда компилируется - думаю, лучше это пусть делается после определения нужных функций (и этим, видимо, как раз и занимается вызов lua_pcall(L,0,0,0) после загрузки ещё одного куска кода )
замыкания - ага, уже почитал, интересная штука. Но пока ещё в голове нет стройности в том, как организовать класс в привычном виде - с методами . Ещё просто не дошёл до этого места, там разберусь )
А в остальном пока всё устраивает в LUA
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #37 : 17-07-2013 19:52 » |
|
Но пока ещё в голове нет стройности в том, как организовать класс в привычном виде - с методами . Элементарно. Метод - это функция, в контексте которой содержатся переменные объекта (видны ей). В данном случае это переменные внутри замыкания и/или значения (которые не ключи) ассоциативного массива. Функция - это тоже объект, назначенный переменной. Т.е. функцию можно добавить в объект как и любое другое значение - и будут тебе методы
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #38 : 19-07-2013 06:37 » |
|
Dimka, правильно ли я понимаю ? Попытался описать фабрику класса A (судя по выводу в консоль, это работает) -- фабрика экземпляров класса A function create_class_A() local this={} --таблица будет содержать переменные и методы экземпляра this.var=0 -- объявил и инит. переменную var this.get_var= -- метод, возвращающий var function() return this.var end return this end
function test()
local a1=create_class_A() local a2=create_class_A()
a1.var=1 a2.var=2 print(a1:get_var()) print(a2:get_var()) end > test() 1 2 >
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #39 : 19-07-2013 08:42 » |
|
Алексей++, с уточнением, что внутри объекта есть разница между замыканием и ассоциативным массивом как точкой доступа. -- конструктор объекта function createC()
-- локальные переменные функции createC сохранятся внутри замыкания и не будут видны снаружи -- так делаются private члены -- чтобы их отличать от public, локальных переменных и аргументов методов, будем им ставить префикс "_"
-- private поля и сразу их инициализация как в конструкторе, код инициализации может быть произвольной сложности local _x = 1
-- protected static поля - общие для всех объектов _Const = 3
-- private методы function _printState() print(_x) end
-- ассоциативный массив для создаваемого объекта, являющийся точкой доступа к объекту -- содержимое ассоциативного массива хранит public члены объекта local self = {}
-- public поля и сразу их инциализация, например, для объявления доступных снаружи констант, которые будем писать с большой буквы self.Const = _Const
-- public методы function self.set(x) -- можем работать с private членами, поскольку функция находится в общем замыкании с переменными _x = x _printState() end
function self.get() return _x end
-- конструктор обязательно возвращает ассоциативный массив с открытыми членами объекта return self
end
-- использование o = createC() -- теперь в переменной o находится ассоциативный массив с открытыми членами объекта, -- со всеми функциями внутри этого массива связано замыкание конструктора, в котором хранятся закрытые члены объекта o.set(o.Const) print(o.get()) 3 3
Таким образом, функция createC здесь не вполне фабрика. Она не ограничивается только созданием ассоциативного массива со связанными между собой элементами, она ещё генерирует собственное замыкание с закрытыми внутри него private переменными и вспомогательными функциями и увязывает всю эту конструкцию в единый объект. Стоит заметить, что конструктор может порождать целую серию ассоциативных массивов, являющихся разными интерфейсами одного и того же объекта. Например function createProcessor
local readerInterface = {} function readerInterface.read() print("read") end
local writerInterface = {} function writerInterface.write() print("write") end
return readerInterface, writerInterface
end
reader, writer = createProcessor() reader.read() writer.write() read write
Наследование с полиморфизмом поведения реализуется элементарно. Достаточно получить ассоциативный массив предка и дополнить/переписать его под потомка. При этом private-члены будут свои для каждого конструктора. С одним ассоциативным массивом связывается несколько замыканий: по одному замыканию от каждого конструктора с local-переменными (private) и общее замыкание для всех конструкторов и всех объектов с не local переменными (static protected). function createParent local _x = 1 _y = 3 local self = {} function self.test() print("test") end function self.foo() print("parent") print(_x) print(_y) end return self end
function createChild local _x = 2 local self = createParent() function self.foo() print("child") print(_x) print(_y) end return self end
p = createParent() p.test() p.foo() c = createChild() c.test() -- унаследовано от parent c.foo() -- переопределено, но переменная _y видна из parent и является общей для всех объектов test parent 1 3 test child 2 3
В общем, вот и весь краткий курс безклассового ООП.
|
|
« Последнее редактирование: 19-07-2013 09:12 от Dimka »
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #40 : 19-07-2013 09:03 » |
|
по первому блоку кода: я всё так и понял, вроде бы. Только в моём случае все переменные размещались в таблице this, которая будет жить в объекте благодаря замыканию и которая есть эквивалент _x, по сути. С той лишь разницей, что я вернул ссылку на эту приватную таблицу, тем самым разрешив доступ ко всем полям извне. Тут вроде всё понятно
С наследованием тоже понятно, спасибо. По сути, всё то, что в C++ скрывается синтаксисом, тут как на ладони расписывается ))
Добавлено через 22 минуты и 24 секунды: а как организовать аналог сишной локальной static переменной в функции ? Глобальная таблица ?
|
|
« Последнее редактирование: 19-07-2013 09:25 от Алексей1153 »
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #41 : 19-07-2013 11:02 » |
|
Алексей++, нет, в C++ нету замыканий функций. Наоборот, из объектов можно делать аналог функций с замыканиями - функторы: объекты с оператором (). В Lua всё с точностью наоборот: из функций с замыканиями делаются объекты. Аналога static переменных внутри функций нет. Но через замыкание можно - см. выше переменные внутри конструктора без local. Т.е. в чистом виде это будет просто замыкание без ассоциативных массивов. f = (function() staticVar = 0 return function() staticVar = staticVar + 1 print(staticVar) end end)()
f() f() 1 2
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #42 : 19-07-2013 11:14 » |
|
Нет, выше я всюду неправ насчёт не local переменных и функция - это просто глобальные переменные и функции, видимые отовсюду. Они не закрыты. Т.е. за пределами объектов такие переменные могут изменить значение, а функции конфликтовать за счёт совпадения имён. Значит нет static protected, бывают только private - это local переменные и функции внутри функций.
|
|
« Последнее редактирование: 19-07-2013 21:32 от Dimka »
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
|