Search code examples
rubylambdaruby-hash

How to get the key name inside the value for printing inside a Ruby hash


I am creating a hash containing lambdas as the value in Ruby. I want to access the key name in the lambda.

The hash is a collection of anonymous functions (lambdas) which take inputs and do a specific task. So, I am making a hash which draws a shape and so the keys in the hash are the shape names like circle, square, and the value for this key is a lambda which takes in inputs and executes some task which results in the shape drawn. So, here I want to print the name of the shape, i.e. the key, in the lambda.

The real example:

MARKER_TYPES = {
        # Default type is circle
        # Stroke width is set to 1
        nil: ->(draw, x, y, fill_color, border_color, size) {
          draw.stroke Rubyplot::Color::COLOR_INDEX[border_color]
          draw.fill Rubyplot::Color::COLOR_INDEX[fill_color]
          draw.circle(x,y, x + size,y)
        },
        circle: ->(draw, x, y, fill_color, border_color, size) {
          draw.stroke Rubyplot::Color::COLOR_INDEX[border_color]
          draw.fill Rubyplot::Color::COLOR_INDEX[fill_color]
          draw.circle(x,y, x + size,y)
        },
        plus: ->(draw, x, y, fill_color, border_color, size) {
          # size is length of one line
          draw.stroke Rubyplot::Color::COLOR_INDEX[fill_color]
          draw.line(x - size/2, y, x + size/2, y)
          draw.line(x, y - size/2, x, y + size/2)
        },
        dot: ->(draw, x, y, fill_color, border_color, size) {
          # Dot is a circle of size 5 pixels
          # size is kept 5 to make it visible, ideally it should be 1
          # which is the smallest displayable size
          draw.fill Rubyplot::Color::COLOR_INDEX[fill_color]
          draw.circle(x,y, x + 5,y)
        },
        asterisk: ->(draw, x, y, fill_color, border_color, size) {
          # Looks like a five sided star
          raise NotImplementedError, "marker #{self} has not yet been implemented"
        }
}

The Hash contains around 40 such key, value pairs.

The desired output of this would be marker star has not yet been implemented

A simple example:

HASH = {
  key1: ->(x) {
   puts('Number of key1 = ' + x.to_s) 
  }
}

Instead of hardcoding key1 I want to get the name of the key in the value which is a lambda as there are a lot of lambdas in the hash.

Replacing key1 with #{self} prints the class and not the name of the key.


Solution

  • I don't think this can be done. A hash is a collection of keys and values. Keys are unique, values are not.You are asking a value (a lambda in this case, but it doesn't matter much) to which key it belongs. I could be one, none or many; there is no way for the value to "know". Ask the hash, not the value.