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