Functional programming

J

Jon Harrop

Has anyone here tried any statically-typed functional programming languages
that target the JVM?

Languages like Scala seem to couple the enormous benefits of functional
programming with Java interoperability. However, the JVM provides little
support for modern languages and I'd like to know how popular these
languages are and how well they work.

Also, would any existing Java programmers be interested in learning
Java-compatible functional languages?
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Jon said:
Has anyone here tried any statically-typed functional programming languages
that target the JVM?

Languages like Scala seem to couple the enormous benefits of functional
programming with Java interoperability. However, the JVM provides little
support for modern languages and I'd like to know how popular these
languages are and how well they work.

Also, would any existing Java programmers be interested in learning
Java-compatible functional languages?

I think functional programming is a popular among Java programmers
as it is among other programmers - it is not popular at all. It is
an academic thing.

You can find a ton of languages at
http://www.robert-tolksdorf.de/vmlanguages.html
and try them out and see what you like.

Arne
 
D

Daniel Dyer

Has anyone here tried any statically-typed functional programming
languages
that target the JVM?

No. I've used Haskell (and, before that, Miranda at university), but not
on the JVM. There is an effort underway to bring Haskell to the JVM
(http://www.cs.rit.edu/~bja8464/lambdavm/).
Languages like Scala seem to couple the enormous benefits of functional
programming with Java interoperability. However, the JVM provides little
support for modern languages and I'd like to know how popular these
languages are and how well they work.

JSR 292 (http://jcp.org/en/jsr/detail?id=292) is extending the JVM to make
it more suitable for other languages. However, it is concerned with
dynamically-typed languages rather than statically-typed ones. There are
dozens (hundreds?) of languages available for the JVM, so it would seem to
be adequate for most.
Also, would any existing Java programmers be interested in learning
Java-compatible functional languages?

I'm not convinced that Java-compatibility is that important. I would be
interested in langauges that combine OO and FP advantages, but whether
that's something that runs on the JVM (like Scala) or something that
doesn't (like OCaml), isn't that important to me. I don't want to write C
programs in Java (JNI is always something to be avoided), I doubt I'd want
to write Java programs in a functional language.

Dan.
 
B

bugbear

Daniel said:
I'm not convinced that Java-compatibility is that important. I would be
interested in langauges that combine OO and FP advantages, but whether
that's something that runs on the JVM (like Scala) or something that
doesn't (like OCaml), isn't that important to me. I don't want to write
C programs in Java (JNI is always something to be avoided), I doubt I'd
want to write Java programs in a functional language.

Having a.n. other language on the JVM is useful,
if only because it renders the hosted language
as portable as the JVM.

BugBear
 
J

Jon Harrop

Lew said:
Excuse me? I do believe you need evidence to support such an outrageous
claim.

That is certainly the impression I had too. AFAIK, the JVM doesn't even
support tail calls let alone a useful representation of parametric
polymorphism etc. so you're looking at something like CPS, seriously
obfuscated interoperability and terrible performance.

Am I right in remembering that Java's implementation of generics is more
than a bit broken and they are just now adding a bad implementation of
closures on top of it?
 
J

Jon Harrop

Arne said:
I think functional programming is a popular among Java programmers
as it is among other programmers - it is not popular at all. It is
an academic thing.

SQL, Yacc, LINQ, Excel and XSLT are hardly just "academic things".
 
T

Twisted

SQL, Yacc, LINQ, Excel and XSLT are hardly just "academic things".

Yes, but lisp, scheme, Haskell, OCaml, and APL are.

The practical world has put functional languages in their place --
academia, and occasionally specialized functions (often preprocessing
or document preparation, or other naturally-largely-stateless tasks).
 
T

Twisted

Am I right in remembering that Java's implementation of generics is more
than a bit broken and they are just now adding a bad implementation of
closures on top of it?

It already HAS an implementation of closures. An anonymous inner class
method. These can modify local variables in their enclosing lexical
scope IF those local variables are actually the elements of one-
element local final arrays, and they can even return from their
lexical scope IF they throw an appropriate exception that the
enclosing method catches and regards as telling it to return (and,
perhaps, return the contents of one of those one-element arrays).

Admittedly, it's a questionable implementation of closures. :)
 
J

Jon Harrop

Twisted said:
Yes, but lisp, scheme, Haskell, OCaml, and APL are.

Ruby? Javascript?
The practical world has put functional languages in their place --
academia, and occasionally specialized functions (often preprocessing
or document preparation, or other naturally-largely-stateless tasks).

Mathematica (is a functional language), Matlab (its FFT routines are written
primarily in OCaml), Windows (driver verification done in OCaml)...
 
T

Twisted

Ruby? Javascript?

They both have assignment statements and suchlike with side effects.
Mathematica (is a functional language), Matlab (its FFT routines are written
primarily in OCaml), Windows (driver verification done in OCaml)...

Re: having their place in specialized functions, I rest my case. Math
software internal languages, driver verification...what else are
these?
 
J

Jon Harrop

Twisted said:
They both have assignment statements and suchlike with side effects.

Then you are referring to a subset of functional programming languages known
as "purely functional" languages.

Javascript, Ruby, Lisp, Scheme, OCaml, F#, Scala and Nemerle are all impure
functional languages: they allow side-effecting statements just like C,
C++, Java and C#.
Re: having their place in specialized functions, I rest my case. Math
software internal languages, driver verification...what else are
these?

Practical applications covering almost all areas of programming from
scientific computing to GUI and web programming.

What "general purpose" tasks do you believe can be done in Java but not in
Scala or F#, for example?
 
T

Twisted

Then you are referring to a subset of functional programming languages known
as "purely functional" languages.

Jeez, will you just stop arguing with me and give it a rest already?

If you're not talking about what you call "purely functional"
programming languages when you mention "functional programming
languages" then what are you talking about? It sounds like it would
have to be either an arbitrary split, with languages considered
"functional" or not by fiat or dice toss, or else a trivial one, with
languages considered "functional" if they have function calls of some
sort, which as far as I am aware excludes assembly, BASIC, one or two
scripting languages, COBOL, and a few other, mostly obsolete,
languages. Arguably BASICs with "gosub" are functional, if they
support passing parameters and returning values with a stack of some
kind. Visual BASIC definitely has functions, and therefore enables a
functional style to be used in places.

Perhaps you mean languages with functions as first-class objects?
Well, that still nets you C, C++, and Java, as well as most other
modern languages. C has function pointers. C++ adds the ability to
overload operator() and make function-like objects of various sorts
that may be mutable. Java obviously allows you to use an interface to
define a function-like object (Comparator comes to mind, and it's
found in the standard library classes) and has anonymous inner
classes, which combination allows anonymous lambdas (and even a kludgy
form of closures, given a little exception throwing abuse).
Javascript, Ruby, Lisp, Scheme, OCaml, F#, Scala and Nemerle are all impure
functional languages: they allow side-effecting statements just like C,
C++, Java and C#.

This further erodes whatever distinction you were looking to make
between functional languages and non-. It's starting to look like
we're not even discussing the same dividing line that the discussion
started with. That one was clearly dividing a set of languages like
Lisp with mostly academic interest from a set used widely in practical
applications as general-purpose coding languages. Your own definition
of "functional" doesn't correspond to this division, although the OP's
definition of "functional" clearly did.

It might be best if we came to some kind of agreement on the
definitions of terms and then made sure we were arguing about the same
thing before continuing. I continue to agree with the OP that whatever
you call the original division, the language subset on one side of it
sees chiefly academic use, and use in specialized functions within
software chiefly written in languages on the other side, rather than
to develop full-blown practical applications in.
Practical applications covering almost all areas of programming from
scientific computing to GUI and web programming.

What "general purpose" tasks do you believe can be done in Java but not in
Scala or F#, for example?

Technically, none, since they're all Turing complete I assume. But in
practise, just about any sort of application can be written in Java
with a minimum of fuss. Try using almost any of the "academic"
languages (or whatever you want to call them; apparently not
"functional") and you'll probably be able to manage a clunky console
app with an IRC-like interaction style at best. Suitable for eliza,
batch conversion tools, and probably little else. Having all memory be
either read-only or write-only is especially constraining on any
complex and stateful job, I'd expect (and what you term "purely
functional" languages and many of the others in the "academic"
grouping tend to do this; the lack of side effects, except to write-
only things like the standard output stream, means that "everything is
a temporary" or thereabouts). The sort of functional languages
originally under discussion seem to be better suited to writing
*functions*, calculation methods that are called by an embedding
software application written in something else, rather than entire
applications. And such a role does, you must admit, make a certain
amount of sense...
 
J

Jon Harrop

Twisted said:
If you're not talking about what you call "purely functional"
programming languages when you mention "functional programming
languages" then what are you talking about?

Functional programming languages are divided into purely functional
(Miranda, Clean, Haskell etc.) and impure (Lisp, Scheme, Erlang, OCaml,
Standard ML, F#, Scala, Nemerle etc.).

I was referring to all functional programming languages but you are quite
correct that the impure functional programming languages are more widely
used in industry.
It sounds like it would
have to be either an arbitrary split, with languages considered
"functional" or not by fiat or dice toss,

Functional programming languages support first-class functions => closures,
higher-order functions and currying.

A closure is a function and its environment.

A higher-order function is a function that accepts a closure/function as an
argument.

A curried function is a function that returns a function as its result.
or else a trivial one, with
languages considered "functional" if they have function calls of some
sort, which as far as I am aware excludes assembly, BASIC, one or two
scripting languages, COBOL, and a few other, mostly obsolete,
languages.

Those are procedural languages.
Arguably BASICs with "gosub" are functional, if they
support passing parameters and returning values with a stack of some
kind. Visual BASIC definitely has functions, and therefore enables a
functional style to be used in places.

BASIC does not support any of the features that I listed.
Perhaps you mean languages with functions as first-class objects?
Well, that still nets you C, C++, and Java, as well as most other
modern languages. C has function pointers.

Function pointers are not closures: they cannot carry environment.
C++ adds the ability to
overload operator() and make function-like objects of various sorts
that may be mutable.

Function objects are an OO design pattern that has some of the benefits of
functional programming, yes. However, C++ does not provide reliable garbage
collection and does not automate the capturing of a closure's environment.
Java obviously allows you to use an interface to
define a function-like object (Comparator comes to mind, and it's
found in the standard library classes) and has anonymous inner
classes, which combination allows anonymous lambdas (and even a kludgy
form of closures, given a little exception throwing abuse).

Java does at least have garbage collection but it doesn't capture the
environment of a closure for you (you must determine free variables
yourself, write the code implementing their storage and keep it up-to-date
manually).
It might be best if we came to some kind of agreement on the
definitions of terms and then made sure we were arguing about the same
thing before continuing. I continue to agree with the OP that whatever
you call the original division, the language subset on one side of it
sees chiefly academic use, and use in specialized functions within
software chiefly written in languages on the other side, rather than
to develop full-blown practical applications in.

Google for applications written in Mathematica, Ruby, OCaml, Lisp and
Erlang, for example.
Technically, none, since they're all Turing complete I assume. But in
practise, just about any sort of application can be written in Java
with a minimum of fuss.

Try translating some simple examples that use features that are not provided
by Java. For example, pattern matching can be used to manipulate concrete
data structures and is provided in all modern functional programming
languages.

This is part of the code used to generate our website from literate
programs:

let parse_command (state, para, doc as accu) line =
match Str.split (Str.regexp_string " ") line with
| "\\title" :: words ->
let title = String.concat " " words in
doc_title := title;
`Text, [], elt "h1" [text title] :: flush accu
| "\\sub" :: words ->
let title = String.concat " " words in
`Text, [], elt "h2" [text title] :: flush accu
| "\\subsub" :: words ->
let title = String.concat " " words in
`Text, [], elt "h3" [text title] :: flush accu
| ["\\text"] -> `Text, [], flush accu
| ["\\code"] -> `Code, [], flush accu
| _ -> failwith("Unknown command: \""^line^"\"")

This is some of the code used to typeset my book OCaml for Scientists:

let rec morph = function
SPECIAL "\\SpecialChar"::SPACE::STRING "~"::CR::t ->
SPECIAL "\\SpecialChar"::SPACE::STRING "~"::CR::(morph t)
| SPECIAL "\\begin_inset"::SPACE::STRING "Quotes"::SPACE::STRING s::CR::
SPECIAL "\\end_inset"::SPACE::CR::CR::t ->
SPECIAL "\\begin_inset"::SPACE::STRING "Quotes"::SPACE::STRING s::CR::
SPECIAL "\\end_inset"::SPACE::CR::CR::(morph t)
| SPECIAL "\\begin_inset"::t ->
incr level;
SPECIAL "\\begin_inset"::(inset morph t)
| SPECIAL "\\layout"::SPACE::STRING
("Chapter" | "Section" | "Subsection" | "S
ubsubsection" as heading)::CR::CR::CR::t ->

Here is some of the code from our high-performance 2D vector graphics
library Smoke:

let rec aux i len segs = match i, len, segs with
0, 0, [] ->
last_invalidate ();
segs'
| 0, 0, (seg :: _ as segs) ->
(** Replacing a segment invalidates the next. *)
Segment.invalidate_caches seg;
segs' @ segs
| 0, len, (_ :: segs) ->
aux 0 (len - 1) segs
| i, len, (seg :: segs) ->
seg :: aux (i - 1) len segs
| _, _, [] -> failwith "Internal error: Contour.replace" in

All of these snippets show commercial uses of OCaml that are substantially
more difficult to write in languages that don't have pattern matching, like
Java. This is why my company uses functional programming languages almost
exclusively, not just in the development of our products but also in the
general running of our company (e.g. our website).
Try using almost any of the "academic"
languages (or whatever you want to call them; apparently not
"functional") and you'll probably be able to manage a clunky console
app with an IRC-like interaction style at best.

I use functional programming languages every day to write graphical
programs.

Our real-time hardware-accelerated zooming GUI is written entirely in the
functional programming language OCaml:

http://www.ffconsultancy.com/products/smoke_vector_graphics/tiger.html

Our scientific visualization library is written entirely in Microsoft's
functional programming language F#:

http://www.ffconsultancy.com/products/fsharp_for_visualization/

Lisp, Scheme, OCaml, Haskell, F# and Scala all have GUI libraries. Scala
compiles to the JVM so it provides strictly more than Java. F# compiles
to .NET so it provides strictly more than VB and C#.
Suitable for eliza,
batch conversion tools, and probably little else. Having all memory be
either read-only or write-only is especially constraining on any
complex and stateful job,

On the contrary, the use of immutable data structures simplifies complex
tasks because you don't need to worry about undoing state changes.

Concurrency is a good example (of growing importance). This is why the
Google search engine is based upon purely functional programming constructs
(map-reduce).
I'd expect (and what you term "purely
functional" languages and many of the others in the "academic"
grouping tend to do this; the lack of side effects, except to write-
only things like the standard output stream, means that "everything is
a temporary" or thereabouts).

Impure functional programming languages do not have that problem: you can
use mutation whenever you want. In practice, all good programmers try to
avoid unnecessary mutation, global variables and so on.
The sort of functional languages
originally under discussion seem to be better suited to writing
*functions*, calculation methods that are called by an embedding
software application written in something else, rather than entire
applications.

There is no logical reason to assume that support for functional programming
somehow inhibits application programming. Here are some examples of free
GUI applications written in OCaml:

http://mldonkey.sourceforge.net/Main_Page
http://www.chez.com/prigaux/mathplot.html
http://ara.alioth.debian.org/
http://www.cis.upenn.edu/~bcpierce/unison/

If you Google you will find many more.
And such a role does, you must admit, make a certain
amount of sense...

Most of these languages take all of the features of Java and C# and simply
add more. For a wide-variety of applications, Java programmers would be
better off using something like Scala simply because it is better in every
respect. Hence my original question about which functional languages a Java
programmer would consider.
 
S

Stefan Ram

Jon Harrop said:
Functional programming languages are divided into purely functional
(Miranda, Clean, Haskell etc.) and impure (Lisp, Scheme, Erlang, OCaml,
Standard ML, F#, Scala, Nemerle etc.).
let parse_command (state, para, doc as accu) line =

I wrote a purely functional parser in Java once for fun.

That is, all assignments are final, thus, there are no
storage modifications. No side effects used anywhere
(except in the test code and in the debug code, which
does the side-effect of printing.) Code is given below.

The building scheme of the »functional« methods
of the scanner and parser below is always like:

let x0 = ...
x1 = ...
x2 = ...
in ...

which, in Java, is written as

{ final x0 = ...;
final x1 = ...;
final x2 = ...;
return ...; }

(When replying to my post, please do not quote my complete
post, but only those parts you directly refer to.
Especially, please do not quote the complete source code.)

public class List
{
// implementation of a dotted pair

private final int car; private final List cdr;
List( final int car, final List cdr ){ this.car = car; this.cdr = cdr; }

// That was the actual class »List«
// The rest are static methods.

// support for lists

private static final boolean DEBUG = false;
static List cons( final int car, final List cdr )
{ return new List( car, cdr ); }
static int fst( final List l ){ return l == null ? INVALID : l.car; }
static List rest( final List l ){ return l == null ? null : l.cdr; }
static int snd( final List l ){ return fst( rest( l )); }
static int caddr( final List l ){ return fst( rest( rest( l ))); }
static List cddr( final List l ){ return rest( rest( l )); }
static List cdddr( final List l ){ return rest( cddr( l )); }
static String prints( final List l )
{ return l == null ? "" : "" + name( fst( l ))+ ", " + prints( rest( l )); }
static List print( final List l )
{ if( DEBUG )System.out.println( "( "+ prints( l ) + " )" ); return l; }
static List print( final String s, final List l )
{ if( DEBUG )System.out.println( s + "( "+ prints( l ) + " )" ); return l; }

// main with some test cases

public static void main( String[] args )
{ System.out.println( "" + evaluate( "(3+4)*2" ) + " [14]." );
System.out.println( "" + evaluate( "2*10" ) + " [20]." );
System.out.println( "" + evaluate( "(9+9)*9+9" ) + " [171]." );
System.out.println( "" + evaluate( "3*(4+5)" ) + " [27]." );
System.out.println( "" + evaluate( "3*(4*5)" ) + " [60]." );
System.out.println( "" + evaluate( "3*(4+5)*2" ) + " [54]." );
System.out.println( "" + evaluate( "3*(4*5)+2" ) + " [62]." );
System.out.println( "" + evaluate( "1+1+1+1+1+1" ) + " [6]." );
System.out.println( "" + evaluate( "2*2*2*2*2*2" ) + " [64]." );
System.out.println( "" + evaluate( "1+1+(2*2*2)+1+1" ) + " [12]." );
System.out.println( "" + evaluate( "1+1+(1+1+1)+1+1" ) + " [7]." );
System.out.println( "" + evaluate( "2*2*(2+2+2)*2*2" ) + " [96]." );
System.out.println( "" + evaluate( "2*2*(2*2*2)*2*2" ) + " [128]." );
System.out.println( "" +
evaluate( "2*2*((1+1)*2*2)*2*2" ) + " [128]." );
System.out.println( "" +
evaluate( "2*2*(2*(1+1)*2)*2*2" ) + " [128]." );
System.out.println( "" +
evaluate( "2*2*(2*2*(1+1))*2*2" ) + " [128]." );
System.out.println( "" +
evaluate( "2*2*(2*(1+1)*(1+1))*2*2" ) + " [128]." );
System.out.println( "" +
evaluate( "2*2*((1+1)*(1+1)*2)*2*2" ) + " [128]." );
System.out.println( "" +
evaluate( "2*2*((1+1)*(1+1)*(1+1))*2*2" ) + " [128]." );
System.out.println( "" +
evaluate( "0+2*2*((1+1)*(1+1+0)*(1+1))*2*2+0" ) + " [128]." );
System.out.println( "" +
evaluate( "10+2*2*((1+1)*(1+1+0)*(1+1))*2*2+10" ) + " [148]." );
System.out.println( "" +
evaluate( "10+2*2*((1+1)*(1+1+0)*(1+1))*2*2+100" ) +
" [238]." ); }

// the evaluator

static int evaluate( final String string )
{ return fst( expression( tokenize( string ))); }

// syntactical analyzer

static List expression( final List arg )
{ final List tokens = term( arg );
final int term = fst( tokens );
final int operator = snd( tokens );
final List tail = cddr( tokens );
final List tailval = operator == PLUS ? expression( tail ) : null;
return tail == null ? cons( term, null ) :
operator == PLUS ? cons( term + fst( tailval ), rest( tailval )) :
operator == R_PAREN ? cons( term, tail ) : null; }

static List term( final List arg )
{ final List pair = factor( arg );
final int result = fst( pair );
final List tokens = rest( pair );
final List tail = rest( tokens );
final List tailval = factor( tail );
return tail == null ? cons( result, null ) :
fst( tokens ) == MUL ?
term( cons( result * fst( tailval ), rest( tailval ))) :
cons( result, tokens ); }

static List factor( final List arg )
{ final int result = fst( arg );
final List tokens = rest( arg );
return result >= NUMBER ? cons( result, tokens ) :
result == L_PAREN ? expression( tokens ) : null; }

// support for the lexical analyzer

static int numlen( final String s )
{ final boolean done = s.equals( "" );
final boolean valid = !done;
final String r = valid ? s.substring( 1, s.length() ): "";
final char c = valid ? s.charAt( 0 ): 0;
final boolean isdigit = Character.isDigit( c );
return done ? 0 : isdigit ? 1 + numlen( r ) : 0; }

static int max( final int i, final int j )
{ return i > j ? i : j; }

// The lexical analyzer

static final int NUMBER = 0;
static final int INVALID = -1;
static final int PLUS = -2;
static final int MUL = -3;
static final int L_PAREN = -4;
static final int R_PAREN = -5;

static String name( final int l )
{ return l >= NUMBER ? "" + l : l == INVALID ? "INVALID" :
l == PLUS ? "PLUS" : l == MUL ? "MUL" : l == L_PAREN ? "L_PAREN" :
l == R_PAREN ? "R_PAREN" : "(UNKNOWN)"; }

static List tokenize( final String s )
{ final boolean done = s.equals( "" );
final boolean valid = !done;
final String r =
valid ? s.substring( max( 1, numlen( s )), s.length() ): "";
final char c = valid ? s.charAt( 0 ): 0;
final boolean isdigit = Character.isDigit( c );
final int d = isdigit ?
Integer.valueOf( s.substring( 0, numlen( s ))).intValue() : 0;
return done ? null : cons
( ( isdigit ? d : c == '+' ? PLUS : c == '*' ? MUL :
c == '(' ? L_PAREN : c == ')' ? R_PAREN : INVALID ),
tokenize( r )); }}

/*
171 [171].
27 [27].
60 [60].
54 [54].
62 [62].
6 [6].
64 [64].
12 [12].
7 [7].
96 [96].
128 [128].
128 [128].
128 [128].
128 [128].
128 [128].
128 [128].
128 [128].
128 [128].
148 [148].
238 [238].
*/

When replying to my post, please do not quote my complete
post, but only those parts you directly refer to.
Especially, please do not quote the complete source code.
 
J

Jon Harrop

Stefan said:
I wrote a purely functional parser in Java once for fun.

That is, all assignments are final, thus, there are no
storage modifications. No side effects used anywhere
(except in the test code and in the debug code, which
does the side-effect of printing.) Code is given below.

The building scheme of the »functional« methods
of the scanner and parser below is always like:

let x0 = ...
x1 = ...
x2 = ...
in ...

which, in Java, is written as

{ final x0 = ...;
final x1 = ...;
final x2 = ...;
return ...; }

Nice. :)
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Jon said:
SQL, Yacc, LINQ, Excel and XSLT are hardly just "academic things".

No.

But they are not programming languages for a JVM either.

Arne
 
S

Stefan Ram

Jon Harrop said:
Has anyone here tried any statically-typed functional programming languages
that target the JVM?

See also:

»Java as a Functional Programming Language«

Book Series Lecture Notes in Computer Science
Publisher Springer Berlin / Heidelberg
ISSN 0302-9743 (Print) 1611-3349 (Online)
Volume Volume 2646/2003
Book Types for Proofs and Programs: International Workshop,
TYPES 2002, Berg en Dal, The Netherlands, April 24-28, 2002.
Selected Papers
Copyright 2003
Page 617

http://www.springerlink.com/content/9tfeaj8mujlcpfq8/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,266
Messages
2,571,081
Members
48,772
Latest member
Backspace Studios

Latest Threads

Top