# How to translate this piece of Golang code to Elixir?

I’m fresh new to Elixir. I’m trying to port a golang library to elixir. But I don’t know how to deal with the the loop part. As a functional programming language. Elixir provides no loop.

``````func (r *ISAAC) isaac() {
r.cc = r.cc + 1    /* cc just gets incremented once per 256 results */
r.bb = r.bb + r.cc /* then combined with bb */

for i := 0; i < 256; i++ {
x := r.mm[i]
switch i % 4 {
case 0:
r.aa = r.aa ^ (r.aa << 13)
case 1:
r.aa = r.aa ^ (r.aa >> 6)
case 2:
r.aa = r.aa ^ (r.aa << 2)
case 3:
r.aa = r.aa ^ (r.aa >> 16)
}
r.aa = r.mm[(i+128)%256] + r.aa
y := r.mm[(x>>2)%256] + r.aa + r.bb
r.mm[i] = y
r.bb = r.mm[(y>>10)%256] + x
r.randrsl[i] = r.bb
}

/* Note that bits 2..9 are chosen from x but 10..17 are chosen
from y.  The only important thing here is that 2..9 and 10..17
don't overlap.  2..9 and 10..17 were then chosen for speed in
the optimized version (rand.c) */
/* See http://burtleburtle.net/bob/rand/isaac.html
for further explanations and analysis. */
}
``````
1 Like

Its hard to say without knowing what `ISAAC` looks like internally…

But loops are generally replaced by recursion or higher order functions in `Enum`.

In general I tend to avoid mechanical translations and rewrite from scratch.

There are a lot of concepts in `go` that you can’t use in elixir. Some do not have even a direct equivalen, like the massive amount of mutation you do in your code.

1 Like

Isaac is a cryptographically secure random number generator. (https://github.com/gtank/isaac/blob/master/isaac.go) This is the golang verison of the CSPRNG. The original version is in C. (http://burtleburtle.net/bob/c/readable.c)

1 Like

If its crypto, don’t touch it. First rule of crypto is to not do it yourself but to use libraries that have been there for a while and are battleproven.

Just implement some bindings to the C or GO versions via NIFs or C-Ports, or use some package from hex.pm if available, or take a look at the erlang `:crypto` module.

2 Likes

Thank you. I’ll give it a try.

1 Like

1 Like

A very slow, probably buggy mechanical translation:

``````def isaac(r) do
import Bitwise

r = %{r | cc: r.cc + 1}
r = %{r | bb: r.bb + r.cc}
r =
Enum.reduce(0..255, r, fn i, r ->
x = Enum.at(r.mm, i)
r =
case rem(i, 4) do
0 -> %{r | aa: r.aa ^^^ (r.aa <<< 13)}
1 -> %{r | aa: r.aa ^^^ (r.aa >>> 6)}
2 -> %{r | aa: r.aa ^^^ (r.aa <<< 2)}
3 -> %{r | aa: r.aa ^^^ (r.aa >>> 16)}
end
r = %{r | aa: Enum.at(r.mm, rem(i + 128, 256)) + r.aa}
y = Enum.at(r.mm, rem(x >> 2, 256)) + r.aa + r.bb
r = %{r | mm: List.replace_at(r.mm, i, y)}
r = %{r | bb: Enum.at(r.mm, rem(y >>> 10, 256)) + x}
%{r | randrsl: List.replace_at(r.randrsl, i, r.bb)}
end)``````
2 Likes

I highlighted the reason why one doesn’t DIY crypto but uses battle proven libraries and wrappers.

1 Like

Yes of course, but porting code can be a great learning exercise.
TIL about Bitwise, which I’ve never had a reason to use yet 4 Likes

Pointing to recursion, comprehensions, and higher-order functions only help so much. They tell us what the desired result will look like, or should look like, but not how to get there @AlecHsueh Once you know what you’re doing, whether that’s by reading that particular Go fragment or not, then you can give it a go in Elixir. It’s hard to get rid of the `for` and the mutation with a line-by-line translation but understanding it helps to get to something that’s more Elixir-like.

There’s a collection of some kind underlying most fragments that have a C-like `for`. A brief glance at the above suggests that it involves byte manipulation or binary data. An Elixir Binary, along with a binary comprehension, and a bunch of meaningful functions might be an idiomatic choice here I hope that helps: it’s a great exercise.

3 Likes