I think this option is a little cleaner, since you can keep the function separate and doesn't require modification of the function, which could be annoying if it is a complex function, or if the user doesn't have direct access to it (as may be the case here with the actual function he is interested in):
p.list <- unname(split(p, row(p))) # `p` is as produced in question
mapply(hypotenuse, head(p.list, -1L), tail(p.list, -1L))
# [1] 1.414214 1.414214 1.414214 1.414214
Using the same hypotenuse
question poster used. The key here is converting your original p matrix into a list containing x-y coordinate pairs, which then allows us to use mapply
.