Project

Profile

Help

Bug #3106

closed

Problems applying fold-left() to random-number-generator()

Added by Michael Kay over 7 years ago. Updated almost 7 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
XPath conformance
Sprint/Milestone:
-
Start date:
2017-01-12
Due date:
% Done:

100%

Estimated time:
Legacy ID:
Applies to branch:
9.7
Fix Committed on Branch:
9.7, trunk
Fixed in Maintenance Release:
Platforms:

Description

The query

fold-left(1 to 10, random-number-generator(), function($z, $i){ head($z)('next')(), tail($z), head($z)('number')}) => tail()

ought to give a sequence of random numbers. It is failing in different ways in 9.7 and 9.8.

In 9.7 the final call to tail() returns an empty sequence; the result of fold-left() is a sequence containing a single item, the random-number-generator itself (a HashTrieMap).

In 9.8 the query crashes, saying

java.lang.IllegalStateException: A LazySequence can only be read once

at net.sf.saxon.om.LazySequence.iterate(LazySequence.java:52)

at net.sf.saxon.expr.VariableReference.iterate(VariableReference.java:525)

at net.sf.saxon.expr.TailExpression.iterate(TailExpression.java:135)
Actions #1

Updated by Michael Kay over 7 years ago

  • Status changed from New to Resolved
  • Applies to branch deleted (9.7)
  • Fix Committed on Branch 9.8 added

In the 9.7 case: user error. The query is generating the correct results but I failed to display them correctly.

Minor issue spotted: HashTrieMap.isTrustedResultType() returns false; this leads to unnecessary type checking of the result. It can safely return true, since the declared result type is ANY_SEQUENCE and the result will always satisfy this.

For 9.8, it is failing because arguments to a system function call (in this case the outermost call on fold-left) are passed as a LazySequence object, the contract being that the implementation of the system function will only read this sequence once. The implementation of fold-left() is not honouring this contract, because it passes the second argument "as is" to a user-written function which is not subject to this contract.

Fixed for 9.8 only.

Actions #2

Updated by Michael Kay over 7 years ago

  • Applies to branch 9.7 added
  • Fix Committed on Branch 9.7 added

Running some further tests, I tried increasing the first argument from (1 to 10) to read (1 to 1000). This leads to a StackOverflow, because the function accumulates a very deeply nested LazySequence, and the final evaluation of this LazySequence is recursive, which blows the stack. So I'm adding a patch which prevents the sequence becoming too deep: fold-left turns it into a grounded sequence every 20 iterations or so, providing a compromise between use of heap memory and excessive recursion.

Actions #3

Updated by O'Neil Delpratt about 7 years ago

  • Status changed from Resolved to Closed
  • % Done changed from 0 to 100
  • Fixed in Maintenance Release 9.7.0.15 added

Bug fix applied to the Saxon 9.7.0.15 maintenance release

Actions #4

Updated by O'Neil Delpratt almost 7 years ago

  • Fix Committed on Branch trunk added
  • Fix Committed on Branch deleted (9.8)
Actions #5

Updated by O'Neil Delpratt almost 7 years ago

  • Applies to branch deleted (9.8)

Please register to edit this issue

Also available in: Atom PDF