asoft
sea

~ tiny vessels of code slowly floating out to sea

Powered by a motorboat called the S.S.Tumblr

1 year ago

@12:36pm

1 note
Comments

referential transparencies

Oftentimes when shifting back and forth between languages it’s easy to fudge syntactic nuances out of habit. Sometimes when you fudge you learn something new. Today I fudged some Java in my Scala.

What would you guess the return type of the following method to be?

def guess(what: String) {
   "%s? really?" format what
}

One who is used to Scala by now knows there’s no need to explicitly declare a return type, let alone use the return keyword at the end of a method thanks to this fancy pants thing called type inference.

So what’s the fuss with this simple example? It obviously returns a String, duh. WRONG.

Scala is part functional and part of that functional nature includes referential transparency.

Functional Projectors

Referential what? Databases? Overhead projectors?

So what does referential transparency mean? It’s simple.

Say you have a value v and are assigning it the result of function f which takes the argument a:

val v = f(a)

Function f is said to be referentially transparent, if you can replace all occurrences f with the the result of applying the same value a to f and always end up with the same result.

Huh?

In functional programming, the idea is that functions should be side effect free, so it’s okay to replace f(a) with just the resulting value of f(a) because your program will not modify state that would adversely affect the result of f(a).

Mixed Flavors

So what’s this have to do with fudge and Java?

As Scala has inherited some of Java’s syntax, Javaisms can creep into your Scalaisms.

Case in point:

def guess(what: String) {
   "%s? really?" format what
}

The Scala return type of this method is actually Unit. The correct way to declare this method in Scala is:

def guess(what: String) = {
   "%s? really?" format what
}

or even better (more minimal)

def guess(what: String) = "%s? really?" format what

So what changed? You assign the name of the function to the it’s functional body. If you’ve been paying attention, you’ll pick up on the fact that this is the functional style. If you are being referentially transparent the about your design you can say

val stringGuessResult = "String? really?"
val guessResult = guess("String")
stringGuessResult == guessResult

where the resulting value is always the same.

In the same manner declaration of function names follow suit.

fnNameWithValue = value
fnNameWithFunctionBody = functionBody
fnNameWithValue == fnNameWithFunctionBody

Without the assignment operator, the { ... } brackets from the previous example merely serve as a means of scoping local variables. The environment surrounding the brackets can not know what kind of scheme the local variables are plotting.

Border Crossing

This key-value concept of assigning function names to function bodies is also common in other languages. Let’s take the same example in Javascript.

As Javascript also inherited some of its syntax from C, you can declare methods in a C-like fashion

function guess(what) {
  what + "? really?"
}

You can also write this in the functional style

var guess = function(what) {
  what + "? really?"
}

Does this look familiar?

var someModule = (function(){
   return {
     guess: function(what) {
        what + "? really?"
     },
     tell: function(story) {
        "my story is "+ story
     }
   };
})();

Or even

$.ajax({ 
   url: "...", 
   context: document.body, 
   success: function() {
     alert("All done!");
   }
});

Both are use cases for using the functional style of assigning a function body to a name.

Back to Our Story

Just for fun let’s say you actually did assign and explicit return type for the previous example with out assigning the the method body.

def guess(what: String): String {
   "%s? really?" format what
}

You actually end up with a compile error.

illegal start of declaration (possible cause: missing `=' in front of current method body)

Ops! You’re Java’s showing.

Overlapping Transparencies

When you think about it, referentially transparency seems the like same idea behind vals. You are assigning some resulting value to a name which cannot change unless explicitly overridden in a sub type. For a program to be side effect free, one might say that when part of a program accesses a val, the val should always return the same referentially transparent result.

  1. asoftsea posted this
blog comments powered by Disqus