feat: support keyword application#85
feat: support keyword application#85phrohdoh wants to merge 1 commit intoclojure-rs:masterfrom phrohdoh:keyword-in-fn-position
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-foundInstead of the above-documented, as-of- (:k {} b) ;; => nil (should be b, see todo)(:k {} :not-found) ;; => nil
(:k {:k :v} :not-found) ;; => nilIf #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.