Какие языки программирования позволят мне управлять последовательностью инструкций в методе?

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

Ключевые свойства, которые мне нужны:

  • Я должен иметь возможность модифицировать метод таким образом, чтобы я мог добавлять новые выражения, удалять существующие выражения или изменять любые выражения, которые в нем присутствуют.

  • После изменения метода последующие вызовы этого метода вызовут новую последовательность операций. (Или, если язык связывает методы, а не оценивает каждый раз, предоставьте мне способ отменить/повторно связать новый метод.)

  • В идеале я хотел бы манипулировать атомарными единицами языка (например, "вызвать метод foo для объекта bar"), а не непосредственно сборкой (например, "поместить эти три параметра в стек"). Другими словами, я хотел бы иметь высокую степень уверенности в том, что операции, которые я создаю, семантически значимы в языке. Но я возьму то, что смогу.

Если вы не уверены, соответствует ли язык-кандидат этим критериям, вот простая лакмусовая бумажка:

Можете ли вы написать другой метод с именем clean, который:

  • принимает метод m в качестве входных данных

  • возвращает другой метод m2, который выполняет те же операции, что и m

  • так что m2 идентичен m, но не содержит никаких вызовов метода печати в стандартный вывод на вашем языке (puts, System.Console.WriteLn, println и т. д.)?

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

Какие варианты доступны для меня? Если возможно, можете ли вы предоставить пример игрушки на одном или нескольких рекомендуемых вами языках или указать мне на недавний пример?


Обновление: Причина, по которой я хочу этого, заключается в том, что я хотел бы написать программу, способную изменять себя во время выполнения в ответ на новую информацию. Эта модификация выходит за рамки простых параметров или настраиваемых данных, но представляет собой полноценные эволюционные изменения в поведении. (Нет, я не пишу вирус. ;))


person John Feminella    schedule 10.02.2011    source источник
comment
Чтобы было ясно, вы хотите динамически изменять инструкции существующего метода? (т.е. не собирать реализацию нового метода на лету?)   -  person Kirk Woll    schedule 10.02.2011
comment
@Kirk Woll: Вы правильно заметили, что меня не особенно волнуют детали реализации того, как язык может удовлетворить мои цели. Я немного уточнил свой вопрос, чтобы выделить ключевые свойства, которые мне нужны.   -  person John Feminella    schedule 10.02.2011


Ответы (5)


Ну, вы всегда можете использовать .NET и библиотеки Expression для создания выражений. Я думаю, что это действительно ваш лучший выбор, поскольку вы можете создавать представления команд в памяти, и есть хорошая библиотечная поддержка для манипулирования, обхода и т. д.

person tster    schedule 10.02.2011
comment
Это позволит мне строить выражения, да. Но могу ли я отменить привязку существующего метода во время выполнения, а затем повторно связать его с новым методом, имеющим только что построенное выражение? - person John Feminella; 10.02.2011
comment
@john-feminella: Откажитесь от идеи метода и вместо этого используйте делегатов. Это позволит изменить метод (делегата) во время выполнения, чтобы вызовы метода использовали новую/обновленную реализацию вместо существующей реализации. В сочетании с .NET 4.0 System.Dynamic.DynamicObject вы можете получить нечто, выглядящее как методы, но обновляемое по запросу. - person jonp; 10.02.2011
comment
@jonp: Звучит как очень привлекательный подход. Я добавлю это в свой список целей исследования. - person John Feminella; 10.02.2011
comment
Извините, не DynamicObject, а System.Dynamic.ExpandoObject. - person jonp; 10.02.2011

Что ж, те языки с действительно мощной поддержкой макросов (в частности, Lisps) могут подойти.

Но вы уверены, что вам действительно нужно идти так глубоко? Я не знаю, что вы пытаетесь сделать, но я полагаю, вы могли бы подражать этому, не слишком углубляясь в метапрограммирование. Скажем, вместо того, чтобы использовать метод и манипулировать им, используйте набор функций (с каким-либо способом совместного использования состояния, например, состояние хранения объекта, передаваемое каждой).

person Community    schedule 10.02.2011
comment
Я согласен, что Lisp — хороший выбор; это определенно в моем списке для исследования. Не уверен, что вашего предложения по ограниченному метапрограммированию будет достаточно, потому что метод, которым нужно манипулировать, будет иметь произвольное содержание, и им нужно будет манипулировать произвольными (но семантически допустимыми) способами. - person John Feminella; 10.02.2011

Я бы сказал, что Groovy может это сделать.

Например

class Foo {
   void bar() {
      println "foobar"
   }
}

Foo.metaClass.bar = {->
    prinltn "barfoo"
}

Или конкретный экземпляр foo без воздействия на другие экземпляры

fooInstance.metaClass.bar = {->
    println "instance barfoo"
}

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

person Ben Doerr    schedule 10.02.2011
comment
Это не совсем то, что я хочу. Это демонстрирует, что один метод можно заменить другим с таким же именем. Но мне нужна возможность манипулировать bar. В качестве простой лакмусовой бумажки можно написать еще один метод capture_printlns, который принимает существующий метод и создает новый метод, содержащий только println операторов исходного метода. - person John Feminella; 10.02.2011

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

Несколько лет назад также широко использовался BCEL.

person Alain Pannetier    schedule 10.02.2011

Существуют языки/окружения, которые позволяют модифицировать реальную среду исполнения, например, Common Lisp, Smalltalk, Forth. Используйте один из них, если вы действительно знаете, что делаете. В противном случае вы можете просто использовать шаблон интерпретатора для развивающейся части вашего кода, это возможно (и тривиально) с любым объектно-ориентированным или функциональным языком.

person SK-logic    schedule 10.02.2011
comment
Я знаю шаблон интерпретатора. Тем не менее, не было бы излишним использовать это здесь? Я не хочу снова и снова реализовывать большую часть внутренностей языка в миниатюрной форме, просто чтобы манипулировать последовательностью операций. - person John Feminella; 10.02.2011
comment
Если вас интересует только последовательность, то вы можете реализовать язык с доступным только примитивом последовательности. Мини-интерпретатор такого типа может быть реализован в 10 строках C# или Java. Это намного проще, чем кормить компилятор кодом во время выполнения. - person SK-logic; 10.02.2011
comment
Нет, мне понадобится весь спектр возможностей языка. Вот почему мне нужен язык, который раскрывает это, чтобы мне не приходилось реализовывать самомодифицирующийся компилятор внутри самого языка. (В некоторых языках это может быть даже невозможно.) - person John Feminella; 10.02.2011
comment
Что такое полный диапазон? Встроенный интерпретатор с последовательностями, привязками, ветвлением, try/catch и циклами по-прежнему очень тривиален. Если ваш код развивается быстро, это может быть даже наиболее эффективной реализацией, так как в противном случае вы можете потратить больше времени на компиляцию и JIT-компиляцию своего изменчивого кода, чем на его фактическое выполнение. Еще одна важная вещь заключается в том, что нединамические методы не являются сборщиком мусора в .NET. - person SK-logic; 10.02.2011