Problem with let declaration v0.6

question
bug

#1

I am pretty sure that the following code was working in julia v0.5. It is a simple recursive walk in a tree given by a root and a function children (the array of children of its argument).

walk(root, children) =
   let result = Set([root]), 
       grep(r) = if (r != []) 
                     for t in children(r) ; push!(result, t) ; grep(t); end
                 end
       grep(root) 
       result
   end

move(x) = x > 10 ? [] : [x+1]

This returns an error, as if the recursive definition of the local function grep is not valid.

julia> walk(0, move)
ERROR: UndefVarError: grep not defined
Stacktrace:
 [1] walk(::Array{Int64,1}, ::#move) at ./none:1

Can someone confirm the error? Is there some change concerning let declarations in v0.6? If I remove the let form, everything works as expected.

function walk2(root, children)
    result = Set([root])
    grep(r) = if (r != []) 
                 for t in children(r) ; push!(result, t) ; grep(t) ; end
              end
    grep(root)
    result
end

julia> walk2(0, move)
Set([2, 11, 0, 7, 9, 10, 8, 6, 4, 3, 5, 1])

#2

I can’t help you with the original issue (I am not totally sure let accepts this function syntax), but if you write it more like Julia and less like Lisp, it works fine:

function walk(root, children)
    result = Set([root])
    function grep(r)
        if r != []
            for t in children(r)
                push!(result, t)
                grep(t)
            end
        end
    end
    grep(root) 
    result
end

move(x) = x > 10 ? [] : [x+1]

walk(0, move)

#3

Like in lisp, the right-hand side of a let binding refers to the outer scope. But definitions within a block act like letrec, so if you delete the comma (moving the definition of grep inside the let block) it works. But there also seems to be a bug here if you try to refer to an outer function with the same name inside a let binding.