3
$\begingroup$

I'd like to use (if this already exists) or create a library to use Mathematica together with Kotlin (or Java) (not JLink, please see below).

We already have this very useful implementation for Python:

Wolfram Client Library for Python

Also, I know that we have the JLink library as well for Java, although the way we use it is not straightforward like in the Python one.

One other thing, in this question of mine I also showed how we could use the MathematicaScript to let Mathematica communicate with different programming languages, if needed.

But my question is a bit different, since in the Python library we could immediately use Mathematica functions, like:

func_squared = wlexpr('#^2 &')
session.evaluate(wl.Map(func_squared, wl.Range(5)))

I was wondering to have something like that for Kotlin and Java as well, directly using, for example, the functions wl.Range, or wl.Map, for example.

So, how could we, maybe using Mathematica internal functions, extract all built-in functions and which arguments they use and their documentation? If we can have this I think we can create the library.

I've seen that we have autocompletion plugins for IntelliJ and VSCode, so, I think their developers have already used something link this, but I'm not sure what did they use.

$\endgroup$
3
  • 1
  • 2
    $\begingroup$ Having said that, I am not sure about your premise which, to me, sounds like If we get a list of all French words, and a dictionary with their definitions, then it should be easy to speak French. $\endgroup$ – MarcoB Jun 1 '20 at 1:15
  • $\begingroup$ Thanks for the links, I'll take a look. Hehe, maybe you're right and the problem is more difficult than that, but I do know that we can automatically generate code files and if we hava this "database" maybe we could automatically generate the functions that I'm saying. But maybe is more difficult than that. Although for python they are already doing that. $\endgroup$ – GarouDan Jun 1 '20 at 2:17
1
$\begingroup$

This is an incomplete answer

I was able to do some progress using the suggestions from @MarcoB.

For example, using this:

Flatten[Names[#] & /@ {"$0*", "$1*", "$2*", "$3*", "$4*", "$5*", "$6*", "$7*", "$8*", "$9*", "$A*", "$B*", "$C*", "$D*", "$E*", "$F*", "$G*", "$H*", "$I*", "$J*", "$K*", "$L*", "$M*", "$N*", "$O*", "$P*", "$Q*", "$R*", "$S*", "$T*", "$U*", "$V*", "$W*", "$X*", "$Y*", "$Z*", "$a*", "$b*", "$c*", "$d*", "$e*", "$f*", "$g*", "$h*", "$i*", "$j*", "$k*", "$l*", "$m*", "$n*", "$o*", "$p*", "$q*", "$r*", "$s*", "$t*", "$u*", "$v*", "$w*", "$x*", "$y*", "$z*", "0*", "1*", "2*", "3*", "4*", "5*", "6*", "7*", "8*", "9*", "A*", "B*", "C*", "D*", "E*", "F*", "G*", "H*", "I*", "J*", "K*", "L*", "M*", "N*", "O*", "P*", "Q*", "R*", "S*", "T*", "U*", "V*", "W*", "X*", "Y*", "Z*", "a*", "b*", "c*", "d*", "e*", "f*", "g*", "h*", "i*", "j*", "k*", "l*", "m*", "n*", "o*", "p*", "q*", "r*", "s*", "t*", "u*", "v*", "w*", "x*", "y*", "z*"}]

We can get the name of all possible functions on Mathematica.

From the Kotlin side, we can transform any iterable object to a "Mathematica List" (this case transforming to a compatible string). This extension will be available to any iterable:

/**
 * Transform an iterable object to a Mathematica List.
 */
fun Iterable<Any>.toMathematicaList(): String {
    var result = "{"

    this.iterator().forEach {
        result += when (it) {
            is Number -> "$it, "
			else -> "\"$it\", "
        }
    }

    // Dropping the remaining `, `.
    result = result.dropLast(2)

    result += "}"

    return result
}

fun main() {
    println(arrayListOf("1", 2, 3.1415, "3", arrayOf(1, 2, 3)).toMathematicaList())
}


// Outputs: {"1", 2, "3", 3.1415, "[Ljava.lang.Integer;@1a6c5a9e"}
// As we can see a more complex object was not transformed because of the toString() method. But we still can handle it later, if needed.
// But the format is the format of what Mathematica expects for a List and the number 2 and 3.1415, remain numbers.

I'm needing a way to get all possible arguments the functions can receive in a way that I could parse them. For example, if it receives a List, I'd like to create a function override that will receive a List as one of its arguments. For simplicity we can consider only the InputForm from Mathematica for now. Does someone knows how can we do that?

Example of function generations:

/**
 *
 */
fun `$ActivationGroupID`(): String {
}

/**
 *
 */
fun `$ActivationKey`(): String {
}

/**
 *
 */
fun `$ActivationUserRegistered`(): String {
}

With the backticks (`) we can escape the $in the function names, when in Kotlin.

An excerpt of how I imagine it could work (maybe not all parts would be easy, but seems possible, please confront with the Range documentation):

import java.lang.IllegalArgumentException

/**
 *
 */
fun main() {
    val range1 = Range(10)!!
    val range2 = Range(10, 20)
    val range3 = Range(10, 20, 2)

    for (i in range1) {
        print(i)
    }
}

/**
 *
 */
class Mathematica {

    /**
     *
     */
    fun evaluateToInputForm(expression: String?): String? {
        if (expression == null) throw IllegalArgumentException("Invalid expression.")

        // ... code that calls Mathematica here.
        val output: String? = null

        return output
    }

    /**
     *
     */
    inline fun <reified Return> extract(rawResult: String?): Return? {
        if (rawResult == null) return null

        // A special code is needed here.
        return rawResult as Return?
    }

    /**
     *
     */
    inline fun <reified Return> evaluateAndExtract(expression: String?): Return? {
        val rawResult = evaluateToInputForm(expression)

        return extract<Return>(rawResult)
    }
}

val mathematica = Mathematica()

open class MathematicaObject{}
abstract class Range : MathematicaObject(), List<Number>

/**
 * Generates the list {1,2,\[Ellipsis],Subscript[i, max]}.
 * Generates the list {Subscript[i, min],\[Ellipsis],Subscript[i, max]}.
 * Uses step di.
 */
fun Range(iMax: Int): Range? {
    return mathematica.evaluateAndExtract<Range>("Range[$iMax]")
}

/**
 * Generates the list {1,2,\[Ellipsis],Subscript[i, max]}.
 * Generates the list {Subscript[i, min],\[Ellipsis],Subscript[i, max]}.
 * Uses step di.
 */
fun Range(iMin: Int, iMax: Int): Range? {
    return mathematica.evaluateAndExtract<Range>("Range[$iMin, $iMax]")
}

/**
 * Generates the list {1,2,\[Ellipsis],Subscript[i, max]}.
 * Generates the list {Subscript[i, min],\[Ellipsis],Subscript[i, max]}.
 * Uses step di.
 */
fun Range(iMin: Int, iMax: Int, di: Int): Range? {
    return mathematica.evaluateAndExtract<Range>("Range[$iMin, $iMax, $di]")
}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.