Динамический вызов методов (Crystal-lang) - PullRequest
2 голосов
/ 30 апреля 2019

Я понимаю, что это может быть дубликат Любой эквивалент метода Ruby public_send? . Я хотел бы объяснить, что я делаю, и, возможно, кто-то мог бы посоветовать.

За последние несколько дней я портировал приложение ruby, чтобы изучить Crystal. Мне пришлось отключить много функций из-за отсутствия send, но сегодня я попал в основную артерию в моей программе.

У меня есть Hash, который содержит нажатие клавиши в качестве ключа и метод в качестве значения. В зависимости от того, какой ключ был нажат, вызывается соответствующий метод. Это очевидно использует send для реализации того же самого.

Из связанного вопроса я понимаю, что Crystal компилируется, поэтому динамические вызовы методов недопустимы. Однако, если вы посмотрите на редактор Vim, пользователь также может сопоставить ключи с методами. И vi (m) написано на C.

Мне интересно, что я что-то пропустил.

Я знаю, что, возможно, мог бы жестко закодировать оператор switch с каждым ключом и вызвать соответствующий метод, но это все еще не позволяет пользователю назначать ключ методу. Есть ли альтернатива этому очень большому методу переключения?

(Я предполагаю, что вместо проверки ключа в части when я бы проверил привязку и вызвал метод.

 binding = @bindings[key]
 case binding
 when :up
    up
 when :down
    down
 when .....
 else
 end

Есть ли лучшее решение?

1 Ответ

2 голосов
/ 30 апреля 2019

Я не уверен, что этот способ наиболее простой и удобный (возможно, более опытные разработчики исправят меня ниже), но я бы использовал Proc :

def method1
  puts "i'm  method1"
end

def method2
  puts "i'm method2"
end

def method3
  puts "i'm  method3"
end

hash = { 
  "ctrl":  -> { method1 },
  "shift": -> { method2 },
  "alt":   -> { method3 }
}

binding = ["ctrl", "shift", "alt"].sample
hash[binding].call #=> i'm method2

См. рабочий пример

...