Поскольку вы спросите как это обычно делается.
Вы создаете таблицу поиска от операций до их реализации. И затем используйте первый элемент для поиска реализации и передайте оставшиеся элементы этой функции.
По сути все, что вам нужно реализовать Лисп
evaluate
apply
- табличного
Это ядро может даже поместиться в 30-50 строк. Я не думаю, что вы хотите, чтобы мы дали вам полную реализацию. Это займет все самое интересное от написания вашего собственного письма.
я, таким образом, просто обрисовать основную структуру ...
$table = {
'+' => lambda { |a, b| a + b },
'-' => lambda { |a, b| a - b },
'*' => lambda { |a, b| a * b },
'/' => lambda { |a, b| a.fdiv(b) },
}
def evaluate(args, context = $table)
# A complete implementation of evaluate would make use of apply ...
head, *tail = args
context[head][*tail]
end
def apply
# ...
end
puts evaluate(['/', 4, 3])
# => 1.3333333333333333
Просто так получилось, что ваши Лиспе имена функций и соответствующие имена функций Рубин одинаковы. Но это не всегда будет дано, поэтому использование справочной таблицы является более типичным решением. Я отобразил lisp /
на Ruby's fdiv
, чтобы продемонстрировать это.
Удовлетворительный факт, эти первые элементы называются символами, и на самом деле Ruby также использует очень похожий механизм и, следовательно, также имеет символы. Внутренне Ruby также использует вложенные таблицы поиска для организации классов и констант и методов, а также локальных переменных и т. Д.
Вам не нужно отделять первый аргумент и все остальное. Вы можете просто сделать «[2, 3, 4, 5, 6] .inject (: +) # => 20'. – sawa
@sawa Да, я добавил немного с 'reduce', который функционально то же самое. – tadman
Вообще говоря, 'сокращение 'здесь размывает идею быть LISP-подобным. АСТ добавления трех элементов не будет '{: +, 1, 2, 3}', это '{: +, 1, {: +, 2, 3}}'. Во всяком случае. – mudasobwa