37
\$\begingroup\$

Over is a higher-order function in multiple languages such as APL (). It takes 2 functions and 2 values as arguments, applies the first function to both values, then applies the second to their result. For example, using to represent Over:

1 ²⍥+ 2

We would first calculate ² of each argument: 1² = 1 and 2² = 4. We then apply + to these, yielding 5.

You are to take as input:

  • A black box function, \$f\$, which takes an integer as input and returns an integer
  • A black box function, \$g\$, which takes 2 integers as input and returns a single integer
  • 2 integers, \$a\$ and \$b\$.

You should then return the result of \$g(f(a), f(b))\$.

If you have a builtin specifically for this (e.g. APL's , Husk's ¤ etc.), consider including a non-builtin answer as well. It might even get you an upvote :)

You may input and output in the most convenient format for your language, and in any convenient method, including taking \$a\$ and \$b\$ as a pair/list/tuple [a, b]

For the sake of simplicity, you can assume that the black-box function will always input and output integers within your language's integer domain, and that \$a\$, \$b\$ and the output will be with your language's integer domain.

This is , so the shortest code in bytes wins

Test cases

f
g
a, b -> out

f(x) = x²
g(x,y) = x - y
-2, 2 -> 0

f(x) = φ(x)     (Euler totient function)
g(x,y) = 2x + y
5, 9 -> 14

f(x) = x³-x²-x-1
g(x,y) = y⁴-x³-y²-x
-1, -1 -> 22

f(x) = x
g(x,y) = x / y   (Integer division)
-25, 5 -> -5
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Can we take a & b as an array [a,b]? \$\endgroup\$
    – Shaggy
    Commented Apr 20, 2021 at 7:12
  • \$\begingroup\$ @Shaggy Yes you can \$\endgroup\$ Commented Apr 20, 2021 at 11:31

52 Answers 52

25
\$\begingroup\$

Haskell, 12 bytes

f?g=(.f).g.f

Try it online!

Haskell was made for this.

Let's unpack it:

(f?g) x y =
(((.f).g.f) x) y =
(.f)(g (f x)) y =
((g (f x)).f) y =
g (f x) (f y)

If you're wondering what happens if we make this further pointfree in f and g, we can express (?) as:

\f->((.f).).(.f)
(.).(.).flip(.)<*>flip(.)

The flipped version of ? that's invoked as g?f is a little nicer:

((.).flip(.)<*>).(.)

(I used pointfree.io for these.)

Test cases copied from Unrelated String.


Haskell, 10 bytes

(.map).(.)

Try it online!

If the input [x,y] is a two-element list, and the binary function g accepts its two arguments as such a list. The main function takes is arguments as g then `f.

\$\endgroup\$
1
  • \$\begingroup\$ I really need to get better at pointfree \$\endgroup\$ Commented Apr 20, 2021 at 0:49
11
\$\begingroup\$

Factor, 16 bytes

[ bi@ rot call ]

Try it online!

Explanation:

It's a quotation (anonymous function) that takes a quotation with stack effect ( x x -- x ), two integers, and a quotation with stack effect ( x -- x ) on the data stack as input. It takes them in that order, as that allows for what I believe is the shortest code. Assuming the data stack looks like [ + ] 1 2 [ sq ] when this quotation is called...

  • bi@ Apply a quotation to two objects.

    Stack: [ + ] 1 4

  • rot Move the object third from the top to the top.

    Stack: 1 4 [ + ]

  • call Call a quotation.

    Stack: 5

Factor, 10 bytes

map-reduce

Try it online!

Built-in.

\$\endgroup\$
1
  • \$\begingroup\$ Exactly what I had in mind :) \$\endgroup\$
    – Bubbler
    Commented Apr 20, 2021 at 2:10
9
\$\begingroup\$

J, 12 bytes

2 :'(u v)~v'

Try it online!

Non-built-in solution. This is an explicit conjunction that takes two functions on two sides and evaluates to a train that acts like "u over v", but with flipped arguments.

x ((u v)~v) y
x (u v)~ v y
(v y) (u v) x
(v y) u v x

J, 1 byte

&

Try it online!

J's built-in conjunctions can be assigned to a variable, unlike in Dyalog APL.

\$\endgroup\$
1
  • \$\begingroup\$ "unlike in Dyalog APL" ― works fine in, say, NARS2000. \$\endgroup\$
    – Adám
    Commented Apr 20, 2021 at 20:20
8
\$\begingroup\$

JavaScript (ES6), 23 bytes

(f,g,x,y)=>g(f(x),f(y))

Try it online!

\$\endgroup\$
4
  • 5
    \$\begingroup\$ Ninja'd by ten seconds :/ \$\endgroup\$ Commented Apr 20, 2021 at 0:26
  • \$\begingroup\$ No need to Over-complexify, life is Overly simple \$\endgroup\$
    – Kaddath
    Commented Apr 20, 2021 at 8:18
  • \$\begingroup\$ 20 \$\endgroup\$
    – l4m2
    Commented Jan 9, 2023 at 21:36
  • \$\begingroup\$ due to rule clarify \$\endgroup\$
    – l4m2
    Commented Jan 9, 2023 at 21:37
7
\$\begingroup\$

Rust, 21 bytes

|f,g,x,y|g(f(x),f(y))

Try it online!

An anonymous function that has the signature

fn(fn(i32)->i32,fn(i32,i32)->i32,i32,i32)->i32

Don't you love it when the function signature is twice as long as the function itself?

\$\endgroup\$
7
\$\begingroup\$

Haskell, 17 16 15 bytes

(f!k)x=k(f x).f

Try it online!

-1 thanks to Wheat Wizard repatterning the use of infix

\$\endgroup\$
3
  • 3
    \$\begingroup\$ Also worth pointing out this exists in the standard library as 'on' in Data.Function \$\endgroup\$
    – rak1507
    Commented Apr 20, 2021 at 0:43
  • \$\begingroup\$ @rak1507 Thanks! Like, actually, thanks--I knew something like that had to exist but instead of searching the type signature I've been stuck on the idea that it has to be one of those infix operators from Control.Arrow :P \$\endgroup\$ Commented Apr 20, 2021 at 0:44
  • 1
    \$\begingroup\$ You can shave off a byte with virtually no modification \$\endgroup\$
    – Wheat Wizard
    Commented Feb 6, 2022 at 17:00
6
\$\begingroup\$

APL (Dyalog Classic), 9 bytes

{⍺⍺/⍵⍵¨⍵}
{⍺⍺/⍵⍵¨⍵}
 ⍺⍺          left operand (function argument)
   /         reduce
    ⍵⍵       right operand
      ¨      each
       ⍵     right argument

APL has a builtin for this, ⍥, but here's a non builtin solution as an operator taking an array of arguments.

Alternative 'proper' definition: {(⍵⍵⍺)⍺⍺⍵⍵⍵}, or more readably as {(⍵⍵ ⍺) ⍺⍺ ⍵⍵ ⍵}

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ ⎕/⎕¨⎕ \$\endgroup\$
    – Adám
    Commented Apr 20, 2021 at 20:15
  • \$\begingroup\$ @Adám not a fan particularly, you can post that as a separate answer if you want \$\endgroup\$
    – rak1507
    Commented Apr 20, 2021 at 20:20
6
\$\begingroup\$

Racket, 26 bytes

(λ(f g x y)(g(f x)(f y)))

Try it online!

λ is 2 bytes, BTW.

Pretty self-explanatory, but:

(λ(f g x y)(g(f x)(f y)))  Anonymous function submission
(λ                      )  Lambda;
  (f g x y)                accept functions f, g and arguments x, y and return
           (g          )   g(
             (f x)           f(x),
                  (f y)            f(y))
\$\endgroup\$
6
\$\begingroup\$

R, 29 bytes

function(f,g,a,b)g(f(a),f(b))

Try it online!

No surprises here. In a future version of R, function will be replaceable with \ (which is supposed to look like a lambda).

\$\endgroup\$
6
\$\begingroup\$

Wolfram Language (Mathematica), 10 bytes

#2@@#/@#3&

Try it online!

Input [f, g, {x, y}].

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Nice ... argh, Inner is so close to doing this task \$\endgroup\$ Commented Apr 23, 2021 at 1:55
5
\$\begingroup\$

SKI-calculus, 71 bytes

S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(KK)))))(S(KS)K)))))(KK)

Edit: Another go at hand-translating the lambda calculus expression into SKI using the rules in Wikipedia, this time arriving at the same answer as @Bubbler.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ According to SKI interpreter by aditsu, your expression evaluates to (x0->(x1->(x2->x0(x1(x2))))) which doesn't look quite correct. \$\endgroup\$
    – Bubbler
    Commented Apr 21, 2021 at 0:44
  • \$\begingroup\$ Working 71 bytes: S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(KK)))))(S(KS)K)))))(KK). I guess there must be a language like Binary Lambda Calculus that can express SKI calculus in binary or something... \$\endgroup\$
    – Bubbler
    Commented Apr 21, 2021 at 1:09
  • \$\begingroup\$ ...and there's Binary Combinatory Logic. Time to build an online interpreter... \$\endgroup\$
    – Bubbler
    Commented Apr 21, 2021 at 1:15
  • \$\begingroup\$ @Bubbler Nice, I hadn't realised that S(KK)I is just K for a start, so I'll take another crack at it. \$\endgroup\$
    – Neil
    Commented Apr 21, 2021 at 14:54
  • \$\begingroup\$ @Bubbler OK I've tried again and come up with your answer. \$\endgroup\$
    – Neil
    Commented Apr 21, 2021 at 16:13
5
+50
\$\begingroup\$

tinylisp, 23 bytes

(q((f g x y)(g(f x)(f y

Try it online!

Ungolfed

(lambda (f g x y)     ; a lambda function taking four arguments
  (g (f x) (f y)))    ; apply f to x, f to y, and g to the results
\$\endgroup\$
4
\$\begingroup\$

Python 2, 25 bytes

\$ a \$ and \$ b \$ are inputted as a tuple (called \$ x \$).

lambda f,g,x:g(*map(f,x))

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ You can save a byte by taking input as a list [a,b] \$\endgroup\$
    – rak1507
    Commented Apr 20, 2021 at 0:45
  • \$\begingroup\$ @rak1507 Yeah, just noticed it. \$\endgroup\$ Commented Apr 20, 2021 at 0:46
4
\$\begingroup\$

Jelly, 4 bytes

Ñ€ç/

Try it online!

Takes f on the first line, g on the second line, and the code is on the third line (this is standard for Jelly). Also, takes the arguments together as a list

 €    For each of the arguments
Ñ     Apply the next link (wraps around to `f`)
   /  Reduce by (for a pair, applies dyad to the first and second element of the list)
  ç   Apply the last link (`g`)

Also works:

Jelly, 4 bytes

ÑçÑ}

Try it online!

Ñ     Apply `f` (to the left argument, since it's called as a monad)
 çÑ}  2-2 chain - given dyads x, y, computes x(a, y(a, b)) if the chain's current value is a and the right argument is b
 ç    Apply `g` to the current value (f(left)) and
  Ñ}  A dyad formed from a monad by ignoring the left argument

Basically, Ñ} is (l, r) -> f(r), so this ends up evaluating as λ x y -> g(f(x), (λ a b -> f(b))(x, y)) which simplifies to λ x y -> g(f(x), f(y)) as required.

(These chaining rules are absolutely beautiful. Thank you Dennis for Jelly :P)

\$\endgroup\$
3
  • 3
    \$\begingroup\$ There is also ÑçÑ} that takes a on the left and b on the right :) \$\endgroup\$ Commented Apr 20, 2021 at 0:53
  • 1
    \$\begingroup\$ @cairdcoinheringaahing lol, I am currently editing that in with a description :P \$\endgroup\$
    – hyper-neutrino
    Commented Apr 20, 2021 at 0:54
  • 1
    \$\begingroup\$ There is also ñçñ, but that requires f to be forced as a monadic link (prefixed with µ) if it has any different behaviour when run monadically/dyadically \$\endgroup\$ Commented Apr 21, 2021 at 13:50
4
\$\begingroup\$

Scala, 16 bytes

_ map _ reduce _

Try it online!

Takes ([a,b],f,g). There’s more ways to do this but I’m on mobile so I’ll add them later

\$\endgroup\$
4
\$\begingroup\$

Proton, 21 bytes

(f,g,a)=>g(*map(f,a))

Try it online!

Time to bring out this garbage again :D

\$\endgroup\$
4
\$\begingroup\$

Stax, 7 bytes

n!aa!a!

Run and debug it

A full program which can be executed as a block as well.

accepts the arguments as g x f y.

\$\endgroup\$
7
  • \$\begingroup\$ Cant this be packed? \$\endgroup\$
    – lyxal
    Commented Apr 20, 2021 at 7:23
  • \$\begingroup\$ doesn't make sense to pack something that can be reused. It takes its arguments from the stack, so I think it doesn't make sense to pack here. \$\endgroup\$
    – Razetime
    Commented Apr 20, 2021 at 7:23
  • \$\begingroup\$ "a full program" submission can surely be packed to save a byte. \$\endgroup\$
    – lyxal
    Commented Apr 20, 2021 at 7:24
  • \$\begingroup\$ nah. not doing it. \$\endgroup\$
    – Razetime
    Commented Apr 20, 2021 at 7:24
  • \$\begingroup\$ Okay boomer :p. How about explaining how the link works \$\endgroup\$
    – lyxal
    Commented Apr 20, 2021 at 7:26
4
\$\begingroup\$

Ruby, 23 bytes

->f,g,x,y{g[f[x],f[y]]}

Try it online!

Or:

Ruby, 23 bytes

->f,g,*x{g[*x.map(&f)]}

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Since you're allowed to take an array of arguments you can omit the first * in your second solution. \$\endgroup\$
    – Jordan
    Commented Oct 5, 2022 at 14:46
4
\$\begingroup\$

C (clang), 54 \$\cdots\$ 37 36 bytes

o(f(),g(),a,b){return g(f(a),f(b));}

Try it online!

Saved 8 bytes thanks to dingledooper!!!
Saved 2 bytes thanks to ceilingcat!!!
Saved a byte thanks to jdt!!!

\$\endgroup\$
4
  • \$\begingroup\$ 39 bytes \$\endgroup\$ Commented Apr 20, 2021 at 0:56
  • \$\begingroup\$ @dingledooper Nice - thanks! :D \$\endgroup\$
    – Noodle9
    Commented Apr 20, 2021 at 1:12
  • \$\begingroup\$ @ceilingcat Nice one - thanks! :D \$\endgroup\$
    – Noodle9
    Commented Apr 20, 2021 at 9:50
  • \$\begingroup\$ 36 bytes \$\endgroup\$
    – jdt
    Commented Oct 8, 2022 at 16:37
3
\$\begingroup\$

Vyxal, 8 3 bytes

M$R

Try it Online!

Takes [g, [a, b], f]. If reduction was reversible, then this would be 2 bytes.

Explained

M$R
M   # map f over [a, b]
 $R # reduce that by g
\$\endgroup\$
3
\$\begingroup\$

Excel (Insider Beta), 29 bytes

=LAMBDA(f,g,a,b,g(f(a),f(b)))

LAMBDA is only available through Excel Insider Beta. The functions have to be defined as names to work. In my case, I defined a name q that is equal to the above and then used the formula =q(LAMBDA(x,x^2),LAMBDA(x,y,x+y),1,2) in a cell. This could also be done by defining the names a=LAMBDA(x,x^2) and b=LAMBDA(x,y,x+y) and then use the formula q(a,b,1,5).

\$\endgroup\$
3
\$\begingroup\$

Red, 24 bytes

func[f g x y][g f x f y]

Try it online!

This version doesn't work in TIO (Red is not up-to date), that's why I provide a screenshot from my Red GUI console:

enter image description here

TIO compatible version, 28 bytes

func[f g x y][do[g f x f y]]

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Husk, 5 4 bytes

₂₁⁰₁

Try it online!

Black-box functions are supplied as sequential lines in the code (in the footer in the TIO link), input values are given as program arguments.

₂₁⁰₁     # 2 argument function: second argument is implicit
   ₁     # perform function ₁ using second argument
 ₁⁰      # perform function ₁ using first argument
₂        # perform function ₂ using the last 2 values as arguments
\$\endgroup\$
2
  • \$\begingroup\$ I'm sure you can use F instead of Ẋ to return a value instead of an array. \$\endgroup\$
    – Razetime
    Commented Apr 20, 2021 at 7:25
  • \$\begingroup\$ @Razetime - Yes, you're right, that's much better. Thanks! \$\endgroup\$ Commented Apr 20, 2021 at 9:40
3
\$\begingroup\$

Coconut, 11 bytes

Takes input as Ꙫ(g)(f, [a, b]).

g->g<*..map

Try it online!

<*.. is the multi-arg backward function composition, which makes this function equivalent to

g->*args->g(*map(*args))
\$\endgroup\$
3
\$\begingroup\$

APL (Dyalog Unicode), 5 bytes (SBCS)

Full program version of rak1507's implementation.

⎕/⎕¨⎕

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Julia, 17 16 bytes

F(!,+,a,b)=!a+!b

Try it online!

Previous answer, 17 bytes

g*f*x=g(f.(x)...)

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Attache, 10 bytes

${z|x|>&y}

Try it online!

Takes input as F[f, g, [a, b]], where F is the above function.

This is two separate pipes: The vectorizing pipe |, and the regular pipe |>. z|x pipes each element of z into the unary function x, i.e., Map[x, z]. Then, this array is piped to &y, which passes each element of the array as a separate parameter.

Alternatives

${&y!x=>z}, 10 bytes. Same input as above.

{_2@@Map[_]}, 12 bytes. Takes parameters f and g, returns a function which takes a tuple [a, b] as input.

Attache (builtin), 3 bytes

`#:

Try it online!

Simple quote-operator. Called as (`#:)[g, f][a, b].

\$\endgroup\$
2
\$\begingroup\$

Stacked, 11 bytes

[@:g"!...g]

Try it online!

Simple anonymous function. Takes input on stack as (a b) f g.

Works by storing g as a temporary function variable. Then, applies the " transformation on function f, which makes it apply on each element its called on. ! calls this function f" on the tuple (a b). Then, we simply put these two elements on the stack and call g.

\$\endgroup\$
2
\$\begingroup\$

C (gcc), 30 bytes

#define o(f,g,a,b)g(f(a),f(b))

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Standard ML, 24 bytes

fn(f,g,a,b)=>g(f a)(f b)

Concurr pre-release, 50 bytes

$lambda\f:lambda\g:lambda\a:lambda\b::g(:f a)$:f b

Wow that's horrible.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ fn(f,g)=>g o map f if you use lists, but I haven’t counted to see if it’s actually shorter. Also with a tuple you can do g(f a,f b) which is certainly one shorter. \$\endgroup\$ Commented Apr 21, 2021 at 22:22

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