@Tiberium Oh, that's wonderful! I like Was interface removed too (I'd really like to use it sometimes)?
2017-09-30 19:04:12

Thanks for the replies!

Would other people find it useful if I made and uploaded a "pythonwith" nim package for this?

2017-10-01 07:28:36
I don't think is worth the effort for roughly 5 or 6 template lines, but i think there is already a pythonesque library in nimble. 2017-10-01 10:15:14
It could be helpful to support something like the contextmanager decorator in Python, which lets the user specify "enter" and "exit" as the code before and after yield, e.g.

iterator myfunc(name: string):
  var myfile = open(name)
  yield myfile

var myit = myfunc(filename)

with context(myit) as f:
or maybe
withcontext myit as f:

I haven't tried this, but maybe something like:

macro withcontext(args, body: untyped): untyped =
  var varValue = args[1]
  var varName = args[^1]
  template takeImpl(thisit, name, body) =
      var private {.genSym.} = thisit
      var name = private()
        assert private.finished()
  # Generate AST
  getAst(takeImpl(varValue, varName, body))

2017-10-01 16:43:21
Why not do something like:
template withFile(f: string, mode: string, statements: untyped) =
    var fileMode: FileMode
    case mode
    of "r":     fileMode = FileMode.fmRead
    of "w":     fileMode = FileMode.fmWrite
    of "a+":    fileMode = FileMode.fmReadWrite
    of "r+":    fileMode = FileMode.fmReadWriteExisting
    var file {.inject.} = open(f, fileMode)
    defer: file.close()
usage example:
withFile("/path/to/file", "r"):
    while not endOfFile(file):
2017-10-01 17:03:24

@Arrrrrrrrr: I haven't seen a package like that, have googled this subject a few times before. Point me at it?

@Benjaminel: I'm trying to emulate the Python "with" style, which is more general-purpose than just files. I think that "using" in C# is similar, to take any given resource for a block, and then auto-close it for you at the end of that block.

@cdunn2001: I don't have any idea how to do that! For now I'm mainly interested in a python-like "with" statement; the other stuff is too advanced for me , eg to give an example of how you'd expand the one to the other. I think that's more on the level of how Dom managed to hack in async and await with just macros.


Thanks for the replies so far! So, another question

Can you update the macro so that it can work without an "as X" clause?

eg, something like this:

echo "I'm anywhere on the filesystem"

with myTempDirChange("/tmp/x"):
   echo "I am now under /tmp"

echo "I'm back to where I was before"

Which then would expand to something along these lines:

echo "I'm anywhere on the filesystem"

var private_x = myTempDirChange("/tmp/x")

   echo "I am now under /tmp"

echo "I'm back to where I was before"

Where myTempDirChange records the current dir, stores that in an object, then returns that object. And my_exit returns to that directory contained in that temporary object. I'm a bit hazy on exact details - whether there is still an intermediate my_enter function needed or not.

Well, basically how idiomatic Python would handle something like this behind the scenes:

print("I'm anywhere on the filesystem")

with my_temp_dir_change("/tmp"):
    print("I'm now under /tmp")

print("I'm back to the directory I was at before")

This is more of a toy example; other things might be locks, or other cases where you might normally use a "defer" statement to do some kind of tidy-up.

Another random example:

echo "sdl2 not yet initialized"

with my_init_sdl2():
   echo "SDL2 is now initialized"
   # Over here do your regular SDL2 logic, but don't need to worry about
   # calling sdl2.quit yourself.

echo "sdl2 was shut down"

Would like to be able to have a "with" macro that supports both forms, based on whether there is an "as" clause.


2017-10-05 05:33:07

Since you don't want to dive into macros and you don't need anything super-generic, I think you're better off with @Benjaminel's idea:

template withcd(newdir: string, statements: untyped) =
  let olddir = os.getCurrentDir()
  defer: os.setCurrentDir(olddir)
import os

proc hi() =
  echo "in:", os.getCurrentDir()


  echo "It works!"

echo "Finish it."

It works!
Finish it.

2017-10-07 18:48:52
cdunn2001: "There's actually a lot of places I'd really like to use "withAs" in, eg to make sure that resources are closed, but without needing to add a resource-specific "defer" line." So wizzardx will need to create a template like this for every type he'll use
2017-10-07 19:23:58