How about to simplify the factorial function name?

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.

13 Likes

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.

7 Likes

Does this hide ! as negation? If so, everywhere?

3 Likes

Just in your code. :slight_smile:

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.

2 Likes

And then again it is debatable whether !(5) is truly more readable than factorial(5), especially in a language where ! usually means boolean negation

10 Likes

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) :stuck_out_tongue_winking_eye: But again, don’t do it!

6 Likes

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

:smiley:

1 Like

[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.

2 Likes

Hm. Maybe:

julia> struct Factorial end

julia> const _! = Factorial()
Factorial()

julia> Base.:*(n::Integer, ::Factorial) = factorial(n)

julia> 5_!
120

?

7 Likes

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

:slight_smile:

9 Likes

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>. :wink:

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.)

5 Likes

Mine’s the ‘fat-torial’… :grinning:

3 Likes

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

1 Like