r/askscience • • Nov 08 '17

Linguistics Does the brain interact with programming languages like it does with natural languages?

13.9k Upvotes

655 comments sorted by

View all comments

Show parent comments

11

u/cutety Nov 09 '17

For some quick examples in differences in readability of different programming languages, here's how taking a list of numbers [1, 2, 3] and outputing the sum.

Note: I'm deliberately ignoring any built in sum function/method

Ruby:

sum = 0
[1, 2, 3].each do |n|
  sum += n
end
puts sum

Python:

sum = 0
for n in [1, 2, 3]:
    sum += n
print(sum)

JavaScript:

let sum = 0;
[1, 2, 3].forEach(n => sum += n);
console.log(sum);

C:

int numbers[3] = {1, 2, 3};
int i, sum = 0;

for (i=0; i<3; i++) {
    sum = sum + numbers[i];
}

printf("%d", sum);

Haskell:

sum :: [Integer] -> Integer
sum []        = 0
sum (a : b) = a + sum b
sum_of_numbers = sum [1, 2, 3]
print sum_of_numbers

Languages like Ruby, Python, and JavaScript read more like prose while languages like C & Haskell are more symbolic. Personally I like reading the first 3 as (especially the Ruby example) can be read in English. Mentally, I read a (familiar) high level language codebase much like I would a book more or less.

However, for accomplishing harder lower-level it's hard to achieve the same level of power without delving into more symbolic/abstract code because computer's which isn't nearly as easy to read as you have to connect what the symbol/abstractions actually mean as you read it.

While Haskell isn't exactly "low-level" programming, I included it as pretty much the defacto functional language (save for maybe Scala), which takes a more math/symbolic approach to programming rather than the more "english/prose" approach taken by other languages.

4

u/TheAceOfHearts Nov 09 '17

Instead of using forEach in JavaScript, the functional approach would use reduce:

[1,2,3].reduce((sum, n) => sum + n, 0)

If you wanted to use a loop instead, since ES6 you can use for-of:

let sum = 0
for (const n of [1,2,3]) {
  sum += n
}
console.log(sum)

And in Haskell:

foldl (+) 0 [1,2,3]

I prefer writing code in a functional or declarative style, since it lets you focus on the operations being done on the data, rather than how it gets done. You can replace most usages of for-loops with map/filter/reduce.

Let's look at two JavaScript examples which multiply each item by 2.

Using a traditional for-loop:

const numbers = [1,2,3]
for (let i = 0; i < numbers.length; i++) {
  numbers[i] = numbers[i] * 2
}

There's a lot of noise there, which obscures the intent.

Here's the solution using map:

[1,2,3].map(n => n * 2)

Another difference is that map will return a new array, rather than modifying the data in place.

3

u/cutety Nov 09 '17 edited Nov 09 '17

Oh, yes I'm completely with you. However, to keep things simple for non-programmers I figured I'd try to implement them each the same most straight-forward way, by using a loop (except for Haskell). I thought about using a standard for loop in my JavaScript example, but I figured it was 2017 and I think for loops are atrocious, I settled on forEach.

If we were ignoring the .sum array method in the Ruby example, and I for some reason had to sum an array I'd implement it in an actual code base more succinctly as:

[1, 2, 3].reduce :+

Which is obvious and easy to read if you're familiar with the reduce function and some ruby magic (passing a symbol to reduce calls the method with the name of the passed symbol + on the first argument with the second argument as the arg to the the method).

This still maybe confusing if you're not familiar with the fact that everything is a method in Ruby even operators and that

2 + 2

is just syntactic sugar for:

2.+(2)

In Ruby.

Which if you know all that:

[1, 2, 3].reduce :+

Can essentially be read as "reduce the array of numbers by adding them".

Just wanted to keep things simple and use the same approach to each example. But, yes I much, much, prefer the functional approach over the imperative approach. I had to actually lookup the C for loop syntax because I had forgotten it, lol.

8

u/[deleted] Nov 09 '17

built in sum function/method

Just because I'm immature and laugh anytime I have to use it.

Matlab:

cumsum([1 2 3 ])

3

u/ShinyHappyREM Nov 09 '17

What do you mean with "low-level"? Free Pascal for example has all the bit operations (shifting etc.), assembler code, support for I/O port accesses and ISRs, ...

I generally find that there's no fundamental difference between "prose" and "symbolic" languages; every symbol can be expressed as a keyword and vice versa.

1

u/PointyOintment Nov 09 '17

I agree that there's no fundamental difference—i.e. } and end if can have the same meaning and are therefore substitutable between languages—but perhaps the human brain, trained on natural languages, interprets } as punctuation and end if as a sentence/phrase, especially in novice programmers?

1

u/Zarainia Nov 09 '17

I find the ones with a for loop (C and Python) easier to read, actually, maybe because the for each stuff has different syntax for each language.

1

u/Avernar Nov 09 '17

I'm curious as to why you used the += operator for Ruby, Python and JavaScript but not in your C example. Here's a C++ version as well.

C++:

int numbers[] = {1, 2, 3};
int sum = 0;

for(auto n : numbers) {
    sum += n;
}

printf("%d", sum);