Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Lately I've become more and more frustrated that in most modern programming languages I've worked with (C/C++, C#, F#, Ruby, Python, JS and more) there is very little, if any, language support for determining what a subroutine will actually do.

Consider the following simple pseudo-code:

var x = DoSomethingWith(y);

How do I determine what the call to DoSomethingWith(y) will actually do? Will it mutate y, or will it return a copy of y? Does it depend on global or local state, or is it only dependent on y? Will it change the global or local state? How does closure affect the outcome of the call?

In all languages I've encountered, almost none of these questions can be answered by merely looking at the signature of the subroutine, and there is almost never any compile-time or run-time support either. Usually, the only way is to put your trust in the author of the API, and hope that the documentation and/or naming conventions reveal what the subroutine will actually do.

My question is this: Does there exist any languages today that make symbolic distinctions between these types of scenarios, and places compile-time constraints on what code you can actually write?

(There is of course some support for this in most modern languages, such as different levels of scope and closure, the separation between static and instance code, lambda functions, et cetera. But too often these seem to come into conflict with each other. For instance, a lambda function will usually either be purely functional, and simply return a value based on input parameters, or mutate the input parameters in some way. But it is usually possible to access static variables from a lambda function, which in turn can give you access to instance variables, and then it all breaks apart.)

share|improve this question
    
Note that "purely functional" is ambiguous. You probably mean "pure" (free of side effects); "functional" implies a programming paradigm that treats functions as first-class objects and allows for higher-order functions. Those functions do not necessarily have to be pure, and most functional programming languages allow for impure functions. –  tdammers Jun 22 '12 at 11:20
    
That sounds like an important semantical distinction to make. What I mean with functional is in the mathematical sense, i.e. that the routine only depends on the input data, and neither reads nor writes to any other data in the program. Is "pure function" a more correct term to describe this? –  Christian Palmstierna Jun 23 '12 at 19:25
add comment

3 Answers 3

Felix has three categories it seems:

  1. functions

    There is a rule for functions: 
    
    A function introduced by a fun binder is not allowed to have any side effects.
    
    The compiler does not enforce this rule, but it does take advantage of it when
    optimising your code. 
    
  2. procedures

    Procedures do not return a value, and may and generally should have side-effects.
    
  3. generators

    A generator is a function that may have side effects.
    
share|improve this answer
    
This sounds like a language that tries to do precisely what I am after. It's unfortunate that functions aren't compiler-enforced, though (after a few years working professionally I have developed a knee-jerk mistrust for other programmers' libraries ;-)). Also, since it's so new, I might tinker with it, but it doesn't sound like a candidate for commercial/professional development :( –  Christian Palmstierna Jun 23 '12 at 19:29
add comment

C and C++ have very limited support for at least part of the problem through the const keyword; while this alone does not control purity, it can be used (especially in C++) to tell the compiler that a particular data structure is not to be modified through a given pointer. Some compilers (e.g. gcc) also provide a 'pure' attribute as a language extension to fully enforce purity. (See this question for details).

The D programming language has support for declaring the purity of functions explicitly, and compilers will check and enforce purity (that is, trying to call a non-pure function from within a pure function yields a compiler error).

Haskell is completely pure, that is, the language itself cannot express impure functions, and there is no concept of a 'routine'. Anything that cannot be solved using pure functions alone is outsourced to the (impure) runtime; a program with side effects is implemented by building (using exclusively pure constructs) a lazy data structure that describes the program behavior, and then handing it to the runtime. The Haskell community is actively experimenting with a whole zoo of programming languages, some of them pure, others with explicit purity.

There may be more, but these are the ones I'm familiar with.

share|improve this answer
    
gcc does support explicit declarations of purity as an extension like so –  Useless Jun 22 '12 at 12:23
    
@Useless: thanks, useful hint. Edited. –  tdammers Jun 22 '12 at 12:44
    
C++'s const member functions do control purity, if your classes have no non-const member functions. All data becomes constant, and then everything is pure functional. –  tp1 Jun 22 '12 at 18:27
    
@tp1: Not quite. A const member function can easily produce side effects by calling non-const static methods of other classes, instantiating other classes, or simply calling free functions or modifying global variables. It only works if you lock down your entire codebase to all-const, including all the libraries you use (even STL). –  tdammers Jun 22 '12 at 19:30
    
@tdammers: The all-const lock down is not very bad since the data can be initialized to different values by constructor parameters. But it does require all your data be located inside your classes and not in global variables. –  tp1 Jun 22 '12 at 19:36
show 3 more comments

Yes, you want to look at Haskell. It does exactly what you want. All functions are pure by default and can only mutate state by using Monads. Also Haskell has very strong static guarantees about all sorts of things http://learnyouahaskell.com/

share|improve this answer
    
Ah! I've heard a lot of good things about Haskell, but haven't gotten around to looking deeply into it. Maybe it will fit my bill :) –  Christian Palmstierna Jun 22 '12 at 11:13
    
It seems to be where a lot of interesting things are going on –  Zachary K Jun 22 '12 at 11:17
5  
Monads cannot mutate state any more than other data types; they are bound by the same purity constraints as the rest of the language. After all, there is nothing special about them, apart from some syntax sugar. What they can do is provide a convenient abstraction over code that accumulates state through chained or recursive function calls, and when compiled against the runtime, such code boils down to imperative code similar to what the monadic code looks like. It's still an abstraction though, and the code is still 100% pure. –  tdammers Jun 22 '12 at 11:18
4  
Also, functions aren't pure by default, they are pure, period. Haskell cannot express impure functions. –  tdammers Jun 22 '12 at 11:21
3  
@CPX: There are at least three industry-strength web frameworks for Haskell (Yesod, Happstack, and Snap), and an abundance of libraries for practically all the tasks you mention (not sure about SOAP though); the average code quality within the Haskell ecosystem tends to be excellent. The biggest problem I can forsee is finding enough programmers to support such a thing over a longer maintenance period. –  tdammers Jun 22 '12 at 12:39
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.