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

Support for single instance types #50

Open
ptarjan opened this issue Sep 13, 2017 · 4 comments
Open

Support for single instance types #50

ptarjan opened this issue Sep 13, 2017 · 4 comments

Comments

@ptarjan
Copy link
Contributor

ptarjan commented Sep 13, 2017

Do you plan on having any notion of "this parameter must == to either 'foo' or 'bar'"?

We use this pretty extensively in our runtime type system and call it Enum but it can be phrased as single instance class and the Enum is just a union over those.

@rmosolgo
Copy link

rmosolgo commented Oct 5, 2017

It looks like this is kinda supported via singleton types, for example:

require "rdl"

class A
  extend RDL::Annotate
  MAGIC_VALUE = 'c'
  
  type("(${A::MAGIC_VALUE}) -> %any")
  def b(arg)
    arg.upcase
  end
end


puts A.new.b('c') # passes 
puts A.new.b('d') # 💥 fails

But, it requires:

  • A constant to put inside ${...} (when I used a string literal, I got a parse error)
  • A full reference to the constant (when I skipped A::, I got a name error for no such constant Kernel::MAGIC_VALUE)

Just thought I'd share in case that arrangement works for anyone else.

@ptarjan
Copy link
Contributor Author

ptarjan commented Oct 6, 2017

@rmosolgo how do you do the "OR" part? RDL does support literals which I think you're showing off.

@rmosolgo
Copy link

rmosolgo commented Oct 6, 2017

Ohhh right, you don't want just one value, you want "one of a set of values".

It's still not quite there but here's what I found:

require "rdl"

class A
  MAGIC_VALUE_1 = 'c'
  MAGIC_VALUE_2 = 'd'
  extend RDL::Annotate
  RDL.type_alias("%some_enum", "${A::MAGIC_VALUE_1} or ${A::MAGIC_VALUE_2}")
  type("(%some_enum) -> %any")
  def b(arg)
    arg.upcase
  end
end


puts A.new.b(A::MAGIC_VALUE_1) # pass
puts A.new.b(A::MAGIC_VALUE_2) # pass
puts A.new.b('z') # 💥

not ideal, and still some caveats:

  • I had to use the constants, I couldn't use string literals as in the previous example
  • It has to be RDL.type_alias(...), not bare type_alias(...) (not sure if that's a bug or if the docs need an update)

@jeffrey-s-foster
Copy link
Contributor

Singleton types work for symbols, nil, and numeric types. But I didn't add direct support for strings because of mutability. For example, suppose we had string singleton types, so we could say var_type :@x, "'foo'". Now let x = 'foo' and set @x = x. This should be fine, since x contains the string matching the singleton type 'foo'. But now suppose we to x[0] = 'g'. Now x has type 'foo', but it actually contains 'goo'.

@ptarjan, this seems like another case that should be allowed (controlled by some configuration option), since presumably you can't and don't want to change your codebase to use symbols instead of strings.

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

3 participants