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:boolean: EBV support for more item types #829

Closed
ChristianGruen opened this issue Nov 12, 2023 · 9 comments
Closed

fn:boolean: EBV support for more item types #829

ChristianGruen opened this issue Nov 12, 2023 · 9 comments
Labels
Enhancement A change or improvement to an existing feature Propose Closing with No Action The WG should consider closing this issue with no action Propose for V4.0 The WG should consider this item critical to 4.0 XPath An issue related to XPath XQFO An issue related to Functions and Operators

Comments

@ChristianGruen
Copy link
Contributor

ChristianGruen commented Nov 12, 2023

In #817, it was discussed that the current EBV semantics have been inspired a lot by XPath 1.0. Today, we have numerous other data types apart from strings, doubles, booleans, and nodes, and I believe it’s time to do justice to this by getting rid of the error for unsupported data types for fn:boolean.

We currently have:

Type Rule to compute boolean value
node() true()
xs:boolean $item != 0 and not(is-NaN($item))
xs:untypedAtomic, xs:string, xs:anyURI $item != ''

I have two options in mind:

  1. The easiest solution, which would come closest to JavaScript, would be to return true() for all other items. This would allow us to do simple checks like:
declare function local:byte-length($data as xs:basexBinary?) xs:integer {
  (: instead of exists($data); utilizes the EXPath Binary Module :)
  if($data) then bin:length($data) else 0
};
  1. If we want to be more fine granular, we could do justice to the specifics of 4 more types:
Type Rule to compute boolean value
array(*) array:size($item) != 0
map(*) map:size($item) != 0
xs:base64Binary
xs:hex64Binary
bin:length($item) != 0 or
not($item = (xs:hexBinary(''), xs:base64Binary(''))

It would then be possible to write:

  • if($map) instead of map:size($map) != 0 or map:exists($map) (see #827 for the naming controversy).
    Note that if($map) will also return false() is $map is an empty sequence.
  • if($func) { $func(1, 2) } instead of exists($func)

In the last comments of #817, it was addressed that the behavior of existing code may change if errors are replaced by results. I hope we can live with that, as I cannot think of cases in which the EBV computation make sense for items that always raise an error.

Which option do some of you prefer?

@ChristianGruen ChristianGruen added XPath An issue related to XPath XQFO An issue related to Functions and Operators Enhancement A change or improvement to an existing feature labels Nov 12, 2023
@ChristianGruen ChristianGruen mentioned this issue Nov 12, 2023
@michaelhkay
Copy link
Contributor

My vote would go for making no change to the EBV rules. I think it's better that we require users to spell out exactly what condition they want to test for.

@dnovatchev
Copy link
Contributor

@ChristianGruen It is not clear with the proposed EBV rules what would be the value of boolean( () ) (My guess is that this must be false() ).

Could you, please, explain?

As for the boolean value of empty maps or arrays, we actually need functions: map:some and array:some for the important distinction between a map (which is an item() and its boolean value probably must be true()) and the contents of this map - which may be empty or non-empty.

@ChristianGruen
Copy link
Contributor Author

@ChristianGruen It is not clear with the proposed EBV rules what would be the value of boolean( () ) (My guess is that this must be false() ).

Could you, please, explain?

You're welcome: fn:boolean accepts arbitrary sequence. In this issue, I'm focusing on the evaluation of single items. The evaluation of empty sequences and sequences with more than 1 item won't change; so you're right, boolean(()) continues to return true.

@ChristianGruen ChristianGruen added the Propose for V4.0 The WG should consider this item critical to 4.0 label Nov 23, 2023
@ChristianGruen
Copy link
Contributor Author

Another user feedback, just from today, referred to the missing EBV support for dates (“if($start-date) raises an error – why?”). As so often, my recommendation was to use exists().

I checked what different processors report back for boolean(xs:date('2001-01-01')):

  • Saxon: Effective boolean value is defined only for sequences containing booleans, strings, numbers, URIs, or nodes
  • BaseX: Number, string, boolean, URI or nodes expected, xs:date found: "2001-01-01".
  • eXist-db: effective boolean value invalid operand type: xs:date
  • Zorba: invalid argument type for function fn:boolean()

I still believe the list of supported types is very arbitrary: Can we give a convincing answer why e.g. URIs are supported, but why QNames, dates, binary data, etc. are rejected?

@michaelhkay
Copy link
Contributor

michaelhkay commented Dec 13, 2023

The "convincing answer" is that the mechanism was invented in XPath 1.0 whose type system was strongly based on Javascript as defined in 1999, and as the type system grew larger (a) extending EBV to cover additional types would have involved many arbitrary decisions that users would find hard to remember, and (b) the Javascript community had itself discovered that the equivalent of EBV (truthy and falsy values) was proving a major nightmare, resulting in the introduction of new operators like "===" with stricter semantics, and general advice that good coding practice was to steer clear of the whole area.

Consider arrays. Is there any serious chance we will get the WG to agree what the EBVs of [], [0], [[]], and [()] should be, let alone persuade the user community that we have made the right decision?

@ChristianGruen
Copy link
Contributor Author

The "convincing answer" is that the mechanism was invented in XPath 1.0 whose type system was strongly based on Javascript as defined in 1999, and as the type system grew larger (a) extending EBV to cover additional types would have involved many arbitrary decisions that users would find hard to remember, and (b) the Javascript community had itself discovered that the equivalent of EBV (truthy and falsy values) was proving a major nightmare, resulting in the introduction of new operators like "===" with stricter semantics, and general advice that good coding practice was to steer clear of the whole area.

What I can observe is (based on the feedback we got over the last years) that the status quo is not satisfying, and I believe it’s exactly because the current language still “smells like XPath 1.0”, and something that was forgotten later on. I would see no reason to push this further without the historical aspect, but now that we have a rather arbitrary situation, I believe we should at least try to do justice to the existence of the other data types.

Consider arrays. Is there any serious chance we will get the WG to agree what the EBVs of [], [0], [[]], and [()] should be, let alone persuade the user community that we have made the right decision?

I would still hope so; that’s why I presented two options in the initial comment, and I would like to have a vote on them. My favorite would now be Option 1, i.e., doing what JavaScript does – your remark that XPath 1.0 was inspired by JavaScript underlines this – and return true() for all other items, i.e., perform a simple item existence check.

@ndw
Copy link
Contributor

ndw commented Dec 13, 2023

I don't remember having Javascript in mind back in 1999. We needed numbers and strings and booleans so we got those. We needed other things too, but the goals were less ambitious (or differently ambitious maybe).

I don't think we'd be making user's lives more difficult if we said the EBV of anything not currently covered was equivalent to ~exists()`. But I almost never try to write code that relies on it, so I don't feel strongly about it.

@ChristianGruen
Copy link
Contributor Author

When it comes to clean and usable design, JavaScript probably doesn’t stand a chance against Python, so if we don’t necessarily take JS as our reference, we could also choose a smarter approach. The mere existence of different solutions shouldn't deter us from choosing our own solution.

If people consider the JS equivalent of EBVs to be a nightmare, the question is why we advocate their usage in our spec at all. Do we generally believe it’s a concept that people users rely on? If yes, we should build on it. If no, we should say so in the spec and update the code examples in question to use explicit boolean comparisons.

@michaelhkay michaelhkay added the Propose Closing with No Action The WG should consider closing this issue with no action label Mar 8, 2024
@ndw
Copy link
Contributor

ndw commented Mar 12, 2024

The CG decided to close this issue without any further action at meeting 069.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement A change or improvement to an existing feature Propose Closing with No Action The WG should consider closing this issue with no action Propose for V4.0 The WG should consider this item critical to 4.0 XPath An issue related to XPath XQFO An issue related to Functions and Operators
Projects
None yet
Development

No branches or pull requests

4 participants