# Letting users change the default types

**URL:** <https://discourse.julialang.org/t/letting-users-change-the-default-types/66781>\
**Category:** Internals & Design\
**Created:** [August 21, 2021, 4:13pm UTC](https://discourse.julialang.org/t/letting-users-change-the-default-types/66781 "2021-08-21T16:13:34Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![Lucas\_Queiroz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucas_queiroz/32/12086_2.png) [@Lucas\_Queiroz](https://discourse.julialang.org/u/Lucas_Queiroz)\
**Post date:** [August 21, 2021, 4:13pm UTC](https://discourse.julialang.org/t/letting-users-change-the-default-types/66781/1 "2021-08-21T16:13:34Z")

</div>

It is common that programming languages have different types with similar or analogous functionality. For example, consider the integer types `Int64`, `BigInt`, or the float point types `Float64`, `BigFloat`.

The reason for this proriferation of types is that none of them is adequate for every situation. `Int64` is favored when one needs high speed of execution, whereas `BigInt` is favored when one is doing calculations with very big numbers.

Given that for some users, the `Big` types might be more adequate than the `64` types, why not let the user decide which one of them is Julia’s default?

The kinds of calculations that I do are so small, that I actually have the luxury of not worrying so much about efficiency. In my case, the `BigInt` type is much more convenient for me than the `Int64` type, because using the first I do not have to check for integer overflow.

But the only way I have of writting Julia code with the `Big` types in place of the `64` types is either to use the `big"-"` or syntax everywhere, or to start every line of code with some macro. A trivial arithmetical operation `julia> 157 + 82` would become `julia> big"157" + big"82"` or `julia> @MyMacro 157 + 82`.

I have some arguments for letting the users change the default types:

1. It seems that many programmer prefer big integers over 64 bits integers.

This might be inferred from the fact that some popular languages (among them Python, JavaScript, Haskell, Ruby) chose big integers as their default.

1. There are languages that allow users to change the default type.

At least Haskell does this: [Kwang's Haskell Blog - Type defaulting in Haskell](https://kseo.github.io/posts/2017-01-04-type-defaulting-in-haskell.html)

1. Letting users change the default type fits very well with the philosophy and design of the Julia Language, as I understood it.Ju

Julia tries not to privilege it’s built-in types, and gives the user the flexibility to use his own custom type. In Julia we have numbers with measurement units(Unitful.jl), dual number(DualNumbers.jl), doublefloats(DoubleFloats.jl), and those numbers are just as good and efficient as the built-in numbers - something that is unimaginable in other languages.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [August 21, 2021, 4:21pm UTC](https://discourse.julialang.org/t/letting-users-change-the-default-types/66781/2 "2021-08-21T16:21:09Z")

</div>

> [@Lucas\_Queiroz](#):
>
> Given that for some users, the `Big` types might be more adequate than the `64` types, why not let the user decide which one of them is Julia’s default?

how does this affect libraries? does each module has its own default type? What about calling other functions from other module?

The fact that most libraries are written size-agnostic, as you have noted, means users can do what they think is the best.

Check out:

> [@\[ANN\] SafeREPL: use BigInt by default at the REPL](https://discourse.julialang.org/t/ann-saferepl-use-bigint-by-default-at-the-repl/41271):
>
> With Julia 1.5 around the corner, I’m happy to present [SafeREPL](https://github.com/rfourquet/SafeREPL.jl), a little experimental package which by default interprets Int and Int128 REPL literals as BigInt, and Float64 literals as BigFloat: julia\> using SafeREPL julia\> factorial(40) 815915283247897734345611269596115894272000000000 julia\> sqrt(2.0) 1.414213562373095048801688724209698078569671875376948073176679737990732478462102 julia\> c = 299\_792\_458; c^3 # the cube of the speed of light can even be computed safely! 26944002417373989…

---

<div class="post-metadata">

**Author:** ![genkuroki](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/genkuroki/32/18030_2.png) [@genkuroki](https://discourse.julialang.org/u/genkuroki)\
**Post date:** [August 21, 2021, 5:10pm UTC](https://discourse.julialang.org/t/letting-users-change-the-default-types/66781/3 "2021-08-21T17:10:50Z")

</div>

Small (but `@big` 😊) working example:

```julia
"""
    big!(expr)

replaces `Int` and `Float64` values in `expr` by big ones and returns the result.
"""
big!(expr) = expr
big!(expr::Int) = big(expr)
big!(expr::Float64) = big(expr)
function big!(expr::Expr)
    for i in eachindex(expr.args)
        expr.args[i] = big!(expr.args[i])
    end
    expr
end

"""
    @big(expr)
    @big expr

replaces `Int` and `Float64` values in `expr` by big ones and executes the result.
"""
macro big(expr) big!(expr) end

```

Input:

```julia
1.0π

```

Output:

> 3.141592653589793

Input:

```julia
@big 1.0π

```

Output:

> 3.141592653589793238462643383279502884197169399375105820974944592307816406286198

Input:

```julia
for n in 20:24
    println("factorial(", n, ") = ", factorial(n))
end

```

Output:

> factorial(20) = 2432902008176640000  
> OverflowError: 21 is too large to look up in the table; consider using `factorial(big(21))` instead

Input:

```julia
@big for n in 20:24
    println("factorial(", n, ") = ", factorial(n))
end

```

Output:

> factorial(20) = 2432902008176640000  
> factorial(21) = 51090942171709440000  
> factorial(22) = 1124000727777607680000  
> factorial(23) = 25852016738884976640000  
> factorial(24) = 620448401733239439360000

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 22, 2021, 2:36pm UTC](https://discourse.julialang.org/t/letting-users-change-the-default-types/66781/4 "2021-08-22T14:36:15Z")

</div>

This is a minor point, but I am not sure one should consider expressions mutable, it is not guaranteed that they don’t share structure. I would just generate a new expression.

---

<div class="post-metadata">

**Author:** ![Lucas\_Queiroz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucas_queiroz/32/12086_2.png) [@Lucas\_Queiroz](https://discourse.julialang.org/u/Lucas_Queiroz)\
**Post date:** [August 22, 2021, 3:25pm UTC](https://discourse.julialang.org/t/letting-users-change-the-default-types/66781/5 "2021-08-22T15:25:34Z")

</div>

Hi!

What do you mean? I do not feel that I understood what you said?

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [August 22, 2021, 4:26pm UTC](https://discourse.julialang.org/t/letting-users-change-the-default-types/66781/6 "2021-08-22T16:26:21Z")

</div>

I believe it was a comment on the solution offered by @genkuroki, where the `big!` fiction mutates expression objects.

---

<div class="post-metadata">

**Author:** ![Lucas\_Queiroz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucas_queiroz/32/12086_2.png) [@Lucas\_Queiroz](https://discourse.julialang.org/u/Lucas_Queiroz)\
**Post date:** [August 22, 2021, 4:38pm UTC](https://discourse.julialang.org/t/letting-users-change-the-default-types/66781/7 "2021-08-22T16:38:46Z")

</div>

I see

---

<div class="post-metadata">

**Author:** ![Lucas\_Queiroz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucas_queiroz/32/12086_2.png) [@Lucas\_Queiroz](https://discourse.julialang.org/u/Lucas_Queiroz)\
**Post date:** [August 22, 2021, 4:52pm UTC](https://discourse.julialang.org/t/letting-users-change-the-default-types/66781/8 "2021-08-22T16:52:11Z")

</div>

I understand your concern for preserving library code. I agree that keeping our libraries intact is crucial for the language.

However, Julia discourages the use of numeric literals when writting functions.

For example, the code below is regarded as bad coding practice, for being type unstable.

```julia
function f(x)
	if x >= 0
		return x
	else
		return 0
	end
end

```

We are encouraged to write the function `f()` the following way:

```julia
funcion f(x)
	if x >= zero(x)
		return x
	else
		return zero(x)
	end
end

```

That is, we are encouraged to use the multimethod functions `zero()`, `one()` instead of the literals `0`, `1`.

Because Julian code tends to be generic, I do not think that making the numeric literals dependant on some global state would cause much damage to our code-base.

---

<div class="post-metadata">

**Author:** ![genkuroki](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/genkuroki/32/18030_2.png) [@genkuroki](https://discourse.julialang.org/u/genkuroki)\
**Post date:** [August 22, 2021, 10:11pm UTC](https://discourse.julialang.org/t/letting-users-change-the-default-types/66781/9 "2021-08-22T22:11:37Z")

</div>

A well-written Julia function is type stable and can accept a sufficiently wide range of arguments. Therefore, there is no need to convert the numeric values in the function code to BigInt or BigFloat.

**If we just give values of BigInt or BigFloat type as arguments to the function, then it should perform the calculation with sufficient digits and sufficient precision.**

Therefore, I think that the only correct use of the `@big` macro introduced above is to simply convert the types of the values given as function arguments to BigInt or BigFloat easily.

Example:

```julia
@big @eval begin
    n = 57
    c = Tuple(1/factorial(k) for k in 0:n)
end
evalpoly(1, c)

```

> 2.718281828459045235360287471352662497757247093699959574966967627724076630353555

```julia
@big exp(1)

```

> 2.718281828459045235360287471352662497757247093699959574966967627724076630353555

```julia
typeof(c)

```

> NTuple{58, BigFloat}

---

<div class="post-metadata">

**Author:** ![Lucas\_Queiroz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucas_queiroz/32/12086_2.png) [@Lucas\_Queiroz](https://discourse.julialang.org/u/Lucas_Queiroz)\
**Post date:** [August 22, 2021, 10:44pm UTC](https://discourse.julialang.org/t/letting-users-change-the-default-types/66781/10 "2021-08-22T22:44:34Z")

</div>

Your macro does solve the problem I am facing. The only thing is that it is not very convenient to write a macro invocation in every line of my code.

But perhaps it might be possible to configure Julia’s REPL so that it automatically applies your macro to every line of code. Someone who knows Julia’s internal much better than I do might be capable of doing that.

---

<div class="post-metadata">

**Author:** ![genkuroki](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/genkuroki/32/18030_2.png) [@genkuroki](https://discourse.julialang.org/u/genkuroki)\
**Post date:** [August 22, 2021, 11:10pm UTC](https://discourse.julialang.org/t/letting-users-change-the-default-types/66781/11 "2021-08-22T23:10:40Z")

</div>

I recommend the following way:

1. Write type-stable functions that can be computed with high precision by simply giving values of BigInt or BigFloat type as arguments.

2. If necessary, provide BigInt or BigFloat type arguments to these functions. Use the `@big` macro only in this case.

If you want to act the `@big` macro on multiple lines at once, enclose the lines with `@big @eval begin` and `end`.

---

<div class="post-metadata">

**Author:** ![non-Jedi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/non-jedi/32/3645_2.png) [@non-Jedi](https://discourse.julialang.org/u/non-Jedi)\
**Post date:** [August 22, 2021, 11:52pm UTC](https://discourse.julialang.org/t/letting-users-change-the-default-types/66781/12 "2021-08-22T23:52:46Z")

</div>

> [@Lucas\_Queiroz](#):
>
> But perhaps it might be possible to configure Julia’s REPL so that it automatically applies your macro to every line of code. Someone who knows Julia’s internal much better than I do might be capable of doing that.

This is exactly what the SafeREPL package linked above does:

> **[GitHub - rfourquet/SafeREPL.jl: Swap the meaning of literals in the Julia REPL](https://github.com/rfourquet/SafeREPL.jl)**
>
> Swap the meaning of literals in the Julia REPL. Contribute to rfourquet/SafeREPL.jl development by creating an account on GitHub.

---

<div class="post-metadata">

**Author:** ![Lucas\_Queiroz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucas_queiroz/32/12086_2.png) [@Lucas\_Queiroz](https://discourse.julialang.org/u/Lucas_Queiroz)\
**Post date:** [August 23, 2021, 12:46am UTC](https://discourse.julialang.org/t/letting-users-change-the-default-types/66781/13 "2021-08-23T00:46:07Z")

</div>

I see, they have a SwapLiterals subpackage that lets me change the meaning of Julia literals 😀

---

<div class="post-metadata">

**Author:** ![Lucas\_Queiroz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucas_queiroz/32/12086_2.png) [@Lucas\_Queiroz](https://discourse.julialang.org/u/Lucas_Queiroz)\
**Post date:** [August 23, 2021, 1:26am UTC](https://discourse.julialang.org/t/letting-users-change-the-default-types/66781/14 "2021-08-23T01:26:35Z")

</div>

SafeREPL has just saved my life! I can hardly overstated how much the package makes my life easier
