Jump to page: 1 214  
Page
Thread overview
A Discussion of Tuple Syntax
Aug 16, 2013
Meta
Aug 16, 2013
bearophile
Aug 17, 2013
Meta
Aug 17, 2013
captaindet
Aug 17, 2013
Meta
Aug 19, 2013
ixid
Aug 19, 2013
bearophile
Aug 19, 2013
ixid
Aug 19, 2013
bearophile
Aug 19, 2013
Wyatt
Aug 19, 2013
Dicebot
Aug 19, 2013
Wyatt
Aug 19, 2013
H. S. Teoh
Aug 19, 2013
Dicebot
Aug 19, 2013
H. S. Teoh
Aug 19, 2013
Dicebot
Aug 19, 2013
Dicebot
Aug 19, 2013
Dicebot
Aug 19, 2013
Dicebot
Aug 19, 2013
Meta
Aug 19, 2013
Timon Gehr
Aug 19, 2013
Brad Anderson
Aug 19, 2013
Brad Anderson
Aug 19, 2013
Meta
Aug 19, 2013
Dicebot
Aug 19, 2013
H. S. Teoh
Aug 19, 2013
Meta
Aug 19, 2013
Meta
Aug 20, 2013
Dicebot
Aug 20, 2013
Meta
Aug 20, 2013
Dicebot
Aug 20, 2013
Meta
Aug 20, 2013
Meta
Aug 20, 2013
Timon Gehr
Aug 20, 2013
Manu
Aug 20, 2013
Timon Gehr
Aug 21, 2013
deadalnix
Aug 20, 2013
H. S. Teoh
Aug 20, 2013
Meta
Aug 20, 2013
H. S. Teoh
Aug 20, 2013
Dicebot
Aug 20, 2013
Meta
Aug 20, 2013
Meta
Aug 20, 2013
H. S. Teoh
Aug 20, 2013
Kenji Hara
Aug 20, 2013
Kenji Hara
Aug 20, 2013
John Colvin
Aug 20, 2013
Jacob Carlborg
Aug 20, 2013
Dicebot
Aug 20, 2013
Meta
Aug 20, 2013
Dicebot
Aug 20, 2013
Meta
Aug 20, 2013
Dicebot
Aug 20, 2013
Meta
Aug 20, 2013
Dicebot
Aug 21, 2013
Kenji Hara
Aug 21, 2013
bearophile
Aug 21, 2013
Meta
Aug 21, 2013
bearophile
Aug 21, 2013
H. S. Teoh
Aug 21, 2013
bearophile
Aug 21, 2013
Dicebot
Aug 21, 2013
Dicebot
Aug 21, 2013
Michel Fortin
Aug 21, 2013
Jonathan M Davis
Aug 21, 2013
Dicebot
Aug 21, 2013
Michel Fortin
Aug 21, 2013
Meta
Aug 21, 2013
eles
Aug 20, 2013
Timon Gehr
Aug 21, 2013
Kenji Hara
Aug 21, 2013
Michel Fortin
Aug 20, 2013
Kenji Hara
Aug 20, 2013
Dicebot
Aug 20, 2013
bearophile
Aug 20, 2013
bearophile
Aug 20, 2013
Dicebot
Aug 20, 2013
bearophile
Aug 20, 2013
Timon Gehr
Aug 20, 2013
Timon Gehr
Aug 20, 2013
Kenji Hara
Aug 20, 2013
bearophile
Aug 20, 2013
bearophile
Aug 19, 2013
John Colvin
Aug 19, 2013
bearophile
Aug 19, 2013
Dicebot
Aug 19, 2013
Wyatt
Aug 19, 2013
Meta
Aug 19, 2013
bearophile
Aug 19, 2013
Meta
Aug 19, 2013
bearophile
Aug 19, 2013
Meta
Aug 19, 2013
bearophile
Aug 19, 2013
Dicebot
Aug 19, 2013
Meta
Aug 19, 2013
captaindet
Aug 20, 2013
deadalnix
Aug 20, 2013
Jonathan M Davis
Aug 20, 2013
H. S. Teoh
Aug 21, 2013
Zach the Mystic
Aug 21, 2013
bearophile
Aug 19, 2013
Meta
Aug 20, 2013
Mr. Anonymous
Aug 20, 2013
Wyatt
Aug 20, 2013
eles
Aug 20, 2013
Mr. Anonymous
Aug 20, 2013
Timon Gehr
Aug 20, 2013
eles
Aug 20, 2013
H. S. Teoh
Aug 20, 2013
Jonathan M Davis
Aug 21, 2013
Walter Bright
Aug 20, 2013
H. S. Teoh
Aug 21, 2013
Daniel Murphy
Aug 21, 2013
Jacob Carlborg
Aug 21, 2013
QAston
August 16, 2013
Awhile ago Kenji posted this excellent dip (http://wiki.dlang.org/DIP32) that aimed to improve tuple syntax, and described several cases in which tuples could be destructured. You can see his original thread here: http://forum.dlang.org/thread/mailman.372.1364547485.4724.digitalmars-d@puremagic.com, and further discussion in this thread: http://forum.dlang.org/thread/dofwinzpbcdwkvhzcgrk@forum.dlang.org.

It seemed that there was a lot of interest in having syntax somewhat like what is described in Kenji's DIP, but it didn't really go anywhere. There is this pull on Github (https://github.com/D-Programming-Language/dmd/pull/341), but it uses the (a, b) syntax, which has too much overlap with other language constructs. Andrei/Walter didn't want to merge that pull request without a full consideration of the different design issues involved, which in retrospect was a good decision.

That said, I'd like to open the discussion on tuple syntax yet again. Tuples are currently sorely underused in D, due in large part to being difficult to understand and awkward to use. One large barrier to entry is that fact that D has not 1, not 2, but 3 different types of tuples (depending on how you look at it), which are difficult to keep straight.

There is std.typecons.Tuple, which is fundamentally different from std.typecons.TypeTuple in that it's implemented as a struct, while TypeTuple is just a template wrapped around the compiler tuple type. ExpressionTuples are really just TypeTuples that contain only values, and aren't mentioned anywhere except for in this article: http://dlang.org/tuple.html, which frankly creates more confusion than clarity.

A good, comprehensive design has the potential to make tuples easy to use and understand, and hopefully clear up the unpleasant situation we have currently. A summary of what has been discussed so far:

- (a, b) is the prettiest syntax, and it also completely infeasible

- {a, b} is not as pretty, but it's not that bad of an alternative (though it may still have issues as well)

- #(a, b) is unambiguous and would probably be the easiest option. I don't think it looks too bad, but some people might find it ugly and noisy

- How should tuples be expanded? There is the precedent of an expand() method of std.typecons.Tuple, but Kenji liked tup[] (slicing syntax). So with a tuple of #(1, "a", 0.0), tup[0..2] would be an expanded tuple containing 1 and "a". On the other hand, Bearophile and Timon Gehr preferred that slicing a tuple create another "closed" tuple, and to use expand() for expansion. So tup[] would create a copy of the tuple, and tup[0..2] would create a closed tuple eqvivalent to #(1, "a"). I don't have any particular preference in that regard.

- Timon Gehr wanted the ability to swap tuple values, so #(x, y) = #(y, x) would be allowed. Kenji was against it, saying that it would introduce too many complications.

- There was no consensus on the pattern matching syntax for unpacking. For example, #(a, _) = #(1, 2) only introduces one binding, "a", into the surrounding scope. The question is, what character should go in the place of "_" to signify that a value should not be bound? Some suggestions were #(a, $), #(a, @), #(a, ?). I personally think #(a, ?) or #(a, *) would be best, but all that's  really necessary is a symbol that cannot also be an identifier.

    Also up for debate was nested patterns, e.g., #(1, 2, #(3, 4, #(5, 6))). I don't think there was a consensus on unpacking and pattern matching for this situation. One idea I saw that looked good:

        * Use "..." to pattern match on the tail of an expressions, so take the above tuple. The pattern #(1, ?, ...) would match the two nested sub-tuples. Or, say, #(1, 2, 3) could be matched by #(1, 2, 3), #(1, ?, 3), #(1, ...), etc. You obviously can't refer to "..." as a variable, so it also becomes a useful way of saying "don't care" for multiple items, e.g., #(a, ...) -> only bind the first item in the tuple. We can play around with this to get a few other useful constructs, such as #(a, ..., b) -> match first and last, #(..., b) -> match last, etc.

Assuming the "..." syntax for unpacking, it would be useful to name the captured tail. For example, you could unpack #(1, 3, #(4, 6)) into #(a, b, x...), where a = 1, b = 3, x = #(4, 6). Similarly, #(head, rest...) results in head = 1, rest = #(2, #(4, 6)). I think this would be very useful.

- Concatenating tuples with ~. This is nice to have, but not particularly important.

One thing that I think was overlooked, but would be pretty cool, is that a tuple unpacking/pattern matching syntax would allow us to unpack/pattern match just about anything that you can make a tuple of in D. Combine this with the .tupleof property, and things get interesting... Maybe. There is one possible problem: .tupleof returns a TypeTuple, and it's not at all clear to me how, if at all, TypeTuple would work with the proposed syntax. Is #(int, string, bool) a valid tuple instantiation? This is something that needs to be worked out.

This is the third or fourth time that I know of that tuple syntax has come up, and as of yet, nothing has been done about it. I'd really like to get the ball rolling on this, as I think a good syntax for these tuple operations would do D a world of good. I'm not a compiler hacker, unfortunately, so I can't implement it myself as proof of concept... However, I hope that discussing it and working out all the kinks will help pave the way for an actual implementation.
August 16, 2013
Meta:

> Andrei/Walter didn't want to merge that pull request without a full consideration of the different design issues involved, which in retrospect was a good decision.

I agree that before adding some new syntax you have to think well.


> - {a, b} is not as pretty, but it's not that bad of an alternative (though it may still have issues as well)

It has technical issues, they were discussed in one of the last threads. Such problems should be added in a note in the DIP32, so they don't get lost in time.


> - #(a, b) is unambiguous and would probably be the easiest option. I don't think it looks too bad, but some people might find it ugly and noisy

It looks nice (but I don't know if it's technically usable), I have added it at the end of the list of alternative syntaxes:
http://wiki.dlang.org/DIP32#Use_case_of_uniform_tuple_syntax


> I personally think #(a, ?) or #(a, *) would be best, but all that's  really necessary is a symbol that cannot also be an identifier.

I think ? is clear, unambiguous, etc, and I like it. The * is already used for pointers, product, dereferencing, ** is used for pow, so it's better to not add further meanings to it.


> - Concatenating tuples with ~. This is nice to have, but not particularly important.

In theory I like this operation, but in practice in my D code I don't need it often, so I think it should be left out, for later.
In Python I sometimes concatenate tuples, but in such use cases they are essentially immutable dynamically typed arrays, losing their positional meaning.


Tuples could also be used in switch/case statements, to support a very basic form of pattern matching. See also a standard method named "unapply" I have discussed a bit here, coming from Scala language, that is a very simple solution to solve a significant problem:
http://d.puremagic.com/issues/show_bug.cgi?id=596

Bye,
bearophile
August 17, 2013
On Friday, 16 August 2013 at 23:48:53 UTC, bearophile wrote:
>> - #(a, b) is unambiguous and would probably be the easiest option. I don't think it looks too bad, but some people might find it ugly and noisy
>
> It looks nice (but I don't know if it's technically usable), I have added it at the end of the list of alternative syntaxes:
> http://wiki.dlang.org/DIP32#Use_case_of_uniform_tuple_syntax

Why do you say that? It seems to me that it would be better than {}, because there's only 1 other language construct that uses #, so there's little overlap with other features.
August 17, 2013
On 2013-08-16 20:02, Meta wrote:
> On Friday, 16 August 2013 at 23:48:53 UTC, bearophile wrote:
>>> - #(a, b) is unambiguous and would probably be the easiest option. I don't think it looks too bad, but some people might find it ugly and noisy
>>
>> It looks nice (but I don't know if it's technically usable), I have added it at the end of the list of alternative syntaxes:
>> http://wiki.dlang.org/DIP32#Use_case_of_uniform_tuple_syntax
>
> Why do you say that? It seems to me that it would be better than {}, because there's only 1 other language construct that uses #, so there's little overlap with other features.

not sure what we are talking about here, new syntax for
a) TypeTuple (that would be my best guess but i am not sure)
b) std.typecons.Tuple
c) both, a unified syntax
the DIP is not completely clear about this either.

only case (a) is hot at the moment and i fell into some related pits recently myself. so i'd love to have a better syntax, one that makes the dirty hack (status quo) a proper part of the language - as it is widely used already and very powerful.

i am curious too if ..(..) constructs are completely out of the question. if not, i would suggest as shorthand:

	!(a,b)

this reminds of template instantiation and is exactly how the awkwardly/confusingly named TypeTuple is realized now, as an alias to its own template arguments. if we need a name for it, it should not remind at all of 'tuple' - since there is also the completely unrelated std.typecons.Tuple. a more verbose/explicit suggestion would be

	symbols(a,b)


/det
August 17, 2013
On Saturday, 17 August 2013 at 05:48:47 UTC, captaindet wrote:
> not sure what we are talking about here, new syntax for
> a) TypeTuple (that would be my best guess but i am not sure)
> b) std.typecons.Tuple
> c) both, a unified syntax
> the DIP is not completely clear about this either.

First and foremost, a new syntax for std.typecons.Tuple. Creating tuple literals -> #(1, "a", false), pattern matching on tuples -> switch (#(1, 2)), and destructuring of tuples -> #(a, b) = #(1, 2).

A good question is whether this syntax can (and more importantly, should) be used for TypeTuples as well. TypeTuples are poorly named and not at all similar to Tuple, so it doesn't make much sense to give them both the same syntax. Also, I can't see TypeTuple seeing nearly as much use as Tuple, so it may be better to introduce the new syntax for Tuple, and keep TypeTuple as-is.

> only case (a) is hot at the moment and i fell into some related pits recently myself. so i'd love to have a better syntax, one that makes the dirty hack (status quo) a proper part of the language - as it is widely used already and very powerful.

What TypeTuple gives you access to is the compiler tuple type that it uses for function argument lists and other things. I wouldn't really call it a dirty hack. The two most confusing things about TypeTuple, I think, is the auto-expansion, and the fact that it can contain both types and values.

> i am curious too if ..(..) constructs are completely out of the question. if not, i would suggest as shorthand:
>
> 	!(a,b)
>
> this reminds of template instantiation and is exactly how the awkwardly/confusingly named TypeTuple is realized now, as an alias to its own template arguments.

Unfortunately, that won't work, as the value of this expression is already well-defined in the current language. A list of comma-separated expressions means that each is evaluated from left to right, and then the result of the entire expression is the result of the rightmost expression, e.g.:

    auto a = true;
    auto b = false;
    //Evaluate a, then b. The result of the expression
    //in the brackets is b. Then the ! gets applied to b
    auto x = !(a, b);
    assert(x == true); //Passes

> if we need a name for it, it should not remind at all of 'tuple' - since there is also the completely unrelated std.typecons.Tuple. a more verbose/explicit suggestion would be
>
> 	symbols(a,b)

I 100% agree that TypeTuple needs a better name. A couple other suggestions were put forward as well in the other tuple thread currently active.

August 19, 2013
Note: I'm leading off with a reply to bearophile transplanted here to stop making OT noise in John's thread about TypeTuple.

On Friday, 16 August 2013 at 23:23:59 UTC, bearophile wrote:
>
> It's short, clear, has a precedent with q{}.

Wait, what is q{}?  That's something in D?  What does that even do?  I can infer that q{} is probably some manner of scoping or grouping _something_ somehow, but I have to dig into lexical and manually search for q{ to find out it's [neither of the things I expected].  In my view, this right here is really just a fundamental problem with single-character prefixes and I feel that's something we should endeavour to avoid, if possible.

> I don't like it a lot, but it's way better than not having
> language support for tuples.
>
On this, I think we all agree.

>> I'd prefer just using parentheses, but I think there were readability problems that caused the DIP to end up with:
>
> More than just readability problems. They were discussed when Kenji presented the DIP 32 in this forum. Timon found a significant problem with the {} syntax.
>
To be clear, I'm not talking about braces, {}; I'm talking about parentheses, ().  I read over that whole DIP32 thread a couple times, and didn't see any rationale offered for why the likely "cleanest" version "can't be used".  It wasn't even brought up (unless I've missed something subtle).  In the second thread, linked in the OP here, they were glossed over again.  Now, I fully believe there's a very good reason that's been written somewhere, but I _would_ like to know what that is, preferably documented somewhere less ephemeral and difficult to search than the newsgroup (such as in DIP32).  The closest I've seen so far is the pull request where Walter and Andrei expressed that it should be considered further.

On Friday, 16 August 2013 at 21:07:52 UTC, Meta wrote:
> - #(a, b) is unambiguous and would probably be the easiest option. I don't think it looks too bad, but some people might find it ugly and noisy
>
The octothorpe _is_ much better than the t simply in terms of readability, though, even more than q{} or t{}, I have concerns about its ability to be found with an ordinary search engine by an ordinary user.  Have you tried looking for documentation on weird operators with a search engine lately?  They don't exactly take to it well. :/ (cf. Perl's <=>)

Addressing the other suggestion I saw that cropped up, I personally find the two-character "bananas" to be impressively ugly.  I considered suggesting some permutation on that same idea, but after toying with a few examples I find it ends up looking awful and I think it's honestly annoying to type them in any form.  I even don't like how the unicode version of that one looks; for doubling up, I think ⟦ ⟧ or ⟪ ⟫ or are easier on the eyes.

It's times like these that I wish the standard PC keyboard had something like guillemets « », or corner brackets 「 」 (big fan of these) in addition to everything else. (Or even that we could use < > for bracing, though at this point I don't think I could easily condone that move for D).

I feel weird admitting this, but if we can't use some manner of bare brace, I think I'd rather have tup(), tup[], tup{} (or even tuple() et al) as a prefix over any single character.

Another stray thought: is there room for a little box of syntax chocolate so that e.g. tuple(), [||], and ⟦ ⟧ are all valid?  I don't know if we have a precedent like that off the top of my head and I'm pretty sure I don't like it, but I thought I'd at least mention it.

> - There was no consensus on the pattern matching syntax for unpacking. For example, #(a, _) = #(1, 2) only introduces one binding, "a", into the surrounding scope. The question is, what character should go in the place of "_" to signify that a value should not be bound? Some suggestions were #(a, $), #(a, @), #(a, ?). I personally think #(a, ?) or #(a, *) would be best, but all that's  really necessary is a symbol that cannot also be an identifier.
>
Can't make it a single underscore? Question mark works best then, IMO.  It isn't as burdened with meanings elsewhere (sure there's ternary and possibly-match in regex, but...have I forgotten something?)

>     Also up for debate was nested patterns, e.g., #(1, 2, #(3, 4, #(5, 6))). I don't think there was a consensus on unpacking and pattern matching for this situation. One idea I saw that looked good:
>
Ah, I was wondering about the case of a tuple of tuples.  It's not mentioned in the DIP that I saw, so I assumed it was allowed, but explicit mention is probably warranted.

>         * Use "..." to pattern match on the tail of an expressions, so take the above tuple. The pattern #(1, ?, ...) would match the two nested sub-tuples. Or, say, #(1, 2, 3) could be matched by #(1, 2, 3), #(1, ?, 3), #(1, ...), etc. You obviously can't refer to "..." as a variable, so it also becomes a useful way of saying "don't care" for multiple items, e.g., #(a, ...) -> only bind the first item in the tuple. We

#(a, ...) looks like to me like it would make a 2-tuple containing a and a tuple of "everything else", because of the ellipsis' use in templated code.  I think this is a little unclear, so instead I'd prefer #(a, ? ...) (or whatever ends up used for the discard character) to make it explicit.

> Assuming the "..." syntax for unpacking, it would be useful to name the captured tail. For example, you could unpack #(1, 3, #(4, 6)) into #(a, b, x...), where a = 1, b = 3, x = #(4, 6). Similarly, #(head, rest...) results in head = 1, rest = #(2, #(4, 6)). I think this would be very useful.
>
As a bonus, explicit discard means a simple comma omission is less likely to completely change the meaning of the statement.  Compare:
#(a, b, ...)   //bind the first two elements, discard the rest.
#(a, b ...)    //bind the first element to a and everything else to b
#(a, b, ? ...) //same as the first
#(a, b ? ...)  //syntax error

Granted, there's this case:
#(a, ?, ...)
...but that seems like it would be less common just based on how people conventionally order their data structures.

Thought: Is there sufficient worth in having different tokens for discarding a single element vs. a range? e.g.
#(a, ?, c, * ...) //bind first and third elements; discard the rest
// I'm not attached to the asterisk there.
// +, #, or @ would also make some amount of sense to me.

> - Concatenating tuples with ~. This is nice to have, but not particularly important.
>
What does concatenating a tuple actually do?  That is:
auto a = #(1,2) ~ 3; //Result: a == #(1,2,3), right?
auto b = a ~ #(4,5); //Is  b == #(1,2,3,#(4,5)) or is b == #(1,2,3,4,5)?

> This is the third or fourth time that I know of that tuple syntax has come up, and as of yet, nothing has been done about it. I'd really like to get the ball rolling on this, as I think a good syntax for these tuple operations would do D a world of good. I'm not a compiler hacker, unfortunately, so I can't implement it myself as proof of concept... However, I hope that discussing it and working out all the kinks will help pave the way for an actual implementation.

Great! After this, let's fix properties. ;)

-Wyatt
August 19, 2013
On Monday, 19 August 2013 at 16:53:06 UTC, Wyatt wrote:
> Note: I'm leading off with a reply to bearophile transplanted here to stop making OT noise in John's thread about TypeTuple.
>
> On Friday, 16 August 2013 at 23:23:59 UTC, bearophile wrote:
>>
>> It's short, clear, has a precedent with q{}.
>
> Wait, what is q{}?

Check "Token Strings" in http://dlang.org/lex.html
August 19, 2013
On Monday, 19 August 2013 at 16:57:35 UTC, Dicebot wrote:
>
> Check "Token Strings" in http://dlang.org/lex.html

Didn't make it to the end of the paragraph? ;)
August 19, 2013
On Mon, Aug 19, 2013 at 06:53:05PM +0200, Wyatt wrote: [...]
> >This is the third or fourth time that I know of that tuple syntax has come up, and as of yet, nothing has been done about it. I'd really like to get the ball rolling on this, as I think a good syntax for these tuple operations would do D a world of good. I'm not a compiler hacker, unfortunately, so I can't implement it myself as proof of concept... However, I hope that discussing it and working out all the kinks will help pave the way for an actual implementation.
> 
> Great! After this, let's fix properties. ;)
[...]

What I'd like to know, is how all of these proposals address the fundamental differences between "symbol tuples" (compile-time construct) and std.range.Tuple (runtime construct). As far as I can tell, people are still confusing the two, and it's really not helping. Before we solve this, any syntax suggestion seems more like a mortician's work than a real solution.


T

-- 
MACINTOSH: Most Applications Crash, If Not, The Operating System Hangs
August 19, 2013
On Monday, 19 August 2013 at 16:53:06 UTC, Wyatt wrote:
> Note: I'm leading off with a reply to bearophile transplanted here to stop making OT noise in John's thread about TypeTuple.
>
> On Friday, 16 August 2013 at 23:23:59 UTC, bearophile wrote:
>>
>> It's short, clear, has a precedent with q{}.
>
> Wait, what is q{}?  That's something in D?  What does that even do?  I can infer that q{} is probably some manner of scoping or grouping _something_ somehow, but I have to dig into lexical and manually search for q{ to find out it's [neither of the things I expected].  In my view, this right here is really just a fundamental problem with single-character prefixes and I feel that's something we should endeavour to avoid, if possible.
>
>> I don't like it a lot, but it's way better than not having
>> language support for tuples.
>>
> On this, I think we all agree.
>
>>> I'd prefer just using parentheses, but I think there were readability problems that caused the DIP to end up with:
>>
>> More than just readability problems. They were discussed when Kenji presented the DIP 32 in this forum. Timon found a significant problem with the {} syntax.
>>
> To be clear, I'm not talking about braces, {}; I'm talking about parentheses, ().  I read over that whole DIP32 thread a couple times, and didn't see any rationale offered for why the likely "cleanest" version "can't be used".  It wasn't even brought up (unless I've missed something subtle).  In the second thread, linked in the OP here, they were glossed over again.  Now, I fully believe there's a very good reason that's been written somewhere, but I _would_ like to know what that is, preferably documented somewhere less ephemeral and difficult to search than the newsgroup (such as in DIP32).  The closest I've seen so far is the pull request where Walter and Andrei expressed that it should be considered further.
>
> On Friday, 16 August 2013 at 21:07:52 UTC, Meta wrote:
>> - #(a, b) is unambiguous and would probably be the easiest option. I don't think it looks too bad, but some people might find it ugly and noisy
>>
> The octothorpe _is_ much better than the t simply in terms of readability, though, even more than q{} or t{}, I have concerns about its ability to be found with an ordinary search engine by an ordinary user.  Have you tried looking for documentation on weird operators with a search engine lately?  They don't exactly take to it well. :/ (cf. Perl's <=>)
>

All we have left from the standard keyboard layout as far as single keys go is # and ¬
I don't think the mathematics crowd would be too happy with ¬ not meaning not.

The only op() options I can think of that aren't ambiguous:
$(a, b)
%(a, b)
^(a, b)
&(a, b) //I like this one
:(a, b)
#(a, b)
'(a, b) //I think....
/(a, b)
\(a, b)
>(a, b)
<(a, b)
|(a, b)
¬(a, b) //not in std ascii
?(a, b)

however, most of those are binary operators too, so it could be quite accident prone and confusing to look at

Some of this could be helped by enforcing at least 1 ','.

e.g.

  &(3)   //illegal
  &(3,)  //legal

There is precedent for this in python.
« First   ‹ Prev
1 2 3 4 5 6 7 8 9 10 11