Самомодифицирующийся код в Ruby

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

То, что я мог бы сделать, например, иметь следующий блок,

_x_ = lambda { |a, b, c, d| b + c }

можно заметить, что аргументы a а также d не используются в организме вообще, поэтому я хотел бы функцию, например. #strip удалить их,

x = _x_.strip

который должен дать тот же результат, что и запись:

x = lambda { |b, c| b + c }

Теперь в Лиспе это будет легко, поскольку в Лисп-коде легко манипулировать данными. Но я не знаю, как манипулировать кодом Ruby. Я могу разобрать это например. от

RubyVM::InstructionSequence.disassemble( x )

Но как, исходя из этого, написать модифицированный блок? Другими примерами того, что я хотел бы сделать, являются, например.

y = lambda { A + B }
y.deconstantize
# should give block same as saying
lambda { |_A, _B| _A + _B }

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

2 ответа

Решение

Борис, вам обязательно нужно положиться на Ruby, чтобы начать здесь?

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

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

ChemicalReaction.new(..., "[ATP] * [GDP] * NDPK_constant")

Вуаля: максимальная гибкость.

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

Определение того, используется переменная блока или нет, является сложной задачей, и вы, кажется, говорите, что вы можете сделать это, используя RubyVM, Таким образом, возникает вопрос, как изменить арность кода.

Если у вас есть:

_x_ = ->a, b, c, d{b + c}

и предположим, что вы смогли использовать RubyVM и узнать, что a а также d не используются, поэтому вы хотите создать

x = ->b, c{b + c}

снаружи _x_, Тогда это просто:

x = ->b, c{_x_.call(nil, b, c, nil)}
Другие вопросы по тегам