Esta discussão foi arquivada. Não se pode acrescentar nenhum comentário. | | | Pareceu-me interessante a nível académico, mas para utilização profissional é mais duvidoso (comparado por exemplo com o PHP) uma vez que o Steam (o engine ) custa a módica quantia de $5000 por CPU. |
| | | | Sinceramente, começo a estar farto desta onda de scripting languages. Tem andado a faltar um conceito básico que uma qualquer nova linguagem de programação que queira inovar em vez de retroceder no tempo tem de implementar e que parece estar esquecido no tempo: Strong Type Checking. O C++ (retirando compatibilidade C) é a única linguagem que neste aspecto é totalmente coerente. Type Checking é fundamental, é algo que está claramente definido por Bjarne Stroustrup desde a sua concepção original, o conceito permeia toda a sua sintaxe e definição. Com isto ganhamos algo, ganhamos o poder de o compilador nos indicar que estamos realmente a usar uma linguagem onde quando nós declaramos algo é para ser assim e não assado, é uma definição, não um "suponhamos". Object Types são o contrato base feito pelo programador para com as suas formas de uso. Period. O Java assumiu-se como uma bela salada mista, maus apis, boas estruturas de object oriented, mas infelizmente abusa do "Object" para tudo e para nada e depois é o "cast party" do dia a dia... enfim, pelo menos no novo JDK 1.5 parecem querer redimir os erros do passdo, vejam só isto; Generic Containers (Uiiii! Século 21!)... :-] Voltando ao Water, só o facto de querer encafuar uma sintaxe de programação no limitado espectro do XML é já por si algo que me repugna (ok, ok, estou a ser falacioso, permitam-me!) de facto, não concordo com o abuso do XML que se tem verificado nos últimos tempos, o que é um excelente formato de representação de dados tem vindo a tornar-se como que a panaceia para todos os males da informática. É como se alguém inventasse a roda e milénios mais tarde nunca surgisse o HoverCraft porque não é assim a forma de fazer as coisas! |
| | | | | O C++ (retirando compatibilidade C) é a única linguagem que neste aspecto é totalmente coerente. Não te estás a esquecer do Ada? Pode ser velhinha mas já tinha isso tudo... |
| | | | | Haskell? What an hell!
Dominus vobiscum
"I may have invented control-alt-delete, but Bill Gates made it really famous", David Bradley, IBM Engineer |
| | | | "Tem andado a faltar um conceito básico que uma qualquer nova linguagem de programação que queira inovar em vez de retroceder no tempo tem de implementar e que parece estar esquecido no tempo: Strong Type Checking."
Tenho que discordar da sua opinião de que "verificação dos tipos" em compile time seja o futuro.
Duas regras empiricas inicias: 1 - a lei de moore (mais que conhecida). 2 - 90% do tempo de processamento é consumido em 10% do codigo. As linguagens com o type checking feito em compile time, essencialmente, obrigam a optimizar todo um programa, visto ser necessario declarar todos os tipos das variaveis. Algumas das novas linguagens que fazem verificação de tipos em compile time, usam inferencia de tipos para que o programador escreva menos. O tempo do programador é mais valioso que o tempo da máquina e as duas regras iniciais mostram que se deve libertar cada vez mais o programador de detalhes irrelevantes, nao o obrigando a efectuar tarefas que podem ser facilmente executadas pela maquina.
O que as linguagens como a 'water' e muitas outras defendem (python, agora muito na berra), é que dynamic type checking liberta o programador de "lutar contra o compilador" (casts automaticos, conversao de objectos em 'containers genericos...).
Eu tambem concordo que é uma boa propriedade detectar erros o mais cedo possível, mas nao à custa de horas de esforço do programador. As linguagens que usam dynamic type checking normalmente têm um ciclo de desenvolvimento bastante mais rapido do que as que o fazem em compile time, permitindo testar as funções que se vão criando através de um interpretador. As novas tecnicas "ageis" para gestao de projectos (extreme programming e afins) ate aconselham o que agora chamam 'unit testing'.
Para alem disso, a declaração de todos os tipos das variaveis, compromentem a longo prazo a manutenção e evolução de um programa (outra regra empirica: 90% do tempo do desenvolvimento de um programa está na manutenção).
A linguagem C++ ainda tem os templates que permitiriam resolver os problemas dos containers genericos (e outros semelhantes), se não fossem tao dificeis de usar.
Quanto ao XML e À sintaxe da linguagem, só mostra que é este (o XML) é uma reinvenção pobre das sexpressions (inventadas em 1959) que quem ja viu codigo lisp saberá o que é (muitos parentesis, anyone?); é mais complexo que as sexpressions e muito mais dificil de fazer parsing. Apesar de admitir que começar a programar com muitos parentesis numa notação infixa seja complicado (desde cedo somos habituados à notação prefixa da matematica), depois de habituados as vantagens tornam-se evidentes (pelo menos nao é preciso decorar as prioridades dos operadores nem onde se põe o ';' - sim já sei, agora os IDEs verificam isso tudo ;). |
| | | | Concordo em parte, de facto é mais rápido programar numa linguagem mais aberta em relação ao Type Checking, é mais fácil fazer protótipos e Unit Testing sem dúvida, mas isto não quer dizer que tenhamos de perder poderosas noções básicas que ao ser aplicadas de forma consistente produzem melhores resultados, e tal só é possível se o compilador reforçar o uso dessas medidas. Principalmente na área de Refactoring ter Type Checking é fundamental. Não estou a contemplar uma ferramenta de desenvolvimento ser flexível o suficiente para fazer o seu trabalho de re-estruturação profunda de código se para tal os seus alicerces de análise forem baseados em estruturas de dados dinâmicas na qual os tipo só são conhecidos em run-time... Podemos argumentar que qualquer programador escreve bom código desde que a linguagem tenha um mínimo de funcionalidade OOP, mas isto é trazer a resolução de um problema do domínio da arquitectura de software para o domínio da natureza humana, e apesar da máquina existir para servir o homem, essa ajuda depende do reforço positivo por parte da máquina na resolução do que o homem propôs-se a resolver quando criou a máquina!
|
| | | | "...mas isto não quer dizer que tenhamos de perder poderosas noções básicas que ao ser aplicadas de forma consistente produzem melhores resultados,..."
O que eu argumentei no post anterior foi que, não é evidente que o 'static type checking' produza melhores resultados a longo prazo (perda de eficiencia do _programador_ traduzidos por dificuldades grandes de manutenção).
A refactorização opera _apenas_ sobre o 'texto' de um programa e portanto, nao ha ferramentas que se baseiem nos tipos de dados das estruturas em runtime. O que é fundamental é verificar que o programa se comporta exactamente da mesma forma, antes e depois de transformado. Era bom que as modificações garantissem com certeza absoluta que o comportamento do programa sem mantem em _todos_ os casos, mas a verificação semantica de um programa nao é trivial em _nenhuma_ linguagem (inclusivé as que usam static type checking). Aqui entra outra vez o conceito de Unit Testing, fundamental para garantir que as transformações semi-automaticas produzidas têm o mesmo comportamento a nível global no programa.
Quando às "funcionalidades OOP" e o static type checking, desafio-o a estudar o seguinte problema e a perceber porque é que nao funciona e se deveria ou não funcionar: #include class Media {}; class Ecra: public Media {}; class Printer: public Media {}; class Figura { public: virtual void draw(Ecra *med) = 0; virtual void draw(Printer *med) = 0; }; class Quadrado: public Figura { public: virtual void draw(Ecra *ecra) { printf("Desenhei um Quadrado num ecra\n"); } virtual void draw(Printer *prt) { printf("Desenhei um Quadrado numa impressora\n"); } }; class Triangulo: public Figura { public: virtual void draw(Ecra *ecran) { printf("Desenhei um Triangulo num ecra\n"); } virtual void draw(Printer *prt) { printf("Desenhei um Triangulo numa impressora\n"); } }; int main() { Ecra *ecra1 = new Ecra(); Figura *fig1 = new Quadrado(); fig1->draw(ecra1); // funciona.. optimo Media *med1 = new Ecra(); fig1->draw(med1); // porque e' que isto nao funciona? return 0; } |
| | | | Isso é um mau exemplo de má prática de POO, não me parece um bom exemplo para sustentar a tua opinião contra o rigor dos compiladores e dos tipos. É natural o compilador dar erro naquela linha, se tu tens um método que recebe um ecrã, e outro que recebe uma Printer, então não sabes o que fazer se receberes outro tipo de Media. É claro que nesse caso tás a passar um Ecrã, que supostamente a class devia conhecer. Mas então chamas o método adquado, pois nada impediria de ser passada uma outra Media qualquer. Nesse caso só devias era ter um método na class Figura a receber um Media, e pronto, recebia qualquer coisa e era transparente, e não precisava de saber para onde tava a "pintar", desde que a class Media tivesse os mecanismos próprios para o fazer. É esse o uso do polimorfismo... Se usas uma ferramenta de forma errada é natural teres problemas adicionais. :-) _____________________ Pedro Santos :: psantos.net :: blog |
| | | | É claro que nesse caso tás a passar um Ecrã, que supostamente a class devia conhecer. Mas então chamas o método adquado, pois nada impediria de ser passada uma outra Media qualquer. Se tiveres uma lista de Figuras, como é que resolves o problema? Nesse caso só devias era ter um método na class Figura a receber um Media, e pronto, recebia qualquer coisa e era transparente, e não precisava de saber para onde tava a "pintar", desde que a class Media tivesse os mecanismos próprios para o fazer. Assim realmente resolves este caso... agora sugiro-te que adiciones uma classe 'Cor' e o respectivo argumento ao metodo draw. Com a tua forma de resolver o problema, vamos ter: 1 - um metodo por classe Figura. 2 - dois metodos por cada classe Media (para especificar se queres desenhar um quadrado ou um circulo, isto se percebi a forma que escolheste para resolver o problema). 3 - quatro metodos por cada classe Cor (a cor 'azul', por exemplo, tem que conhecer que medias e que figuras existem). Sugiro que tentes perceber a explosão combinatoria de metodos, por cada argumento e nova classe que adicionas ao metodo draw. Ou entao mostra-me que estou enganado e que há uma forma de resolver o problema inicial (o meu "problema adicional devido a ter usado a ferramenta de forma errada"). :-)
|
| | | | 1) A Cor não tem de saber as Medias q existem nem as Figuras que existem. 2) As Figuras não têm de saber que Medias existem. Figura::draw(Media* aMedia) { //figura executa um método virtual qualquer da //classe Media que é implementado pelas sub-classes } static Cor::draw(Figura* aFigura) { //Cor executa um método virtual qualquer da classe Figura //que é implementado pelas sub-classes } static int main(void) { Cor::draw((new Quadrado())->draw(new Printer())); } Jamais a cor tem de saber que executa o draw de um Quadrado e o Quadrado que está a ser desenhado para uma Printer.
--- Conformity is the jailer of freedom and the enemy of growth. --John F. Kennedy |
| | | | Obviamente que nao percebeste o problema. O que me estás a dizer é que as cores,figuras e medias sabem imprimir-se a si proprias, mas nao era esse o problema inicial.
Dado que a fraca de especificação do problema é provavelmente culpa minha, vou clarificar.
O problema inicial consistia em, dada uma figura, imprimi-la num media. Tu resolveste o problema (noutro post), fazendo com que o media se imprima a si proprio (?) e a figura a si propria tambem.
A forma correcta de resolver o problema seria algo como: class Media { public: virtual void drawQuadrado()=0; virtual void drawTriangulo() =0; }; class Ecra: public Media { public: virtual void drawQuadrado() { printf("desenhei um quadrado num ecra."); } virtual void drawTriangulo() { printf("desenhei um triangulo num ecra."); } }; class Printer: public Media { public: virtual void drawQuadrado() { printf("desenhei um quadrado numa printer."); } virtual void drawTriangulo() { printf("desenhei um triangulo numa preinter."); } }; class Figura { public: virtual void draw(Media *med) = 0; }; class Quadrado: public Figura { public: virtual void draw(Media *med) { med->drawQuadrado(); } }; class Triangulo: public Figura { public: virtual void draw(Media *med) { med->drawTriangulo(); } };
Repare-se que os media têm que saber como se imprime um quadrado e um triangulo, eles nao se imprimem a si proprios(os printfs eram ilustrativos!!! o problema nao é imprimir pro terminal a frase certa;).
Para ver que isto implica uma explosão combinatoria de metodos, sugeri adicionar uma classe cor (um novo argumento no metodo draw) e ver quantos metodos sao precisos por cada classe (volto a repetir, as cores nao se imprimem a si proprias,etc...).
Ainda ha alguma duvida sobre o problema a resolver? |
| | | | Pah, não estás bem a ver a coisa. Como desenháste essas classes, sempre que quisésses agora permitir à Media desenhar uma figura nova, tinhas de fazer isso? Na Media? Repare-se que os media têm que saber como se imprime um quadrado e um triangulo, eles nao se imprimem a si proprios(os printfs eram ilustrativos!!! o problema nao é imprimir pro terminal a frase certa;). Muito pelo contrário! Não têm! Os quadrados é que têm de saber a forma de se imprimirem numa Media, desde que a Media tenha uma interface que o permita. A função da Media é permitir que outros a usem para se imprimir, a Printer não tem de saber todos os objectos que existem no mundo, nem podia. São os objectos que se querem imprimir na Media que têm de fazer por isso. Para ver que isto implica uma explosão combinatoria de metodos(...) Pois, o mau design leva a isso. Não é à toa que qualquer um programa, e outros UMLizam. _____________________ Pedro Santos :: psantos.net :: blog |
| | | | Onde eu queria chegar, é que aquele codigo funciona com dynamic type checking e multi-metodos, precisamente com o desenho inicial. O problema do "mau design" é uma limitação da linguagem.
ver CLOS e derivados (Dylan e penso que ha outras...) para observar dynamic type checking e multi-metodos em acção.
Cumprimentos |
| | | | Permite-me discordar: numa linguagem OOP problemas desses são problemas *graves* de design/implementação. Aqui me confesso, sou um bocado paranóico e control-freak portanto gosto de meter o compilador a verificar exactamente o que quero e ter o código a executar exactamente o que lhe peço. Nem mais nem menos... deixar a cargo do JIT Compiler (ou o que lhe quiseres chamar) descobrir quais são as instrucções que deve executar no ambiente actual é coisa que não me agrada porque se dá buraco é um piço para tentar replicar o problema tantas que são as variáveis para aquilo acontecer (não é bem assim mas pronto, é o FUD :P).
--- Conformity is the jailer of freedom and the enemy of growth. --John F. Kennedy |
| | | | O problema do "mau design" é uma limitação da linguagem. Não, é uma limitação do programador. Agora as linguagens é que permitem o bom design? Tu dizes que como fizeste funciona nessas linguagens, mas o que fizeste é um exemplo de mau design, como eu o o cliff te temos tentado dizer. Ou seja, as facilidades inerentes nessas linguagens ainda permitem pior programação. _____________________ Pedro Santos :: psantos.net :: blog |
| | | | Não, é uma limitação do programador.Agora as linguagens é que permitem o bom design? Parece-me obvio que a tecnologia que se usa, limita o design. Afirmarem que aquele programa tem um mau design à luz da tipificação estática era precisamente onde queria chegar (se bem se lembram, estava a tentar demonstrar que as "linguagens dinamicas" tinham os seus meritos e que a tipificação estática podia nao ser tao boa quanto isso). Mas a realidade é que à luz da POO, pretende-se que as hierarquias de classes evoluam independentemente (a evolução do programa a longo prazo é um objectivo a ter em conta). Naquele exemplo, as hierarquias de classes dos Media e Figuras nao evoluem independentemente... é mau design meu? Ora vejamos...
Numa linguagem tipo water (no caso concreto, Common Lisp - espero que percebam a sintaxe, nao é assim tao complicada :)
(defclass media () ; classe Media ())
(defclass ecra (media) ; classe ecra, subclass de media ())
(defclass printer (media) ())
(defclass figura () ())
(defclass quadrado (figura) ())
(defclass triangulo (figura) ())
temos duas hierarquias de classes independentes, que podem evoluir independentemente uma da outra (optimo)!!
Agora os métodos:
(defmethod draw ((med ecra) (fig quadrado)) (print "desenhei um quadrado no ecra"))
(defmethod draw ((med printer) (fig quadrado)) (print "desenhei um quadrado na printer"))
etc...
Isto é um mau design da hierarquia de classes? Nao me parece. O pessoal dos padroes de desenho ate documentou coisas como o 'Bridge' para permitir hierarquias de classes independentes, dado que isto acontece com bastante frequencia.
"No single language can support every style, but a variety of styles can be supported within the framework of a single language. Where this can be done, significant benefits arise from sharing a common type system, a common toolset, and so forth. These technical advantages translate into important practical benefits such as enabling groups with moderately differing needs to share a language rather than having to apply a number of specialized languages." - Bjarne Stroustrup Permitir que se possam usar diferentes estilos, é até defendido pelo criador do C++. É isto que uma linguagem como common Lisp (CLOS - Common Lisp Object System foi a primeira linguagem OO que recebeu um standard) permite precisamente.
1 - Herança múltipla (em java nao ha!) 2 - multi-metodos (exemplificados em cima... em c++ e java ha apenas single dispatch, e é por isso que os exemplos iniciais em C++ nao funcionam) ha ainda coisas mais "exotericas": 3 - metodos que sao especializados para tratar instancias especificas de uma determinada classe (alguem quer tratar o caso especial 'zero'? optimo.. nada de if's, faz-se um novo metodo). 4 - combinação de metodos.
Voces afirma: "ah mas isso nao é preciso para nada". Aconselho-vos a experimentar e a ver os dois lados da "historia". :)
Nao tenho a certeza se a linguagem 'water', suporta tudo isto, mas foi baseada nestes principios (ja em pratica ha largos anos).
Cumprimentos |
| | | | pois, mas pelo que percebo, arriscas-te a ter programadores a usar features quando não são precisas. já em java é o que é, agora imagino abusar os casos especiais... e herança múltipla... ugh... --- Trolls, nem respondam porque não vos ouço. Que Bush vos abençoe. |
| | | | 0 dúvidas :) prometo que não envio mais código para aqui, se quiseres continuar a discussão podemos fazê-lo por email. Visita o website no perfil. Este bocado de código ilustra o que julgo que pretendes resolver: um media desenha um gráfico. Nem o gráfico tem de saber o tipo de media específico, nem o media tem de saber qual é o gráfico específico. Só tens de achar o ponto comum: /* Exemplo muito básico que só aceita 4 coordenadas */ typedef struct { int iX; int iY; int iX2; int iY2; } Area; typedef struct { int iRed; int iGreen; int iBlue; } Colour; class Graphic { protected: Area iArea; Colour iColour; protected: //já não me lembro se isto funciona bem assim... Graphic(const Area& aArea,const Colour& aColour) : iArea(aArea),iColour(aColour) {} public: inline Area getArea() const { return iArea; } inline Colour getColour() const { return iColour; } } class Square { public: Square(const Area& aArea,const Colour& aColour) : Graphic(aArea,aColour) {} } class Media { public: virtual void drawGraphics(Graphic* aGraph) = 0; }; class Printer : public Media { public: void drawGraphics(Graphic* aGraph) { //algures arranjas maneira de inicializar //a impressora printer->plot(aGraph->getArea().iX, aGraph->getArea().iY, aGraph->getArea().iX2, aGraph->getArea().iY2, aGraph->getColour()); } }; class Screen : public Media { public: void drawGraphics(Graphic* aGraph) { //algures arranjas maneira de inicializar //a impressora screen->draw( aGraph->getArea().iX, aGraph->getArea().iY, aGraph->getArea().iX2, aGraph->getArea().iY2, aGraph->getColour()); } }; public MainClass { public: static int main(void) { Area area; area.iX=10; area.iY=10; area.iX2=20; area.iY2=20; Colour colour; colour.iRed=0xFF; colour.iGreen=0xFF; colour.iBlue=0xFF; //isto imprime um objecto no Media que é uma impressora (new Printer())->drawGraphics(new Square(area,colour)); //isto imprime o mesmo objecto mas no Media que é um ecrã (new Screen())->drawGraphics(new Square(area,colour)); return 0; } }
Disclaimer: Não garanto que isto funcione :P Peço desculpa por entulhar esta thread com código.
--- Conformity is the jailer of freedom and the enemy of growth. --John F. Kennedy |
| | | | olha lá, não é assim que está feito o swing? podia ver, mas sou preguiçoso :P --- Trolls, nem respondam porque não vos ouço. Que Bush vos abençoe. |
| | | | Pegando no teu pedaço de código, a correcção: class Media { public: virtual void draw() = 0; }; class Ecra: public Media { public: void draw() { printf("Ecra\n"); } }; class Printer: public Media { public: void draw() { printf("Printer\n"); } }; class Figura { public: virtual void draw(Media *med) = 0; }; class Quadrado: public Figura { public: void draw(Media *media) { printf("Desenhei um Quadrado num "); media->draw(); } }; class Triangulo: public Figura { public: void draw(Media *media) { printf("Desenhei um Triangulo num "); media->draw(); } };
static int main() { Ecra *ecra1 = new Ecra(); Figura *fig1 = new Quadrado(); fig1->draw(ecra1); // funciona.. optimo Media *med1 = new Ecra(); fig1->draw(med1); // porque e' que isto nao funciona? //passou a funcionar ou q? ;-) return 0; }
Podes argumentar que este exemplo é bastante básico, mas nesta altura do campeonato já deves saber que o Media::Draw deveria receber parâmetros que indicam as coordenadas, as dimensões, o tipo de preenchimento da área etc etc etc.
--- Conformity is the jailer of freedom and the enemy of growth. --John F. Kennedy |
| | | | Subscrevo esta solução totalmente. Isto demonstra o porquê do OOP e Type Cheking, vejamos: No enunciado original: class Figura { public: virtual void draw(Ecra *med) = 0; virtual void draw(Printer *med) = 0; }; Isto é um mau exemplo de design; com este interface se quiser acrescentar outro Media teria necessariamente de quebrar o interface existente por cada vez que o fizesse (péssimo) além disso isto indica que uma Figura concreta tem de saber necessariamente pormenores de implementação de output para um Media (!), o que potencialmente iria requerer que se eu quiser desenhar outro conteúdo para um Media, digamos Texto então isto iria implicar duplicação de código de baixo-nível implementando pormenores respeitantes quer ao Ecra quer ao Printer nas novas classes concretas. class Texto { public: virtual void draw(Ecra *med) = 0; virtual void draw(Printer *med) = 0; }; Ou seja, onde está a abstração aqui? A a solução dada por [Cliff] é simpesmente académica, não há margem para dúvidas. Noutro post acerca de lisp: (...) (defmethod draw ((med ecra) (fig quadrado)) (print "desenhei um quadrado no ecra")) (defmethod draw ((med printer) (fig quadrado)) (print "desenhei um quadrado na printer")) (...) O mesmo problema insiste em permancer; cada destas duas funções têm de conter pormenores de implementação de como preencher um media com um determinado conteúdo! Voltando ao Texto teria de: (defmethod draw ((med ecra) (fig quadrado)) (print "desenhei um quadrado no ecra")) (defmethod draw ((med printer) (fig quadrado)) (print "desenhei um quadrado na printer")) (defclass texto () ()) (defclass texto_simples (texto) ()) (defclass texto_formatado (texto) ()) Até aqui tudo bem, depois... (defmethod draw ((med ecra) (texto texto_simples)) (print "oops tenho de escrever pormenores de implentação do media")) (defmethod draw ((med printer) (texto texto_formatado)) (print "oops tenho de escrever pormenores de implentação do media")) Explosão combinatória é apelido. Na solução correcta em OOP/C++ (deverá ser possível fazer o mesmo em lisp claro) Media é algo genérico, é um conceito não um conjunto ad-hoc de 'function signatures' que por acaso fazem algo de interessante, para demonstrar um interface mais completo seria algo como: class Media { virtual DrawLine(Point p0, Point p1)=0; virtual DrawCircle(Point p0,int radius)=0; virtual DrawVectorImage(VectorImageRaster &v)=0; (...) }; É por isto que argumentei Type Checking como sendo algo de positivo e fundamental. Com este interface quem quiser usar Media sabe que tem disponível um conjunto de funcionalidades que lhe permite desenhar seja o que for que poder ser exposto num plano a duas dimensões, desde figuras a texto formatado passando pelo Rato Mickey... :) |
| | | | epah, a mim convenceste-me, quanto custa? ;) --- Trolls, nem respondam porque não vos ouço. Que Bush vos abençoe. |
| | | | Apesar de admitir que começar a programar com muitos parentesis numa notação infixa seja complicado (desde cedo somos habituados à notação prefixa da matematica), [...] É mais ao contrário (infixa da matemática)... Mas concordo contigo, apesar de levar algum tempo, ao fim de alguma prática torna-se natural o uso de notações prefixas... E até torna as linguagens mais coerentes, já que um simples operador passa a ser uma função... Disclaimer: não fazer posts quando se está sobre a influência do álcool. |
| | | | É preciso ser-se muito masoquista para querer usar uma liguagem com aquela sintaxe... O aspecto daquilo agride os olhos (e o cérebro).
-- Carlos Rodrigues |
| | | | Com o objetivo de criar uma linguagem de fácil compreensão Facil ?!!? Irra.... Em alternativa à obvia (e hoje ainda já mui popular) recomendação de Python para os mesmos fins, ultimamente tenho andado a olhar um bocadinho (pouco...) para REBOL Tem a sua piada usar uma unica linha para receber o Gildot por email... send mvalente@ruido-visual.pt read http://www.gildot.org ... ou um webchecker em pouco mais de 10 linhas ou um webserver em pouco mais de 40... Cumprimentos Mario Valente |
| |
|