-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: support keyword application #85
base: master
Are you sure you want to change the base?
Conversation
|
The culprit here seems to be our current implementation of impl IFn for NsMacro {
fn invoke(&self, args: Vec<Rc<Value>>) -> Value {
if args.len() != 1 {
return error_message::wrong_arg_count(1, args.len());
}
let namespace = args.get(0).unwrap();
match &**namespace {
Value::Symbol(sym) => {
self.enclosing_environment.change_or_create_namespace(sym);
Value::Nil
}
_ => error_message::type_mismatch(TypeTag::Symbol, &**namespace),
}
}
} Specifically, the See https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/ns, reproduced below, for valid
|
Per https://clojure.org/reference/data_structures#Keywords
so
fn get(&self, key: &Rc<Value>) -> Rc<Value>; Which does not allow for a default value. We could hardcode/specialize keyword application to support a default, or wait until |
(:k {:k "v"}) ;; => "v" (:k ((fn [] {:k "v"}))) ;; => "v" (:k) ;; => arity error (:k a b c) ;; => arity error (:k {} b) ;; => nil (should be b, see todo) (:k "does not eval to map") ;; => nil (:x {:k "v"}) ;; => nil
Current HEAD of this PR's branch at time of writing this comment (
So will return let map = evaled_arg_values.get(0).unwrap().as_ref();
// @TODO IPersistentMap::get to support optional default value
let _default = evaled_arg_values.get(1).map(|x| x.as_ref());
Some(match map {
Value::PersistentListMap(map) => map.get(&keyword.to_rc_value()),
_ => Rc::new(Value::Nil),
}) The following (which is the impl IPersistentMap for PersistentListMap {
fn get(&self, key: &Rc<Value>) -> Rc<Value> {
match self {
PersistentListMap::Map(parent, entry) => {
if entry.key == *key {
return Rc::clone(&entry.val);
}
parent.get(key) // @TODO if nil return default
}
PersistentListMap::Empty => Rc::new(Value::Nil),
}
}
} |
#87 proposes an implementation of (:k {} :not-found) ;; => :not-found
(:k {:x :v} :not-found) ;; => :not-found Instead of the above-documented, as-of- (:k {} b) ;; => nil (should be b, see todo) (:k {} :not-found) ;; => nil
(:k {:k :v} :not-found) ;; => nil If #87 is merged (or some other implementation!) prior to this (assuming this is), I will update this PR to incorporate those changes. |
Similar to #84.