diff options
-rw-r--r-- | de-de/dhall-de.html.markdown | 380 | ||||
-rw-r--r-- | dhall.html.markdown | 6 | ||||
-rw-r--r-- | directx9.html.markdown | 827 | ||||
-rw-r--r-- | mercury.html.markdown | 263 | ||||
-rw-r--r-- | tr-tr/clojure-tr.html.markdown | 1 | ||||
-rw-r--r-- | tr-tr/edn-tr.html.markdown | 157 |
6 files changed, 1631 insertions, 3 deletions
diff --git a/de-de/dhall-de.html.markdown b/de-de/dhall-de.html.markdown new file mode 100644 index 00000000..385c88be --- /dev/null +++ b/de-de/dhall-de.html.markdown @@ -0,0 +1,380 @@ +--- +language: Dhall +contributors: + - ["Gabriel Gonzalez", "http://www.haskellforall.com/"] +translators: + - ["Profpatsch", "http://profpatsch.de"] +filename: learndhall-de.py +lang: de-de +--- + +Dhall ist eine programmierbare Konfigurationssprache und bietet eine +nicht-repetetive Alternative zu YAML. + +Man kann Dhall sehen als: JSON + Funktionen + Typen + Importsystem + +Obwohl Dhall programmierbar ist, ist die Sprache nicht +turingvollständig. Viele von Dhalls Features benutzen diese +Einschränkung, um stärkere Sicherheitsgarantien zu bieten und besseres +Tooling zu ermöglichen. + +```haskell +-- einzeiliger Kommentar + +{- mehrzeiliger Kommentar + + Unicode funktioniert 🙂 + + Diese Datei ist eine valide Dhall-Expression und evaluiert zu einem + großen Record, welcher die Ergebnisse jedes Schritts beinhaltet. + + Das Ergebnis kann angezeigt werden, indem man die Datei evaluiert: + + $ dhall --file learndhall.dhall + + {- Kommentare können verschachtelt sein -} +-} + +let greeting = "Hallo, Welt!" + +let fruits = "🍋🍓🍍🍉🍌" + +let interpolation = "Ein paar leckere Früchte: ${fruits}" + +let multilineText {- Inline-Kommentare funktionieren ebenfalls -} = + '' + In Multiline-Text-Literals wird Whitespace am Anfang der Zeile + entfernt. + + Das bedeutet Text kann frei eingerückt oder ausgerückt werden, + ohne dass sich der Inhalt des Strings ändert. + + Relative Einrückungen bleiben erhalten. + + Ansonsten wird das Text-Literal verbatim erhalten, ähnlich + zu “literal”-Multiline-Strings in YAML. + '' + +let bool = True + +-- Typannotationen für Bindings sind optional, aber hilfreich, also +-- benutzen wir sie hier. +let annotation : Bool = True + +let renderedBool : Text = if bool then "True" else "False" + +-- Natürliche Zahlen sind nicht-negativ und vorzeichenlos. +let naturalNumber : Natural = 42 + +-- Integer können negativ sein, brauchen aber ein explizites Vorzeichen. +let positiveInteger : Integer = +1 + +let negativeInteger : Integer = -12 + +let pi : Double = 3.14159265359 + +{- Identifier dürfen eine große Anzahl an verschiedenen Zeichen + beinhalten (wie z.B. Anführungszeichen oder Whitespace), wenn man + sie mit Backticks umschließt. +-} +let `Avogadro's Number` : Double = 6.0221409e+23 + +let origin : { x : Double, y : Double } = { x = 0.0, y = 0.0 } + +let somePrimes : List Natural = [ 2, 3, 5, 7, 11 ] + +{- Ein Schema ist das gleiche wie ein Typ. + + Typnamen beginnen konventionell mit einem Großbuchstaben, was + jedoch nicht erzwungen wird. +-} +let Profile : Type + = { person : + { name : Text + , age : Natural + } + , address : + { country : Text + , state : Text + , city : Text + } + } + +let bernd : Profile = + { person = + { name = "Bernd Lauert" + , age = 67 + } + , address = + { country = "Deutschland" + , state = "Bayern" + , city = "Augsburg" + } + } + +let augsburg : Text = bernd.address.city + +{- Enum-Alternativen beginnen konventionell auch mit einem + Großbuchstaben. Das wird ebenfalls nicht erzwungen. +-} +let DNA : Type = < Adenine | Cytosine | Guanine | Thymine > + +let dnaSequence : List DNA = [ DNA.Thymine, DNA.Guanine, DNA.Guanine ] + +let compactDNASequence : List DNA = + let a = DNA.Adenine + let c = DNA.Cytosine + let g = DNA.Guanine + let t = DNA.Thymine + in [ c, t, t, a, t, c, g, g, c ] + +-- Enums werden transformiert, indem man einen Record mit einem Feld +-- pro Alternative angibt. +let theLetterG : Text = + merge + { Adenine = "A" + , Cytosine = "C" + , Guanine = "G" + , Thymine = "T" + } + DNA.Guanine + +let presentOptionalValue : Optional Natural = Some 1 + +let absentOptionalValue : Optional Natural = None Natural + +let points : List { x : Double, y : Double } = + [ { x = 1.1, y = -4.2 } + , { x = 4.4, y = -3.0 } + , { x = 8.2, y = -5.5 } + ] + +{- `Natural -> List Natural` ist der Funktionstyp mit Eingabetyp + `Natural` und Ausgabetyp `List Natural`. + + Alle Funktionen in Dhall sind Anonyme Funktionen (aka. „Lambdas“), + denen man optional einen Namen geben kann. + + Die folgende Funktion beispielsweise ist äquivalent zu diesem + Python Code: + + lambda n : [ n, n + 1 ] + + ... und diesem Javascript Code: + + function (n) { return [ n, n + 1 ]; } +-} +let exampleFunction : Natural -> List Natural = + \(n : Natural) -> [ n, n + 1 ] + +-- Dhall unterstützt auch Unicode-Syntax, aber dieses Tutorial nutzt +-- die ASCII-Syntax. +let unicodeFunction : Natural → List Natural = + λ(n : Natural) → [ n, n + 1 ] + +-- Funktionsargumente brauchen keine Klammern. +let exampleFunctionApplication : List Natural = + exampleFunction 2 + +let functionOfMultipleArguments : Natural -> Natural -> List Natural = + \(x : Natural) -> \(y : Natural) -> [ x, y ] + +let functionAppliedToMultipleArguments : List Natural = + functionOfMultipleArguments 2 3 + +{- Wie `exampleFunction`, aber wir geben dem Eingabetypen + einen Namen, `n`. +-} +let namedArgumentType : forall (n : Natural) -> List Natural = + \(n : Natural) -> [ n, n + 1 ] + +{- Bekommt der Eingabetyp einen Namen, kann man ihn weiter hinten in + der gleichen Typdefinition wiederverwenden. + + Das ermöglicht Funktionen, die mit mehr als einem Eingabetypen + arbeiten können (aka. „polymorphe“ Funktionen). +-} +let duplicate : forall (a : Type) -> a -> List a = + \(a : Type) -> \(x : a) -> [ x, x ] + +let duplicatedNumber : List Natural = + duplicate Natural 2 + +let duplicatedBool : List Bool = + duplicate Bool False + +{- Die Sprache hat auch eine handvoll eingebauter polymorpher + Funktionen, wie zum Beispiel: + + List/head : forall (a : Type) -> List a -> Optional a +-} +let firstPrime : Optional Natural = List/head Natural somePrimes + +let functionOfARecord : { x : Natural, y : Natural } -> List Natural = + \(args : { x : Natural, y : Natural }) -> [ args.x, args.y ] + +let functionAppliedToARecord : List Natural = + functionOfARecord { x = 2, y = 5 } + +{- Alle Typkonversionen sind explizit. + + `Natural/show` ist eine eingebaute Funktion mit dem Typ: + + Natural/show : Natural -> Text + + ... welche `Natural`s in ihre `Text`-Repräsentation konvertiert. +-} +let typeConversion : Natural -> Text = + \(age : Natural) -> "Ich bin ${Natural/show age} Jahre alt!" + +-- Ein „Template“ ist einfach eine Funktion mit Ausgabetyp `Text`. +let mitLicense : { year : Natural, copyrightHolder : Text } -> Text = + \(args : { year : Natural, copyrightHolder : Text }) -> +'' +Copyright ${Natural/show args.year} ${args.copyrightHolder} + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +'' + +-- Template-Instanziierung ist das gleiche wie Funktionsanwendung. +let templatedLicense : Text = + mitLicense { year = 2019, copyrightHolder = "Jane Smith" } + +{- Expressions können via URL importiert werden. + + Ähnlich wie in Bash kann man Code aus dem lokalen Dateisystem + importieren (wird nicht gezeigt). + + Sicherheitsbewusste Nutzer können via URLs importierte Expressions + mit einem semantischen Integritätscheck versehen („pinnen“). + Für gepinnte Imports wird der Dhall-Interpreter jeden Versuch + vereiteln, auf der Remote-Seite die Expression zu manipulieren. + Jedoch werden Änderungen, die den Inhalt der importierten + Expression nicht verändern trotzdem akzeptiert. + + Auf diese Weise gepinnte Expressions werden auch in einem + Content-Adressable Store lokal gecached (standardmäßig in + `~/.cache/dhall`). +-} +let Natural/sum : List Natural -> Natural = + https://prelude.dhall-lang.org/Natural/sum + sha256:33f7f4c3aff62e5ecf4848f964363133452d420dcde045784518fb59fa970037 + +let twentyEight : Natural = Natural/sum somePrimes + +-- Ein „Paket“ ist einfach ein (möglicherweise verschachtelter) +-- Record, den man importiert. +let Prelude = https://prelude.dhall-lang.org/package.dhall + +let false : Bool = Prelude.Bool.not True + +-- Durch das Anhängen von `as Text` wird eine Datei verbatim +-- importiert und nicht als Dhall-Code interpretiert. +let sourceCode : Text = https://prelude.dhall-lang.org/Bool/not as Text + +-- Environment-Variablen können auch imortiert werden. +let presentWorkingDirectory = env:PWD as Text + +-- Mit `?` kann man eine “Fallback-Expression” angeben, für den Fall +-- dass ein Import fehlschlägt. +let home : Optional Text = Some env:HOME ? None Text + +-- Fallback-Expressions können auch alternative Imports enthalten. +let possiblyCustomPrelude = + env:DHALL_PRELUDE + ? https://prelude.dhall-lang.org/package.dhall + +{- Ein ausführliches Beispiel, welches mithilfe der + `generate`-Funktion eine Konfiguration für 10 Build-User generiert: + + Prelude.List.generate + : Natural -> forall (a : Type) -> (Natural -> a) -> List a +-} +let buildUsers = + let makeUser = \(user : Text) -> + let home = "/home/${user}" + let privateKey = "${home}/.ssh/id_ed25519" + let publicKey = "${privateKey}.pub" + in { home = home + , privateKey = privateKey + , publicKey = publicKey + } + + let buildUser = + \(index : Natural) -> makeUser "build${Natural/show index}" + + let Config = + { home : Text + , privateKey : Text + , publicKey : Text + } + + in Prelude.List.generate 10 Config buildUser + +-- Alle Ergebnisse in einem großen Record +in { greeting = greeting + , fruits = fruits + , interpolation = interpolation + , multilineText = multilineText + , bool = bool + , annotation = annotation + , renderedBool = renderedBool + , naturalNumber = naturalNumber + , positiveInteger = positiveInteger + , negativeInteger = negativeInteger + , pi = pi + , `Avogadro's Number` = `Avogadro's Number` + , origin = origin + , somePrimes = somePrimes + , bernd = bernd + , augsburg = augsburg + , dnaSequence = dnaSequence + , compactDNASequence = compactDNASequence + , theLetterG = theLetterG + , presentOptionalValue = presentOptionalValue + , absentOptionalValue = absentOptionalValue + , points = points + , exampleFunction = exampleFunction + , unicodeFunction = unicodeFunction + , exampleFunctionApplication = exampleFunctionApplication + , functionOfMultipleArguments = functionOfMultipleArguments + , functionAppliedToMultipleArguments = functionAppliedToMultipleArguments + , namedArgumentType = namedArgumentType + , duplicate = duplicate + , duplicatedNumber = duplicatedNumber + , duplicatedBool = duplicatedBool + , firstPrime = firstPrime + , functionOfARecord = functionOfARecord + , functionAppliedToARecord = functionAppliedToARecord + , typeConversion = typeConversion + , mitLicense = mitLicense + , templatedLicense = templatedLicense + , twentyEight = twentyEight + , false = false + , sourceCode = sourceCode + , presentWorkingDirectory = presentWorkingDirectory + , home = home + , buildUsers = buildUsers + } +``` + +Mehr Infos und Lernmaterialien gibt es auf der offiziellen Website +(Englisch), auf der man Dhall auf im Browser ausprobieren kann: + +* [https://dhall-lang.org](http://dhall-lang.org/) diff --git a/dhall.html.markdown b/dhall.html.markdown index 21126c8a..704a94ee 100644 --- a/dhall.html.markdown +++ b/dhall.html.markdown @@ -11,7 +11,7 @@ alternative to YAML. You can think of Dhall as: JSON + functions + types + imports Note that while Dhall is programmable, Dhall is not Turing-complete. Many -of Dhall's features take advantage of this restriction to provider stronger +of Dhall's features take advantage of this restriction to provide stronger safety guarantees and more powerful tooling. ```haskell @@ -216,7 +216,7 @@ let functionAppliedToARecord : List Natural = let typeConversion : Natural -> Text = \(age : Natural) -> "I am ${Natural/show age} years old!" --- A template is the same thing as a function whose output type is `Text` +-- A "template" is the same thing as a function whose output type is `Text` let mitLicense : { year : Natural, copyrightHolder : Text } -> Text = \(args : { year : Natural, copyrightHolder : Text }) -> '' @@ -263,7 +263,7 @@ let Natural/sum : List Natural -> Natural = let twentyEight : Natural = Natural/sum somePrimes --- A package is the same thing as a (possibly nested) record that you can import +-- A "package" is the same thing as a (possibly nested) record that you can import let Prelude = https://prelude.dhall-lang.org/package.dhall let false : Bool = Prelude.Bool.not True diff --git a/directx9.html.markdown b/directx9.html.markdown new file mode 100644 index 00000000..b51f418d --- /dev/null +++ b/directx9.html.markdown @@ -0,0 +1,827 @@ +--- +category: tool +tool: DirectX 9 +filename: learndirectx9.cpp +contributors: + - ["Simon Deitermann", "s.f.deitermann@t-online.de"] +--- + +**Microsoft DirectX** is a collection of application programming interfaces (APIs) for handling tasks related to +multimedia, especially game programming and video, on Microsoft platforms. Originally, the names of these APIs +all began with Direct, such as Direct3D, DirectDraw, DirectMusic, DirectPlay, DirectSound, and so forth. [...] +Direct3D (the 3D graphics API within DirectX) is widely used in the development of video games for Microsoft +Windows and the Xbox line of consoles.<sup>[1]</sup> + +In this tutorial we will be focusing on DirectX 9, which is not as low-level as it's sucessors, which are aimed at programmers very familiar with how graphics hardware works. It makes a great starting point for learning Direct3D. In this tutorial I will be using the Win32-API for window handling and the DirectX 2010 SDK. + +## Window creation + +```cpp +#include <Windows.h> + +bool _running{ false }; + +LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { + // Handle incoming message. + switch (msg) { + // Set running to false if the user tries to close the window. + case WM_DESTROY: + _running = false; + PostQuitMessage(0); + break; + } + // Return the handled event. + return DefWindowProc(hWnd, msg, wParam, lParam); +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPSTR lpCmdLine, int nCmdShow) { + // Set window properties we want to use. + WNDCLASSEX wndEx{ }; + wndEx.cbSize = sizeof(WNDCLASSEX); // structure size + wndEx.style = CS_VREDRAW | CS_HREDRAW; // class styles + wndEx.lpfnWndProc = WndProc; // window procedure + wndEx.cbClsExtra = 0; // extra memory (struct) + wndEx.cbWndExtra = 0; // extra memory (window) + wndEx.hInstance = hInstance; // module instance + wndEx.hIcon = LoadIcon(nullptr, IDI_APPLICATION); // icon + wndEx.hCursor = LoadCursor(nullptr, IDC_ARROW); // cursor + wndEx.hbrBackground = (HBRUSH) COLOR_WINDOW; // background color + wndEx.lpszMenuName = nullptr; // menu name + wndEx.lpszClassName = "DirectXClass"; // register class name + wndEx.hIconSm = nullptr; // small icon (taskbar) + // Register created class for window creation. + RegisterClassEx(&wndEx); + // Create a new window handle. + HWND hWnd{ nullptr }; + // Create a new window handle using the registered class. + hWnd = CreateWindow("DirectXClass", // registered class + "directx window", // window title + WS_OVERLAPPEDWINDOW, // window style + 50, 50, // x, y (position) + 1024, 768, // width, height (size) + nullptr, // parent window + nullptr, // menu + hInstance, // module instance + nullptr); // struct for infos + // Check if a window handle has been created. + if (!hWnd) + return -1; + // Show and update the new window. + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); + // Start the game loop and send incoming messages to the window procedure. + _running = true; + MSG msg{ }; + while (_running) { + while (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + return 0; +} +``` + +This should create a window, that can the moved, resized and closed. + +## Direct3D initialization + +```cpp +// Includes DirectX 9 structures and functions. +// Remember to link "d3d9.lib" and "d3dx9.lib". +// For "d3dx9.lib" the DirectX SDK (June 2010) is needed. +// Don't forget to set your subsystem to Windows. +#include <d3d9.h> +#include <d3dx9.h> +// Includes the ComPtr, a smart pointer automatically releasing COM objects. +#include <wrl.h> +using namespace Microsoft::WRL; +// Next we define some Direct3D9 interface structs we need. +ComPtr<IDirect3D9> _d3d{ }; +ComPtr<IDirect3DDevice9> _device{ }; +``` + +With all interfaces declared we can now initialize Direct3D. + +```cpp +bool InitD3D(HWND hWnd) { + // Store the size of the window rectangle. + RECT clientRect{ }; + GetClientRect(hWnd, &clientRect); + // Initialize Direct3D + _d3d = Direct3DCreate9(D3D_SDK_VERSION); + // Get the display mode which format will be the window format. + D3DDISPLAYMODE displayMode{ }; + _d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, // use default graphics card + &displayMode); // display mode pointer + // Next we have to set some presentation parameters. + D3DPRESENT_PARAMETERS pp{ }; + pp.BackBufferWidth = clientRect.right; // width is window width + pp.BackBufferHeight = clientRect.bottom; // height is window height + pp.BackBufferFormat = displayMode.Format; // use adapter format + pp.BackBufferCount = 1; // 1 back buffer (default) + pp.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard after presentation + pp.hDeviceWindow = hWnd; // associated window handle + pp.Windowed = true; // display in window mode + pp.Flags = 0; // no special flags + // Variable to store results of methods to check if everything succeded. + HRESULT result{ }; + result = _d3d->CreateDevice(D3DADAPTER_DEFAULT, // use default graphics card + D3DDEVTYPE_HAL, // use hardware acceleration + hWnd, // the window handle + D3DCREATE_HARDWARE_VERTEXPROCESSING, + // vertices are processed by the hardware + &pp, // the present parameters + &_device); // struct to store the device + // Return false if the device creation failed. + // It is helpful to set breakpoints at the return line. + if (FAILED(result)) + return false; + // Create a viewport which hold information about which region to draw to. + D3DVIEWPORT9 viewport{ }; + viewport.X = 0; // start at top left corner + viewport.Y = 0; // .. + viewport.Width = clientRect.right; // use the entire window + viewport.Height = clientRect.bottom; // .. + viewport.MinZ = 0.0f; // minimun view distance + viewport.MaxZ = 100.0f; // maximum view distance + // Apply the created viewport. + result = _device->SetViewport(&viewport); + // Always check if something failed. + if (FAILED(result)) + return false; + // Everything was successful, return true. + return true; +} +// ... +// Back in our WinMain function we call our initialization function. +// ... +// Check if Direct3D initialization succeded, else exit the application. +if (!InitD3D(hWnd)) + return -1; + +MSG msg{ }; +while (_running) { + while (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + // Clear to render target to a specified color. + _device->Clear(0, // number of rects to clear + nullptr, // indicates to clear the entire window + D3DCLEAR_TARGET, // clear all render targets + D3DXCOLOR{ 1.0f, 0.0f, 0.0f, 1.0f }, // color (red) + 0.0f, // depth buffer clear value + 0); // stencil buffer clear value + // ... + // Drawing operations go here. + // ... + // Flip the front- and backbuffer. + _device->Present(nullptr, // no source rectangle + nullptr, // no destination rectangle + nullptr, // don't change the current window handle + nullptr); // pretty much always nullptr +} +// ... +``` + +Now the window should be displayed in a bright red color. + +## Vertex Buffer + +Let's create a vertex buffer to store the vertices for our triangle + +```cpp +// At the top of the file we need to add a include. +#include <vector> +// First we declare a new ComPtr holding a vertex buffer. +ComPtr<IDirect3DVertexBuffer9> _vertexBuffer{ }; +// Lets define a funtion to calculate the byte size of a std::vector +template <typename T> +unsigned int GetByteSize(const std::vector<T>& vec) { + return sizeof(vec[0]) * vec.size(); +} +// Define "flexible vertex format" describing the content of our vertex struct. +// Use the defined color as diffuse color. +const unsigned long VertexStructFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE; +// Define a struct representing the vertex data the buffer will hold. +struct VStruct { + float x, y, z; // store the 3D position + D3DCOLOR color; // store a color +}; +// Declare a new function to create a vertex buffer. +IDirect3DVertexBuffer9* CreateBuffer(const std::vector<VStruct>& vertices) { + // Declare the buffer to be returned. + IDirect3DVertexBuffer9* buffer{ }; + HRESULT result{ }; + result = _device->CreateVertexBuffer( + GetByteSize(vertices), // vector size in bytes + 0, // data usage + VertexStructFVF, // FVF of the struct + D3DPOOL_DEFAULT, // use default pool for the buffer + &buffer, // receiving buffer + nullptr); // special shared handle + // Check if buffer was created successfully. + if (FAILED(result)) + return nullptr; + // Create a data pointer for copying the vertex data + void* data{ }; + // Lock the buffer to get a buffer for data storage. + result = buffer->Lock(0, // byte offset + GetByteSize(vertices), // size to lock + &data, // receiving data pointer + 0); // special lock flags + // Check if buffer was locked successfully. + if (FAILED(result)) + return nullptr; + // Copy the vertex data using C standard libraries memcpy. + memcpy(data, vertices.data(), GetByteSize(vertices)); + buffer->Unlock(); + // Set the FVF Direct3D uses for rendering. + _device->SetFVF(VertexStructFVF); + // If everything was successful return the filled vertex buffer. + return buffer; +} +``` + +In our **WinMain** we can now call the new function after the Direct3D initialization. + +```cpp +// ... +if (!InitD3D(hWnd)) + return -1; +// Define the vertices we need to draw a triangle. +// Values are declared in a clockwise direction else Direct3D would cull them. +// If you want to diable culling just call: +// _device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); +std::vector<VStruct> vertices { + // Bottom left + VStruct{ -1.0f, -1.0f, 1.0f, D3DXCOLOR{ 1.0f, 0.0f, 0.0f, 1.0f } }, + // Top left + VStruct{ -1.0f, 1.0f, 1.0f, D3DXCOLOR{ 0.0f, 1.0f, 0.0f, 1.0f } }, + // Top right + VStruct{ 1.0f, 1.0f, 1.0f, D3DXCOLOR{ 0.0f, 0.0f, 1.0f, 1.0f } } +}; +// Try to create the vertex buffer else exit the application. +if (!(_vertexBuffer = CreateBuffer(vertices))) + return -1; +// ... +``` + +## Transformations + +Before we can use the vertex buffer to draw our primitives, we first need to set up the matrices. + +```cpp +// Lets create a new funtions for the matrix transformations. +bool SetupTransform() { + // Create a view matrix that transforms world space to + // view space. + D3DXMATRIX view{ }; + // Use a left-handed coordinate system. + D3DXMatrixLookAtLH( + &view, // receiving matrix + &D3DXVECTOR3{ 0.0f, 0.0f, -20.0f }, // "camera" position + &D3DXVECTOR3{ 0.0f, 0.0f, 0.0f }, // position where to look at + &D3DXVECTOR3{ 0.0f, 1.0f, 0.0f }); // positive y-axis is up + HRESULT result{ }; + result = _device->SetTransform(D3DTS_VIEW, &view); // apply the view matrix + if (FAILED(result)) + return false; + // Create a projection matrix that defines the view frustrum. + // It transforms the view space to projection space. + D3DXMATRIX projection{ }; + // Create a perspective projection using a left-handed coordinate system. + D3DXMatrixPerspectiveFovLH( + &projection, // receiving matrix + D3DXToRadian(60.0f), // field of view in radians + 1024.0f / 768.0f, // aspect ratio (width / height) + 0.0f, // minimum view distance + 100.0f); // maximum view distance + result = _device->SetTransform(D3DTS_PROJECTION, &projection); + if (FAILED(result)) + return false; + // Disable lighting for now so we can see what we want to render. + result = _device->SetRenderState(D3DRS_LIGHTING, false); + // View and projection matrix are successfully applied, return true. + return true; +} +// ... +// Back in the WinMain function we can now call the transformation function. +// ... +if (!(_vertexBuffer = CreateVertexBuffer(vertices))) + return -1; +// Call the transformation setup function. +if (!SetupTransform()) + return -1; +// ... +``` + +## Rendering + +Now that everything is setup we can start drawing our first 2D triangle in 3D space. + +```cpp +// ... +if (!SetupTransform()) + return -1; +// First we have to bind our vertex buffer to the data stream. +HRESULT result{ }; +result = _device->SetStreamSource(0, // use the default stream + _vertexBuffer.Get(), // pass the vertex buffer + 0, // no offset + sizeof(VStruct)); // size of vertex struct +if (FAILED(result)) + return -1; + +// Create a world transformation matrix and set it to an identity matrix. +D3DXMATRIX world{ }; +D3DXMatrixIdentity(&world); +// Create a scalation matrix scaling our primitve by 10 in the x, +// 10 in the y and keeping the z direction. +D3DXMATRIX scaling{ }; +D3DXMatrixScaling(&scaling, // matrix to scale + 10, // x scaling + 10, // y scaling + 1); // z scaling +// Create a rotation matrix storing the current rotation of our primitive. +// We set the current rotation matrix to an identity matrix for now. +D3DXMATRIX rotation{ }; +D3DXMatrixIdentity(&rotation); +// Now we multiply the scalation and rotation matrix and store the result +// in the world matrix. +D3DXMatrixMultiply(&world, // destination matrix + &scaling, // matrix 1 + &rotation); // matrix 2 +// Apply the current world matrix. +_device->SetTransform(D3DTS_WORLD, &world); +// Disable culling so we can see the back of our primitive when it rotates. +_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); +// The default cullmode is D3DCULL_CW. +// After we used our the rotation matrix for multiplication we can set it +// to rotate a small amount. +// D3DXToRadian() function converts degree to radians. +D3DXMatrixRotationY(&rotation, // matrix to rotate + D3DXToRadian(0.5f)); // rotation angle in radians + +MSG msg{ }; + while (_running) { + // ... + _device->Clear(0, nullptr, D3DCLEAR_TARGET, + D3DXCOLOR{ 0.0f, 0.0f, 0.0f, 1.0f }, 0.0f, 0); + // With everything setup we can call the draw function. + _device->BeginScene(); + _device->DrawPrimitive(D3DPT_TRIANGLELIST, // primitive type + 0, // start vertex + 1); // primitive count + _device->EndScene(); + + _device->Present(nullptr, nullptr, nullptr, nullptr); + // We can keep multiplying the world matrix with our rotation matrix + // to add it's rotation to the world matrix. + D3DXMatrixMultiply(&world, &world, &rotation); + // Update the modified world matrix. + _device->SetTransform(D3DTS_WORLD, &world); + // ... +``` + +You should now be viewing a 10x10 units colored triangle from 20 units away, rotating around its origin.<br> +You can find the complete working code here: [DirectX - 1](https://pastebin.com/YkSF2rkk) + +## Indexing + +To make it easier to draw primitives sharing a lot of vertices we can use indexing, so we only have to declare the unique vertices and put the order they are called in another array. + +```cpp +// First we declare a new ComPtr for our index buffer. +ComPtr<IDirect3DIndexBuffer9> _indexBuffer{ }; +// ... +// Declare a function creating a index buffer from a std::vector +IDirect3DIndexBuffer9* CreateIBuffer(std::vector<unsigned int>& indices) { + IDirect3DIndexBuffer9* buffer{ }; + HRESULT result{ }; + result = _device->CreateIndexBuffer( + GetByteSize(indices), // vector size in bytes + 0, // data usage + D3DFMT_INDEX32, // format is 32 bit int + D3DPOOL_DEFAULT, // default pool + &buffer, // receiving buffer + nullptr); // special shared handle + if (FAILED(result)) + return nullptr; + // Create a data pointer pointing to the buffer data. + void* data{ }; + result = buffer->Lock(0, // byte offset + GetByteSize(indices), // byte size + &data, // receiving data pointer + 0); // special lock flag + if (FAILED(result)) + return nullptr; + // Copy the index data and unlock after copying. + memcpy(data, indices.data(), GetByteSize(indices)); + buffer->Unlock(); + // Return the filled index buffer. + return buffer; +} +// ... +// In our WinMain we can now change the vertex data and create new index data. +// ... +std::vector<VStruct> vertices { + VStruct{ -1.0f, -1.0f, 1.0f, D3DXCOLOR{ 1.0f, 0.0f, 0.0f, 1.0f } }, + VStruct{ -1.0f, 1.0f, 1.0f, D3DXCOLOR{ 0.0f, 1.0f, 0.0f, 1.0f } }, + VStruct{ 1.0f, 1.0f, 1.0f, D3DXCOLOR{ 0.0f, 0.0f, 1.0f, 1.0f } }, + // Add a vertex for the bottom right. + VStruct{ 1.0f, -1.0f, 1.0f, D3DXCOLOR{ 1.0f, 1.0f, 0.0f, 1.0f } } +}; +// Declare the index data, here we build a rectangle from two triangles. +std::vector<unsigned int> indices { + 0, 1, 2, // the first triangle (b,left -> t,left -> t,right) + 0, 2, 3 // the second triangle (b,left -> t,right -> b,right) +}; +// ... +// Now we call the "CreateIBuffer" function to create a index buffer. +// ... +if (!(_indexBuffer = CreateIBuffer(indices))) + return -1; +// ... +// After binding the vertex buffer we have to bind the index buffer to +// use indexed rendering. +result = _device->SetStreamSource(0, _vertexBuffer.Get(), 0, sizeof(VStruct)); +if (FAILED(result)) + return -1; +// Bind the index data to the default data stream. +result = _device->SetIndices(_indexBuffer.Get()) +if (FAILED(result)) + return -1; +// ... +// Now we replace the "DrawPrimitive" function with an indexed version. +_device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, // primitive type + 0, // base vertex index + 0, // minimum index + indices.size(), // amount of vertices + 0, // start in index buffer + 2); // primitive count +// ... +``` + +Now you should see a colored rectangle made up of 2 triangles. If you set the primitive count in the "DrawIndexedPrimitive" method to 1 only the first triangle should be rendered and if you set the start of the index buffer to 3 and the primitive count to 1 only the second triangle should be rendered.<br> +You can find the complete working code here: [DirectX - 2](https://pastebin.com/yWBPWPRG) + +## Vertex declaration + +Instead of using the old "flexible vertex format" we should use vertex declarations instead, as the FVF declarations get converted to vertex declarations internally anyway. + +```cpp +// First we have to REMOVE the following lines: +const unsigned long VertexStructFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE; +// and +_device->SetFVF(VertexStructFVF); +// ... +// We also have to change the vertex buffer creation FVF-flag. +result = _device->CreateVertexBuffer( + GetByteSize(vertices), + 0, + 0, // <- 0 indicates we use vertex declarations + D3DPOOL_DEFAULT, + &buffer, + nullptr); +// Next we have to declare a new ComPtr. +ComPtr<IDirect3DVertexDeclaration9> _vertexDecl{ }; +// ... +result = _device->SetIndices(_indexBuffer.Get()); +if (FAILED(result)) + return -1; +// Now we have to declare and apply the vertex declaration. +// Create a vector of vertex elements making up the vertex declaration. +std::vector<D3DVERTEXELEMENT9> vertexDeclDesc { + { 0, // stream index + 0, // byte offset from the struct beginning + D3DDECLTYPE_FLOAT3, // data type (3d float vector) + D3DDECLMETHOD_DEFAULT, // tessellator operation + D3DDECLUSAGE_POSTION, // usage of the data + 0 }, // index (multiples usage of the same type) + { 0, + 12, // byte offset (3 * sizeof(float) bytes) + D3DDECLTYPE_D3DCOLOR, + D3DDECLMETHOD_DEFAULT, + D3DDECLUSAGE_COLOR, + 0 }, + D3DDECL_END() // marks the end of the vertex declaration +}; +// After having defined the vector we can create a vertex declaration from it. +result = _device->CreateVertexDeclaration( + vertexDeclDesc.data(), // the vertex element array + &_vertexDecl); // receiving pointer +if (FAILED(result)) + return -1; +// Apply the created vertex declaration. +_device->SetVertexDeclaration(_vertexDecl.Get()); +// ... +``` + +## Shader + +The maximum shader model for Direct3D 9 is shader model 3.0. Even though every modern graphics card should support it, it is best to check for capabilities. + +```cpp +// ... +_device->SetVertexDeclaration(_vertexDecl.Get()); +// First we have to request the device capabilities. +D3DCAPS9 deviceCaps{ }; +_device->GetDeviceCaps(&deviceCaps); +// Now we check if shader model 3.0 is supported for the vertex shader. +if (deviceCaps.VertexShaderVersion < D3DVS_VERSION(3, 0)) + return -1; +// And the same for the pixel shader. +if (deviceCaps.PixelShaderVersion < D3DPS_VERSION(3, 0)) + return -1; +``` + +Now that we are sure shader model 3.0 is supported let's create the vertex and pixel shader files. +DirectX 9 introduced the HLSL (**High Level Shading Language**), a C-like shader language, which +simplified the shader programming a lot, as you could only write shaders in shader assembly in DirectX 8. +Let's create a simple vertex- and pixel shader. + +**Vertex Shader** + +```cpp +// 3 4x4 float matrices representing the matrices we set in the fixed-function +// pipeline by using the SetTransform() method. +float4x4 projectionMatrix; +float4x4 viewMatrix; +float4x4 worldMatrix; +// The input struct to the vertex shader. +// It holds a 3d float vector for the position and a 4d float vector +// for the color. +struct VS_INPUT { + float3 position : POSITION; + float4 color : COLOR; +}; +// The output struct of the vertex shader, that is passed to the pixel shader. +struct VS_OUTPUT { + float4 position : POSITION; + float4 color : COLOR; +}; +// The main function of the vertex shader returns the output it sends to the +// pixel shader and receives it's input as a parameter. +VS_OUTPUT main(VS_INPUT input) { + // Declare a empty struct, that the vertex shader returns. + VS_OUTPUT output; + // Set the output position to the input position and set + // the w-component to 1, as the input position is a 3d vector and + // the output position a 4d vector. + output.position = float4(input.position, 1.0f); + // Multiply the output position step by step with the world, view and + // projection matrices. + output.position = mul(output.position, worldMatrix); + output.position = mul(output.position, viewMatrix); + output.position = mul(output.position, projectionMatrix); + // Pass the input color unchanged to the pixel shader. + output.color = input.color; + // Return the output struct to the pixel shader. + // The position value is automatically used as the vertex position. + return output; +} +``` + +**Pixel Shader** + +```cpp +// The pixel shader input struct must be the same as the vertex shader output! +struct PS_INPUT { + float4 position : POSITION; + float4 color : COLOR; +}; +// The pixel shader simply returns a 4d vector representing the vertex color. +// It receives it's input as a parameter just like the vertex shader. +// We have to declare the output semantic as color to it gets interpreted +// correctly. +float4 main(PS_INPUT input) : COLOR { + return input.color; +} +``` + +For more on semantics: [DirectX - Semantics](https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics#vertex-shader-semantics) + +Now we have to do quite some changes to the code. + +```cpp +ComPtr<IDirect3DDevice9> _device{ }; +ComPtr<IDirect3DVertexBuffer9> _vertexBuffer{ }; +ComPtr<IDirect3DIndexBuffer9> _indexBuffer{ }; +ComPtr<IDirect3DVertexDeclaration9> _vertexDecl{ }; +// We have to add a ComPtr for the vertex- and pixel shader, aswell as one +// for the constants (matrices) in our vertex shader. +ComPtr<IDirect3DVertexShader9> _vertexShader{ }; +ComPtr<IDirect3DPixelShader9> _pixelShader{ }; +ComPtr<ID3DXConstantTable> _vertexTable{ }; +// Declare the world and rotation matrix as global, because we use them in +// WinMain and SetupTransform now. +D3DXMATRIX _worldMatrix{ }; +D3DXMATRIX _rotationMatrix{ }; +// ... +bool SetupTransform() { + // Set the world and rotation matrix to an identity matrix. + D3DXMatrixIdentity(&_worldMatrix); + D3DXMatrixIdentity(&_rotationMatrix); + + D3DXMATRIX scaling{ }; + D3DXMatrixScaling(&scaling, 10, 10, 1); + D3DXMatrixMultiply(&_worldMatrix, &scaling, &_rotationMatrix); + // After multiplying the scalation and rotation matrix the have to pass + // them to the shader, by using a method from the constant table + // of the vertex shader. + HRESULT result{ }; + result = _vertexTable->SetMatrix( + _device.Get(), // direct3d device + "worldMatrix", // matrix name in the shader + &_worldMatrix); // pointer to the matrix + if (FAILED(result)) + return false; + + D3DXMATRIX view{ }; + D3DXMatrixLookAtLH(&view, &D3DXVECTOR3{ 0.0f, 0.0f, -20.0f }, + &D3DXVECTOR3{ 0.0f, 0.0f, 0.0f }, &D3DXVECTOR3{ 0.0f, 1.0f, 0.0f }); + // Do the same for the view matrix. + result = _vertexTable->SetMatrix( + _device.Get(), // direct 3d device + "viewMatrix", // matrix name + &view); // matrix + if (FAILED(result)) + return false; + + D3DXMATRIX projection{ }; + D3DXMatrixPerspectiveFovLH(&projection, D3DXToRadian(60.0f), + 1024.0f / 768.0f, 0.0f, 100.0f); + // And also for the projection matrix. + result = _vertexTable->SetMatrix( + _device.Get(), + "projectionMatrix", + &projection); + if (FAILED(result)) + return false; + + D3DXMatrixRotationY(&_rotationMatrix, D3DXToRadian(0.5f)); + return true; +} +// ... +// Vertex and index buffer creation aswell as initialization stay unchanged. +// ... +// After checking that shader model 3.0 is available we have to compile and +// create the shaders. +// Declare two temporary buffers storing the compiled shader code. +ID3DXBuffer* vertexShaderBuffer{ }; +ID3DXBuffer* pixelShaderBuffer{ }; +result = D3DXCompileShaderFromFile("vertex.hlsl", // shader name + nullptr, // macro definitions + nullptr, // special includes + "main", // entry point name + "vs_3_0", // shader model version + 0, // special flags + &vertexShaderBuffer, // code buffer + nullptr, // error message + &_vertexTable); // constant table +if (FAILED(result)) + return -1; +// After the vertex shader compile the pixel shader. +result = D3DXCompileShaderFromFile("pixel.hlsl", + nullptr, + nullptr, + "main", + "ps_3_0", // pixel shader model 3.0 + 0, + &pixelShaderBuffer, + nullptr, + nullptr); // no need for a constant table +if (FAILED(result)) + return -1; +// Create the vertex shader from the code buffer. +result = _device->CreateVertexShader( + (DWORD*)vertexShaderBuffer->GetBufferPointer(), // code buffer + &_vertexShader); // vertex shader pointer +if (FAILED(result)) + return -1; + +result = _device->CreatePixelShader( + (DWORD*)pixelShaderBuffer->GetBufferPointer(), + &_pixelShader); +if (FAILED(result)) + return -1; +// Release the temporary code buffers after the shaders are created. +vertexShaderBuffer->Release(); +pixelShaderBuffer->Release(); +// Apply the vertex- and pixel shader. +_device->SetVertexShader(_vertexShader.Get()); +_device->SetPixelShader(_pixelShader.Get()); +// Apply the transform after the shaders have been set. +if (!SetupTransform()) + return -1; +// You can also REMOVE the call so set the lighting render state. +_device->SetRenderState(D3DRS_LIGHTING, false); +``` + +You can find the complete code here: [DirectX - 3](https://pastebin.com/y4NrvawY) + +## Texturing + +```cpp +// First we need to declare a ComPtr for the texture. +ComPtr<IDirect3DTexture9> _texture{ }; +// Then we have to change the vertex struct. +struct VStruct { + float x, y, z; + float u, v; // Add texture u and v coordinates + D3DCOLOR color; +}; +// In the vertex declaration we have to add the texture coordinates. +// the top left of the texture is u: 0, v: 0. +std::vector<VStruct> vertices { + VStruct{ -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, ... }, // bottom left + VStruct{ -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, ... }, // top left + VStruct{ 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, ... }, // top right + VStruct{ 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, ... } // bottom right +}; +// Next is the vertex declaration. +std::vector<D3DVERTEXELEMENT9> vertexDecl{ + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + // Add a 2d float vector used for texture coordinates. + {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + // The color offset is not (3 + 2) * sizeof(float) = 20 bytes + {0, 20, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() +}; +// Now we have to load the texture and pass its to the shader. +// ... +_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); +// Create a Direct3D texture from a png file. +result = D3DXCreateTextureFromFile(_device.Get(), // direct3d device + "texture.png", // texture path + &_texture); // receiving texture pointer +if (FAILED(result)) + return -1; +// Attach the texture to shader stage 0, which is equal to texture register 0 +// in the pixel shader. +_device->SetTexture(0, _texture.Get()); +``` + +With the main code ready we now have to adjust the shaders to these changes. + +**Vertex Shader** + +```cpp +float4x4 projectionMatrix; +float4x4 viewMatrix; +float4x4 worldMatrix; +// Add the texture coordinates to the vertex shader in- and output. +struct VS_INPUT { + float3 position : POSITION; + float2 texcoord : TEXCOORD; + float4 color : COLOR; +}; + +struct VS_OUTPUT { + float4 position : POSITION; + float2 texcoord : TEXCOORD; + float4 color : COLOR; +}; + +VS_OUTPUT main(VS_INPUT input) { + VS_OUTPUT output; + + output.position = float4(input.position, 1.0f); + output.position = mul(output.position, worldMatrix); + output.position = mul(output.position, viewMatrix); + output.position = mul(output.position, projectionMatrix); + + output.color = input.color; + // Set the texcoord output to the input. + output.texcoord = input.texcoord; + + return output; +} +``` + +**Pixel Shader** + +```cpp +// Create a sampler called "sam0" using sampler register 0, which is equal +// to the texture stage 0, to which we passed the texture. +sampler sam0 : register(s0); + +struct PS_INPUT { + float4 position : POSITION; + float2 texcoord : TEXCOORD; + float4 color : COLOR; +}; + +float4 main(PS_INPUT input) : COLOR{ + // Do a linear interpolation between the texture color and the input color + // using 75% of the input color. + // tex2D returns the texture data at the specified texture coordinate. + return lerp(tex2D(sam0, input.texcoord), input.color, 0.75f); +} +``` + +## Quotes +<sup>[1]</sup>[DirectX - Wikipedia](https://en.wikipedia.org/wiki/DirectX) diff --git a/mercury.html.markdown b/mercury.html.markdown new file mode 100644 index 00000000..f749bac4 --- /dev/null +++ b/mercury.html.markdown @@ -0,0 +1,263 @@ +--- +language: mercury +contributors: + - ["Julian Fondren", "https://mercury-in.space/"] +--- + +Mercury is a strict, pure functional/logic programming language, with +influences from Prolog, ML, and Haskell. + +```prolog +% Percent sign starts a one-line comment. + + % foo(Bar, Baz) + % + % Documentation comments are indented before what they describe. +:- pred foo(bar::in, baz::out) is det. + +% All toplevel syntax elements end with a '.' -- a full stop. + +% Mercury terminology comes from predicate logic. Very roughly: + +% | Mercury | C | +% | | | +% | Goal | statement | +% | expression | expression | +% | predicate rule | void function | +% | function rule | function | +% | head (of a rule) | function name and parameters | +% | body (of a rule) | function body | +% | fact | (rule without a body) | +% | pred/func declaration | function signature | +% | A, B (conjunction) | A && B | +% | A ; B (disjunction) | if (A) {} else if (B) {} | + +% some facts: +man(socrates). % "it is a fact that Socrates is a man" +man(plato). +man(aristotle). + +% a rule: +mortal(X) :- man(X). % "It is a rule that X is a mortal if X is a man." +% ^^^^^^-- the body of the rule +% ^^-- an arrow <--, pointing to the head from the body +%^^^^^^^^-- the head of the rule +% this is also a single clause that defines the rule. + +% that X is capitalized is how you know it's a variable. +% that socrates is uncapitalized is how you know it's a term. + +% it's an error for 'socrates' to be undefined. It must have a type: + +% declarations begin with ':-' +:- type people + ---> socrates + ; plato + ; aristotle + ; hermes. + %<--first tab stop (using 4-space tabs) + %<--third tab stop (first after --->) + +:- pred man(people). % rules and facts also require types + +% a rule's modes tell you how it can be used. +:- mode man(in) is semidet. % man(plato) succeeds. man(hermes) fails. +:- mode man(out) is multi. % man(X) binds X to one of socrates ; plato ; aristotle + +% a semidet predicate is like a test. It doesn't return a value, but +% it can succeed or fail, triggering backtracking or the other side of +% a disjunction or conditional. + +% 'is semidet' provides the determinism of a mode. Other determinisms: +% | Can fail? | 0 solutions | 1 | more than 1 | +% | | | | | +% | no | erroneous | det | multi | +% | yes | failure | semidet | nondet | + +:- pred mortal(people::in) is semidet. % type/mode in one declaration + +% this rule's body consists of two conjunctions: A, B, C +% this rule is true if A, B, and C are all true. +% if age(P) returns 16, it fails. +% if alive(P) fails, it fails. +:- type voter(people::in) is semidet. +voter(P) :- + alive(P), + registered(P, locale(P)), + age(P) >= 18. % age/1 is a function; int.>= is a function used as an operator + +% "a P is a voter if it is alive, is registered in P's locale, and if +% P's age is 18 or older." + +% the >= used here is provided by the 'int' module, which isn't +% imported by default. Mercury has a very small 'Prelude' (the +% 'builtin' module). You even need to import the 'list' module if +% you're going to use list literals. +``` + +Complete runnable example. File in 'types.m'; compile with 'mmc --make types'. + +```prolog +:- module types. +:- interface. +:- import_module io. % required for io.io types in... +% main/2 is usually 'det'. threading and exceptions require 'cc_multi' +:- pred main(io::di, io::uo) is cc_multi. % program entry point +:- implementation. +:- import_module int, float, string, list, bool, map, exception. + +% enum. +:- type days + ---> sunday + ; monday + ; tuesday + ; wednesday + ; thursday + ; friday + ; saturday. + +% discriminated union, like datatype in ML. +:- type payment_method + ---> cash(int) + ; credit_card( + name :: string, % named fields + cc_number :: string, + cvv :: int, + expiration :: string + ) + ; crypto(coin_type, wallet, amount). + +:- type coin_type + ---> etherium + ; monero. % "other coins are available" + +% type aliases. +:- type wallet == string. +:- type amount == int. + +% !IO is the pair of io.io arguments +% pass it to anything doing I/O, in order to perform I/O. +% many otherwise-impure functions can 'attach to the I/O state' by taking !IO +main(!IO) :- + Ints = [ + 3, + 1 + 1, + 8 - 1, + 10 * 2, + 35 / 5, + 5 / 2, % truncating division + int.div(5, 2), % floored division + div(5, 2), % (module is unambiguous due to types) + 5 `div` 2, % (any binary function can be an operator with ``) + 7 `mod` 3, % modulo of floored division + 7 `rem` 3, % remainder of truncating division + 2 `pow` 4, % 2 to the 4th power + (1 + 3) * 2, % parens have their usual meaning + + 2 >> 3, % bitwise right shift + 128 << 3, % bitwise left shift + \ 0, % bitwise complement + 5 /\ 1, % bitwise and + 5 \/ 1, % bitwise or + 5 `xor` 3, % bitwise xor + + max_int, + min_int, + + 5 `min` 3, % ( if 5 > 3 then 3 else 5 ) + 5 `max` 3 + ], + Bools = [ + yes, + no + % bools are much less important in Mercury because control flow goes by + % semidet goals instead of boolean expressions. + ], + Strings = [ + "this is a string", + "strings can have "" embedded doublequotes via doubling", + "strings support \u4F60\u597D the usual escapes\n", + % no implicit concatenation of strings: "concat:" "together" + "but you can " ++ " use the string.++ operator", + + % second param is a list(string.poly_type) + % s/1 is a function that takes a string and returns a poly_type + % i/1 takes an int. f/1 takes a float. c/1 takes a char. + string.format("Hello, %d'th %s\n", [i(45), s("World")]) + ], + + % start with purely functional types like 'map' and 'list'! + % arrays and hash tables are available too, but using them + % requires knowing a lot more about Mercury + get_map1(Map1), + get_map2(Map2), + + % list.foldl has *many* variations + % this one calls io.print_line(X, !IO) for each X of the list + foldl(io.print_line, Ints, !IO), + foldl(io.print_line, Bools, !IO), + foldl(io.print_line, Strings, !IO), + io.print_line(Map1, !IO), + % ( if Cond then ThenGoal else ElseGoal ) + % I/O not allowed in Cond: I/O isn't allowed to fail! + ( if Map2^elem(42) = Elem then + io.print_line(Elem, !IO) + else % always required + true % do nothing, successfully (vs. 'fail') + ), + + % exception handling: + ( try [io(!IO)] ( % io/1 param required or no I/O allowed here + io.print_line(received(cash(1234)), !IO), + io.print_line(received(crypto(monero, "invalid", 123)), !IO) + ) then + io.write_string("all payments accepted\n", !IO) % never reached + catch "monero not yet supported" -> % extremely specific catch! + io.write_string("monero payment failed\n", !IO) + ). + +:- pred get_map1(map(string, int)::out) is det. +get_map1(!:Map) :- % !:Map in the head is the final (free, unbound) Map + !:Map = init, % !:Map in the body is the next Map + det_insert("hello", 1, !Map), % pair of Map vars + det_insert("world", 2, !Map), + + % debug print of current (bound) Map + % other [Params] can make it optional per runtime or compiletime flags + trace [io(!IO)] (io.print_line(!.Map, !IO)), + + det_insert_from_corresponding_lists(K, V, !Map), + % this code is reordered so that K and V and defined prior to their use + K = ["more", "words", "here"], + V = [3, 4, 5]. + +:- pred get_map2(map(int, bool)::out) is det. +get_map2(Map) :- + det_insert(42, yes, map.init, Map). + +:- func received(payment_method) = string. +received(cash(N)) = string.format("received %d dollars", [i(N)]). +received(credit_card(_, _, _, _)) = "received credit card". % _ is throwaway +received(crypto(Type, _Wallet, Amount)) = S :- % _Wallet is named throwaway + ( % case/switch structure + Type = etherium, + S = string.format("receiving %d ETH", [i(Amount)]) + ; + Type = monero, + throw("monero not yet supported") % exception with string as payload + ). +``` + +## That was quick! Want more? + +### More Tutorials + +* [Mercury Tutorial](https://mercurylang.org/documentation/papers/book.pdf) (pdf link) - a more traditional tutorial with a more relaxed pace +* [Mercury Crash Course](https://mercury-in.space/crash.html) - a dense example-driven tutorial with Q&A format +* [Github Wiki Tutorial](https://github.com/Mercury-Language/mercury/wiki/Tutorial) +* [Getting Started with Mercury](https://bluishcoder.co.nz/2019/06/23/getting-started-with-mercury.html) - installation and your first steps + +### Documentation + +* Language manual, user's guide, and library reference are all at + [mercurylang.org](https://mercurylang.org/documentation/documentation.html) diff --git a/tr-tr/clojure-tr.html.markdown b/tr-tr/clojure-tr.html.markdown index 64970945..5ebe5ce6 100644 --- a/tr-tr/clojure-tr.html.markdown +++ b/tr-tr/clojure-tr.html.markdown @@ -4,6 +4,7 @@ lang: tr-tr filename: learnclojure-tr.clj contributors: - ["Adam Bard", "http://adambard.com/"] + - ["Seçkin KÜKRER", "https://leavenha.github.io"] translators: - ["Seçkin KÜKRER", "https://leavenha.github.io"] --- diff --git a/tr-tr/edn-tr.html.markdown b/tr-tr/edn-tr.html.markdown new file mode 100644 index 00000000..9a2ac1ff --- /dev/null +++ b/tr-tr/edn-tr.html.markdown @@ -0,0 +1,157 @@ +--- +language: edn +filename: learnedn-tr.edn +lang: tr-tr +contributors: + - ["Seçkin KÜKRER", "https://github.com/LeaveNhA"] +--- + +# Y = 20 Dakika. + +### Genişletilebilir Veri Notasyonu (EDN, Extensible Data Notation). + +### Okunuşu: (Türkçe: ey-di-en), (English: eed-n) + +### Kodlama Türü: UTF-8 + +EDN Clojure sözdiziminin bir alt kümesidir. Bu alt küme, amacı gereği kod barındırmaz. Ve kendisi bir tip sistemi değildir. Bir şeması da yoktur. En basit tabirle; Genişletilebilir Veri Notasyonu kabul edilebilir elemanların bir kümesidir. + +EDN elementleri, akışları ve dosyaları UTF-8 kullanılarak kodlanmalıdır. Üstelik, dökümanı çevreleyen işaretçiler de olmadığı için akış, dağıtık programlama mesaj arayüzü ve diğer dinamik sistemler için idealdir. + + +```clojure +; Yorumlar, yorumlarımız, noktalı virgül ile başlıyor. +;; Genellikle ikili olarak kullanılıyorlar. + +;; |--------------------------------| +; |--------- Genel Yapısı ---------| +;; |--------------------------------| + +;; Boşluklar --whitespaces--, elementler için en yaygın ayıraçtır. +"Mustafa" "Kemal" "ATATÜRK" +;; Fakat okunuşu arttırdığı gerekçesiyle "," (virgüller --commas--) EDN yorumlayıcısı tarafından görmezden gelinir ve boşluk olarak nitelendirilir. +"Mustafa","Kemal","PAŞA" +;; Üstelik bu yenilikçi sözdizimsel kurala rağmen, {}, [] () gibi koleksiyon karakterlerini ayırmak için boşluğa ya da boşluğa çözümlenen virgüle ihtiyacınız yoktur. +[["MUSTAFA"] ["KEMAL"] [[{"ATA" "ATATÜRK"}]]] +;; Üst düzey vektör elemanlarını birbirinden ayıran boşlukları da kaldırabilirsiniz. +;; Fakat bu size, okunması zor bir vektör dışında hiç bir şey vermeyecektir. + +;; |--------------------------------| +; |-------- Atomik Yapılar --------| +;; |--------------------------------| + +; Mantıksal Değerler +;; Mantıksal Doğru, çoğu teknolojide aynı gösterimi var. +true +;; Mantıksal Yanlış. +false + +; Karakter Katarları +;; Karakter katarları, --SADECE-- çift tırnak ile belirtilebilir. +"İzmirin dağlarında çiçekler açar!" +;; C, C++, Java v.b. gibi dillerin desteklediği kaçış sekanslarını da destekler. +"Altın güneş orda sırmalar saçar.\nBozulmuş düşmanlar yel gibi kaçar." +;; Kaçış sekansları için bknz: $!$ + +; Karakter Sabitleri +;; Karakter sabitleri önlerinde bir ters eğik çizgi ile temsil edilirler. +\T \Ü \R \K +;; Üstelik, belirli kaçıl sekanslarının da karşılığı Karakter Sabiti olarak var. +\newline \return + +; Anahtar Kelimeler +;; Anahtar Kelimeler, önlerinde bir ":" iki nokta --colon-- +:yımırta +:kaşar +:bıngıl + +; Semboller +;; Semboller tanımlayıcıları temsil etmek için kullanılır. +;; "/" karakteri, Sembol Sabitlerinde isim-uzayı ayıracı olarak kullanılıyor. +izmir/kızları +;; "mutfak" isim uzayındaki "ekmek-bıçağı" isimli sembole çözümlenir. + +banyo/fayans +parke +laminat + +; Sayısal Değerler +;; Tam Sayı sabiti. +1991 +;; Kayan Noktalı Sabiti. +19.67 + +; Listeler +;; Listeler, yukarıdaki temel tiplerin ardışıklanmasıdır. +(bomba :bomba nokta \c \o \m) + +; Vektörler +;; Vektörler bir bakıma Listelere benzeseler de, bir çok açıdan farklıdırlar. +;; Mesela Listenin aksine Vektörler, Rastgele Erişime imkan verir. +[[] "şimdi" "asker"] + +; Eşlemeler +;; Sıfır veya daha fazla Anahtar-Değer çifti kabul eder. +;; Not: Clojure Veri Yapıları Soyutlaması ile Eşlemeler de, teknik olarak ardışık olarak işlenebilir. +{:canı :neler-ister? + :uykuda "mevlam"} +;; Bu ve diğer tüm Veri Yapıları Homojendir, birbirilerini barındırabilir, kapsayabilir, içerebilirler. +;; Ayrıca okunurluk gibi farklı sebeplerle virgül kullanımında özgürsünüz. +{{:id_ "129u391824981237981237" :kim "BEN"}, göster!} + +; Kümeler +;; Kümeler eşsiz eleman barındıran bir yapıdır. +;; Matematikteki karşılığını veriyor dersek yanlış olmaz. +#{:sen 3 milyar 750 milyon} + +;; |--------------------------------| +; |------ Etiketli Elemanlar ------| +;; |--------------------------------| + +;; EDN (Genişletilebilir Veri Notasyonu), # sembolü ile genişletilebilir. + +#benimuygulamam/bağlantı {:içerik "Y dakikada EDN Öğren" :url "https://learnxinyminutes.com/docs/tr-tr/edn-tr" :tıhlama-aksiyonu yırrttılll!} + +;; Ve bu yapıyı yorumlayacak bir de yapı gerekiyor. +(defn ->bağlantı [props] + (str "<a href='" (:url props) "'" ">" + (:içerik props) + "</a>")) + +;; Bu örnekte yorumlayıcıya, basit bir fonksiyon veriyoruz. +;; `clojure.edn/read-string` aslında bir ayarlar Eşlemesi kabul ediyor. +;; (Bu tür fonksiyon genişlemeleri, Clojure ekosisteminde yaygındır.) + +(clojure.edn/read-string + {:readers {'benimuygulamam/bağlantı ->bağlantı}} + "#benimuygulamam/bağlantı {:içerik \"Y dakikada EDN Öğren\" :url \"https://learnxinyminutes.com/docs/tr-tr/edn-tr\" :tıhlama-aksiyonu yırrttılll!}") +;=> "<a href='https://learnxinyminutes.com/docs/tr-tr/edn-tr'>Y dakikada EDN Öğren</a>" + +;; |--------------------------------| +; |--- Ön Tanımlı Genişletmeler ---| +;; |--------------------------------| + +; Tarih Etiketi +;; Bu etiket `inst` ön-ekinden sonra bir RFC-3339 formatında bir karakter katarı beklemektedir. +#inst "2013-10-21T14:50:00+00:00" ; => Formatlanmış bir şekilde: 21/10/2013 14:50:00 + +; UUID Etiketi +;; Bu etiket `uuid` ön-ekinden sonra bir UUID karşılığını karakter katarı olarak kabul eder. +#uuid "11k12fae-7d3c-11k0-a765-0010ckke6hgk" + +``` + +# Son Ek +Bu içerik, EDN'i tanıtmakta kısıtlı bir açıyla, özet bilgiler sunmaktadır. +Fakat, Clojure ve diğer Veri Odaklı dillerde, Verinin yolculuğunu anlamak için önemli bir rol oynamaktadır. +EDN'in var olan probleme çözümü ve artı/eksilerinin doğru şekilde kavranması mühimdir. +Ben bu dökümanı hazırlarken, EDN ve gerçek dünya kullanımını anlatan yoktu. Fakat ümidim, Clojure ve diğer teknolojiler üzerinde kullanımının artmasından sonra birinin bu ihtiyacı giderecek özgün kaynak çıkarmasıdır. + +Başarılar! + +# Referanslar + +- [EDN Formatı Standardı](https://github.com/edn-format/edn) +- [Gerçeklemeler](https://github.com/edn-format/edn/wiki/Implementations) +- [Etiketlenmiş Elementler](http://www.compoundtheory.com/clojure-edn-walkthrough/) +- [Clojure.Docs EDN İçeriği](https://clojuredocs.org/clojure.edn) |