MV Coders on fire

EnZo

#90 Ya que estás podrias contarnos que es lo que no te gusta de Java, que la conversacion está muy interesante :P

2 respuestas
B

#91 yo creo que Java mató a sus padres porque no deja un post sin criticarlo venga o no a cuento.

1 respuesta
EnZo

#92 O, en un principio le gustaba tanto tanto tanto que no podia dejar de programar y se pasaba tantas horas programando que olvidaba que tenia una novia. Pero entonces esta novia le dejó. Cuando despertó del hechizo Javero se dio cuenta de lo que perdió y a raiz de ahí lo odia xD

PD: En cualquier caso seguro que tiene argumentos ricos ricos y con fundamento.

eisenfaust

Porque Java tiró completamente por la borda 30 años de investigación en cuanto a diseño de lenguajes.

Creo que hoy por hoy es de lo más limitado que existe. Tan limitado que tienen que recurrir a hacer magia con IDEs y XML para trampear el sistema y hacer algo medianamente decente.

Está diseñado para grandes empresas donde viene un arquitecto, diseña su abominación y se lo pasa a cientos de programadores novatos de los que cobran cuatro duros (de estos de quita y pon, no se vayan a creer que realmente son imprescindibles para la empresa y pidan un aumento de sueldo) por escribir 500 líneas de código diarias gracias al IDE que no hacen absolutamente nada para que los del equipo de gestión al ver los commits digan "hmmm... qué rápido escribir" y sigan con sus métricas absurdas de rendimiento basadas en LOC.

#81 CL en ese sentido es estricto. Tienes que definir los streams tú mismo.

Desconozco cómo funciona reduce en Scala, pero no me creo que en ese ejemplo use evaluación lazy, porque precisamente en Haskell para hacer eso se aconsejaría el uso de foldl' (forzando evaluación estricta) en lugar de foldl, ya que el resultado de la "reducción" no se evaluaría hasta ser solicitada, consumiendo un stack interno y aumentando el uso de memoria.

Generalmente el uso de este tipo de evaluaciones da problemas de rendimiento y son un quebradero de la cabeza a la hora de optimizar los compiladores.

PUSH es básicamente

(setf *var* (cons 'value *var*))

el beneficio surge a la hora de poder utilizar NREVERSE sobre dicha variable. Eso y que escribes menos xD

#83 http://www.info.ucl.ac.be/pvr/book.html

Y muy especialmente http://www.amazon.com/The-Little-Schemer-4th-Edition/dp/0262560992

2 1 respuesta
elkaoD

#94 gracias. Iba a vomitar exactamente esa parrafada y me la has ahorrado :P

Con respecto a lo del reduce, éste va pidiendo valores al stream según los va necesitando si no me equivoco. Lo que es lazy no es el reduce si no los valores de la lista (del stream en realidad.) El stream es imposible que no sea lazy porque no genera una lista en ningún momento, sólo va escupiendo valores según se le piden.

Ten en cuenta que la evaluación funciona ejecutando (*) cada vez. No se ejecuta el reduce sobre el stream, sino que la función reduce ejecuta el take sobre el stream cuando lo va necesitando.

Además reduceRight usa TCO si no me equivoco por lo que no gastas en stack frames (y creo que no me equivoco porque reduceLeft da stack overflow con N grande y reduceRight no.)

Aún así no es el mejor modo de atacar el problema ni mucho menos, es más eficiente trocear el problema con split que usar streams, pero vamos, se pilla la idea.

EDIT: Comprobado

Stream.range(1,10).map(i => print(i)).reduceLeft((a,b) => print("r"))

Salida:

12r3r4r5r6r7r8r9r

EDIT2: Aún así, pensándolo mejor, un iterador soluciona el problema mejor porque NO GUARDA VALORES ANTERIORES. El stream y la lista son lo mismo prácticamente, el iterador hace closure sobre las variables necesarias para la siguiente ejecución y fin. Si se van a generar varios factoriales es mejor el stream. Para una sóla vez, el iterador. El stream sigue siendo mejor que la lista porque se reutiliza para varias ejecuciones (y sus valores "cacheados".)

#91 a riesgo de que me digan que no viene a cuento:

No puedo hablar de muchas cosas que me gusten de Java y no estén en Scala, casi todo lo que me gusta de Java lo tiene Scala por aquello de que corre en la misma plataforma y su diseñador curró en la JVM desde la... 1.3 creo (así que se quedó con lo mejor) y sobre todo porque son 100% interoperables (puedes crear objetos Scala desde Java y Java desde Scala, no hay distinción.)

De la plataforma creo que nadie se puede quejar: la JVM por ejemplo es una maravilla. Java en sus inicios era... lo que era, pero ahora es sin duda un producto maduro como plataforma y como lenguaje (recordemos que los genéricos no han estado siempre ahí, p.ej.)

Como contraejemplo... ¿anotaciones tan CLAVES como @Override no son parte del lenguaje? ¿WTF? En Scala override es un cualificador de miembros como debería serlo en Java (y ahorraría quebraderos de cabeza.)

Con respecto al lenguaje sí que hay cosas que me gustan más que en Scala. El lenguaje se nota que está pensado para lo que está y cumple su trabajo perfectamente: aunque, como #94 dice, sea vomitar diseños rápidos, es un fin legítimo al fin y al cabo. Lo que se pretende es hacer el trabajo barato, robusto y hacerlo YA.

Java no trata de ser elegante ni de ser conciso ni de ser potente. Java trata de ser robusto como lenguaje y como plataforma y lo cumple con creces. Su mayor baza es a la vez lo que más y menos me gusta de él.

No me quiero imaginar a un puñado de recién licenciados programando en Scala en una gran empresa...

1 respuesta
eisenfaust

#95 Hola, entiendo lo que quieres decir. Por lo que describes el comportamiento es igualito que en Haskell xD

reduceLeft = foldl
reduceRight = foldr
reduce = foldl'

Siendo foldl la "peligrosa" xD

Clojure es similar, lo "bueno" es que incluso funciones como map y filter también devuelven lazy seqs.

Un ejemplo chulo:

user> (def my-stream (map inc (range)))
#'user/my-stream
user> (reduce + (take 1000000 my-stream))
500000500000

Donde RANGE sin parámetros es un stream infinito partiendo de 0.

Los beneficios de todo esto es que siempre trabajas sobre un set de datos ínfimo, ya que como bien dices se crea única y dinámicamente cuando es necesario, y en las llamadas a funciones lazy como MAP o FILTER no estamos dependiendo de una estructura de datos intermedia O(n). Además como comentas con el uso de memoization se puede mejorar el rendimiento.

El gran problema es que implica un aumento del overhead en el uso de memoria por cada elemento a medida que se va realizando. Concretamente en Clojure (y seguramente en Scala sea igual) guardamos por cada elemento dos objetos, uno con la propia computación, y otro con un cons de la computación realizada y un puntero a la siguiente computación.

Siempre vamos a tener algo de overhead (aunque sea por culpa del propio GC) al trabajar con streams, nada es gratis. Lo bueno es que se está logrando que éste con el tiempo sea menor (por ejemplo evaluando por bloques de 32 elementos a la vez en lugar de uno a uno) y al menos en Clojure se terminó implementando INTO para hacer un dump de la secuencia a una estructura de datos como PersistentVector cuando necesitemos máximo rendimiento.

En definitiva, está bien y permite escribir código conciso y elegante reduciendo la complejidad de algoritmos pero dudo que veamos el uso de estas técnicas en clusters, procesamiento gráfico, HFT, etc. en un futuro próximo. Creo que siempre es mejor evaluar tan pronto como sea posible (siempre y cuando sea absolutamente necesario obtener el resultado).

B

¿Cómo va el tema de escoger nuevo kata?

B

Estaría guay hacer un pequeño chat :D

PD: No sé vosotros pero yo estoy ansioso!!!

Animaos! Y sobre todo, la cosa es que venga gente nueva, o sea que los que ya estáis no os echéis atrás.

#99, #100: Pues cuando se ponga en #1 podemos empezar si a todos les parece bien. Estaría bien poner una fecha límite (una semana por ejemplo, para que así no estemos como ahora, que no sabemos cuando empezar la siguiente).

EDIT: #101: Mi idea de chat es hacerlo desde 0. Es decir, servidor y cliente. Yo posiblemente pruebe node.js para esto.

3 3 respuestas
Nucklear

#98 Masuno a lo del chat :)

1 respuesta
Isotoperd

Venga, a la siguiente participo, el tema del chat podría estar bien.

1 respuesta
Nucklear

#98 Si, y se deberia de poner una fecha para entregarlo para que no se vea el codigo antes de tiempo y se tome inspiracion de los demas.

¿El chat sería un chat individual, a traves de IRC o como?

1 respuesta
Khanser

Bueno, nueva semana, nuevo Kata, y dejamos el anterior por finiquitado. La verdad es que estoy más que satisfecho, 8 participantes, 7 tecnologías diferentes.

Así que abrimos votaciones para nuevo Kata.

Éste kata se dará por terminado el día 30, y hasta éste día no se podrá subir código.
El dia 24 a las 23:59 terminarán las votaciones.

El tema del chat estaría interesante, pero molaría más que todos picaramos el mismo netcode con el mismo protocolo al server, o adoptamos una versión sencilla del protocolo de IRC. Además creo que lo podríamos hacer en 2 fases, la creación del servidor y de una api de cliente. Y una segunda fase, que usando las apis de cliente, cada uno se haga los clientes como le de la gana.

Decid también al votar, si votais por el chat, quien está interesado en participar en la creación de la especificación del netcode.

Voto por el chat y yo participaré en la creación de la especificación.

PD:
#98 En #0 puse que los katas se resolverian en 1-2 semanas, fallo mio al no indicar fecha de término.

Todo el que quiera subir código a partir de ahora o se crea una cuenta de gitHub y lo sube a https://github.com/khanser/MVCOF
O me envia MP para ver como lo subimos.
En el repositorio de GitHub crearé una carpeta para la kata que ya diré cual es.

2 respuestas
B

#102: A mí me molaría que hiciésemos un protocolo nuestro (no el IRC). No debería de ser demasiado complicado.

Eso sí, yo voto por no fliparnos. La gracia de esto es que no tengas que estar una tarde entera o dos haciéndolo, si no que te diviertas echándole unos minutitos. Con no fliparnos me refiero a que si contemplamos temas como OPs de canal, registro persistente, varios canales... quieras que no algo se complica.

Lo suyo sería desarrollar una interfaz con el servidor muy sencilla:

· Entrar con un nick (si no está ocupado)
· Poner mensajes
· Leer mensajes
· Como mucho registro persistente o canales

2 respuestas
EnZo

Me mola la idea del chat. Lo mismo participo ya que tengo el core del servidor hecho en php y no me llevaria mucho mucho tiempo.

#103 Mejor no fliparse no, xD me parece bien tu especificacion. Incluso quitaría los registros persistentes. Por que ya te metes en base de datos...
Canales... complica un poco pero un chat sin canales...

Mensajes privados tambien?

Y como dice #102 lo haria en 2 katas. Server primero y luego client.

1 respuesta
Khanser

#103 Pues para evitar overheads enviando xml's podemos enviar texto plano via TCP.
Propuesta:

Para las operaciones que has puesto, que se envíe 1 carácter inicial para indicarlo, y seguidamente el valor del parámetro.

Operaciones

  • Operación enter Entra con el nick especificado. carácter: E parámetro: Nick alfanumérico

  • Operación post Postea un texto en el chat. carácter: P parámetro: Texto alfanumérico

  • Operación read Lee los mensajes que se enviaron en el chat desde el timestamp indicado. carácter: R parámetro: timestamp

  • Operación list Lista los usuarios conectados en ese momento carácter: L parámetro: -sin parámetro-

  • Operación exit Sale del chat. carácter: X parámetro: -sin parámetro-

Ejemplos de peticiones en una sesión típica:
EKhanser
L
PQue pasa perras!!!
L
L
PPor qué no contesta nadie?
PAh vale, seré tonto...
R0
PJoder
R1335178416
L
PBah, que os den
X

Respuesta:
De ir todo bien devuelve O, si hubo algún error devolverá E seguidamente de un número de error. Los mensajes de error ya los definiremos cuando acabemos de especificar las operaciones

2 respuestas
B

#104, #105: Si os parece bien (a vosotros y a los demás), podemos hacer lo básico como digo y, si vemos que todos o la mayoría vamos sobrados, pues le metemos el tema de privados y canales.

#105: Veo bien una especificación de ese tipo, sencilla y efectiva.

De todas formas los códigos de errores tampoco serían muchos:

· Nick en uso.
· Operación no permitida (todas las demás si no estás registrado con un nick :P).

La gracia, btw, sería que todos los servidores y clientes puedan interconectarse. Así que ceñíos a la explicación!

3 respuestas
Khanser

#106

También haría falta un mensaje de error del palo "CAPULLO DEJA DE SPAMEAR OPS!" :)

#108 El contexto de la E en la respuesta no es el mismo contexto de la E en la entrada. Otra cosa es que te guste mas "join" XD

1 respuesta
EnZo

#105 Enter y Error usan los dos la E. Cambiamos Enter por J (Join)?

#106 Sip, que cualquier cliente pueda conectar a cualquier servidor.

1 respuesta
EnZo

#107 Yap, aparte de que me gusta mas xD. Si usamos las E para ambos habria que restringir el tipo de nick a ponerse. Si yo me pongo de nick "10" y tambien tenemos un error con numero 10.
No sabremos interpretar si se refiere a un error o a la entrada de alguien.

1 respuesta
Khanser

#109

El E10 que reciba el server será el comando de que entra el usuario en cuestión
El E10 que reciba el cliente será el error 10.

Tu al server no le puedes enviar como cliente un error y el servidor no te va a enviar comandos de operaciones a ti (a no ser que queramos hacerlo así) Por eso da igual que E de enter y E de exit tengan la misma E, porque E de enter es una operación en el contexto de petición cliente -> servidor, y E de error es una respuesta en el contexto servidor -> cliente.

1 respuesta
EnZo

#110 Ah vale. Es que daba por hecho que Enter iba a ser tanto de salida (Cuando tu entras) como de entrada (cuando entra un nuevo usuario). Tu no contemplas que el servidor te envie un "EKhanser" ? Por que no?

Así te evitas tener que enviar la lista de los 1000 usuarios que pueden estár conectados. Igual que con el exit. Creo que debe ser tanto de entrada como de salida.

No es optimo refrescar la lista de usuarios conectados cada vez. La descargas una sola vez al entrar/conectar y la vas actualizando con los exists y joins que se produzcan.
El servidor te lo agradecerá.

Khanser

Ya, no es optimo, pero el concepto de observer, eventos y demás, no será familiar para todo el mundo, por eso tenemos un comando L, y por eso el comando R admite un timestamp, porque no saltarán eventos en el servidor hacia los clientes cuando otros entren al canal y envíen mensajes.

Yo no tengo problema en contemplar una 'arquitectura' cliente <-> servidor con eventos de servidor->cliente, pero esto hará que los programadores más novatos se encallen.
Si la propuesta siempre es cliente ->servidor el concepto será sencillo, por eso lo hemos propuesto así, almenos entiendo que #106 también ha pensado así XD

2 respuestas
EnZo

#112 "porque no saltarán eventos en el servidor hacia los clientes cuando otros entren al canal y envíen mensajes."

De que forma recibo yo los mensajes de Pepito que envia al chat, si no es con un evento recibido desde el servidor?

"Si la propuesta siempre es cliente ->servidor el concepto será sencillo"

No puede ser siempre cliente->servidor. El servidor tiene que enviar informacion al cliente de una forma u otra. Simplemente para los mensajes. Cuando yo envio un mensaje el servidor lo tiene que repartir a todos los clientes conectados. De igual forma cuando yo entre tendria que enviar a todos los clientes que he entrado.

1 respuesta
Khanser

#113 No que no solo hay una forma de hacer las cosas. Y en este caso propongo hacer esta porque considero que para una persona que no se haya metido en redes antes, le va a costar más el concepto de los eventos y el de (cliente/servidor) que envia y recibe mensajes del servidor.

La propuesta que estamos contemplando no es un server orientado a eventos sino a encuesta.

Tu le vas preguntando al server, oye, qué mensajes hay nuevos? Nuevos respecto a qué, pues al timestamp que se le pasa. Y el server, te contesta cuando le preguntas.

El cliente, según esta propuesta, será el encargado de decir, por ejemplo "vale, hace ya más de 2 segundos que hice la ultima actualización de mensajes, voy a pedir nuevos... socket.send("R"+new Date().getTime()-2000). Y el servidor te contestará, con una lista de elementos cliente,mensaje,timestamp, y tú como cliente, lo mostrararás por consola, en la ventana, o donde sea.

Lo que estamos diciendo es que un sistema que funciona mediante encuesta es mucho más sencillo tanto de implementar como de pensar para que todo el mundo pueda implementarlo, rápido y sin dolores de cabeza.

EnZo

Si yo mi mente la abro xD pero dudo que sea mas sencillo de programar como tu lo planteas.

[SE] Server Client

Modelo que tu propones:
- [C] User1 Entra -> [SE] recibe entrada y almacena user
- [C] User1 Solicita listado usuarios -> [SE] recibe y envia listado -> [C] Recibe listado
- [C] User2 Entra -> [SE] recibe entrada y almacena user
- [C] User2 Solicita listado usuarios -> [SE] recibe y envia listado -> [C] Recibe listado
- [C] User1 envia msg -> [SE] recibe y almacena msg en memoria
- [C] User2 envia msg -> [SE] recibe y almacena msg en memoria
- [C] User1 actualiza msg -> [SE] recibe y envia msgs-> [C] Recibe msg
- [C] User2 actualiza msg -> [SE] recibe y envia msgs-> [C] Recibe msg
- [C] User1 sale -> [SE] recibe y almacena
- [C] User2 Solicita listado usuarios -> [SE] recibe y envia listado -> [C] Recibe listado



Modelo propongo:
- [C] User1 Entra -> [SE] recibe entrada y almacena user -> [C] informa a clientes conectados
- [C] User1 Solicita listado usuarios -> [SE] recibe y envia listado -> [C] Recibe listado
- [C] User2 Entra -> [SE] recibe entrada y almacena user -> [C] informa a clientes conectados
- [C] User2 Solicita listado usuarios -> [SE] recibe y envia listado -> [C] Recibe listado
- [C] User1 envia msg -> [SE] recibe y NO almacena msg en memoria -> [C] informa a clientes conectados
- [C] User2 envia msg -> [SE] recibe y NO almacena msg en memoria -> [C] informa a clientes conectados
- [C] User1 sale -> [SE] recibe y almacena -> [C] informa a clientes conectados

B

#112: La verdad es que no había reflexionado sobre el tema pero reconozco que estoy más con Enzo :P

Es decir, con lo de leer mensajes me refiero al caso de uso, no a que haya una operación de leer mensajes.

A ver si los demás se pasan por aquí y nos dicen qué opinan.

La cosa quedaría algo así como:

Cliente a servidor
Servidor a cliente

Posiblemente se me escape algo, pero vamos. Esta es mi idea más o menos.

PD: Si queréis utilizar canales entonces hay que cambiar un poco las llamadas. Pero vamos yo creo que para empezar esto está bien. Hacemos servidor y cliente y, si nos quedamos con ganas de más, hacemos otra iteración añadiciendo funcionalidades.

1 respuesta
elkaoD

A mí como simple me parece más la opción de Enzo, pero tampoco complica mucho más hacerlo como dice Khanser (es tener un buffer de X minutos o X mensajes max y fin.)

Lo primero es chat en directo y lo segundo más en plan tablón de anuncios.

Yo de hecho creo que lo mejor sería ambos para la kata: chat en directo sin que haya que preguntar, pero también que te de la posibilidad de recuperar mensajes de hace X minutos.

EnZo

En cuanto a dificultad diria que están a la par. En ambos el servidor tiene que enviar y recibir de una forma u otra. Solo los diferencia la forma de encauzar las instrucciones.

Lo que si que creo es que el cliente se complica. Por que tienes que estar controlando tiempos para actualizar datos haciendo mas peticiones. Cuando recibes el listado de mensajes, debes comprobar cual se ha recibido ya y cual no.

Y lo peor no es eso, si no que gastas muchisimo mas de ancho de banda. Y memoria, ya que tienes que ir almacenando mensajes para luego servirlos.

De todas formas no es algo que haya inventado yo. El protocolo IRC funciona mas o menos así. Entre todos podemos reinventar la rueda :P

Nucklear

¿Y para los que no tenemos mucha idea nos podeis recomendar alguna documentación?

1 respuesta
Khanser

#119 A ti que te mola Python: http://luauf.com/2008/04/14/servervidor-y-cliente-tcp-en-python/

#115 #116 De ser por mí lo haría de esa manera, solo estoy diciendo que el concepto de que el cliente es cliente y servidor(para recibir mensajes asíncronos del server) sin contar que para la recepción asíncrona hay que meter Sincronización de procesos por en medio, para un novato le supondrá más esfuerzo mental, no estoy metiendo cuestiones técnicas por en medio en mi propuesta, coñe.

BTW #115 #116 #117 No entiendo como podeis ver igual de sencillo hacer un cliente que recibe asincronamente información del server, que hacer envio/recepción simple por polling. En el primero aparecen problemas de sincronización de datos en cliente y paralelismo que un novato no va a saber resolver porque para eso primero tiene que conocerse un mínimo de teoria y según tengo entendido, programadores que salgan de modulo o módulo superior, o no han visto esto, o lo han visto muuuuy por encima. Y si recordais, el propósito de esto es que participen tanto pr0s como n00bs. Pero para vosotros la perra gorda XD

1 4 respuestas