Passing Args to Clojure from Java - java

I would like to embed Clojure code into Java. This site was helpful in the basics of setting this up, but the only arg it ever passes is of type String. I have tried using ints as well, and those also work.
My question is whether there is some formatted way to pass in structured data to Clojure. In particular, I have a list of points I would like to pass to Clojure and turn into a vector that would look something like this:
[[1 2] [3 4] [5 6]]
What is the easiest way to go about doing this? Is there preprocessing I can do on Java's end, or should I do postprocessing on Clojure's end, or is there something in Clojure that will handle this? I suspect it's passing in a String of numbers and the length of each tuple to Clojure, and letting it process the String into a vector. However, this aspect of Clojure doesn't have many examples, and I'm curious if I'm missing something obvious.
EDIT: Please look at mikera's answer is you're interested in passing in Java Objects. Please look at my answer below if you just want to format your data ahead of time into a Clojure format for a set/map/etc.

It depends a bit on what format your data is in to start with, but you may find it easiest just to pass the Java object that represents the data directly and read it using Clojure's Java interoperability features.
e.g. you could pass a Java array of Points directly and do something like:
(let [point (aget some-array index)]
(do-stuff-with-point point))

For those cases when you want to pass in a simple data structure that you've already formatted to look like Clojure in Java, you can pass in that arg as a string. So for the example I gave in my question, I would pass in
"[[1 2] [3 4] [5 6]]"
as my arg. When you've called Clojure using invoke(arg), you can make the first step of your function to be a call to readString on your arg:
(defn foo [d]
(def data (read-string d)))
The above will produce a vector when the example String is passed in.

Related

How to stringify in Java

In c++ we could use macro as
#define check_and_log_warning(x) if (!(x)) {log_error(#x); cout<<__LINE__;}
I want to get values of a boolean expression and also use it as a string.
Getting the line number inside macro would be added benefit.
Can something like this macro be written in Java ?
I recently moved from c/c++ to java, so I am wondering could such thing be done in c++ without macro ?
Preprocessor is what I miss from C/C++ in Java. There are ways ..., but they are Java ways.
1/ Assertions:
http://docs.oracle.com/javase/7/docs/technotes/guides/language/assert.html
2/ Logs:
The one that I use is https://commons.apache.org/proper/commons-logging/
(over log4J or whatever you want)
To print line numbers in log messages, you can use something like:
int lineNo = Thread.currentThread().getStackTrace()[2].getLineNumber();
Edit:
Be warned: unlike __LINE__ in C++ getting the stack trace incurs a performance penalty. Be nice :)
There is no macro facility in Java.
You would be using a logging framework (of which there are plenty to choose from).
if (! theActualConditionNotJustX) myLogger.error("describe problem here");
The logging backend (if configured that way) makes sure to capture and display line numbers. There is some runtime cost for this, but it is usually negligable, especially where actual "errors" are involved (it can get a bit costly for trace-level logging).

How to use or implement arrays in XQuery?

Is there any built in support for array in XQuery? For example, if we want to implement
the simple java program in xquery how we would do it:
(I am not asking to translate the entire program into xquery, but just asking
how to implement the array in line number 2 of the below code to xquery? I am
using marklogic / xdmp functions also).
java.lang.String test = new String("Hello XQuery");
char[] characters = test.toCharArray();
for(int i = 0; i<characters.length; i++) {
if(character[i] == (char)13) {
character[i] = (char) 0x00;
}
}
Legend:
hex 0x00 dec 0 : null
hex 0x0d dec 13: carriage return
hex 0x0a dec 10: line feed
hex 0x20 dec 22: dquote
The problem with converting your sample code to XQuery is not the absence of support for arrays, but the fact that x00 is not a valid character in XML. If it weren't for this problem, you could express your query with the simple function call:
translate($input, '', '')
Now, you could argue that's cheating, it just happens so that there's a function that does exactly what you are trying to do by hand. But if this function didn't exist, you could program it in XQuery: there are sufficient primitives available for strings to allow you to manipulate them any way you want. If you need to (and it's rarely necessary) you can convert a string to a sequence of integers using the function string-to-codepoints(), and then take advantage of all the XQuery facilities for manipulating sequences.
The lesson is, when you use a declarative language like XQuery or XSLT, don't try to use the same low-level programming techniques you were forced to use in more primitive languages. There's usually a much more direct way of expressing the problem.
XQuery has built-in support for sequences. The function tokenize() (as suggested by #harish.ray) returns a sequence. You can also construct one yourself using braces and commas:
let $mysequence = (1, 2, 3, 4)
Sequences are ordered lists, so you can rely on that. That is slightly different from a node-set returned from an XPath, those usually are document-ordered.
On a side mark: actually, everything in XQuery is either a node-set or a sequence. Even if a function is declared to return one string or int, you can treat that returned value as if it is a sequence of one item. No explicit casting is necessary, for which there are no constructs in XQuery anyhow. Functions like fn:exists() and fn:empty() always work.
HTH!
Just for fun, here's how I would do this in XQuery if fn:translate did not exist. I think Michael Kay's suggestion would end up looking similar.
let $test := "Hello XQuery"
return codepoints-to-string(
for $c in string-to-codepoints($test)
return if ($c eq 32) then 44 else $c)
Note that I changed the transformation because of the problem he pointed: 0 is not a legal codepoint. So instead I translated spaces to commas.
With MarkLogic, another option is to use http://docs.marklogic.com/json:array and its associated functions. The json:set-item-at function would allow coding in a vaguely imperative style. Coding both variations might be a good learning exercise.
There are two ways to do this.
Firstly you can create an XmlResults object using
XmlManager.createResults(), and use XmlResults.add() to add your
strings to this. You can then use the XmlResults object to set the
value of a variable in XmlQueryContext, which can be used in your
query.
Example:
XmlResults values = XMLManager.createResults();
values.add(new XmlValue("value1"));
values.add(new XmlValue("value2"));
XmlQueryContext.setVariableValue("files", values);
The alternative is to split the string in XQuery. You
can do this using the tokenize() function, which works using a
regular expression to match the string separator.
http://www.w3.org/TR/xpath-functions/#func-tokenize
Thanks.
A little outlook: XQuery 3.1 will provide native support for arrays. See http://www.w3.org/TR/xquery-31/ for more details.
You can construct an array like this:
$myArray = tokenize('a b c d e f g', '\s')
// $myArray[3] -> c
Please note that the first index of this pseudo-array is 1 not 0!
Since the question "How to use or implement arrays in XQuery?" is being held generic (and thus shows up in search results on this topic), I would like to add a generic answer for future reference (making it a Community Wiki, so others may expand):
As Christian GrĂ¼n has already hinted at, with XQuery 3.1 XQuery got a native array datatype, which is a subtype of the function datatype.
Since an array is a 'ordered list of values' and an XPath/XQuery sequence is as well, the first question, which may arise, is: "What's the difference?" The answer is simple: a sequence can not contain another sequence. All sequences are automatically flattened. Not so an array, which can be an array of arrays. Just like sequences, arrays in XQuery can also have any mix of any other datatype.
The native XQuery array datatype can be expressed in either of two ways: As [] or via array {}. The difference being, that, when using the former constructor, a comma is being considered a 'hard' comma, meaning that the following array consists of two members:
[ ("apples", "oranges"), "plums" ]
while the following will consist of three members:
array { ("apples", "oranges"), "plums" }
which means, that the array expression within curly braces is resolved to a flat sequence first, and then memberized into an array.
Since Array is a subtype of function, an array can be thought of as an anonymous function, that takes a single parameter, the numeric index. To get the third member of an array, named $foo, we thus can write:
$foo(3)
If an array contains another array as a member you can chain the function calls together, as in:
$foo(3)(5)
Along with the array datatype, special operators have been added, which make it easy to look up the values of an array. One such operator (also used by the new Map datatype) is the question mark followed by an integer (or an expression that evaluates to zero or more integers).
$foo?(3)
would, again, return the third member within the array, while
$foo?(3, 6)
would return the members 3 and 6.
The parenthesis can be left out, when working with literal integers. However, the parens are needed, to form the lookup index from a dynamic expression, like in:
$foo?(3 to 6)
here, the expression in the parens gets evaluated to a sequence of integers and thus the expression would return a sequence of all members from index position 3 to index position 6.
The asterisk * is used as wildcard operator. The expression
$foo?*
will return a sequence of all items in the array. Again, chaining is possible:
$foo?3?5
matches the previos example of $foo(3)(5).
More in-depth information can be found in the official spec: XML Path Language (XPath) 3.1 / 3.11.2 Arrays
Also, a new set of functions, specific to arrays, has been implemented. These functions resinde in the namespace http://www.w3.org/2005/xpath-functions/array, which, conventionally, is being prefixed with array and can be found referenced in here: XPath and XQuery Functions and Operators 3.1 / 17.3 Functions that Operate on Arrays

Reflection, hashtable or methods for performance?

I'm trying to write a Java program to decode and encode Ogg streams. I've got a decoder working but I didn't like the fact that I had duplicate code so I started writing something like that:
Decoder oggDecoder = new Decoder(
new StringDecoder( "Ogg" ),
new IntDecoder( "something" )//, ...
);
I wrote encoders and decoders for some "types" and then use them to build the whole thing.
But then I don't know how to store the result. I have 3 options I know:
- keep the data in an array of bytes and provide a get( String name ) and set( String name, Object value ) methods that will work directly on the bytes.
- use a dictionary.
- use a class and use reflection to set the properties.
I'm not that much into performance and if it's slow I don't really care as long as it's fast enough to read music. Meaning that I know writing the functions myself would make it faster but I want to write just one function working for all the properties.
So what do you think would be the fastest way of doing this?
Another way to ask this question would be:
Given a set of field names as an array of String, what is the most appropriate data structure to store the corresponding values that got decoded from a byte stream:
- keep them as byte
- store them in a dictionary
- store them in a class using reflexion
Thanks in advance for your answer.
KISS - just use a HashMap<String, byte[]>. No reflection needed.
Update
I don't think I understood at first what you want, but now I think what you are looking for is a hetergeneous map structure.
Here's a question that might be of more use to you.

Good way to serialize array in Java that is readable from Python?

I have some Java's serialized objects (arrays of doubles) in MySql database fields that I generated previously. Now I needed to read them from Python and I have just realized that it is probably not possible to do directly.
Then I tried to convert them to strings in java (simply comma delimited), and manually parse them from Python. But, it turned out that parsing from Python works painfully slow this way. Is there any better way for serializing arrays that is compatible between Java and Python?
Edit: Sorry, my parsing code was the problem, of course. I replaced it with this:
stringList = string.split(', ')
svdVector = [float(x) for x in stringList]
..and now it is almost instant for my case of 1000x1000 doubles. Although it still feels wrong to store doubles as strings instead of binary, but since it's easy to code and runs fast enough, it is fine.
Python comes with modules for CSV files, XML, and JSON, so one of those would likely do the trick quite well.
If you really want to try binary serialization, check out the built-in struct and array modules for help with interpreting the data in Python.

A way to strip returned values from java.io.File.listFiles in Clojure

I call a java function in Clojure to get a list of files.
(require '[clojure.java.io :as io])
(str (.listFiles (io/file "/home/loluser/loldir")))
And I get a whole bunch of strings like these
#<File /home/loluser/loldir/lolfile1>
etc. How do I get rid of the brackets and put them in some form of an array so another function can access it?
Those strings are just the print format for a Java File object.
See the File javadoc for which operations are available.
If you want the file paths as strings, it would be something like
(map #(.getPath %)
(.listFiles (io/file "/home/loluser/loldir")))
Or you could just use list, which returns strings in the first place:
(.list (io/file "/home/loluser/loldir"))
If you want to read the file, you might as well keep it as a File object to pass into the core slurp or other clojure.java.io or clojure.contrib.duck-streams functions.

Categories