Reputation: 705
I am trying to understand first class functions and how they may be used in a practical example. The example that I came up with is for authentication before calling specific functions for a logged-in user. For example:
def authenticate(user_id):
if user_id != 1: return None
def call_func(func_name):
print(f"{user_id} is logged in! ==> Calling function '{func_name}'")
return call_func
user0 = authenticate(user_id=0)
if user0: user0(func_name='xyz')
user1 = authenticate(user_id=1)
if user1: user1(func_name='xyz')
Which prints:
1 is logged in! ==> Calling function 'xyz'
Is this a proper understanding of first-class functions? The above seems more like the concept of a wrapper
or decorator
. Are these basically the same thing, or what's the difference between these three concepts?
Upvotes: 0
Views: 276
Reputation: 2658
First class simply means it can exist on its own. It is not required to be accompanied by no one.
Where in languages like Java and C#, you create classes to shove methods into.
class Logger {
public Logger(string name) {
this.name = name;
}
public void Log(string msg) {
System.out.print(name + msg);
}
}
And then you use instances of those classes to call the methods.
Logger logger = new Logger("a name");
logger.Log("a message");
A function can only exist as a method of a class. The class is the first class citizen.
In languages like python you can just have a function.
def log(name, msg):
print(name, msg)
And just call that function.
log('a name', 'a message')
A function can simply exist.
Python has classes has well. So if you still want to avoid typing 'a name'
all the time, you can use them.
class Logger:
def __init__(self, name):
self.name = name
def log(self, msg):
print(self.name, msg)
logger = Logger('a name')
logger.log('a message')
And since functions are first class citizens, closures are a thing as well and the same can be achieved, again, with just functions.
def logger(name):
def log(msg):
print(name, msg)
return log
log = logger('a name')
log('a message')
Decorators are simply functions that make use other function.Take the previous log
function for example. If we have a fuzz
decorator, and decorate the log
function with it, it essentially replaces our log function by its own (that happens to call ours).
def fuzz(func):
def fuzzed_func(*args, **kwargs):
print('fuzz')
func(*args, **kwargs)
print('fuzz')
return fuzzed_func
@fuzz
def log(name, msg):
print(name, msg)
fuzz
a name a message
fuzz
Note 1. data types are first class citizens as well, in all example given here. The string
is by itself in Java. As 'a name'
is a str
by itself, as well, in Python. So, not only functions and classes apply to the first class.
Note 2. Also consider in the case of a class, you can have methods that do not act on self
or this
, they are referenced as static methods. Essentially a function in a class.
There is a fantastic satire about exactly this, you may want to read at some point.
Execution in the Kingdom of Nouns by Steve Yegge
David Beazley, just recently at PyCon 2019, gave an outstanding talk, loosely on this topic, that demonstrates quite brilliantly the power of a function.
Lambda Calculus from the Ground Up
Upvotes: 2