Polyglot Series in Javascript, Dart, Ruby, Python,Go: Sorting List 
Tags: javascript, dart, ruby, python
Published: 2020-05-06 07:13:42


##Preface
This is the first post of the series that will dive into my journey in exploring these languages, some of which I have years of experience (Javascript, Ruby) and those are newer to me (Dart, Go). 
As there are many aspects of programming language that we can explore and compare, my exploration will emphasize on the cookbook-style approach - how to solve common problems like sorting, filtering, etc, while comparing the unique features of the language.
I hope these posts will help new learners to get started with the languages and experienced learners alike to reinforce/refresh your understanding. 
Last but not least, your feedbacks are very welcome to help me revise these posts with more contents, alternate solutions or even better ones.

##Sorting List / Array
Scripts are located under the following path: collection/list/sort
The script has been structured with the following content:
- Sort methods can either returns a new array or modify existing one
- Sort methods with a single comparator and multiple comparators
- Sort list of string in numeric order and vice versa
- Sort a numeric list

{% replit @achristoph/pg  %}

###Javascript
- the sort method accepts the comparator function, if not specified, the elements are converted to string and ordered in UTF-16 code units order.
- if supplied, the comparator function **fn(a,b)** is expected to return:
 - a negative number for **a** order less than **b**
 - a positive number for **a** order greater than **b**
 - a zero for equal order
 - typically, -1, 1, and 0 is used to represent these values 
- In Javascript, 0 value is evaluated as false when treated as boolean. This enable a nice hack when sorting the list with multiple comparator using OR operator. So, as in the example below, if the length of a and b is equal, the returned 0 value is evaluated as false, which then execute continue to invoke the second comparator **byLowerCase**. It makes the code looks so succinct.
```javascript
c.sort((a, b) => byLength(a, b) || byLowerCase(a, b));
``` 
Another nice hack is we can take advantage of the comparator function convention to write a succinct line when sorting a numeric array by calculating the value difference of a and b. Javascript unfortunately needs this, since sort() without argument will sort by string value.

```javascript
f.sort((a, b) => a - b);
```   

###Dart
- Instead of using low-level comparator condition, Dart has a helper function **compareTo** that behaves just like the Javascript comparator
```dart
byLength(a, b) {
  return a.length.compareTo(b.length);
}
```
- When using multiple comparators, unlike Javascript, we cannot use the OR operator hack - Dart expects a literal boolean value, so the approach is to have the comparator functions in an array that will execute the next comparator if the current one is zero (equal order)
```dart
var sortFunctions = [byLength, byLowerCase];
  c.sort((a, b) {
    var i = 0;
    var r = 0;
    while (r == 0 && i < sortFunctions.length) {
      r = sortFunctions[i++](a, b);
    }
    return r;
  });
```

###Ruby
- The idiomatic Ruby gives us the 'spaceship' <=> comparator, equivalent to comparator we have seen in JS and Dart. It does look like the body of a flying saucer from the sideview :)
```ruby
def by_length(a,b)
  return a.length <=> b.length
end
```
- Unlike Javascript and Dart, both Ruby and Python have specific sort method to either modify the current array or create a new copy of sorted array. In Ruby API, the use of exclamation point at the end of method is to indicate that the method is mutating the current object instead of making a new one. I love this idiomatic. 
```ruby
a.sort! {|a,b| by_lower_case(a,b) }
```
- **sort_by** can be used to shorten the need of passing a and b. The use of ampersand colon is another idiom in Ruby to make even morse terse syntax
```ruby
a.sort! {|a,b|  a.downcase <=> b.downcase}
a.sort_by! { |e| e.downcase }
a.sort_by!(&:downcase)
```
- Ruby converts 0 to false in OR operation, so the same nice hack of Javascript can be done as well. Nice :)
```ruby
c = a.sort {|a,b|  by_length(a,b) || by_lower_case(a,b) }
```

###Python
- Python has **sorted** function to return a new sorted list and the **.sort** to modify the current list
- Instead of defining a comparator function(a,b), Python's **sort** and **sorted** have **key** argument which can specify either: a compare function or a tuple consisting the comparator functions. The shortest of all we have seen so far.

```python
b = sorted(a, key=by_lower_case)
c = sorted(a, key=(len(item), item.lower()))
```

###Go
- Go has a less straightforward way of copying a list using the **make** and **copy** combo, makes it more verbose to sort that produces a new sorted array
- Two ways to sort: 
  1. use comparator type which implements three functions: Len, Swap and Less. Multiple comparators one is not easy - need to implement a new method that consist for the logic to compare in sequential order of the comparators.
  2. use Slice function, which only needs the Less function

```go
type byLength []string

func (s byLength) Len() int {
	return len(s)
}

func (s byLength) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

func (s byLength) Less(i, j int) bool {
	return len(s[i]) < len(s[j])
}
a := []string{"Art", "b", "ART"}
c := make([]string, len(a))
copy(c, a)
sort.Sort(byLength(a))

// Slice method
f := []int{3, 1, 2}
sort.Slice(f, func(i, j int) bool {
 return f[i] < f[j]
})
```
- Unlike other languages, the string to integer conversion has the golang style of returning multiple values, two values: the value and the error if any
```go
ei, _ := strconv.Atoi(e[i])
```

##Summary
We have seen many different features of these languages, just by exploring sorting a list problem. In the sequential posts of the series, I will try to not repeat the same language feature discussion, to keep the posts simpler and more to the point, as we are getting more skilled after this first journey. Onward Polyglots!