-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Use super script T as tranpose operator instead of .' #19344
Conversation
@@ -1116,4 +1116,8 @@ Filesystem.stop_watching(stream::Filesystem._FDWatcher) = depwarn("stop_watching | |||
@deprecate takebuf_array take! | |||
@deprecate takebuf_string(b) String(take!(b)) | |||
|
|||
# Deprecate .' syntax for transpose | |||
matlabtranspose(x) = depwarn(string(".' is now depreacted in favor of ᵀ, i.e. superscipt T which ", | |||
"you can type \\^T[tab] in the REPL, Jupyter, and most editors"), :matlabtranspose) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think "most editors" really is true,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably not. Then "most common editors" maybe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You typically need plugins as well, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...then maybe "most common editors have plugins supporting this"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM
@@ -662,6 +662,7 @@ export | |||
lufact!, | |||
lufact, | |||
lyap, | |||
matlabtranspose, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should go in deprecated.jl so we know to remove it eventually. I would also rename it something like nonctranspose
. Alternatively, this function could be avoided entirely by giving the deprecation warning during lowering.
If we do this, maybe we should also add superscript |
Maybe add |
I'm a little concerned about the precedent set by making some superscripts operators while others are parts of variable names. Still, this is appealing. |
I find this non-ascii chars an unnecessary pain that users would be subjected when writing in a text editor. For example, I simply do not know how to do it and imagine trying to do a transpose and have to go google on how to do it. Might look nice but doesn't pay. |
I have to say I don't like this. It is nice to be able to do Also, I think the adjoint |
(@joa-quim, you can type |
Also, superscript T has other uses, e.g. in international macro It just seems much more sensible to me to let all letterlike and numberlike characters form part of an identifier, rather than making a few special cases into operators. |
I know (sort of) how to use latex on REPL and But my point is not for me in particular. Just imagine the number of users that would stuck when trying to do a transpose and find that they would have to find how print that Unicode (or any other) to do what can simply and usually be done with |
@joa-quim You can also do it Sublime with the UnicodeCompletion package. I use that all the time. Generally, I also think we beyond the point in Julia where we want to be restricted to ASCII. There is simply too much good stuff in unicode that makes code easier to read and with editor and REPL support these are easy to write. The policy has typically been that there should always be an ASCII alternative, e.g. you can write The only drawback I see is the "minor problem" I mentioned initially which @stevengj also mentions, i.e. we lose I guess that most of the arguments have been mentioned at this point so we should probably just let the thumbs speak. |
This argument makes a better case for nixing the exceptional syntax altogether than for changing the symbols involved :). |
@andreasnoack I installed UnicodeCompletion but nothing happens when I do Really, one thing is to a able to use Unicode symbols. Another, very different, is to make it's use almost mandatory (for some cases like this ofc). |
I really don't think the slight syntactic oddity of Moreover, |
This will go away with a matrix transpose type which we plan to do anyway. At that point, |
Yeah, we've been discussing a transpose type for ages (e.g. JuliaLang/LinearAlgebra.jl#42); it comes with its own tradeoffs. But at the very least this PR cannot even be considered until such a time as a |
The issue is not JuliaLang/LinearAlgebra.jl#42. We can (and most likely will) have a matrix transpose type without/before a vector transpose type.
I appreciate your critique but I think it's unfair to other participants to claim a veto right over what can and cannot be considered. Anyway, I made this RFC to get some feedback. I'm not in a hurry. @joa-quim I confused two of my packages. The completion is in the "Julia" package not in the "UnicodeCompletion" package. |
I would give a thumps up if |
I have to say I'm not sure what fundamental problem new syntax addresses here, aside from making the conjugate-transpose less likely to be used on values for which conjugation doesn't make sense. Wouldn't introducing a |
But Addressing that is, of course, a separate issue from adding a new syntax for transposition. |
That's true, but I'm way less concerned with that one irregularity than I am about the fundamental problems we have with generic (c)transpose. |
Indeed I think the fact that OTOH, using I think my vote would be to use |
I'm generally in favor for having a "beautified" unicode version so long as it doesn't degrade the ASCII experience. However, to be honest, we are really running out of ASCII characters... consider function composition which just plain looks better and more sensible as an operator Thus I would be OK with having e.g. A final idea: we can easily define Random thought. if
True, and I agree, but OTOH how cool would it be if @andreasnoack wrote
Is that a challenge? ;) |
I wasn't sure at first but I've now decided that I'm against this change. While |
Why would this require Unicode characters? |
If you have a real matrix, |
@KristofferC If we require @stevengj Yeah, that's a good point... |
@stevengj I would buy that argument if |
@nalimilan, see JuliaLang/LinearAlgebra.jl#257 ... it's unfortunate that the |
As stevengj said, I'm against using My dot-vectorized argument was not good. But with a bit wider perspective one could maybe say that dots were introduced to ~save a 'oh so convenient' syntax (mostly vectors but sometimes, like here, special cases). I still think |
I'm not an expert in this maters and I'm not suggesting by any menas to do it this way, yet I kinda like my way of doing this, something like this: julia> const ᵀ = ctranspose;
julia> Base.:*{T<:Number}(x::AbstractMatrix{T}, f::typeof(Base.ctranspose)) = f(x)
julia> A = rand(2, 2);
julia> Aᵀ = (A)ᵀ
2×2 Array{Float64,2}:
0.943234 0.64957
0.00476442 0.596362
julia> In this example I came with this while playing around in twitter, see if I could do this in just one tweet! So I'll leave this just for reference to you. Still trying to generalize this syntax proves difficult as things are now, ie I want to say now julia> square(n) = n^2; cube(n) = n^3;
julia> Base.:*(n, f::typeof(square)) = f(n)
julia> Base.:*(n, f::typeof(cube)) = f(n)
julia> const ² = square # why?
syntax: invalid character "²"
julia> const ³ = cube # why?
syntax: invalid character "³"
julia> n = 3;
julia> n² = (n)square # I want: (n)² instead
9
julia> n³ = (n)cube # I want: (n)³ instead
27
julia> I still don't understand what is allowed and what not, the only way to tell is to try to do it, or try to understand the parser perhaps. Edit: ...mmm in this case I think it's because both are number like: julia> const ⁽²⁾ = square
square (generic function with 1 method)
julia> n² = (n)⁽²⁾
9
julia> const ⁽³⁾ = cube
cube (generic function with 1 method)
julia> n³ = (n)⁽³⁾
27 This makes it legal but more impractical IMO. |
@Ismael-VC, superscripts are too useful for variable names, e.g. you can currently have a variable named (This only goes to show what a can of worms And |
@nalimilan wrote
To me it seems crucial that the purpose of @ararlsan the ASCII version of the postfix operator @stevengj wrote
From my interpretation, I thought that @Ismael-VC was suggesting the brackets were mandatory, like I don't understand why the parser treats |
@stevengj @andyferris yes, they are, this is not mock up syntax, this works already without touching the parser, we'd only need to define the The whole example from the tweet was: Suppose I would like to do: julia> for (func, n) in Dict(:square => 2, :cube => 3, :pow¹² => 12)
@eval $(func)(x) = x^$n
end;
julia> for (super_script, func) in Dict(
:⁻¹ => :inv, :⁽²⁾ => :square, :⁽³⁾ => :cube, :⁽¹²⁾ => :pow¹²,
:ᵀ => :transpose, :ᴴ => :ctranspose
)
@eval begin
const $super_script = $func
Base.:*{T <: Number}(x::T, f::typeof($func)) = f(x)
Base.:*{T <: Number}(x::AbstractArray{T}, f::typeof($func)) = f(x)
end
end;
julia> d = 2; G = rand(d, d)
2×2 Array{Float64,2}:
0.720101 0.967408
0.724678 0.318131
julia> Gᵀ = (G)ᵀ # implicit multiplication, see: http://bit.ly/NumericLiteralCoeficients_JL
2×2 Array{Float64,2}:
0.720101 0.724678
0.967408 0.318131
julia> GGᵀ = G * Gᵀ
2×2 Array{Float64,2}:
1.45442 0.829604
0.829604 0.626366
julia> m̂ = Gᵀ * (GGᵀ)⁻¹ * (d)⁽²⁾
2×2 Array{Float64,2}:
-2.69618 8.19885
6.1417 -6.1029
julia> m̂¹² = (m̂)⁽¹²⁾
2×2 Array{Float64,2}:
2.51495e12 -3.68582e12
-2.76102e12 4.04645e12
julia> :(m̂⁽¹²⁾= (m̂)⁽¹²⁾)
:(m̂⁽¹²⁾ = m̂ * ⁽¹²⁾)
julia> It's effectively some kind of reverse application syntax, ie. instead of |
@andyferris, there is a difference between something being a digit allowed in a literal vs. a digit allowed (as the second or later character) in an identifier. The latter is anything in one of the three Unicode "number" categories (Nd, Nl, and No). Superscripts like ² are in No (Number, other). Using Unicode character categories to decide whether a character is allowed is an identifier is a huge win. It allows us to include huge swaths of characters using sensible general rules, without having to special-case each one (especially hard in non-English languages), and is automatically updated when the Unicode standard is revised (utf8proc's tables are updated by a semi-automatic process). In contrast, I don't think we want to allow numeric literals using anything other than ASCII decimals. |
That being said, there is a reasonable argument for allowing characters in categories No |
(I just ran into a case today where it was really nice to be able to use |
(See #20278 for allowing category No to start identifiers.) |
It is compelling to have this beautiful mathematical syntax in a language, but on the other hand it seems inconsistent with other decisions previously taken, like for instance A^2. Having to think if unicode means something or not can get in the way of programming productivity. I am neutral on this one, it definitely requires deeper thought of the pros and cons. |
While the small amount of ASCII operators should be enough for compilers in theory, it surely can't meet the simplicity requirement for many people that is used to common mathematical operations from mathematical background. |
Thought it might be worth pointing out that in v0.7 we will have non recursive transpose (for data manipulation - can transpose a matrix or vector of strings) and recursive Perhaps this might create the raison d'être for another operator (or a change in operators) in this space? |
Regardless of whether we want another operator, I don't like the idea of singling out one or two superscripts as operators. They are too useful in identifiers. |
With my hack both kinda worked, but the idea is that:
|
We no longer have special syntax for the transpose so I'll close. |
Would it at all be possible to allow certain symbols to be used as both identifiers and operators. Could we allow super script T to be used as an operator, but not define it in base? I'd like to use it in https://github.com/musm/EasyTranspose.jl so that we can write |
Now that we have gotten used to the nice dot broadcast syntax, our
.'
transpose seems like an odd inheritance from Matlab. Therefore in this PR, I'm trying outᵀ
as the symbol for (non-conjugate) transpose of a matrix, i.e.For most of us, it is
twothree keystrokes more (\^T[tab]
) but I think it reads so much nicer that it is worth it. Only minor problem is ifAᵀ
is used as an identified but it will error and it will probably be a minor inconvenience to change the name.