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⍥+ 2

We would first calculate 2 of each argument: 12 = 1 and 22 = 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) = x2
g(x,y) = x - y
-2, 2 -> 0
f(x) = φ(x) (Euler totient function)
g(x,y) = 2x + y
5, 9 -> 14
f(x) = x3-x2-x-1
g(x,y) = y4-x3-y2-x
-1, -1 -> 22
f(x) = x
g(x,y) = x / y (Integer division)
-25, 5 -> -5
asked Apr 20, 2021 at 0:17
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Can we take a & b as an array [a,b]? \$\endgroup\$ Commented Apr 20, 2021 at 7:12
  • \$\begingroup\$ @Shaggy Yes you can \$\endgroup\$ Commented Apr 20, 2021 at 11:31

52 Answers 52

1
2
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.

answered Apr 20, 2021 at 0:42
\$\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.

answered Apr 20, 2021 at 1:30
\$\endgroup\$
1
  • \$\begingroup\$ Exactly what I had in mind :) \$\endgroup\$ 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.

answered Apr 20, 2021 at 4:23
\$\endgroup\$
1
  • \$\begingroup\$ "unlike in Dyalog APL" ― works fine in, say, NARS2000. \$\endgroup\$ 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!

answered Apr 20, 2021 at 0:25
\$\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\$ Commented Apr 20, 2021 at 8:18
  • \$\begingroup\$ 20 \$\endgroup\$ Commented Jan 9, 2023 at 21:36
  • \$\begingroup\$ due to rule clarify \$\endgroup\$ 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?

answered Apr 20, 2021 at 0:42
\$\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

answered Apr 20, 2021 at 0:40
\$\endgroup\$
3
  • 3
    \$\begingroup\$ Also worth pointing out this exists in the standard library as 'on' in Data.Function \$\endgroup\$ 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\$ 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!

answered Apr 20, 2021 at 0:29
\$\endgroup\$
2
  • \$\begingroup\$ ⎕/⎕¨⎕ \$\endgroup\$ 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\$ 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))
answered Apr 20, 2021 at 0:30
\$\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).

answered Apr 20, 2021 at 0:50
\$\endgroup\$
6
\$\begingroup\$

Wolfram Language (Mathematica), 10 bytes

#2@@#/@#3&

Try it online!

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

answered Apr 20, 2021 at 3:13
\$\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.

answered Apr 20, 2021 at 10:20
\$\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\$ 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\$ Commented Apr 21, 2021 at 1:09
  • \$\begingroup\$ ...and there's Binary Combinatory Logic. Time to build an online interpreter... \$\endgroup\$ 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\$ Commented Apr 21, 2021 at 14:54
  • \$\begingroup\$ @Bubbler OK I've tried again and come up with your answer. \$\endgroup\$ 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
answered Feb 3, 2022 at 4:26
\$\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!

answered Apr 20, 2021 at 0:44
\$\endgroup\$
2
  • \$\begingroup\$ You can save a byte by taking input as a list [a,b] \$\endgroup\$ 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)

answered Apr 20, 2021 at 0:52
\$\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\$ 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\$

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).

answered Apr 20, 2021 at 2:06
\$\endgroup\$
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

answered Apr 20, 2021 at 2:10
\$\endgroup\$
4
\$\begingroup\$

Proton, 21 bytes

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

Try it online!

Time to bring out this garbage again :D

answered Apr 20, 2021 at 2:39
\$\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.

answered Apr 20, 2021 at 2:43
\$\endgroup\$
7
  • \$\begingroup\$ Cant this be packed? \$\endgroup\$ 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\$ Commented Apr 20, 2021 at 7:23
  • \$\begingroup\$ "a full program" submission can surely be packed to save a byte. \$\endgroup\$ Commented Apr 20, 2021 at 7:24
  • \$\begingroup\$ nah. not doing it. \$\endgroup\$ Commented Apr 20, 2021 at 7:24
  • \$\begingroup\$ Okay boomer :p. How about explaining how the link works \$\endgroup\$ 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!

answered Apr 20, 2021 at 4:05
\$\endgroup\$
1
  • \$\begingroup\$ Since you're allowed to take an array of arguments you can omit the first * in your second solution. \$\endgroup\$ 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!!!

answered Apr 20, 2021 at 0:38
\$\endgroup\$
4
  • \$\begingroup\$ 39 bytes \$\endgroup\$ Commented Apr 20, 2021 at 0:56
  • \$\begingroup\$ @dingledooper Nice - thanks! :D \$\endgroup\$ Commented Apr 20, 2021 at 1:12
  • \$\begingroup\$ @ceilingcat Nice one - thanks! :D \$\endgroup\$ Commented Apr 20, 2021 at 9:50
  • \$\begingroup\$ 36 bytes \$\endgroup\$ 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
answered Apr 20, 2021 at 0:28
\$\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!

answered Apr 20, 2021 at 7:00
\$\endgroup\$
3
\$\begingroup\$

Husk, (削除) 5 (削除ここまで) 4 bytes

2101

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.

2101 # 2 argument function: second argument is implicit
 1 # perform function 1 using second argument
 10 # perform function 1 using first argument
2 # perform function 2 using the last 2 values as arguments
answered Apr 20, 2021 at 6:53
\$\endgroup\$
2
  • \$\begingroup\$ I'm sure you can use F instead of Ẋ to return a value instead of an array. \$\endgroup\$ 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))
answered Apr 20, 2021 at 6:05
\$\endgroup\$
3
\$\begingroup\$

APL (Dyalog Unicode), 5 bytes (SBCS)

Full program version of rak1507's implementation.

⎕/⎕ ̈⎕

Try it online!

answered Apr 20, 2021 at 20:22
\$\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!

answered Apr 20, 2021 at 11:53
\$\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].

answered Apr 20, 2021 at 9:16
\$\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.

answered Apr 20, 2021 at 13:08
\$\endgroup\$
2
\$\begingroup\$

C (gcc), 30 bytes

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

Try it online!

answered Apr 20, 2021 at 13:16
\$\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.

answered Apr 20, 2021 at 13:35
\$\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
1
2

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.