-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Using std library with private enums #4269
Comments
I searched issues for "enum"s, so didn't found it. So there is also #3878 where issue with |
The problem is that when macros are expanded they might reference to private types. That is, types that are only accesible to the caller. The expansion somehow lives in other context. Like if it would be an external reference to a private type, hence, it is not visible. Basically any The following code also fails to compile on private enum private enum Foo
Bar,
Baz,
Qux
end
Foo.each do |e|
pp e
end |
One solution is to remove private types from the language. It was probably a bad idea in the first place. |
@asterite is because is a hard problem to solve or because is conceptually flawed? I find useful been able to decide the surface size that my libraries expose, avoiding me to deal with future breakage and possible deprecation warnings. Perhaps a more controlled scenario will be able to use Thank you. |
Personally, I always liked the way Python does private stuff: shove an underscore in front. If someone uses it anyway, then they know that it'll probably end up breaking at some point and it's not your fault. However, then you don't really need runtime support behind it. |
@luislavena It's because it breaks with methods like Enum.values and such. I think it's better to have that working and simply mark private types with |
Private came handy to manage defs and sample types in specs mainly. Since everything share the namespace at the end of the day. I think those are the main benefits of private. In that sense, I consider acceptable if the private top level methods and types are just prefixed with something the user won't easily type, but when expanded the |
Sounds like a smell: adding features to the language to fix limits in Spec's implementation? I would say we don't even need this for specs. For example, instead of a file-private |
It seems this discussion has been a bit mixed up between private types and private methods. While it may be an option to remove private visibility entirely, I'm sure we need to discuss types and methods (variables, constants) separately because they have very different effects. We should keep this discussion focused on private types. Private types are actually causing issues like the one mentioned in the OP. They are can really be confusing. For example, different types can share the same name: # -- private_foo.cr
private class Foo
end
def foo1
Foo.new
end
# -- foo.cr
require "./private_foo"
private class Foo
end
foo2 = Foo.new
typeof(foo1) # => Foo
typeof(foo2) # => Foo
typeof(foo1) == typeof(foo2) # => false The point is, types can't be completely encapsulated. They're always accessible through its instances and thus even a private type is visible and can be used outside the "private bubble". It just can't be directly addressed by name, that's it. There are also benefits to private types. But we need to differentiate between file-private and namespace-private. # this is file-private, only visible in the file where it is defined
private class Foo
end
module Bar
# this is namespace-private, only visible in the Bar namespace
private class Baz
end
end File-private types allow you to define simple helper types and you don't need to worry if the same type might also be defined elsewhere, when you just need it inside that file. This can be handy for spec files. Private types in namespaces are primarily useful to declare a type to be internal for purposes of the namespace and shouldn't be used from outside. But of course, you still can do that. For example by reopening the namespace. You can even do |
I like private types exactly for how they make code simpler - no need to prefix them or place in an unique namespace. |
The type restriction `self` would be strict about the generic type argument, but that's not wanted here. The solution does not work for private generic struct types because the explicit path won't have visibility (crystal-lang#4269).
https://carc.in/#/r/1ufx
Module A declares a private enum, in order to don't open it in public interface (obviously), but instead to use it in the implementation. Expected behavior - module is, well, using it. Current behaviour: things like
Enum#values
are a macroses, so they don't work with private enum.Of course the public enum can be used instead, it adds only a single symbol to namespace so the issue isn't very serious, but still looks like a bug. Maybe private enums should be just forbidden if there is no easy way to fix it.
The text was updated successfully, but these errors were encountered: