Skip to content
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

fn:function-identity for maps and arrays #1881

Open
michaelhkay opened this issue Mar 15, 2025 · 18 comments · May be fixed by #1895
Open

fn:function-identity for maps and arrays #1881

michaelhkay opened this issue Mar 15, 2025 · 18 comments · May be fixed by #1895
Labels
Bug Something that doesn't work in the current specification PR Pending A PR has been raised to resolve this issue XQFO An issue related to Functions and Operators

Comments

@michaelhkay
Copy link
Contributor

The data model spec says that function identity is not defined for maps and arrays.

The specification of fn:function-identity() fails to mention this fact.

@michaelhkay michaelhkay added Bug Something that doesn't work in the current specification XQFO An issue related to Functions and Operators labels Mar 15, 2025
@michaelhkay
Copy link
Contributor Author

The situation is a bit more complex than this -- and very unsatisfactory. The information is very scattered around the various specs.

The data model, in section 7, has very little to say about "maps as functions" or "arrays as functions". In fact, it doesn't even mention that maps and arrays are functions. It also fails to mention that function identity is exposed through the fn:function-identity function.

And XDM section 4.2 only mentions in passing that maps and arrays are functions ("A map item, as well as being a function, ...").

The main exposition of function identity is not in XDM, but in XPath §4.7.2 -- which doesn't mention maps and arrays.

XPath §3.2.8.2 and §3.2.8.4 have a bit more to say about maps/arrays as functions, but they don't mention function identity.

F&O 1.9.5 has a bit more to say about function identity, but again it doesn't really cover the ground. Quite apart from the fact that you wouldn't expect to find this material in a section headed "Terminology".

@dnovatchev
Copy link
Contributor

dnovatchev commented Mar 16, 2025

The data model spec says that function identity is not defined for maps and arrays.

The specification of fn:function-identity() fails to mention this fact.

Not true. At present the referred-to above DM paragraph is no longer in the DM. It was deleted by the PR for
fn:function-identity : See https://qt4cg.org/specifications/xpath-datamodel-40/Overview.html#function-items

Image

The specification of fn:function-identity() fails to mention this fact.

Why should this be mentioned here? any map and any array is a function, therefore it can be passed as the argument of a call to fn:identity

@michaelhkay
Copy link
Contributor Author

Not true. At present the referred-to above DM paragraph is no longer in the DM. It was deleted by the PR for
fn:function-identity

Thanks for that information. I wondered what happened to it. The deletion leaves a gap - if arrays and maps have a function identity, we need to say what it is.

@dnovatchev
Copy link
Contributor

Not true. At present the referred-to above DM paragraph is no longer in the DM. It was deleted by the PR for
fn:function-identity

Thanks for that information. I wondered what happened to it. The deletion leaves a gap - if arrays and maps have a function identity, we need to say what it is.

We do not say anything about "what function identity is". The text of the specifications says that it is "abstract".

If so, we don't need to specify what more precisely is the identity of maps and arrays, or otherwise need to say what the identity is for any function type.

@michaelhkay
Copy link
Contributor Author

Some users and implementers might expect that there is only one empty map, others might expect that there are many. We should enlighten them.

@dnovatchev
Copy link
Contributor

dnovatchev commented Mar 16, 2025

Some users and implementers might expect that there is only one empty map, others might expect that there are many. We should enlighten them.

Shouldn't this be part of the specification/definition of map, and not added "after the fact"/only in the definition of function identity?

It seems to me very clear that in an immutable language we need a single {} and []. And the main place for stating this is the section on Maps - not the section for function-identity.

@michaelhkay
Copy link
Contributor Author

Shouldn't this be part of the specification/definition of map, and not added

Sure. I'm not talking about where it should be stated, I'm just saying it needs to be said.

@ChristianGruen
Copy link
Contributor

It seems to me very clear that in an immutable language we need a single {} and [].

While it may seem obvious, it may not necessarily be the case. For example, { 1: 2 } => map:remove(1) may result in a different empty-map instance than { 'a': 'b' } => map:remove('a') if specialized internal implementations are used to represent integer maps and string maps.

And the main place for stating this is the section on Maps - not the section for function-identity.

(agreed)

@dnovatchev
Copy link
Contributor

if specialized internal implementations are used to represent integer maps and string maps.

If so, these implementations are just wrong. {} is both an integer-key map and a string-key map - in fact it is map(T1, T2) for any types T1 and T2.

Like in an OO PL, object is of any other, more-concrete type.

@michaelhkay
Copy link
Contributor Author

If so, these implementations are just wrong

Are you saying they violate a rule in the spec, or that they violate your personal expectations?

@dnovatchev
Copy link
Contributor

If so, these implementations are just wrong

Are you saying they violate a rule in the spec, or that they violate your personal expectations?

What implementations do internally should not affect the user of the language.
When I am using BaseX I may even not know that it is written in Java, and as a user I don't care how many internal representations of an empty map they might be using - it is up to them and we, the users don't care. Such separation gives a lot of freedom and convenience to both users and implementors of the language.

@ChristianGruen
Copy link
Contributor

ChristianGruen commented Mar 17, 2025

If so, these implementations are just wrong. {} is both an integer-key map and a string-key map - in fact it is map(T1, T2) for any types T1 and T2.

An implementation is wrong if it does not comply with the spec.

We can include the rule in the specification that all empty maps must have the same function identity, but it may be an arbitrary decision from both implementer’s and the user’s perspective. If {} and {} are defined to have the same identity, there is no stringent requirement that { 1: 1 } and { 1: 1 } shouldn’t; many users would even expect it.

With regard to BaseX, enforcing the same identity for empty maps wouldn’t change things; we use one internal instance for all empty maps.

@MarkNicholls
Copy link

@ChristianGruen

I find this a bit confusing.

I would expect { 1: 1 } and { 1: 1 } to be equal.

are you saying they should or they shouldn't be?

(I can understand a conversation about whether {} and {} are equal (or even makes sense) - because the 'type' of the items is not specified).

@ChristianGruen
Copy link
Contributor

I find this a bit confusing.

I guess so.

I would expect { 1: 1 } and { 1: 1 } to be equal.

To avoid misunderstandings: These two maps are already defined to be deep-equal in the spec, but in the scope of this issue, the function identity concept is to be extended for maps and arrays, and an open question is which maps are supposed to have the same identity, such that the recently added fn:function-identity function returns the same string for these maps.

are you saying they should or they shouldn't be?

Neither nor. I want to point out that there is no obvious answer to that question.

@MarkNicholls
Copy link

MarkNicholls commented Mar 17, 2025

to me, the "obvious" answer is that they are equal (unless I'm missing something)?

I personally think the problem here is "functional identity", not these expressions.

It may just be easier to wrap these data types and make them, non functions and dissolve the issue.

(I say this because I think functional identity is akin to "squaring the circle", so the fewer cases you can apply it to the better)

@michaelhkay
Copy link
Contributor Author

Indeed, until recently the data model spec said that the concept of "function identity" was not applicable to maps and arrays, because they were always compared by their content. We seem to have lost the statement that maps and arrays have no function identity, and are left with a situation where they do have an identity but we don't say what it is. That's the problem which this issue describes.

@MarkNicholls
Copy link

MarkNicholls commented Mar 17, 2025

yes, I can see that's not ideal, cant you just add the statement back in?

(I'm not trying to be obtuse, I think function-identity is probably a mistake, so anything that comes up here about it I tend to read).

@dnovatchev
Copy link
Contributor

I would expect { 1: 1 } and { 1: 1 } to be equal.

are you saying they should or they shouldn't be?

Definitely equal. Why at all could anyone think they are unequal?

I find all this argument quite artificial, with no solid justification. Unless you could prove otherwise...

@michaelhkay michaelhkay linked a pull request Mar 25, 2025 that will close this issue
@michaelhkay michaelhkay added the PR Pending A PR has been raised to resolve this issue label Mar 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something that doesn't work in the current specification PR Pending A PR has been raised to resolve this issue XQFO An issue related to Functions and Operators
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants