qt4cg / qtspecs

QT4 specifications
https://qt4cg.org/
Other
28 stars 15 forks source link

Remove the inlined function expression variant of the thin arrow operator #435

Closed rhdunn closed 1 year ago

rhdunn commented 1 year ago

This proposal is to remove the third bullet/variant from the thin arrow operator so that the new inline function syntax (-> { ... }) cannot be used within the arrow expressions.

This makes the thin/fat arrows consistent in behaviour with each other, with the exception of how they pass the value to the expressions:

  1. thin arrow operators pass the values in the sequence one at a time to the associated function;
  2. fat arrow operators pass all the values in the sequence to the associated function in a single call.

Changes

  1. Update the syntax:

    [46] FatArrowTarget  ::= "=>" ((ArrowStaticFunction ArgumentList) | (ArrowDynamicFunction PositionalArgumentList))  
    [47] ThinArrowTarget ::= "->" ((ArrowStaticFunction ArgumentList) | (ArrowDynamicFunction PositionalArgumentList))
  2. Remove the text for the inline function variant:

    If the arrow is followed by an EnclosedExpr:

    Given a UnaryExpr U, and an EnclosedExpr {E}, the expression U -> {E} is equivalent to the expression (U) ! (E).

    For example, the expression $x -> {.+1} is equivalent to ($x)!(.+1).

  3. Remove/update the associated examples, e.g. to use let $f := function ($x) { $x + 1 } return $x -> f() -> $f().

ChristianGruen commented 1 year ago

For the sake of completeness, I’m adding the link to the original suggestion from @dirkk… https://www.w3.org/Bugs/Public/show_bug.cgi?id=29393

…and the link to the xpath-ng proposal: https://github.com/expath/xpath-ng/pull/5

michaelhkay commented 1 year ago

Thanks for the references, and for the reminder of my comment:

("a", "b", "c") => for-each(uppercase#1)

which I suggested again in today's call.

The current example

"The cat sat on the mat" => tokenize() -> concat(".") -> upper-case() => string-join(" ")

then becomes

"The cat sat on the mat" => tokenize() => for-each( concat(?, ".") => upper-case() ) => string-join(" "))

which is longer, but seems to have more clarity; it certainly introduces fewer new concepts.

Correction. I got that wrong. The 2nd argument to for-each must be a function, and concat(?, ".") => upper-case() is not a function. Rather, it throws a type error saying that upper-case() cannot be applied to a function. Perhaps influenced by Dimitre's remarks today, I was thinking here of => as being an operator that composes two functions into a single function, which it is not.

What we have to write instead is something like => for-each(->( (.||".") => upper-case())

After today's discussion, I think I'm leaning towards dropping the thin-arrow operator completely (not just the "inlined function" variant of it)

rhdunn commented 1 year ago

It would be worth adding that example using for-each as it is a useful demonstration of how to do this with the existing arrow operator.

Arithmeticus commented 1 year ago

If the thin arrow is kept, I recommend starting with a much simpler example that makes the difference in behavior clear, repeated for each operator, e.g.: (1, 2) => sum() returns 3 (1, 2) -> sum() returns (1, 2)

michaelhkay commented 1 year ago

I'd like to put forward a more radical set of reforms. Each of the following changes could technically be made on its own, but taken together, they are designed to reduce the amount of new syntax that needs to be mastered (and explained) while retaining or increasing its expressive power.

  1. In Inline Function Expressions, drop the variant with no argument list (->{.+1})
  2. In Inline Function Expressions, drop the use of -> as a synonym for function (as in ->($a, $b){$a + $b})
  3. Introduce new syntax for Quick Inline Functions (details below): for example {$1 + $2}
  4. Drop Thin Arrow expressions ($x -> f())
  5. In Fat Arrow expressions, allow a Quick Inline Function in place of the VarRef or ParenthesizedExpr. For example $x => {$1 * 2}()
  6. In Fat Arrow expressions, allow the ArgumentList or PositionalArgumentList to be omitted if it is empty (provided we can satisfy ourselves that this will parse unambiguously)
  7. Introduce a function composition operator, spelt perhaps ~>, so that if F1 and F2 are expressions returning functions, then F1 ~> F2 returns a function F3 with the same signature as F1, with the effect that F3(args) delivers the same result as F2(F1(args)). Example 1: sort($input, key:=normalize-space#1~>upper-case#1).

Notes:

  1. Simple "focus functions" may become just a tiny bit more verbose: filter($in, ->{. gt 2}) becomes filter($in, {$1 gt 2}), while sort(//emp, (), ->{@salary}) becomes sort(//emp, (), {$1/@salary}).
  2. ->($a, $b){$a + $b} becomes more compact: {$1 + $2}. The zero-arity function ->{EXPR} becomes simply {EXPR}. Note that the arity is inferred from the highest argument number in a contained parameter reference.
  3. I'm proposing "bare braces" as the delimiter: {EXPR}, but we could avoid closing up our future options by adding some syntactic marker, for example ${EXPR} or \{EXPR} or f{EXPR}.
  4. As a replacement for EXPR -> f(), use EXPR => for-each(f). As a replacement for EXPR -> f() -> g(), use perhaps EXPR => for-each(f ~> g). To take an example from the spec, (1 to 5) -> xs:double() -> math:sqrt() -> {.+1} => sum() becomes (1 to 5) => for-each(xs:double ~> math:sqrt ~> {$1+1}) => sum()
  5. see examples above.
  6. My reasoning that an empty argument list can be omitted runs informally as follows: the only way an expression E can be immediately followed by "(" is if E is a PrimaryExpr. An ArrowExpr is not a PrimaryExpr, therefore it cannot be immediately followed by "(", therefore we know that if the next token is "(", it must indicate the start of the optional argument list.
  7. The function composition operator (suggested to me by Dimitre's remarks during yesterday's meeting) seems to have a lot of potential which I haven't yet fully explored. The suggested spelling is just a first-cut idea, alternatives are welcome. This would be better explored as a separate proposal, but I include it here because I think it's part of justification that says we can drop the thin arrow expression without losing anything. I feel it's more poweful than the thin arrow in its current form because it's a pure binary operator that can take arbitrary expressions as its operands (subject to type and precedence rules of course), and it can be used anywhere that a function item is expected, including a "fat arrow" pipeline.
ChristianGruen commented 1 year ago

Michael, thanks for the revised proposal.

"The cat sat on the mat"
=> tokenize()
-> concat(".")
-> upper-case()
=> string-join(" ")

I don’t think there’s anything close as elegant and readable with the existing language. Examples:

let $string := "The cat sat on the mat"
let $tokens := (
  for $token in tokenize($string)
  return $token => concat(".") => upper-case()
)
return string-join($tokens, " ")

string-join(
  let $string := "The cat sat on the mat"
  for $token in tokenize($string)
  return upper-case(concat($token, ".")),
  " "
)

"The cat sat on the mat"
=> tokenize()
=> for-each(concat(?, '.'))
=> for-each(upper-case#1)
=> string-join(" ")
ndw commented 1 year ago

With respect to

"The cat sat on the mat"
=> tokenize()
-> concat(".")
-> upper-case()
=> string-join(" ")

Am I correct that it would be the same if you wrote "The cat sat on the mat" -> tokenize() ...? Since there's only one argument before the first arrow operator, either would work? Or maybe I haven't groked some subtle aspect of the difference.

At a glance, the mixture of arrows seems awfully subtle. I can see how it's concise, but I find the syntactic variation of using ! easier to read:

('The cat sat on the mat' => tokenize())
! concat(., '.')
! upper-case(.)
=> string-join()

The parentheses around the first expression are perhaps a little annoying, but like MSM, I tend to use parentheses liberally. Do I remember that 3 * 4 + 2 is 14? Yeah, probably, but I'd always write (3 * 4) + 2 anyway.

I, being the sort who prefers things to be explicit rather than implicit, actually like ! concat(., '.') better than -> concat('.') though I wouldn't be surprised if I'm in the minority on that point.

rhdunn commented 1 year ago

My concern with item 3 (quick inline functions) is how that syntax mixes with existing EnclosedExpr usage. -- For example, what does if (true()) { $1 + $1 } parse as, given the new EnclosedExpr form for if expressions?

michaelhkay commented 1 year ago

We currently don't have any expression, or any construct that can appear in the same context as an expression, that starts with a left open brace. There's a valid argument that we should avoid introducing such an expression in order to keep some of the syntactic space unused -- unused syntactic space preserves options for later enhancements, and tends to allow more accurate diagnosis of syntax errors.

So in your example, the construct if (true()) { $1 + $1 } is an error, but it might be tricky to give a good error message. The open brace is will get the parser thinking it's a braced conditional expression, it will then find the $1 which is allowed only in a "quick inline function", so the likely error message is "numeric parameter reference not allowed outside a quick inline function" (or whatever we decide to call the thing).

ChristianGruen commented 1 year ago

Am I correct that it would be the same if you wrote "The cat sat on the mat" -> tokenize() ...?

Exactly: If there’s one argument, the arrows are interchangeable. It’s comparable to for and let, both do the same if a single item is bound.

At a glance, the mixture of arrows seems awfully subtle. I can see how it's concise, but I find the syntactic variation of using ! easier to read:

The syntax and the formatting gets tricky once you have intermixed occurrences of single and multiple items: Imagine you have item iterations followed by sequence operations followed by item iterations…

What I really like about the arrow approach is that you don’t have to reformat your code once a single operation is added. Instead, you simply move it in between. Currently, with the given syntax, we rewrite arrow chains back to FLWOR expressions in such cases, or we decide not to use the arrow operator at all because of the given restrictions.

michaelhkay commented 1 year ago

An alternative to

"The cat sat on the mat"
=> tokenize()
=> for-each(concat(?, '.'))
=> for-each(upper-case#1)
=> string-join(" ")

under the proposal is to write

"The cat sat on the mat"
=> tokenize()
=> for-each(concat(?, '.') ~> upper-case#1)
=> string-join(" ")

or if you prefer

"The cat sat on the mat"
=> tokenize()
=> for-each({($1 || '.') => upper-case()})
=> string-join(" ")

My thinking is that the function composition operator (which I'm writing as ~>) is more versatile and powerful than the current single-arrow operator, though it might not always be simpler. Of course, I wouldn't want to have both. But I think that flagging the point at which the pipeline splits into item-by-item processing with the visible "for-each" call improves readability for those who're not 100% familiar with the subtle distinctions.

ChristianGruen commented 1 year ago

Just for the record, my comment from Slack (in which the latest proposals haven’t been considered yet):


In 2014, there was a suggestion from @LeoWoerteler to extend the arrow operator for function items: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26889. If it had been adopted, we could do things like:

$text => file:write-text('data.txt, ?)
$payloads => http:send-request($request, $uri, ?)

Back then, I favored that design choice, which got rejected, and our impression was that the fat arrow operator was designed to be intuitive for occasional and intermediate users of the languages.

The good thing about the decision was that the fat arrow is widely used today, and I think we should follow the popularity/simplicity argument for the thin arrow operator as well. Constructs such as…

$seq => ! op("+")(?, 1)
$seq => for-each(function($x) { $x + 1 })

…are certainly more flexible, and we could add or motivate those in addition, but I’m not sure if we should try to introduce or present them to inexperienced users as a default solution. Recommending standard FLWOR expressions would probably be a better choice for most users.

dnovatchev commented 1 year ago

From Slack, using the proposed squashing operator:

"The cat sat on the mat"
=> tokenize()
~> concat(?, ".")
~> upper-case#1
=> string-join(" ")

And the same starting from a single array, containing the words:

["The",  "cat",  "sat",  "on",  "the",  "mat"]
~> concat(?, ".")
~> upper-case#1
=> string-join(" ")
ChristianGruen commented 1 year ago

It’s due to the 3.1 grammar that an arrow expression can yield either the result of function call or a partially applied function:

(1 to 5) => sum(0)  (: yields the result of the function call :)
(1 to 5) => sum(?)  (: yields a function item :)

The behavior is consistent, as it’s a basic property of argument lists that they contain expressions and argument placeholders:

ArrowExpr               ::=  UnaryExpr ("=>" ArrowFunctionSpecifier ArgumentList)*
ArrowFunctionSpecifier  ::=  EQName | VarRef | ParenthesizedExpr
ArgumentList            ::=  "(" (Argument ("," Argument)*)? ")"
Argument                ::=  ExprSingle | ArgumentPlaceholder
ArgumentPlaceholder     ::=  "?"

Perhaps we can avoid new intricacies by sticking to a simple grammar representation. If we want to have a unified syntax for function calls, and if we want to support the two arrow operators, we could simplify the current 4.0 grammar and instead slightly enhance the 3.1 grammar as follows:

ArrowExpr               ::=  UnaryExpr (("=>" | "->") ArrowFunctionSpecifier ArgumentList)*
ArrowFunctionSpecifier  ::=  EQName | VarRef | InlineFunctionExpr | ParenthesizedExpr

Examples for legal expressions:

(: processing of sequences; analogous to the let clause :)
$seq => sum()
$seq => $process-sequence()
$seq => function($x) { count($x) }()
$seq => (if($sum) then sum#1 else avg#1)()

(: processing of items; analogous to the for clause :)
$seq -> string()
$seq -> $process-item()
$seq -> function($x) { $x + 1 }()
$seq -> (if($short) then xs:short#1 else xs:byte#1)()

In a second step (see #53), the InlineFunctionExpr rule can be further tweaked (provided that the alternative syntax creates no ambiguities with the ArrowFunctionSpecifier RHS rules).

PS: In addition to InlineFunctionExpr, we could add NamedFunctionRef, but as count() and count#1() return the same result, it would probably have no added value within the scope of my proposed rules.

ChristianGruen commented 1 year ago

Alternative syntax proposals for the item arrow (see https://github.com/qt4cg/qtspecs/issues/53#issuecomment-1513297753):

Arithmeticus commented 1 year ago

Once a user understands what ! does and what => does, !=> should be an intuitive compound. The other options, not so much.

benibela commented 1 year ago

!=> makes me think of 8======D

ChristianGruen commented 1 year ago

!=> makes me think of 8======D

(: fits the language :)

dnovatchev commented 1 year ago

the current example

"The cat sat on the mat" => tokenize() -> concat(".") -> upper-case() => string-join(" ")

then becomes

"The cat sat on the mat" => tokenize() => for-each( concat(?, ".") => upper-case() ) => string-join(" "))

which is longer, but seems to have more clarity; it certainly introduces fewer new concepts.

Correction. I got that wrong. The 2nd argument to for-each must be a function, and concat(?, ".") => upper-case() is not a function. Rather, it throws a type error saying that upper-case() cannot be applied to a function. Perhaps influenced by Dimitre's remarks today, I was thinking here of => as being an operator that composes two functions into a single function, which it is not.

What we have to write instead is something like => for-each(->( (.||".") => upper-case())

After today's discussion, I think I'm leaning towards dropping the thin-arrow operator completely (not just the "inlined function" variant of it)

Actually no new constructs like "lambda expressions" or "thin arrows" are necessary. The following is a correct XPath 3.1 expression that produces the wanted result and demonstrates chaining:

"The cat sat on the mat" => tokenize() => for-each( concat(?, "."))  => for-each( upper-case#1 )  => string-join(" ")

With BaseX:

image

and with Saxon (Oxygen):

image

Excuse me for still failing to understand why we should be inventing new, complicated and confusing syntax , when we already can write such expressions. 😢


P.S. I still wouldn't be writing such expressions for anyone to look at, and would be afraid that in one month from now I myself wouldn't be confident that I understand what I have written ...

But for anyone wanting powerful shiny new toys: stay relaxed, as this example already shows, we have them at present 😄 If you haven't mastered even what we already have, why want even new such toys?

Is this indicative of too much "parental care", or lack of it?

dnovatchev commented 1 year ago

. . . 7. Introduce a function composition operator, spelt perhaps ~>, so that if F1 and F2 are expressions returning functions, then F1 ~> F2 returns a function F3 with the same signature as F1, with the effect that F3(args) delivers the same result as F2(F1(args)). Example 1: sort($input, key:=normalize-space#1~>upper-case#1).

Notes: . . .

  1. The function composition operator (suggested to me by Dimitre's remarks during yesterday's meeting) seems to have a lot of potential which I haven't yet fully explored. The suggested spelling is just a first-cut idea, alternatives are welcome. This would be better explored as a separate proposal, but I include it here because I think it's part of justification that says we can drop the thin arrow expression without losing anything. I feel it's more poweful than the thin arrow in its current form because it's a pure binary operator that can take arbitrary expressions as its operands (subject to type and precedence rules of course), and it can be used anywhere that a function item is expected, including a "fat arrow" pipeline.

Yes, multiple-composition is really powerful.

But please note the following:

  1. In Maths and in some languages, like Haskell, the function composition (I am using ^ to denote it) is defined as:

F ^ G (x) is F(G(x))

not:

G(F(x))

Maybe to avoid confusion we should call the latter with a different name, why not "left-to-right composition"

  1. In Haskell there is the function application operator $ and the function composition operator ., though just $ could be used.

Multiple composition is defined as a right fold over the list of functions to be composed, with step-function the apply operator $ and the "zero" accumulator - the value on which the multiple composition is to be applied.

We can express the same in XPath:

let $apply := function($f, $x) {$f($x)},
    $multiCompose := function($funs as function(*)*, $x as item()*) {fold-right($funs,$x, $apply)}
 return
    $multiCompose(   (op('+')(?, 1), op('*')(?, 2)), ?) (2)

And this correctly produces:

5,

that is : *`1 + (22)`**

With BaseX:

image

And with Saxon (Oxygen):

image

michaelhkay commented 1 year ago

I could certainly live without the "mapping arrow". I think that if we make it easier to write inline functions, use of things like for-each and filter will start to become more normal and natural, and reduce the need for more complex constructs.

ChristianGruen commented 1 year ago

Actually no new constructs like "lambda expressions" or "thin arrows" are necessary.

@dnovatchev You’re obviously right. The assumption is that the mapping arrow (as coined by Michael in #447) improves the readability of code that can be chained, in particular for novice and intermediate users, and this assumption is based on the wide acceptance of =>.

It’s completely fair to question new syntax in general. In retrospect, your objection is also valid for the 3.0/3.1 operators (!, ?, =>), and it applies to any 4.0 operators that still being discussed. You are right that the abstracted version of the sitting-cat example…

$input => A() =!> B(".") =!> C() => D(" ")

…can already be written as:

$input => A() => for-each( B(?, ".") ) => for-each( C#1 ) => D(" ")

My experience is that partial function applications – B(?, ".") – and named function references – C#1 – are rare encounters, whereas $input => A() is used a lot today. Instead of using these constructs, I would rather expect most users to throw all 3.0 constructs overboard and use FLWOR expressions instead (provided you use XQuery):

let $a := $input
for $b in A($a)
for $c in B($b, " ")
let $d := C($c)
return $D($d, " ")
benibela commented 1 year ago

I think that if we make it easier to write inline functions, use of things like for-each and filter will start to become more normal and natural, and reduce the need for more complex constructs.

That is so bad

The great thing about XPath was that you could do for-each with / and filter with []

The XPath way of cat sitting would be

 ("The cat sat on the mat" => tokenize()) ! concat(., ".")  ! upper-case(.) => string-join(" ")

! concat(., ".") is shorter than => for-each( concat(?, ".")) and easier to read.

dnovatchev commented 1 year ago

@michaelhkay , @ChristianGruen

Yes, we all agree that the newly-proposed syntax is just another way of writing an XPath expression, that we can already write today.

Sometimes inventing "yet another way" to do the same thing and including it in the language makes it difficult to choose which of the available writing facilities to choose, and on reading, why exactly this way of writing was chosen and not that one, again leading to confusion trying to distinguish the differences between this form and that form.

I believe that at present we already have too-many ways to say the same thing, that inventing and adding to the language yet other ways to express the same thing already becomes counter-productive. And most of us shared that the newly-proposed writing additions would benefit and be used just by 5% of the user audience. Thus, introducing this will be devisive and not uniting the users of XPath.

It seems to me that here we are doing the opposite of what Antoine de Saint-Exupéry “Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.”

ChristianGruen commented 1 year ago

It seems to me that here we are doing the opposite of what Antoine de Saint-Exupéry “Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.”

It’s certainly a good principle to literature. Kafka also felt that way, he didn’t believe his work was perfect enough to be kept alive. Still, Max Brod refused to destroy his legacy. Hardly anyone thinks it was a bad decision.

Maybe it was a bad design to add =>, ! and ? to the language, even though it could be taken away. Maybe we should never have introduced higher-order features, which 95% don’t use in practice. – I still believe the decisions made development of complex applications much more comfortable.

rhdunn commented 1 year ago

@dnovatchev Having an existing way of doing something shouldn't mean that a feature/syntax is rejected, otherwise we would not add anything new. [1] The test should be:

  1. Is this useful in practice?
  2. Does this make it easier to read/write queries/code?
  3. Does it follow existing practices in other languages?

Note that these tests need to be applied to different types of user -- i.e. not everyone uses the same coding style, or features. I understand that there are users who want/write simple XSLT transforms, while others are more familiar with higher order functions, etc.

[1] That would apply to many of the proposed and accepted features -- simple mapping operator, exists/every, named keywords, arrays (XPath/XQuery had sequences), sequences (XPath/XQuery had nodes), etc. It would even apply to other languages and features such as procedural languages vs assembly; while/for given the presence of if and goto; classes; etc.

michaelhkay commented 1 year ago

It's very much my experience that the small things are often the ones that are most popular with users: things like the separator attribute of xsl:value-of. I remember there was an argument for minimalism in the Algol68 working group, and someone pointed out that you didn't actually need a "+" operator because "--" did the job perfectly well. It's all about finding the right balance, not about following philosophical design principles blindly.

ndw commented 1 year ago

I bet that most of the folks in our CG can program in more than one language. I'll further bet that for every one of us, and every language, there are features of the language that we have never used or only very rarely use. I would be very surprised if the features we don't use are all the same! But I bet few of us regularly scorn the languages we use because they have features we don't use.

Language design has a scientific component: determining what can actually be achieved, what is intentionally not possible, what is accidentally not possible, and even what is possible but we didn't know it[¹]. It's also part art. Sometimes having redundancy makes a task easier, or easier to do correctly. Sometimes it makes the language more confusing to some users.

I think the working group is largely of the opinion that we need some new syntax to make inline functions easier to use in some circumstances and some new variant of the existing fat arrow operator. At this point, I think everyone recognizes that there are ways to use functions that satisfy the "can it be achieved" requirements. If arguments of the form "you don't need this because..." were going to be persuasive, I think they would already have been so. Conversely, I don't think arguments of the form "by that logic, we don't need [some feature we already have]" are likely to be persuasive (though if the completion of that argument is actually "therefore we should remove it", please open an issue specifically about that).

I think what's left to do is work out what syntax choices are the most agreeable, offer the least element of surprise, and introduce the smallest practical amount of confusion. I encourage everyone to approach the questions in that spirit.


[¹] I love this story, even though I expect it's apocryphal. The story goes that back in the 70's or thereabouts, a team of engineeers was challenged to add a stop watch function to some HP scientific calculator. This is back in the days of 8 digit glowing red LED displays and chunky collections of physical buttons that clicked when you pushed on them. So the team gets out the schematics, big hardcopy print outs of the circuit design, spreads them out over a table in a conference room, and begins the difficult process of working out where and how they can fit the new circuits into the calculator. They've been going at it for a while when one of the engineers looks up from the table: "hang on a minute. If you pressed that button and that button," he says, pointing at places several feet apart on the diagrams, "and that button, wouldn't that make the circuit?" So someone gets out the calculator and pushes the three buttons and the little LED display starts running a stopwatch.

ChristianGruen commented 1 year ago

It's very much my experience that the small things are often the ones that are most popular with users: […]

I once asked developers what’s the coolest 3.0 feature, and the answer was: ||, the operator for concatenating strings!

dnovatchev commented 1 year ago

Hey folks,

I wouldn't be raising my concerns if the proposed new syntax wasn't so confusing.

Just take my feedback (2¢) and let the resulting (hopefully not) monstrosity weigh on your conscience.

I do understand the reasons and justification to strive for expressiveness, but my gut feeling is that the currently proposed new syntax crosses a line that we probably should not.

Also, please, ask yourselves these questions:

  1. Is this the most important and most urgent new feature that we should be working on at present?
  2. Where should we put the focus and emphasis in our future work:

    • providing missing language features that are sorely needed, or
    • inventing yet the Nth way to write an expression that now can be written "only" in N - 1 ways.

Imagine that the "End of the world" is just in 3 years. 😄 Would you then be happy to be working on this feature? If not, what feature you would have chosen to be working on?

I think the working group is largely of the opinion that we need some new syntax to make inline functions easier to use in some circumstances and some new variant of the existing fat arrow operator. At this point, I think everyone recognizes that there are ways to use functions that satisfy the "can it be achieved" requirements. If arguments of the form "you don't need this because..." were going to be persuasive, I think they would already have been so. Conversely, I don't think arguments of the form "by that logic, we don't need [some feature we already have]" are likely to be persuasive (though if the completion of that argument is actually "therefore we should remove it", please open an issue specifically about that).

I think what's left to do is work out what syntax choices are the most agreeable, offer the least element of surprise, and introduce the smallest practical amount of confusion. I encourage everyone to approach the questions in that spirit.

As for the working group being " largely of the opinion that ...", this definitely doesn't seem so definite. The last and only time there was an attempt at voting, exactly 50% of the voters did not support the proposal. Taking into account that some valued people were not present due to health and other reasons (could it not be because they were not feeling satisfied and confident with the current state and subject-matter of work?) , it wouldn't be too-surprising at all if this proposal turns out to be not too-popular even amongst the so called 5%.

If we really do care about "diversity", why not ask for the opinion of more users whenever approaching an obviously controversial decision?

ChristianGruen commented 1 year ago

The last and only time there was an attempt at voting, exactly 50% of the voters did not support the proposal. Taking into account that some valued people were not present due to health and other reasons (could it not be because they were not feeling satisfied and confident with the current state and subject-matter of work?) , it wouldn't be too-surprising at all if this proposal turns out to be not too-popular even amongst the so called 5%.

@dnovatchev Statements like this are simply biased and misleading. The result was that no one objected. 5 favored the proposal, 5 were undecided, no one objected (including you). Only 3 persons were not present in the meeting (https://qt4cg.org/meeting/minutes/2023/04-11.html).

The result of this vote was a new proposal: #447. I’m not even sure if you are still commenting on the old status quo or the recently proposed adjustments. Originally, this issue (#435) was about the “removal of the inlined function expression variant of the thin arrow operator“; we shouldn’t overstretch it and try to focus again to make progress.

  1. Is this the most important and most urgent new feature that we should be working on at present?

I’m sorry I have to mention that no one at the meeting strongly opposed the proposal except you. If we want to be able to focus on other features soon, it’s time to get constructive, accept others’ opinions that may contrast with the personal ones, and look at the overall picture again. Without compromises, we wouldn’t have added a single feature to the spec yet.

Next, note that the feature had already been included in the spec for a longer time; even users of us discovered it on their own. It would have been easy to comment on it at an earlier stage.

If we really do care about "diversity", why not ask for the opinion of more users whenever approaching an obviously controversial decision?

I regularly mention we do things like that. We are in regular contact with our users (both novice and advanced) via trainings and assisted coding sessions. I can safely confirm that a) there’s a need for a compacter lambda syntax and b) that an arrow for requesting single items has been repeatedly asked for, not only by our own team members. I can also confirm that users have been happy to see the thin arrow included in our latest minor versions (but we remind everyone that none of these features are to be included in productive code, which is also the reason we don’t document any preliminary 4.0 features before they haven’t been added to the spec).

I don’t understand why you aren’t bringing this into the equation when demanding diversity. Please don’t hesitate to share your experiences with users. I have shared some quantitative evaluations on code bases on Slack. I would be happy to see more of such results, as I believe they can help us to at least assess the acceptance of already added features.

dnovatchev commented 1 year ago

@ChristianGruen

The last and only time there was an attempt at voting, exactly 50% of the voters did not support the proposal. Taking into account that some valued people were not present due to health and other reasons (could it not be because they were not feeling satisfied and confident with the current state and subject-matter of work?) , it wouldn't be too-surprising at all if this proposal turns out to be not too-popular even amongst the so called 5%.

@dnovatchev Statements like this are simply biased and misleading. The result was that no one objected. 5 favored the proposal, 5 were undecided, no one objected (including you).

I am tired of people either ignoring facts pointed out or twisting statements made by me.

What I clearly said (quoted and bolded above) was that "exactly 50% of the voters did not support the proposal" not that they voted "against". The fact is that they didn't vote "for" this proposal.

Only 3 persons were not present in the meeting (https://qt4cg.org/meeting/minutes/2023/04-11.html).

As for "Only 3 persons were not present in the meeting" this is only 😄 30% of the people that were present. 😄😄

dnovatchev commented 1 year ago

Reading about the history of mathematical symbols here, it once again seems that being too-eager to add new such symbols is most likely going to pollute this nice space.

Will any of the proposed new XPath operators be known 100 years from now?

image

ChristianGruen commented 1 year ago

As #447 was merged, I’m closing this issue, as well as #53 and #436. In #503, an alternative compact syntax for anonymous functions with single arguments is discussed.