Repository: hylang/hy

Issue:
`(name :under_scored)` returns `"under-scored"`... Why?
I have the next code:

```
(setv sample :under_scored)
(name sample)
```

Expected:
```
"under_scored"
```

Actually:
```
"under-scored"
```

At the same time, Clojure's name` returns `"under_scored"`. Please, fix it.


Discussion:
`name` calls `unmangle` internally. `name` itself is of dubious value, though; we should probably just trash it.
Could we just make an exception for keywords since they should probably stay as close to their string representation as possible anyways?
It would be better for the user to use whatever combination of `str`, `mangle`, `unmangle`, and `(. … __name__)` that they want. Again, I don't see what the value of `name` is to begin with.
because as far as i can tell none of those get you the underlying name of the keyword. 
```hy
(str :hello_world) ; =>  :hello_world
(repr :hello_world) ; =>  HyKeyword('hello_world')
(mangle :hello_world) ; =>  hyx_XcolonXhello_world
(unmangle :hello_world) ; =>  :hello-world
(name :hello_world) ; =>  hello-world
```
The closest to what jedi wants is `str` but that doesn't remove the `:` and it's such a common operation that it doesn't seem right to make users do `(.replace (str ':hello_world) ":" "" 1)` every time or make their own function. Clojure doesn't unmangle keywords and we probably shouldn't either
You can use `sym.name` or `(cut sym 1)`.
lol didn't know that `sym.name` existed that changes things. 
@jedi2light you should probably use `(. :hello_!->world name) ; => "hello_!->world"`
instead. since hy doesn't have namespaces like clojure i think i agree with kodi now. There doesn't seem much use for `name` besides providing an alias for `(. key name)` 
There is one use case I'm starting to think of and that's the ability to normalize dict keys to strings easily. 

```hy
(setv x {"a" 1  :b 2})

(dfor [k v] (x.items) [(name k) v]) ; => {"a" 1 "b" 2}
;; you could write that as
(dfor [k v] (x.items) [(if (keyword? k) k.name k) v]) ; => {"a" 1  "b" 2}
```

Don't know how valid of use case this is to keep `name` around, but something to think about

Generally, it's a mistake to use a HyKeyword instead of a string as a dictionary key. It's too easy to confuse yourself, especially when you're looking at forms like `(dict :foo 1)`.
yeah, that's why i don't use them myself, but i'm trying to think of reasons to keep `name` around since hy doesn't have clojure style namespaces which clojure's `name` handles specially. So far i'm not comming up with much :woman_shrugging: 

> it's a mistake to use a HyKeyword instead of a string as a dictionary key

That seems to go against the intention of the `HyKeyword.__call__` implementation, but I agree that keywords-as-keys gets confusing with keywords-as-keyword-arguments. Should we consider removing the `(:foo mapping)` feature? Or instead, we could change it to do a string lookup instead of a HyKeyword lookup (e.g. `(:foo (dict :foo 1))` would produce `1`).
Probably the latter.
> Or instead, we could change it to do a string lookup instead of a HyKeyword lookup (e.g. `(:foo (dict :foo 1))` would produce `1`).

I think that string lookup would be the most convenient. It would actually allow for it to be used with other python objects like pandas dataframes etc. Using keywords outside of function arguments doesn't seem to mix well with the python ecosystem.
I like the string lookup idea. I pretty much never use the `(:akey adict)` type expression because keywords as dict keys is generally a bad idea anyways.

so would `(:hello {:hello 1})` be a `KeyError` then? 
> so would `(:hello {:hello 1})` be a `KeyError` then?

I guess it would just be equal to `(get {:hello 1} (. :hello name))`, which throws a `KeyError`.
Remove `(:some col)`? Ok, will switch to another language then :/
The current proposals would still work though? it would just be a lookup for a string key.
`(:hello {"hello": 1}) ; => 1` So i'm confused?
And in particular, `(:hello (dict :hello 1)) ; => 1` with the new proposal, which seems like a plus.
Awesome, looks like there's enough buy-in so I'll start up a PR for this.

Resolving patch:
diff --git a/hy/models.py b/hy/models.py
--- a/hy/models.py
+++ b/hy/models.py
@@ -181,7 +181,7 @@ def __bool__(self):
 
     def __call__(self, data, default=_sentinel):
         try:
-            return data[self]
+            return data[self.name]
         except KeyError:
             if default is HyKeyword._sentinel:
                 raise


Test patch:
diff --git a/tests/native_tests/core.hy b/tests/native_tests/core.hy
--- a/tests/native_tests/core.hy
+++ b/tests/native_tests/core.hy
@@ -262,8 +262,7 @@ result['y in globals'] = 'y' in globals()")
   (assert-false (symbol? "hello"))
   (assert-false (symbol? [1 2 3]))
   (assert-false (symbol? '[a b c]))
-  (assert-true (symbol? 'im-symbol))
-  (assert-false (symbol? (name 'im-symbol))))
+  (assert-true (symbol? 'im-symbol)))
 
 (defn test-list? []
   "NATIVE: testing the list? function"
diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy
--- a/tests/native_tests/language.hy
+++ b/tests/native_tests/language.hy
@@ -698,16 +698,16 @@
 
 (defn test-as-threading []
   "NATIVE: test as threading macro"
-  (setv data [{:name "hooded cuttlefish"
-               :classification {:subgenus "Acanthosepion"
-                                :species "Sepia prashadi"}
-               :discovered {:year 1936
-                            :name "Ronald Winckworth"}}
-              {:name "slender cuttlefish"
-               :classification {:subgenus "Doratosepion"
-                                :species "Sepia braggi"}
-               :discovered {:year 1907
-                            :name "Sir Joseph Cooke Verco"}}])
+  (setv data [{"name" "hooded cuttlefish"
+               "classification" {"subgenus" "Acanthosepion"
+                                "species" "Sepia prashadi"}
+               "discovered" {"year" 1936
+                            "name" "Ronald Winckworth"}}
+              {"name" "slender cuttlefish"
+               "classification" {"subgenus" "Doratosepion"
+                                "species" "Sepia braggi"}
+               "discovered" {"year" 1907
+                            "name" "Sir Joseph Cooke Verco"}}])
   (assert (= (as-> (first data) x
                    (:name x))
              "hooded cuttlefish"))
@@ -1140,7 +1140,7 @@
   (assert (= : :))
   (assert (keyword? ':))
   (assert (!= : ":"))
-  (assert (= (name ':) "")))
+  (assert (= (. ': name) "")))
 
 (defn test-pickling-keyword []
   ; https://github.com/hylang/hy/issues/1754
@@ -1488,13 +1488,13 @@ cee\"} dee" "ey bee\ncee dee"))
 
 (defn test-keyword-get []
 
-  (assert (= (:foo {:foo "test"}) "test"))
+  (assert (= (:foo (dict :foo "test")) "test"))
   (setv f :foo)
-  (assert (= (f {:foo "test"}) "test"))
+  (assert (= (f (dict :foo "test")) "test"))
 
-  (with [(pytest.raises KeyError)] (:foo {:a 1 :b 2}))
-  (assert (= (:foo {:a 1 :b 2} 3) 3))
-  (assert (= (:foo {:a 1 :b 2 :foo 5} 3) 5))
+  (with [(pytest.raises KeyError)] (:foo (dict :a 1 :b 2)))
+  (assert (= (:foo (dict :a 1 :b 2) 3) 3))
+  (assert (= (:foo (dict :a 1 :b 2 :foo 5) 3) 5))
 
   (with [(pytest.raises TypeError)] (:foo "Hello World"))
   (with [(pytest.raises TypeError)] (:foo (object)))
@@ -1672,20 +1672,6 @@ macros()
   (setv x :foo_bar)
   (assert (= (keyword x) :foo-bar)))
 
-(defn test-name-conversion []
-  "NATIVE: Test name conversion"
-  (assert (= (name "foo") "foo"))
-  (assert (= (name "foo_bar") "foo-bar"))
-  (assert (= (name `foo) "foo"))
-  (assert (= (name `foo_bar) "foo-bar"))
-  (assert (= (name 'foo) "foo"))
-  (assert (= (name 'foo_bar) "foo-bar"))
-  (assert (= (name 1) "1"))
-  (assert (= (name 1.0) "1.0"))
-  (assert (= (name ':foo) "foo"))
-  (assert (= (name ':foo_bar) "foo-bar"))
-  (assert (= (name test-name-conversion) "test-name-conversion")))
-
 (defn test-keywords []
   "Check keyword use in function calls"
   (assert (= (kwtest) {}))