Recently I found it quite complicated to call the function factorial()
. I feel it too long for such a function that is so frequently used in some situations. Can we make it simpler? Like !(n)
(I found that the operator !
does not have a method for ::Integer
), for example.
Iāve never found the argument about length of functions/commands compelling, in any language. If you get tired of typing itās probably a sign you need better tooling (for example some more help from your IDE), but bending a language because you donāt want to type to more is never a good idea.
If you have some factorial-heavy code you can introduce an alias yourself.
julia> const ! = factorial
factorial (generic function with 7 methods)
julia> !(5)
120
For performance reasons itās important to use const
.
Does this hide ! as negation? If so, everywhere?
Just in your code.
Well, I guess thatās a little heavy-handed. In your own code itās probably a better idea to commit some type piracy with
Base.:!(x::Int) = factorial(x)
but on the whole it would be advisable to alias it to something truly private.
And then again it is debatable whether !(5)
is truly more readable than factorial(5)
, especially in a language where !
usually means boolean negation
If you have a high factorial density in your code I think itās an arguable improvement but since it definitely means something different from negation it will never be considered for Base.
If you really want to commit a crime, with this
julia> Base.:(*)(n::Int, ::typeof(Base.:(!))) = factorial(n)
julia> 5(!)
120
at least you get the order right (although you need too many parentheses) But again, donāt do it!
Thanks. It wouldnāt ever happen in my code. I was just curious how much potential damage it would cause.
You can just do
julia> !5
120
[I think actually `5!` could be made to do this, as in with Unitful.jl, but Iām not sure.]
You can get this with one letter, and readable in a way, i.e. using the correct functional form with the related gamma function:
julia> Ī(6) # Yes, you still have to type \Gamma<TAB>
120
after defining:
julia> const Ī(x::Integer) = factorial(x-1)
Ī (generic function with 2 methods)
The gamma function is there:
Iām not going to propose adding const Ī(x::Number) = gamma(x)
there (which gives Float64), I suppose the Greek letters were considered too valuable to also claim one of them.
Hm. Maybe:
julia> struct Factorial end
julia> const _! = Factorial()
Factorial()
julia> Base.:*(n::Integer, ::Factorial) = factorial(n)
julia> 5_!
120
?
It doesnāt parse:
julia> 5!
ERROR: syntax: extra token "!" after end of expression
Stacktrace:
[1] top-level scope
@ none:1
I like it.
julia> struct Factorial end
julia> const ā¢ = Factorial()
julia> Base.:*(n::Integer, ::Factorial) = factorial(n)
julia> 5ā¢
120
Thatās very clever but isnāt Base.*
supposed to be for a function that behaves like multiplication?
Not really much danger in abusing it here for nice juxtaposition notation
Or const ā = Factorial()
, which can be typed by \:exclamation:<tab>
.
Honestly, though, Iām a bit curious about what kind of code makes such heavy use of factorial
that a shortcut is worth it.
(A common mistake is calling factorial
when evaluating series formulas. See also this tutorial.)
Mineās the āfat-torialāā¦
Sometimes you want to optimize for performance and or numerical accuracy. Other times you know that doesnāt matter in your case and you just want to write pretty code