<p>Inspired by this question - <a href="https://languagedesign.stackexchange.com/q/1282/285">What are the disadvantages of being able to define a matrix without typing any words?</a></p>
<p>There is a more general question of what are some syntaxes for initialising tensors and where are their strengths and weaknesses.</p>
<p>There are some obvious cases to cover. Illustrated by pseudo-code below:</p>
<p>An array:</p>
<pre><code>array[int] = {1,2,3};
</code></pre>
<p>A matrix:</p>
<pre><code>matrix[int][int] = {{1,2,3},
                   {4,5,6},
                   {7,8,9}};
</code></pre>
<p>A rank3 tensor:</p>
<pre><code>tensor3d[int][int][int] = {
      {{1,2,3},
       {4,5,6},
       {7,8,9}},
      {{10,11,12},
       {13,14,15},
       {16,17,18}},
      {{19,20,21},
       {22,23,24},
       {23,25,27}},
  };
</code></pre>
<p>You need to be able to specify:</p>
<ul>
<li>The rank   - number of dimnensions</li>
<li>The shape  - the number of elements in each dimension</li>
<li>The values - values for each item</li>
<li>The types of values contained</li>
</ul>
<p>You might want to specify the shape in advance or it might be implied by your initialisation. You might have a syntax allowing the shape to be inferred or requiring it to agree with the initialisation.</p>
<p>Things get hairier still if we think about sparse matrices (assume all elements are zero except those specified), triangular matrices or matrices where there is some symmetry.</p>
<p>You might also want to support populating them alogrithmically by defining a function e.g.</p>
<pre><code>tensor[1:int, 2:int, 3:int] = f(x,y,z) -&gt; int { //calc value for pos x,yz...  };
</code></pre>
<p>for a 1 by 2 by 3 tensor.</p>
<p>There is quite a lot of scope for variation and verbosity here.</p>
<p>What is the prior art here and where do existing approaches succeed or fail?</p>

<syntax><arrays>
What are some good syntaxes for tensor initialisation?
CC BY-SA 4.0
2023-05-30T11:45:56.700Z
Surely, you don't need to be able to specify the rank if you can specify the shape, since the rank is the length of the shape.
Adám
CC BY-SA 4.0
2023-05-30T11:48:40.113Z
Funny you should ask this. I've [asked for permission](https://languagedesign.meta.stackexchange.com/q/32/7) (but not gotten an answer) to ask for feedback on [my proposal for such a notation](https://abrudz.github.io/aplan/Formal%20Proposal%20%E2%80%94%20APL%20Array%20Notation.html).
Adám
CC BY-SA 4.0
2023-05-30T11:49:18.570Z
Additional things to consider is how you'll represent a 0 by 2 tensor and other empty tensors.
Adám
CC BY-SA 4.0
2023-05-30T12:06:36.330Z
I've voted yes to your meta. Also you don't need to ask permission to post. The community will vote to close if your question is bad (which I suspect won't be the case).
Bruce Adams
CC BY-SA 4.0
2023-05-30T12:09:26.493Z
Re the shape. You might specify it in advance or it might be implied by your initialisation. You might have a syntax allowing you to omit one or requiring them to agree.
Bruce Adams
<p>I think you actually need a compile-time DSL, and a general-purpose programming language will never be more concise than a domain specific language.</p>
<p>A directional problem is that it is very bad to write tensor data in the code, and the code should focus on logic rather than data.</p>
<p>The best approach is something like:</p>
<pre class="lang-rust prettyprint-override"><code>let t333 = Tensor::&lt;(3, 3, 3), f64&gt;::parse!(include_str!(&quot;data.tensor&quot;))
</code></pre>
<p>Roughly equivalent to rust that supports method macros.</p>
<hr />
<p>I will design the DSL into two types: dense and sparse.</p>
<ul>
<li>dense and static</li>
</ul>
<pre class="lang-rust prettyprint-override"><code>let magic3 = Tensor::&lt;(3, 3, 3), f64&gt;::parse!(&quot;
// 9 elements per section, if the section elements are not enough, fill with 0
@dense(3, 3, 3, default: 0)

@view(1, _, _)
8  15 19
24 1  17
10 26 6

@view(2, _, _)
12 25 5
7  14 21
23 3  16

@view(3, _, _)
22 2  18
11 27 4
9  13 20
&quot;)
</code></pre>
<ul>
<li>It's stupid to write it twice inside and outside, maybe can omit outside one:</li>
</ul>
<pre class="lang-rust prettyprint-override"><code>let magic2 = Tensor::&lt;_, f64&gt;::parse!(&quot;
@dense(3, 3)
// Read nine numbers directly, with or without line breaks
4 9 2 3 5 7 8 1 6
&quot;)
</code></pre>
<ul>
<li>sparse and dynamic</li>
</ul>
<pre class="lang-rust prettyprint-override"><code>let mut magic3 = Tensor::&lt;(3, 3, 3), f64&gt;::parse!(&quot;
@sparse(3, 3, 3, default: 0)
// Also can support imaginary numbers, so avoid cut off using `-`
&gt; 1, 1, 1: 8
&gt; 1, 1, 2: 15
&gt; 1, 1, 3: 19
.............
&quot;)
magic3[1, 2, 1] = ...
</code></pre>
<p>This DSL syntax can be simply compiled into a instruction machine.</p>
<p>For higher-dimensional data, read binary directly.</p>
<pre class="lang-rust prettyprint-override"><code>let t333 = Tensor::&lt;(3, 3, 3), f64&gt;::deserialize!(include_bytes!(&quot;data.tensor&quot;))
</code></pre>
<p>At this time, textualization does not actually make any sense.</p>

CC BY-SA 4.0
2023-06-30T12:07:07.607Z
2023-06-30T12:15:46.250Z
2023-06-30T12:15:46.250Z
Aster
CC BY-SA 4.0
2023-06-30T12:12:21.000Z
A GPL is arguably partly a collection of DSLs. It is a good point that its generally more useful to parse of external data. Typically this is done at run time so a library solution is sufficient. As an aside, surprisingly, #embed has only very recently made it into C and doesn't include any parsing.
Bruce Adams
CC BY-SA 4.0
2023-06-30T12:27:05.300Z
@BruceAdams Someone told me that the one that borrows the original language is called EDSL, and the one that parses strings is called DSL. I wonder if you assume that the tensor is a hypercube? If the support variable-length list in list, the starting point of the design will be different.
Aster
# What are some good syntaxes for tensor initialisation?
Posted by: username_0 on 2023-05-30
Inspired by this question - What are the disadvantages of being able to define a matrix without typing any words?
There is a more general question of what are some syntaxes for initialising tensors and where are their strengths and weaknesses.
There are some obvious cases to cover. Illustrated by pseudo-code below:
An array:
array[int] = {1,2,3};

A matrix:
matrix[int][int] = {{1,2,3},
                   {4,5,6},
                   {7,8,9}};

A rank3 tensor:
tensor3d[int][int][int] = {
      {{1,2,3},
       {4,5,6},
       {7,8,9}},
      {{10,11,12},
       {13,14,15},
       {16,17,18}},
      {{19,20,21},
       {22,23,24},
       {23,25,27}},
  };

You need to be able to specify:

The rank   - number of dimnensions
The shape  - the number of elements in each dimension
The values - values for each item
The types of values contained

You might want to specify the shape in advance or it might be implied by your initialisation. You might have a syntax allowing the shape to be inferred or requiring it to agree with the initialisation.
Things get hairier still if we think about sparse matrices (assume all elements are zero except those specified), triangular matrices or matrices where there is some symmetry.
You might also want to support populating them alogrithmically by defining a function e.g.
tensor[1:int, 2:int, 3:int] = f(x,y,z) -> int { //calc value for pos x,yz...  };

for a 1 by 2 by 3 tensor.
There is quite a lot of scope for variation and verbosity here.
What is the prior art here and where do existing approaches succeed or fail?
**Tags:** syntax arrays
> **Comments:**
> **username_1**: Surely, you don't need to be able to specify the rank if you can specify the shape, since the rank is the length of the shape.  
> **username_1**: Funny you should ask this. I've [asked for permission](https://languagedesign.meta.stackexchange.com/q/32/7) (but not gotten an answer) to ask for feedback on [my proposal for such a notation](https://abrudz.github.io/aplan/Formal%20Proposal%20%E2%80%94%20APL%20Array%20Notation.html).  
> **username_1**: Additional things to consider is how you'll represent a 0 by 2 tensor and other empty tensors.  
> **username_0**: I've voted yes to your meta. Also you don't need to ask permission to post. The community will vote to close if your question is bad (which I suspect won't be the case).  
> **username_0**: Re the shape. You might specify it in advance or it might be implied by your initialisation. You might have a syntax allowing you to omit one or requiring them to agree.  
---
## 1 answers
### Answer by username_2 on 2023-06-30. Score: 3
I think you actually need a compile-time DSL, and a general-purpose programming language will never be more concise than a domain specific language.
A directional problem is that it is very bad to write tensor data in the code, and the code should focus on logic rather than data.
The best approach is something like:
let t333 = Tensor::<(3, 3, 3), f64>::parse!(include_str!("data.tensor"))

Roughly equivalent to rust that supports method macros.

I will design the DSL into two types: dense and sparse.

dense and static

let magic3 = Tensor::<(3, 3, 3), f64>::parse!("
// 9 elements per section, if the section elements are not enough, fill with 0
@dense(3, 3, 3, default: 0)

@view(1, _, _)
8  15 19
24 1  17
10 26 6

@view(2, _, _)
12 25 5
7  14 21
23 3  16

@view(3, _, _)
22 2  18
11 27 4
9  13 20
")


It's stupid to write it twice inside and outside, maybe can omit outside one:

let magic2 = Tensor::<_, f64>::parse!("
@dense(3, 3)
// Read nine numbers directly, with or without line breaks
4 9 2 3 5 7 8 1 6
")


sparse and dynamic

let mut magic3 = Tensor::<(3, 3, 3), f64>::parse!("
@sparse(3, 3, 3, default: 0)
// Also can support imaginary numbers, so avoid cut off using `-`
> 1, 1, 1: 8
> 1, 1, 2: 15
> 1, 1, 3: 19
.............
")
magic3[1, 2, 1] = ...

This DSL syntax can be simply compiled into a instruction machine.
For higher-dimensional data, read binary directly.
let t333 = Tensor::<(3, 3, 3), f64>::deserialize!(include_bytes!("data.tensor"))

At this time, textualization does not actually make any sense.
> **Comments:**
> **username_0** (2023-06-30): A GPL is arguably partly a collection of DSLs. It is a good point that its generally more useful to parse of external data. Typically this is done at run time so a library solution is sufficient. As an aside, surprisingly, #embed has only very recently made it into C and doesn't include any parsing.  
> **username_2** (2023-06-30): @BruceAdams Someone told me that the one that borrows the original language is called EDSL, and the one that parses strings is called DSL. I wonder if you assume that the tensor is a hypercube? If the support variable-length list in list, the starting point of the design will be different.  
---
