# Some thoughts for Crystal arguments default value and type inference

**URL:** <https://forum.crystal-lang.org/t/some-thoughts-for-crystal-arguments-default-value-and-type-inference/5045>\
**Category:** Help & Support\
**Created:** [October 29, 2022, 7:11pm UTC](https://forum.crystal-lang.org/t/some-thoughts-for-crystal-arguments-default-value-and-type-inference/5045 "2022-10-29T19:11:43Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![zw963](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/zw963/32/1623_2.png) [@zw963](https://forum.crystal-lang.org/u/zw963)\
**Post date:** [October 29, 2022, 7:11pm UTC](https://forum.crystal-lang.org/t/some-thoughts-for-crystal-arguments-default-value-and-type-inference/5045/1 "2022-10-29T19:11:43Z")

</div>

Following is a example:

```auto
require "yaml"

class A
  @option : YAML::Any

  def initialize(option = YAML.parse("{}"))
    @option = option
  end
end

if File.file? "1.yml"
  option = YAML.parse(File.read("1.yml"))
end

a = A.new(option)

```

This will get error like this:

```auto
In 1.cr:15:7

 15 | a = A.new(option)
            ^--
Error: no overload matches 'A.new' with type (YAML::Any | Nil)

Overloads are:
 - A.new(option : ::YAML::Any = YAML.parse("{}"))
Couldn't find overloads for these types:
 - A.new(option : Nil)

```

Okay, this is expected, because the `option` args can’t be nil.

So, the question is, what is the purpose of this default value parameter? okay, this make not pass this parameter is possible, But if you pass a nil, it will raise error, Ruby blurs the lines, but, in Crystal, you have to distinguish pass a nil as parameter with not pass it.

Let change code to make pass nil is possible.

```crystal
require "yaml"

class A
  @option : YAML::Any

  def initialize(option : YAML::Any? = YAML.parse("{}"))
    @option = option
  end
end

if File.file? "1.yml"
  option = YAML.parse(File.read("1.yml"))
end

a = A.new(option)

```

It should work, right? because `@option` can never by nil, but still get compile error:

```auto
In 1.cr:7:5

 7 | @option = option
     ^------
Error: instance variable '@option' of A must be YAML::Any, not (YAML::Any | Nil)

```

Any idea?

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [October 29, 2022, 7:46pm UTC](https://forum.crystal-lang.org/t/some-thoughts-for-crystal-arguments-default-value-and-type-inference/5045/2 "2022-10-29T19:46:47Z")

</div>

> [@zw963](#):
>
> It should work, right? because `@option` can never by nil, but still get compile error:

That’s precisely the problem, `@option` isn’t nilable, but you’re allowed to pass a `nil` argument to the constructor. This in turn changes the error from “no overload” to what you see there because you’re trying to assign a variable that can be nilable to an ivar that cannot.

In this case, I’d do something like:

```auto
def initialize(option : YAML::Any? = nil)
  @option = option || YAML.parse("{}")
end

```

Related: [[RFC] Undefined Type](https://forum.crystal-lang.org/t/rfc-undefined-type/2695)

---

<div class="post-metadata">

**Author:** ![zw963](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/zw963/32/1623_2.png) [@zw963](https://forum.crystal-lang.org/u/zw963)\
**Post date:** [October 29, 2022, 7:55pm UTC](https://forum.crystal-lang.org/t/some-thoughts-for-crystal-arguments-default-value-and-type-inference/5045/3 "2022-10-29T19:55:00Z")

</div>

```auto
def initialize(option : YAML::Any? = nil)
  @option = option || YAML.parse("{}")
end

```

Yes, a really nice workaround.

> `@option` isn’t nilable, but you’re allowed to pass a `nil` argument to the constructor. This in turn changes the error from “no overload” to what you see there because you’re trying to assign a variable that can be nilable to an ivar that cannot.

Oops, i messed up something, i thought when pass a nil as parameter, it will use default value `YAML.parse("{}")`, i am wrong, thanks.
