HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Twirling cursor

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
twirlingcursorstackoverflow

Problem

I'm writing a twirling cursor, which is a cursor that twirls in place in the console. In Forth, this takes just 3 lines, whereas in Python3 I have this:

from time import sleep # sleep(sec)
import sys

def flash(c):
    """Shows character c momentarily."""
    # backspace ($8)  and sleep(sec)  keep it in place and slow enough to see
    print(c,end=""); sys.stdout.flush(); sleep(0.05); print(chr(0x8),end=""); sys.stdout.flush()
    return

def halftwirl():
    """Twirls the cursor in place half-way i.e. | / - \."""
    flash(chr(0x7C)); flash(chr(0x2F)); flash(chr(0x2D)); flash(chr(0x5C));
    return

def twirl(n):
    """Twirls cursor in place n times."""
    for i in range(2*n):
        halftwirl()
    return

# Programme
print(twirl.__doc__)
twirl(5)


Whilst this works, and is no different from Forth in terms of code structure (see the Forth below), it is still, to my eyes, quite verbose.

In Forth, where there is no expense in calling subroutines, one naturally does something like this:

\ Building Blocks
0x7C  constant .|     
0x2F  constant ./     
0x2D  constant .-     
0x5C  constant .\     
0x8   constant .del    \ backspace delete

: flash ( c -- ) emit 50 ms .del emit ;  \ show character momentarily

: half-twirl ( -- )  .| flash   ./ flash   .- flash   .\ flash ;  \ half-twirl cursor in place

: twirl ( n -- ) 0 do half-twirl half-twirl loop ;  \ twirl cursor in place n times


Questions:

-
Is the cost of calling subroutines in Python cheap enough to support refactoring, i.e. pulling out flash() as its own subroutine, halftwirl() as its own, and making twirl() call these within its inner loop?

-
Is the resulting verbosity as compared to similarly factored Forth code just the cost of doing business when writing in Python compared to Forth, or am I missing some Python idioms?

Solution

Repetitive code should be put in a loop.

Most programmers don't have the ASCII table memorized. Why not use literal characters instead?

Flush can be handled by print() itself. I don't believe you need to flush after backspacing.

The speed of the rotation can be made overridable with a trivial change.

from time import sleep 

def halftwirl(delay=0.05):
    """Twirls the cursor in place half-way i.e. | / - \."""
    for glyph in '|/-\\':
        print(glyph, end='', flush=True)
        sleep(delay)                # sleep(sec) to keep it slow enough to see
        print('\b', end='')         # backspace to keep it in place


To answer your questions:

  • Performance is just not an issue here. The main slowdowns would be the deliberate sleep() call and I/O overhead.



  • See the rewrite above.

Code Snippets

from time import sleep 

def halftwirl(delay=0.05):
    """Twirls the cursor in place half-way i.e. | / - \."""
    for glyph in '|/-\\':
        print(glyph, end='', flush=True)
        sleep(delay)                # sleep(sec) to keep it slow enough to see
        print('\b', end='')         # backspace to keep it in place

Context

StackExchange Code Review Q#40724, answer score: 4

Revisions (0)

No revisions yet.