lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Am 14.04.2014 20:32 schröbte Enrique Garcia Cota:
Hi,


Hi!

In most cases I consider the use of standard library functions in my
modules to be an implementation detail, so by caching them in locals I
_enable_ you to monkey-patch to your heart's desire without fear of
breaking the functions of my modules.


"Breaking the functions of my modules" is a language trap. It has a
negative connotations that are not really there. Change it with a more
positive verb, like "patch the functions of my modules" or "fix the
functions of my modules", and the phrase takes a different meaning.

[...]

Your comment about making the dependencies more explicit is very
interesting. I will see if I can make a note about it somewhere in the
article.

It depends on what you intended to achieve with monkey-patching. Did you really mean to change the behavior of all code using a certain function internally (even those whose implementation you don't know) or do you want to enhance an existing module/function to make your own programming more expressive. If it's the latter (which I assumed), the code that has already been written and tested with the old behavior in mind will not benefit. But it _can_ break (popular example: someone enhances `type` to return class names for objects, and some other module uses the result of `type` in a lookup table)! If on the other hand you want the first, to patch some error without fixing the source code, you can still do that, but it requires the `debug` module (but that's ok, because you are _actually_ debugging ;-) ). Also on the plus side: you can replace some function _for certain modules only_. (If you mean serious business, you could also monkey-patch before the module in question captures its env, e.g. first thing in the main script.)


  locals are faster than upvalues, so for tight loops it might make sense to
cache the upvalues defined at the beginning of the module in locals ... :-p


I am not opposed to caching things up in local variables when the
performance tests show that it makes a significant difference. What I
contest is doing it by default.

I just mentioned it because if performance is your main concern, doing it your proposed way (assign to locals inside of the function) is probably faster than doing module level upvalues. On the other hand you can't really be sure how fast/slow access to a global will be because there could be a metatable involved which queries a white-list on some server for every access ...


If you move your modules from `./my-package` to `./lib/my-package`, you
should change `package.path` and not your module references!


That's one way to do it, yes. But I wanted to see if I could find a way
around that, and the other problem is still present (having to change lots
of files). There's also the fact that I know of at least one system that
doesn't respect package.path when loading modules (LÖVE).

I always meant to try Löve, but I've never got around. It uses zip files for storing modules, right?


And your `current_folder` trick is (slightly) broken. When you run
`my-package/init.lua` via `require( "my-package" )` `...` will contain
"my-package", not "my-package.init"


It's the folder containing init.lua that I'm interested in - I needed
something that discarded "the last file name", if it existed. Can you show
me a test exemplifying what you think it's broken?

Assume a file `my/module/init.lua`. If it is require'd as `require "my.module"` (because "./?/init.lua" is in `package.path`), the name passed to the loader is "my.module", and your code will strip the last name component which makes all references to submodules relative to `my` and not `my/module` like it was intended. If on the other hand it is require'd as "my.module.init", you do have to strip that last name component.


You just use `local mod1 = require( (...)..".module1" )` to get to your
submodules.


That strategy is interesting and creative. Thanks for showing it to me, I
will include it on my article.

However it is of no use when you need to "require a module from a sibling
module" (require mypackage.module1 from mypackage.module2). I still think
current_folder covers those edge cases better.

Yes, if you want one submodule to reference another on the same level, you need to strip one module name component like you did.


Thanks,

Enrique (kikito / @otikik)


Philipp