# Use generic to define method

**URL:** <https://forum.crystal-lang.org/t/use-generic-to-define-method/1866>\
**Category:** Crystal Contrib\
**Created:** [March 25, 2020, 6:18am UTC](https://forum.crystal-lang.org/t/use-generic-to-define-method/1866 "2020-03-25T06:18:43Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![rogerdpack](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/rogerdpack/32/117_2.png) [@rogerdpack](https://forum.crystal-lang.org/u/rogerdpack)\
**Post date:** [March 25, 2020, 6:18am UTC](https://forum.crystal-lang.org/t/use-generic-to-define-method/1866/1 "2020-03-25T06:18:43Z")

</div>

Is it possible to define methods relative to a generic type? Or access the generic type outside of methods at all? This:

```auto
module Moo(T)
  {% if T < Number %}
    def method(param1=true)
    end
  {% else %}
    def method(param1=false)
    end
  {% end %}
end

```

yields this:

```auto

 3 | {% if T < Number %}
           ^
Error: undefined constant T

```

But if I put that same statement within the method, it compiles fine.

Any ideas on how to vary a parameter value based on a generic type? For now I’m going to just use an Enum and have it default to 'default" and override it within the method if it’s “default” 😑

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [March 25, 2020, 11:53am UTC](https://forum.crystal-lang.org/t/use-generic-to-define-method/1866/2 "2020-03-25T11:53:21Z")

</div>

It doesn’t work like that because macros at the “top level” are expanded as soon as you reach them.

What you want is possible:

```crystal
module Moo(T)
  def method
    method({{ T < Number }})
  end

  def method(param1)
  end
end

```

---

<div class="post-metadata">

**Author:** ![rogerdpack](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/rogerdpack/32/117_2.png) [@rogerdpack](https://forum.crystal-lang.org/u/rogerdpack)\
**Post date:** [March 26, 2020, 2:22am UTC](https://forum.crystal-lang.org/t/use-generic-to-define-method/1866/3 "2020-03-26T02:22:51Z")

</div>

Nice! So I can set a default based on type.

I’m trying to satisfy [https://github.com/crystal-lang/crystal/issues/6057](https://github.com/crystal-lang/crystal/issues/6057) and was hoping to set

```auto
def sort(stable = false) : Array(T)

```

with the “stable” set to false for Number types and true for Objects (since stable doesn’t matter for Numbers). It appears that I won’t be able to do that in the type signature…

Anybody have any ideas on how to accomplish this? Suggestions? Enum? Thanks for any help.

Update: It appears I can use something like a param whose default value is a method call to accomplish it, thanks for the hints:

```auto
class Moo(T)
  def get_type()
    {{ T < Number }}
  end

  def method(param1 = get_type())
   puts param1
  end
end

Moo(Int32).new.method # => true
Moo(String).new.method # => false

```

---

<div class="post-metadata">

**Author:** ![tsundsted](https://avatars.discourse-cdn.com/v4/letter/t/ecccb3/32.png) [@tsundsted](https://forum.crystal-lang.org/u/tsundsted)\
**Post date:** [March 26, 2020, 8:53am UTC](https://forum.crystal-lang.org/t/use-generic-to-define-method/1866/4 "2020-03-26T08:53:18Z")

</div>

You could also avoid the method and drop the macro into the argument list:

```crystal
class Moo(T)
  def method(param1 = {{ T < Number }})
   puts param1
  end
end

puts Moo(Int32).new.method # => true
puts Moo(String).new.method # => false

```

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [March 26, 2020, 11:52am UTC](https://forum.crystal-lang.org/t/use-generic-to-define-method/1866/5 "2020-03-26T11:52:26Z")

</div>

> [@tsundsted](#):
>
> You could also avoid the method and drop the macro into the argument list

TIL
