Skip to content
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

rename defclass to class #899

Closed
gilch opened this issue Aug 16, 2015 · 7 comments
Closed

rename defclass to class #899

gilch opened this issue Aug 16, 2015 · 7 comments

Comments

@gilch
Copy link
Member

gilch commented Aug 16, 2015

class is a reserved word in Python, and so is already reserved in Hy,

=> (def class "Hy")
  File "<input>", line 1, column 6

  (def class "Hy")
       ^----^
HyTypeError: Can't assign to a builtin: `class'

but doesn't do anything useful.

=> (class)
class()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'class' is not defined
=> class
class
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'class' is not defined

And class is shorter to type.

@algernon algernon added this to the Grand Language Cleanup milestone Aug 17, 2015
@algernon
Copy link
Member

On the other hand, we have (defn), (def), (defmacro), etc. (defclass) just follows the convention.

@zackmdavis
Copy link
Contributor

I think maintaining the analogy to def, defn, and defmacro that Algernon mentions is more important than saving three characters or minimizing the number of keywords, even unfortunate keywords that don't do anything. (Hey, JavaScript gets by with a few of those, right?—although maybe that's not the best role model.) But speaking of which—

class is a reserved word in Python, and so is already reserved in Hy,

We do that, but you know, I don't think we need to do that. By bypassing Python's parser and constructing ast nodes directly, Hy has been known to create Python ASTs that aren't legal Python in the respect of using illegal names; that's why, for example, you could name a function set! even before the bang-mangling patch landed.

zmd@ExpectedReturn:~$ hy --spy  # last released version, no '!' mangling
hy 0.11.0 using CPython(default) 3.4.0 on Linux
=> (defn set! [])
def set!(): # bad Python (even though `--spy` didn't notice)
    pass

A simple experiment suggests we'd likely be able to do the same for class and other Python keywords that we don't need as Hy keywords—

in [1]: import ast; from ast import *
in [2]: ast.dump(ast.parse("foo = 1"))
Out[2]: "Module(body=[Assign(targets=[Name(id='foo', ctx=Store())], value=Num(n=1))])"

# We can't parse the use of `class` as a variable name ...
in [3]: ast.dump(ast.parse("class = 1"))  File "<unknown>", line 1
    class = 1
          ^
SyntaxError: invalid syntax

# But no one objects if we construct the corresponding AST ourselves.
in [4]: ast.dump(Module(body=[Assign(targets=[Name(id='class', ctx=Store())], value=Num(n=1))]))
Out[4]: "Module(body=[Assign(targets=[Name(id='class', ctx=Store())], value=Num(n=1))])"

@algernon
Copy link
Member

FWIW, I removed the python builtin check, and the following worked just fine:

(def class 1)
(defclass Foo [] (defn zing [self] (print "zing!")))
(def f (Foo))
(.zing f)
(print class)

Perhaps we should allow Python keywords to be used in Hy? Or at least, some of them.

@gilch
Copy link
Member Author

gilch commented Aug 17, 2015

I think maintaining the analogy to def, defn, and defmacro that Algernon mentions is more important

By that logic we should have class as an anonymous class by analogy to fn.

We do that, but you know, I don't think we need to do that.

...

Perhaps we should allow Python keywords to be used in Hy? Or at least, some of them.

You know, maybe we should. This would let us get rid of True/False in favor of the preferred true/false. And also get rid of None in favor of nil should #896 be rejected.

I was under the impression that this would break Hy<->Python interop, but maybe it doesn't have to if we provide workarounds? For example, we allow Unicode symbols because Hy treats the equivalent Punycode as the same symbol, and this alias also works in Python.

Python actually does allow reserved words as attributes, so that's not a problem either.

>>> class namespace:
    pass

>>> namespace.foo = 2
>>> namespace.foo
2
>>> namespace.class = 42
SyntaxError: invalid syntax
>>> setattr(namespace,'class',42)
>>> namespace.class
SyntaxError: invalid syntax
>>> getattr(namespace,'class')
42

You don't get the sugar, but it does work.

I think imports might even work.

# from class import class as Class
from importlib import import_module
Class = getattr(import_module('class'), 'class')

I would want this tested though.

The reverse is also a concern, e.g. can Hy import a Python module named defclass? I think the same workarounds work.

Are there other cases interop would break that I'm not thinking of? Are there workarounds?

@algernon
Copy link
Member

Well, I think if one uses reserved python keywords in Hy code, that's not something we should care about. If one intentionally makes it hard to interoperate with their code from Python (or Hy), that's not something we should be responsible for. One can already make interop a pain, this wouldn't be any different.

In short, I'd 👍 a PR that removes the python keyword checking lines, and as such 👎 on defclass => class.

@farhaven
Copy link
Contributor

Same here, 👍 for removing the keyword checking, 👎 for renaming defclass to class.

@algernon
Copy link
Member

Looks like this is staying as defclass. The option for removing the python keyword check lines remains open, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants