For T in (Float64,) vs let T=Float64

I wonder why the first one in the following fails

for T in (Float64,)
    sizefloat(x::T) = sizeof(T)
    println(methods(sizefloat))
    println(sizefloat(3.4))
end
ERROR: UndefVarError: T not defined
Stacktrace:
 [1] top-level scope

while the second one works:

let T=Float64
    sizefloat(x::T) = sizeof(T)
    println(methods(sizefloat))
    println(sizefloat(3.4))
end
# 1 method:
[1] (::var"#sizefloat#31")(x::Float64) in Main at E:\work\julia\mytest.jl:9
8

Hmm, that does seem inconsistent. I recognize the error. That’s what happens when you leave out the where T after sizefloat(x::T), but in this case T is bound to Float64 and so it seems like it should work the same as it does in the let block. Both the for loop and the let block introduce a local scope with a local variable T bound to Float64, so I’m not sure why they behave differently… :thinking:

1 Like

This seems similar to the question that came up in this thread: Can a function return another function?

Apparently, it’s considered a bug or unwanted limitation. But I don’t really see why this should work. Dynamically creating named functions at runtime seems unnatural to me.

Isn’t this metaprogramming, that should require a macro? Or, if you don’t really need a globally defined name, make an anonymous function.

1 Like

It’s purely out of curiosity. There is a code snippet in Revise documentation:

for T in (Float16, Float32, Float64)
    @eval sizefloat(x::$T) = sizeof($T)
end

Then, I had this thought for a moment; the following should do the same:

for T in (Float16, Float32, Float64)
    global sizefloat(x::T) = sizeof(T)
end

It indeed works. Then I tried removing global keyword(I sometimes play with the language like that and it helps me understand the subject better.) When the code failed without global then I tried replacing for with `let’. :slight_smile:

Thank you for the related topic!

1 Like