Skip to content

Instantly share code, notes, and snippets.

@yutannihilation
Created September 17, 2018 02:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yutannihilation/1c227c6d662c991cc2c66ca146de80ea to your computer and use it in GitHub Desktop.
Save yutannihilation/1c227c6d662c991cc2c66ca146de80ea to your computer and use it in GitHub Desktop.
foo <- function(x = list()) structure(x, class = "foo")
`+.foo` <- function(e1, e2) message("foo!")

bar <- function(x = list()) structure(x, class = "bar")
`+.bar` <- function(e1, e2) message("bar?")

# unaddable, no methods
list() + list()
#> Error in list() + list(): non-numeric argument to binary operator

# unaddable, first one has a method
foo() + 1
#> foo!
#> NULL

# unaddable, second one has a method
1 + foo()
#> foo!
#> NULL

# unaddable, both have methods
foo() + bar()
#> Warning: Incompatible methods ("+.foo", "+.bar") for "+"
#> Error in foo() + bar(): non-numeric argument to binary operator

# addable, both have methods
foo(1) + bar(1)
#> Warning: Incompatible methods ("+.foo", "+.bar") for "+"
#> [1] 2
#> attr(,"class")
#> [1] "foo"

Created on 2018-09-17 by the reprex package (v0.2.0).

@yutannihilation
Copy link
Author

  1. Enter do_arith().

https://github.com/wch/r-source/blob/5a156a0865362bb8381dcd69ac335f5174a4f60c/src/main/arithmetic.c#L386

  1. If both arguments are not missing, do DispatchGroup().

https://github.com/wch/r-source/blob/5a156a0865362bb8381dcd69ac335f5174a4f60c/src/main/arithmetic.c#L403-L404
https://github.com/wch/r-source/blob/fabab8108783c8c48ae277120cfa0046b7b48f17/src/main/eval.c#L3541

  1. If one of these is S4 and has a S4 method, use it.

https://github.com/wch/r-source/blob/fabab8108783c8c48ae277120cfa0046b7b48f17/src/main/eval.c#L3563-L3575

  1. Otherwise, try S3 method dispatch; find methods for each.

https://github.com/wch/r-source/blob/fabab8108783c8c48ae277120cfa0046b7b48f17/src/main/eval.c#L3606-L3614

  1. If both objects don't have S3 method, fall back to R_binary(). (If either one is a scalar, there's a shortcut, but I omit the detail here.)

https://github.com/wch/r-source/blob/fabab8108783c8c48ae277120cfa0046b7b48f17/src/main/eval.c#L3618-L3621
R_binary(): https://github.com/wch/r-source/blob/5a156a0865362bb8381dcd69ac335f5174a4f60c/src/main/arithmetic.c#L493-L494

  1. If both objects have different S3 methods, fall back to R_binary() with a warning. (There's some extra step for difftime, but I omit the detail here.)

https://github.com/wch/r-source/blob/fabab8108783c8c48ae277120cfa0046b7b48f17/src/main/eval.c#L3623-L3641

  1. If one of the objects has an S3 method and the other doesn't, use it.

https://github.com/wch/r-source/blob/fabab8108783c8c48ae277120cfa0046b7b48f17/src/main/eval.c#L3642-L3649 (See lsxp and lmeth are used in the following lines)

  1. If both objects have the same S3 method, use it.

R_binary()

https://github.com/wch/r-source/blob/5a156a0865362bb8381dcd69ac335f5174a4f60c/src/main/arithmetic.c#L518

  1. If either argument is not NILSXP, CPLXSXP, REALSXP, INTSXP, or LGLSXP, raise an error.

https://github.com/wch/r-source/blob/5a156a0865362bb8381dcd69ac335f5174a4f60c/src/main/arithmetic.c#L529-L530
FIXUP_NULL_AND_CHECK_TYPES() https://github.com/wch/r-source/blob/5a156a0865362bb8381dcd69ac335f5174a4f60c/src/main/arithmetic.c#L510-L516

  1. Do complex_binary() or real_binary() or integer_binary(). (There's a lot of special treatments on ts and array, but I omit the details here)

https://github.com/wch/r-source/blob/5a156a0865362bb8381dcd69ac335f5174a4f60c/src/main/arithmetic.c#L648-L673

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment