Is there a modulo function in M2DOC?

Hello,
Let’s say we are iterating through a for loop,
it would be interesting to be able to check the number of the iteration, and check wether it is odd or even.
That could be achieved using the modulo function such as Variable%2=0 ==> {m:modulo 2|MyVariable}

Is there some function similar? or any other way to achieve it? Thanks.

There is a mod() service you can use:

variable.mod(2)

I doesn’t appear in the documentation, but you can find the implementation here.

1 Like

Thank you Yvan.
I have a subsidiary question (maybe 2), but a really interesting one.
let me show you what i have tried to set up.
I am trying to do an iteration of a variable. Maybe this needs its own post, but here goes:

m:let iteration = 0
m: iteration = iteration +1
m: iteration
m: iteration.add(1)
m: iteration

The previous lines of code would return:

  • Nothing
  • false
  • 0
  • 1
  • 0

A) I understand that (x=y) is only used to verify expressions. Same for (x==y). Furthermore, x.add(y) will not increment the x let variable…

  1. Is there a way to Change the value of our “let” variable ? The same way as we would do i a classical programming langage. (var=var+1, var++… )
    or maybe save the result in a new “unassigned” let variable?

(Someone had asked a similar question I think here : [M2Doc] Variable declaration with ‘let’ is final? - Capella - Eclipse Capella Forum (mbse-capella.org))

  1. Or a add the value at the end of some sequence. It is possible to create a let empty sequence and append values to it by the way?

Or maybe:
3) Is it possible to acquire the “index” of the current iteration in the for loop? Something like this:

{m:for var|expression}

{m:let i=var.FORINDEX}

{m:if i.mod(2)=0}
The current iteration is pair
{m:endif}
{m:endlet}
{m:endfor}

B) I found the “add” function in the git documentation,

public Integer add(Integer a, Integer b) {
		return Integer.valueOf(a.intValue() + b.intValue());
	}

	/**
	 * Performs the substraction of the specified arguments.
	 * 
	 * @param a
	 *            the first operand
	 * @param b
	 *            the second operand
	 * @return the substraction of the arguments.
	 */

However to use it in the M2DOC template and in the M2DOC interpreter, i had to convert what seemed to me to be a double parameters function (add(Integer a, Integer b)) into one paremeter function (add(integer a)).
4) How does this work? Is there some method to know in order to be able to exploit all the functions mentioned in the git documentation?
Or maybe that’s related to Acceleo VS AQL somehow?
Anyway, all of this is really interesting, thanks a lot.

A)
All variables are immutable in M2Doc. You can get the index of the current value in the collection which is a bit sub optimal:

{m:for value | myList}
    {m:myList->indexOf(value)}
{m:endfor}

Or you can create a Java service to keep count of iterations.

B)
In the Java service, the first parameter is the receiver. Its the part of the expression before the call. And all services must have at least one parameter:

public Integer add(Integer a, Integer b)

Is called like this if you don’t want to use the + operator:

a.add(b)

Behind the scene everything is called via a service. It allows to extends the behavior of AQL: feature calls on other element than EObject, call services that are not Java methods (EOperation, template construct, …), and override operators.

And all AQL services and M2Doc services are accessible by default in M2Doc. You don’t need to do anything special to use them like an import.

1 Like

I see, very insightful.
One quick last question for the day

All variables are immutable in M2Doc. You can get the index of the current value in the collection which is a bit sub optimal:

{m:for value | myList}
    {m:myList->indexOf(value)}
{m:endfor}

Or you can create a Java service to keep count of iterations.

How it is possible to test the index? I would like to store it in a variable and test (might not be possible) or at least test it immediately.

Something like
m:if (m:myList->indexOf(value)).mod(2)=0
The value is pair.

Something like this. Seems to be needing to use 2 m.expressons is one. Thx, good evening.

I’m not sure to understand but you can simply write:

{if myList->indexOf(value).mod(2) = 0}

If you are using myList->indexOf(value) more than once, I would recommend caching the result in a variable using a let statement.

1 Like