In quale area la macro di LISP è migliore della "abilità" di Ruby per creare DSL

20

Una delle cose che fa risaltare Ruby è la capacità di creare meglio le lingue specifiche del dominio, come

Anche se è possibile duplicare queste librerie in LISP tramite macro, penso che l'implementazione di Ruby sia più elegante. Nondimeno, penso che ci siano casi in cui la macro di LISP può essere migliore di quella di Ruby, anche se non riuscivo a pensarne una.

Quindi, in quale area la macro di LISP è migliore rispetto alla "capacità" di Ruby di creare DSL, se esiste?

Aggiorna

L'ho chiesto perché i linguaggi di programmazione moderni sono che si avvicinano alla singolarità di LISP , come

  • C ha ottenuto preprocessore di espansione macro , anche se molto primitivo e soggetto a errori
  • C # ha attributi, benché questo sia di sola lettura, esposto attraverso il riflesso
  • Il decoratore aggiunto in Python, che può modificare il comportamento della funzione (e la classe per la v 3.0), sebbene sia abbastanza limitato.
  • Ruby TMTOWTDI che rende elegante DSL, se applicato con cura, ma in modo Ruby.

Mi chiedevo se la macro di LISP fosse applicabile solo a casi speciali e che le altre funzionalità del linguaggio di programmazione fossero abbastanza potenti da sollevare l'astrazione per affrontare le sfide odierne nello sviluppo del software.

    
posta OnesimusUnbound 03.06.2011 - 07:53
fonte

3 risposte

23

Leggi On Lisp e poi decidi tu stesso.

Il mio riassunto è che Ruby è migliore nel fornire una sintassi comoda. Ma Lisp vince, a mani basse, l'abilità di creare nuove astrazioni e quindi di astrarre l'astrazione sull'astrazione. Ma è necessario vedere Lisp in pratica per capire quel punto. Quindi il libro consiglia.

    
risposta data 03.06.2011 - 08:19
fonte
14

Le funzionalità di Ruby per l'authoring DSL non modificano la natura della lingua. Le funzioni di metaprogrammazione di Ruby sono intrinsecamente legate alla sintassi e alla semantica di Ruby e qualsiasi cosa tu scriva deve essere deviata nel modello a oggetti di Ruby.

Confrontalo con Lisp (e Scheme, le cui macro strutture differiscono ), dove le macro operano sul programma astratto stesso. Poiché un programma Lisp è un valore Lisp, una macro è una funzione che associa una sintassi essenzialmente arbitraria a un'altra.

In effetti, un Ruby DSL ancora si sente come Ruby, ma un Lisp DSL non deve sentirsi come Lisp.

    
risposta data 03.06.2011 - 08:23
fonte
2

I DSL di Ruby non sono affatto DSL e odio assolutamente usarli perché la loro documentazione piatta si basa su come funzionano davvero. Prendiamo ad esempio ActiveRecord. Permette di "dichiarare" le associazioni tra i Modelli:

class Foo < ActiveRecord::Base
    has_one :bar
    has_one :baz
end

Ma la dichiaratività di questo "DSL" (come la dichiaratività della stessa sintassi class di Ruby) è una bugia orribile che può essere esposta da chiunque comprenda come funzionano realmente le "DSL" di Ruby:

class Foo < ActiveRecord::Base
    [:bar,:baz,:qux,:quux].each do |table|
        has_one table if i_feel_like_it?(table)
    end
    puts "Just for shits and giggles, and to show"
    puts "just how fucked up Ruby really is, we're gonna ask you"
    puts "which SQL table you want the Foo model to have an"
    puts "association with.\n"
    puts "Type the name of a table here: "
    has_one gets.chomp.to_sym
end

(Prova a fare qualsiasi cosa chiudi nel corpo di un modulo Lisp defclass !)

Non appena hai codice come sopra nel tuo codebase, ogni sviluppatore del progetto deve comprendere appieno come funzionano i di Ruby (non solo l'illusione che creano) prima che possano mantenere il codice. La documentazione disponibile sarà completamente inutile, perché documenta solo l'uso idiomatico , che preserva l'illusione dichiarativa.

RSpec è anche peggio di quanto sopra, perché ha bizzarri edge case che richiedono un reverse reverse engineering per eseguire il debug. (Ho trascorso un'intera giornata cercando di capire perché uno dei miei casi di test è stato saltato. È risultato che RSpec esegue tutti i casi di test che hanno contesti dopo casi di test senza contesto, indipendentemente dall'ordine in cui appaiono nella sorgente, perché il metodo context pone il blocco in una struttura dati diversa da quella in cui normalmente verrebbe inserito.)

I DSL Lisp sono implementati da macro, che sono piccoli compilatori. Le DSL che puoi creare in questo modo non sono semplici abusi della sintassi esistente di Lisp. Sono veri mini-linguaggi che possono essere scritti per essere completamente senza interruzioni, perché possono avere la loro grammatica. Ad esempio, la macro di Lisp LOOP è molto più potente del metodo each di Ruby.

(So che hai già accettato una risposta, ma non tutti quelli che leggeranno questo argomento vorranno leggere la totalità di On Lisp .)

    
risposta data 05.06.2017 - 09:03
fonte

Leggi altre domande sui tag