Closed mstade closed 9 years ago
Yeah I'm not clear whats best here either. The problem with require('./funkis/core/thing')
is that it wont work form outside funkis. When you package something up with npm I think you can only have one exposed object. In which case ./funkis/core/thing'
would become something like require('funkis').core.thing
lipstick on a pig
Yo!
When you package something up with npm I think you can only have one exposed object. In which case ./funkis/core/thing' would become something like require('funkis').core.thing
Actually, no. The node module lookup algo says that the first segment of the path is the module, and subsequent segments are a subpath. So require('funkis/core/thing')
would work, but stuff couldn't be in a lib folder. Put everything that should be in core in a folder named core, and it'll work just fine. The benefit to this is that dependency tree becomes clear, and isn't hidden away in objects acting as namespaces, which then has some incidental benefits in terms of doing builds and stuff like that. I'm not sure I care very much about that in particular, at least not right now, but it seems like the neater way of categorizing things than the typical namespace-by-object way. The downside of course is that you have to require
every function you're going to use. This may or may not be an issue.
That said, still feels like a not so very important thing. Just figured I'd drop it here as a todo-maybe, so I don't have to keep it in my head. :o)
so require('funkis/core/thing') would work
Awesome, I had no idea you could do that.
The benefit to this is that dependency tree becomes clear, and isn't hidden away in objects acting as namespaces
Yeah its still not wonderful, but it is a whole lot nicer!
:+1:
Did some further thinking on this and I reckon a decent approach would be to split things up into folders, as a sort of coarse categorization. There should only be one level of folders to make things simple, and they should all be in root. This enables a usage of the library like mentioned above, i.e. require('funkis/core')
or require('funkis/data')
, whereby an index-like module is loaded that just pollutes the global namespace, kind of like what the recently introduced repl module does. Likewise, doing require('funkis')
would load all funkis packages, and thus making the full funkis environment available to the code. Should you not want this, you could still just load individual modules by doing something like require('funkis/fun/variadic')
or require('funkis/data/vector')
.
Alternatively, the index-like module returns a map, where the keys are the module names (i.e. seq
, variadic
etc.) and the values are the modules. This would let the user decide for themselves whether they want to pollute the global namespace. I'm not sure I care to be honest. Funkis will probably be one of those libraries that is quite simply best suited when buying in pretty much wholesale, since you just kind of want to keep using functions from it once you've started. I mean, no one pulls in a lib like funkis just to use lt
. Seriously.
Regardless, the point of packages isn't so much to create a comprehensive ontology, but rather just to group reasonably related things together. Things like gt
, lt
, and other comparators may live in funkis/compare
or something while filter functions such as even
or odd
may live in funkis/filter
. Like I said, it's not that important what the folders are, just that stuff are reasonably related. Each folder could contain lots of functions, I don't mind that very much, but I think it might help to keep some sort of coarse organization by topic.
Oh yeah I forgot. Another reason why I reckon splitting things up into high level folders at the root, is because if this project starts to get unwieldy and I do want to split it up into multiple repositories, it becomes a whole lot easier to do so since require statements won't have to change. I probably won't do this because I don't think it actually solves any organizational problems (just creates more) but I like to keep the option available should I change my mind.
As I'm evolving this lib more and more, I'm running into a distinction between low-level and high-level functionality. The difference is that low-level functions should only really depend horizontally on other low-level functions, if it has any dependencies at all. Ideally, these functions are optimized for speed and small call stacks. I don't envision that there will be very many such functions, but a handful, and I'm finding the cognitive load to remember whether a function is safely low-level or not is annoying. Ideally, I wouldn't need to know this at all, but it does become important at times – things such as deftype
and fn
shows this. In a sense, one could think of these functions as Clojure's special forms. Sort of.
Anyway, I'm thinking that splitting the project up in at least two parts would help dealing with this cognitive load. Everything that is low-level goes into some core
or whatever package, something small, and everything else goes elsewhere. There's little need to go crazy with categorization, but this particular case seems like a candidate anyhow.
Packages probably makes sense, but will punt till I need it.
This stuff is growing out of control. I wonder whether it'd make sense to package things up just so
lib
isn't just one long list of functions. Clojure has core and stuff like that, maybe just bundling stuff into folders would work, and then you require things by doing something like `require('funkis/core/thing')? Or perhaps even going so far as to moving stuff into separate projects altogether, so there's a funkis.core, funkis.stuff, etc. But then also comes maintenance headaches of multiple repos etc.Obviously little more than lipstick on a pig, but worth thinking about. Later. Maybe.