Literal Types in Julia

Viewed 107

What is the best pattern to create literal types in Julia?

In Typescript, you can make types out of string literals:

type command = "start" | "end" | "pause";

In Julia, this would allow you to use multiple-dispatch with string arguments, making it easy to extend cases.

An example of this would look like

function process(::"start") 
    initialize()
    do_something()
    ...
end

function process(::"end")
    teardown()
    ...
end

function process(::"pause")
    temporary_pause()
    ...
end

Currently, I am using a workaround similar to this

struct CommandType{T}
end

CommandType(s::AbstractString) = CommandType{Symbol(s)}()

macro CommandType_str(s)
  return CommandType{Symbol(s)}
end

function process(t::CommandType"start")
  ...
end

function process(t::CommandType"stop")
  ...
end

function process(t::CommandType"pause")
  ...
end

process(command::String) = process(CommandType(command))

# Usage
process("start")

Is there a more succinct pattern I can use? Is it possible that literal types will be added to Julia in the near future?

2 Answers

As far as I know the current practice is essentially what you have developed. To be concrete it is to use Val with Symbol argument. So your function signature would be e.g. process(::Val{:start}) and you would call it with process(Val(:start)) (of course you could use a utility function or macro to generate Val(:start) from a string as in your code if you wanted)

I would take another approach to your problem, don't rely on string or symbols to determine which function to use, instead write functions that have clear names.

For example, your function is named process() and takes a start command. What I'm I processing? Do I do something with that command in the function?

Instead what if I wrote:

function start_service(# pass required arguments)
   ...
end 

Sounds better, I know what I'm starting and the necessary arguments, if any, would make sense.

Later on, I decide I need to write data to a file, I now have to update the Command, perhaps, write?

function process(::CommandType"write",path::AbstractString,data)
    # What is being written? Error log? Data?
end

It would be cleaner to write:

write_data_to(path::AbstractString)
Related