This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-01-12
Channels
Yeah, it supports a file system abstraction over other things as well, such as a ZIP file, for example. I use that in depstar
Well, I'm not too sure, but I'd assume there can be many filesystems in use, say you have a USB key plugged in for example, and your hard-drive, that would now be two accessible file systems
@deleted-user https://github.com/seancorfield/depstar/blob/master/src/hf/depstar/uberjar.clj#L332 -- that's where depstar
opens a new FileSystem
on a JAR (zip) file
and so if the library is being asked to join paths, for instance, you want to know the file system
a File object can already do path joining for you in the constructor and static methods as appropriate, doesn't that already resolve the issue?
it should use the fs that the File itself would end up on?
I'm probably missing something here
what I'm saying is the constructor for File
should know which fs it ends up on based on the path, and use the correct separator
Though I'm guessing "mounting" would actually have the OS adapt the NTFS filesystem to the current one
@deleted-user dynamic variables are... problematic... start by assuming the filesystem will be passed into all your functions and provide an extra arity that calls each function with the default filesystem).
Where shall I start? 🙂
I don't have the time/patience tonight for it to be honest, sorry. Just don't do it 🙂
I'll be happy to explain when I'm back at work on Monday tho'...
I only know that you have to be careful not to depend on them in a context that runs after the binding is gone.
It's really problematic if a library uses a dynvar because then you can't have multiple instances in use and, yeah, the threading issues. And it makes testing harder.
And it's not considered idiomatic either.
@didibus No, they break that use case.
For example, when I took over clojure.java.jdbc
, it relied on a dynvar for the DB and that made it really hard to use in code that needed to talk to multiple databases because you end up being forced to call binding
everywhere around every call to the library.
Well, I'm not against them, and I do use them, like I said, for cross-cutting concerns.
But I think what I got from Sean and his java.jdbc example, it is a usability thing for the library
Now I need to either do everything inside one (with-cwd ...) or I need to keep repeating (with-cwd x/y/z) over and over in many places
You need to consider whether folks using your lib are likely to need multiple filesystems or not (in your case).
Ya, and if I really didn't want to repeat myself, I could partial all the functions or something like that too, if I don't like typing options on every call
But depstar
is pretty simple and it already needs two filesystems.
Ya, that can make sense too. Probably easier to add bindings over API that take options already then the other way around
But, if you're imaging it being command line driven, I could see even going for a global context.
Well, I mean like, would you ever want two cwd at the same time? If not, the global context can be locked or using an atom under the hood for example
Dynvar or options map are similar-ish, but with dynvar you need to nest things to use the configured values, where with options you can have things flat and thus more easily reused in varying contexts. I'd say that's the biggest difference in terms of usability.
user=> (def ^:dynamic *a* 100)
#'user/*a*
user=> (binding [*a* 200] *a*)
200
user=> (binding [*a* 200] @(future *a*))
200
And this is an example of what to be aware with dynvar:
user=> @(binding [*a* 200] (delay *a*))
100
user=> (def ^:dynamic cwd "z/y/z")
#'user/cwd
user=> (defn read-file "A mock to demonstrate" [file] (str cwd))
#'user/read-file
user=> (binding [cwd "a/b/c"] (map read-file ["file1.txt" "file2.txt"]))
("z/y/z" "z/y/z")
well I'm making up here that read-file is from your library, but because I call it in a lazy seq and it is realized after the binding context has exited, it is using the wrong cwd
haha, ya, I mean again you'd know best how you anticipate your lib to be used and if these edge cases would be common issues faced by users or not
I have a list of symbols (def my-sym '[ a b])
. These symbols have not been declared yet.
In a function -
(defn abc
[a b]
my-sym)
I want the above fn (abc 1 2) => [1 2]
however the above returns the unevaluated [a b]
symbol names. How do I get the fn to return [1 2]If I am right. def is evaluated on loading the file and is not a runtime. http://squirrel.pl/blog/2012/09/13/careful-with-def-in-clojure/
with def you define a value
why do you expect it to behave like a function afterwards ? 🙂
or like a macro .. i'm not even sure what you have meant here
There is a list of symbols which I need to reuse in multiple places, I could have written the fn simply to return [a b]
, but then I would need to keep my multiple fns in sync
i think you are expecting def to behave like #define in C
like a templating tool ? 🙂 but that's not what it is ...
It is usually not a good idea to assume local var names when reusing code. But perhaps something like this would help remove redundancy?
(defn abc [& args]
(vec args))
Right :-) I had to assume that the example given was a partial snippet, but if that's all that's needed then of course vector
will do it.
Macros can be used to do such things, but like I say it is not a good idea to assume local var names.
cant I make it work without macros, something like (eval (map symbol my-sym))
(which gives an error)
Obviously it will give error because when you try to
(eval [a b])
it will say
Unable to resolve symbol: a in this context
because it is not defined in the contextIf you want a function which simply returns a vector of args passed to it, you can use the function abc as suggested by @UBRMX7MT7
There may be some way to get eval to work for this. But the common practice is that macros and eval should be avoided unless a function really won't meet the need. I don't use eval at all.