<p>Going off of <a href="https://languagedesign.stackexchange.com/questions/360/what-are-the-pros-and-cons-of-an-option-type-in-comparison-to-nullable-types/367#367">this question</a> about the difference between nullable types and optional types, I notice that no mainstream dynamically typed language has ever gone for an explicitly-boxed <code>Option</code> type. Python, Ruby, and Javascript all have null values, called (respectively) <code>None</code>, <code>nil</code>, and <code>null</code>.</p>
<p>Obviously, we could define such a type with something like</p>
<pre><code>class Option:
  def __init__(self, is_empty, value):
    self.is_empty = is_empty
    self.value = value
  def map(self, f):
    if self.is_empty:
      return Option(True, None)
    else:
      return Option(False, f(self.value))
  # ... and other helper functions ...
</code></pre>
<p>What would be the benefits of adding something like this to the standard library in a language where types are not checked at compile time?</p>

<optionals><nullability><dynamic-typing>
Are there any benefits to an Option type in a dynamically-typed language?
CC BY-SA 4.0
2024-10-16T17:26:22.327Z
Fun fact, Visual Basic classic had Nothing, Null and Empty, each with different semantics. Nothing has null reference semantics -- pointer to nowhere -- Null has database null semantics -- we don't know this value -- and Empty is the value of an uninitialized untyped variable. This gives some insight into your question: if the semantics of a null Option are different than those of a null reference, then there is value in having an Option type.
Eric Lippert
CC BY-SA 4.0
2023-05-17T22:00:53.050Z
Does this answer your question? [What are the pros and cons of an Option type in comparison to nullable types?](https://languagedesign.stackexchange.com/questions/360/what-are-the-pros-and-cons-of-an-option-type-in-comparison-to-nullable-types)
Arthur Araruna
CC BY-SA 4.0
2023-06-11T15:26:01.033Z
@ArthurAraruna That talks about Option types and nullable types (at compile time) in statically typed languages. This question is specifically about dynamically typed languages.
user
<h3>Union types</h3>
<p>Some languages never implement an <code>Option</code> type because they can express &quot;one level&quot; <code>Option</code> at syntax level, so <code>Option</code> can be easily expressed as <code>type | null</code>.</p>
<h3>Nullable syntax</h3>
<p><code>Option(type)</code> is analogous to <code>type?</code> <em>until</em> it starts clashing with syntax, usually the ternary operator <code>a ? b : c</code>.</p>
<h3>Nesting</h3>
<p>As commented in <a href="https://langdev.stackexchange.com/a/380/954">user's answer</a>, having an <code>Option</code> type  enables nesting. But it is very uncommon to have <em>nesting syntax</em> (for example, <code>type??</code>, <code>type???</code> and so on) because this further complicates the parsing and clashes with null testing operators like <code>a ?? b</code>.</p>
<p>An <code>Option</code> type allows nesting without any of these problems, and has the nice property of making this language feature more orthogonal.</p>
<h3>De-nesting</h3>
<p>For simple cases of <code>type | null</code>, is possible to examine if a reference is of some type with an <code>is</code> or <code>typeof</code> operator. But where union types <em>and</em> nesting are possible, orthogonality issues start to creep in.</p>
<p>Writing function signatures with nested options is easy enough, but <em>generating</em> or <em>inspecting</em> nested options is not so simple at syntax level.</p>
<p>For example, a nested <code>Option(Option(type))</code> can be expressed as <code>null | ( null | type )</code>. But:</p>
<pre><code>var x = func();    // returns: null | ( null | int )

if ( /* how? */ )
{}
</code></pre>
<p>How to test for the second <code>null</code> case with only syntax?</p>
<p>By having <code>null |</code> being compiled to and being synonymous to <code>Option</code> types, this is simple as <code>if ( x.Value is null )</code>.</p>
<h3>Gradual typing, tooling</h3>
<p>Dynamic typing is a very nice thing to have in small and/or experimental code bases, but as the code base grows, static analysis allows catching a lot of evitable bugs. By having an explicit option <em>native</em> type allows to gradually annotate the code base with types to enable static code analysis.</p>

CC BY-SA 4.0
2024-10-17T14:44:04.303Z
2024-10-22T21:03:54.493Z
2024-10-22T21:03:54.493Z
André L F S Bacci
<p>As a quick remark, dynamically typed languages can still benefit from algebraic-data-type-like constructions in general (for example Prolog and Erlang) for writing correct code (even if the benefits aren't as large as they would be for a statically typed language). ADTs communicate which states are possible and can cause buggy code to break on the happy path, which leads to problems being addressed earlier.</p>
<p>I think providing a dedicated option type in the standard library has value, though, independently of whether the language has a more generic ADT-like facility.</p>
<p>Providing an optional type in the standard library and using it in the standard library, though, is a very strong signal that that is the idiomatic way to do things in your language. And since the standard library is always available, it means that libraries written by different authors can use those types at interface boundaries without needing to coordinate and without requiring a shared dependency.</p>
<p>Putting an option type in the standard library of a dynamically typed language avoids <em>a proliferation of incompatible strategies for encoding optionalness</em>.</p>
<p>In Python, for example, because there's no option type in the standard library, libraries are free to roll their own idioms.</p>
<p>In practice, I think most use one of two strategies:</p>
<ol>
<li>returning <code>None</code> if there's no data.</li>
<li>throwing an exception if there's no data.</li>
</ol>
<p>However, more strategies are possible, in addition to the option type you mentioned. I don't think they're idiomatic Python, though.</p>
<p>It would be perfectly valid to just define <code>Some</code> and leave the built in <code>None</code> as the empty case of an option.</p>
<pre><code>Some = collections.namedtuple('Some', 'data')
</code></pre>
<p>It would also be fine to just a list <code>[]</code> to represent zero or one of something, and throw an exception if the list has more than one element.</p>
<p>The fact that so many possible idioms exist with different tradeoffs is a good reason to choose one in the standard library.</p>

CC BY-SA 4.0
2024-10-16T16:17:22.773Z
2024-10-16T16:17:22.773Z
Greg Nisbet
CC BY-SA 4.0
2024-10-16T16:53:18.437Z
The reasoning here feels somewhat tautological: the advantage of having an option type *is that there is an option type* for people to use. But what actually is the advantage over what you call solutions "In practice" that are in fact already idiomatic and in the standard library and have clear advantage over a naive option type (namely, being very fast)?
MisterMiyagi
CC BY-SA 4.0
2024-10-16T17:58:42.993Z
They don't expose problems in code that doesn't handle the sad path `Empty` without the sad path being executed and it doesn't communicate intent as well.
Greg Nisbet
<p>Functional-style handling comes to mind. Even in your example, you have introduced a <code>map</code> method. This kind of API is very convenient for chained operations on <code>Option</code>s, and cannot be easily provided for a dynamic <code>None</code> (unless you make such methods common to all objects)</p>

CC BY-SA 4.0
2023-05-17T16:28:50.770Z
2023-05-17T16:28:50.770Z
abel1502
<h2>Nesting</h2>
<p>In a language with <code>Option</code>s, you can have a function that takes a list of values and returns a new list with those same values wrapped in <code>Some</code>s. In a language without <code>Option</code>s, you couldn't do that, as there'd be no way to distinguish between <code>Some(None)</code> and <code>None</code>.</p>

CC BY-SA 4.0
2023-05-17T16:22:23.663Z
2023-05-17T16:22:23.663Z
user
CC BY-SA 4.0
2024-10-16T20:55:52.163Z
Note that you can nest an optional type without having to use boxing (not editing my answer itself because it's been upvoted already)
user
# Are there any benefits to an Option type in a dynamically-typed language?
Posted by: username_0 on 2023-05-17
Going off of this question about the difference between nullable types and optional types, I notice that no mainstream dynamically typed language has ever gone for an explicitly-boxed Option type. Python, Ruby, and Javascript all have null values, called (respectively) None, nil, and null.
Obviously, we could define such a type with something like
class Option:
  def __init__(self, is_empty, value):
    self.is_empty = is_empty
    self.value = value
  def map(self, f):
    if self.is_empty:
      return Option(True, None)
    else:
      return Option(False, f(self.value))
  # ... and other helper functions ...

What would be the benefits of adding something like this to the standard library in a language where types are not checked at compile time?
**Tags:** optionals nullability dynamic-typing
> **Comments:**
> **username_2**: Does this answer your question? [What are the pros and cons of an Option type in comparison to nullable types?](https://languagedesign.stackexchange.com/questions/360/what-are-the-pros-and-cons-of-an-option-type-in-comparison-to-nullable-types)  
> **username_3**: @ArthurAraruna That talks about Option types and nullable types (at compile time) in statically typed languages. This question is specifically about dynamically typed languages.  
> **username_1**: Fun fact, Visual Basic classic had Nothing, Null and Empty, each with different semantics. Nothing has null reference semantics -- pointer to nowhere -- Null has database null semantics -- we don't know this value -- and Empty is the value of an uninitialized untyped variable. This gives some insight into your question: if the semantics of a null Option are different than those of a null reference, then there is value in having an Option type.  
---
## 4 answers
### Answer by username_3 on 2023-05-17. Score: 16
## Nesting

In a language with `Option`s, you can have a function that takes a list of values and returns a new list with those same values wrapped in `Some`s. In a language without `Option`s, you couldn't do that, as there'd be no way to distinguish between `Some(None)` and `None`.
> **Comments:**
> **username_3** (2024-10-16): Note that you can nest an optional type without having to use boxing (not editing my answer itself because it's been upvoted already)  
---
### Answer by username_7 on 2023-05-17. Score: 9
Functional-style handling comes to mind. Even in your example, you have introduced a `map` method. This kind of API is very convenient for chained operations on `Option`s, and cannot be easily provided for a dynamic `None` (unless you make such methods common to all objects)
---
### Answer by username_4 on 2024-10-17. Score: 3
Union types
Some languages never implement an Option type because they can express "one level" Option at syntax level, so Option can be easily expressed as type | null.
Nullable syntax
Option(type) is analogous to type? until it starts clashing with syntax, usually the ternary operator a ? b : c.
Nesting
As commented in user's answer, having an Option type  enables nesting. But it is very uncommon to have nesting syntax (for example, type??, type??? and so on) because this further complicates the parsing and clashes with null testing operators like a ?? b.
An Option type allows nesting without any of these problems, and has the nice property of making this language feature more orthogonal.
De-nesting
For simple cases of type | null, is possible to examine if a reference is of some type with an is or typeof operator. But where union types and nesting are possible, orthogonality issues start to creep in.
Writing function signatures with nested options is easy enough, but generating or inspecting nested options is not so simple at syntax level.
For example, a nested Option(Option(type)) can be expressed as null | ( null | type ). But:
var x = func();    // returns: null | ( null | int )

if ( /* how? */ )
{}

How to test for the second null case with only syntax?
By having null | being compiled to and being synonymous to Option types, this is simple as if ( x.Value is null ).
Gradual typing, tooling
Dynamic typing is a very nice thing to have in small and/or experimental code bases, but as the code base grows, static analysis allows catching a lot of evitable bugs. By having an explicit option native type allows to gradually annotate the code base with types to enable static code analysis.
---
### Answer by username_5 on 2024-10-16. Score: 2
As a quick remark, dynamically typed languages can still benefit from algebraic-data-type-like constructions in general (for example Prolog and Erlang) for writing correct code (even if the benefits aren't as large as they would be for a statically typed language). ADTs communicate which states are possible and can cause buggy code to break on the happy path, which leads to problems being addressed earlier.
I think providing a dedicated option type in the standard library has value, though, independently of whether the language has a more generic ADT-like facility.
Providing an optional type in the standard library and using it in the standard library, though, is a very strong signal that that is the idiomatic way to do things in your language. And since the standard library is always available, it means that libraries written by different authors can use those types at interface boundaries without needing to coordinate and without requiring a shared dependency.
Putting an option type in the standard library of a dynamically typed language avoids a proliferation of incompatible strategies for encoding optionalness.
In Python, for example, because there's no option type in the standard library, libraries are free to roll their own idioms.
In practice, I think most use one of two strategies:

returning None if there's no data.
throwing an exception if there's no data.

However, more strategies are possible, in addition to the option type you mentioned. I don't think they're idiomatic Python, though.
It would be perfectly valid to just define Some and leave the built in None as the empty case of an option.
Some = collections.namedtuple('Some', 'data')

It would also be fine to just a list [] to represent zero or one of something, and throw an exception if the list has more than one element.
The fact that so many possible idioms exist with different tradeoffs is a good reason to choose one in the standard library.
> **Comments:**
> **username_6** (2024-10-16): The reasoning here feels somewhat tautological: the advantage of having an option type *is that there is an option type* for people to use. But what actually is the advantage over what you call solutions "In practice" that are in fact already idiomatic and in the standard library and have clear advantage over a naive option type (namely, being very fast)?  
> **username_5** (2024-10-16): They don't expose problems in code that doesn't handle the sad path `Empty` without the sad path being executed and it doesn't communicate intent as well.  
---
