Rekursion
Stellen Sie sich vor, Sie haben ein großes JSON-Objekt, in dem Benutzer verstreut sind. Sie können auf verschiedenen Pfaden gefunden werden:
{
"serviceUsers": [
{
"name": "bob",
"service": "clicker"
},
...
],
"org": {
"admins": [
{
"name": "joy",
"teamMembers": [ ... ]
}
...
Wie können wir anhand des obigen Beispiels jeden Benutzer in diesem Objekt finden? Mit dem neuen rekursieren
Methode Diese Frage kann leicht beantwortet werden.
Stellen Sie sich vor, diese Struktur wird in eine geparst jdata
Objekt.
jdata = parse.json("data.json").params;
Angesichts der Tatsache, dass Benutzer eine haben Name
Feld definiert, wir könnten in allen Objekten und Pfaden nach diesen suchen:
> jdata.recurse( name != empty )
[
0: {
name: "bob",
service: "clicker"
},
1: {
name: "joy",
teamMembers: [ ... ]
},
...
]
Von hier aus können Sie die Ergebnisse weiter suchen oder ändern. Zum Beispiel könnten wir nach allen Benutzern suchen, die Teammitglieder
definiert:
> jdata.recurse( name != empty ).where( teamMembers != empty )
Wir könnten uns auch Felder zur Weiterverarbeitung schnappen:
> jdata.recurse( name != empty ).map( name )
[
0: "bob"
1: "joy"
...
]
Find and fix the security risks that pose the biggest threat to your business.
Benannte Funktionsargumente
MQL ordnet im Allgemeinen alle Felder, auf die Sie zugreifen, dem Objekt zu, das es aufruft. Zum Beispiel, wenn Sie Schlüsselwörter wie verwenden woher
, ihre Filterfunktion ist an jedes Objekt in der Liste gebunden:
> users.where( name != /bob/i )
Implizit rufen wir Name
auf jedem Benutzer
Objekt, das die Liste betrachtet. Unter der Haube sieht die innere Funktion so aus:
user.name != /bob/i
MQL hatte nur zwei Möglichkeiten, auf dieses gebundene Objekt zuzugreifen. Eine war die implizite _
Bezeichner, der auf das gebundene Objekt zeigt:
> users.where( _.name != /bob/i )
Der zweite Weg gilt nur für Karten und wird aufgerufen über Schlüssel
oder Wert
um auf ihre Daten zuzugreifen:
> {name: "bob", id: "bid"}.where( value == "bob" )
{
name: "bob"
}
Wir haben jedoch festgestellt, dass ein wichtiger Anwendungsfall von diesen Methoden nicht abgedeckt wurde: die verschachtelte Rekursion.
Stellen Sie sich beispielsweise vor, Sie haben eine Liste von Gruppen und möchten nach Einträgen suchen, deren Mitglieder einen Benutzer mit demselben Namen wie der Gruppenname enthielten. Dank benannter Funktionsargumente können wir jetzt diesen Anwendungsfall abdecken:
> groups.where(g: g.members.contains(u: u.name == g.name))
groups.where.list: [
0: group name="root" gid=0
]
Nehmen wir das auseinander: Wir suchen nach einer Reihe von Gruppen, die unseren Kriterien entsprechen. Die äußere Schleife enthält:
> groups.where(g: g.members.contains(u: u.name == g.name))
groups.where.list: [
0: group name="root" gid=0
]
Hier definieren wir das Argument g
, was bedeutet, dass wir jedes Mal, wenn wir diesen Bezeichner aufrufen, auf die Gruppe zugreifen, die die Schleife betrachtet.
Als Nächstes schauen wir uns die Mitglieder jeder Gruppe an g
:
groups.where(g:
...
)
Das Mitglieder
Feld ist eine Liste von Benutzern, die dieser Gruppe zugewiesen sind. Auch hier definieren wir ein benanntes Argument, in diesem Fall u
, wodurch wir auf jeden Benutzer in dieser Liste zugreifen können.
Schließlich fügen wir die Filterbedingung hinzu und verwenden die Gruppe g
und der Mitgliedsbenutzer u
in jeder Schleife:
u.name == g.name
Wenn wir das alles mit einer schönen Formatierung zusammenbringen, erhalten wir:
groups.where(g:
g.members.contains(u:
u.name == g.name
)
)
Die Verwendung benannter Funktionsargumente ist nicht auf verschachtelte Schleifen beschränkt. Sie können es überall in MQL verwenden, um die Lesbarkeit des Codes zu verbessern:
packages.where(package:
package.name == /ssh/i
)
Semver
Eine der am häufigsten nachgefragten Funktionen in MQL waren bereits in unseren ersten Alpha-Versionen intelligente Operationen zum Vergleich von Versionen. Es hat einige Zeit gedauert, bis wir das geschafft haben, aber wir haben endlich native Unterstützung für semantische Versionen in MQL.
Um semantische Versionen zu verwenden, können Sie jede Zeichenfolge mit der neuen umschließen Semver
Schlüsselwort
> semver("1.2.3")
semver: 1.2.3
Semver ist sehr nützlich, wenn Versionen miteinander verglichen werden. Ohne semantische Versionen erhalten wir oft unerwartete Ergebnisse wie diese:
> "1.2.3" < "1.12"
# false
Bei semantischen Versionen verhält sich dies jedoch korrekt:
> semver("1.2.3") < semver("1.12")
# true
Wir haben auch Unterstützung für die automatische Konvertierung von Zeichenketten in Semver hinzugefügt, wenn nur eine Seite der Operation eine Zeichenfolge ist.