# 8 Brief introduction into Wolfram Language for Clojure developers

    (ns for-developers.wolfram-for-clojurians
      (:require [scicloj.kindly.v4.kind :as k]
                [wolframite.api.v1 :as wl]
                [wolframite.wolfram :as w :refer :all
                 :exclude [* + - -> / < <= = == > >= fn
                           Byte Character Integer Number Short String Thread]]))

    (wl/start!)

    {:status :ok, :wolfram-version 14.2}

## 8.1 What is Wolfram?

According to Wikipedia,

> The Wolfram Language is a proprietary, general, very high-level multi-paradigm programming language developed by Wolfram Research. It emphasizes symbolic computation, functional programming, and rule-based programming and can employ arbitrary structures and data. It is the programming language of the mathematical symbolic computation program Mathematica.

Moreover, the Wolfram Language has the unique position of being not only a programming language but also a full-scale computational language, that incorporates vast amounts of computable knowledge and lets one broadly express things computationally.

“Symbolic” means that everything is a symbolic expression and you can manipulate these expressions themselves - somewhat reminiscent of how you can transform code with Clojure macros.

## 8.2 Pitfalls

In Wolfram, everything is global by default and you need to take care to avoid that, when necessary. `w/Block`and `w/Module` may be useful here.

## 8.3 Building blocks

#### 8.3.0.1 Symbolic expressions

Expressions have the generic form `head[arguments...]`, which becomes Wolframite `(head arguments...)`

Ex.: `Plus[Power[x, 2], Times[3, Power[y, 3]]]`. Notice that we can use undefined symbols, since this is just a symbolic expression, not (yet) a computation. In Clj:

    (wl/->clj "Plus[Power[x, 2], Times[3, Power[y, 3]]]")

    (+ (** x 2) (* 3 (** y 3)))

And if we try to evaluate this:

    (wl/! (w/+ (w/** 'x 2) (w/* 3 (w/** 'y 3))))

    (+ (** x 2) (* 3 (** y 3)))

we get the same expression back, because x and y aren’t defined (yet).

An expression’s head identifies the type of data or operation being represented - f.ex. `List` or `Plus`.

#### 8.3.0.2 Functions

There are multiple ways to create a function.

The canonical way of defining a named function is using patterns (see Section 8.3.0.7): `f[x_] := x^2`, which defines the fn `f`.

To create an ad-hoc function, we can use `Function` similar to Clojure’s `fn` or anonymous function literals with body`&`, where the body may use `#, #1, #2, ...` or `(Slot 1), (Slot 1), (Slot 2), ...` equivalent to Clojure’s `%, %1, %2, ...`. Ex.: `Map[# + 2&,{1,2,3}]`.

In Wolframite, you’ll typically use `w/fn` or leverage the operator form of functions (see Section 8.3.0.9.1).

#### 8.3.0.3 Lists

A Wolfram List `{1, "hello", 3.14}` becomes a vector in Wolframite: `[1, "hello", 3.14]`.

List access by indexing (from 1) via `[[idx or a range a.k.a. Span]]`. Here we access the first element:

    (wl/->clj "{1,2,3}[[1]]")

    (Part [1 2 3] 1)

    (wl/! (Part [1 2 3] 1))

    1

Here we extract a sublist:

    (wl/->clj "{1,2,3}[[1 ;; 2]]")

    (Part [1 2 3] (Span 1 2))

→

    (wl/! (Part [1 2 3] (Span 1 2)))

    [1 2]

Many operations “thread” over lists, applying to each element:

    (wl/! (Plus [1 2 3] 10))

    [11 12 13]

#### 8.3.0.4 Iterators simplify repetitive operations

`Table[x^2, {x, 4, 20, 2}]` in Wolfram is equivalent to Clojure’s `(map (fn [x] (math/pow x 2)) (range 4 20 2))`, while `Table[x, n]` functions as `(repeat n x)` in Clojure.

See also the List Manipulation reference.

#### 8.3.0.5 Associations

Similar to Clojure maps, with a unique syntax using Rules (see Section 8.3.0.6). Fortunately, in Clojure we can just use maps:

    (wl/->clj "<|\"a\" -> x, \"b\" -> y|>")

    {"a" x, "b" y}

#### 8.3.0.6 Rules

Rules, or rewrite rules, of the form `key -> value` predate associations and are used where you’d have expected a map, often to define options to functions, as in here: `Import["demo.csv.gz", {"Data", 1 ;; 3}, "HeaderLines" -> 1]` (Think of this as saying “when evaluating the operation, replace HeaderLines with a truthy value.)

In Wolframite, we would write this as:

    (w/Import "demo.csv.gz" ["Data" (w/Span 1 3)] (w/-> w/HeaderLines 1))

    (Import "demo.csv.gz" ["Data" (Span 1 3)] (-> HeaderLines 1))

#### 8.3.0.7 Patterns

are used to transform symbolic expressions into other symbolic expressions. F.ex. here we replace anything that matches `f[singleArg]` with the arg + 5:

    (wl/! "Replace[f[100], f[x_] -> x + 5]")

    105

Here, `_` a.k.a. Blank is a pattern that matches any expression and a double blank `__` matches any sequence of expressions. We can name the captured value by prepending a name, as in `x_`. There is also `|` for alternatives, `_h` to capture expressions with the head `h`, `:>` for delayed rules.

Notice that this provides one way to define what we would call functions. `Function` and lambdas are another way.

#### 8.3.0.8 Real-World Entities

Real-world entities are symbolic expressions representing information about concepts, things etc. such as countries and chemicals.

We can use entity[“Properties”] to find a list of properties and `EntityValue[entity, "Population"]` to get the value of a property.

We have two ways to represent entities in Wolframite, which both may be useful:

    (def LA-expr (Entity "City" ["LosAngeles" "California" "UnitedStates"]))

    (wl/! (EntityValue LA-expr "Population"))

    (Quantity 3849297 "People")

    (def LA-evaled (wl/! LA-expr))

    (wl/! (EntityValue LA-evaled "Population"))

    (Quantity 3849297 "People")

To get entity properties, we need a small workaround - Wolfram allows `someEntity["Properties"]` but in our case it would mean trying to use the list `(Entity ...)` as a function, which wouldn’t work. So we construct an expression list explicitly:

    (take 3 (wl/! (list (Entity "City" ["LosAngeles" "California" "UnitedStates"])
                        "Properties")))

    ((EntityProperty "City" "ActiveHomeListingCount")
     (EntityProperty "City" "AdministrativeDivision")
     (EntityProperty "City" "AggravatedAssault"))

#### 8.3.0.9 Various

- Assignments - `=` and `:=`; `Module` for scoping
- Applying Functions - `Map` with the shorthand `/@`, `Apply` with the shorthand `@@`
- Use `;` to separate different side-effecting operations, as `(do ...)` would in Clojure (Wolframite: `w/do`)
- Booleans: `True`, `False` (Wolframite: `true`, `false`)
- String: “…”
- Note: Indices in Wolfram start from 1, not 0

##### 8.3.0.9.1 The “operator” form of functions

Many functions are similar to Clojure transducers such as `map` in the regard that you can invoke them without the data they are intended to operate on, and they will return a function that can be applied to the data later. This is called the “operator” form. Examples are `Map` and `AllTrue`.

See Functionals & Operators for more info.

#### 8.3.0.10 Clojure <-> Wolfram

Clojure | Wolfram | Comments
--- | --- | ---
apply | Apply |
comp | Composition |
count | Length |
filter | Select |
nth | Part | 1-based indexing
map | Map |
(map f c1 c2) | (MapThread f [c1 c2]) |
partial | operator form | (see above)
reduce | Fold |
take | Part |

#### 8.3.0.11 Additional resources

Read more in the online booklet The Wolfram Language: Fast Introduction for Programmers, which we have borrowed heavily from.

The dense one-page Wolfram Language Syntax may also be of use, especially when reading Wolfram code.

    source: notebooks/for_developers/wolfram_for_clojurians.clj