Re: API in Clojure for Java folklore
I think the right place for this is Maven, Ant, Leiningen, and command line. It's a generic thing for any build system. :-) Generating correct stubs is the common part, and then there is an integration into each system. I'm most interested in having this for Maven, but there's really not much to the Maven part of this (aside from some rather arcane knowledge). See also http://groups.google.com/group/clojure-maven-plugin/browse_thread/thread/1d710e7d75a564b7 (related) On Jun 5, 5:41 am, ka wrote: > On Jun 5, 1:33 am, Jason Smith wrote: > > > > > > > The Java stubs are, ideally, a temporary thing. They don't need to be > > around forever. However, I know of no way at present to generate them > > automatically. > > > Also, you are solving half the problem. Generating the stubs and > > class files at the same time does not solve the compile-time > > dependency problem. Consider: > > > Clojure A references Java class B references Clojure class C > > references Java class D. A, B, C, D are in a single project. > > > You *must* run either gen-class or Javac first. Without some kind of > > stubbing, the compile-time references are unknown, either way. Either > > Java does not know about the Clojure gen-class classes that are to > > come, or Clojure does not yet know about the Java classes in the > > project. > > > So, treating Java as the least-common-denominator, you run: > > * gen-stubs > > * Javac > > * gen-class > > > Since the stubs are around, you can also run JavaDoc. > > > The stubs don't need to be saved. In the Maven world, they are part of > > the build, not source files. > > > On Jun 4, 8:03 am, ka wrote: > > > > @Jason > > > > I'm supplying a Java API (implemented in Clojure) so needed a solution > > > quickly which just worked w/o me having to do special things. > > > > Hence the gen-class+javadoc macro (http://gist.github.com/415269). > > > But I feel there should be something like this available in contrib > > > which handles the whole jing-bang of gen-class ! > > > > Currently I'm using the strategy of generating .class files from gen- > > > class, then generating java-stubs as required, running javadoc and > > > just deleting the java-stubs (as they provide no value in their own). > > > > Why do you think keeping the java-stubs is necessary? > > > > - Thanks > > Oh, now I understand fully your last post! I hadn't considered the > cyclic dependencies situation, thanks for pointing that out. Though I > can't see why right now; in future I might write some code (of mine) > in Java to be used from Clojure (maybe performance). In that > situation you are right we should - > > 1) Generate Java-stubs for Clojure gen-class, gen-interface. > My macro is a half-assed attempt to generate stubs automatically > using the gen-class args. One complexity is to choose return values > if return type is primitive. > > 2) Run javac to compile all java sources properly. > > 3) Run gen-class to replace stubbed .class files by Clojure > generated .class files. > > 4) Run javadoc to get the seamless documentation. > > I'm sure I'm not qualified enough to try to code this up, given that I > haven't used maven or ant ever myself. But I'd like to give it a shot > given some guidance. > > Do you think the right place for this is leiningen? > > - Thanks- Hide quoted text - > > - Show quoted text - -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: API in Clojure for Java folklore
On Jun 5, 1:33 am, Jason Smith wrote: > The Java stubs are, ideally, a temporary thing. They don't need to be > around forever. However, I know of no way at present to generate them > automatically. > > Also, you are solving half the problem. Generating the stubs and > class files at the same time does not solve the compile-time > dependency problem. Consider: > > Clojure A references Java class B references Clojure class C > references Java class D. A, B, C, D are in a single project. > > You *must* run either gen-class or Javac first. Without some kind of > stubbing, the compile-time references are unknown, either way. Either > Java does not know about the Clojure gen-class classes that are to > come, or Clojure does not yet know about the Java classes in the > project. > > So, treating Java as the least-common-denominator, you run: > * gen-stubs > * Javac > * gen-class > > Since the stubs are around, you can also run JavaDoc. > > The stubs don't need to be saved. In the Maven world, they are part of > the build, not source files. > > On Jun 4, 8:03 am, ka wrote: > > > @Jason > > > I'm supplying a Java API (implemented in Clojure) so needed a solution > > quickly which just worked w/o me having to do special things. > > > Hence the gen-class+javadoc macro (http://gist.github.com/415269). > > But I feel there should be something like this available in contrib > > which handles the whole jing-bang of gen-class ! > > > Currently I'm using the strategy of generating .class files from gen- > > class, then generating java-stubs as required, running javadoc and > > just deleting the java-stubs (as they provide no value in their own). > > > Why do you think keeping the java-stubs is necessary? > > > - Thanks Oh, now I understand fully your last post! I hadn't considered the cyclic dependencies situation, thanks for pointing that out. Though I can't see why right now; in future I might write some code (of mine) in Java to be used from Clojure (maybe performance). In that situation you are right we should - 1) Generate Java-stubs for Clojure gen-class, gen-interface. My macro is a half-assed attempt to generate stubs automatically using the gen-class args. One complexity is to choose return values if return type is primitive. 2) Run javac to compile all java sources properly. 3) Run gen-class to replace stubbed .class files by Clojure generated .class files. 4) Run javadoc to get the seamless documentation. I'm sure I'm not qualified enough to try to code this up, given that I haven't used maven or ant ever myself. But I'd like to give it a shot given some guidance. Do you think the right place for this is leiningen? - Thanks -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: API in Clojure for Java folklore
The Java stubs are, ideally, a temporary thing. They don't need to be around forever. However, I know of no way at present to generate them automatically. Also, you are solving half the problem. Generating the stubs and class files at the same time does not solve the compile-time dependency problem. Consider: Clojure A references Java class B references Clojure class C references Java class D. A, B, C, D are in a single project. You *must* run either gen-class or Javac first. Without some kind of stubbing, the compile-time references are unknown, either way. Either Java does not know about the Clojure gen-class classes that are to come, or Clojure does not yet know about the Java classes in the project. So, treating Java as the least-common-denominator, you run: * gen-stubs * Javac * gen-class Since the stubs are around, you can also run JavaDoc. The stubs don't need to be saved. In the Maven world, they are part of the build, not source files. On Jun 4, 8:03 am, ka wrote: > @Jason > > I'm supplying a Java API (implemented in Clojure) so needed a solution > quickly which just worked w/o me having to do special things. > > Hence the gen-class+javadoc macro (http://gist.github.com/415269). > But I feel there should be something like this available in contrib > which handles the whole jing-bang of gen-class ! > > Currently I'm using the strategy of generating .class files from gen- > class, then generating java-stubs as required, running javadoc and > just deleting the java-stubs (as they provide no value in their own). > > Why do you think keeping the java-stubs is necessary? > > - Thanks -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: API in Clojure for Java folklore
@Jason I'm supplying a Java API (implemented in Clojure) so needed a solution quickly which just worked w/o me having to do special things. Hence the gen-class+javadoc macro (http://gist.github.com/415269). But I feel there should be something like this available in contrib which handles the whole jing-bang of gen-class ! Currently I'm using the strategy of generating .class files from gen- class, then generating java-stubs as required, running javadoc and just deleting the java-stubs (as they provide no value in their own). Why do you think keeping the java-stubs is necessary? - Thanks -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: API in Clojure for Java folklore
[Note, you can implement this solution by writing stub classes by hand. This means you write stubbed out Java classes, run Javac first, and allow Clojure to overwrite the stubbed class files when it compiles. This is easy to do in Maven, and not difficult in ANT. And I have not actually tried this yet, so it's possible that there are wrinkles that still need to be ironed out.] For a general solution to this problem, which covers not only Javadoc but also the compile-time dependency "chicken-and-egg" problem, I believe we need two stages of compilation to be compatible with Javac. 1) Generate Java stubs from Clojure. 2) Generate class files from Clojure. These need to be separate steps, since (1) must be run before Javac and (2) must be run afterwards. Here is how it would work in the bigger scheme of things. a) gen-stubs generates stubbed Java files. These files are actual Java source, but the methods just throw NotImplementedException. (1) includes Javadoc from Clojure metadata (2) includes annotations (3) includes Types, including generic definitions b) Run Javac against Java classes and Clojure (Java) stubs. Everything compiles, and the annotation processor (Java 5 and 6) is happy as well. c) Run Clojure compile, which overwrites all the stubbed classes from step (b). d) (OPTIONAL) Run Javadoc against Java + Clojure stubs. This will produce complete, seamless Javadoc for consumption by Java users. By using two steps and stubs, the chicken-and-egg problem is solved. You don't get odd compile-time dependency problems. Even though there are two separate compilations happening, it works as if there is only one. I am hoping that someone else will implement this solution before I get around to needing it! :-) Note also that this would allow you to combine Java, Groovy (which already implements stubbed compilation), and Clojure all in the same build with circular dependencies between all three languages. On May 28, 3:36 pm, ka wrote: > I've also added a :class-doc key to the macro - > > (gen-class+javadoc > :class-doc "Class Docs > One Two > " > :name "a.b.c.MyCoolClass" > :methods [ > #^{:static true} [method1 > [clojure.lang.PersistentArrayMap] int] > #^{:static true} [method2 [int int float] > clojure.lang.LazySeq] > #^{:static true} [method3 [] Object] > ]) > > Thanks -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: API in Clojure for Java folklore
I've also added a :class-doc key to the macro - (gen-class+javadoc :class-doc "Class Docs One Two " :name "a.b.c.MyCoolClass" :methods [ #^{:static true} [method1 [clojure.lang.PersistentArrayMap] int] #^{:static true} [method2 [int int float] clojure.lang.LazySeq] #^{:static true} [method3 [] Object] ]) Thanks -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: API in Clojure for Java folklore
Hi all, Inspired by Erik above, I've written a macro: gen-class+javadoc (http://gist.github.com/415269). It works quite well for me on Windows XP. For *nix, I think people will have to make at least one change - the shell command (at line 57). What it does - 1. Generates a javadoc for your API made using gen-class. How to use - 1. Just use gen-class+javadoc macro instead of the gen-class macro. _No other changes are required by the coder_. Functioning - 1. It calls gen-class first as usual with the args. 2. Generates a .java file containing the javadoc. 3. Runs the javadoc command and generates docs in the doc/ directory. 4. Deletes the .java file created above. Few points to note - 1. It is by no means complete. For eg. it doesn't handle interface related stuff yet. 2. It uses macroexpand inside a macro, but some people on Clojure# pointed out that this is not recommended. I'm very new to macro-foo, so please let me know of the alternatives. 3. The macro itself contains a lot of side effects, dunno if this is a very big issue. Try it out if you expose an API through gen-class. Any comments / suggestions / critiques are welcome. - Thanks -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: API in Clojure for Java folklore
It sure seems like we need a good stub generator for Clojure. Java- interop just doesn't seem complete without it. On May 22, 10:12 pm, ka wrote: > Hi, any responses? > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with your > first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group > athttp://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: API in Clojure for Java folklore
hi, you could use a simple class signature generator and then run javadoc on it: (def javadoc-strings (atom {})) (defn javadoc [class name & body] (swap! javadoc-strings update-in [class] #(conj (or % []) %2) [name (apply str body)]) nil) (defn -myMethod "My cool documentation" [x y] '...) (javadoc 'MyClass '-myMethod " /* . * " (:doc (meta #'-myMethod)) " */ public Object MyMethod(int x, int y) { }; ") (javadoc 'Bar 'one " /* * */ public Object one(int t) {}; ") (javadoc 'Bar 'two " /* * */ public Object one(int t) {}; ") (deftype Bar [x] Foo (one [t] (+ x 2)) (two [t] (+ x 2))) (defn make-docclass [p c] (let [cname (str c) methods (into {} (get @javadoc-strings c))] (str "package " p \; \newline "public class " c "{" \newline (apply str (interpose \newline (map second methods))) "}"))) (clojure.contrib.io/make-parents (java.io.File. "/src/bar/foo/ Bar.java")) (clojure.contrib.io/spit "/src/bar/foo/Bar.java" (make-docclass "bar.foo" 'Bar)) ;; in the directory, call: ;; javadoc -sourcepath src bar.foo Depending on your time and macro-foo skills, you can extend this to automtically generate documentation from a genclass definition or a whole namespace. But for a one-shot documentation of a simple API, this might be enough. Erik -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: API in Clojure for Java folklore
Hi, any responses? -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
API in Clojure for Java folklore
Hi all, I've written an API in Clojure to be consumed by people working in the Java world. Now most of these people haven't even heard of Clojure; but all they care about is 1) a working API and 2) with nice documentation. 1) Something about the API - I tried out various things, types, records, protocols (from the master). But finally I've decided to stick with 2-3 defrecords + gen-class. The API is just a bunch of static methods with zero state (earlier I was thinking fancy stuff like OO, and keeping state for each object ... but didn't like any of it). Anyway, so now I've a working API. 2) The problem I have now is how to put Javadocs in all my static methods? I don't want to create documentation that is detached from the code. For example, if I declare a method in gen-class as - #^{:static true} [myCoolFn [int int] clojure.lang.LazySeq] and definition of the function- (defn -myCoolFn "My cool documentation" [a b] ... ) The .class file generated and hence the API - 2.1) Doesn't have the parameters named int a, int b :(. They are named as int arg0, int arg1. 2.2) "My cool documentation" doesn't come up in the Javadocs. I'm not much familiar with Java so please advise. Thanks! -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en