If f = +, why can't I use f as an infix operator (e.g., 2 f 3 == 5)?

3 + 4 gives the usual result. f = + followed by 3 f 4 gives an error.

Why doesn’t this work?

Only some operators have infix syntax.

3 Likes

Yes, and + is one of them. Why does + work and f does not, when f == x?

You can do

julia> f = +
+ (generic function with 190 methods)

julia> f(3, 4)
7

julia> +(3,4)  # above is same as 
7

The same problem occurs with +(3,4) vs. f(3,4) when f == +

That works on the command line, but when I try it in code, it fails.

This comment suggests your mental model is that the bound values of operators determine what syntax is allowed, but the syntax is not influenced by values at all.

3 Likes

Here is the function that fails:

function apply(f)
printstyled("\nenter apply", color=:green)
ar = methods(+).ms[1].nargs-1 # get function arity
if ar == 1
x = pop()
push(f(x))
return
elseif ar == 2

	printstyled("\nS = $S", color = :green)

	x = pop()
	y = pop()

	printstyled("\napply:f=$f x=$x y=$y ", color=:green)

	push(f(x,y))
	return
elseif ar == 3
	x = pop() 
	x = pop()
	z = pop()
	push(f(x,y,z)) 
end
printstyled("\nleave apply", color = :green)

end

The error occurs at the ar == 2 part.

Clearly the runtime variables are as follows: f = +, x = 3, and y = 2. So, f(x,y) should result in 5.

But here is the resulting console output:

enter apply
S = Stack{Any}(Deque [Any[2, 3]])
apply:f=+ x=3 y=2
ERROR: MethodError: objects of type SubString{String} are not callable

Why should code that works on the command line not work in code? That conflicts with the entire idea of developing interactively, then putting the checked out code in a file.

It works for me in code. File foo.jl

function foo(f, x, y)
    f(x,y)
end
julia> include("foo.jl")
foo (generic function with 1 method)

julia> foo(+,3,4)
7
1 Like

Unfortunately none of us can run that example because none of push, pop and S are defined. If you could provide those and reduce it into a MWE (see Please read: make it easier to help you), we can dig into it.

I just tried putting this into a file and running it:

f = +
x, y = 2, 3
println(f(x, y))
println(+(x, y))

As expected, it prints out 5 twice.

Edit: to elaborate on @johnmyleswhite’s point, most languages with infix operators (i.e. not lisps or forths) allow a limited number of symbols in infix position. This is a parsing restriction as opposed to a runtime one, so while you can overload the meaning of those symbols, you can not use symbols or identifiers that have not been explicitly allowed by the parser in infix position. There are languages that allow arbitrary infix functions (e.g. Kotlin, Haskell), but they must be escaped with something like lhs `infixop` rhs (as opposed to native infix functions, which do not require escaping).

4 Likes

OK, I guess I must use that format. Thanks for the input!

1 Like

The only difference I can is that I’m passing the function in to apply and popping x and y off a stack.

I take your point about infix functions. Thanks!

The big difference is that f has mysteriously become a string instead of a reference to a function (hence MethodError: objects of type **SubString{String}** are not callable). That shouldn’t be happening from the snippet you posted, so some external code must be to blame.

I thought that also, but no other code is running. Notice the printout that clearly shows
f = + and is not a string. Very strange…

I found the problem, cockpit error as usual. Thanks for all the help!

4 Likes