public function offsetGet($name)
    {
        if (!$this->offsetExists($name)) {
            throw new \InvalidArgumentException(sprintf('Fact "%s" is not defined.', $name));
        }

        $value = $this->values[$name];

        // If the value is already frozen, or if it's not callable, or if it's protected, return the raw value
        if (isset($this->frozen[$name]) || !is_object($value) || $this->protected->contains($value) || !$this->isCallable($value)) {
            return $value;
        }

        // If this is a shared value, resolve, freeze, and return the result
        if ($this->shared->contains($value)) {
            $this->frozen[$name] = true;
            $this->raw[$name]    = $value;

            return $this->values[$name] = $value($this);
        }

        // Otherwise, resolve and return the result
        return $value($this);
    }