What is a first-class-citizen function?
Asked Answered
F

7

54

What is a first-class-citizen function?

Does Java support first-class-citizen functions?

As mentioned on Wikipedia:

First-class functions are a necessity for the functional programming style.

Is there any other use of first-class functions?

Furring answered 3/3, 2011 at 8:0 Comment(2)
en.wikipedia.org/wiki/First-class_functionRathe
take a look at: #1599676Hacksaw
M
58

A language that considers procedures to be "first-class" allows functions to be passed around just like any other value.

Languages like Java 7 (and earlier) and C "kind of" have this capability: C allows function pointers to be passed around, but you can't dynamically define a function in those languages and suddenly pass that somewhere else. Java before version 8 can simulate this to a certain extent with anonymous classes, but it doesn't technically have first-class functions.

On the other hand, C++, D, C#, Visual Basic .NET, Java 8+, and functional languages (like Scheme and Haskell) do allow you to pass around functions like variables. For example, the code below returns a function that adds addend to its input:

Written in D:

int delegate(int) makeAdder(int addend) //Returns a function
{
    return delegate int(int x) //Long way
    {
        return x + addend; //Notice that addend came from _outside_ the function
    };

    return (int x) { return x + addend; }; //Short way

    return x => addend + x; //Super-short way, introduced in D 2.058
}

Written in C#:

Func<int, int> MakeAdder(int addend) //Returns a function
{
    return delegate(int x) //The long way. Note: Return type is implicitly 'int'
    {
        return x + addend;
    };

    return x => x + addend; //Short way: x "goes to" (x + addend); inferred types
}

Written in C++:

#include <functional>

std::function<int(int)> make_adder(int addend)
{
    return [=](int x)
    {
        return addend + x;
    };
}

Written in Scala:

def makeAdder(addend: Int) = (x: Int) => addend + x

Written in Python:

def make_adder(addend):
    def f(x):
        return addend + x
    return f
    # or...
    return lambda x: addend + x

Written in Erlang:

make_adder(Addend) ->
    fun(X) -> Addend + X end.

Written in JavaScript:

function makeAdder(addend) {
    return function(x) {
        return addend + x;
    };
}

Written in JavaScript (ES2015 arrow function syntax):

const makeAdder = addend => x => addend + x;

Written in Scheme:

(define (makeAdder addend)
  (lambda (x)
    (+ x addend)))

Written in Haskell:

makeAdder :: Int -> (Int -> Int)
makeAdder addend = \x -> addend + x

Written in Visual Basic 2008:

Function MakeAdder(addend As Integer) As Func(Of Integer, Integer)
    Return Function(x) (x + addend)
End Function

Written in Swift (both verbose and short-hand implementations):

func makeAdder(append: Int) -> (x: Int) -> Int {
    return { (x: Int) -> Int in
        return x + append
    };
}

func makeAdder(append: Int) -> (Int) -> Int {
    return {$0 + append};
}

(By the way, a "lambda" is just a function without a name. Lambdas are only supported in languages that support first-class functions.)

Mccullum answered 3/3, 2011 at 8:5 Comment(13)
in C++ you can using template function objects: boost.org/doc/libs/1_46_0/libs/spirit/phoenix/doc/html/…Rathe
They're not functions, they're function objects. They behave similarly, but they're not lambdas like in C# or D, and making them is a huge pain compared to languages that have lambdas, since you have to declare an entirely new class, etc.Mccullum
there isnt a difference between a stateless functor and function. do look at phoenix, you'll be surprisedRathe
@aaa: Yes there is, because your methods explicitly have to accept a different data type than a normal function pointer. By contrast, in C#, you can just always accept a Func<int, int>, regardless of whether that function is a lambda or a regular function -- function pointers and lambdas are represented the same way.Mccullum
I dont follow you, explicitly have to accept a different data type?Rathe
@aaa: Yeah. How would you do the exact equivalent of what I did in my in C++? If you write it (try here), I'll show you what I mean.Mccullum
@aaa: Exactly my point. The return type is BOOST_TYPEOF(phoenix::_1 + phoenix::val(int())), not int (*)(int), so you can't interchange it with a regular function.Mccullum
it's similar to python duck typing in a way - its still a function albeit "unusual" one. one can argue functor isnt pointer but thats just semantics. If you accept functions as templates - there isnt difference.Rathe
@aaa: Semantics means a lot, though... the C++ version is harder to code, a lot harder to understand, and doesn't receive the same treatment from the language as functions do in other languages.Mccullum
i wont argue that - lambda functions arent very easy in c++ - but you can do them.Rathe
@aaa: You can simulate them, but they're not lambdas, but pseudo-lambdas that are harder to work with than lambdas and treated differently by the language and compiler.Mccullum
Something I forgot to note: yes, you can use tricks like boost::function in order to use the same syntax for everything even before C++11. But that isn't "first-class" anymore, since it's not a standard part of the C++ language. (C++11 will have std::function, which does make these first-class.)Mccullum
does to be passed around actually cover anything else than passing an object as an argument (to a function/callable), or using it in an assignment (as right-value)? if yes, what exactly?Broadbent
F
4

Let us consider the example of functional programming paradigm in which functions are the first class citizens. When we say functions are the first class citizens, we can do the following things with the function...

  • Function can be assigned to a variable
  • Function can be stored in a data structure
  • Function can be passed around as an argument to other functions
  • Function can be returned from the functions

In functional programming languages, it is possible to do the above mentioned things.

Now, let us try to answer the question, whether java supports first class citizen functions (or) not.

In java, methods are equivalent of functions. It is not possible to do any of the above with methods. But all of the above are possible with java objects. So, objects are the first class citizens in java. Admittedly, java8 supports passing of methods (method behavior, to be precise) to other methods using functional interfaces and lambda expressions. But that does not mean that java has functions as first class citizens.

The ability to do above things such as passing around functions, returning functions from functions is very powerful and useful. This is because, it allows us to pass around the behavior not just the data.

Funds answered 13/11, 2015 at 14:50 Comment(0)
B
3

A first class function can be passed around. A typical example is the map function. Here is an example in Scala that squares the elements of a list:

val square = (x:Int) => x*x

val squaredList = List(1,2,3,4).map(square _)
//--> List(1,4,9,16)

The square function is here an argument to the map method, which applies it to every element. If you want to do something like this in Java, you have to use a method wrapped in a class, something like this:

interface F<A,B>{ B apply(A a); }

static <A,B> List<B> map(List<A> list, F<A,B> f) {
  List<B> result = new ArrayList<B>();
  for(A a:list) result.add(f.apply(a));
  return result;   
}

//we have to "wrap" the squaring operation in a class in order to make it a function
F<Integer,Integer> square = new F<Integer,Integer>(){ 
  Integer apply(Integer a) { return a*a; }
}

List<Integer> ints = Arrays.<Integer>asList(1,2,3,4);
List<Integer> squares = map(ints, square);

Looking at this you can see that you can get the same task somehow done in Java, but with more overhead, and without "native" support by the language, but by using a workaround (wrapper classes). So Java doesn't support first class functions, but can "simulate" them.

Hopefully Java 8 will support first class functions. If you want to have some support for this now, look at http://functionaljava.org/ or http://functionalj.sourceforge.net/ , or have a look at the Scala language.

Bridwell answered 3/3, 2011 at 8:24 Comment(0)
C
1

The Wikipedia definition is pretty good—it's a function that can be passed around like any other piece of data. Java does not support them. The closest it has is Runnable and Callable objects.

Creight answered 3/3, 2011 at 8:4 Comment(0)
C
1

The above answers for @Alpine questions are mostly defining what is First Class Functions along with examples. But still, one question remains why to use?

I'll try to answer the benefits a little differently in Scala where first-class functions are used further as higher-order functions(map, flatMap), Partially Applied Functions and Currying:

  1. As we focus on declarative programming, the how part of processing the data is left as an implementation detail to map, flatMap, and focused more on handling the what actual logic flow. A caller can specify what should be done and leave the higher-order functions to handle the actual logic flow.

  2. Partially Applied Functions and Currying: What if you wanted to reuse a function invocation and retain some of the parameters to avoid typing them in again?

Partially Applied Function Example:

def factorOf(x: Int, y: Int) = y % x == 0
val multipleOf3 = factorOf(3, _: Int)
val y = multipleOf3(78)

Currying Example:

def factorOf(x: Int)(y: Int) = y % x == 0
val isEven = factorOf(2) _
val z = isEven(32)

The above examples show you how you can reuse the part of first-class functions by not passing all parameters and keep your code DRY principle. These are few benefits for using first-class functions

Reference for more details: https://www.oreilly.com/library/view/learning-scala

Coady answered 13/7, 2020 at 19:32 Comment(0)
C
0

Functions are first class citizen means you can pass function anywhere as if it's a variable.

From Scala

def isOdd(in: Int) = in % 2 == 1
val n = (1 to 10).toList
n.filter(isOdd)

see here: isOdd is a function. passed as if it's a variale.

Objects are first class citizen in Java. A first class citizen is the one that can be passed anywhere. The parallel is from a first class citizen of country are allowed almost everywhere.

Read:

Cyano answered 3/3, 2011 at 8:6 Comment(0)
M
0

No, you cannot assign a method to a variable or pass it as an argument to another method for example.

Instead you can use interfaces to wrap the intended behaviour, or reflection to reify methods.

Malathion answered 3/3, 2011 at 8:9 Comment(1)
How can I wrap a function using Interfaces?Furring

© 2022 - 2024 — McMap. All rights reserved.