2011-10-14 8 views
5

Ciao ragazzi: Mi stavo chiedendo se qualcuno fosse a conoscenza di un esempio concreto di un DSL in Clojure che sostituisce l'astrazione e la leggibilità di un buon programma OO (scritto, per esempio, Java).DSL in Clojure che sostituisce una soluzione software orientata agli oggetti?

ho cercato di prendere un modello di dati OO (che è "fagiolo" base, con metodi molto astratte che nascondono sottostanti implementazioni) in un moeity clojure ...

so che "macro" e "funzioni di ordine superiore" esistono, tuttavia, non li ho mai visti applicati a un set di dati del mondo reale che è facilmente comprensibile (ad esempio un sistema di registrazione del corso, o un concessionario di auto, o un sistema di fatturazione, o qualcosa del genere , ricorda i famigerati esempi di "JPetStore" che Hibernate e Ibatis hanno reso popolari nell'ultimo decennio).

ogni modo ... La mia domanda fondamentale è:

esistono eventuali modelli specifici del dominio per imparare a modellare i sistemi del mondo reale in Clojure con i protocolli e le funzioni di ordine superiore?

risposta

1

Non so se questo è quello che stai cercando ma ho letto un libro su Clojure (Programmazione Clojure; Programmatori pragmatici) che contiene un esempio di una bella piccola DSL. È possibile trovare il codice a https://github.com/stuarthalloway/lancet. Fondamentalmente la lancetta è qualcosa come rendere o ant ma implementato come Clojure-DSL.

+0

... lancet è un DSL, ma non è proprio un problema del "mondo reale" in quanto la maggior parte dei programmatori non ha mai provato a scrivere un sistema del genere: controlla il buon vecchio 'google: applicazione jpetstore .... – jayunit100

1

OOP è buono nel senso che ci siamo veramente abituati e che mappa i concetti nel mondo reale.

Si può vedere come costruire un sistema di OOP con mappe e metodi multipli (qualcosa di simile a ereditarietà prototipale in JS) nella gioia di clojure, capitolo 9.

sul libro Lisp da Paul Graham mostrano come creare un sistema di oggetti in lisp. Dovrebbe essere facile adattarlo al clojure.

Questo libro spiega anche ampiamente la programmazione "dal basso verso l'alto", ovvero la costruzione di piccoli mattoncini di base e la loro composizione per costruire più costrutti di alto livello.

Anche se si vede il concetto principale in molte applicazioni (come java pet store) è procedurale/fonctionnal e non usa il concetto di oggetti come generalizzazione o incapsulamento estensivo.

Il bean non ha alcun comportamento. I dati senza incapsulamento hanno getter/setter che consentono l'accesso pubblico ad essi. Per quello che ti dà, potresti usare una struct C (in un linguaggio tipizzato) o una mappa in un linguaggio dinamico come il clojure.

Il servizio che funzionano su di essi sono fondamentalmente funzioni. Non hanno stato e prendono dati da parametri (fagioli) o database. Se hai davvero bisogno di intefaccia, hai protocolli in clojure.

Non è così complicato.

Nome vostro fagioli come in JAVA ... Ma li attuare, a mappa clojure o come record

Nome i propri servizi e la loro attuazione come funzioni.

Hai bisogno di fabbriche? Quelle funzioni che richiedono funzioni di configurazione e di ritorno.

Iniezione di necessità? Bene, puoi usare i parametri di funzione.

3

Non ci sono modelli speciali per DSL - basta prendere strumenti disponibili nella lingua e tenta di farlo più comodo e vicino al dominio come possibile. Lisp ti offre solo più strumenti di quelli di altre lingue.

Per esempio concreto di bello look DSL allo ClojureQL. Inizialmente, SQL è stato creato come DSL per i database relazionali. Ed è molto conveniente per lavorare dalla console ... ma non dal linguaggio di programmazione come Java o Clojure. Java è venuto con grandi quadri ORM come Hibernate, e Clojure offre semplici DSL, che è così conveniente come SQL originale, ma funziona in modo completamente come parte del linguaggio:

(select (table :users) (where (= :id 5))) 

cosa comune in Lisp DSL sta usando costrutti come defsomething. Ad esempio, in un libro (mi spiace, non ricordo il suo nome) c'è un esempio di corrispondenza del modello nel testo. L'autore crea un modulo con un numero di elementi di corrispondenza come ? per una parola, + per una o più parole, * per zero o più parole e così via. A questo scopo crea la macro defmatcher che richiede una certa sintassi e aggiunge il gestore per questa sintassi al registro centrale. Questa è solo astrazione: invece di molte ripetute operazioni, introduce una macro singola che dice cosa vuole realmente fare: definire il matcher. Anche questo esempio usa entrambe le macro e le funzioni di alto ordine.

Così, ancora una volta, non c'è niente di speciale in DSL Lisp-based - semplicemente descrivere zona dominio con gli strumenti che hai nella tua lingua, sia Java, Clojure o qualsiasi altra cosa. Basta abituarsi con le strutture linguistiche e vedrai come deve essere.

UPD. Alcuni esempi "mondo reale" in cui DSL Lisp-based sono più convenienti rispetto, ad esempio, OOP:

Domain: auto dillership

(defcar my-cool-car :wheels 4, :doors 2, :color red) ;; in Java you need Factory 
(def car1 (make-car my-cool-car))     ;; and lots of methods to 
                ;; add features to cars and 
                ;; cars to factory 

Domain: il sistema di fatturazione

(transaction    ;; in Java you cannot create wrapping constructs 
    (withdraw account1 100) ;; so you have to use inheritance, annotations, etc. 
    (put account2 100))  ;; which is much more code 

Domain: qualche servizio web, che gestisce richieste di diversi tipi

(defhandler :show-all (fn [params] ...))  ;; adds defined function to the 
(defhandler :find-best (fn [params] ...)) ;; map of :message-type -> function 
... 
(defn handle [message] 
    (let [msg-type (:type message), msg-params (:params message)] 
    (if (contains? *handlers* msg-type) 
     ((*handlers* msg-type) msg-params) 
     (throw (Exception. (concat "No handler for type" (:type message))))))) 

Non c'è cosa speciale su questi esempi: puoi implementarli tutti in Java o in qualsiasi altra lingua. Tuttavia, cose come le parole chiave (1 ° esempio), le funzioni di ordine superiore (2 ° esempio), le macro (tutti e 3 gli esempi) rendono il codice più conciso e descrittivo.