New semantics of utime.ticks_diff

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
User avatar
pythoncoder
Posts: 4793
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

New semantics of utime.ticks_diff

Post by pythoncoder » Tue Nov 01, 2016 9:57 am

Unusually the maintainers have introduced a change which breaks existing code. This has been discussed ad nauseam on Github, but for those who don't go there a word of warning. The latest firmware build has implemented a reversal in the ticks_diff() argument order so that it now works like arithmetic subtraction. To time the interval between events you now need to issue:

Code: Select all

import utime
old = utime.ticks_ms()
# do something
time_taken = utime.ticks_diff(utime.ticks_ms(), old)
This poses a problem for those of us with code which users may run against old firmware builds. One solution is as follows with ticksdiff() retaining the old semantics. It works with any firmware build.

Code: Select all

import utime
def tdiff():
    new_semantics = utime.ticks_diff(2, 1) == 1
    def func(old, new):
        nonlocal new_semantics
        if new_semantics:
            return utime.ticks_diff(new, old)
        return utime.ticks_diff(old, new)
    return func

ticksdiff = tdiff()
Arguably a bit of a bodge but it does enable a quick search and replace.
Peter Hinch

pfalcon
Posts: 1155
Joined: Fri Feb 28, 2014 2:05 pm

Re: New semantics of utime.ticks_diff

Post by pfalcon » Tue Nov 01, 2016 11:39 am

Thanks for bringing this up, pythoncoder - it was in my queue to, which is as usual backlogged.

So, I'd like to start with - if you are affected by this change (i.e. if you need to update your code for the new argument order), please add comment to this thread. We, maintainers, sometimes have a skewed outlook - seeing all the issue reports, many of which aren't directly related to MicroPython itself, but to outside matters, or answers to which can be easily found by looking at docs, it's easy to believe: "Well, nobody uses yet that non-standard function we added, let's change it". Again, that may turn out a skewed position - we miss all people who silently enjoy MicroPython and read the docs and use what's described there without any issues. So this, change is kind of experiment - don't be silent, let is know you use it (ticks_diff() in this case) ;-).

Otherwise, I have to say that any non-standard feature we add to MicroPython implicitly has "provisional" status and may change, just like ticks_diff() did. Rest assured that we aren't set to break anything and everything, and we have pretty good change control: all changes are discussed, and actions usually take months to collect any opinions first. Among 2 core maintainers, we also have different position: more conservative (should I say "rather conservative") by Damien and more liberal (as you guessed) by me, so we need to come to common understanding before making a change. But note that with "Micro" in MicroPython doesn't cater for accumulating all the compatibility hacks and different versions of API. So, we may need to make such changes in the future too. Beauty (of the API) requires sacrifice.

Note that now the semantics of ticks_*() is described in very detailed manner in the docs: http://docs.micropython.org/en/latest/e ... e.ticks_ms

And to achieve compatibility with older and newer versions you just need to wrap ticks_diff() in abs():

Code: Select all

import utime
def ticks_diff(a, b):
    return abs(utime.ticks_diff(a, b))
(We of course encourage to just switch to newer version when it is released.)
Awesome MicroPython list
Pycopy - A better MicroPython https://github.com/pfalcon/micropython
MicroPython standard library for all ports and forks - https://github.com/pfalcon/micropython-lib
More up to date docs - http://pycopy.readthedocs.io/

Lysenko
Posts: 62
Joined: Wed Aug 17, 2016 1:21 pm

Re: New semantics of utime.ticks_diff

Post by Lysenko » Tue Nov 01, 2016 12:48 pm

pfalcon wrote: So, I'd like to start with - if you are affected by this change (i.e. if you need to update your code for the new argument order), please add comment to this thread.
My native language is English which is written left to right. As a consequence the semantics of time intervals are invariably:

start -> stop
then -> now
birth -> death
before -> after

Swapping the argument order to invert that, especially in a library that is already in production is .... questionable. I haven't had cause to use this function myself, but I program in several languages on a day to day basis and I'm definitely not inclined to use it as implemented.

Past/Start/Before/Smaller is always to the left of Future/Now/Stop/After/Bigger:

getIntegerRange(1, 10)
getCharRange('A', 'Z')
getDateRange(birth, death)

getTicksDiff(death, birth) ???!!!

That's the sort of illogical nonsense I expect from PHP. When I'm forced to use a library that does this sort of thing (puts larger values on the left for no good reason) then I almost invariably wrap the API to restore consistency which in this case would mean reverting your change.

pfalcon
Posts: 1155
Joined: Fri Feb 28, 2014 2:05 pm

Re: New semantics of utime.ticks_diff

Post by pfalcon » Tue Nov 01, 2016 1:21 pm

Lysenko, you exactly follow the evolution of ticks_diff() semantics. It started with thinking like you just showed, but progressed beyond that to what it is now. If you keep thinking, you will arrive there too.

Hint: there's no "before" and "after" in ticks_diff() arguments. It's just "a" and "b". And you can use ticks_diff() to find if "a" was before "b", or "b" before "a". And then ticks_diff() takes arguments in the order subtraction operator takes them: "a - b" and produce value similar to subtraction - it will be negative if "a" is "before" "b". And all that is written in the docs, and some share of people will keep not reading them.
Awesome MicroPython list
Pycopy - A better MicroPython https://github.com/pfalcon/micropython
MicroPython standard library for all ports and forks - https://github.com/pfalcon/micropython-lib
More up to date docs - http://pycopy.readthedocs.io/

Lysenko
Posts: 62
Joined: Wed Aug 17, 2016 1:21 pm

Re: New semantics of utime.ticks_diff

Post by Lysenko » Tue Nov 01, 2016 1:55 pm

pfalcon wrote:Lysenko, you exactly follow the evolution of ticks_diff() semantics. It started with thinking like you just showed, but progressed beyond that to what it is now. If you keep thinking, you will arrive there too.
Possible, but unlikely. Ticks emanate from the internal clock which is incrementing to produce larger numbers as time passes, much like a UNIX timestamp just with greater resolution and no externally fixed base.

If I were spending most of my time implementing MicroPython you might be correct, but I'm not. This morning I was working on a sensor graph. That consists of:

PIC18 - C - MP-LAB
PIC32 - Pascal - Mikroelektronika
i.MX6 - Linux/Python 3
Server - Linux/Flask/Python 3
Browser - TypeScript/Angular2/HighCharts

I move around within that stack all the time. Having: ticks_diff(now, last_irq) reversed in logic from time_diff(last_login,now) is a recipe for me making mistakes that compilers and linters can't catch.

My interest in MP is related to swapping the PICs for STM parts btw.

User avatar
wminarik
Posts: 7
Joined: Thu Oct 27, 2016 12:03 am
Location: Montréal, Canada

Re: New semantics of utime.ticks_diff

Post by wminarik » Tue Nov 01, 2016 3:34 pm

Thank you, @pythoncoder, for noting the change and for providing the code snippet. If you don't mind, would you post the link to the related Github discussion? When I see a reference like yours, I try to find the discussion as a way of practicing my Git-fu. This time I'm unable to make the link... (it's not because I want to be nauseous!) It also helps me to understand the evolution of MicroPython.
Cheers,
Bill
Last edited by wminarik on Wed Nov 02, 2016 2:29 pm, edited 1 time in total.

User avatar
pythoncoder
Posts: 4793
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: New semantics of utime.ticks_diff

Post by pythoncoder » Wed Nov 02, 2016 9:11 am

@wminarik https://github.com/micropython/micropython/issues/2217
@pfalcon Thanks for your much simpler abs() solution ;)

As for argument order this debate has been going on at least since the days of CP/M86 vs MSDOS 1.0, and probably since the time of Babbage ;) I'm agnostic on the subject; it's all down to age. If you're young, you remember. When you get to my age you have to look it up every time :?
Peter Hinch

Lysenko
Posts: 62
Joined: Wed Aug 17, 2016 1:21 pm

Re: New semantics of utime.ticks_diff

Post by Lysenko » Wed Nov 02, 2016 12:10 pm

pythoncoder wrote: As for argument order this debate has been going on at least since the days of CP/M86 vs MSDOS 1.0, and probably since the time of Babbage ;) I'm agnostic on the subject; it's all down to age. If you're young, you remember. When you get to my age you have to look it up every time :?
Personally I'm not that exercised about this, I just replied because the question was asked.

What is more potentially concerning is uneccessarily breaking a userspace function in a patch. Swapping the parameters fixes no bug and adds no functionality. It does nothing besides break existing code and address one perspective on "aesthetics".

That's the sort of thing you expect (if at all) in a full version increment. UART.send vs UART.write is another example of course, so I guess people are used to it with this project (though that one isn't as bad because it will break hard, not silently).

User avatar
pythoncoder
Posts: 4793
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Code-breaking

Post by pythoncoder » Wed Nov 02, 2016 1:22 pm

To be fair I can't recall an instance of a code-breaking change in over two years of using modules such as pyb. MicroPython has now been ported to multiple platforms and there's an ongoing effort to develop a unified model for hardware such as UARTs, pins and other interfaces. Some breakages are inevitable in modules aiming to support this model.

It's not obvious to new users that, for example, pyb is stable while machine may not be: clarification would be good. And code breaking changes should, in my view, be synchronised with formal firmware releases and documented with a suitable change list.
Peter Hinch

Lysenko
Posts: 62
Joined: Wed Aug 17, 2016 1:21 pm

Re: Code-breaking

Post by Lysenko » Wed Nov 02, 2016 1:56 pm

pythoncoder wrote: MicroPython has now been ported to multiple platforms and there's an ongoing effort to develop a unified model for hardware such as UARTs, pins and other interfaces. Some breakages are inevitable in modules aiming to support this model.
Absolutely. Except that this change doesn't address such issues as your workaround illustrates. All changes like this do are scratch personal itches regarding elegance/aesthetics and break userspace. A certain volatile personage well known in OSS circles would never approve ! ;)

Anyway, it's no big deal so long as you know what the polices are. Personally I want:

function ticks_interval(const start : UInt32; const stop : UInt32) : Integer

... and I'm free to implement it.

Post Reply