2011-01-30 13 views

Respuesta

12

Una cosa fácil de hacer, si tiene la imagen de donde vino el código, se ejecuta un depurador y paso a través.

Si descubrió el código fuera de contexto, como una publicación de la lista de correo, entonces podría examinar los implementadores de uno de los mensajes y ver qué hace. Por ejemplo, #size y #whileTrue son bastante estándar, por lo que los omitiremos por ahora, pero #upTo: suena interesante. Me recuerda a los métodos de transmisión, y mencionar a los implementadores confirma que (en Pharo 1.1.1), ReadStream lo define. No hay ningún comentario sobre el método, pero OmniBrowser muestra una pequeña flecha al lado del nombre del método que indica que está definida en una superclase. Si verificamos la superclase inmediata, PositionableStream, hay un buen comentario de método que explica qué hace el método, que es extraer de la secuencia hasta alcanzar el objeto especificado por el argumento.

Ahora bien, si analizar el código lógicamente, parece que:

  • lee una línea de la corriente (es decir, hasta un cr)
    • si está vacío (tamaño = 0) , el bucle continúa
    • si no lo es, se devuelve

Por lo tanto, el código se salta todas las líneas vacías y los retornos th e primero no vacío. Para confirmar, podríamos pasar una corriente en una cadena de múltiples líneas y ejecutarlo así:

line := nil. 
paragraph := ' 


this is a line of text. 
this is another line 
line number three' readStream. 
[(line := paragraph upTo: Character cr) size = 0] whileTrue. 
line. "Returns 'this is a line of text.'" 
+0

Gracias amigo, su respuesta me ayuda mucho :) por cierto, creo que el código de fijación de workmanlike en el depurador es una poderosa habilidad. caso algún mothod no es muy fácil de depurar, excepto por el método inheritage de String Category, rigth? – parsifal

+0

¡De nada! No estoy seguro de cuál es tu otra pregunta, ¿puedes decirlo de otra manera? –

+0

lea la primera línea no vacía –

-2

Una cosa acerca de Smalltalk que, personalmente, no soy un gran fan de es que, si bien se utiliza el paso de mensajes consistentemente para hacer casi todo, a veces puede ser difícil determinar qué mensaje se envía a qué receptor. Esto se debe a que Smalltalk no tiene ningún delimitador alrededor de los envíos de mensajes (como Objective-C, por ejemplo) y permite encadenar envíos de mensajes a la vez que sigue un conjunto de reglas de precedencia que dicen algo así como "los envíos de mensajes se interpretan de izquierda a derecha". , y a menos que estén delimitados por paréntesis, los mensajes con muchas palabras clave se evalúan primero, luego los mensajes de palabras clave binarias, luego unarios, y luego no los de palabras clave ". Por supuesto, el uso de variables temporales o incluso solo entre paréntesis para que el orden de los mensajes sea explícito puede reducir el número de situaciones en las que debe pensar en este orden de operaciones. Aquí hay un ejemplo del código anterior, dividido en múltiples líneas, usando variables temporales y paréntesis para ordenar mensajes explícitos para facilitar la lectura. Creo que esto es un poco más clara acerca de la intención del código:

line = (self upTo: (Character cr)). 

([((line size) = 0)] whileTrue). 

Así que, básicamente, es la línea de cadena creada al concatenar los personajes en sí cuerda hacia arriba hasta que el carácter de retorno de carro (carácter CR). Luego, verificamos el tamaño de la línea en caracteres, y verificamos si eso es igual a 0, y porque ponemos esto en un bloque (corchetes), podemos enviar un tiempo verdadero, que reevalúa la condición en el bloque hasta que devuelve verdadero . Así que, sí, mientras que True realmente sería más claro si se llamaba DoWhileTrue o algo así.

Espero que ayude.

+1

"[...] reglas de precedencia que van algo así como" los envíos de mensajes se interpretan de izquierda a derecha, ya menos que estén delimitados por paréntesis, los mensajes con muchas palabras clave se evalúan primero, luego los mensajes de palabras clave binarias, luego unario, y luego no palabras clave. "- eso está mal: las reglas son: los mensajes unarios tienen mayor prioridad que los binarios, que tienen una precedencia mayor que los mensajes de palabra clave. Se puede usar el paréntesis para anular ese valor predeterminado. las expresiones pueden ser difíciles de leer, y los paréntesis ocasionales son útiles para enfatizar el orden, incluso si no es estrictamente necesario. – blabla999

+0

Después de algunos años de smalltalk, y algo más de Java, Delphi, Javascript y una docena más, tengo que decir que encuentro que las reglas simples de precedencia de smalltalk son muy superiores y mucho menos propensas a provocar errores. El encadenamiento (en cascada) ayuda mucho en la creación de DSL e interfaces fluidas –

1

esto es más legible:

while(!strlen(line=gets(self))) 

Por encima de expresión tiene un defecto si feof o cualquier otro error, la línea == NULL
También lo ha hecho la expresión Smalltalk, si se encuentra al final del flujo, hasta que lo vaya responder a una colección vacía, y usted tiene un bucle infinito, a menos que tenga una corriente especial que genera un error en el extremo de la corriente ... Prueba

String new readStream upTo: Character cr 
1

Las reglas de precedencia de Smalltalk son
primero: mensajes unarios
segundos: mensajes binarios
tercera: mensajes de palabras clave
última: de izquierda a derecha

Este orden de izquierda a derecha, se puede cambiar mediante el uso de soportes es decir paréntesis(). La expresión dentro del par de corchetes se evalúa primero. Dónde están anidados entre paréntesis, la más interior del soporte es se evalúa primero, y luego trabajar hacia afuera en hacia el soporte exterior, y, finalmente, los restos de la expresión fuera de los corchetes.

Debido a la fuerte tendencia de izquierda a derecha, a menudo me resulta útil leer la expresión de derecha a izquierda.

Así que para [(line := self upTo: Character cr) size = 0] whileTrue.

acercarse a ella desde el extremo posterior al comienzo nos da la siguiente interpretación.

. Fin de la expresión. Equivalente a ; en C o Java

whileTrue ¿Qué hay inmediatamente a la izquierda? ] el cierre de un objeto de bloque.

Así whileTrue es un mensaje unario de ser enviado al bloque [ ... ] es decir, seguir haciendo este bloque, mientras que el bloque se evalúa como verdadera

Un bloque devuelve el resultado de la última expresión evaluada en el bloque .

La última expresión en el bloque es size = 0 una comparación. Y un mensaje binario.

size es generalmente un mensaje único enviado a un receptor. Así que estamos comprobando el size de algo, para ver si es 0. Si algo tiene un size de 0, continúa.

¿Qué es lo que estamos revisando el size de? La expresión inmediatamente a la izquierda del nombre del mensaje. A la izquierda de size es
(line := self upTo: Character cr)

Eso es lo que queremos saber el tamaño de.

Por lo tanto, el momento de poner esta expresión por el quirófano.

(line := self upTo: Character cr) es una tarea.line va a tener el resultado de
self upTo: Character cr asignado a él.

¿Qué hay al final de la derecha de esa expresión? cr Es un mensaje único, por lo que tiene la más alta prioridad. ¿A qué se envía? es decir, ¿cuál es el receptor para el mensaje cr?

Inmediatamente a su izquierda es Character. Por lo tanto, envíe la clase de caracteres al mensaje cr Esto se evalúa como una instancia de clase Character con el valor 13 - es decir, un carácter de retorno de carro.

Así que ahora estamos abajo a self upTo: aCarriageReturn

Si self - el objeto que recibe el mensaje self upTo: aCarriageReturn - no entiende el nombre del mensaje sizeUpto: se lanzará una excepción.

Así que si este es el código de un sistema de trabajo, se puede inferir que self Tiene que haber un objeto que comprende sizeUpTo: En este punto, estoy a menudo la tentación de buscar el nombre de masaje para ver qué clases han llamado el mensaje sizeUpto: en su lista de nombres de mensajes que conocen y entienden (es decir, su mensaje protocolo).

(En este caso, no me sirvió de nada, no es un método en ninguna de las clases de mi sistema Smalltalk).

Parece que se le pide a self que trate una cadena de caracteres que contiene (potencialmente) muchos retornos de carro.

Devuelve la primera parte de aCharacterString, hasta el primer retorno de carro.

Si la longitud de unCharacterString desde el inicio hasta el primer retorno de carro es cero, continúe y vuelva a hacerlo.

Parece ser que estamos tratando con una concatenación de múltiples cadenas terminadas en cr, y procesando cada una por vez hasta que encontremos una que no esté vacía (aparte de su retorno de carro) y la asignemos a line

Cuestiones relacionadas