24

I know that obj.func1().func2() is called method chaining, but what is the technical term for:

func1(func2(), func3());

Where return of a function is used as an argument to another.

zhenka
  • 1,688
  • 8
    obj.func1().func2() is called method chaining - Correction: It's called a train wreck. – Yam Marcovic Nov 17 '11 at 10:18
  • That sounds very, very, very tricky unless you're absolutely sure that obj.func1() always returns an object that has func2() as a member function. – Shadur-don't-feed-the-AI Nov 17 '11 at 11:33
  • 8
    @Yam Care to explain? It’s employed for great profit in fluent interfaces, amongst others. Are you referring to the Law of Demeter? If so, this doesn’t forbid the above pattern, and even in cases where it does there is a good case against the LoD. – Konrad Rudolph Nov 17 '11 at 12:47
  • 1
    method chaining lies on one shelf with syntactic sugar, no need to make a fuss over it. – Kos Nov 17 '11 at 17:21
  • @KonradRudolph train wreck reefers to the debug-mess you'll fine yourself in when one of the methods in the chain fails. Ie. a Null Reference Exception on line 345 - great, which one of the 13 methods where you saying it was? oh, you didn't, right. – Pauli Østerø Nov 17 '11 at 21:15
  • 1
    @PauliØsterø I thought that's what stack tracing is meant for. – Chris C Nov 17 '11 at 21:32
  • @CCRicers your stacktrace cant tell you which one of the 13 methods thas is trying to call something on a null - it only shows you a trace to the method actually having the train wreck inside it, no? – Pauli Østerø Nov 18 '11 at 07:52
  • @Pauli Well that then depends on the language / API you’re using. For instance, a null-reference-free style of programming makes this much easier. Also, the same applies to any complex expression in code. Do you suggest refactoring them all into an equivalent of three-address codes (i.e. using two operands and one operator)? – Konrad Rudolph Nov 18 '11 at 08:39
  • parser .setOption1(111) .setOption2("aaa").parse() Properly indented. – ripper234 Nov 20 '11 at 23:32

4 Answers4

38

I don't think it's function composition. Function composition means taking two or more functions and turning them into a new function, like f . g . h in Haskell. Note that no function is called at this point.

Personally, I would refer to constructs like func1(func2(), func3()) as "nested function calls".

fredoverflow
  • 6,874
  • 1
    +1, it's referred to as "nested function calls" in all programming contexts I've seen. – Izkata Nov 17 '11 at 15:20
  • 2
    +1, calling this "function composition" is deceptively wrong. – Gian Nov 17 '11 at 16:37
  • +1. All f(g()) is doing is calling f() with an expression for the first argument, and it so happens the function call g() qualifies as an expression. But if there has to be a name for it, this is as close as it gets. – Blrfl Nov 17 '11 at 20:34
16

In mathematics, it's called function composition. I don't think I've heard the term applied to programming, though. That may be because the usage is largely avoided for a few reasons. It can introduce strange bugs when the functions have side effects, due to compilers being free to evaluate func3 before func2. It's more difficult to debug because you can't set breakpoints on or print out intermediate results, and most people just plain find it harder to read.

Karl Bielefeldt
  • 147,435
  • 4
    It's called composition in functional programming as well. – Chuck Nov 17 '11 at 05:25
  • 1
    I often see/hear it called 'nested function call' as well, although this term may be somewhat ambiguous. – tdammers Nov 17 '11 at 07:16
  • 9
    I don't think it's "largely avoided". IMO it's not uncommon to write code like printf("%d %d\n", strlen(a), strlen(b)); instead of using intermediary variables. – user281377 Nov 17 '11 at 07:50
  • 3
    I think the solution to the strange bugs when the functions have side-effects is not to avoid this, but instead to avoid writing functions that produce values and have side-effects. Similarly, regarding the debuggers, the solution should be to ask for a better debugger, one that doesn't force you to change your code to make the debugger work. – R. Martinho Fernandes Nov 17 '11 at 07:55
  • 7
    Whether the compiler free to evaluate func3 before func2 depends entirely on the language being used. In Java, for example, the evaluation order is strictly specified. I'd actually suspect that this is the case for most languages. – Michael Borgwardt Nov 17 '11 at 08:02
  • 1
    @Michael Borgwardt: In C++ and (I think) C, the order is unspecified, which means the compiler is free to evaluate as it likes without documentation. It can't interleave execution, so either func2 or func3 will run all the way to completion and then the other will run. The solution is to write programs that don't depend on unspecified behavior. – David Thornley Nov 17 '11 at 17:40
  • 3
    The term "function composition" in mathematics actually only applies to single-argument functions, where it refers to a structure of the form func1(func2(func3(x))). Or technically, it refers to the functions themselves: if g(x) = f1(f2(f3(x))), then g (not g(x)) is the composition of f1, f2, and f3. While I could see a way in which you could call the structure in the question "function composition," it strikes me as a very unusual use of the term, in a mathematical sense. – David Z Nov 18 '11 at 08:12
  • -1, function composition in programming is more like (to borrow Python's syntax): newfunc = lambda x, y : func1(func2(x), func3(y)). Then you've "composed" a new function that can be called later: newfunc(x, y) – Izkata Jul 26 '12 at 14:25
2

As @Karl Bielefeldt points, it's called function composition in Math.

There is NO technical term for this thing in programming. And I think this is a Good thing, because it indicates that the operation is normal and Orthogonal.

Orthogonality in programming languages means that you can use an instruction/operation independent of it's context. For example, you can call a function/method in all of the following ways, and it would behave the same...

f1()(f2(), f3());

x = y + f4();

if ( f5() && !f6() ) doSomething();

f7() = f8() + f9(); // in C++ when a function returns a reference

x = f10() ? f11(f12(f13(x))) : f14();

You can read more on Orthogonality in Programming on Wikipedia, and there's a question on StackOverflow on this.

treecoder
  • 9,495
1

I really am not that good with terms, but I just read an article a few days ago that referred to the term Higher order functions, and here's an abstract of the definition per Wikipedia:

http://en.wikipedia.org/wiki/Higher-order_function

In mathematics and computer science, higher-order functions, functional forms, or functionals are functions which do at least one of the following:

  • take one or more functions as an input
  • output a function

All other functions are first-order functions. In mathematics higher-order functions are also known as operators or functionals. The derivative in calculus is a common example, since it maps a function to another function.

so in this case, since that scenario does take at least one function as an input/param, it'd be considered a higher order function, i believe.

silverCORE
  • 173
  • 1
  • 6
  • 2
    No, calling a higher order function would look like func1(func2, func3). Note the absent parenthesis. – fredoverflow Nov 18 '11 at 05:23
  • that makes sense Fred. one's the address of a function, and the other the result of executing that function. Thanks for pointing that out. – silverCORE Nov 18 '11 at 06:14
  • @fredoverflow func2 and func3 could be higher-order functions themselves and return a new function when called. – Frerich Raabe Jan 09 '20 at 11:33