# Parse String to DataType

**URL:** <https://discourse.julialang.org/t/parse-string-to-datatype/7118>\
**Category:** General Usage\
**Tags:** question, strings\
**Created:** [November 17, 2017, 8:35am UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118 "2017-11-17T08:35:50Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [November 17, 2017, 8:35am UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/1 "2017-11-17T08:35:50Z")

</div>

I can do

```julia
julia> s = "Complex{Float64}"
"Complex{Float64}"

julia> x = eval(parse(s))
Complex{Float64}

julia> typeof(x)
DataType

```

Is there a neater way than using `eval` to interpret the string as a datatype? Why is there no `parse(DataType, s)`?

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [November 17, 2017, 8:49am UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/2 "2017-11-17T08:49:04Z")

</div>

x-ref: [https://github.com/JuliaLang/julia/issues/24349](https://github.com/JuliaLang/julia/issues/24349)

---

<div class="post-metadata">

**Author:** ![greg\_plowman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/greg_plowman/32/8100_2.png) [@greg\_plowman](https://discourse.julialang.org/u/greg_plowman)\
**Post date:** [November 17, 2017, 11:13am UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/3 "2017-11-17T11:13:11Z")

</div>

Perhaps `include_string(s)` ?

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [November 17, 2017, 3:21pm UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/4 "2017-11-17T15:21:01Z")

</div>

Thanks for your replies!

---

<div class="post-metadata">

**Author:** ![galenlynch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/galenlynch/32/17947_2.png) [@galenlynch](https://discourse.julialang.org/u/galenlynch)\
**Post date:** [July 26, 2018, 5:11pm UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/5 "2018-07-26T17:11:05Z")

</div>

Is there still no better way to parse a `DataType` than to use an `eval` statement? `include_string` is essentially an eval, isn’t it?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [July 26, 2018, 5:41pm UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/6 "2018-07-26T17:41:18Z")

</div>

Why would you provide data types as strings outside of a code interpreter?

---

<div class="post-metadata">

**Author:** ![galenlynch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/galenlynch/32/17947_2.png) [@galenlynch](https://discourse.julialang.org/u/galenlynch)\
**Post date:** [July 26, 2018, 5:59pm UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/7 "2018-07-26T17:59:52Z")

</div>

For example, as part of a header for a data file that says what the element type of the file is.

My specific use case is this: I have a bunch of large arrays that I would like to work with, but they can have different element types (Float32, Int16) and different sizes. I’m generating the arrays as binary files on a one computer, and memory mapping them on a second computer. Right now the files are just binary values, and the metadata (identifier, element type, size) are in the file name. I would like to read the file name, parse it with a regular expression, and use the capture groups to memory map the file.

I’ve wanted to convert strings into datatypes for similar reasons (producing data artefacts in julia that I want to store and use later) a number of times now. Perhaps there’s some easier way that I’m missing?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [July 26, 2018, 6:09pm UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/8 "2018-07-26T18:09:46Z")

</div>

> [@galenlynch](#):
>
> For example, as part of a header for a data file that says what the element type of the file is.

You definitely don’t want to use `eval` for this, because that could inject arbitrary code into your program via the data file.

Most likely you only support a relatively small set of element types, in which case you can use a dictionary mapping supported type strings to the corresponding types. `Dict("Float32"=>Float32,"Int16"=>Int16,...)`

---

<div class="post-metadata">

**Author:** ![galenlynch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/galenlynch/32/17947_2.png) [@galenlynch](https://discourse.julialang.org/u/galenlynch)\
**Post date:** [July 26, 2018, 6:20pm UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/9 "2018-07-26T18:20:01Z")

</div>

Yeah, I might end up doing something like the dictionary.

I don’t really understand why `DataType` isn’t already a parse target, since they’re such an important part of Julia. Simple data types (`Float32` etc…) usually parse to `Symbol`s, so I could alternatively just `eval` only if the string parses into a symbol. Sadly, things like `"Complex{T}"` don’t parse into `Symbols`.

---

<div class="post-metadata">

**Author:** ![jandehaan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jandehaan/32/6805_2.png) [@jandehaan](https://discourse.julialang.org/u/jandehaan)\
**Post date:** [July 26, 2018, 8:20pm UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/10 "2018-07-26T20:20:30Z")

</div>

How about

```julia
julia> macro datatype(str); :($(Symbol(str))); end
@datatype (macro with 1 method)

julia> t = @datatype("Float64")
Float64

julia> typeof(t)
DataType

```

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [July 26, 2018, 8:35pm UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/11 "2018-07-26T20:35:37Z")

</div>

```julia
julia> x = "Float64"
"Float64"

julia> @datatype x
"Float64"

julia> @macroexpand @datatype(x)
:(Main.x)

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [July 26, 2018, 8:57pm UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/12 "2018-07-26T20:57:09Z")

</div>

> [@jandehaan](#):
>
> How about

There’s no way around `eval` if you want to handle arbitrary types. Many people seems to think `macro` gives you magic power to accomplish things (edit: at runtime) that are not possible without them. They don’t, they are just a fancy way to save repeated typing.

Going from string to value is not parsing, its evaluating (ok, parsing (to AST) plus evaluating (to value)). The only way to evaluate something from a runtime expression is `eval`, everything else is just `eval` wrapped in one way or another, including `include`, `include_string` etc.

The real question is what property you want. Do you want to handle all possible types? If yes, then you have to use `eval`. Do you want to avoid code injection attach? Then you can’t use `eval`, you can use a table (`Dict`) or use an arbitrary set of operations you support and are safe for your application.

> [@galenlynch](#):
>
> since they’re such an important part of Julia.

They are not. Not for the parser and not any more than basically anything else. Types are values, they are special in dispatch but that has nothing to do with syntax/parsing. Designing a system that give them more coupling is possible (C++…) but that’s usually not a desired property and makes parsing so much harder.

> [@galenlynch](#):
>
> I don’t really understand why `DataType` isn’t already a parse target

As an example, what do you think the last `B` in the following code should parse to?

```julia
a = 2 + 2
struct B
    x::NTuple{a,Int}
end
B

```

It’s obviously a type (which is clear in this case but does not have to in general in julia) but how do you want the parser to figure out all it’s property before the code is evaluated?

---

<div class="post-metadata">

**Author:** ![jandehaan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jandehaan/32/6805_2.png) [@jandehaan](https://discourse.julialang.org/u/jandehaan)\
**Post date:** [July 26, 2018, 9:36pm UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/13 "2018-07-26T21:36:26Z")

</div>

> [@yuyichao](#):
>
> magic power to accomplish things (edit: at runtime)

I must have stumbled on a corner case:

```julia
julia> macro datatype(str); :($(Symbol(str))); end
@datatype (macro with 1 method)

julia> @datatype "Float64"
Float64

julia> @datatype "String"
String

julia> @datatype "Int"
Int64

```

Looks like “runtime magic” to me.  
However

```julia
@macroexpand @datatype "Float64"
:(Main.Float64)

@macroexpand @datatype "Int"
:(Main.Int)

```

makes it look as if the macro itself is being “re-compiled” at runtime. What is going on here?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [July 26, 2018, 9:38pm UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/14 "2018-07-26T21:38:05Z")

</div>

> [@jandehaan](#):
>
> Looks like “runtime magic” to me.

No. All of that is accomplished at compile time.

---

<div class="post-metadata">

**Author:** ![ggggggggg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ggggggggg/32/265_2.png) [@ggggggggg](https://discourse.julialang.org/u/ggggggggg)\
**Post date:** [July 26, 2018, 9:38pm UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/15 "2018-07-26T21:38:51Z")

</div>

The trick is you are passing a string to the macro, but when you pass a variable to the macro it doesn’t get the value of the variable, it just gets the symbol of the variable name.

```julia
julia> macro mydump(x)
       dump(x)
       end
@mydump (macro with 1 method)

julia> x="Int"
"Int"

julia> @mydump x
Symbol x

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [July 26, 2018, 9:39pm UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/16 "2018-07-26T21:39:35Z")

</div>

> [@jandehaan](#):
>
> makes it look as if the macro itself is being “re-compiled” at runtime

As you can see, `@datatype "Float64"` is basically the same as writing `Main.Float64`. It doesn’t allow you to parse a runtime string and turn that into a value without `eval`. It just allow you to spell something differently.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [July 26, 2018, 9:41pm UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/17 "2018-07-26T21:41:50Z")

</div>

> [@jandehaan](#):
>
> :($(Symbol(str)))

Also, FWIW, `:($(...))` is always the same as `...` itself…

---

<div class="post-metadata">

**Author:** ![galenlynch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/galenlynch/32/17947_2.png) [@galenlynch](https://discourse.julialang.org/u/galenlynch)\
**Post date:** [July 27, 2018, 3:51pm UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/18 "2018-07-27T15:51:44Z")

</div>

Thanks for the responses guys!

> [@yuyichao](#):
>
> The real question is what property you want.

Ideally I would like something that takes a string, a module (defaulting to Main), and returns the type if the string matches an existing type in the specified module, and errors if the string does not match an existing type.

> [@yuyichao](#):
>
> Types are values

Yes, but with there is no easy and safe way to parse strings into those values, unlike `Int` or other values.

> [@yuyichao](#):
>
> As an example, what do you think the last `B` in the following code should parse to?

Yeah I understand why it’s impossible to parse an arbitrary string into a arbitrary datatype, but I do think parsing into existing DataTypes in some specified module seems possible, without having to roll your own lookup table.

Something like this I guess, except it’d be nice if it handled parametric types:

```julia
macro datatype(name, namespace = Core)
    name_sym = Symbol(name)
    quote
        if Symbol($name) in names($namespace) && isa($namespace.$name_sym, DataType)
            $namespace.$name_sym
        else
            error("Not a datatype")
        end
    end
end

foo = @datatype "Float32"
foo == Float32 # true

foo = @datatype "println(\"Mwahahaha\")" # errors 

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [July 27, 2018, 4:23pm UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/19 "2018-07-27T16:23:45Z")

</div>

> [@galenlynch](#):
>
> macro datatype(name, namespace = Core)

First, again, macro buy you absolutely nothing here. You’ll also have a hard type passing in the `namespace` parameter to the macro.

> [@galenlynch](#):
>
> Ideally I would like something that takes a string, a module (defaulting to Main), and returns the type if the string matches an existing type in the specified module, and errors if the string does not match an existing type.

See the examples I gave, these does not answer the question sepecific enough. In particular what does “existing type in the specific module” mean. Esepcially for paramatric type, what value do you want to allow to be the type parameters.

> [@galenlynch](#):
>
> Yes, but with there is no easy and safe way to parse strings into those values, unlike `Int` or other values.

Types are nothing special here. There are infinite number of types that cannot be parsed from. The exception here is actually types that are has literal representations. There are only a few types that has this property (`Int`, `UInt*`, `Float*`, `String`, is there any others that I missed?) It’s possible for these types because they have a context independent representation. There are indeed many other types that has context independent representation without a literal syntax but the context independent representation is a hard requirement for having a literal syntax. (By literal syntax I mean it can be parsed to a value in the AST. I’m not counting `[]` as literal here). `DataType`s does not have this property. You cannot express a type without referencing where it’s coming from and what you think as a type is barely a name that the type is bound to.

> [@galenlynch](#):
>
> Yeah I understand why it’s impossible to parse an arbitrary string into a arbitrary datatype, but I do think parsing into existing DataTypes in some specified module seems possible, without having to roll your own lookup table.

No. For one, there’s absolutely nothing special about type here. Also, although scope resolution can be done at parse time, value resolution can’t. It’s not useful as an optimization and it’s not useful as an API for exactly the reason I mentioned above, the expectation for the feature is way too vague.

As another example of why your request is way too vague, consider which one of the following types do you want to support?

```julia
Val{()}
Val{(1,)}
Val{(1,:a)}
Val{(1,:a,pi)} # which prints as `Val{(1, :a, π = 3.1415926535897...)}` btw

```

These are still fairly simple types, and with values in the type parameters that are even harder to construct, you quickly need a full interpreter to handle all of those.

Put it another way, obviously it’s possible to create a version that handles only the simple cases that’s useful for you **as long as you precisely define what simple means**. You can create a version that has an arbitrarily defined limitation though the more feature complete you want it to be the harder it is to write it. Since the definition of simple/the limitation you can work with is in general very arbitrary, it’s not useful to have any of them as a base function. Two exceptions are empty set, i.e. only parsing, and full set, i.e. the interpreter, which are special, well defined, useful and are indeed implemented in base.

---

<div class="post-metadata">

**Author:** ![galenlynch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/galenlynch/32/17947_2.png) [@galenlynch](https://discourse.julialang.org/u/galenlynch)\
**Post date:** [July 27, 2018, 5:17pm UTC](https://discourse.julialang.org/t/parse-string-to-datatype/7118/20 "2018-07-27T17:17:06Z")

</div>

I see, thanks for taking the time to explain it.

[Next page](https://discourse.julialang.org/t/parse-string-to-datatype/7118.md?page=2)
