Smalltalk tiene el tiempo True: -Mensaje implementado a través de la recursión (en VisualWorks) o mediante el compilador en línea (en Squeak/Pharo). ¿Hay alguna forma de definir dicho método sin usar uno de ellos? Si no, ¿hay alguna prueba de que esté disponible en algún lado?¿Hay alguna forma en un lenguaje de solo mensaje para definir un mensaje while True sin recursión o trucos de compilación?
Respuesta
whileTrue: & whileFalse: always return nil. p. si hay una definición recursiva normales:
whileTrue: aBlock
^self value ifTrue: [self whileTrue: aBlock]
la ifTrue: volverá nula si el valor de uno mismo es falso y lo que el valor debe ser siempre cero. Eso se refleja en la optimización del compilador. El libro azul original de Smalltalk-80 V2 definición es
whileTrue: aBlock
"Evaluate the argument, aBlock, as long as the value
of the receiver is true. Ordinarily compiled in-line.
But could also be done in Smalltalk as follows"
^self value
ifTrue:
[aBlock value.
self whileTrue: aBlock]
Así que acaba de cambiar su de a
BlockContext>>myWhileTrue: aBlock
| start |
start := thisContext pc.
self value ifFalse: [^nil ].
aBlock value.
thisContext pc: start
o ??
BlockContext>>myWhileTrue: aBlock
| start |
start := thisContext pc.
^self value ifTrue:
[aBlock value.
thisContext pc: start]
Pero, por desgracia ambos accidente de la máquina virtual en algún momento después de la segunda iteración debido thisContext pc no responde a la PC en la siguiente iteración, sino que cualquiera que sea la parte superior de la pila es :)
Sin embargo, el Cómo funciona el siguiente:
ContextPart methods for controlling
label
^{ pc. stackp }
goto: aLabel
"N.B. we *must* answer label so that the
top of stack is aLabel as it is when we send label"
pc := aLabel at: 1.
self stackp: (aLabel at: 2).
^aLabel
BlockContext>>myWhileTrue: aBlock
| label |
label := thisContext label.
self value ifFalse: [^nil].
aBlock value.
thisContext goto: label
BlockClosure>>myWhileTrue: aBlock
| label |
label := thisContext label.
^self value ifTrue:
[aBlock value.
thisContext goto: label]
propongo la siguiente solución:
BlockContext>>myWhileTrue: aBlock
| start |
start := thisContext pc.
self value ifFalse: [^self ].
aBlock value.
thisContext pc: start
En lugar de utilizar la recursividad y trucos de compilación, el código anterior utiliza la reflexión sobre la pila de ejecución. Antes de que comience el ciclo, el método almacena el contador del programa actual en una variable temporal y lo restablece al final para volver al principio del método. En algunas implementaciones de Smalltalk, este enfoque puede ser lento, ya que algunos dialectos de Smalltalk reifican la pila bajo demanda solamente, pero en Pharo/Squeak este truco es bastante practicable.
Nota: el código anterior no responde al resultado de la última activación de bloque ya que la implementación original de #whileTrue: does. Sin embargo, debería ser fácil solucionarlo.
También podría usar un manejador de excepciones para que vuelva al principio, pero eso podría contar como hacer trampa si el código de manejo de excepciones usó un whileTrue: u otro constructo de bucle en alguna parte. Entonces, básicamente, la pregunta se reduce a si puedes implementar un ciclo sin goto o recursión, y creo que la respuesta es no. Por lo tanto, si la recursión está prohibida, se trata de improvisar un conjunto de técnicas como establecer el método de PC o usar una excepción.
Just do:
BlockClousure >> whileTrue: unBloque
valor propio if True: [ aBlock value. thisContext restart. "restart on pharo, reset on VW"]
- 1. ¿Hay alguna forma nativa en ASP.NET para hacer un "mensaje de éxito"?
- 2. ¿hay alguna forma de forzar la copia? copiar sin un mensaje de sobrescritura, usando Windows?
- 3. ¿Hay alguna manera rápida de, al depurar, detenerse en un mensaje o API específico de Windows?
- 4. Espere un solo mensaje RabbitMQ con un tiempo de espera
- 5. ¿Hay alguna forma de detectar un lenguaje RTL en Java?
- 6. CS1061: Compilación mensaje de error
- 7. forma más eficiente para definir Socket.io on ("mensaje")
- 8. ¿Hay alguna forma de obtener la dirección IP de origen de un mensaje JMS?
- 9. ¿Cómo puedo definir un origen de mensaje personalizado para un flujo de web de primavera?
- 10. ¿Hay alguna manera de definir un valor constante para Java en tiempo de compilación
- 11. Cuerpo del mensaje en un mensaje 404
- 12. ¿Hay alguna forma portátil de imprimir un mensaje desde el preprocesador C?
- 13. Espera de forma sincrónica para el mensaje en Web-Worker
- 14. Rieles: ¿hay alguna forma de actualizar un solo atributo?
- 15. Enviar o publicar un mensaje en un bucle de mensaje de Windows Forms
- 16. Gmail IMAP: ¿Hay alguna forma de encontrar todas las etiquetas (carpetas) en las que se encuentra un mensaje en particular?
- 17. En bash, ¿hay un equivalente de morir "mensaje de error"
- 18. Cambiar mensaje de error MSBUILD lenguaje
- 19. Python - Threading y un while True Loop
- 20. while (true) frente a (;;)
- 21. ¿Hay alguna forma de multirreproducir un SqlDataReader?
- 22. ¿Hay alguna forma de usar estilos en línea para definir un estilo de enlace visitado?
- 23. ¿Hay alguna forma de obtener el SHA de una confirmación a partir de su mensaje?
- 24. PHP - Función de validación para devolver true | false, Y un mensaje si es falso
- 25. ¿Cómo enviar un mensaje sin un destino específico en MPI?
- 26. cómo mostrar solo un mensaje para múltiples RequiredFieldValidators?
- 27. ¿Por qué hay un mensaje separado para WM_ERASEBKGND
- 28. ¿Hay un mensaje SetText para el control Win32 ListBox?
- 29. Detectando el estado de ánimo de un tweet o mensaje
- 30. ¿Hay alguna forma de instanciar un NSManagedObject sin insertarlo?
Siempre es una ayuda, gracias Lukas :) –
En este caso, restaurar el contexto es básicamente el equivalente a GOTO –
sin recursión infinita, sin un número infinito de declaraciones y sin la capacidad de reanudar un contexto parece ser imposible. –