0

I currently have a Java program which does something like the following:

  int nvars = 10;
  long vars[] = new long[nvars];
  for(int i = 0; i < nvars; i++) {
      vars[i] = someFunction(i);
      anotherFunction(vars[i]);
  }

I am converting it into Scala code and have:

val nvars: Int = 10
val vars: Array[Long] = new Array[Long](nvars)

for ( i <- 0 to nvars-1 )
    vars(i) = someFunction(i)
    anotherFunction(vars(i))
}

Any advice on how to make this (more) functional?

1
  • 1
    In a mathematical sense, functions have no side-effects, so you could make your "fuctions" side-effect free, returning a new array (or an immutable list) Commented Jun 11, 2015 at 6:00

3 Answers 3

7

There are lots of useful constructor methods in the Array companion object, for example, for your situation here, you can use tabulate:

val nvars: Int = 10
val vars = Array.tabulate(nvars){ someFunction } // calls someFunction on the values 0 to nvars-1, and uses this to construct the array
vars foreach (anotherFunction) // calls anotherFunction on each entry in the array

If anotherFunction returns a result rather than just being a "side-effect" function, you can instead capture this with a call to map:

val vars2 = vars map (anotherFunction) // vars2 is a new array with the results computed from applying anotherFunction to each element of vars, which is left unchanged.
Sign up to request clarification or add additional context in comments.

3 Comments

A question: isn't what you are proposing equivalent to two consecutive loops? I mean, in terms of the computational efficiency, how optimal is it?
@Daniel In regards to complexity, 2 loops are as complex as 1, or as 10. It's still linear (O(n)).
@Daniel It wasn't clear from your question whether you needed separate results from each function, or just the outcome of the second function. If the latter, then you could have compounded the functions together. Eg. if anotherFunction generates values (is not just side-effecting) you could write Array.tabulate(nvars){ someFunction _ then anotherFunction _ } (as suggested by someone in a proposed edit to my answer - sorry I can't see who that was now to give them credit).
4

Use map. A call to map on an Array will return a new collection. So call map twice for each function you want to apply to all elements of the Array.

Some simple functions for demonstration:

scala> def addOne(l: Long) = l + 1
addOne: (l: Long)Long

scala> def addTwo(l: Long) = l + 2
addTwo: (l: Long)L

map the array vars using the functions defined.

scala> val vars = Array[Long](1,2,3,4,5,6,7,8,9,10)
vars: Array[Long] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> vars.map(addOne(_))
res0: Array[Long] = Array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11)

scala> vars.map(addOne(_)).map(addTwo(_))
res1: Array[Long] = Array(4, 5, 6, 7, 8, 9, 10, 11, 12, 13)

Another approach that is "more functional" and probably a good exercise is to use a recursive function that takes a function as a parameter and applies the function passed in to each element of the List.

scala> def fun[A](as: List[A], f: A => A): List[A] = as match {
     | case List() => List()
     | case h::t => f(h) :: fun(t, f)
     | }
fun: [A](as: List[A], f: A => A)List[A]

Comments

1

Consider iterating over a range of Long values,

val vars = (1L to 10L).map(someFunction).map(anotherFunction)

This applies someFunction onto each value from the range, and then each intermediate result from the first map onto anotherFunction. Assumed it is that each function takes and delivers a values of type Long.

For converting vars onto a desired collection such as Array or List consider,

vars.toArray
vars.toList

Use view to apply both functions at once onto each value in the range, hence not having to create an intermediate collection from mapping someFunction,

(1L to 10L).view.map(someFunction).map(anotherFunction)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.