0

I have a collection of 'data endpoints'. Each endpoint has a name and can be available or unavailable. In Ruby I want to present the available endpoints as a Hash to make it easy to work with them. The difficulty is that getting information about the endpoints is costly and should be done lazily.

Some examples of how I want my object to behave:

endpoints = get_endpoints.call        # No endpoint information is accessed yet
result = endpoints['name1']           # This should only query endpoint "name1"
is_available = endpoints.key? 'name2' # This should only query endpoint "name2"
all_available = endpoints.keys        # This has to query all endpoints

The comments describe how the object internally makes requests to the 'data endpoints'.

It is straightforward to make a Hash that can do the first 2 lines. However I don't know how to support the last 2 lines. To do this I need a way to make the keys lazy, not just the values.

Thank you for taking a look!

user183966
  • 131
  • 3
  • Not sure what aspect of Hash you would like to be lazy-implemented ? Keys evaluation ? How would it be addressed in memory ? – MrAleister Nov 21 '18 at 14:18
  • Hi @MrAleister Yes, keys evaluation (or rather, all aspects of the map). I have no idea how it would be addressed in memory. I thought that didn't really matter since it's object oriented, the same way I can just provide a lazy evaluation block for the values I would hope to provide a lazy evaluation block for the keys. – user183966 Nov 21 '18 at 14:22
  • What do you mean by *"I have made the value lookup lazy in the straightforward way"*? Why is that *"no advantage in [your] scenario if [you] have to look up the keys eagerly"*? – Tom Lord Nov 21 '18 at 14:42
  • 1
    I don't understand what you're trying to achieve. (Why do you want to do this?) Can you show what code you've written so far? You could just use `my_hash.keys.lazy`, but... *why*? What would be the purpose? – Tom Lord Nov 21 '18 at 14:45
  • Hi @TomLord . It is not laziness on the output side of the hash that I want, but laziness on the input side of the hash. I hope that makes sense. – user183966 Nov 21 '18 at 15:02
  • @user183966 No, that doesn't really make sense to me. Can you please provide a [mcve] of the problem? At a guess, perhaps what you'd like to do is define each hash **value** as a **lambda** - and only evaluate this at the point of accessing? Or perhaps you're looking at this the wrong way, and what's really needed is some optimisation of how/when the "eager loading" is performed. – Tom Lord Nov 21 '18 at 17:45
  • @user183966 not really, could you please present some example of such lazy-input ? – MrAleister Nov 21 '18 at 17:45
  • `by passing a block to the Hash, and an exception is thrown if that key is not associated with an available data source` so Hash with a query interface where query itself is in a form of code block ? – MrAleister Nov 21 '18 at 17:50
  • I have rewritten the question using code examples to hopefully make it clearer. – user183966 Nov 21 '18 at 22:28
  • You say, "..I want to present the available endpoints as a Hash..." What are the hash's keys ("endpoints"?) and values ("available")? What is the "expensive" operation? (Determining if an endpoint is "availIable"?) Do you simply want to avoid determining if an endpoint is available if you've previously made that determination (i.e., assuming it will remain in its earlier state). Meaningless jargon ("lazy keys") is not helpful. – Cary Swoveland Nov 22 '18 at 02:10

1 Answers1

0

You'd have to override the key? method, and do your own checking in there.

class LazyHash < Hash
  def key?(key)
    # Do your checking here. However that looks for your application
  end
end

In my opinion, you're asking for trouble though. One of the most powerful virtues in computer science is expectability. If you're changing the behavior of something, modifying it far beyond it's intent, it doesn't serve you to continue calling it by the original name. You don't need to shoe-horn your solution into existing classes/interfaces.

Programming offers you plenty of flexibility, so you can do stuff like this (dependent on the language of course), but in that same argument, you have no reason not to simply build a new object/service with it's own API.

I recommend starting fresh with a new class and building out your desired interface and functionality.

class LazyEndpoints
  def on?(name)

  end

  def set(name, value)

  end
end

(Or something like that, the world is yours for the taking!)

Volte
  • 1,905
  • 18
  • 25