5

Apply is a fitting name for a member function of a function-type class that applies the function to the given arguments:

class Addition {
   int apply(int a, int b) {
      return a + b;
   }
}

But what about the opposite, when the class that a function is applied to has a method that applies a given function to itself?

class FktArg {
   Object whatShouldIBeNamed(Function<FktArg> fkt) {
      return fkt.apply(this);
   }
}

What is the naming convention here?

3
  • 1
    Please, for the sake of your fellow programmers :) , don't automatically name the method "map" every time you pass in a function - see my comment to the accepted answer. Mar 11, 2020 at 18:31
  • @FilipMilovanović For the sake of my fellow programmers I probably shouldn't have such a method in the first place :-P I am writing a code generator and thought having such a method in my generated code would make the generator easier in other places. I ended up not needing it. Still I am not sure how such a general method should be called.
    – kutschkem
    Mar 12, 2020 at 7:38
  • 1
    callWithThis, passInto. But it seems like an unnecessary indirection and against OO principles. fkt(fktArgObj) just does the trick. Just like we don't do number.passInto(negate).
    – Sopel
    Mar 12, 2020 at 18:13

3 Answers 3

2

It's always nice to see people who really care about good naming.

I think map would be a well understood name for this method:

// Java 1.8 example
// `T` is the type of `this` Object
public <R> R map(Function<? super T, ? extends R> func) {
    return func.apply(this);
}

Wikipedia says:

In many programming languages, "map" is the name of a higher-order function that applies a given function to each element of a functor...

Usually the functor is a collection of elements but I believe that an individual element as the functor is still very understandable.

Sticking with the Java example, this would be similar to map in the Java Stream API, but since you're only mapping one Object, you just return R instead of Stream<R>

java.util.stream.Stream:
<R> Stream<R> map(Function<? super T, ? extends R> mapper)

Returns a stream consisting of the results of applying the given function to the elements of this stream.

This is an intermediate operation.

Type Parameters: <R> The element type of the new stream
Parameters:mapper - a non-interfering, stateless function to apply to each element
Returns:the new stream

7
  • 4
    Sorry, but just for reference, "map" would not be a good generalized name for this method, as "map" (in some languages named "select") has a very specific meaning. Call it map if you are mapping input elements to something else. There's really no general naming convention here, nor there should be - the method name should describe what the method does, and the function parameter's name should communicate the role it has. In your example, it's map-mapper, but there are others, like filter-predicate, compare-comparer, etc. Mar 11, 2020 at 18:28
  • map would have a different signature note the java returns a stream<R> not R
    – jk.
    Mar 12, 2020 at 8:01
  • @jk. But I did note that in the answer: "since you're only mapping one Object, you just return R instead of Stream<R>"
    – xtratic
    Mar 12, 2020 at 12:16
  • map has the signiture (a -> b) -> f a -> f b OPs function has a different signature so map is not an appropriate name, you will be confusing anyone with a FP backround if you call this map as it is (flip $) i.e. function application with the arguments reversed aka pipe
    – jk.
    Mar 12, 2020 at 12:32
  • in the above f is the functor mentioned in the wikipedia link (for java this is stream) if you remove the functor it is not map anymore
    – jk.
    Mar 12, 2020 at 12:40
1

I think I'd possibly go with the word "apply" for both contexts.

In the first case, the operands are provided as method arguments whilst the operation is parameterised via the object itself (presumably subtraction etc. would be handled by the programmer using the method of a different object).

In the second case it is the operation which is parameterised, whereas the operand(s) are implied by the containing object.

Either way, it's equally an application of operations to operands. And to that extent, it may imply poor modelling - what may be missing here is an operator or applicator class with an apply method, that is, a class which generically applies operations to operands, both of which are provided as parameters. Operations then become functions instead of classes, and operands become records instead of classes, both of which are passed as parameters to an apply method.

It's like the old question about whether it should be the sending or receiving Account object which contains the TransferMoney method - in fact it's neither, it's the Journal object which transfers money, and it takes at least two Accounts as parameters.

Alternatively, it may be a sign that there is confusion or inconsistency in whether it is the operation or the operand which is treated as the active participant. It makes natural sense to say that an addition takes two numbers and sums them. It makes less natural sense to say two numbers take an addition and sum themselves, even less again to say that a number takes an addition and another number and sums itself.

1
  • it is a backward apply so I can get behind this, still think pipe is better but I would wouldnt I
    – jk.
    Mar 12, 2020 at 7:54
-3

Its similar to the pipe forward operator in F# https://theburningmonk.com/2011/09/fsharp-pipe-forward-and-pipe-backward/ so I'd go for pipe

this is also essentially the powershell pipe operator, which obviously is realted to unix pipe (though in unix land it's strings only)

other less well know places I've found this

elm has a pipe operator https://dennisreimann.de/articles/elm-functions.html

elixir https://elixirschool.com/en/lessons/basics/pipe-operator/

OCaml (admitedly this is highly related to F#) has a pipline operator https://www.cs.cornell.edu/courses/cs3110/2019sp/textbook/hop/pipelining.html

R (but not in the base language) https://magrittr.tidyverse.org/reference/pipe.html

Javascript (but experimental) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Pipeline_operator

RFC to add a pipe operator to PHP https://wiki.php.net/rfc/pipe-operator

Overall I think the consensus is that a flipped function application is a pipe

for completness the only language I can find that has this and doesn't call it pipe is kotlin and thats becuase you can emulate this with existing run or let

5
  • 2
    That name would confuse (or not mean anything to) anyone not familiar with F# though.
    – Flater
    Mar 11, 2020 at 14:19
  • @Flater updated, its not a uniquely F# thing, granted if you havent heard of pipe in any context then it wont mean anything but I think you have to assume some familiarity
    – jk.
    Mar 11, 2020 at 16:24
  • I'm inclined to agree with @Flater. The word "pipe" in this context is specific to F#. Mar 11, 2020 at 16:59
  • I'd say the concept of "piping" the output of one operation to the input of the next is widely understood, and not particular to F#. But I wouldn't recommend the use of the word here.
    – Steve
    Mar 11, 2020 at 20:36
  • @Steve I could contextually understand what "piping the output" means, but like you said, that clarity doesn't extend to "pipe" by itself.
    – Flater
    Mar 12, 2020 at 11:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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