0

Here's a short example of my problem.

prefix = "!"
commands = ["right"]
response = nil

message = "Some text !right here"

for i in 0..commands.length
    if message.include?(prefix + commands[i]) # If message contains "!right"
        response = commands[i](parameter) # Load matching function
    end
end

if response
    puts(response)
end

def right(parameter)
    "This is an example response"
end

Why can't I load the function right by doing it like this?

1
  • I guess it's mainly because Ruby is not JavaScript. There are tools to dynamically call methods in Ruby though, like public_send. Commented Apr 19, 2018 at 6:54

1 Answer 1

1

First of all, numeric for loops are usually not used in ruby. You can just write

commands.each do |command|
    ...
end

As for calling "functions", you need to know that functions as such don't exist in ruby, only methods (which are, in theory, just a special case of function).

To call a method on an object, you use the send method, which "sends" (read: calls) a "message" (read: the method name) to the object.

The send method takes a symbol as its argument, which is in practice just an interned string, but you're supposed to use them differently from normal strings.

Last but not least, how can you write def outside of any class to define a function, but it's still somehow a method? That's because Ruby pretty much wraps your entire code in an implicit object.


In practice, you'll be better off using a lambda, which is really just an object with a call method that simulates first class functions as you may know them from javascript, lua, etc.

The syntactic sugar for defining one is whatever = lambda { |argument| puts "I'm a lambda" } or whatever = ->(argument){ puts "I'm a lambda too" }.

do |argumetn| ... some lines of code ... end syntax can also be used with both lambda and -> notations.

You can then call the lambda with whatever.call(<argument>)

There's also Procs, which are like lambdas, but with a few differences and I suggest you just google it if you want to know what exactly they are.


Assuming each command is a lambda (or a proc), to assign each one to a string, I recommend just using a hash (read: map or dict).

They are defined like this:

my_map_variable = {
    20 => "I'm an integer",
    "string" => "I'm a string",
    :symbol => "I'm a symbol, an interned string",
    symbol2: "I'm the same as above, but with fancy notation",
    right: -> (parameter) { puts "This is an example response" }
}

You can then access the values like this

puts my_map_variable[20] # prints: I'm an integer
puts my_map_variable[:symbol2]
puts my_map_variable[:right].call(nil) # prints: "This is an example response"

Lastly, if you have a string "right", but your hash uses symbol indices, you can just call "right".to_sym to turn the string into a symbol. Or you can just use strings in the first place.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.