5

How can I use use something like variant (which is in C++) in Julia?

In C++, I can do something like this

variant<int, float> value;

How can I do the same thing in Julia for a parameter of a function?

function func(??)
    # something
end

Sorry if it does not convey what I want to do.

pooooky
  • 490
  • 2
  • 12
  • You should add what kind of operations you want to be able to do with such a type. I.e., should it be a tagged or untagged union. – phipsgabler Jan 05 '22 at 08:50

2 Answers2

9

You can use union types to do the same.

function func(x::Union{Int, AbstractFloat})
    x + 1
end

Note that C++ std::variant is a tagged union, so you can always ask "which" variant it is, whereas a Julia union is a proper set union. Pragmatically, that means that in std::variant<int, int>, you can distinguish between a "left int" and a "right int", but a Union{Int, Int} really is just an Int. There's no way to tell which "side" it came from. To emulate the exact tagged union behavior, you'll need to make some custom structs to represent each case.

struct LeftInt
    value :: Int
end

struct RightInt
    value :: Int
end

function func(x::Union{LeftInt, RightInt})
    # ... Check whether x is a LeftInt or not ...
end

but, in Julia, you often don't need this, and if you do then it's generally smarter to work with generic functions to do your dispatching anyway.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
  • (don't know C++) How would you distinguish the left and right `int` in the `variant`? Like if the variable has a value 5, wouldn't any `typeof`-like function only be able to tell the value's type is an `int`, not which one? – BatWannaBe Jan 05 '22 at 00:49
  • 1
    @BatWannaBe Normally, you'll let the automatic type conversions take care of everything for you. But you can tell which variant is in use via [the `index` function](https://en.cppreference.com/w/cpp/utility/variant/index). And C++ provides constructors for `std::variant` which allow you to specify which variant to use, i.e. `std::variant(std::in_place_index<0>, 100)` versus `std::variant(std::in_place_index<1>, 100)`. Normally, you wouldn't need any of this, but it is a distinction that the C++ compiler keeps track of. – Silvio Mayolo Jan 05 '22 at 01:58
  • 1
    [Here](https://tio.run/##fY7RCoIwFIbv9xQHuynS0AgCXb6KjDl1MKdsMwLx1VvTSsGwm3Px/f/5zqFtG5SUWrvjkoouZ4DvRHEiTYoWxBttFCN1ihCXBmrC5f4APQLQJo/jzwZ2mQ9upCBYYbKx2r8bXGatIJQ5lrMHDlMfLmcYkm2D4mX1TxGtFbTpDGAM3ny7IhqmMnhj8OWnibn/HZs2mczFr2Z5YOWZg02RYqZTEsIEDdY@aSFIqW3gKjd6PEbXFw "C++ (gcc) – Try It Online") is a runnable example of what I'm talking about. Two `std::variant` where we can distinguish which one is the "left" and which is the "right". – Silvio Mayolo Jan 05 '22 at 02:01
3

In Julia, you can just write

function func(value)
    # something
end

and the compiler will then automatically compile for you separate type-specific method of this untyped function whenever you call it with another type.

In Julia, unlike in C++, you usually don't provide a parameter type at all, and you instead let the compiler figure out the types for you. Any parameter types that you provide are just assertions, or help to dispatch to the right method in case you want to provide different implementations for different types yourself.

Markus Kuhn
  • 983
  • 9
  • 10