Return outer function in do block

Is it possible to return an outer function from a do block, e.g. the following code

f(x) = map(x) do y; if y==1; return -1; end; x *=2; end
f([1,2])

evaluates to

2-element Array{Int64,1}:
 -1
  4

I guess this is because the do block is creating an anonymous function, in which the return then gets evaluated. Is it possible to return from the enclosing function f and return just
-1
? Maybe that is not useful/possible for map but I would find this very handy for loading files with open or h5open.

Best,
Jamble

No. It doesn’t make much sense. It makes even less sense for open. What do you want open to do in that case. Should it leave the file open?

no, it should close the file of course. I mean, if an exception arises, the file is closed first and then the exception is propagated. Why not have something similar with return?

Why am I asking: I find myself doing the following a lot:
Having a function which is checking files and e.g. calculating and adding missing data to the files. E.g.

function check(filename)
# opens the file for reading and doing checks
ok = false
open(filename, "r") do file
  # do some checks here
  if checks_passed
    ok = true
  end
end

if !ok
  open(filename, "cw")
  # fix stuff
  end
end

return results
end

I do not want to open the file in write mode, because this updates the timestamp of the last edit. This is something I need to avoid for synchronization/fileversioning. Is there really a need for a ok boolean?

Errr but that is exactly what open does??? If the do block returns the filel is closed and open returns? Or you mean to return the value? Sure. That’s fine, but that’s strictly a property of open. It makes no sense for this to be a property of do block.

I can see how that would be helpful for your usage model. Not sure it how useful it would be for everyone. It would probably complicate if you have do inside a do, how could you break out of the inside do, but not the outside do? You’d need some way of specifying how many “levels” you want to return from.

Something that might work for you is to create your own function, something like:

function check(filename, test, fix)
   ok = false
   open(filename, "r") do file
       ok = test(file)
   end
  
   if !ok 
       open(filename, "cw") do file
          fix(file)
       end
   end
end

Then you just need to create the test() an fix() functions for your various files, all call check on them.

1 Like
function check(filename)
# opens the file for reading and doing checks
ok = open(filename, "r") do file
  # do some checks here
  return checks_passed
end
if !ok
  open(filename, "cw") do
  # fix stuff
  end
end

return results
end

You can simplify it a bit like this, no?

2 Likes

I occasionally miss common-lisp:return-from in Julia, which has no such construct AFAIK.

A version of map, mapreduce & friends (foldl etc) that allow early termination (eg based on a sentinel value or a flag that is returned) could help in cases like this, and there is no reason a package could not implement these efficiently (maybe there is one already, I just missed it). Cf

2 Likes

I tried this but open is returning nothing. I guess I will just stick with my solution right now.

I was thinking about doing this as well. I am not sure right now, if this will make the code more unreadable/complicated. I want to avoid writing functions which go into some “meta-module” I have to load in all my projects.

What was your full code? open should return the value from the callback. If that’s indeed the property you’d like to have then yes, for open it’s totally valid. If you are not seeing the return value of the callback returned by open it’s a bug in open and you should report that.

(OTOH, a quick glance didn’t seem to have this behavior documented so it could be considered a partial new feature if some method indeed don’t have this already)

1 Like

No, no bug. My mistake. The following code works:

function check(filename)
# opens the file for reading and doing checks
ok = open(filename, "r") do file
  # do some checks here
  if checks_passed 
    return true
  else
    return false
  end
end

if !ok
  open(filename, "cw")
  # fix stuff
  end
end

return results
end