Un reloj simple a otro -- beginner campo con timer campo con forth camp codereview Relacionados El problema

A simple clock in FORTH


7
vote

problema

Español

Intento programar un reloj de cronómetro / cuenta regresiva a otro con GFORTH (y usar palabras específicas de GFORTH).

Soy un principiante completo y el siguiente código es el material básico (voy a agregar una función de alarma / la opción de cuenta regresiva y más).

Por ahora el cronómetro cuenta desde las 00:00:00 (HH: MM: SS) hasta 24:00:00 y

  • presionando espacio pausa el reloj, presionándolo nuevamente reanuda el reloj
  • presionando j / k configura el reloj hacia atrás / adelante un minuto
  • presionando j / k configura el reloj hacia atrás / adelante una hora
  • presionando q Soporta el programa

¿Mi código sigue las mejores prácticas? ¿Es un mal estilo para las palabras como move-clock-seconds-back para devolver las banderas porque se utilizarán en una declaración 99887776655544332 ?

  1000000 constant million  : sextal  ( -- )    6 base ! ;  : hhmmss.  ( ud --  )    drop million /  0 <# decimal # sextal # [char] : hold decimal # sextal # [char] : hold decimal # sextal # decimal #> TYPE ;  : pause-clock  ( ud -- ud f )    utime    begin       50 ms       key? if          key bl = ( pause is released )       else         false ( clock keeps pausing )       then    until    utime d- d-     false ;  : move-clock-seconds-ahead  ( u ud -- ud f )     million * 0 d-     false ;  : move-clock-seconds-back  ( u ud -- ud f )     million * 0 d+     utime dmin     false ;  : get-elapsed-time  ( ud -- ud )     2dup     utime      2swap d- ;  : 24-hours-elapsed?  ( ud -- f )     get-elapsed-time ( elapsed time fits in single integer )     drop 24 60 * 60 * million * u> ;  : run-clock  ( -- )     page ( clears the terminal )     utime ( returns a ud timestamp in microseconds )     begin        50 ms ( sleep for 50 ms )        get-elapsed-time        5 0 at-xy ( coordinates where to print output )        hhmmss.        key? if        key case        bl of pause-clock endof           [char] j of 60 move-clock-seconds-back endof           [char] k of 60 move-clock-seconds-ahead endof           [char] J of 60 60 * move-clock-seconds-back endof           [char] K of 60 60 * move-clock-seconds-ahead endof           [char] q of true endof           false swap ( the char is now on top of the stack, will be dropped by endcase )        endcase        else 24-hours-elapsed? if           CR           ." 24 hours elapsed."           true        else           false        then then     until ;  run-clock  bye   
Original en ingles

I try to program a stopwatch/countdown clock in FORTH with Gforth (and using Gforth-specific words).

I'm a complete beginner and the following code is the basic stuff (going to add an alarm function / countdown option and more).

For now the stopwatch counts from 00:00:00 (hh:mm:ss) up to 24:00:00 and

  • pressing space pauses the clock, pressing it again resumes the clock
  • pressing j/k sets the clock back/ahead one minute
  • pressing J/K sets the clock back/ahead one hour
  • pressing q quits the program

Does my code follow best practices? Is it bad style for words like move-clock-seconds-back to return flags because they will be used in a begin ... until statement?

1000000 constant million  : sextal  ( -- )    6 base ! ;  : hhmmss.  ( ud --  )    drop million /  0 <# decimal # sextal # [char] : hold decimal # sextal # [char] : hold decimal # sextal # decimal #> TYPE ;  : pause-clock  ( ud -- ud f )    utime    begin       50 ms       key? if          key bl = ( pause is released )       else         false ( clock keeps pausing )       then    until    utime d- d-     false ;  : move-clock-seconds-ahead  ( u ud -- ud f )     million * 0 d-     false ;  : move-clock-seconds-back  ( u ud -- ud f )     million * 0 d+     utime dmin     false ;  : get-elapsed-time  ( ud -- ud )     2dup     utime      2swap d- ;  : 24-hours-elapsed?  ( ud -- f )     get-elapsed-time ( elapsed time fits in single integer )     drop 24 60 * 60 * million * u> ;  : run-clock  ( -- )     page ( clears the terminal )     utime ( returns a ud timestamp in microseconds )     begin        50 ms ( sleep for 50 ms )        get-elapsed-time        5 0 at-xy ( coordinates where to print output )        hhmmss.        key? if        key case        bl of pause-clock endof           [char] j of 60 move-clock-seconds-back endof           [char] k of 60 move-clock-seconds-ahead endof           [char] J of 60 60 * move-clock-seconds-back endof           [char] K of 60 60 * move-clock-seconds-ahead endof           [char] q of true endof           false swap ( the char is now on top of the stack, will be dropped by endcase )        endcase        else 24-hours-elapsed? if           CR           ." 24 hours elapsed."           true        else           false        then then     until ;  run-clock  bye 
        

Lista de respuestas

2
 
vote
vote
La mejor respuesta
 

La otra revisión cubre algunos puntos valiosos, por lo que solo me concentraré en agregar sugerencias adicionales aquí.

Considere la portabilidad

Realmente no parece haber una necesidad de precisión de microsegundos para este temporizador, por lo que sugeriría que en lugar de usar el 99887766555544330 , tal vez time&date (que es estándar) podría ser utilizado.

Considere restaurar la base numérica

Cuando programo a otro, a menudo lo estoy usando en modo hexagonal. Si utilicé su hhmmss. Word, me molestaría que no restauró la base original. Solo se necesitan algunas palabras adicionales para almacenar y restaurar base .

considere establecer explícitamente la base

Cuando el programa define million se utilizará cualquier base se ha establecido previamente, lo que resultará en un comportamiento muy extraño si no es decimal. La buena práctica es establecer explícitamente la base para que esto pueda ser un módulo independiente.

Agregar comentarios

Hay algunos comentarios dentro del código, pero sugeriría que cada función podría tener un comentario inmediatamente por encima de la definición para describir lo que hace. La convención habitual es usar para tales comentarios y para usar ( -- ) para comentarios de pila que ya está haciendo.

Hacer que los comentarios cuenten

Describiendo qué page hace en un comentario asociado no es muy útil, ya que page es una palabra estándar y debe ser bien entendida. Mejor sería documentar lo que se supone que está en la pila (semánticamente, no solo cuán grande y cuántos)

tiene cada palabra hacer solo una cosa

Ya se ha mencionado que el time&date0 que comienza time&date1 es muy extraño y no es una buena idea. De manera similar, finalizar varias de las otras palabras con time&date2 es en el mejor contraintuncia. En general, sigo la guía de que las únicas cosas en la pila son las cosas que se requieren para que se define la palabra en particular. Esto lo convierte en que la persona que llama haga las manipulaciones de la pila sean necesarias para poner las cosas en el lugar correcto. Podría hacer que el programa sea un poco más largo, pero es muy probable que sea mucho más fácil de depurar interactivamente.

Use más constantes

El número de milisegundos en 24 horas podría calcularse una vez, colóquelo en una constante y luego se usa en lugar de calcularlo cada vez a través de time&date3 .

Arregla los comentarios de la pila

Los comentarios de la pila para time&date4 y time&date5 no son correctos. En lugar de time&date6 , deben leer time&date7 .

fijar tipográficos menores

Corrección del error en uno de los comentarios (Pring - & gt; imprimir) y fijando el formato del primer caso (debe ser sangrado con los otros casos).

Simplifique la lógica

En este momento, el código contiene estas líneas:

  time&date8  

Creo que sería un poco más conciso escribirlo así:

  time&date9  
 

The other review covers some valuable points, so I'll just concentrate on adding additional suggestions here.

Consider portability

There does not really seem to be a need for microsecond precision for this timer, so I'd suggest that rather than using the non-standard utime, perhaps time&date (which is standard) could be used.

Consider restoring the number base

When I program in Forth, I'm often using it in hex mode. If I used your hhmmss. word, I'd be annoyed that it didn't restore the original base. It only takes a few extra words to store and restore base.

Consider explicitly setting the base

When the program defines million it will be using whatever base had previously been set, which will result in very strange behavior if it's not decimal. Good practice is to explicitly set the base so that this can be a standalone module.

Add comments

There are a few comments within the code, but I'd suggest that each function could have a comment immediately above the definition to describe what it does. The usual convention is to use \ for such comments and to use ( -- ) for stack comments as you're already doing.

Make comments count

Describing what page does in an associate comment isn't very useful, since page is a standard word and should be well understood. Better would be to document what's assumed to be on the stack (semantically, not just how big and how many)

Have each word do just one thing

It's already been mentioned that the drop that begins hhmmss. is very odd and not a good idea. Similarly, ending a number of the other words with false is at best counterintuitive. Generally, I follow the guideline that the only things on the stack are things that are required for the particular word being defined. This makes it up the caller to do whatever stack manipulations are required to put things in the right place. It might make the program slightly longer, but it is very likely to make it a lot easier to interactively debug.

Use more constants

The number of milliseconds in 24 hours could be calculated once, put into a constant and then used instead of calculating it each time through 24-hours-elapsed?.

Fix the stack comments

The stack comments for move-clock-seconds-ahead and move-clock-seconds-back are not correct. Instead of ( u ud -- ud f ), they should both read ( ud u -- ud f ).

Fix minor typos

Correcting the error in one of the comments (pring -> print) and fixing the formatting of the first case (it should be indented with the other cases).

Simplify the logic

Right now, the code contains these lines:

   else 24-hours-elapsed? if       CR       ." 24 hours elapsed."       true    else       false    then then 

I think it would be a little more concise to write it instead like this:

   else 24-hours-elapsed? dup if       CR       ." 24 hours elapsed."    then then 
 
 
3
 
vote

un comentario en

  hhmmss.0  

parece mal. El código deja el tiempo transcurrido en la parte superior de la pila no modificada, por lo que la acción es realmente hhmmss.1 .

La forma hhmmss.2 Deja un doble resultados en hhmmss.3 y hhmmss.5 . Recomiendo encarecidamente hacer que se deje un solo entero en su lugar.

También recomiendo para reducir las manipulaciones de la pila con

  hhmmss.6  

es un mal estilo para las palabras como el movimiento-reloj-segundos-Volver a las banderas de retorno

si. Hace que sea muy difícil reutilizarlos en otros contextos. Considerar (no probado)

  hhmmss.7  
 

A comment in

: get-elapsed-time  ( ud -- ud ) 

seems wrong. The code leaves the elapsed time on top of the otherwise unchanged stack, so the action is really (-- ud).

The way get-elapsed-time leaves a double results in very unnerving drop in hhmmss. and 24-hours-elapsed?. I strongly recommend to make it leave a single integer instead.

I also recommend to reduce stack manipulations with

: get-elapsed-time     utime     2over     d- drop ; 

Is it bad style for words like move-clock-seconds-back to return flags

Yes. It makes it very hard to reuse them in other contexts. Consider (untested)

    begin key dup [char] q <> while         case             ....         endcase     repeat 
 
 
       
       

Relacionados problema

6  Juguete del intérprete  ( Toy forth interpreter ) 
He estado leyendo demasiados papeles y escribiendo muy poco código. Estas son mis primeras 300 líneas de Haskell: {-# LANGUAGE NoMonomorphismRestriction, T...

7  Un reloj simple a otro  ( A simple clock in forth ) 
Intento programar un reloj de cronómetro / cuenta regresiva a otro con GFORTH (y usar palabras específicas de GFORTH). Soy un principiante completo y el sig...

24  Fizzbuzz a adelante  ( Fizzbuzz in forth ) 
Hay bastante a grande number_number de existente implementatons de fizzbuzz pero me desperté esta mañana en un sudor frío wi ¡La terrible reve...

Relacionados problema

6  Juguete del intérprete 
7  Un reloj simple a otro 
24  Fizzbuzz a adelante 



© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos