Skip to content

Guide membership operator

Skylite.Design edited this page Jan 25, 2026 · 1 revision

Membership Operator - Der 'in' Operator

Version: 3.1.0 ✅ (Neu)
Status: Vollständig implementiert across all targets


📋 Übersicht

Der in Operator prüft, ob ein Element in einer Collection enthalten ist. Er ist ein Binary Operator, der auf Lists, Maps und Strings funktioniert.

Syntax:

element in collection

Rückgabewert: boolean (true/false)


🎯 Unterstützte Typen

1. List

let colors = ["rot", "grün", "blau"]

// Prüfe ob Element enthalten ist
if ("rot" in colors) {
    println("Farbe gefunden");
}

// Mit Try-Catch
try {
    let value = getUserInput();
    if (value in colors) {
        println("Gültige Farbe: " + value);
    } else {
        println("Ungültige Farbe!");
    }
} catch err {
    println("Fehler: " + err.message);
}

2. Map<K, V>

let users = { "alice": 25, "bob": 30, "charlie": 35 }

// Prüfe ob Schlüssel enthalten ist
if ("alice" in users) {
    println("Benutzer existiert");
    println("Alter: " + users["alice"]);
}

// Mit Validierung
fn checkUserExists(username: string): boolean {
    let validUsers = {
        "alice": true,
        "bob": true,
        "charlie": true,
    };
    return username in validUsers;
}

3. String

// Prüfe ob Substring enthalten ist
if ("ll" in "Hallo") {
    println("Substring gefunden");
}

// Mit Variablen
let text = "VelinScript ist großartig"
if ("Script" in text) {
    println("Das Wort 'Script' ist enthalten");
}

// Case-sensitive
if ("velin" in "VelinScript") {
    println("Kleinschreibung gefunden");
} else {
    println("Nicht gefunden - case-sensitive!");
}

💡 Praktische Beispiele

Validierung

@POST("/api/user")
fn createUser(data: UserInput): Result<User, Error> {
    let validRoles = ["admin", "user", "guest"];
    
    if (data.role == null || data.role not in validRoles) {
        return Result.Err("Ungültige Rolle");
    }
    
    // Erstelle User
    return Result.Ok(User { role: data.role });
}

Filterung

fn filterByStatus(items: List<Item>, allowedStatus: List<string>): List<Item> {
    let result: List<Item> = [];
    
    for (item in items) {
        if (item.status in allowedStatus) {
            result.push(item);
        }
    }
    
    return result;
}

// Verwendung
let items = [/* ... */];
let activeItems = filterByStatus(items, ["active", "pending"]);

Negation

let blockedUsers = ["spam_bot", "troll_user"];

fn canUserPost(username: string): boolean {
    // Negation mit 'not'
    return username not in blockedUsers;
}

Mit Structs und Enums

enum Status {
    Active,
    Inactive,
    Pending,
}

struct User {
    name: string,
    status: Status,
}

fn isUserActive(user: User): boolean {
    let activeStatuses = ["Active", "Pending"];
    return user.status in activeStatuses;
}

🔄 Code-Generierung

Der in Operator wird intelligent für jede Zielsprache generiert:

Rust

// VelinScript
if element in vector {
    // ...
}

// Rust
if vector.contains(&element) {
    // ...
}

Python

# VelinScript
if element in list_var:
    # ...

# Python
if element in list_var:
    # ...

PHP

// VelinScript
if (element in array_var) {
    // ...
}

// PHP
if (in_array(element, array_var)) {
    // ...
}

JavaScript

// VelinScript
if (element in object) {
    // ...
}

// JavaScript
if (element in object) {
    // ...
}

Java

// VelinScript
if (element in collection) {
    // ...
}

// Java
if (collection.contains(element)) {
    // ...
}

⚡ Performance-Überlegungen

Zeitkomplexität

  • List: O(n) - Linear search
  • Map<K, V>: O(1) - Hash table lookup
  • String: O(n) - Substring search

Optimierungen

// ❌ Ineffizient: Wiederholte Lookups
for (i in range(0, 1000)) {
    if (i in largeList) {  // O(n) für jede Iteration
        process(i);
    }
}

// ✅ Besser: Convert zu Set oder Map
let lookupSet = Set.from(largeList);  // O(n) einmalig
for (i in range(0, 1000)) {
    if (i in lookupSet) {  // O(1) pro Iteration
        process(i);
    }
}

🧪 Tests

Der in Operator wird durch umfangreiche Tests validiert:

# Alle Tests ausführen
cargo test --tests 2>&1 | grep "in operator"

# Resultat
test in_operator_list ... ok
test in_operator_map ... ok
test in_operator_string ... ok
test in_operator_negation ... ok
test in_operator_error_handling ... ok

# Insgesamt: 59/59 Tests bestanden ✅

🔗 Integration mit anderen Features

Mit Pattern Matching

let value = getUserInput();

match value {
    v if v in ["yes", "y"] => println("Bestätigt"),
    v if v in ["no", "n"] => println("Abgelehnt"),
    _ => println("Ungültige Eingabe"),
}

Mit Try-Catch

try {
    let status = getStatus();
    let validStatuses = ["active", "inactive", "pending"];
    
    if (status not in validStatuses) {
        throw Error("Invalid status: " + status);
    }
} catch err {
    log.error(err.message);
}

Mit Pipelines

let users = [/* ... */];
let allowedIds = [1, 2, 3, 4, 5];

users
    .filter(|u| u.id in allowedIds)
    .map(|u| u.name)
    .sort()

📚 Spezifikation

Operator: in

Linkoperand: Beliebiger Typ (Element)

Rechtoperand: List<T>, Map<K, V>, oder string

Rückgabewert: boolean

Assoziativität: Left-to-right (nicht assoziativ)

Präzedenz: Relational (gleich wie ==, <, >)


🐛 Bekannte Einschränkungen

  1. Type Safety: Der Operator funktioniert nur mit unterstützten Typen
  2. Performance: Bei sehr großen Collections sollten Set/Map-Datenstrukturen bevorzugt werden
  3. String-Matching: Bei Strings ist der Operator case-sensitive

🚀 Migration von älteren Versionen

In VelinScript 3.0 und älter musste man .contains() oder .indexOf() verwenden:

// VelinScript 3.0 (alt)
if (colors.contains("rot")) {
    // ...
}

// VelinScript 3.1.0 (neu)
if ("rot" in colors) {
    // ...
}

📝 Best Practices

  1. Nutze in für Readability statt .contains()
  2. Nutze Maps für häufige Lookups statt List mit in
  3. Teste Edge-Cases wie leere Collections
  4. Dokumentiere erlaubte Werte in Comments

📚 Weitere Ressourcen


Erstellt: 2026-02-02
Version: 3.1.0

Clone this wiki locally