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

Type restriction a : ModFoo & ModBar #7534

Open
bew opened this issue Mar 10, 2019 · 6 comments
Open

Type restriction a : ModFoo & ModBar #7534

bew opened this issue Mar 10, 2019 · 6 comments

Comments

@bew
Copy link
Contributor

bew commented Mar 10, 2019

Didn't find another issue about that except #1839 (comment)

I think there's no easy way to do that atm, I'd like to restrict my argument to have ModFoo AND ModBar as in:

module ModFoo
  abstract def foo
end

module ModBar
  abstract def bar
end

class FooBar
  include ModFoo
  include ModBar
  def foo; end
  def bar; end
end

class OnlyFoo
  include ModFoo
  def foo; end
end

# The argument should have ModFoo AND ModBar
def need_foo_and_bar(param : ModFoo & ModBar)
  puts param.foo
  puts param.bar
end

need_foo_and_bar(FooBar.new)  # should work
need_foo_and_bar(OnlyFoo.new) # should fail

I know it's not currently possible as is, but has it been considered at some point?

How can I restrict the param without 'workaround' like creating a module that include both, and include that module in all classes that include both (e.g: found using some macro-fu). Or using forall & macro checks at beginning of the method (see #7534 (comment))

I know I could simply not restrict the param and rely on the compiler telling the user that the given arg doesn't have method foo or bar. But what if those methods are generated, the user doesn't necessarily know where they come from and what to do (include some module) to be able to pass their object.

@konovod
Copy link
Contributor

konovod commented Mar 10, 2019

Madskillz, but if you really need to restrict with both you can do something like this:

private def need_foo_and_bar_impl(param : ModBar)
  puts param.foo
  puts param.bar
end

# The argument should have ModFoo AND ModBar
def need_foo_and_bar(param : ModFoo)
  need_foo_and_bar_impl(param)
end

https://carc.in/#/r/6gqk

@bew
Copy link
Contributor Author

bew commented Mar 10, 2019

@konovod THAT is a fun workaround 😄

Actually I've found another one: https://carc.in/#/r/6gs1

# The argument should have ModFoo AND ModBar
def need_foo_and_bar(param : T) forall T
  {% unless T < ModFoo && T < ModBar %}
    {% raise "nop!" %}
  {% end %}
  puts param.foo
  puts param.bar
end

But I don't have any trace now..

@straight-shoota
Copy link
Member

Also an option: typeof(param_bar : ModBar = param)

@bew
Copy link
Contributor Author

bew commented Mar 10, 2019

Also an option: typeof(param_bar : ModBar = param)

What do you mean? An option for a workaround? or for a way to restrict the param?
Also how would I use it for the need_foo_and_bar example?

@straight-shoota
Copy link
Member

As a workaround.

# The argument should have ModFoo AND ModBar
def need_foo_and_bar(param : ModFoo)
  typeof(param_bar : ModBar = param)
  param.foo
  param.bar
end

https://carc.in/#/r/6gsb

@HertzDevil
Copy link
Contributor

Related: #2404

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

No branches or pull requests

4 participants