Why is "reduce" an infix operator in Chapel? - reduction

According to this manual page, we can use reduce to perform reduction like
summation (+):
var a = (+ reduce A) / num;
var b = + reduce abs(A);
var c = sqrt(+ reduce A**2);
and maximum value/location:
var (maxVal, maxLoc) = maxloc reduce zip(A, A.domain);
Here, Chapel defines reduce to be an infix operator rather than a function (e.g., reduce( A, + )). IMHO, the latter form seems to be a bit more readable because the arguments are always separated by parentheses. So I am wondering if there is some reason for this choice (e.g., to simplify some parallel syntax) or just a matter of history (convention)?

I'd say the answer is a matter of history / convention. A lot of Chapel's array and domain features were heavily inspired by the ZPL language from the University of Washington, and I believe this syntax was taken reasonably directly from ZPL.
At the time, we didn't have a notion of passing things like functions and operators around in Chapel, which is probably one of the reasons that we didn't consider more of a function-based approach. (Even now, first-class function support in Chapel is still somewhat in its infancy, and I don't believe we have a way to pass operators around).
I'd also say that Chapel is a language that generally favors syntax for key patterns rather than taking more of a "make everything look like a function / method call" approach (e.g., ranges are supported via a literal syntax and several key operators rather than using an object type with methods).
None of this is to say that the choice was obviously right or couldn't be reconsidered.

Related

Should I ever prefer operators overloading over functions/methods?

I feel like using operators overloading adds unnecessary complexity and ambiguity to the code.
Does it have its benefits in real-world cases where it's worth to use custom operators or overload existing operators instead of using functions or object methods?
Is it used on a regular basis or more just a funny exotic stuff to add a language a bit more hipness?
The main reason for overloading is comfort of using custom class with mathematic or logic background
like:
vectors
matrices
complex numbers
phasors,tensors,quaternions,...
finite fields
big-numbers (arbnum,biginteger,bigdecimal...)
custom precision floating and fixed formats
predicates,boolean,fuzy and probabilistic
strings,lists,ques
and much much more
If coded right you can write math equations directly and not bother to convert to set of function calls. The reading and understanding math code is much simpler and straightforward with operators.
Sometimes even non strictly math classes are used this way for example images or signals. In DIP/CV there are usually math/physics equations applied on those and overloaded operators make that more simple.
For the non-math classes
are operators usually useless/meaningless (as you feel) except for special operator= which is crucial for any class/struct with dynamic allocation members. Without it things like std:vector<> will not work properly.
Another example are comparison operators which are sometimes implemented for non math classes to make sorting easier.
from wiki
operator overloading—less commonly known as operator ad hoc polymorphism—is a specific case of polymorphism, where different operators have different implementations depending on their arguments
Swift has over 40 operators, all of them are overloaded and we are using them on regular bases. Do you prefer let sum = value.plus(anotherValue) over let sum = value + anotherValue ?? I am sure, you don't! If the value is custom type conforming to protocol Equatable, == operator must be overloaded and we do it regularly.
Is it a good idea to use custom defined operators (like ±, <*> etc ...)? In that area I am not sure. I am not big fan of this ...
Is it a good idea to overload + operator for something else than sum ? No, definitely not!

for vs map in functional programming

I am learning functional programming using scala. In general I notice that for loops are not much used in functional programs instead they use map.
Questions
What are the advantages of using map over for loop in terms of performance, readablity etc ?
What is the intention of bringing in a map function when it can be achieved using loop ?
Program 1: Using For loop
val num = 1 to 1000
val another = 1000 to 2000
for ( i <- num )
{
for ( j <- another)
{
println(i,j)
}
}
Program 2 : Using map
val num = 1 to 1000
val another = 1000 to 2000
val mapper = num.map(x => another.map(y => (x,y))).flatten
mapper.map(x=>println(x))
Both program 1 and program 2 does the same thing.
The answer is quite simple actually.
Whenever you use a loop over a collection it has a semantic purpose. Either you want to iterate the items of the collection and print them. Or you want to transform the type of the elements to another type (map). Or you want to change the cardinality, such as computing the sum of the elements of a collection (fold).
Of course, all that can also be done using for - loops but to the reader of the code, it is more work to figure out which semantic purpose the loop has, compared to a well known named operation such as map, iter, fold, filter, ...
Another aspect is, that for loops lead to the dark side of using mutable state. How would you sum the elements of a collection in a for loop without mutable state? You would not. Instead you would need to write a recursive function. So, for good measure, it is best to drop the habit of thinking in for loops early and enjoy the brave new functional way of doing things.
I'll start by quoting Programming in Scala.
"Every for expression can be expressed in terms of the three higher-order functions map, flatMap and filter. This section describes the translation scheme, which is also used by the Scala compiler."
http://www.artima.com/pins1ed/for-expressions-revisited.html#23.4
So the reason that you noticed for-loops are not used as much is because they technically aren't needed, and any for expressions you do see are just syntactic sugar which the compiler will translate into some equivalent. The rules for translating a for expression into a map/flatMap/filter expression are listed in the link above.
Generally speaking, in functional programming there is no index variable to mutate. This means one typically makes heavy use of function calls (often in the form of recursion) such as list folds in place of a while or for loop.
For a good example of using list folds in place of while/for loops, I recommend "Explain List Folds to Yourself" by Tony Morris.
https://vimeo.com/64673035
If a function is tail-recursive (denoted with #tailrec) then it can be optimized so as to not incur the high use of the stack which is common in recursive functions. In this case the compiler can translate the tail-recursive function to the "while loop equivalent".
To answer the second part of Question 1, there are some cases where one could make an argument that a for expression is clearer (although certainly there are cases where the opposite is true too.) One such example is given in the Coursera.org course "Functional Programming with Scala" by Dr. Martin Odersky:
for {
i <- 1 until n
j <- 1 until i
if isPrime(i + j)
} yield (i, j)
is arguably more clear than
(1 until n).flatMap(i =>
(1 until i).withFilter(j => isPrime(i + j))
.map(j => (i, j)))
For more information check out Dr. Martin Odersky's "Functional Programming with Scala" course on Coursera.org. Lecture 6.5 "Translation of For" in particular discusses this in more detail.
Also, as a quick side note, in your example you use
mapper.map(x => println(x))
It is generally more accepted to use foreach in this case because you have the intent of side-effecting. Also, there is short hand
mapper.foreach(println)
As for Question 2, it is better to use the map function in place of loops (especially when there is mutation in the loop) because map is a function and it can be composed. Also, once one is acquainted and used to using map, it is very easy to reason about.
The two programs that you have provided are not the same, even if the output might suggest that they are. It is true that for comprehensions are de-sugared by the compiler, but the first program you have is actually equivalent to:
val num = 1 to 1000
val another = 1000 to 2000
num.foreach(i => another.foreach(j => println(i,j)))
It should be noted that the resultant type for the above (and your example program) is Unit
In the case of your second program, the resultant type of the program is, as determined by the compiler, Seq[Unit] - which is now a Seq that has the length of the product of the loop members. As a result, you should always use foreach to indicate an effect that results in a Unit result.
Think about what is happening at the machine-language level. Loops are still fundamental. Functional programming abstracts the loop that is implemented in conventional programming.
Essentially, instead of writing a loop as you would in conventional or imparitive programming, the use of chaining or pipelining in functional programming allows the compiler to optimize the code for the user, and map is simply mapping the function to each element as a list or collection is iterated through. Functional programming, is more convenient, and abstracts the mundane implementation of "for" loops etc. There are limitations to this convenience, particularly if you intend to use functional programming to implement parallel processing.
It is arguable depending on the Software Engineer or developer, that the compiler will be more efficient and know ahead of time the situation it is implemented in. IMHO, mid-level Software Engineers who are familiar with functional programming, well versed in conventional programming, and knowledgeable in parallel processing, will implement both conventional and functional.

Cost in Scala of iteratively manipulating functions rather than simpler types

Having spent some time exploring Haskell, I've become used to building and manipulating chains of functions - and to assessing how this will perform in non-strict evaluation. I realise I do not understand well how that style performs in Scala.
To take a simple example, imagine that the Scala List had no append method. You could concatenate two lists of integers like this:
xs.reverse.foldLeft(ys)(_.::(_))
(Yes, I know Scala recently changed foldRight so that it just does reverse.foldLeft. sigh)
An alternative is to build up a function chain like this:
xs.foldLeft(identity[List[Int]] _)((f, a) => f compose (a :: _)) (ys)
In non-strict Haskell, the second approach is often better because it is "productive" and the entire chain will not necessarily be evaluated (I know, in Haskell you would just use a right fold for this). But in Scala, these two approaches will perform similarly. Both are O(n). Both are effectively creating a reversed collection on the heap and then iteratively consing that onto ys (you can think of the second style as creating a linked list of functions).
I have a general inclination towards the second style, but my question is: are there hidden gotchas (performance penalties I had not considered, significantly higher heap usage, that kind of thing) in this approach? In Scala, what factors should I keep in mind (other than code readability) when choosing between manipulating data or functions?

What is the difference between = and := in Scala?

What is the difference between = and := in Scala?
I have googled extensively for "scala colon-equals", but was unable to find anything definitive.
= in scala is the actual assignment operator -- it does a handful of specific things that for the most part you don't have control over, such as
Giving a val or var a value when it's created
Changing the value of a var
Changing the value of a field on a class
Making a type alias
Probably others
:= is not a built-in operator -- anyone can overload it and define it to mean whatever they like. The reason people like to use := is because it looks very assignmenty and is used as an assignment operator in other languages.
So, if you're trying to find out what := means in the particular library you're using... my advice is look through the Scaladocs (if they exist) for a method named :=.
from Martin Odersky:
Initially we had colon-equals for assignment—just as in Pascal, Modula, and Ada—and a single equals sign for equality. A lot of programming theorists would argue that that's the right way to do it. Assignment is not equality, and you should therefore use a different symbol for assignment. But then I tried it out with some people coming from Java. The reaction I got was, "Well, this looks like an interesting language. But why do you write colon-equals? What is it?" And I explained that its like that in Pascal. They said, "Now I understand, but I don't understand why you insist on doing that." Then I realized this is not something we wanted to insist on. We didn't want to say, "We have a better language because we write colon-equals instead of equals for assignment." It's a totally minor point, and people can get used to either approach. So we decided to not fight convention in these minor things, when there were other places where we did want to make a difference.
from The Goals of Scala's Design
= performs assignment. := is not defined in the standard library or the language specification. It's a name that is free for other libraries or your code to use, if you wish.
Scala allows for operator overloading, where you can define the behaviour of an operator just like you could write a method.
As in other languages, = is an assignment operator.
The is no standard operator I'm aware of called :=, but could define one with this name. If you see an operator like this, you should check up the documentation of whatever you're looking at, or search for where that operator is defined.
There is a lot you can do with Scala operators. You can essentially make an operator out of virtually any characters you like.

The case for point free style in Scala

This may seem really obvious to the FP cognoscenti here, but what is point free style in Scala good for? What would really sell me on the topic is an illustration that shows how point free style is significantly better in some dimension (e.g. performance, elegance, extensibility, maintainability) than code solving the same problem in non-point free style.
Quite simply, it's about being able to avoid specifying a name where none is needed, consider a trivial example:
List("a","b","c") foreach println
In this case, foreach is looking to accept String => Unit, a function that accepts a String and returns Unit (essentially, that there's no usable return and it works purely through side effect)
There's no need to bind a name here to each String instance that's passed to println. Arguably, it just makes the code more verbose to do so:
List("a","b","c") foreach {println(_)}
Or even
List("a","b","c") foreach {s => println(s)}
Personally, when I see code that isn't written in point-free style, I take it as an indicator that the bound name may be used twice, or that it has some significance in documenting the code. Likewise, I see point-free style as a sign that I can reason about the code more simply.
One appeal of point-free style in general is that without a bunch of "points" (values as opposed to functions) floating around, which must be repeated in several places to thread them through the computation, there are fewer opportunities to make a mistake, e.g. when typing a variable's name.
However, the advantages of point-free are quickly counterbalanced in Scala by its meagre ability to infer types, a fact which is exacerbated by point-free code because "points" serve as clues to the type inferencer. In Haskell, with its almost-complete type inferencing, this is usually not an issue.
I see no other advantage than "elegance": It's a little bit shorter, and may be more readable. It allows to reason about functions as entities, without going mentally a "level deeper" to function application, but of course you need getting used to it first.
I don't know any example where performance improves by using it (maybe it gets worse in cases where you end up with a function when a method would be sufficient).
Scala's point-free syntax is part of the magic Scala operators-which-are-really-functions. Even the most basic operators are functions:
For example:
val x = 1
val y = x + 1
...is the same as...
val x = 1
val y = x.+(1)
...but of course, the point-free style reads more naturally (the plus appears to be an operator).