Register Guidelines E-Books Today's Posts Search

Go Back   MobileRead Forums > E-Book Software > Calibre > Library Management

Notices

Reply
 
Thread Tools Search this Thread
Old 05-07-2022, 02:04 PM   #1
chaley
Grand Sorcerer
chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.
 
Posts: 11,757
Karma: 7029857
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
Request for opinion: a template while loop

I have been thinking about adding a while loop construct to the template language. This would permit looping based on a count or some test between two lists. The construct would be what one would expect:
Code:
    while expr do
        <<stuff>>
    od
An alternate form could be
Code:
    while expr:
        <<stuff>>
    od
I prefer the first because the correspondence between "do" and "od" is clearer.

The problem: this construct would for the first time permit infinite loops in the template language. A template infinite loop would freeze the GUI and be nearly impossible to fix because the user could never get past the loop to the editor.

One possible fix is to limit the number of iterations to something, perhaps 1000. The loop would exit if this limit is hit. That would permit getting to the editor to fix it, albeit with some delays. This solution opens the door to a language construct to specify the limit, for example:
Code:
    while expr limit <numeric expression> do
        <<stuff>>
    od
Another solution would be to set a computation time limit, perhaps 1 second, but this would be slower because it would require checking the elapsed time every iteration (or every N interations where N is small). Of course the time limit could be set as above, only with the limit in milliseconds instead of iterations.

An alternate construct would be to avoid the problem by not using a while loop but instead require a counting for loop and a break statement, such as:
Code:
    for var range N to M:
        <<stuff>>
        if <something> then break fi;
        <<stuff>>
    rof
This construct would loop max(0, (M - N)) times. I would still need either to put a maximum on (M - N) or use a maximum duration.

Thoughts on
  • whether a while loop is useful (use cases are welcome)
  • which form you prefer
  • how to deal with infinite loops
will be appreciated.
chaley is offline   Reply With Quote
Old 05-08-2022, 02:00 AM   #2
kovidgoyal
creator of calibre
kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.
 
kovidgoyal's Avatar
 
Posts: 43,920
Karma: 22669818
Join Date: Oct 2006
Location: Mumbai, India
Device: Various
I vote for a for loop. Since the language is meant for newcomers to programming to be able to use, its safer.
kovidgoyal is online now   Reply With Quote
Advert
Old 05-08-2022, 09:06 AM   #3
davidfor
Grand Sorcerer
davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.
 
Posts: 24,906
Karma: 47303748
Join Date: Jul 2011
Location: Sydney, Australia
Device: Kobo:Touch,Glo, AuraH2O, GloHD,AuraONE, ClaraHD, Libra H2O; tolinoepos
I'd go with the for loop as well. I've seen the condition on while loops mess up far to many times.
davidfor is offline   Reply With Quote
Old 05-08-2022, 03:12 PM   #4
ownedbycats
Custom User Title
ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.
 
ownedbycats's Avatar
 
Posts: 8,710
Karma: 62000001
Join Date: Oct 2018
Location: Canada
Device: Kobo Libra H2O, formerly Aura HD
As someone who's good at breaking things, the for loop seems a lot more difficult to break.
ownedbycats is online now   Reply With Quote
Old 05-08-2022, 05:06 PM   #5
DNSB
Bibliophagist
DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.
 
DNSB's Avatar
 
Posts: 35,839
Karma: 145624992
Join Date: Jul 2010
Location: Vancouver
Device: Kobo Sage, Forma, Clara HD, Lenovo M8 FHD, Paperwhite 4, Tolino epos
Quote:
Originally Posted by ownedbycats View Post
As someone who's good at breaking things, the for loop seems a lot more difficult to break.
Not quite right. A while loop can be a lot harder to break. A reset or power down may be needed.
DNSB is offline   Reply With Quote
Advert
Old 05-08-2022, 05:18 PM   #6
ownedbycats
Custom User Title
ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.
 
ownedbycats's Avatar
 
Posts: 8,710
Karma: 62000001
Join Date: Oct 2018
Location: Canada
Device: Kobo Libra H2O, formerly Aura HD
Quote:
Originally Posted by DNSB View Post
Not quite right. A while loop can be a lot harder to break. A reset or power down may be needed.
Halt and catch fire, essentially?
ownedbycats is online now   Reply With Quote
Old 05-08-2022, 05:39 PM   #7
DNSB
Bibliophagist
DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.DNSB ought to be getting tired of karma fortunes by now.
 
DNSB's Avatar
 
Posts: 35,839
Karma: 145624992
Join Date: Jul 2010
Location: Vancouver
Device: Kobo Sage, Forma, Clara HD, Lenovo M8 FHD, Paperwhite 4, Tolino epos
Quote:
Originally Posted by ownedbycats View Post
Halt and catch fire, essentially?
Yes. Fond memories of executing a 0xDD instruction on a Motorola 6800 (commonly called Halt and Catch Fire but also known as Drop Dead (made it easy to remember the instruction value).
DNSB is offline   Reply With Quote
Old 05-10-2022, 03:02 AM   #8
ownedbycats
Custom User Title
ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.
 
ownedbycats's Avatar
 
Posts: 8,710
Karma: 62000001
Join Date: Oct 2018
Location: Canada
Device: Kobo Libra H2O, formerly Aura HD
Could this be a simple use case for a while loop?

I was thinking something like this in an action chain:

Code:
while select($identifiers, 'mobi-asin') do columnupdate_identifiers_amazon() od
Which, if I understand right, would loop the template until mobi-asin no longer exists and thus resolve the 'needing to run it twice' issue.

Last edited by ownedbycats; 05-10-2022 at 03:23 AM.
ownedbycats is online now   Reply With Quote
Old 05-10-2022, 04:39 AM   #9
chaley
Grand Sorcerer
chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.
 
Posts: 11,757
Karma: 7029857
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
Quote:
Originally Posted by ownedbycats View Post
Could this be a simple use case for a while loop?

I was thinking something like this in an action chain:

Code:
while select($identifiers, 'mobi-asin') do columnupdate_identifiers_amazon() od
Which, if I understand right, would loop the template until mobi-asin no longer exists and thus resolve the 'needing to run it twice' issue.
As I said in the other post, I don't understand the question. Lets keep the discussion over there.
chaley is offline   Reply With Quote
Old 05-12-2022, 10:46 AM   #10
chaley
Grand Sorcerer
chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.
 
Posts: 11,757
Karma: 7029857
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
I am implementing the for/range loop.

Syntax:
Code:
for_expr  ::= for_list | for_range
for_list  ::= 'for' identifier 'in' list_expr 
          [ 'separator' separator_expr ] ':' expression_list 'rof'
for_range ::= 'for' variable 'range' [ start_expr 'to' ] stop_expr
          [ 'limit' limit_expr ] ':' expression_list 'rof'
The loop is zero-based -- from start_expr up to but not including stop_expr. Example: "range 0 to 10" counts from zero to nine. This makes loops that reference lists and strings more natural, as in this example that uppercases every other letter in the title.
Code:
program:
	res = '';
	for i range 0 to strlen($title):
	    c = substr($title, i, i+1);
	    res = strcat(res, if mod(i, 2) == 0 then uppercase(c) else c fi)
	rof
If you omit the start_expr then it is set to zero.

The limit specified the maximum number of loop iterations allowed. It is set to 1000 if omitted.
chaley is offline   Reply With Quote
Old 05-12-2022, 09:35 PM   #11
davidfor
Grand Sorcerer
davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.davidfor ought to be getting tired of karma fortunes by now.
 
Posts: 24,906
Karma: 47303748
Join Date: Jul 2011
Location: Sydney, Australia
Device: Kobo:Touch,Glo, AuraH2O, GloHD,AuraONE, ClaraHD, Libra H2O; tolinoepos
Quote:
Originally Posted by chaley View Post
I am implementing the for/range loop.

Syntax:
Code:
for_expr  ::= for_list | for_range
for_list  ::= 'for' identifier 'in' list_expr 
          [ 'separator' separator_expr ] ':' expression_list 'rof'
for_range ::= 'for' variable 'range' [ start_expr 'to' ] stop_expr
          [ 'limit' limit_expr ] ':' expression_list 'rof'
The loop is zero-based -- from start_expr up to but not including stop_expr. Example: "range 0 to 10" counts from zero to nine. This makes loops that reference lists and strings more natural, as in this example that uppercases every other letter in the title.
Code:
program:
	res = '';
	for i range 0 to strlen($title):
	    c = substr($title, i, i+1);
	    res = strcat(res, if mod(i, 2) == 0 then uppercase(c) else c fi)
	rof
If you omit the start_expr then it is set to zero.

The limit specified the maximum number of loop iterations allowed. It is set to 1000 if omitted.
That looks good.

Except that I really don't like the handling of the range. Firstly, I will never remember the upper limit rules. I will automatically write "strlen($title) - 1" and wonder why it doesn't work properly. I would always expect that the range to handle both the start number and the last number.
davidfor is offline   Reply With Quote
Old 05-13-2022, 04:30 AM   #12
chaley
Grand Sorcerer
chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.
 
Posts: 11,757
Karma: 7029857
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
Quote:
Originally Posted by davidfor View Post
Except that I really don't like the handling of the range. Firstly, I will never remember the upper limit rules. I will automatically write "strlen($title) - 1" and wonder why it doesn't work properly. I would always expect that the range to handle both the start number and the last number.
I hear you. Unfortunately I don't think there is a one-true answer.

We start with the fact that like in python, ranges in the template language are 'i = start' to 'i < stop'. Consider list slices and substrings. Why should a loop from 1 to strlen(x) do something different than substr(x,1,strlen(x))
or sublist(x,1,4,',')?

We then should consider previous knowledge, which argues for doing what some other language already does. There are three basic formulations that I remember:
  1. Python and other list-handling languages such as lisp: loop over a sequence of items.
  2. Java and other C-derived languages: (initializer, condition, increment).
  3. Pascal, Fortran, and Algol-like languages: "from n to m" inclusive.
The question: which one to choose? I could go with either of the first 2. I don't like the third because the loop has different semantics than slices.

Any one of the following works for me:
  • Implement the Python range() function as a 'real' function. Example:
    Code:
        i = range(0, 5)
    returns the list '0,1,2,3,4'. One could use this in the standard 'for' as in
    Code:
        for i in range(0,5):
    or even
    Code:
        return range(0,5)
    This has the advantage of consistency with python, and doesn't introduce a new syntax for loops.
  • Go all the way to Java. Example:
    Code:
        for (i = 0, i < 5, i = i + 1):
    This makes all the choices explicit at the cost of some complexity. It is also much more error prone, but the 'limit' specification helps with that.
  • Look for wording that implies the limit is less-than. Example:
    Code:
        for i range 1 upto 5:
    This has the advantage of being simple, but the implication remains just that -- an implication. It probably won't translate well.
I am strongly tempted to go with the range() function. Its semantics are well documented, it is 'pythonic' and calibre is written in python, and it fits well into the template language architecture. And who knows, being able to generate a list of numbers in sequence might actually be useful. In this case, range() would be defined like python's range, as follows:
  • Base definition: range(start, stop, step). The argument count determines which values are provided.
  • range(5): arg count of one is 'stop'. The resulting list is '0,1,2,3,4'
  • range(1, 5): arg count of two is 'start, stop'. The list is '1,2,3,4'
  • range(0, 5, 2): arg count of three is 'start, stop, step', The list is '0,2,4'
  • range(5, 0, -1): example of negative step. The list is '5,4,3,2,1'
The values can be specified by expressions as in range(strlen(x)).

Using this scheme the for statement syntax would be mostly unchanged. The only change is to add the 'limit' clause.
Code:
for_expr  ::= 'for' identifier 'in' list_expr  [ 'separator' separator_expr ] 
              [ 'limit' limit_expr ] ':' expression_list 'rof'
The range() function is a 'list_expr'
chaley is offline   Reply With Quote
Old 05-13-2022, 05:06 AM   #13
kovidgoyal
creator of calibre
kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.
 
kovidgoyal's Avatar
 
Posts: 43,920
Karma: 22669818
Join Date: Oct 2006
Location: Mumbai, India
Device: Various
From a usability perspective I like range, however, range has th eissue of performance, which is why though the initial python implementation of range returned a list of numbers, in later versions it was changed to return an iterator over numbers.
kovidgoyal is online now   Reply With Quote
Old 05-13-2022, 05:41 AM   #14
chaley
Grand Sorcerer
chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.
 
Posts: 11,757
Karma: 7029857
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
Quote:
Originally Posted by kovidgoyal View Post
From a usability perspective I like range, however, range has th eissue of performance, which is why though the initial python implementation of range returned a list of numbers, in later versions it was changed to return an iterator over numbers.
I am worried about that. I am considering making range() a pseudo-function valid only in the context of a for statement. Because I know the context I can use the built-in range(), not generating the actual list. Something like this:
Code:
program:
    for i in range(1, 10, 1) limit 1000:
        <<something>>
    rof
would be implemented as
Code:
    generator = (str(j) for i,j in enumerate(range(start, stop, step)) if i < limit)
    for lv in generator:
        user_vars[loop_var] = lv
        <<execute the block>>
The str() is needed because all values in the template language are strings.

It might be better from an error reporting standpoint not to check the limit in the generator but instead use an enumerate() when looping, checking the limit explicitly, and raising an exception if it is exceeded. Something like:
Code:
    generator = (str(j) for j in range(start, stop, step))
    for count, lv in enumerate(generator):
        if count > limit:
            raise (ERROR)
        user_vars[loop_var] = lv
        <<execute the block>>
chaley is offline   Reply With Quote
Old 05-13-2022, 07:27 AM   #15
kovidgoyal
creator of calibre
kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.
 
kovidgoyal's Avatar
 
Posts: 43,920
Karma: 22669818
Join Date: Oct 2006
Location: Mumbai, India
Device: Various
You could have both, in the for loop context make range special and everywhere else have it return a list. Reporting an error when limit is exceeded seems better to me.

If you do have range be a special function in the for context, you can statically determine when limit is excedded instead of checking on every iteration.
kovidgoyal is online now   Reply With Quote
Reply


Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Template: Converting a search & replace into a template ownedbycats Library Management 11 03-26-2021 04:32 AM
Request for comments: new template language operations chaley Library Management 3 02-27-2021 12:09 PM
Request: Match Calibre Filename template recipe cbook7 Library Management 10 06-05-2020 05:11 AM
Request: template-making assistance for column built from other columns iienderii Library Management 9 04-04-2016 10:27 PM
Request for Feedback on E-book Web Template andreasw Writers' Corner 5 05-14-2011 12:34 AM


All times are GMT -4. The time now is 02:35 AM.


MobileRead.com is a privately owned, operated and funded community.