Search code examples
crystal-lang

Calling methods dynamically (Crystal-lang)


I understand that this may be a duplicate of Any equivalent of Ruby's public_send method?. I'd like to explain what I am doing, and perhaps someone could advice.

I've been porting a ruby app over the last few days to learn Crystal. I've had to cut out a lot of functionality due to lack of send but today I've hit a main artery in my program.

I have a Hash which contains keystroke as key, and method as value. Based on what key is struck, the appropriate method is called. This obviously uses the send to implement the same.

From the linked question, I understand that Crystal is compiled so dynamic method calls are not permitted. However, if you look at the Vim editor, a user can map keys to methods, too. And vi(m) is written in C.

I am wondering if I missed something.

I know I could probably hardcode a switch statement with each key and call the appropriate method, but that still does not allow the user to assign a key to a method. Is there any alternative to this very large switch-case method ?

(I am guessing that rather than check the key in the when part, I would check the binding and call the method.

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

Any better solution ?


Solution

  • I'm not sure that this way most simple and convenient (perhaps more experienced developers will correct me below) but i would use the 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
    

    See working example