# Strange Lispy warning on master

**URL:** <https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999>\
**Category:** General Usage\
**Created:** [December 26, 2017, 4:03pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999 "2017-12-26T16:03:34Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [December 26, 2017, 4:03pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/1 "2017-12-26T16:03:34Z")

</div>

I’m not sure what I’m supposed to do with this:

> WARNING: deprecated syntax “parametric method syntax (::Core.Type{Str{T}}){(var-bounds T #f #f)}(S, v::Vector{UInt8}) around /Users/scott/.julia/v0.7/Strs/src/types.jl:57”.  
> Use “(::Core.Type{Str{T}})(S, v::Vector{UInt8}) where (var-bounds T #f #f)” instead.  
> ERROR: LoadError: LoadError: MethodError: Cannot `convert` an object of type Array{UInt8,1} to an object of type Strs.Str{:Binary}

The code was this:

```julia
struct Str{T} <: AbstractString
    data::Vector{UInt8}
    Str(S, v::Vector{UInt8}) = (new{S}(v) where {S})
end

```

Things were working fine, before I added the inner constructor, but now I get that strange error.  
What I’m trying accomplish is simply that I need a constructor, that can safely take a `Vector{UInt8}` that has already be set up (allocated always via `Base.StringVector(len)`, and with the correct type T that indicates what the character set and encoding are), but make `Str(vec)` where vec is a `Vector{UInt8}`, call an outer constructor, that looks at `vec`, assuming it’s UTF-8, and checks validity and returns with an instance of one of the `Str` subtypes.

Anybody know what’s going on? Thanks in advance!

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [December 26, 2017, 4:18pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/2 "2017-12-26T16:18:36Z")

</div>

> [@ScottPJones](#):
>
> struct Str{T} \<: AbstractString  
> data::Vector{UInt8}  
> Str(S, v::Vector{UInt8}) = (new{S}(v) where {S})  
> end

I think you need

```julia
struct Str{T} <: AbstractString
    data::Vector{UInt8}
               
    Str{T}(S, v::Vector{UInt8}) where {T} = (new{S}(v) where {S})
end

```

i.e. to make the inner constructor parametric on `T`.

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [December 26, 2017, 4:19pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/3 "2017-12-26T16:19:53Z")

</div>

Hmm, shouldn’t `S` be related to `T`, though?

---

<div class="post-metadata">

**Author:** ![favba](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/favba/32/2735_2.png) [@favba](https://discourse.julialang.org/u/favba)\
**Post date:** [December 26, 2017, 4:41pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/4 "2017-12-26T16:41:16Z")

</div>

What is that `where {S}` on the right side for? Is it really necessary?  
I’m assuming `S` must be a symbol right?  
Doesn’t the inner constructor below work?

```julia
Str(S::Symbol,v) = new{S}(v)

```

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [December 26, 2017, 4:44pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/5 "2017-12-26T16:44:50Z")

</div>

I’m still trying to work out all the details of the new syntax, we only recently (this month) moved over to v0.6.1 for our code (still using the old v0.5 syntax that has been deprecated on master)  
That’s why I’m getting twisted about so much! (I do appreciate the much greater power of the new syntax,  
and don’t mind having to rewrite things to adapt to it, it just will take a little time to learn all the nitty gritty details!)

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [December 26, 2017, 4:50pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/6 "2017-12-26T16:50:09Z")

</div>

Currently a symbol, but I’m in the process of changing it, using @nalimilan’s nice approach (in the pull request [https://github.com/nalimilan/StringEncodings.jl/pull/9](https://github.com/nalimilan/StringEncodings.jl/pull/9)) to use singleton types that take a Symbol.  
(Splitting out CharSet, Encoding, and CharSetEncoding - those are not the same, but people frequently conflate them)

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [December 26, 2017, 4:53pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/7 "2017-12-26T16:53:18Z")

</div>

> [@ScottPJones](#):
>
> Use “(::Core.Type{Str{T}})(S, v::Vector{UInt8}) where (var-bounds T #f #f)” instead

Anyway, part of my real issue, was that I feel this deprecation warning is a bug - I don’t think what it tells you to use instead `(var-bounds T #f #f)` is valid Julia syntax 🙂

edit: (It’s probably something that @jeff.bezanson can fix in a minute!)

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [December 26, 2017, 5:03pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/8 "2017-12-26T17:03:07Z")

</div>

Is this what you want?

```julia
julia> struct Str{T} <: AbstractString
           data::Vector{UInt8}
           Str{S}(v::Vector{UInt8}) where {S} = new(v)
       end

julia> Str(S, v::Vector{UInt8}) = Str{S}(v)
Str

julia> a = Str(:encoding, UInt8[1,2,3]);

julia> a.data
3-element Array{UInt8,1}:
 0x01
 0x02
 0x03

julia> typeof(a)
Str{:encoding}

```

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [December 26, 2017, 5:22pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/9 "2017-12-26T17:22:47Z")

</div>

Thank you very much!  
With that, and the addition of:  
`Str(v::Vector{UInt8}) = Str(:Binary, v)`  
it does exactly what I want!  
😄

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [December 26, 2017, 5:30pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/10 "2017-12-26T17:30:22Z")

</div>

> [@mohamed82008](#):
>
> Str(S, v::Vector{UInt8}) = Str{S}(v)

Btw, this function is not type stable, because the function may return a whole family of output types for the same input types.

```julia
julia> @code_warntype Str(:encoding, UInt8[1, 2, 3])
Variables:
  #self# <optimized out>
  S::Symbol
  v::Array{UInt8,1}

Body:
  begin
      return ((Core.apply_type)(Main.Str, S::Symbol)::Type{Str{_}} where _)(v::Array{UInt8,1})::Str{_} where _
  end::Str{_} where _

```

If `S` is known at compile time, you could do this instead which is type stable.

```julia
Str(::Val{S}, v::Vector{UInt8}) where {S} = Str{S}(v)
# a = Str(Val{:encoding}(), UInt[1,2,3])

```

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [December 26, 2017, 5:58pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/11 "2017-12-26T17:58:59Z")

</div>

Rather than using the `Val` trick, I would suggest just migrating your usage from`Str(S, v)` to `Str{S}(v)`, by analogy to the way the Array constructors have changed from `Array(T, dims...)` to `Array{T}(dims...)`. You can even deprecate the two-argument version to make it easy to find usages that need to be updated:

```julia
@deprecate Str(S, v) Str{S}(v)

```

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [December 26, 2017, 6:41pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/12 "2017-12-26T18:41:13Z")

</div>

No need to deprecate, this isn’t even released yet, I just started writing it Dec. 15th.

I need an inner constructor, so it will create it with the type, which determines the behavior, but is not in any fields, and also to prevent a problem that I’ve run into, that without an inner constructor, Julia sets up a default inner constructor, with behavior I want to make not possible (i.e. `Str(vec)` where `vec` is a `Vector{UInt8}`, or `Str(str)`, where `str` is of type `String`, which for some reason is causing a deprecation warning, instead of calling the `Str(str::String)` outer constructor that I had defined.  
I’ll have to see if I come up with a MWE of the problem, to see if it’s a bug, or just something wrong in my code.

---

<div class="post-metadata">

**Author:** ![jeff.bezanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff.bezanson/32/48_2.png) [@jeff.bezanson](https://discourse.julialang.org/u/jeff.bezanson)\
**Post date:** [December 26, 2017, 7:22pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/13 "2017-12-26T19:22:43Z")

</div>

This might be due in part to the deprecation of special “inner constructor” behavior in 0.6: before 0.6, writing `Str(x) = ...` inside a type definition block actually defined a constructor for calls that look like `Str{T}(x)` (which is why it was confusing and needed to be deprecated). While this deprecation is in place, a constructor for `Str(x)` calls can be defined inside the type definition block using `(::Type{Str})(x) = ...`. When the deprecation is removed (which could probably be right now, actually) it will be possible to write it as just `Str(x) = ...` like you’d expect.

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [December 26, 2017, 7:40pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/14 "2017-12-26T19:40:46Z")

</div>

Thanks! It was driving me a bit batty this morning, I want to get the last few problems resolved so I can concentrate on improving the benchmarking, and push a WIP version of my `Strs.jl` package.

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [December 26, 2017, 8:23pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/15 "2017-12-26T20:23:22Z")

</div>

I’m still not able to get this working:

```julia
julia> struct Str{T} <: AbstractString
           data::Vector{UInt8}
           (::Type{Str})(::Type{S}, v::Vector{UInt8}) where {S} = new{S}(v)
       end

julia> (::Type{Str{T} where T})(v::Vector{UInt8}) = Str(T, v)

julia> Str{:Binary}(b"foo")
ERROR: MethodError: Cannot `convert` an object of type Array{UInt8,1} to an object of type Str{:Binary}
Stacktrace:
 [1] Str{:Binary}(::Array{UInt8,1}) at ./deprecated.jl:1590
 [2] top-level scope

```

Any ideas?

edit: What I’m trying to accomplish is make it so that the `const` type aliases such as `BinaryStr`, `ASCIIStr`, `UTF8Str`, which are simply (currently) `Str{:Binary}`, `Str{:ASCII}`, `Str{:UTF8}` (I’m in the middle of changing them so that they might be more complicated, such as `UTF16BEStr` being `Str{cse"UTF16BE", Nothing, Nothing}` (where the unused type parameters are for built-in substrings, and cached raw data, UTF-8 or UTF-16 encodings of the string, much as Python does).

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [December 26, 2017, 8:57pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/16 "2017-12-26T20:57:25Z")

</div>

```julia
julia> struct Str{T} <: AbstractString
         data::Vector{UInt8}
         Str{S}(v::Vector{UInt8}) where {S} = new{S}(v)
       end

julia> Str{:binary}(b"foo");

```

if you want your non-type-stable outer constructor, it’s just:

```julia
julia> Str(S, v::Vector{UInt8}) = Str{S}(v)
Str

julia> typeof(Str(:binary, b"foo"))
Str{:binary}

```

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [December 26, 2017, 9:00pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/17 "2017-12-26T21:00:59Z")

</div>

I’m still running into this problem:

```julia
julia> struct Str{T} <: AbstractString
           data::Vector{UInt8}
           (::Type{Str})(::Type{S}, v::Vector{UInt8}) where {S} = new{S}(v)
       end

julia> Str(S, v::Vector{UInt8}) = Str{S}(v)
Str

julia> const BinaryStr = Str{:Binary}
Str{:Binary}

julia> BinaryStr(b"123")
ERROR: MethodError: Cannot `convert` an object of type Array{UInt8,1} to an object of type Str{:Binary}
Stacktrace:
 [1] Str{:Binary}(::Array{UInt8,1}) at ./deprecated.jl:1590
 [2] top-level scope

```

---

<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:** [December 26, 2017, 9:02pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/18 "2017-12-26T21:02:46Z")

</div>

FWIW, with IPO, the “non-type stable” version infers fine.

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [December 26, 2017, 9:03pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/19 "2017-12-26T21:03:41Z")

</div>

Yes, I’ve been very happy with some of the new enhancements such as that!

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [December 26, 2017, 9:09pm UTC](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999/20 "2017-12-26T21:09:53Z")

</div>

Your inner constructor is still incorrect (you’re only defining `Str(S, v)` where `S` is a `Type`, but (a) `S` is a Symbol, not a Type and (b) you need the `Str{S}(v)` constructor, which can _only_ be defined as an inner constructor). This works with the version I posted above:

```julia
julia> struct Str{T} <: AbstractString
          data::Vector{UInt8}
          Str{S}(v::Vector{UInt8}) where {S} = new{S}(v)
        end

julia> const BinaryStr = Str{:Binary}
Str{:Binary}

julia> BinaryStr(b"123");

```

[Next page](https://discourse.julialang.org/t/strange-lispy-warning-on-master/7999.md?page=2)
