-
Notifications
You must be signed in to change notification settings - Fork 15
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
Simple mapping operator for arrays #1158
Comments
isnt this effectively my suggestion that was deemed irrelevant? i.e. if you embed the value in a non flattening container you can map.
means. (I do find XPATH is becoming more and more closely related to brainfuck, this is a geniune criticism, I can remember only a few weeks ago being accused of introducing suggestions for more and and esoteric operators, but I'm finding myself feeling the same way) Its a shame that these array suggestions effectively mirror sequence constructs but have subtly different syntax. I assume that the rule of thumb is. if the sequence operator is X then the array operator is !X? |
Sorry, I don't know which suggestion you are referring to. However, it's very much my personal style to reject new ideas when I first see them, and then come round to them later when I understand them better, so this is by no means impossible.
Yes, indeed so. We pretty well forced ourselves down that path when we decided that an array was a sequence of length one. No turning back from that, unfortunately.
The rule of thumb is, try to choose an operator that (a) doesn't make the grammar ambiguous, and (b) has some kind of mnemonic value in terms of its relationship to other operators either in XPath or in other languages. |
nice! one of the problems I have with F# is that there are several standard data types in the language, that all share the same patterns, e.g. map, bind etc, but in each data types module these functions have different names, now in a world of intellisense and a language where these functions are names (not operators) thats irritating, but not a massive problem, in a world of of operators and and no modules for intellisense to grab onto thats problematic, you just end up spending your day looking up operators in a spec. It would be nice to at least try to adopt some sort of naming convention that saves 10 visits to the XPath functions and operators specs per day. so if '!' is a sensible prefix to sequence operators to get the 'corresponding' arrray one, then the proposal makes sense (in fact you get a whole raft of functions and operators 'for free'
you can extend the same idea to map using '?' as the prefix? (though you would have to have a think what the context item is I assume a map-entry) you may want to also consider extending this suggestion to include a 'bind' operator for array (obviously a bind operator + unit can subsume map, and bind doesn't exist on sequence as it self/auto binds) If you don't have a naming convention then I stand by my brainfuck comment.) |
let me spell out the bind alternative/addition lets call it....
(horrid mashup of haskell and the above suggestion)
would be equivalent I think to
but bind is strictly more powerful than map. (I still dont know what *? means) |
This looks related to #700; maybe one of the issues is obsolete?
To understand the analogy better, how can multiple operations be chained this way? For example, how would the following expression need to be written? $data ~ subsequence(., 1, 5) ~ count(.) I see similarities, but I wonder if it can serve as a full and intuitive replacement. |
Yes, sorry, it's a duplicate. I've now split filtering and mapping into separate issues though, which is probably clearer. |
Please do spell it out. I have no idea from your post what |
theres always a danger of teaching granny to suck eggs, and as Wadler was part of XQuery (I think), I wonder how much of the stuff I drone on about is just tumbleweed (silence can be incomprehension or boredom of the obvious). lets use XQuery as a lingua franca (my XQuery is embryonic) but forget that sequences auto flatten (i.e. think of these as expressions over arrays), (its hard because the whole sequence thing in XPath etc is boiled in...but try to forget it, we have items and we have arrays) lets introduce 'map' and 'bind'
this in psuedo xpath is
but map alone cannot represent this
because there are two nested 'for' loops this is
(you can put the map in the bind, its equivalent) i.e. you need both map and bind to do nested for loops BUT you can express map in terms of bind and unit where 'unit' is the function that takes a single value and puts in an array....i.e. (u don't need to read this deeply)
thats hand written so it will be wrong somewhere.... In psuedo XQuery its just the following trick. map is only required in the above translation if the 'return' term has a function applied to it, so this so i simply map this
to this
i.e. i wrap the returned expression in a we cant do the trick the other way around (we need a function to logically 'eliminate' the collection type). ok, thats lots of (slightly hand waving flawed lingua franca) theory.... so...the summary is
P.S. the operator for bind in haskell is |
Definitely entertaining, either way…
I guess you are looking for We also have $array !! EXPR
array:for-each($array, fn { EXPR }) |
achchchch....how to say in 5 lines what took me 50 I assume you don't have bind? (it unfortunate you used 'for-each', as nesting for-each functions doesnt do the same as nesting for-each statements....I probably would have done the same, and regretted it) |
I can’t tell who chose it, but it’s popular in various other languages, and I assume yet another
I’m not sure if you are missing an operator or a function:
fn:for-each(
$input as item()*,
$action as function(item(), xs:integer) as item()*
) as item()* |
…a fair observation, which I share: There’s nothing about |
I assumed that Mr Kay was just prefixing all array operators with ! |
I assume there is a typo in action's type like map, its either or both an operator or function. well in sequences bind doesnt really make sense, because sequences cant be nested so map and bind are functionally equivalent,,,but if they could then,,,, so map (for-each) does this fn:map(
$input as item()*,
$action as function(item(), xs:item()) as item()*
) as item and bind does this fn:bind(
$input as item()*,
$action as function(item(), xs:item()*) as item()*
) as item and unit does this (takes a value and embeds it in a sequence of 1 element. fn:unit(
$input as item()
) as item()* do we have a common language we all dabble in a bit? Haskell? no I know a few others but not well enough. for-each IS common, but not as a 'map' function, its usually used for effectively side effects, i.e. actions with no return, in C# map is 'select' and bind is 'selectmany', in scala its 'map' and 'mapflatten', in haskell its 'map' and 'bind' etc etc I can write the definitions in XQuery probably |
I’m not sure which one you mean. If there is one, it would need to be fixed in the spec as well (https://qt4cg.org/specifications/xpath-functions-40/Overview.html#func-for-each).
Thanks. So you’d like to have an equivalent solution to Scala’s
Java may be an alternative, other languages as well, but the main challenge (at least for me) is to understand how you would expect XPath to change. |
sorry my post is wrong let me fix it |
sorry my post is wrong, it was the
and pretend this query is over an array (i.e. no auto flattening) then you'd define bind and map like this (this is the equivalent expression to above).
the I'd love to be good enough at XQuery to write this definition over array, but I'm not, and I think actually it would be quite ugly (because it doesnt exist). note this is supposed to demonstrate the behaviour of functions that would be in XPath....I'm using XQuery simply as a language to communicate behaviour. |
As you can probably imagine, we had quite a debate before calling the function We reckoned that far more of our users would know XSLT than would know Haskell or other functional programming languages... |
Simple answer, no. One of the joys of this business is that we are all steeped in different traditions. Getting people who live and breathe SQL to talk to people who live and breathe Haskell or Javascript is a major undertaking, but a very rewarding one for everyone. |
Call me old fashioned, but I tend to believe speaking a common language is a prerequisite to effective communication, reality is a shared experience, language is just syntax. |
yes but the issue cascades, a for-each statement isnt just a map, its map + bind, so if you call map, 'for-each' then what do you call 'bind'? i think thats why these other languages have used for-each for the only case where map and bind coincide i.e. when they return unit. |
Since our sequences are a bit different from the lists used by most functional languages, our operators will inevitably be a little different. And one of the challenges in computing has always been that if your X is a little bit different from someone else's X, should you call it X or should you find a different name? There is no right answer. |
Its a common trap, F# is largely borrowed from Haskell, but even there they have made an inconsistent mess of 'bind', sometimes its bind, sometimes its collect, sometimes it doesnt exist...I think that is a wrong answer (there are plenty of those too), if a language (haskell) has gone to the bother of being incredibly formal about its constructs then not following the same structure (if not maybe the same names), would seem foolhardy. whatever, this is a tangent.
P.S. what does |
You find some good examples in the spec: https://qt4cg.org/specifications/xquery-40/xquery-40.html#id-unary-lookup |
Please explain what Haskell "bind" does. I've found plenty of web sites that claim to explain it in simple terms, but the simple terms require a prior understanding of a whole host of abstract concepts (starting with monads) and a whole raft of algebraic notation. You can't assume that people reading here are up to speed on your favourite language. I think your question about
Indeed so, and despite the fact that we come from many different backgrounds, the one thing we should be able to assume is that everyone here understands the current specs. |
ah thankyou, so I assume
|
that's quite a narrow potential population of contributors. |
For general questions on XPath, https://xmlcom.slack.com or StackOverflow may be better platforms indeed; others can jump in there if needed, and we’ll be able to keep the issue threads focused. I hope that sounds reasonable. With regard to bind, I would be happy to hear your summary (it’s been a while ago when I spent some time with Haskell). |
It wasn't a general question, I was asking about ?* in the context of this issue, it seemed a reasonable question, I'm happy to try to try to explain bind (though it also seems to me to be a general question that could be asked elsewhere also). Genuinely if my ramblings are not worth the reading, or I don't 'qualify' to contribute, let me know and I'll take the dog a walk instead, I DO use XPath and XSLT every day, I'm far from an expert in it, or 'familiar' with the specs, i actually think my main value in these discussions is i'm consciously not an expert, I know why some of this is difficult and unintuitive, where I think those that know the spec intimately have forgotten, you are all mostly unconsciously competent, whilst I am consciously incompetent. I am consciously competent in other languages, which I think helps, but if its just noise, then I'll shut up. I'm happy you are 'happy', but you don't need to indulge me if it has no value. I'll write an explanation but dont feel obliged to read it, its technically not directly relevant to the issue. lets take an informal explantion using the word 'maybe/may/might'. Am I going to post something on this site in the next week that has value? (possibly controversial) There maybe an issue that interests me. So this is an informal constructive proof that I may post something of value. so notice each is of the same form, I extract something from the previous expression derive a 'maybe' relationship and continue until I get to the end then I terminate the sentence by returning the noun 'value', This is effectively a monad. There are two rules here, e.g. (and now I need a common language for types...I'll use haskell as you've explicitly mentioned it) e.g. the functions
and but now given a 'Maybe Post' I can create a function to tell me if it way understood
if we were to model my example we would get
so bind allows you to chain together these functions to create new functions that you can then bind so in haskell Philip Wadler and Stephen Blott invented do notation (just syntax sugar) and the above can be written
(apologies with any more intimate with Haskell syntax for my handwritten code) notice this looks a lot like
obviously XQuery doesnt understand Maybe, but it could, and sequence and array and map are all 'monadic' and can support bind. note you cannot do this with just map, if you used map to chain my example you would get a
but you can use map + concat (i.e. array join) but bind is more primitive. I'll get my coat. |
@MarkNicholls The discussion became quite emotional. I’m sorry if you felt offended and if misunderstood. And…
Same here. I’m not a native speaker; there must be better ways to express I appreciate your time. And…
Thanks for your summary, which I’ll certainly read. In the meanwhile, I was lazy and asked ChatGPT to give me a non-technical dummy summary, which I’ll add for the sake of completeness: Imagine you have a box, and inside this box could be either a toy or it could be empty. Now, you want to do something with the toy, like paint it, but you can only proceed if there is actually a toy in the box. In this scenario,
This tool is useful because it lets you chain these actions together. For example, if you need to first wash the toy and then paint it, This way, you don't have to keep opening the box yourself to check for the toy at every step; |
My comment to you wasn't intended to sound churlish, apologies, as a native speaker it does. Like a lot of what chatgpt says...I'm not sure its explanation helps me, there is a danger that you immediately think a monad is a collection, when IO, for example, is monadic but I cant see how to apply its analogy to IO, it doesn't work for me, there is no empty box,, but if I say a function that takes a value and returns a value AND does some IO and its signature is.
bind is simply the mechanism used to chain constructs like these together for a fixed polymorphic type that obeys the rules (there are rules too...but we can ignore them). P.S. (this is meant to be light hearted) chatgpt also says this
but chatgpt is a pretty low bar. |
Marked |
The CG decided not to proceed with this. Reasons include: (a) concern about the proliferation of operators and the difficulty of remembering them and reading the resulting code (b) the fact that there are other ways of doing this, e.g. |
See also additional discussion at meeting 085, 9 July 2024. |
I propose to provide
!!
as a simple mapping operator for arrays.For example
[(1,2,3), (4.5.6)]!!count(.)
returns[3, 3]
.The expression on the LHS must be an array.
The expression on the RHS is evaluated once for every member of the array, with that member as the context value, with the context position set to the position of that member in the array, and with the context size set to the array size.
The result is returned as an array which will always be the same size as the input array.
Note in passing that this provides a solution (though perhaps a clumsy solution) to issue #755, in that the example expression
(0 to 4) ~ count(.)
can now be written as
[(0 to 4)]!!count(.)?*
The text was updated successfully, but these errors were encountered: