Groovy 1.8 bringt neue Command Chain Syntax

Alles, was nicht direkt mit Python-Problemen zu tun hat. Dies ist auch der perfekte Platz für Jobangebote.
Antworten
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Es wird viel "mitgedacht" und die (idealisierten) Beispiele sehen auch ganz nett aus. Leseprobe:
If your command chain contains an odd number of elements, the chain will be composed of method / arguments, and will finish by a final property access:

Code: Alles auswählen

take 3 cookies                                 // equivalent to: take(3).cookies
                                               // and also this: take(3).getCookies()
Der komplette Absatz zu dem Thema: http://docs.codehaus.org/display/GROOVY ... cLanguages

Ist m.E. eine spannende Sache, mal zu sehen, wie sich die Syntax in der Praxis hinsichtlich Lesbarkeit und Intuitivität verhält, d.h. wie das ganze angenommen wird. Vielleicht probiere ich es beizeiten mal selber aus. :)

Habe weiter unten auf der Seite noch was in der Art gefunden (keine Ahnung, ob die Syntax in früheren Versionen so ging):
Parsing JSON data structures is one thing, but we should also be able to produce JSON content just like we create markup with the MarkupBuilder. The following example:

Code: Alles auswählen

import groovy.json.*

def json = new JsonBuilder()

json.person {
    name "Guillaume"
    age 33
    pets "Hector", "Felix"
}

println json.toString()
Will create the JSON output:

Code: Alles auswählen

{"person":{"name":"Guillaume","age":33,"pets":["Hector","Felix"]}}
Schon cool, weil man sich nach etwas Einarbeitung IMHO schnell dran gewöhnt und Ergebnisse erhält, die man erwartet. :)
lunar

@snafu: Ob es sinnvoll ist, eine Sprache mit DSLs für alle möglichen Markup-Formate aufzublasen, sei dahingestellt ... in diesem Fall sieht das nur irgendwie nicht so spektakulär aus, der Unterschied zu einem entsprechenden Literal in Python ist doch marginal:

Code: Alles auswählen

person = {'person': dict(
    name='Guillaume',
    age=33,
    pets=['Hector', 'Felix'])}
json.dumps(person)
Dafür braucht es meiner Ansicht keine eigene Syntax ...
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Habe ich schon erwähnt dass Scala ne XML-Syntax hat?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

In CoffeeScript kann man JSON so ähnlich wie in Groovy eingeben:

Code: Alles auswählen

#!/usr/bin/env coffee

json =
    person:
        name: "Guillaume"
        age: 33
        pets: ["Hector", "Felix"]

console.log json
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Hier ein Versuch, den Groovy-Builder in Python abzubilden:

Code: Alles auswählen

class JSONObject:
    def __init__(self, *pairs):
        self.properties = pairs or []
    
    def append(self, name, value):
        self.properties.append((name, value))
    
    def __repr__(self):
        return "{%s}" % ", ".join("%r: %r" % pair for pair in self.properties)

print JSONObject(
    ("name", "Guillaume"),
    ("age", 33),
    ("pets", ["Hector", "Felix"]),
)


json = JSONObject()
json.append("name", "Guillaume")
json.append("age", 33)
json.append("pets", ["Hector", "Felix"])
print json


class JSONBuilder:
    def __getattr__(self, name):
        def f(*args):
            if all(isinstance(arg, tuple) for arg in args):
                self.object = JSONObject(*args)
                return name, self.object
            return name, args[0] if len(args) == 1 else list(args)
        return f
    
    def __str__(self):
        return repr(self.object)

json = JSONBuilder()

json.person(
    json.name("Guillaume"),
    json.age(33),
    json.pets("Hector", "Felix"),
)

print json
Ich zeige "JSONObject", eine Klasse, mit der ich JSON-Objekte repräsentieren kann. Ich kann sie entweder mit einer Liste von Tupeln initialisieren oder über die Methode "append". Ich nehme kein dict, weil ich auf diese Weise die Reihenfolge der Attribute nicht gleich halten kann. Außerdem wäre es ansonsten viel zu einfach.

Dank variabler Argumentliste kann man bis auf die runden Klammern bereits die erste Variante der Initialisierung einigermaßen gut lesen. Python zwingt mich natürlich, überall Anführungszeichen zu benuzten. Die Variante mit "append" ist imperativ und "verschwendet" eine Variable, ist aber immer noch recht einfach (solange man nicht Objekte schachteln will).

Die Klasse "JSONBuilder" macht, was auch Groovy macht. Im Gegensatz zu Groovy habe ich jedoch keine Blöcke, in denen ich den Scope so manipulieren kann, dass ein bestimmtes Objekt der Empfänger alle Nachrichten ist, sondern ich muss den Empfänger immer explizit angeben, daher überall "json.". Ich spare mir dafür die Anführungszeichen. Ich weiß nicht, wie Groovy das regelt, aber ich musste festlegen, dass jede Argumentliste mit Länge != 1 als Array (repräsentiert durch eine Python-Liste) aufgefasst wird. Außerdem musste ich noch tricksen, damit ich Objekte schachteln kann.

Ist jetzt die Syntax mit einem Builder so viel schicker? Ich weiß nicht. Der Vorteil gegenüber einer funktionalen Variante wäre, dass man Bedingungen oder Schleifen einbauen kann, aber das gibt das Beispiel nicht her.

Stefan
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

sma hat geschrieben:Ist jetzt die Syntax mit einem Builder so viel schicker?
Im Rahmen der Möglichkeiten von Python wohl eher nicht. Wie du schon gesagt hast, muss wegen dem Scope ständig ein ``json`` mitgeschleppt werden, was nervig ist. Allerdings bietet Python ja auch von Haus aus schon eine wenig geschwätzige Syntax, die allgemein gut lesbar ist, so dass man sich solche Verrenkungen sparen kann.

Ein paar Zeichen spart man mit der Groovy-Syntax aber natürlich trotzdem ein. Und man kann netterweise wählen, ob man Klammern setzen will oder nicht. So möchte man vielleicht eine Funktion, die mit nur einem Argument genutzt wird, ohne Klammern schreiben und bei mehreren Argumenten oder mehrfach verschachtelten Funktionen wiederum zwecks Lesbarkeit lieber Klammern setzen (wobei ich glaube, dass letzteres ohnehin nur mit Klammern ausgedrückt werden kann).

Ich finde die in Groovy implementierte Idee jedenfalls ganz interessant. Mehr wollte ich damit auch nicht sagen. ;)
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

snafu hat geschrieben:Es wird viel "mitgedacht" und die (idealisierten) Beispiele sehen auch ganz nett aus. Leseprobe:
If your command chain contains an odd number of elements, the chain will be composed of method / arguments, and will finish by a final property access:

Code: Alles auswählen

take 3 cookies                                 // equivalent to: take(3).cookies
                                               // and also this: take(3).getCookies()
Der komplette Absatz zu dem Thema: http://docs.codehaus.org/display/GROOVY ... cLanguages

Ist m.E. eine spannende Sache, mal zu sehen, wie sich die Syntax in der Praxis hinsichtlich Lesbarkeit und Intuitivität verhält, d.h. wie das ganze angenommen wird. Vielleicht probiere ich es beizeiten mal selber aus. :)
Ich weiß nicht, das setzt ja schon recht komische Schnittstellen voraus.

Code: Alles auswählen

take 2.pills of chloroquinine after 6.hours // equivalent to: take(2.pills).of(chloroquinine).after(6.hours)
Die Programmlogik ist schon recht verquer. Logischer fände ich

Code: Alles auswählen

take(2.pillsOf(chloroquinine), after:6.hours)
Oder hat da goovie irgendwelche Sprachfeatures die ich nicht kenne, so dass take(2.pills).of(chloroquinine).after(6.hours) etwas völlig anderes als in Python bedeutet?

Ich finde es auch immer wieder erstaunlich wie gut leserlich Smalltalk ist, auch ohne neue Syntaxfeatures:

Code: Alles auswählen

self take: (2 pillsOf: chloroquinine) after: 6 hours
Antworten