thinking outloud

Wednesday, 17 June 2015 · 3 messages
RS
Rob Stapper17 Jun 2015 13:41 #
Hi Christian, Elaborating on the issue below and just thinking out loud. Would it make sense having to opportunity to evaluate a function body lazily? Consider the following function:
declare function item:exists
( $item , $existProcessor , $emptyValue ) { if ( exists( $item)) then $existProcessor( $item) else $emptyValue } ; Even when called with an existing: $item, $emptyValue will be evaluated what could be an expensive evaluation. Having the possibility of lazy evaluation of the function body would prevent this. I’ve two questions: - does the above make sense? - does it make enough sense to be implemented in basex? If implemented: for keeping the code clean, specifying this laziness should be done within the function, not within the function call. I tumbled on the %basex:inline-annotation for global variables. This would do very nicely for specifying laziness for evaluating function bodies.
declare %basex:inline function item:exists
( $item , $existProcessor , $emptyValue ) { if ( exists( $item)) then $existProcessor( $item) else $emptyValue } ; Best, Rob
Quoted text · Christian Grün · 55 lines
Van: Christian Grün [mailto:christian.gruen at gmail.com] Verzonden: woensdag 13 mei 2015 12:36 Aan: Rob Stapper; BaseX Onderwerp: Re: [basex-talk] unexpected behaviour If I get it right, you would also expect '!' not to be output in the following query, right? declare function local:f($a, $b) { if($a) then $b else () }; local:f((), trace('!')) In this case, you'll have to wrap your trace call in a function: declare function local:f($a, $b) { if($a) then $b() else () }; local:f((), function() { trace('!') }) Best, Christian On Wed, May 13, 2015 at 11:44 AM, Rob Stapper <r.stapper at lijbrandt.nl> wrote: Hi Christian, This is the best I can do without losing the essence of the issue. Sorry about the import, forgot to remove that one. The clue is in the “Query Info”-window. It shows: Evaluating: f1: 1 Compiling: ……. So function “local:f1#1” is unnecessarely evaluated with value 1. Success, Rob Van: Christian Grün [mailto:christian.gruen at gmail.com] Verzonden: woensdag 13 mei 2015 11:13 Aan: Rob Stapper CC: BaseX Onderwerp: Re: [basex-talk] unexpected behaviour Hi Rob, It usually takes me some time to understand new code, so could you possibly simplify the example as much as possible? For example, the import cannot be resolved, an empty squence is bound to $a, which means that one branch will never be called, and maybe you can simplify the partial function application as well.. Thanks in advance, Christian On Wed, May 13, 2015 at 9:55 AM, Rob Stapper <r.stapper at lijbrandt.nl> wrote: Hi Christian, Can you have a look at the attached program. Both items of the returned sequence of the program should do the same thing. Both do give the same, correct result: an empty sequence, but the first item unnecessarely triggers function: “local:f1#1” , while the second item doesn’t. This a pity since “local:f1#1” could be a time-consuming function. Cheers, Rob _____ <http://www.avast.com/> Afbeelding verwijderd door afzender. Avast logo Dit e-mailbericht is gecontroleerd op virussen met Avast antivirussoftware. www.avast.com <http://www.avast.com/> _____ <http://www.avast.com/> Afbeelding verwijderd door afzender. Avast logo Dit e-mailbericht is gecontroleerd op virussen met Avast antivirussoftware. www.avast.com <http://www.avast.com/> --- Dit e-mailbericht is gecontroleerd op virussen met Avast antivirussoftware. https://www.avast.com/antivirus
CG
Christian Grün17 Jun 2015 15:05 #
Hi Rob, Yes, lazy evaluation of function arguments or the function body could be an interesting optimization. We just need to find someone who's motivated enough to implement it.. ;) For now, you can either trust the function inlining feature or, as you have already discovered by yourself, enforce function inlining with the %basex:inline flag. In this case, you can often prevent expensive operations to be evaluated. This is e.g. the case in the following query:
  declare %basex:inline function local:exists(
    $item, $existProcessor, $emptyValue
  ) {
    if ( exists( $item))
    then $existProcessor( $item)
    else $emptyValue
  };

  let $f := function($x) { 123 }
  let $e := (1 to 10000000)[. = 0]
  return local:exists(123, $f, $e)
Quoted text · Rob Stapper · 231 lines
On Wed, Jun 17, 2015 at 1:41 PM, Rob Stapper <r.stapper at lijbrandt.nl> wrote: > > Hi Christian, > > > > Elaborating on the issue below and just thinking out loud. > > Would it make sense having to opportunity to evaluate a function body lazily? > > > > Consider the following function: > > > > declare function item:exists > > ( $item > > , $existProcessor > > , $emptyValue > > ) > > { if ( exists( $item)) > > then $existProcessor( $item) > > else $emptyValue > > } ; > > > > Even when called with an existing: $item, $emptyValue will be evaluated what could be an expensive evaluation. > > Having the possibility of lazy evaluation of the function body would prevent this. > > I’ve two questions: > > - does the above make sense? > > - does it make enough sense to be implemented in basex? > > > > If implemented: for keeping the code clean, specifying this laziness should be done within the function, not within the function call. > > I tumbled on the %basex:inline-annotation for global variables. This would do very nicely for specifying laziness for evaluating function bodies. > > > > declare %basex:inline function item:exists > > ( $item > > , $existProcessor > > , $emptyValue > > ) > > { if ( exists( $item)) > > then $existProcessor( $item) > > else $emptyValue > > } ; > > > > Best, > > Rob > > Van: Christian Grün [mailto:christian.gruen at gmail.com] > Verzonden: woensdag 13 mei 2015 12:36 > Aan: Rob Stapper; BaseX > Onderwerp: Re: [basex-talk] unexpected behaviour > > > > If I get it right, you would also expect '!' not to be output in the following query, right? > > > > declare function local:f($a, $b) { > > if($a) then $b else () > > }; > > local:f((), trace('!')) > > > > In this case, you'll have to wrap your trace call in a function: > > > > declare function local:f($a, $b) { > > if($a) then $b() else () > > }; > > local:f((), function() { trace('!') }) > > > > Best, > > Christian > > > > > > > > On Wed, May 13, 2015 at 11:44 AM, Rob Stapper <r.stapper at lijbrandt.nl> wrote: > > Hi Christian, > > > > This is the best I can do without losing the essence of the issue. Sorry about the import, forgot to remove that one. > > The clue is in the “Query Info”-window. It shows: > > > > Evaluating: > > f1: 1 > > Compiling: > > ……. > > > > So function “local:f1#1” is unnecessarely evaluated with value 1. > > > > Success, > > Rob > > > > Van: Christian Grün [mailto:christian.gruen at gmail.com] > Verzonden: woensdag 13 mei 2015 11:13 > Aan: Rob Stapper > CC: BaseX > Onderwerp: Re: [basex-talk] unexpected behaviour > > > > Hi Rob, > > > > It usually takes me some time to understand new code, so could you possibly simplify the example as much as possible? For example, the import cannot be resolved, an empty squence is bound to $a, which means that one branch will never be called, and maybe you can simplify the partial function application as well.. > > > > Thanks in advance, > > Christian > > > > > > > > On Wed, May 13, 2015 at 9:55 AM, Rob Stapper <r.stapper at lijbrandt.nl> wrote: > > Hi Christian, > > > > Can you have a look at the attached program. > > Both items of the returned sequence of the program should do the same thing. > > Both do give the same, correct result: an empty sequence, but the first item unnecessarely triggers function: “local:f1#1” , while the second item doesn’t. > > This a pity since “local:f1#1” could be a time-consuming function. > > > > Cheers, > > Rob > > > > ________________________________ > > Dit e-mailbericht is gecontroleerd op virussen met Avast antivirussoftware. > www.avast.com > > > > > > > > ________________________________ > > Dit e-mailbericht is gecontroleerd op virussen met Avast antivirussoftware. > www.avast.com > > > > > > > > ________________________________ > > Dit e-mailbericht is gecontroleerd op virussen met Avast antivirussoftware. > www.avast.com > >
CG
Christian Grün17 Jun 2015 15:10 #
PS: the inline annotation does not only work for global functions. See e.g. the following example, in which inlining is disabled:
  let $fun := function() { 123 }
  let $def := (1 to 100000000)[. = 0]
  return %basex:inline(0) function($fun, $def) {
    if(exists($fun)) then $fun() else $def
  }($fun, $def)
Quoted text · Christian Grün · 258 lines
On Wed, Jun 17, 2015 at 3:05 PM, Christian Grün <christian.gruen at gmail.com> wrote: > Hi Rob, > > Yes, lazy evaluation of function arguments or the function body could > be an interesting optimization. We just need to find someone who's > motivated enough to implement it.. ;) > > For now, you can either trust the function inlining feature or, as you > have already discovered by yourself, enforce function inlining with > the %basex:inline flag. In this case, you can often prevent expensive > operations to be evaluated. This is e.g. the case in the following > query: > > declare %basex:inline function local:exists( > $item, $existProcessor, $emptyValue > ) { > if ( exists( $item)) > then $existProcessor( $item) > else $emptyValue > }; > > let $f := function($x) { 123 } > let $e := (1 to 10000000)[. = 0] > return local:exists(123, $f, $e) > > > On Wed, Jun 17, 2015 at 1:41 PM, Rob Stapper <r.stapper at lijbrandt.nl> wrote: >> >> Hi Christian, >> >> >> >> Elaborating on the issue below and just thinking out loud. >> >> Would it make sense having to opportunity to evaluate a function body lazily? >> >> >> >> Consider the following function: >> >> >> >> declare function item:exists >> >> ( $item >> >> , $existProcessor >> >> , $emptyValue >> >> ) >> >> { if ( exists( $item)) >> >> then $existProcessor( $item) >> >> else $emptyValue >> >> } ; >> >> >> >> Even when called with an existing: $item, $emptyValue will be evaluated what could be an expensive evaluation. >> >> Having the possibility of lazy evaluation of the function body would prevent this. >> >> I’ve two questions: >> >> - does the above make sense? >> >> - does it make enough sense to be implemented in basex? >> >> >> >> If implemented: for keeping the code clean, specifying this laziness should be done within the function, not within the function call. >> >> I tumbled on the %basex:inline-annotation for global variables. This would do very nicely for specifying laziness for evaluating function bodies. >> >> >> >> declare %basex:inline function item:exists >> >> ( $item >> >> , $existProcessor >> >> , $emptyValue >> >> ) >> >> { if ( exists( $item)) >> >> then $existProcessor( $item) >> >> else $emptyValue >> >> } ; >> >> >> >> Best, >> >> Rob >> >> Van: Christian Grün [mailto:christian.gruen at gmail.com] >> Verzonden: woensdag 13 mei 2015 12:36 >> Aan: Rob Stapper; BaseX >> Onderwerp: Re: [basex-talk] unexpected behaviour >> >> >> >> If I get it right, you would also expect '!' not to be output in the following query, right? >> >> >> >> declare function local:f($a, $b) { >> >> if($a) then $b else () >> >> }; >> >> local:f((), trace('!')) >> >> >> >> In this case, you'll have to wrap your trace call in a function: >> >> >> >> declare function local:f($a, $b) { >> >> if($a) then $b() else () >> >> }; >> >> local:f((), function() { trace('!') }) >> >> >> >> Best, >> >> Christian >> >> >> >> >> >> >> >> On Wed, May 13, 2015 at 11:44 AM, Rob Stapper <r.stapper at lijbrandt.nl> wrote: >> >> Hi Christian, >> >> >> >> This is the best I can do without losing the essence of the issue. Sorry about the import, forgot to remove that one. >> >> The clue is in the “Query Info”-window. It shows: >> >> >> >> Evaluating: >> >> f1: 1 >> >> Compiling: >> >> ……. >> >> >> >> So function “local:f1#1” is unnecessarely evaluated with value 1. >> >> >> >> Success, >> >> Rob >> >> >> >> Van: Christian Grün [mailto:christian.gruen at gmail.com] >> Verzonden: woensdag 13 mei 2015 11:13 >> Aan: Rob Stapper >> CC: BaseX >> Onderwerp: Re: [basex-talk] unexpected behaviour >> >> >> >> Hi Rob, >> >> >> >> It usually takes me some time to understand new code, so could you possibly simplify the example as much as possible? For example, the import cannot be resolved, an empty squence is bound to $a, which means that one branch will never be called, and maybe you can simplify the partial function application as well.. >> >> >> >> Thanks in advance, >> >> Christian >> >> >> >> >> >> >> >> On Wed, May 13, 2015 at 9:55 AM, Rob Stapper <r.stapper at lijbrandt.nl> wrote: >> >> Hi Christian, >> >> >> >> Can you have a look at the attached program. >> >> Both items of the returned sequence of the program should do the same thing. >> >> Both do give the same, correct result: an empty sequence, but the first item unnecessarely triggers function: “local:f1#1” , while the second item doesn’t. >> >> This a pity since “local:f1#1” could be a time-consuming function. >> >> >> >> Cheers, >> >> Rob >> >> >> >> ________________________________ >> >> Dit e-mailbericht is gecontroleerd op virussen met Avast antivirussoftware. >> www.avast.com >> >> >> >> >> >> >> >> ________________________________ >> >> Dit e-mailbericht is gecontroleerd op virussen met Avast antivirussoftware. >> www.avast.com >> >> >> >> >> >> >> >> ________________________________ >> >> Dit e-mailbericht is gecontroleerd op virussen met Avast antivirussoftware. >> www.avast.com >> >>

⚡Generated with XQuery