Kategorien-Archiv Symbolische Programmierung

VonAlexander Vozian

Co-Creative Melody Provider: Visual Live-Coding with OM and Supercollider

Abstract: Der Co-Creative Melody Provider ist ein System für zeitgleiches Live-Coding mit SuperCollider und OpenMusic. Während in OpenMusic die Musik auf Notenebene gestaltet wird, ist SuperCollider für die Klangerzeugung zuständig. Die Kommunikation läuft durch Austausch von Nachrichten im Open-Sound-Control Protokoll per Abfrage durch User oder automatisiert.

Verantwortliche: Alexander Vozian

Überblick:

Die Zielsetzung für das Projekt war Integration von OpenMusic (OM) in einen Live Coding Workflow. Meine erste Idee dazu war es, SuperCollider (SC) für die Klangerzeugung zu verwenden und das Setzen der Noten auf OM auszulagern. Das heißt, man kann in SC live coden und OM als Hilfstool benutzen. In der Erarbeitung wurde aber klar, dass der OM-Patch während der Soundausgabe parallel verändert werden kann. Solange das Klang erzeugende Element nicht unterbrochen wird, kann Live Coding auch in OM stattfinden. Beispielsweise ist es möglich, die Auswahl an “Instrumenten”, in dem Fall SC Synths, vorzubereiten und diese komplett in OM zu steuern. Ein anderer kooperativerer Ansatz wäre, die zwei Programme, SC und OM, auf zwei Live Codende aufzuteilen. Zum Beispiel könnte eine Person in SC die Klanggestaltung übernehmen, während eine andere in OM diese Klänge in Zeit setzt. 

OM kümmert sich um die Generierung der Noten und SC um die Klangsynthese. Diese kommunizieren über das Open Sound Control  (OSC) Protokoll. Der User (Live Codende) schickt in SC eine Anfrage per OSC-Message an den OM-Patch. Die Message enthält Parameter für die Generierung einer Melodie, in dem Fall für eine Markov Analyse und Synthese. Die Message besteht aus:

  • der maximalen Anzahl von Noten,
  • die maximale Länge eines Loops in ms,
  • die Unter- und Obergrenze des zu analysierenden Ausgangsmaterials in ms
  • Auswahl des Ausgangsmaterials.

Das Ausgangsmaterial sind etwa 1 min lange Midi Dateien.

Quellen der Midi Dateien: bitmidi.com

Nach der Synthese schickt OM automatisch eine Message mit der Anzahl der generierten Noten, der Länge der Melodie in ms, einer Liste von Frequenzen und einer Liste von Onsets. Diese werden genutzt, um die Synths in SC zu steuern.

Bei jeder Evaluierung wird Notenmaterial analysiert und eine Liste von Frequenzen und Onsets synthetisiert und dann ausgegeben.

Für die Generierung der Noten werden etwa 1 min lange Midi-Dateien verwendet. Die Pitches und die Durations der Noten werden unabhängig voneinander mit Markov Funktionen erster Ordnung der OM-Alea Bibliothek analysiert, synthetisiert und per osc-send abgeschickt. Dadurch entstehen Tonfolgen, die in den Originaldateien nicht vorkommen. (Im Patch wird sichergestellt, dass die Liste der Pitches und die der Durations gleich lang ist.) Die Eingabeargumente sind bereits oben beschrieben.

Eine OSC-Message von OM zu SC besteht aus folgenden Daten:

  • OSC Key als Identifikator,
  • Gesamtzahl der Noten,
  • Länge der Melodie in Millisekunden,
  • Liste der Frequenzen,
  • Liste der Onsets.

Die Gesamtzahl der Noten wird in dem Fall nur für die Navigation durch die unformatierte OSC Message. Die Länge der Melodie wird benötigt, um den Zeitpunkt zu bestimmen, zu welchem die nächste Melodie angefragt wird. Die Liste der Frequenzen und die der Onsets wird erst in SC zusammengesetzt.

Die osc-send Funktion ist dabei in dem Patch markov_firstorder_osc_send. Um den Patch automatisch auszuführen, wenn eine OSC-Message ankommt, sind alle Teile des übergeordneten Patches auf reactive mode gestellt. Die list Funktion kann erst evaluiert werden, wenn alle Formen ein Ergebnis liefern, das heißt, wenn die Markov-Synthese abgeschlossen und osc-send ausgeführt wurde.

Das Ergebnis ist eine Art Server, der beim Eingang einer Anfrage aus SC automatisch eine Melodie zurückschickt.

In SC wird eine neue Instanz von OSCdef erzeugt, die die erhaltenen Parameter in globale Variablen speichert. Ein Synth(\t1) wird definiert, der von Patterns gespielt werden kann. Die Pfuncn Funktion interpretiert die globalen Variablen ~freq und ~dur als Funktionen und fragt diese damit ständig neu ab. Die Pseq Funktion setzt diese in eine Sequenz um, die von Pbind in als Pattern umgesetzt wird. Somit bildet der erste Parameter von ~freq mit dem ersten Parameter von ~dur die erste Note der Melodie. Die Pdef Funktion erstellt eine Instanz, die während der Laufzeit verändert werden kann. Damit wird auch sicher gestellt, dass ein laufender Loop erst nach Ende einer Melodie eine neue spielt.

Um eine neue Melodie, einen neuen Loop, anzufragen, reicht es, eine OSC-Message mit den entsprechenden Parametern zu schicken. Um diesen Prozess zu automatisieren, benötigt man ein die Funktion Tdef. 

Genauso wie das Ausführen eines Codeblocks in SC direkt Einfluss auf den Klang nehmen kann und somit richtig eingebettet werden muss, muss die Evaluierung eines Patches zur richtigen Zeit erfolgen. Im Falle des MWE wäre nicht der Klang unterbrochen, sondern das Metrum. 

Tdef(\om) berechnet zuerst die Zeitdauer, mit der das Senden der OSC-Message verzögert wird. Die Wartezeit ist abhängig von der Gesamtlänge des Loops und der Anzahl der Loops, welche man innerhalb des Tdef setzen kann. Dabei wird sichergestellt, dass der vorhandene Loop immer zu Ende gespielt wird, bevor die Parameter für einen neue Melodie ankommen.

Der Code zu OM und SC findet sich über diesen Link.

Abschließend noch folgendes Klangbeispiel zum Projekt:

Es wird ausschließlich die maximale Länge eines Loops und die Tonanzahl verändert. Das Ausgangsmaterial wird an zwei Stellen ausgewechselt. Es fängt an mit „Mario“, wechselt bei etwa 1:39 zu „Pokemon“ und bei 2:24 zu „Tetris“. Im Beispiel wird bewusst nichts am Klang des Instruments verändert (einfache Saw-Wave), um einen Fokus auf die Wechsel des Notenmaterials zu setzen.

Mario – Main Theme Overworld:


Pokemon – Battle (vs Wild Pokémon):


Tetris Theme:


Ergebnis:

Quellen der Midi Dateien: bitmidi.com

VonFlorian Simon

PixelWaltz: Sonifikation von Bildern in OpenMusic

Abstract: Mit dem OpenMusic-Programm PixelWaltz lassen sich Bilder in symbolische Repräsentation von Musik (Tonhöhen und Einsatzzeitpunkte) umsetzen. Es stehen Optionen zur Bildmanipulation zur Verfügung, mit denen das Resultat zusätzlich beeinflusst werden kann.

Verantwortliche: Florian Simon

Mapping: Pitch

Die Pixel des Bildes werden zeilenweise durchlaufen und die jeweiligen Rot-, Grün- und Blauwerte (zwischen 0 und 1) auf einen gewünschten Tonhöhenbereich gemappt. Aus einem Pixel werden damit stets drei Tonhöhenwerte in Midicent gewonnen. Da zwei nebeneinander liegende Pixel einander in vielen Fällen ähnlich sind, treten bei dieser Mapping-Methode oft sich alle drei Noten wiederholende Muster auf. Hierin liegt der Grund für den Titel des Projektes.

Es besteht auch die Möglichkeit die Anzahl der ausgegebenen Notenwerte zu begrenzen.

Mapping: Einsatzzeitpunkte

Für die Einsatzzeitpunkte und Tondauern kann ein konstanter Wert festgelegt werden. Zudem lässt sich ein Humanizer-Effekt zuschalten, der jede Note innerhalb eines angegebenen Bereiches zufällig nach vorne oder hinten verschiebt. Ausgehend vom Grundtempo lassen sich accelerandi und ritardandi gestalten, indem Listen aus drei Zahlen übergeben werden. Diese stehen für Startnote, Endnote sowie Geschwindigkeit der Tempoänderung. (20 50 -1) sorgt von Note 20 bis Note 50 für ein accelerando, bei dem die Abstände pro Ton um eine Millisekunde kürzer werden. Ein positiver dritter Wert entspricht einem ritardando.

Dynamik

Für die Lautstärke bzw. Velocity lassen sich verschiedene Zufallsbereiche für „rote“, „grüne“ und „blaue“ Noten festlegen. Die so erzeugten Werte können zudem sinusförmig moduliert werden, sodass beispielsweise ein An- und Abschwellen der Lautstärke über längere Zeiträume hinweg möglich ist. Dafür ist die Angabe einer Wellenlänge in Notenzahl sowie des maximalen Abweichungsfaktors nötig.

Begleitstimme

Optional bietet PixelWaltz die Möglichkeit eine Begleitstimme zu generieren, welche aus einzelnen zusätzlichen Tönen in einer gewünschten festen Notenzahlfrequenz besteht. Ist diese nicht durch 3 teilbar, entsteht oft eine Polymetrik. Die Tonhöhe wird zufällig bestimmt und kann dabei zwischen 3 und 6 Halbtönen unter der jeweils „begleiteten“ Note liegen.

Bildbearbeitung

Um weitere Variation zu kreieren sind dem Sonifikationsabschnitt von PixelWaltz Werkzeuge zur Manipulation des Eingangsbildes vorangestellt. Neben der Anpassung von Bildgröße, Helligkeit und Kontrast ist auch eine Verschiebung der Farbwerte und damit ein Umfärben des Bildes möglich. Die Änderungen in der musikalischen Übersetzung sind sofort merkbar: Mehr Helligkeit führt zu einer höheren Durchschnittstonhöhe, mehr Kontrast verkleinert die Zahl der verschiedenen Tonhöhenwerte. Bei einem blaudominierten Bild werden die jeweils letzten Noten der Tripel meist die höchsten sein.

Klangergebnisse

Die klanglichen Resultate unterscheiden sich natürlich je nach Input – gerade fotografiertes Material führt aber oft zu derselben wellenartigen Gesamtstruktur, die sich unregelmäßig und in langsamem Tempo chromatisch mal aufwärts, mal abwärts windet. Die Begleitung unterstützt diesen Effekt und kann einen Gegenpuls zur Hauptstimme bilden.

VonZeno Lösch

Erweiterung der akousmatischen Studie – 3D 5th-order Ambisonics

Dieser Beitrag handelt über die vierte Iteration einer akousmatischen Studie von Zeno Lösch, welche im Rahmen des Seminars „Visuelle Programmierung der Raum/Klangsynthese“ bei Prof. Dr. Marlon Schumacher an der HFM Karlsruhe durchgeführt wurden. Es wird über die grundlegende Konzeption, Ideen, aufbauende Iterationen sowie die technische Umsetzung mit OpenMusic behandelt.

Verantwortliche: Zeno Lösch, Master Student Musikinformatik der HFM Karlsruhe, 2. Semester

 

Pixel

Um Parameter zum Modulieren zu erhalten, wurde ein Python-Script verwendet.  

  Dieses Script ermöglicht es ein beliebiges Bild auf 10 x 10 Pixel zu skalieren und die jeweiligen Pixel Werte in eine Text Datei zu speichern. „99 153 187 166 189 195 189 190 186 88 203 186 198 203 210 107 204 143 192 108 164 177 206 167 189 189 74 183 191 110 211 204 110 203 186 206 32 201 193 78 189 152 209 194 47 107 199 203 195 162 194 202 192 71 71 104 60 192 87 128 205 210 147 73 90 67 81 130 188 143 206 43 124 143 137 79 112 182 26 172 208 39 71 94 72 196 188 29 186 191 209 85 122 205 198 195 199 194 195 204 “ Die Werte in der Textdatei sind zwischen 0 und 255. Die Textdatei wird in Open Music importiert und die Werte werden skaliert.      

Diese skalierten Werte werden als pos-env Parameter verwendet.      

Reaper und IEM-Plugin Suite

 

Mit verschiedenen Bildern und verschiedenen Skalierungen erhält man verschiedene Ergebnisse die für man als Parameter für Modulation verwenden kann. In Reaper wurden bei der Postproduktion die IEM-Plugin-Suite verwendet. Diese Tools verwendet man für Ambisonics von verschiedenen Ordnungen. In diesem Fall wurde Ambisonics 5 Ordnung angewendet. Ein Effekt der oft verwendet wurde ist der FDNReverb. Dieses Hallgerät bietet die Möglichkeit einen Ambisonics Reverb auf ein Mulikanal-File anzuwenden.           Die Stereo und Monofiles wurden zuerst in 5th Order Ambisonics Codiert (36 Kanäle) und schließlich mit dem binauralen Encoder in zwei Kanäle umgewandelt.                 Andere Effekte zur Nachbearbeitung(Detune, Reverb) wurden von mir selbst programmiert und sind auf Github verfügbar. Der Reverb basiert auf einen Paper von James A. Moorer About this Reverberation Business von 1979 und wurde in C++ geschrieben. Der Algorythmus vom Detuner wurde von der HTML Version vom Handbuch „The Theory and Technique of Electronic Music“ von Miller Puckette  in C++ geschrieben.     Das Ergebnis der letzen Iteration ist hier zu hören.  Alex Player - Best audio player

 

VonLorenz Lehmann

Library „OM-LEAD“

Abstract:

Die Library „OM-LEAD“ ist eine Library für regelbasierte, computergenerierte Echtzeit-Komposition. Die Überlegungen und Ansätze in Joseph Brancifortes Text „FROM THE MACHINE: REALTIME ALGORITHMIC APPROACHES TO HARMONY AND ORCHESTRATION“ sind Ausgangspunkt für die Entwicklung.

Momentan umfasst die Library zwei Funktionen, die sowohl mit CommonLisp, als auch mit schon bestehenden Funktionen aus dem OM-Package geschrieben sind.

Zudem ist die Komposition im Umfang der zu kontollierenden Parametern, momentan auf die Harmonik und die Stimmführung begrenzt. 

Für die Zukunft möchte ich ebenfalls eine Funktion schreiben, welche mit den Parametern Metrik und Einsatzabstände, die Komposition auch auf zeitlicher Ebene erlaubt.

Entwicklung: Lorenz Lehmann

Betreuung und Beratung: Prof. Dr. Marlon Schumacher

Mein herzlicher Dank für die freundliche Unterstützung gilt Joseph Branciforte und 

Prof. Dr. Marlon Schumacher.

weiterlesen

Seiten: 1 2 3 4

VonKaspars Jaudzems

BAD GUY: Eine akusmatische Studie

Abstract:

Inspiriert vom „Infinite Bad Guy“ Projekt und all den sehr unterschiedlichen Versionen, wie manche Leute ihre Fantasie zu diesem Song beflügelt haben, dachte ich, vielleicht könnte ich auch damit experimentieren, eine sehr lockere, instrumentale Coverversion von Billie Eilish’s „Bad Guy“ zu erstellen.

Betreuer: Prof. Dr. Marlon Schumacher

Eine Studie von: Kaspars Jaudzems

Wintersemester 2021/22
Hochschule für Musik, Karlsruhe

Zur Studie:

Ursprünglich wollte ich mit 2 Audiodateien arbeiten, eine FFT-Analyse am Original durchführen und dessen Klanginhalt durch Inhalt aus der zweiten Datei „ersetzen“, lediglich basierend auf der Grundfrequenz. Nachdem ich jedoch einige Tests mit einigen Dateien durchgeführt hatte, kam ich zu dem Schluss, dass diese Art von Technik nicht so präzise ist, wie ich es gerne hätte. Daher habe ich mich entschieden, stattdessen eine MIDI-Datei als Ausgangspunkt zu verwenden.

Sowohl die erste als auch die zweite Version meines Stücks verwendeten nur 4 Samples. Die MIDI-Datei hat 2 Kanäle, daher wurden 2 Dateien zufällig für jede Note jedes Kanals ausgewählt. Das Sample wurde dann nach oben oder unten beschleunigt, um dem richtigen Tonhöhenintervall zu entsprechen, und zeitlich gestreckt, um es an die Notenlänge anzupassen.

Die zweite Version meines Stücks fügte zusätzlich einige Stereoeffekte hinzu, indem 20 zufällige Pannings für jede Datei vor-generiert wurden. Mit zufällig angewendeten Kammfiltern und Amplitudenvariationen wurde etwas mehr Nachhall und menschliches Gefühl erzeugt.

Akusmatische Studie Version 1

Akusmatische Studie Version 2

Die dritte Version war eine viel größere Änderung. Hier werden die Noten beider Kanäle zunächst nach Tonhöhe in 4 Gruppen eingeteilt. Jede Gruppe umfasst ungefähr eine Oktave in der MIDI-Datei.

Dann wird die erste Gruppe (tiefste Töne) auf 5 verschiedene Kick-Samples abgebildet, die zweite auf 6 Snares, die dritte auf perkussive Sounds wie Agogo, Conga, Clap und Cowbell und die vierte Gruppe auf Becken und Hats, wobei insgesamt etwa 20 Samples verwendet werden. Hier wird eine ähnliche Filter-und-Effektkette zur Stereoverbesserung verwendet, mit dem Unterschied, dass jeder Kanal fein abgestimmt ist. Die 4 resultierenden Audiodateien werden dann den 4 linken Audiokanälen zugeordnet, wobei die niedrigeren Frequenzen kanale zur Mitte und die höheren kanale zu den Seiten sortiert werden. Für die anderen 4 Kanäle werden dieselben Audiodateien verwendet, aber zusätzliche Verzögerungen werden angewendet, um Bewegung in das Mehrkanalerlebnis zu bringen.

Akusmatische Studie Version 3

Die 8-Kanal-Datei wurde auf 2 Kanäle in 2 Versionen heruntergemischt, einer mit der OM-SoX-Downmix-Funktion und der andere mit einem Binauralix-Setup mit 8 Lautsprechern.

Akusmatische Studie Version 3 – Binauralix render

Erweiterung der akousmatischen Studie – 3D 5th-order Ambisonics

Die Idee mit dieser Erweiterung war, ein kreatives 36-Kanal-Erlebnis desselben Stücks zu schaffen, also wurde als Ausgangspunkt Version 3 genommen, die nur 8 Kanäle hat.

Ausgangspunkt Version 3

Ich wollte etwas Einfaches machen, aber auch die 3D-Lautsprecherkonfiguration auf einer kreativen weise benutzen, um die Energie und Bewegung, die das Stück selbst bereits gewonnen hatte, noch mehr hervorzuheben. Natürlich kam mir die Idee in den Sinn, ein Signal als Quelle für die Modulation von 3D-Bewegung oder Energie zu verwenden. Aber ich hatte keine Ahnung wie…

Plugin „ambix_encoder_i8_o5 (8 -> 36 chan)“

Bei der Recherche zur Ambix Ambisonic Plugin (VST) Suite bin ich auf das Plugin „ambix_encoder_i8_o5 (8 -> 36 chan)“ gestoßen. Dies schien aufgrund der übereinstimmenden Anzahl von Eingangs- und Ausgangskanälen perfekt zu passen. In Ambisonics wird Raum/Bewegung aus 2 Parametern übersetzt: Azimuth und Elevation. Energie hingegen kann in viele Parameter übersetzt werden, aber ich habe festgestellt, dass sie am besten mit dem Parameter Source Width ausgedrückt wird, weil er die 3D-Lautsprecherkonfiguration nutzt, um tatsächlich „nur“ die Energie zu erhöhen oder zu verringern.

Da ich wusste, welche Parameter ich modulieren muss, begann ich damit zu experimentieren, verschiedene Spuren als Quelle zu verwenden. Ehrlich gesagt war ich sehr froh, dass das Plugin nicht nur sehr interessante Klangergebnisse lieferte, sondern auch visuelles Feedback in Echtzeit. Bei der Verwendung beider habe ich mich darauf konzentriert, ein gutes visuelles Feedback zu dem zu haben, was im Audiostück insgesamt vor sich geht.

Visuelles Feedback – video

Kanal 2 als modulations quelle für Azimuth

Dies half mir, Kanal 2 für Azimuth, Kanal 3 für Source Width und Kanal 4 für Elevation auszuwählen. Wenn wir diese Kanäle auf die ursprüngliche Eingabe-Midi-Datei zurückverfolgen, können wir sehen, dass Kanal 2 Noten im Bereich von 110 bis 220 Hz, Kanal 3 Noten im Bereich von 220 bis 440 Hz und Kanal 4 Noten im Bereich von 440 bis 20000 Hz zugeordnet ist. Meiner Meinung nach hat diese Art der Trennung sehr gut funktioniert, auch weil die Sub-bass frequenzen (z. B. Kick) nicht moduliert wurden und auch nicht dafur gebraucht waren. Das bedeutete, dass der Hauptrhythmus des Stücks als separates Element bleiben konnte, ohne den Raum oder die Energiemodulationen zu beeinflussen, und ich denke, das hat das Stück irgendwie zusammengehalten.

Akusmatische Studie Version 4 – 36 channels, 3D 5th-order Ambisonics – Datei war zu groß zum Hochladen

Akusmatische Studie Version 4 – Binaural render

VonLorenz Lehmann

Library „OM-LEAD“

Abstract:

Die Library „OM-LEAD“ ist eine Library für regelbasierte, computergenerierte Echtzeit-Komposition. Die Überlegungen und Ansätze in Joseph Brancifortes Text „FROM THE MACHINE: REALTIME ALGORITHMIC APPROACHES TO HARMONY AND ORCHESTRATION“ sind Ausgangspunkt für die Entwicklung.

Momentan umfasst die Library zwei Funktionen, die sowohl mit CommonLisp, als auch mit schon bestehenden Funktionen aus dem OM-Package geschrieben sind.

Zudem ist die Komposition im Umfang der zu kontollierenden Parametern, momentan auf die Harmonik und die Stimmführung begrenzt. 

Für die Zukunft möchte ich ebenfalls eine Funktion schreiben, welche mit den Parametern Metrik und Einsatzabstände, die Komposition auch auf zeitlicher Ebene erlaubt.

Entwicklung: Lorenz Lehmann

Betreuung und Beratung: Prof. Dr. Marlon Schumacher

Mein herzlicher Dank für die freundliche Unterstützung gilt Joseph Branciforte und 

Prof. Dr. Marlon Schumacher.

weiterlesen

Seiten: 1 2 3 4

VonLorenz Lehmann

SPCL – 2a) Variablen, Scoping

In dieser Einheit haben wir uns mit Variablen und Scoping (Gültigkeitsbereichen) beschäftigt. Insbesondere haben wir Konzepte zu lexicalische vs dynamische, sowie lokale vs. globale Gültigkeitsbereiche studiert. Hier finden Sie eine kurze Zusammenfassung. Im Zshg. mit diesem Thema findet sich am Ende des Beitrags noch ein interessantes Video zum Lambda Calculus, bzw. dem Unterschied zwischen zustands-basierten (state-based) und funktionalen (functional) Sprachen.

Variablen

Lokale Variablen

  • let => erzeugt lokale, lexikalische  Variablen. Beispiel:

(let ((x 5) (y 10))
(+ x y)
)

=> 15 ;  x und y können innerhalb des let-statements benutzt werden

Globale Variablen:

  • defvar => erzeugt Variable und weist einen Wert zu, allerdings nur wenn die Variable noch nicht definiert wurde. Beispiel:

(defvar *mydefvar* 'something)

  • defparameter => erzeugt Variable und weist ihr einen Wert zu. Beispiel:

(defparameter *mydefparameter* 'anotherthing)

  • defconstant => erzeugt eine Konstante. Beispiel:

(defconstant +pi+ 3.14)

; => globale Variablen sind (wie der Name schon sagt) global existent und überall benutzbar. PS Bitte beachten Sie die “earmuffs” Notation für globale *Variable*, bzw. +Konstanten+.

(* +pi+ 2)

=> 6.28

Setz-Operatoren

Die Werte von existenten lexikalischen und dynamischen Variablen lassen sich mit Setz-Operatoren (set, setq, setf) setzen*.

(let ((something 2.3))
(setq something 1)
(print  something)
)

; => “1”

(setq *mydefparameter* 5.0)
(print *mydefparameter*)

; => “5”

*Konstanten können nicht mit Setz-Operatoren verändert oder mit neuen Werten gebunden werden. Beispiel:

(setf  +pi+ 1.0) ; => ERROR

Lexikalisch (statisch)  vs  Dynamisch (special) 

  • Lexikalisch: Der Wert der Variablen wird durch den umgebenden Text (also “räumlich”) der Funktionsdefinition bestimmt. Beispiel:

(let ((x 5))
          (defun return-x () x)
)

(let ((x 10))
         (return-x)
)

=> 5 ;   der Wert von x aus der Umgebung der Funktionsdefinition

  • Dynamisch: Der Wert der Variablen wird zur Funktionslaufzeit (also zeitlich) bestimmt. Beispiel:

(defparameter *x* 5)

(defun return-x () *x*)

(setf *x* 10)

(return-x)

=> 10 ; der Wert von *x* zur Laufzeit der Funktion

Closures

Als Closure wird ein Konstrukt (Umgebung und Funktionsdefinition) bezeichnet, welches Funktionen Zugriff auf (lexikalische) Variablen erlaubt, die ausserhalb der Funktionsdefinition selbst, jedoch innerhalb des lexikalischen Scopes in der die Funktionen definiert wurden, gebunden sind. Beispiel:

(let ((number 10))
           (defun add1 () (incf number))
(defun sub1 () (decf number))
)

(add1) , => 11, 12, 13, ...

(sub1), => 9, 8, 7, ...

; Obwohl die Variable ‘number’ nicht innerhalb der Funktionen add1 und sub1 definiert wurde, kann Sie dennoch verwendet (und verändert) werden.

Für mehr Lektüre zu Variablen und Scoping empfehle ich Ihnen dringend diesen sehr guten Text:

http://www.gigamonkeys.com/book/variables.html

Hier eine Beschreibung aus Wikipedia:

Lexical scope vs. dynamic scope

A fundamental distinction in scoping is what “part of a program” means. In languages with lexical scope (also called static scope), name resolution depends on the location in the source code and the lexical context, which is defined by where the named variable or function is defined. In contrast, in languages with dynamic scope the name resolution depends upon the program state when the name is encountered which is determined by the execution context or calling context. In practice, with lexical scope a variable’s definition is resolved by searching its containing block or function, then if that fails searching the outer containing block, and so on, whereas with dynamic scope the calling function is searched, then the function which called that calling function, and so on, progressing up the call stack.[4] Of course, in both rules, we first look for a local definition of a variable.

Most modern languages use lexical scoping for variables and functions, though dynamic scoping is used in some languages, notably some dialects of Lisp, some “scripting” languages like Perl, and some template languages.[c] Even in lexically scoped languages, scope for closures can be confusing to the uninitiated, as these depend on the lexical context where the closure is defined, not where it is called.

Lexical resolution can be determined at compile time, and is also known as early binding, while dynamic resolution can in general only be determined at run time, and thus is known as late binding.

VonLorenz Lehmann

SPCL – 1) Formen, S-Expressions, Funktionen

Einführung in die Sprache Common LISP

In dieser Unterrichtseinheit wird die Sprache Common LISP eingeführt. Hierzu betrachten wir Besonderheiten dieser Sprache, insbesondere die Syntax: sog. „S-Expressions“ (symbolic expressions) und Prefix (oder „Polish“) Notation. Des Weiteren befassen wir uns mit dem Konzept der  Evaluierung von Formen unter Berücksichtigung der Äquivalenz von Daten und Funktionen: „A lisp form is a lisp datum that is also a program, that is, it can be evaluated without an error.

Wir haben uns mit der Evaluierungsreihenfolge studiert. Lisp evaluiert Formen rekursiv. Hierzu ein kleines Beispiel aus diesem online LISP Tutorial. Folgende form soll evaluiert werden:

(+ 33 (* 2.3 4)) 9)

  1. The + function is looked up.
  2. 33 is evaluated (its value is 33).
  3. (* 2.3 4) is evaluated:
    1. The * function is looked up.
    2. 2.3 is evaluated (its value is 2.3)
    3. 4 is evaluated (its value is 4)
    4. 2.3 and 4 are passed to the * function.
    5. The * function returns 9.2. This is the value of (* 2.3 4).
  4. 9 is evaluated (its value is 9).
  5. 33, 9.2, and 9 are passed to the + function.
  6. The + function returns 51.2. This is the value of (+ 33 (* 2.3 4) 9).
  7. The Lisp system returns 51.2.

Wir haben sodann verschiedene Datentypen kennengelernt: symbols, floats, integers und ratios.

Wir haben unsere ersten Programmierversuche gestartet und unsere ersten kleinen LISP forms geschrieben. Dabei haben wir sog. „primitive functions“ (Funktionen, die bereits in der Sprache implementiert sind) verwendet, um Operationen mit Daten auszuführen. Diese waren: (*für die u.s. Tabellen nehmen wir an, die  Variable A hätte den Wert 10 und Variable B den Wert 20) :

Arithmetische Operatoren

+, -, *, /, mod, rem, incf, decf

Operator Description Example
+ Adds two operands (+AB) will give 30
Subtracts second operand from the first (- A B) will give -10
* Multiplies both operands (* A B) will give 200
/ Divides numerator by de-numerator (/ B A) will give 2
mod, rem Modulus Operator and remainder of after an integer division (mod B A) will give 0
incf Increments operator increases integer value by the second argument specified (incf A 3) will give 13
decf Decrements operator decreases integer value by the second argument specified (decf A 4) will

Prädikatsfunktionen

equalp, symbolp, numberp, oddp, evenp

Operator Description Example
equalp Checks if the values of the two arguments are equal (= A B) is not true.
symbolp Checks if the value of the argument is a symbol (symbolp A) is not true
numberp Checks if the value of the argument is a number (numberp A) is true.
oddp Checks if the value of the argument (integer) is odd (oddp A) is not true
evenp Checks if the value of the argument (integer) is even (evenp A) is true

Vergleichsoperatoren

=, /=, >, <, >=, <=, max, min

Operator Description Example
= Checks if the values of the operands are all equal or not, if yes then condition becomes true. (= A B) is not true.
/= Checks if the values of the operands are all different or not, if values are not equal then condition becomes true. (/= A B) is true.
> Checks if the values of the operands are monotonically decreasing. (> A B) is not true.
< Checks if the values of the operands are monotonically increasing. (< A B) is true.
>= Checks if the value of any left operand is greater than or equal to the value of next right operand, if yes then condition becomes true. (>= A B) is not true.
<= Checks if the value of any left operand is less than or equal to the value of its right operand, if yes then condition becomes true. (<= A B) is true.
max It compares two or more arguments and returns the maximum value. (max A B) returns 20
min It compares two or more arguments and returns the minimum value. (min A B) returns 20

 

Logische Operatoren

Hierfür nehmen wir an, A hat den Wert NIL (false) und B hat den Wert 5 (true).

Operator Description Example
and It takes any number of arguments. The arguments are evaluated left to right. If all arguments evaluate to non-nil, then the value of the last argument is returned. Otherwise nil is returned. (and A B) will return NIL.
or It takes any number of arguments. The arguments are evaluated left to right until one evaluates to non-nil, in such case the argument value is returned, otherwise it returns nil. (or A B) will return 5.
not It takes one argument and returns t if the argument evaluates to nil. (not A) will return T.

Danach haben wir die Macro Funktion „defun“ kennen gelernt, um unsere eigenen Funktionen zu definieren. Dies haben wir dann mit der Programmierung eines kleinen Würfelspiels zur Anwendung gebracht.

Seiten: 1 2