# Curried Broadcasting Comparison Operators

**URL:** <https://discourse.julialang.org/t/curried-broadcasting-comparison-operators/90613>\
**Category:** General Usage\
**Tags:** question, broadcasting, currying\
**Created:** [November 22, 2022, 1:24am UTC](https://discourse.julialang.org/t/curried-broadcasting-comparison-operators/90613 "2022-11-22T01:24:23Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [November 22, 2022, 1:24am UTC](https://discourse.julialang.org/t/curried-broadcasting-comparison-operators/90613/1 "2022-11-22T01:24:23Z")

</div>

This is not what I expected:

```julia
julia> >(2) === .>(2)
true

julia> .>(1:4)
4-element Vector{Base.Fix2{typeof(>), Int64}}:
 (::Base.Fix2{typeof(>), Int64}) (generic function with 1 method)
 (::Base.Fix2{typeof(>), Int64}) (generic function with 1 method)
 (::Base.Fix2{typeof(>), Int64}) (generic function with 1 method)
 (::Base.Fix2{typeof(>), Int64}) (generic function with 1 method)

```

Intuitively, I thought `.>(y)` would be a `broadcast(>, _, y)` partial applicator (in lambda terms, `x->broadcast(>, x, y)`), but instead it’s a `broadcast(Base.Fix2, >, y)`—making it so that it’s not a function, but an array of functions, and thus is not a callable object.

This is inconsistent with, for example, `.!`, which is a callable object and can be directly called on a collection:

```julia
julia> .!((true, false, true))
(false, true, false)

```

For comparison, `.>(y)` can’t be called on anything:

```julia
julia> (>(2))(1:4)
ERROR: MethodError: no method matching isless(::Int64, ::UnitRange{Int64})

julia> (.>(2))(1:4)
ERROR: MethodError: no method matching isless(::Int64, ::UnitRange{Int64})

julia> (.>(1:4))(2)
ERROR: MethodError: objects of type Vector{Base.Fix2{typeof(>), Int64}} are not callable

julia> (.>(1:4)).(2)
ERROR: MethodError: objects of type Vector{Base.Fix2{typeof(>), Int64}} are not callable

julia> (.>(1:4))(4:-1:1)
ERROR: MethodError: objects of type Vector{Base.Fix2{typeof(>), Int64}} are not callable

julia> (.>(1:4)).(4:-1:1)
ERROR: MethodError: objects of type Vector{Base.Fix2{typeof(>), Int64}} are not callable

```

I can only get it to do something under three scenarios:

```julia
julia> (.>(2))(2)
false

julia> (.>(2)).(1:4)
4-element BitVector:
 0
 0
 1
 1

julia> ((x,y)->x(y)).(.>(1:4), 4:-1:1)
4-element BitVector:
 1
 1
 0
 0

```

However, the first two scenarios are already covered by (non-broadcasted) `>(y)`:

```julia
julia> (>(2))(2)
false

julia> (>(2)).(1:4)
4-element BitVector:
 0
 0
 1
 1

```

So really, `.>(y)` (and all the other curried broadcasting binary operators) only do something useful in the case where a function which calls another function is being broadcasted.

Maybe I’m just unimaginative, but can someone help me out with finding a use case for this, and why this behavior is preferred over a partial function applicator on `broadcast`, e.g. `Fix{(1,3),3}(broadcast, >, 1:4)` (supposing that specializations on `broadcast` would be written for `Fix{typeof(broadcast)}` objects)? I can imagine use cases for `(.>(2))(1:4)` or for `(.>(1:4))(2)`, but I’m having trouble imagining use cases for its current behavior.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [November 23, 2022, 8:18am UTC](https://discourse.julialang.org/t/curried-broadcasting-comparison-operators/90613/2 "2022-11-23T08:18:27Z")

</div>

It’s just how broadcasting works in Julia: `f.(1:4) == [f(1), f(2), f(3), f(4)]`.  
Substitute `f` with `>`, and you get `.>(1:4) == [>(1), >(2), >(3), >(4)]`, that is an array of functions.  
And of course this is consistent with `!`: `.!((true, false, true)) == (!(true), !(false), !(true)) == (false, true, false)`.

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [November 23, 2022, 8:45am UTC](https://discourse.julialang.org/t/curried-broadcasting-comparison-operators/90613/3 "2022-11-23T08:45:47Z")

</div>

Relevant discussion: [Broadcasting tuple functions · Issue #22129 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/22129)

---

<div class="post-metadata">

**Author:** ![bert](https://avatars.discourse-cdn.com/v4/letter/b/9e8a1a/32.png) [@bert](https://discourse.julialang.org/u/bert)\
**Post date:** [October 4, 2023, 7:40pm UTC](https://discourse.julialang.org/t/curried-broadcasting-comparison-operators/90613/4 "2023-10-04T19:40:05Z")

</div>

You can get the desired behavior with the (very verbose) `Base.Broadcast.BroadcastFunction`, which “dots” the function it wraps:

```plaintext
julia> Broadcast.BroadcastFunction(<(2))
Base.Broadcast.BroadcastFunction(Base.Fix2{typeof(<), Int64}(<, 2))

julia> Broadcast.BroadcastFunction(<(2))([1, 2, 3])
3-element BitVector:
 1
 0
 0

julia> Broadcast.BroadcastFunction(<)
Base.Broadcast.BroadcastFunction(<)

julia> Broadcast.BroadcastFunction(<)([1, 2, 3])
3-element Vector{Base.Fix2{typeof(<), Int64}}:
 (::Base.Fix2{typeof(<), Int64}) (generic function with 1 method)
 (::Base.Fix2{typeof(<), Int64}) (generic function with 1 method)
 (::Base.Fix2{typeof(<), Int64}) (generic function with 1 method)

julia> Broadcast.BroadcastFunction(<)([1, 2, 3], [3, 2, 1])
3-element BitVector:
 1
 0
 0

```

But I agree that given the verbosity of this, it would be great to have something simpler. `.<(2)` can’t work for syntactic reasons. But if `.!` and `.<` are how you create the dotted versions of _those_ functions, why not just allow `.f` to mean “`f`, but dotted” for any function `f`. So `.<(2)` would still broadcast `<` over `2`, giving `(::Base.Fix2{typeof(<), Int64})`, but `.(<(2))` would give `Base.Broadcast.BroadcastFunction(Base.Fix2{typeof(<), Int64}(<, 2))`.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [October 4, 2023, 8:06pm UTC](https://discourse.julialang.org/t/curried-broadcasting-comparison-operators/90613/5 "2023-10-04T20:06:22Z")

</div>

> [@bert](#):
>
> You can get the desired behavior with the (very verbose) `Base.Broadcast.BroadcastFunction`, which “dots” the function it wraps:

You can just do `<(2).(x)` to broadcast `<(2)`, like `f.(x)` for any other function `f`:

```julia
julia> <(2).([3,2,1])
3-element BitVector:
 0
 0
 1

```

---

<div class="post-metadata">

**Author:** ![bert](https://avatars.discourse-cdn.com/v4/letter/b/9e8a1a/32.png) [@bert](https://discourse.julialang.org/u/bert)\
**Post date:** [October 4, 2023, 8:18pm UTC](https://discourse.julialang.org/t/curried-broadcasting-comparison-operators/90613/6 "2023-10-04T20:18:19Z")

</div>

Yes, but you can’t use this to pass the broadcasted function around as a first-class object. This only allows you to call the function immediately.
