JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.43k stars 5.46k forks source link

Use `\mapsto` ( ↦ ) for anonymous functions #11223

Open dpsanders opened 9 years ago

dpsanders commented 9 years ago

It would be nice to be able to use the correct mathematical notation " ↦ " (\mapsto) for anonymous functions, x ↦ f(x), in addition to x -> f(x)

This sounds like it should be a relatively easy addition to the parser (but I don't know where to start).

StefanKarpinski commented 9 years ago

+1

jakebolewski commented 9 years ago

If you want to try it out

diff --git a/src/julia-parser.scm b/src/julia-parser.scm
index 36981c0..b4a1423 100644
--- a/src/julia-parser.scm
+++ b/src/julia-parser.scm
@@ -64,7 +64,7 @@
 ; operators that are special forms, not function names
 (define syntactic-operators
   '(= := += -= *= /= //= .//= .*= ./= |\\=| |.\\=| ^= .^= ÷= .÷= %= .%= |\|=| &= $= =>
-      <<= >>= >>>= -> --> |\|\|| && |.| ... |.+=| |.-=|))
+      <<= >>= >>>= -> ↦ --> |\|\|| && |.| ... |.+=| |.-=|))
 (define syntactic-unary-operators '($ & |::|))

 (define syntactic-op? (Set syntactic-operators))
@@ -74,7 +74,7 @@
 (define ctrans-op (string->symbol "'"))
 (define vararg-op (string->symbol "..."))

-(define operators (list* '~ '! '¬ '-> '√ '∛ '∜ ctrans-op trans-op vararg-op
+(define operators (list* '~ '! '¬ '-> '↦ '√ '∛ '∜ ctrans-op trans-op vararg-op
                          (delete-duplicates
                           (apply append (map eval prec-names)))))

@@ -897,7 +897,7 @@
       (case t
         ((|::|) (take-token s)
          (loop (list t ex (parse-call s))))
-        ((->)   (take-token s)
+        ((->  ↦)   (take-token s)
          ;; -> is unusual: it binds tightly on the left and
          ;; loosely on the right.
          (let ((lno (line-number-filename-node s)))
tkelman commented 9 years ago

Would it need to be removed from prec-arrow?

jakebolewski commented 9 years ago

Yes, it should be if this were the a formal PR. But -1 on this proposal, I don't like the use of unicode for special forms that have a perfectly sane ascii equivalent.

jakebolewski commented 9 years ago

Similar to #8487

dpsanders commented 9 years ago

@jakebolewski Great, thanks for the code sample.

I see where you're coming from, but it seems to me that basically all unicode would be excluded by your reasoning, e.g. using α (\alpha) instead of alpha.

From my point of view, one of the points of allowing unicode is that code can resemble hand-written (or LaTeX) equations as much as possible. \mapsto is a nice step in that direction. #8487 is not quite the same, since in maths you don't actually write for i ∈ 1:10.

stevengj commented 9 years ago

+1. It seems like there is no other sane meaning for \mapsto other than ->, so if we are going to accept it at all, we might as make the two synonyms. No different from \sqrt for sqrt or \le for <=.

JeffBezanson commented 9 years ago

One difference is that it's a special form, so can't be handled with a simple alias.

stevengj commented 9 years ago

One counter-proposal: it might be useful to parse \mapsto as a macro @mapsto args body. e.g. @timholy's FastAnonymous package could then make x ↦ f(x) turn into @anon x -> f(x), and in general a package could use this for construction of new function-like objects.

MithrandirMiles commented 9 years ago

:+1: That's a cool use of the Unicode character!

MikeInnes commented 9 years ago

+1

StefanKarpinski commented 9 years ago

I really don't think we should make an operator for something that is a stopgap for something that just ought to be fixed.

tkelman commented 9 years ago

Reminds me of the macro-parsing of ~ which seems a bit arbitrary to me. If you want macro parsing, shouldn't you use a macro?

shashi commented 9 years ago

Yes, ~ being a macro was surprising

I like @stevengj's idea of allowing a few infix operators as macros, although I'm not sure if is a good candidate for it.

A bit unrelated: I'd really like to use ~> and <~ as aliases for lift in Reactive... e.g. lift(sqrt, signal) would be equivalent to signal ~> sqrt or sqrt <~ signal. Currently this is not possible though.

stevengj commented 9 years ago

The reason I suggested a macro for is that if (a) we parse for overloading, the most sensible use for it would be for user-defined function-like syntaxes (FastAnonymous being just one example) and (b) if you want to define your own function-like operator syntax, you kind of need a macro.

nalimilan commented 9 years ago

It would look less confusing to me to have and -> mean exactly the same thing.

MikeInnes commented 9 years ago

~ is a slightly weird special case, but if anything I'd vote for fixing that by making more operators parse as macros, not fewer – and if that's not feasible I think the benefit of a few special cases outweighs the aesthetic cost. They're really, really useful for making intuitive APIs. As an example of a non-DataFrames use of ~ I'm working on an object system of sorts with syntax

object~method(x, y)

Of course, I could write this as

@call object.method(x, y)

but if you're using the system a lot this adds a ton of noise to the code. It's really nice to have an escape hatch here.

I agree that it wouldn't be right to make this work specifically for FastAnonymous, but as @stevengj says this could have plenty of uses for function-like things (Reactive.jl, function-like operators, etc.).

shashi commented 9 years ago

I was noting that should either parse as macro OR as a synonym for ->, and cannot have both meanings. I agree that is a useful symbol to parse as a macro. One more thing to note: the usefulness of a macro operator will go away if two packages define macros of the same name, i.e. you cannot use the infix notation (for one of them) anymore if both packages are loaded.

tkelman commented 9 years ago

@one-more-minute I'm not convinced. In addition to macro-operators being poorly composable due to the lack of namespacing, there's already a quite straightforward escape hatch for dsl's to cut down on macro-call noise:

@dsl begin
    # anything you want
end
jasonmorton commented 9 years ago

Julia's support of Latex notation for unicode makes it really easy to create mathematical DSLs that look and feel like the mathematics we are used to writing. I'm making liberal use of them as operators (\otimes, \circ) myself. However, every time a symbol is reserved in the base language, the ability to do this is diminished. Keep in mind that the same symbol, however standard it may seem to be, ends up used differently in different subfields of math, physics, economics, and so on where Julia may be used. For a non-unicode example, I had to rewrite a lot of code when capital I became UniformScaling, since I was using it to mean the monoidal identity in a monoidal category, where that use is also standard.

Another consideration is that unicode support is still buggy in many places (e.g. the red boxes in saved IJulia notebooks). For example, the default system font in Ubuntu 15.04 causes unicode characters to behave incorrectly (spacing issues causing illegibility or huge spaces) in the Julia terminal and in emacs until the font settings are changed.

You gave us unicode and you can take it away, but let me plead for extreme caution in reserving things.

Jutho commented 7 years ago

I'll ask this here, as I did not right away find any other appropriate issue and I guess several of the Unicode & Julia experts are subscribed to this issue. I didn't want to open a new issue right away for something so small.

It's great that \mapsto at least parses as infix operator. Strangely enough, this is not true for \mapsfrom. \leftarrow and \rightarrow both work and could serve as an alternative if there is a good reason why this is the case.

So all of these work, in an expression:

:(a ↦ b)
:(a → b)
:(a ← b)

but this one :(a ↤ b) yields

ERROR: syntax: missing comma or ) in argument list

Any reason why this is so?

JeffBezanson commented 7 years ago

\mapsfrom is somehow not included in our list of operators. Probably an oversight. It should be added.

dpsanders commented 4 years ago

This just came up again on Slack. Maybe it's time to reconsider this? It actually seems to have been closed prematurely despite quite a few +1s.

sdewaele commented 4 years ago

+1.

-> is a frequently used construct. Using ↦ will make a lot of code look cleaner / compact / more like pseudocode.

c42f commented 4 years ago

I'm going to reopen this as there still seems to be broad interest, and there's no recorded reason for why it was closed.

StefanKarpinski commented 4 years ago

I think Jake just decided that he didn't like it.

JeffBezanson commented 4 years ago

I can think of several points against this:

c42f commented 4 years ago

I didn't find https://github.com/JuliaLang/julia/issues/11223#issuecomment-101881412 super convincing but you've got some good points.

The mathematician in me really wants this to work so I'm torn. I'll admit that personally I don't even use in code even though I love the look of it. It seems a bit spurious and confusing for readers to have to navigate that syntax variation.

JeffBezanson commented 4 years ago

https://juliamono.netlify.app/#contextual_and_stylistic_alternates

musm commented 4 years ago

Cascadia code will also do the substitutions that @JeffBezanson linked to in Julia Mono

ExpandingMan commented 3 years ago

I want to resurrect this, as every time I type -> I die a little bit inside. If I do a PR, is there any chance it would be accepted? Though, much to my chagrin, I'm sure it would have to wait for 1.8 because of deprecations.

stevengj commented 3 years ago

I feel like there is a broad consensus of the core devs against this…