# Help with where syntax in Julia v0.6

**URL:** <https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458>\
**Category:** General Usage\
**Tags:** question\
**Created:** [June 26, 2017, 5:14am UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458 "2017-06-26T05:14:59Z")\
**Posts on this page:** 17\
**Page:** 2

<div class="post-metadata">

**Author:** ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)\
**Post date:** [June 29, 2017, 4:07am UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458/21 "2017-06-29T04:07:37Z")

</div>

> [@ScottPJones](#):
>
> With the change that we’ve been talking about, those calculations would occur once, when the type was instantiated

That’s not how the change works. Type instantiation cannot _run_ code since types are created during _compilation_, not _run_time. Any _run_time computations in the definition must happen each time that type is created when the program is _run_.

> [@ScottPJones](#):
>
> and to have the constructor perform the calculations (and that would be happening 100 million times, instead of just once).  
> Your ComputedFieldTypes has the same performance issue, AFAICT.

That’s not how compilation works. Our compiler may be simplistic right now, but it’s not that badly broken.

---

<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:** [June 29, 2017, 2:16pm UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458/22 "2017-06-29T14:16:07Z")

</div>

@jameson Have you bothered to benchmark this, or look at the generated code?  
I have, and it bears out what I’ve been trying to get across to you.  
Before making inflammatory statements (i.e. “sheer and utter nonsense”), you should check out the facts first.

Also, you seem to have a misunderstanding as to what is going on when types are created.

> [@jameson](#):
>
> Type instantiation cannot run code since types are created during compilation, not runtime

Code definitively is run when a type is created, and you can use functions that return the types used for the fields.  
The issue is that those functions are run when the type is created, which doesn’t work if the calculations contain any type parameters, since those are not yet bound.  
That is where Jeff agreed (when asked both at JuliaCon 2016 and JuliaCon 2017, @andyferris is a witness!) that that could be fixed (as I had already pointed out) by created a thunk if there were any type parameters used in the expression that would get evaluated when a concrete type was instantiated from that parameterized type, i.e. when the parameters were all bound)

The workaround of doing the calculations when an object is created, instead of fixing the bug of prematurely evaluating the type variables, is simply too slow for many of the cases where this would be useful (such as for new faster numeric types, where you want to create a struct (immutable) with a number of limbs that depends on the number of bits of precision desired and the machine integer size).

> [@jameson](#):
>
> That’s not how compilation works. Our compiler may be simplistic right now, but it’s not that badly broken.

I’m talking about when parameterized types are created, when concrete types are actually instantiated from those parameterized types, when values are constructed, and when potentially costly calculations are done, i.e. either at the time that the concretes types are instantiated, or when every value is constructed (as happens now with the workaround).

As far as I understand (from inspecting the code, and inserting debugging statements into the code called when types are created), what currently happens is:

1. when a parameterized type is created, any expressions to calculate the types of the fields are executed. If a function is called with a type parameter, it is passed something of type TypeVar, which indicates that it is bound or unbound.  
This is used for example with the `Maybe(T)` function, which returns a `Union{T, Void}`, which I’ve seen in various places in Julia code.  
This type is cached by Julia.
2. when a concrete type is created from a parameterized type, any fields whose type was a type parameter, or a type parameterized by the type parameters, have those type vars replaced by their bound values.  
This concrete type is then also cached by Julia.

What needs to happen is:

1. when a parameterized type is created, thunks are created for any expression that uses a type parameter in the body of the type definition. Otherwise, expressions without type variables can be immediately evaluated, as occurs now.
2. when a concrete type is created from a parameterized type, any thunks are evaluated with the type vars replaced by their bound values.

This would eliminate the need for the “hidden” parameters needed by the current workaround, which can make the types harder to understand, and expose internal implementation details.

---

<div class="post-metadata">

**Author:** ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)\
**Post date:** [June 29, 2017, 4:58pm UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458/23 "2017-06-29T16:58:31Z")

</div>

> [@ScottPJones](#):
>
> Have you bothered to benchmark this, or look at the generated code?

Yes, I have. Did you remember to mark the functions you called as `@pure`?

> [@ScottPJones](#):
>
> This would eliminate the need for the “hidden” parameters

It doesn’t eliminate them – the values still have to be stored somewhere – it just hides them better (so that reflection can only retrieve them from fieldtypes, instead of via reflection on the parameters).

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [June 29, 2017, 5:43pm UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458/24 "2017-06-29T17:43:31Z")

</div>

> [@jameson](#):
>
> This is shear and utter nonsense.

I want to emphasize here that this is the type of comment that kills a community. At JuliaCon we had a talk discussing good manners in open source, and I invite everyone to look it up when it is out.

Dozens of smart people cannot be wasting their time shitting each other, instead we should all be polite and have empathy when we discuss on this forum.

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [July 2, 2017, 2:05am UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458/25 "2017-07-02T02:05:48Z")

</div>

> [@ScottPJones](#):
>
> abstract type AP{N,T} end  
> abstract type AD{P} end  
> abstract type AG{P} \<: AD{P} end
> 
> (ntyp(::Type{A}) where A\<:AP{N,T} where {N,T}) = T  
> (nval(::Type{A}) where A\<:AP{N,T} where {N,T}) = N
> 
> struct RegularGrid{P\<:AP} \<: AG{P}  
> dims::Dims{ntyp(P)}  
> units::NTuple{nval(P),ntyp(P)}  
> end

@ScottPJones I just tried to copy/paste your solution, but it is giving me an error in Julia v0.6:

> ERROR: MethodError: no method matching ntyp(::TypeVar)  
> Closest candidates are:  
> ntyp(::Type{A\<:AP{N,T}}) where {N, T, A\<:AP{N,T}} at REPL[4]: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:** [July 2, 2017, 4:56am UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458/26 "2017-07-02T04:56:30Z")

</div>

As I said, that’s how you could do it, _IF_ you could perform calculations directly on parameters.  
There is a work-around for now (which you can do directly, or use @jameson’s package that automates it),  
that adds extra parameters for the values that need to be calculated, and then uses a constructor that performs the calculations.

The difference is that instead of performing the calculations once, when the concrete type is instantiated with all the parameters bound, they happen every time an instance of that type is created, which is one of the reasons I strongly believe this needs to be fixed.

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [July 2, 2017, 5:07am UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458/27 "2017-07-02T05:07:41Z")

</div>

Thank you @ScottPJones, I thought your code snippet was working already in Julia v0.6, I had sketched similar answer in the past on this forum: [Recovering parameter type from parameter list - #5 by juliohm](https://discourse.julialang.org/t/recovering-parameter-type-from-parameter-list/1343/5)

I really miss this feature in Julia.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [July 2, 2017, 5:29am UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458/28 "2017-07-02T05:29:27Z")

</div>

> [@ScottPJones](#):
>
> they happen every time an instance of that type is created

This is overly pessimistic. The sorts of computations required here are (by definition) entirely determined by the given types. That means that they are typically compiled to directly down to constants, no runtime computation needed at all.

---

<div class="post-metadata">

**Author:** ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)\
**Post date:** [July 3, 2017, 5:02am UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458/29 "2017-07-03T05:02:09Z")

</div>

Correct. Also, memoizing something in a type has never guaranteed that we won’t recompute it – we only usually ensure that is true for the typeof of an instance, and then only so far as we can make the changes hard to observe. This is somewhat analogous to generated functions (we don’t guaranteed they won’t be recomputed each time it is run, we simply guarantee that it won’t recompile while its being run). Although comparing type fields to functions also fails on several key points, so I wouldn’t bother with trying to push that comparison very far.

---

<div class="post-metadata">

**Author:** ![ValdarT](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/valdart/32/24146_2.png) [@ValdarT](https://discourse.julialang.org/u/ValdarT)\
**Post date:** [August 30, 2017, 10:24am UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458/30 "2017-08-30T10:24:12Z")

</div>

I’m probably missing something very obvious but why does this:

```julia
struct Foo{T<:Number}
  name::String
  state::T
  
  function Foo{T}(name::String, state::T) where {T<:Number}
      new(name, state)
  end
end

Foo("a", 1.)

```

give a `MethodError: no method matching Bar(::String, ::Float64)` ?

I’m expecting the above to be identical to

```julia
struct Bar{T <: Number}
  name::String
  state::T
end

Bar("a", 1.)

```

which works fine.

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [August 30, 2017, 12:10pm UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458/31 "2017-08-30T12:10:40Z")

</div>

Hi @ValdarT, I think it has to do with the fact that whenever you define an inner constructor for a type, Julia doesn’t define outer constructors automatically, you have to write them yourself. Someone else can correct me.

---

<div class="post-metadata">

**Author:** ![tkoolen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkoolen/32/1603_2.png) [@tkoolen](https://discourse.julialang.org/u/tkoolen)\
**Post date:** [August 30, 2017, 12:12pm UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458/32 "2017-08-30T12:12:49Z")

</div>

The inner constructor you’ve written requires you to specify `T` explicitly. An inner constructor for which `T` is inferred from the `state` argument should be written as

```julia
struct Foo{T<:Number}
  name::String
  state::T
  
  function Foo(name::String, state::T) where {T<:Number}
      new{T}(name, state)
  end
end

```

This is called an [outer-only constructor](https://docs.julialang.org/en/stable/manual/constructors/#Outer-only-constructors-1) (although I’m not a big fan of that name). **Edit** : or [maybe it isn’t called an outer-only constructor](https://github.com/JuliaLang/julia/issues/23022)? I’m confused.

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [August 30, 2017, 12:23pm UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458/33 "2017-08-30T12:23:16Z")

</div>

Very interesting @tkoolen, first time reading that section of the documentation, thanks for sharing.

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [August 30, 2017, 12:29pm UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458/34 "2017-08-30T12:29:14Z")

</div>

we have `methods` & `parametric methods`, and for consistency’s sake, maybe it’s a good idea to classify constructors by `constructors` & `parametric constructors` instead of `inner` & `outer`?

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [August 30, 2017, 6:40pm UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458/35 "2017-08-30T18:40:31Z")

</div>

> [@tkoolen](#):
>
> This is called an outer-only constructor (although I’m not a big fan of that name). Edit: or maybe it isn’t called an outer-only constructor? I’m confused.

The way I understand it, the “outer-only constructor” term refers to the inner constructors being blocked by the constructor provided, and hence only the outer constructors being available.

---

<div class="post-metadata">

**Author:** ![ValdarT](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/valdart/32/24146_2.png) [@ValdarT](https://discourse.julialang.org/u/ValdarT)\
**Post date:** [August 31, 2017, 6:41am UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458/36 "2017-08-31T06:41:52Z")

</div>

That solves it. Thank you! And it really is a bit confusing.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [August 31, 2017, 3:32pm UTC](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458/37 "2017-08-31T15:32:38Z")

</div>

I think that if you had never learned the old syntax the new one would be far less confusing – in the new way, `Foo{T}` only ever means `Foo` with `T` as a type parameter, and you define methods for that type the same way you call it. I explained more in this post:

> [@Anybody else find the new where syntax less than satisfactory?](https://discourse.julialang.org/t/anybody-else-find-the-new-where-syntax-less-than-satisfactory/4897/14):
>
> I explained the overall motivation for the where syntax in this StackOverflow answer: Partly quoting from there (with some clarifications and edits): Fundamentally, the problem with F{T}(args...) in Julia 0.5 and earlier is that the F{T} part is ambiguous – the parser knows what it means from the broader context, but its meaning depends heavily on that context. The fact that it can mean such different things is pretty confusing: In most contexts, F{T} means the parametric type F with type…

[Previous page](https://discourse.julialang.org/t/help-with-where-syntax-in-julia-v0-6/4458.md?page=1)
