It's interesting but I think it's a bit of a cop out and introduce more inconsistencies and weirdness.  I think it a common reaction to this kind of thing will be 'why is that not a hash?'  It seems like the most surprising thing to do.

This effectively introduce a 3rd and 4th hash pattern to the language:

    $some_hash["x"]["y"]
    $settings::x
    fact(x) # which may or may not return a hash or array or....
    facts()

Except the function method will result in more typing, imagine nested data:

    {"os" => {"release" => 6, "family" => "RedHat"}}

Getting to this data with the function means:

    $temp = fact("os")

    notify{$temp["release": }
    
or in a template:

    <%= fact("os")["release"] %> or maybe <%= @temp["release"] %> or <%= scope.facts["os"]["release"] %>

because we can't do:

    fact("os")["release"]
    facts()["os"]["release"]
    facts["os"]["release"]

But there are all things people will instinctively think they could do - the affordances and what we're actually able to do is off.  It's not reducing complexity it's adding multiple ways to get to the same data and forces the user to make more decisions and be more disciplined about writing good code something that we know they aren't which is why we tell them to trust our DSL.

It would be kind of ok if we could do this but to me it seems that it will yield worse code patterns.  We also cant call functions without arguments so `facts["x"]` it has to be `facts()["x"]` which also won't work unless we fix that too and so it will promote more throw away yet uniquely named variables much like the problem we have today that led to the proliferation of the `$real_xxx` variable pattern.

This is problematic in string interpolation:

    "this is a string ${facts[os][release]}" 

works, but how to do that with a function without first creating temp variables? Do we add yet another function to do sprintf?

Ultimately I think this will decrease readability over the true hash proposal