Convert \r\n to \n

This commit is contained in:
Boris Verkhovskiy 2024-04-04 00:27:01 -07:00
parent 4ab1be1be5
commit 818b8eec46
18 changed files with 6767 additions and 6767 deletions

View File

@ -1,212 +1,212 @@
---
category: tool
tool: amd
contributors:
- ["Frederik Ring", "https://github.com/m90"]
filename: learnamd.js
---
## Getting Started with AMD
The **Asynchronous Module Definition** API specifies a mechanism for defining
JavaScript modules such that the module and its dependencies can be asynchronously
loaded. This is particularly well suited for the browser environment where
synchronous loading of modules incurs performance, usability, debugging, and
cross-domain access problems.
### Basic concept
```javascript
// The basic AMD API consists of nothing but two methods: `define` and `require`
// and is all about module definition and consumption:
// `define(id?, dependencies?, factory)` defines a module
// `require(dependencies, callback)` imports a set of dependencies and
// consumes them in the passed callback
// Let's start by using define to define a new named module
// that has no dependencies. We'll do so by passing a name
// and a factory function to define:
define('awesomeAMD', function(){
var isAMDAwesome = function(){
return true;
};
// The return value of a module's factory function is
// what other modules or require calls will receive when
// requiring our `awesomeAMD` module.
// The exported value can be anything, (constructor) functions,
// objects, primitives, even undefined (although that won't help too much).
return isAMDAwesome;
});
// Now, let's define another module that depends upon our `awesomeAMD` module.
// Notice that there's an additional argument defining our
// module's dependencies now:
define('loudmouth', ['awesomeAMD'], function(awesomeAMD){
// dependencies will be passed to the factory's arguments
// in the order they are specified
var tellEveryone = function(){
if (awesomeAMD()){
alert('This is sOoOo rad!');
} else {
alert('Pretty dull, isn\'t it?');
}
};
return tellEveryone;
});
// As we do know how to use define now, let's use `require` to
// kick off our program. `require`'s signature is `(arrayOfDependencies, callback)`.
require(['loudmouth'], function(loudmouth){
loudmouth();
});
// To make this tutorial run code, let's implement a very basic
// (non-asynchronous) version of AMD right here on the spot:
function define(name, deps, factory){
// notice how modules without dependencies are handled
define[name] = require(factory ? deps : [], factory || deps);
}
function require(deps, callback){
var args = [];
// first let's retrieve all the dependencies needed
// by the require call
for (var i = 0; i < deps.length; i++){
args[i] = define[deps[i]];
}
// satisfy all the callback's dependencies
return callback.apply(null, args);
}
// you can see this code in action here: http://jsfiddle.net/qap949pd/
```
### Real-world usage with require.js
In contrast to the introductory example, `require.js` (the most popular AMD library) actually implements the **A** in **AMD**, enabling you to load modules and their dependencies asynchronously via XHR:
```javascript
/* file: app/main.js */
require(['modules/someClass'], function(SomeClass){
// the callback is deferred until the dependency is loaded
var thing = new SomeClass();
});
console.log('So here we are, waiting!'); // this will run first
```
By convention, you usually store one module in one file. `require.js` can resolve module names based on file paths, so you don't have to name your modules, but can simply reference them using their location. In the example `someClass` is assumed to be in the `modules` folder, relative to your configuration's `baseUrl`:
* app/
* main.js
* modules/
* someClass.js
* someHelpers.js
* ...
* daos/
* things.js
* ...
This means we can define `someClass` without specifying a module id:
```javascript
/* file: app/modules/someClass.js */
define(['daos/things', 'modules/someHelpers'], function(thingsDao, helpers){
// module definition, of course, will also happen asynchronously
function SomeClass(){
this.method = function(){/**/};
// ...
}
return SomeClass;
});
```
To alter the default path mapping behavior use `requirejs.config(configObj)` in your `main.js`:
```javascript
/* file: main.js */
requirejs.config({
baseUrl : 'app',
paths : {
// you can also load modules from other locations
jquery : '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min',
coolLibFromBower : '../bower_components/cool-lib/coollib'
}
});
require(['jquery', 'coolLibFromBower', 'modules/someHelpers'], function($, coolLib, helpers){
// a `main` file needs to call require at least once,
// otherwise no code will ever run
coolLib.doFancyStuffWith(helpers.transform($('#foo')));
});
```
`require.js`-based apps will usually have a single entry point (`main.js`) that is passed to the `require.js` script tag as a data-attribute. It will be automatically loaded and executed on pageload:
```html
<!DOCTYPE html>
<html>
<head>
<title>A hundred script tags? Never again!</title>
</head>
<body>
<script src="require.js" data-main="app/main"></script>
</body>
</html>
```
### Optimizing a whole project using r.js
Many people prefer using AMD for sane code organization during development, but still want to ship a single script file in production instead of performing hundreds of XHRs on page load.
`require.js` comes with a script called `r.js` (that you will probably run in node.js, although Rhino is supported too) that can analyse your project's dependency graph, and build a single file containing all your modules (properly named), minified and ready for consumption.
Install it using `npm`:
```shell
$ npm install requirejs -g
```
Now you can feed it with a configuration file:
```shell
$ r.js -o app.build.js
```
For our above example the configuration might look like:
```javascript
/* file : app.build.js */
({
name : 'main', // name of the entry point
out : 'main-built.js', // name of the file to write the output to
baseUrl : 'app',
paths : {
// `empty:` tells r.js that this should still be loaded from the CDN, using
// the location specified in `main.js`
jquery : 'empty:',
coolLibFromBower : '../bower_components/cool-lib/coollib'
}
})
```
To use the built file in production, simply swap `data-main`:
```html
<script src="require.js" data-main="app/main-built"></script>
```
An incredibly detailed [overview of build options](https://github.com/jrburke/r.js/blob/master/build/example.build.js) is available in the GitHub repo.
### Topics not covered in this tutorial
* [Loader plugins / transforms](http://requirejs.org/docs/plugins.html)
* [CommonJS style loading and exporting](http://requirejs.org/docs/commonjs.html)
* [Advanced configuration](http://requirejs.org/docs/api.html#config)
* [Shim configuration (loading non-AMD modules)](http://requirejs.org/docs/api.html#config-shim)
* [CSS loading and optimizing with require.js](http://requirejs.org/docs/optimization.html#onecss)
* [Using almond.js for builds](https://github.com/jrburke/almond)
### Further reading:
* [Official Spec](https://github.com/amdjs/amdjs-api/wiki/AMD)
* [Why AMD?](http://requirejs.org/docs/whyamd.html)
* [Universal Module Definition](https://github.com/umdjs/umd)
### Implementations:
* [require.js](http://requirejs.org)
* [dojo toolkit](http://dojotoolkit.org/documentation/tutorials/1.9/modules/)
* [cujo.js](http://cujojs.com/)
* [curl.js](https://github.com/cujojs/curl)
* [lsjs](https://github.com/zazl/lsjs)
* [mmd](https://github.com/alexlawrence/mmd)
---
category: tool
tool: amd
contributors:
- ["Frederik Ring", "https://github.com/m90"]
filename: learnamd.js
---
## Getting Started with AMD
The **Asynchronous Module Definition** API specifies a mechanism for defining
JavaScript modules such that the module and its dependencies can be asynchronously
loaded. This is particularly well suited for the browser environment where
synchronous loading of modules incurs performance, usability, debugging, and
cross-domain access problems.
### Basic concept
```javascript
// The basic AMD API consists of nothing but two methods: `define` and `require`
// and is all about module definition and consumption:
// `define(id?, dependencies?, factory)` defines a module
// `require(dependencies, callback)` imports a set of dependencies and
// consumes them in the passed callback
// Let's start by using define to define a new named module
// that has no dependencies. We'll do so by passing a name
// and a factory function to define:
define('awesomeAMD', function(){
var isAMDAwesome = function(){
return true;
};
// The return value of a module's factory function is
// what other modules or require calls will receive when
// requiring our `awesomeAMD` module.
// The exported value can be anything, (constructor) functions,
// objects, primitives, even undefined (although that won't help too much).
return isAMDAwesome;
});
// Now, let's define another module that depends upon our `awesomeAMD` module.
// Notice that there's an additional argument defining our
// module's dependencies now:
define('loudmouth', ['awesomeAMD'], function(awesomeAMD){
// dependencies will be passed to the factory's arguments
// in the order they are specified
var tellEveryone = function(){
if (awesomeAMD()){
alert('This is sOoOo rad!');
} else {
alert('Pretty dull, isn\'t it?');
}
};
return tellEveryone;
});
// As we do know how to use define now, let's use `require` to
// kick off our program. `require`'s signature is `(arrayOfDependencies, callback)`.
require(['loudmouth'], function(loudmouth){
loudmouth();
});
// To make this tutorial run code, let's implement a very basic
// (non-asynchronous) version of AMD right here on the spot:
function define(name, deps, factory){
// notice how modules without dependencies are handled
define[name] = require(factory ? deps : [], factory || deps);
}
function require(deps, callback){
var args = [];
// first let's retrieve all the dependencies needed
// by the require call
for (var i = 0; i < deps.length; i++){
args[i] = define[deps[i]];
}
// satisfy all the callback's dependencies
return callback.apply(null, args);
}
// you can see this code in action here: http://jsfiddle.net/qap949pd/
```
### Real-world usage with require.js
In contrast to the introductory example, `require.js` (the most popular AMD library) actually implements the **A** in **AMD**, enabling you to load modules and their dependencies asynchronously via XHR:
```javascript
/* file: app/main.js */
require(['modules/someClass'], function(SomeClass){
// the callback is deferred until the dependency is loaded
var thing = new SomeClass();
});
console.log('So here we are, waiting!'); // this will run first
```
By convention, you usually store one module in one file. `require.js` can resolve module names based on file paths, so you don't have to name your modules, but can simply reference them using their location. In the example `someClass` is assumed to be in the `modules` folder, relative to your configuration's `baseUrl`:
* app/
* main.js
* modules/
* someClass.js
* someHelpers.js
* ...
* daos/
* things.js
* ...
This means we can define `someClass` without specifying a module id:
```javascript
/* file: app/modules/someClass.js */
define(['daos/things', 'modules/someHelpers'], function(thingsDao, helpers){
// module definition, of course, will also happen asynchronously
function SomeClass(){
this.method = function(){/**/};
// ...
}
return SomeClass;
});
```
To alter the default path mapping behavior use `requirejs.config(configObj)` in your `main.js`:
```javascript
/* file: main.js */
requirejs.config({
baseUrl : 'app',
paths : {
// you can also load modules from other locations
jquery : '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min',
coolLibFromBower : '../bower_components/cool-lib/coollib'
}
});
require(['jquery', 'coolLibFromBower', 'modules/someHelpers'], function($, coolLib, helpers){
// a `main` file needs to call require at least once,
// otherwise no code will ever run
coolLib.doFancyStuffWith(helpers.transform($('#foo')));
});
```
`require.js`-based apps will usually have a single entry point (`main.js`) that is passed to the `require.js` script tag as a data-attribute. It will be automatically loaded and executed on pageload:
```html
<!DOCTYPE html>
<html>
<head>
<title>A hundred script tags? Never again!</title>
</head>
<body>
<script src="require.js" data-main="app/main"></script>
</body>
</html>
```
### Optimizing a whole project using r.js
Many people prefer using AMD for sane code organization during development, but still want to ship a single script file in production instead of performing hundreds of XHRs on page load.
`require.js` comes with a script called `r.js` (that you will probably run in node.js, although Rhino is supported too) that can analyse your project's dependency graph, and build a single file containing all your modules (properly named), minified and ready for consumption.
Install it using `npm`:
```shell
$ npm install requirejs -g
```
Now you can feed it with a configuration file:
```shell
$ r.js -o app.build.js
```
For our above example the configuration might look like:
```javascript
/* file : app.build.js */
({
name : 'main', // name of the entry point
out : 'main-built.js', // name of the file to write the output to
baseUrl : 'app',
paths : {
// `empty:` tells r.js that this should still be loaded from the CDN, using
// the location specified in `main.js`
jquery : 'empty:',
coolLibFromBower : '../bower_components/cool-lib/coollib'
}
})
```
To use the built file in production, simply swap `data-main`:
```html
<script src="require.js" data-main="app/main-built"></script>
```
An incredibly detailed [overview of build options](https://github.com/jrburke/r.js/blob/master/build/example.build.js) is available in the GitHub repo.
### Topics not covered in this tutorial
* [Loader plugins / transforms](http://requirejs.org/docs/plugins.html)
* [CommonJS style loading and exporting](http://requirejs.org/docs/commonjs.html)
* [Advanced configuration](http://requirejs.org/docs/api.html#config)
* [Shim configuration (loading non-AMD modules)](http://requirejs.org/docs/api.html#config-shim)
* [CSS loading and optimizing with require.js](http://requirejs.org/docs/optimization.html#onecss)
* [Using almond.js for builds](https://github.com/jrburke/almond)
### Further reading:
* [Official Spec](https://github.com/amdjs/amdjs-api/wiki/AMD)
* [Why AMD?](http://requirejs.org/docs/whyamd.html)
* [Universal Module Definition](https://github.com/umdjs/umd)
### Implementations:
* [require.js](http://requirejs.org)
* [dojo toolkit](http://dojotoolkit.org/documentation/tutorials/1.9/modules/)
* [cujo.js](http://cujojs.com/)
* [curl.js](https://github.com/cujojs/curl)
* [lsjs](https://github.com/zazl/lsjs)
* [mmd](https://github.com/alexlawrence/mmd)

File diff suppressed because it is too large Load Diff

View File

@ -1,423 +1,423 @@
---
language: Elixir
contributors:
- ["Joao Marques", "http://github.com/mrshankly"]
translators:
- ["Gregor Große-Bölting", "http://www.ideen-und-soehne.de"]
filename: learnelixir-de.ex
lang: de-de
---
Elixir ist eine moderne, funktionale Sprache für die Erlang VM. Sie ist voll
kompatibel mit Erlang, verfügt aber über eine freundlichere Syntax und bringt
viele Features mit.
```ruby
# Einzeilige Kommentare werden mit der Raute gesetzt.
# Es gibt keine mehrzeiligen Kommentare;
# es ist aber problemlos möglich mehrere einzeilige Kommentare hintereinander
# zu setzen (so wie hier).
# Mit 'iex' ruft man die Elixir-Shell auf.
# Zum kompilieren von Modulen dient der Befehl 'elixirc'.
# Beide Befehle sollten als Umgebungsvariable gesetzt sein, wenn Elixir korrekt
# installiert wurde.
## ---------------------------
## -- Basistypen
## ---------------------------
# Es gibt Nummern:
3 # Integer
0x1F # Integer
3.0 # Float
# Für bessere Lesbarkeit des Codes können Unterstriche "_" als Trennzeichen verwendet werden
1_000_000 == 1000000 # Integer
1_000.567 == 1000.567 # Float
# Atome, das sind Literale, sind Konstanten mit Namen. Sie starten mit einem
# ':'.
:hello # Atom
# Außerdem gibt es Tupel, deren Werte im Arbeitsspeicher vorgehalten werden.
{1,2,3} # Tupel
# Die Werte innerhalb eines Tupels können mit der 'elem'-Funktion ausgelesen
# werden:
elem({1, 2, 3}, 0) # => 1
# Listen sind als verkettete Listen implementiert.
[1, 2, 3] # list
# Auf Kopf und Rest einer Liste kann wie folgt zugegriffen werden:
[ kopf | rest ] = [1,2,3]
kopf # => 1
rest # => [2, 3]
# In Elixir, wie auch in Erlang, kennzeichnet '=' ein 'pattern matching'
# (Musterabgleich) und keine Zuweisung.
# Das heißt, dass die linke Seite auf die rechte Seite 'abgeglichen' wird.
# Auf diese Weise kann im Beispiel oben auf Kopf und Rest der Liste zugegriffen
# werden.
# Ein Musterabgleich wird einen Fehler werfen, wenn die beiden Seiten nicht
# zusammenpassen.
# Im folgenden Beispiel haben die Tupel eine unterschiedliche Anzahl an
# Elementen:
{a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2}
# Es gibt außerdem 'binaries',
<<1,2,3>> # binary.
# Strings und 'char lists'
"hello" # String
'hello' # Char-Liste
# ... und mehrzeilige Strings
"""
Ich bin ein
mehrzeiliger String.
"""
#=> "Ich bin ein\nmehrzeiliger String.\n"
# Alles Strings werden in UTF-8 enkodiert:
"héllò" #=> "héllò"
# Eigentlich sind Strings in Wahrheit nur binaries und 'char lists' einfach
# Listen.
<<?a, ?b, ?c>> #=> "abc"
[?a, ?b, ?c] #=> 'abc'
# In Elixir gibt `?a` den ASCII-Integer für den Buchstaben zurück.
?a #=> 97
# Um Listen zu verbinden gibt es den Operator '++', für binaries nutzt man '<>'
[1,2,3] ++ [4,5] #=> [1,2,3,4,5]
'hello ' ++ 'world' #=> 'hello world'
<<1,2,3>> <> <<4,5>> #=> <<1,2,3,4,5>>
"hello " <> "world" #=> "hello world"
## ---------------------------
## -- Operatoren
## ---------------------------
# Einfache Arithmetik
1 + 1 #=> 2
10 - 5 #=> 5
5 * 2 #=> 10
10 / 2 #=> 5.0
# In Elixir gibt der Operator '/' immer einen Float-Wert zurück.
# Für Division mit ganzzahligen Ergebnis gibt es 'div'
div(10, 2) #=> 5
# Um den Rest der ganzzahligen Division zu erhalten gibt es 'rem'
rem(10, 3) #=> 1
# Natürlich gibt es auch Operatoren für Booleans: 'or', 'and' und 'not'. Diese
# Operatoren erwarten einen Boolean als erstes Argument.
true and true #=> true
false or true #=> true
# 1 and true #=> ** (ArgumentError) argument error
# Elixir bietet auch '||', '&&' und '!', die Argumente jedweden Typs
# akzeptieren. Alle Werte außer 'false' und 'nil' werden zu wahr evaluiert.
1 || true #=> 1
false && 1 #=> false
nil && 20 #=> nil
!true #=> false
# Für Vergleiche gibt es die Operatoren `==`, `!=`, `===`, `!==`, `<=`, `>=`,
# `<` und `>`
1 == 1 #=> true
1 != 1 #=> false
1 < 2 #=> true
# '===' und '!==' sind strikter beim Vergleich von Integern und Floats:
1 == 1.0 #=> true
1 === 1.0 #=> false
# Es ist außerdem möglich zwei verschiedene Datentypen zu vergleichen:
1 < :hello #=> true
# Die gesamte Ordnung über die Datentypen ist wie folgt definiert:
# number < atom < reference < functions < port < pid < tuple < list < bitstring
# Um Joe Armstrong zu zitieren: "The actual order is not important, but that a
# total ordering is well defined is important."
## ---------------------------
## -- Kontrollstrukturen
## ---------------------------
# Es gibt die `if`-Verzweigung
if false do
"Dies wird nie jemand sehen..."
else
"...aber dies!"
end
# ...und ebenso `unless`
unless true do
"Dies wird nie jemand sehen..."
else
"...aber dies!"
end
# Du erinnerst dich an 'pattern matching'? Viele Kontrollstrukturen in Elixir
# arbeiten damit.
# 'case' erlaubt es uns Werte mit vielerlei Mustern zu vergleichen.
case {:one, :two} do
{:four, :five} ->
"Das wird nicht passen"
{:one, x} ->
"Das schon und außerdem wird es ':two' dem Wert 'x' zuweisen."
_ ->
"Dieser Fall greift immer."
end
# Es ist eine übliche Praxis '_' einen Wert zuzuweisen, sofern dieser Wert
# nicht weiter verwendet wird.
# Wenn wir uns zum Beispiel nur für den Kopf einer Liste interessieren:
[kopf | _] = [1,2,3]
kopf #=> 1
# Für bessere Lesbarkeit können wir auch das Folgende machen:
[kopf | _rest] = [:a, :b, :c]
kopf #=> :a
# Mit 'cond' können diverse Bedingungen zur selben Zeit überprüft werden. Man
# benutzt 'cond' statt viele if-Verzweigungen zu verschachteln.
cond do
1 + 1 == 3 ->
"Ich werde nie aufgerufen."
2 * 5 == 12 ->
"Ich auch nicht."
1 + 2 == 3 ->
"Aber ich!"
end
# Es ist üblich eine letzte Bedingung einzufügen, die immer zu wahr evaluiert.
cond do
1 + 1 == 3 ->
"Ich werde nie aufgerufen."
2 * 5 == 12 ->
"Ich auch nicht."
true ->
"Aber ich! (dies ist im Grunde ein 'else')"
end
# 'try/catch' wird verwendet um Werte zu fangen, die zuvor 'geworfen' wurden.
# Das Konstrukt unterstützt außerdem eine 'after'-Klausel die aufgerufen wird,
# egal ob zuvor ein Wert gefangen wurde.
try do
throw(:hello)
catch
nachricht -> "#{nachricht} gefangen."
after
IO.puts("Ich bin die 'after'-Klausel.")
end
#=> Ich bin die 'after'-Klausel.
# ":hello gefangen"
## ---------------------------
## -- Module und Funktionen
## ---------------------------
# Anonyme Funktionen (man beachte den Punkt)
square = fn(x) -> x * x end
square.(5) #=> 25
# Anonyme Funktionen unterstützen auch 'pattern' und 'guards'. Guards erlauben
# es die Mustererkennung zu justieren und werden mit dem Schlüsselwort 'when'
# eingeführt:
f = fn
x, y when x > 0 -> x + y
x, y -> x * y
end
f.(1, 3) #=> 4
f.(-1, 3) #=> -3
# Elixir bietet zahlreiche eingebaute Funktionen. Diese sind im gleichen
# Geltungsbereich ('scope') verfügbar.
is_number(10) #=> true
is_list("hello") #=> false
elem({1,2,3}, 0) #=> 1
# Mehrere Funktionen können in einem Modul gruppiert werden. Innerhalb eines
# Moduls ist es möglich mit dem Schlüsselwort 'def' eine Funktion zu
# definieren.
defmodule Math do
def sum(a, b) do
a + b
end
def square(x) do
x * x
end
end
Math.sum(1, 2) #=> 3
Math.square(3) #=> 9
# Um unser einfaches Mathe-Modul zu kompilieren muss es unter 'math.ex'
# gesichert werden. Anschließend kann es mit 'elixirc' im Terminal aufgerufen
# werden: elixirc math.ex
# Innerhalb eines Moduls definieren wir private Funktionen mit 'defp'. Eine
# Funktion, die mit 'def' erstellt wurde, kann von anderen Modulen aufgerufen
# werden; eine private Funktion kann nur lokal angesprochen werden.
defmodule PrivateMath do
def sum(a, b) do
do_sum(a, b)
end
defp do_sum(a, b) do
a + b
end
end
PrivateMath.sum(1, 2) #=> 3
# PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError)
# Auch Funktionsdeklarationen unterstützen 'guards' und Mustererkennung:
defmodule Geometry do
def area({:rectangle, w, h}) do
w * h
end
def area({:circle, r}) when is_number(r) do
3.14 * r * r
end
end
Geometry.area({:rectangle, 2, 3}) #=> 6
Geometry.area({:circle, 3}) #=> 28.25999999999999801048
# Geometry.area({:circle, "not_a_number"})
#=> ** (FunctionClauseError) no function clause matching in Geometry.area/1
# Wegen der Unveränderlichkeit von Variablen ist Rekursion ein wichtiger
# Bestandteil von Elixir.
defmodule Recursion do
def sum_list([head | tail], acc) do
sum_list(tail, acc + head)
end
def sum_list([], acc) do
acc
end
end
Recursion.sum_list([1,2,3], 0) #=> 6
# Elixir-Module unterstützen Attribute. Es gibt eingebaute Attribute, ebenso
# ist es möglich eigene Attribute hinzuzufügen.
defmodule MyMod do
@moduledoc """
Dies ist ein eingebautes Attribut in einem Beispiel-Modul
"""
@my_data 100 # Dies ist ein selbst-definiertes Attribut.
IO.inspect(@my_data) #=> 100
end
## ---------------------------
## -- 'Records' und Ausnahmebehandlung
## ---------------------------
# 'Records' sind im Grunde Strukturen, die es erlauben einem Wert einen eigenen
# Namen zuzuweisen.
defrecord Person, name: nil, age: 0, height: 0
joe_info = Person.new(name: "Joe", age: 30, height: 180)
#=> Person[name: "Joe", age: 30, height: 180]
# Zugriff auf den Wert von 'name'
joe_info.name #=> "Joe"
# Den Wert von 'age' überschreiben
joe_info = joe_info.age(31) #=> Person[name: "Joe", age: 31, height: 180]
# Der 'try'-Block wird zusammen mit dem 'rescue'-Schlüsselwort dazu verwendet,
# um Ausnahmen beziehungsweise Fehler zu behandeln.
try do
raise "Irgendein Fehler."
rescue
RuntimeError -> "Laufzeit-Fehler gefangen."
_error -> "Und dies fängt jeden Fehler."
end
# Alle Ausnahmen haben das Attribut 'message'
try do
raise "ein Fehler"
rescue
x in [RuntimeError] ->
x.message
end
## ---------------------------
## -- Nebenläufigkeit
## ---------------------------
# Elixir beruht auf dem Aktoren-Model zur Behandlung der Nebenläufigkeit. Alles
# was man braucht um in Elixir nebenläufige Programme zu schreiben sind drei
# Primitive: Prozesse erzeugen, Nachrichten senden und Nachrichten empfangen.
# Um einen neuen Prozess zu erzeugen nutzen wir die 'spawn'-Funktion, die
# wiederum eine Funktion als Argument entgegen nimmt.
f = fn -> 2 * 2 end #=> #Function<erl_eval.20.80484245>
spawn(f) #=> #PID<0.40.0>
# 'spawn' gibt eine pid (einen Identifikator des Prozesses) zurück. Diese kann
# nun verwendet werden, um Nachrichten an den Prozess zu senden. Um
# zu senden nutzen wir den '<-' Operator. Damit das alles Sinn macht müssen wir
# in der Lage sein Nachrichten zu empfangen. Dies wird mit dem
# 'receive'-Mechanismus sichergestellt:
defmodule Geometry do
def area_loop do
receive do
{:rectangle, w, h} ->
IO.puts("Area = #{w * h}")
area_loop()
{:circle, r} ->
IO.puts("Area = #{3.14 * r * r}")
area_loop()
end
end
end
# Kompiliere das Modul, starte einen Prozess und gib die 'area_loop' Funktion
# in der Shell mit, etwa so:
pid = spawn(fn -> Geometry.area_loop() end) #=> #PID<0.40.0>
# Sende eine Nachricht an die 'pid', die ein Muster im 'receive'-Ausdruck
# erfüllt:
pid <- {:rectangle, 2, 3}
#=> Area = 6
# {:rectangle,2,3}
pid <- {:circle, 2}
#=> Area = 12.56000000000000049738
# {:circle,2}
# Die Shell selbst ist ein Prozess und mit dem Schlüsselwort 'self' kann man
# die aktuelle pid herausfinden.
self() #=> #PID<0.27.0>
```
## Referenzen und weitere Lektüre
* [Getting started guide](http://elixir-lang.org/getting_started/1.html) auf der [elixir Website](http://elixir-lang.org)
* [Elixir Documentation](http://elixir-lang.org/docs/master/)
* ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) von Fred Hebert
* "Programming Erlang: Software for a Concurrent World" von Joe Armstrong
---
language: Elixir
contributors:
- ["Joao Marques", "http://github.com/mrshankly"]
translators:
- ["Gregor Große-Bölting", "http://www.ideen-und-soehne.de"]
filename: learnelixir-de.ex
lang: de-de
---
Elixir ist eine moderne, funktionale Sprache für die Erlang VM. Sie ist voll
kompatibel mit Erlang, verfügt aber über eine freundlichere Syntax und bringt
viele Features mit.
```ruby
# Einzeilige Kommentare werden mit der Raute gesetzt.
# Es gibt keine mehrzeiligen Kommentare;
# es ist aber problemlos möglich mehrere einzeilige Kommentare hintereinander
# zu setzen (so wie hier).
# Mit 'iex' ruft man die Elixir-Shell auf.
# Zum kompilieren von Modulen dient der Befehl 'elixirc'.
# Beide Befehle sollten als Umgebungsvariable gesetzt sein, wenn Elixir korrekt
# installiert wurde.
## ---------------------------
## -- Basistypen
## ---------------------------
# Es gibt Nummern:
3 # Integer
0x1F # Integer
3.0 # Float
# Für bessere Lesbarkeit des Codes können Unterstriche "_" als Trennzeichen verwendet werden
1_000_000 == 1000000 # Integer
1_000.567 == 1000.567 # Float
# Atome, das sind Literale, sind Konstanten mit Namen. Sie starten mit einem
# ':'.
:hello # Atom
# Außerdem gibt es Tupel, deren Werte im Arbeitsspeicher vorgehalten werden.
{1,2,3} # Tupel
# Die Werte innerhalb eines Tupels können mit der 'elem'-Funktion ausgelesen
# werden:
elem({1, 2, 3}, 0) # => 1
# Listen sind als verkettete Listen implementiert.
[1, 2, 3] # list
# Auf Kopf und Rest einer Liste kann wie folgt zugegriffen werden:
[ kopf | rest ] = [1,2,3]
kopf # => 1
rest # => [2, 3]
# In Elixir, wie auch in Erlang, kennzeichnet '=' ein 'pattern matching'
# (Musterabgleich) und keine Zuweisung.
# Das heißt, dass die linke Seite auf die rechte Seite 'abgeglichen' wird.
# Auf diese Weise kann im Beispiel oben auf Kopf und Rest der Liste zugegriffen
# werden.
# Ein Musterabgleich wird einen Fehler werfen, wenn die beiden Seiten nicht
# zusammenpassen.
# Im folgenden Beispiel haben die Tupel eine unterschiedliche Anzahl an
# Elementen:
{a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2}
# Es gibt außerdem 'binaries',
<<1,2,3>> # binary.
# Strings und 'char lists'
"hello" # String
'hello' # Char-Liste
# ... und mehrzeilige Strings
"""
Ich bin ein
mehrzeiliger String.
"""
#=> "Ich bin ein\nmehrzeiliger String.\n"
# Alles Strings werden in UTF-8 enkodiert:
"héllò" #=> "héllò"
# Eigentlich sind Strings in Wahrheit nur binaries und 'char lists' einfach
# Listen.
<<?a, ?b, ?c>> #=> "abc"
[?a, ?b, ?c] #=> 'abc'
# In Elixir gibt `?a` den ASCII-Integer für den Buchstaben zurück.
?a #=> 97
# Um Listen zu verbinden gibt es den Operator '++', für binaries nutzt man '<>'
[1,2,3] ++ [4,5] #=> [1,2,3,4,5]
'hello ' ++ 'world' #=> 'hello world'
<<1,2,3>> <> <<4,5>> #=> <<1,2,3,4,5>>
"hello " <> "world" #=> "hello world"
## ---------------------------
## -- Operatoren
## ---------------------------
# Einfache Arithmetik
1 + 1 #=> 2
10 - 5 #=> 5
5 * 2 #=> 10
10 / 2 #=> 5.0
# In Elixir gibt der Operator '/' immer einen Float-Wert zurück.
# Für Division mit ganzzahligen Ergebnis gibt es 'div'
div(10, 2) #=> 5
# Um den Rest der ganzzahligen Division zu erhalten gibt es 'rem'
rem(10, 3) #=> 1
# Natürlich gibt es auch Operatoren für Booleans: 'or', 'and' und 'not'. Diese
# Operatoren erwarten einen Boolean als erstes Argument.
true and true #=> true
false or true #=> true
# 1 and true #=> ** (ArgumentError) argument error
# Elixir bietet auch '||', '&&' und '!', die Argumente jedweden Typs
# akzeptieren. Alle Werte außer 'false' und 'nil' werden zu wahr evaluiert.
1 || true #=> 1
false && 1 #=> false
nil && 20 #=> nil
!true #=> false
# Für Vergleiche gibt es die Operatoren `==`, `!=`, `===`, `!==`, `<=`, `>=`,
# `<` und `>`
1 == 1 #=> true
1 != 1 #=> false
1 < 2 #=> true
# '===' und '!==' sind strikter beim Vergleich von Integern und Floats:
1 == 1.0 #=> true
1 === 1.0 #=> false
# Es ist außerdem möglich zwei verschiedene Datentypen zu vergleichen:
1 < :hello #=> true
# Die gesamte Ordnung über die Datentypen ist wie folgt definiert:
# number < atom < reference < functions < port < pid < tuple < list < bitstring
# Um Joe Armstrong zu zitieren: "The actual order is not important, but that a
# total ordering is well defined is important."
## ---------------------------
## -- Kontrollstrukturen
## ---------------------------
# Es gibt die `if`-Verzweigung
if false do
"Dies wird nie jemand sehen..."
else
"...aber dies!"
end
# ...und ebenso `unless`
unless true do
"Dies wird nie jemand sehen..."
else
"...aber dies!"
end
# Du erinnerst dich an 'pattern matching'? Viele Kontrollstrukturen in Elixir
# arbeiten damit.
# 'case' erlaubt es uns Werte mit vielerlei Mustern zu vergleichen.
case {:one, :two} do
{:four, :five} ->
"Das wird nicht passen"
{:one, x} ->
"Das schon und außerdem wird es ':two' dem Wert 'x' zuweisen."
_ ->
"Dieser Fall greift immer."
end
# Es ist eine übliche Praxis '_' einen Wert zuzuweisen, sofern dieser Wert
# nicht weiter verwendet wird.
# Wenn wir uns zum Beispiel nur für den Kopf einer Liste interessieren:
[kopf | _] = [1,2,3]
kopf #=> 1
# Für bessere Lesbarkeit können wir auch das Folgende machen:
[kopf | _rest] = [:a, :b, :c]
kopf #=> :a
# Mit 'cond' können diverse Bedingungen zur selben Zeit überprüft werden. Man
# benutzt 'cond' statt viele if-Verzweigungen zu verschachteln.
cond do
1 + 1 == 3 ->
"Ich werde nie aufgerufen."
2 * 5 == 12 ->
"Ich auch nicht."
1 + 2 == 3 ->
"Aber ich!"
end
# Es ist üblich eine letzte Bedingung einzufügen, die immer zu wahr evaluiert.
cond do
1 + 1 == 3 ->
"Ich werde nie aufgerufen."
2 * 5 == 12 ->
"Ich auch nicht."
true ->
"Aber ich! (dies ist im Grunde ein 'else')"
end
# 'try/catch' wird verwendet um Werte zu fangen, die zuvor 'geworfen' wurden.
# Das Konstrukt unterstützt außerdem eine 'after'-Klausel die aufgerufen wird,
# egal ob zuvor ein Wert gefangen wurde.
try do
throw(:hello)
catch
nachricht -> "#{nachricht} gefangen."
after
IO.puts("Ich bin die 'after'-Klausel.")
end
#=> Ich bin die 'after'-Klausel.
# ":hello gefangen"
## ---------------------------
## -- Module und Funktionen
## ---------------------------
# Anonyme Funktionen (man beachte den Punkt)
square = fn(x) -> x * x end
square.(5) #=> 25
# Anonyme Funktionen unterstützen auch 'pattern' und 'guards'. Guards erlauben
# es die Mustererkennung zu justieren und werden mit dem Schlüsselwort 'when'
# eingeführt:
f = fn
x, y when x > 0 -> x + y
x, y -> x * y
end
f.(1, 3) #=> 4
f.(-1, 3) #=> -3
# Elixir bietet zahlreiche eingebaute Funktionen. Diese sind im gleichen
# Geltungsbereich ('scope') verfügbar.
is_number(10) #=> true
is_list("hello") #=> false
elem({1,2,3}, 0) #=> 1
# Mehrere Funktionen können in einem Modul gruppiert werden. Innerhalb eines
# Moduls ist es möglich mit dem Schlüsselwort 'def' eine Funktion zu
# definieren.
defmodule Math do
def sum(a, b) do
a + b
end
def square(x) do
x * x
end
end
Math.sum(1, 2) #=> 3
Math.square(3) #=> 9
# Um unser einfaches Mathe-Modul zu kompilieren muss es unter 'math.ex'
# gesichert werden. Anschließend kann es mit 'elixirc' im Terminal aufgerufen
# werden: elixirc math.ex
# Innerhalb eines Moduls definieren wir private Funktionen mit 'defp'. Eine
# Funktion, die mit 'def' erstellt wurde, kann von anderen Modulen aufgerufen
# werden; eine private Funktion kann nur lokal angesprochen werden.
defmodule PrivateMath do
def sum(a, b) do
do_sum(a, b)
end
defp do_sum(a, b) do
a + b
end
end
PrivateMath.sum(1, 2) #=> 3
# PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError)
# Auch Funktionsdeklarationen unterstützen 'guards' und Mustererkennung:
defmodule Geometry do
def area({:rectangle, w, h}) do
w * h
end
def area({:circle, r}) when is_number(r) do
3.14 * r * r
end
end
Geometry.area({:rectangle, 2, 3}) #=> 6
Geometry.area({:circle, 3}) #=> 28.25999999999999801048
# Geometry.area({:circle, "not_a_number"})
#=> ** (FunctionClauseError) no function clause matching in Geometry.area/1
# Wegen der Unveränderlichkeit von Variablen ist Rekursion ein wichtiger
# Bestandteil von Elixir.
defmodule Recursion do
def sum_list([head | tail], acc) do
sum_list(tail, acc + head)
end
def sum_list([], acc) do
acc
end
end
Recursion.sum_list([1,2,3], 0) #=> 6
# Elixir-Module unterstützen Attribute. Es gibt eingebaute Attribute, ebenso
# ist es möglich eigene Attribute hinzuzufügen.
defmodule MyMod do
@moduledoc """
Dies ist ein eingebautes Attribut in einem Beispiel-Modul
"""
@my_data 100 # Dies ist ein selbst-definiertes Attribut.
IO.inspect(@my_data) #=> 100
end
## ---------------------------
## -- 'Records' und Ausnahmebehandlung
## ---------------------------
# 'Records' sind im Grunde Strukturen, die es erlauben einem Wert einen eigenen
# Namen zuzuweisen.
defrecord Person, name: nil, age: 0, height: 0
joe_info = Person.new(name: "Joe", age: 30, height: 180)
#=> Person[name: "Joe", age: 30, height: 180]
# Zugriff auf den Wert von 'name'
joe_info.name #=> "Joe"
# Den Wert von 'age' überschreiben
joe_info = joe_info.age(31) #=> Person[name: "Joe", age: 31, height: 180]
# Der 'try'-Block wird zusammen mit dem 'rescue'-Schlüsselwort dazu verwendet,
# um Ausnahmen beziehungsweise Fehler zu behandeln.
try do
raise "Irgendein Fehler."
rescue
RuntimeError -> "Laufzeit-Fehler gefangen."
_error -> "Und dies fängt jeden Fehler."
end
# Alle Ausnahmen haben das Attribut 'message'
try do
raise "ein Fehler"
rescue
x in [RuntimeError] ->
x.message
end
## ---------------------------
## -- Nebenläufigkeit
## ---------------------------
# Elixir beruht auf dem Aktoren-Model zur Behandlung der Nebenläufigkeit. Alles
# was man braucht um in Elixir nebenläufige Programme zu schreiben sind drei
# Primitive: Prozesse erzeugen, Nachrichten senden und Nachrichten empfangen.
# Um einen neuen Prozess zu erzeugen nutzen wir die 'spawn'-Funktion, die
# wiederum eine Funktion als Argument entgegen nimmt.
f = fn -> 2 * 2 end #=> #Function<erl_eval.20.80484245>
spawn(f) #=> #PID<0.40.0>
# 'spawn' gibt eine pid (einen Identifikator des Prozesses) zurück. Diese kann
# nun verwendet werden, um Nachrichten an den Prozess zu senden. Um
# zu senden nutzen wir den '<-' Operator. Damit das alles Sinn macht müssen wir
# in der Lage sein Nachrichten zu empfangen. Dies wird mit dem
# 'receive'-Mechanismus sichergestellt:
defmodule Geometry do
def area_loop do
receive do
{:rectangle, w, h} ->
IO.puts("Area = #{w * h}")
area_loop()
{:circle, r} ->
IO.puts("Area = #{3.14 * r * r}")
area_loop()
end
end
end
# Kompiliere das Modul, starte einen Prozess und gib die 'area_loop' Funktion
# in der Shell mit, etwa so:
pid = spawn(fn -> Geometry.area_loop() end) #=> #PID<0.40.0>
# Sende eine Nachricht an die 'pid', die ein Muster im 'receive'-Ausdruck
# erfüllt:
pid <- {:rectangle, 2, 3}
#=> Area = 6
# {:rectangle,2,3}
pid <- {:circle, 2}
#=> Area = 12.56000000000000049738
# {:circle,2}
# Die Shell selbst ist ein Prozess und mit dem Schlüsselwort 'self' kann man
# die aktuelle pid herausfinden.
self() #=> #PID<0.27.0>
```
## Referenzen und weitere Lektüre
* [Getting started guide](http://elixir-lang.org/getting_started/1.html) auf der [elixir Website](http://elixir-lang.org)
* [Elixir Documentation](http://elixir-lang.org/docs/master/)
* ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) von Fred Hebert
* "Programming Erlang: Software for a Concurrent World" von Joe Armstrong

File diff suppressed because it is too large Load Diff

View File

@ -1,263 +1,263 @@
---
category: tool
tool: make
contributors:
- ["Robert Steed", "https://github.com/robochat"]
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
translators:
- ["Martin Schimandl", "https://github.com/Git-Jiro"]
filename: Makefile-de
lang: de-de
---
Eine Makefile definiert einen Graphen von Regeln um ein Ziel (oder Ziele)
zu erzeugen. Es dient dazu, die geringste Menge an Arbeit zu verrichten um
ein Ziel in Einklang mit dem Quellcode zu bringen. Make wurde berühmterweise
von Stuart Feldman 1976 übers Wochenende geschrieben. Make ist noch immer
sehr verbreitet (vorallem im Unix Umfeld) obwohl es bereits sehr viel
Konkurrenz und Kritik zu Make gibt.
Es gibt eine Vielzahl an Varianten von Make, dieser Artikel beschäftigt sich
mit der Version GNU Make. Diese Version ist Standard auf Linux.
```make
# Kommentare können so geschrieben werden.
# Dateien sollten Makefile heißen, denn dann können sie als `make <ziel>`
# aufgerufen werden. Ansonsten muss `make -f "dateiname" <ziel>` verwendet
# werden.
# Warnung - Es sollten nur TABULATOREN zur Einrückung im Makefile verwendet
# werden. Niemals Leerzeichen!
#-----------------------------------------------------------------------
# Grundlagen
#-----------------------------------------------------------------------
# Eine Regel - Diese Regel wird nur abgearbeitet wenn die Datei file0.txt
# nicht existiert.
file0.txt:
echo "foo" > file0.txt
# Selbst Kommentare in der 'Rezept' Sektion werden an die Shell
# weitergegeben. Versuche `make file0.txt` oder einfach `make`
# die erste Regel ist die Standard-Regel.
# Diese Regel wird nur abgearbeitet, wenn file0.txt aktueller als file1.txt ist.
file1.txt: file0.txt
cat file0.txt > file1.txt
# Verwende die selben Quoting-Regeln wie die Shell
@cat file0.txt >> file1.txt
# @ unterdrückt die Ausgabe des Befehls an stdout.
-@echo 'hello'
# - bedeutet, dass Make die Abarbeitung fortsetzt auch wenn Fehler
# passieren.
# Versuche `make file1.txt` auf der Kommandozeile.
# Eine Regel kann mehrere Ziele und mehrere Voraussetzungen haben.
file2.txt file3.txt: file0.txt file1.txt
touch file2.txt
touch file3.txt
# Make wird sich beschweren, wenn es mehrere Rezepte für die gleiche Regel gibt.
# Leere Rezepte zählen nicht und können dazu verwendet werden weitere
# Voraussetzungen hinzuzufügen.
#-----------------------------------------------------------------------
# Phony-Ziele
#-----------------------------------------------------------------------
# Ein Phony-Ziel ist ein Ziel, das keine Datei ist.
# Es wird nie aktuell sein, daher wird Make immer versuchen, es abzuarbeiten
all: maker process
# Es ist erlaubt Dinge ausserhalb der Reihenfolge zu deklarieren.
maker:
touch ex0.txt ex1.txt
# Um das Fehlschlagen von Phony-Regeln zu vermeiden wenn eine echte Datei den
# selben namen wie ein Phony-Ziel hat:
.PHONY: all maker process
# Das ist ein spezielles Ziel. Es gibt noch ein paar mehr davon.
# Eine Regel mit einem Phony-Ziel als Voraussetzung wird immer abgearbeitet
ex0.txt ex1.txt: maker
# Häufige Phony-Ziele sind: all make clean install ...
#-----------------------------------------------------------------------
# Automatische Variablen & Wildcards
#-----------------------------------------------------------------------
process: file*.txt # Eine Wildcard um Dateinamen zu vergleichen
@echo $^ # $^ ist eine Variable die eine Liste aller
# Voraussetzungen enthält.
@echo $@ # Namen des Ziels ausgeben.
#(Bei mehreren Ziel-Regeln enthält $@ den Verursacher der Abarbeitung
#der Regel.)
@echo $< # Die erste Voraussetzung aus der Liste
@echo $? # Nur die Voraussetzungen, die nicht aktuell sind.
@echo $+ # Alle Voraussetzungen inklusive Duplikate (nicht wie Üblich)
#@echo $| # Alle 'order only' Voraussetzungen
# Selbst wenn wir die Voraussetzungen der Regel aufteilen, $^ wird sie finden.
process: ex1.txt file0.txt
# ex1.txt wird gefunden werden, aber file0.txt wird dedupliziert.
#-----------------------------------------------------------------------
# Muster
#-----------------------------------------------------------------------
# Mit Mustern kann man make beibringen wie Dateien in andere Dateien
# umgewandelt werden.
%.png: %.svg
inkscape --export-png $^
# Muster-Vergleichs-Regeln werden nur abgearbeitet, wenn make entscheidet das
# Ziel zu erzeugen
# Verzeichnis-Pfade werden normalerweise bei Muster-Vergleichs-Regeln ignoriert.
# Aber make wird versuchen die am besten passende Regel zu verwenden.
small/%.png: %.svg
inkscape --export-png --export-dpi 30 $^
# Make wird die letzte Version einer Muster-Vergleichs-Regel verwenden, die es
# findet.
%.png: %.svg
@echo this rule is chosen
# Allerdings wird make die erste Muster-Vergleicher-Regel verwenden, die das
# Ziel erzeugen kann.
%.png: %.ps
@echo this rule is not chosen if *.svg and *.ps are both present
# Make hat bereits ein paar eingebaute Muster-Vergleichs-Regelen. Zum Beispiel
# weiß Make wie man aus *.c Dateien *.o Dateien erzeugt.
# Ältere Versionen von Make verwenden möglicherweise Suffix-Regeln anstatt
# Muster-Vergleichs-Regeln.
.png.ps:
@echo this rule is similar to a pattern rule.
# Aktivieren der Suffix-Regel
.SUFFIXES: .png
#-----------------------------------------------------------------------
# Variablen
#-----------------------------------------------------------------------
# auch Makros genannt.
# Variablen sind im Grunde genommen Zeichenketten-Typen.
name = Ted
name2="Sarah"
echo:
@echo $(name)
@echo ${name2}
@echo $name # Das funktioniert nicht, wird als $(n)ame behandelt.
@echo $(name3) # Unbekannte Variablen werden als leere Zeichenketten behandelt.
# Es git 4 Stellen um Variablen zu setzen.
# In Reihenfolge der Priorität von höchster zu niedrigster:
# 1: Befehls-Zeilen Argumente
# 2: Makefile
# 3: Shell Umbebungs-Variablen - Make importiert diese automatisch.
# 3: MAke hat einige vordefinierte Variablen.
name4 ?= Jean
# Setze die Variable nur wenn es eine gleichnamige Umgebungs-Variable noch
# nicht gibt.
override name5 = David
# Verhindert, dass Kommando-Zeilen Argumente diese Variable ändern können.
name4 +=grey
# Werte an eine Variable anhängen (inkludiert Leerzeichen).
# Muster-Spezifische Variablen Werte (GNU Erweiterung).
echo: name2 = Sara # Wahr innerhalb der passenden Regel und auch innerhalb
# rekursiver Voraussetzungen (ausser wenn es den Graphen zerstören
# kann, wenn es zu kompilizert wird!)
# Ein paar Variablen, die von Make automatisch definiert werden.
echo_inbuilt:
echo $(CC)
echo ${CXX}
echo $(FC)
echo ${CFLAGS}
echo $(CPPFLAGS)
echo ${CXXFLAGS}
echo $(LDFLAGS)
echo ${LDLIBS}
#-----------------------------------------------------------------------
# Variablen 2
#-----------------------------------------------------------------------
# Der erste Typ von Variablen wird bei jeder Verwendung ausgewertet.
# Das kann aufwendig sein, daher exisitert ein zweiter Typ von Variablen.
# Diese werden nur einmal ausgewertet. (Das ist eine GNU make Erweiterung)
var := hello
var2 ::= $(var) hello
#:= und ::= sind äquivalent.
# Diese Variablen werden prozedural ausgwertet (in der Reihenfolge in der sie
# auftauchen), die stehen daher im wiederspruch zum Rest der Sprache!
# Das funktioniert nicht
var3 ::= $(var4) and good luck
var4 ::= good night
#-----------------------------------------------------------------------
# Funktionen
#-----------------------------------------------------------------------
# Make verfügt über eine Vielzahl von Funktionen.
sourcefiles = $(wildcard *.c */*.c)
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
# Das Format ist $(func arg0,arg1,arg2...)
# Ein paar Beispiele
ls: * src/*
@echo $(filter %.txt, $^)
@echo $(notdir $^)
@echo $(join $(dir $^),$(notdir $^))
#-----------------------------------------------------------------------
# Direktiven
#-----------------------------------------------------------------------
# Inkludiere andere Makefile, sehr praktisch für platformspezifischen Code
include foo.mk
sport = tennis
# Konditionale kompiliereung
report:
ifeq ($(sport),tennis)
@echo 'game, set, match'
else
@echo "They think it's all over; it is now"
endif
# Es gibt auch ifneq, ifdef, ifndef
foo = true
ifdef $(foo)
bar = 'hello'
endif
```
### Mehr Resourcen
+ [gnu make documentation](https://www.gnu.org/software/make/manual/)
+ [software carpentry tutorial](http://swcarpentry.github.io/make-novice/)
+ learn C the hard way [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html)
---
category: tool
tool: make
contributors:
- ["Robert Steed", "https://github.com/robochat"]
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
translators:
- ["Martin Schimandl", "https://github.com/Git-Jiro"]
filename: Makefile-de
lang: de-de
---
Eine Makefile definiert einen Graphen von Regeln um ein Ziel (oder Ziele)
zu erzeugen. Es dient dazu, die geringste Menge an Arbeit zu verrichten um
ein Ziel in Einklang mit dem Quellcode zu bringen. Make wurde berühmterweise
von Stuart Feldman 1976 übers Wochenende geschrieben. Make ist noch immer
sehr verbreitet (vorallem im Unix Umfeld) obwohl es bereits sehr viel
Konkurrenz und Kritik zu Make gibt.
Es gibt eine Vielzahl an Varianten von Make, dieser Artikel beschäftigt sich
mit der Version GNU Make. Diese Version ist Standard auf Linux.
```make
# Kommentare können so geschrieben werden.
# Dateien sollten Makefile heißen, denn dann können sie als `make <ziel>`
# aufgerufen werden. Ansonsten muss `make -f "dateiname" <ziel>` verwendet
# werden.
# Warnung - Es sollten nur TABULATOREN zur Einrückung im Makefile verwendet
# werden. Niemals Leerzeichen!
#-----------------------------------------------------------------------
# Grundlagen
#-----------------------------------------------------------------------
# Eine Regel - Diese Regel wird nur abgearbeitet wenn die Datei file0.txt
# nicht existiert.
file0.txt:
echo "foo" > file0.txt
# Selbst Kommentare in der 'Rezept' Sektion werden an die Shell
# weitergegeben. Versuche `make file0.txt` oder einfach `make`
# die erste Regel ist die Standard-Regel.
# Diese Regel wird nur abgearbeitet, wenn file0.txt aktueller als file1.txt ist.
file1.txt: file0.txt
cat file0.txt > file1.txt
# Verwende die selben Quoting-Regeln wie die Shell
@cat file0.txt >> file1.txt
# @ unterdrückt die Ausgabe des Befehls an stdout.
-@echo 'hello'
# - bedeutet, dass Make die Abarbeitung fortsetzt auch wenn Fehler
# passieren.
# Versuche `make file1.txt` auf der Kommandozeile.
# Eine Regel kann mehrere Ziele und mehrere Voraussetzungen haben.
file2.txt file3.txt: file0.txt file1.txt
touch file2.txt
touch file3.txt
# Make wird sich beschweren, wenn es mehrere Rezepte für die gleiche Regel gibt.
# Leere Rezepte zählen nicht und können dazu verwendet werden weitere
# Voraussetzungen hinzuzufügen.
#-----------------------------------------------------------------------
# Phony-Ziele
#-----------------------------------------------------------------------
# Ein Phony-Ziel ist ein Ziel, das keine Datei ist.
# Es wird nie aktuell sein, daher wird Make immer versuchen, es abzuarbeiten
all: maker process
# Es ist erlaubt Dinge ausserhalb der Reihenfolge zu deklarieren.
maker:
touch ex0.txt ex1.txt
# Um das Fehlschlagen von Phony-Regeln zu vermeiden wenn eine echte Datei den
# selben namen wie ein Phony-Ziel hat:
.PHONY: all maker process
# Das ist ein spezielles Ziel. Es gibt noch ein paar mehr davon.
# Eine Regel mit einem Phony-Ziel als Voraussetzung wird immer abgearbeitet
ex0.txt ex1.txt: maker
# Häufige Phony-Ziele sind: all make clean install ...
#-----------------------------------------------------------------------
# Automatische Variablen & Wildcards
#-----------------------------------------------------------------------
process: file*.txt # Eine Wildcard um Dateinamen zu vergleichen
@echo $^ # $^ ist eine Variable die eine Liste aller
# Voraussetzungen enthält.
@echo $@ # Namen des Ziels ausgeben.
#(Bei mehreren Ziel-Regeln enthält $@ den Verursacher der Abarbeitung
#der Regel.)
@echo $< # Die erste Voraussetzung aus der Liste
@echo $? # Nur die Voraussetzungen, die nicht aktuell sind.
@echo $+ # Alle Voraussetzungen inklusive Duplikate (nicht wie Üblich)
#@echo $| # Alle 'order only' Voraussetzungen
# Selbst wenn wir die Voraussetzungen der Regel aufteilen, $^ wird sie finden.
process: ex1.txt file0.txt
# ex1.txt wird gefunden werden, aber file0.txt wird dedupliziert.
#-----------------------------------------------------------------------
# Muster
#-----------------------------------------------------------------------
# Mit Mustern kann man make beibringen wie Dateien in andere Dateien
# umgewandelt werden.
%.png: %.svg
inkscape --export-png $^
# Muster-Vergleichs-Regeln werden nur abgearbeitet, wenn make entscheidet das
# Ziel zu erzeugen
# Verzeichnis-Pfade werden normalerweise bei Muster-Vergleichs-Regeln ignoriert.
# Aber make wird versuchen die am besten passende Regel zu verwenden.
small/%.png: %.svg
inkscape --export-png --export-dpi 30 $^
# Make wird die letzte Version einer Muster-Vergleichs-Regel verwenden, die es
# findet.
%.png: %.svg
@echo this rule is chosen
# Allerdings wird make die erste Muster-Vergleicher-Regel verwenden, die das
# Ziel erzeugen kann.
%.png: %.ps
@echo this rule is not chosen if *.svg and *.ps are both present
# Make hat bereits ein paar eingebaute Muster-Vergleichs-Regelen. Zum Beispiel
# weiß Make wie man aus *.c Dateien *.o Dateien erzeugt.
# Ältere Versionen von Make verwenden möglicherweise Suffix-Regeln anstatt
# Muster-Vergleichs-Regeln.
.png.ps:
@echo this rule is similar to a pattern rule.
# Aktivieren der Suffix-Regel
.SUFFIXES: .png
#-----------------------------------------------------------------------
# Variablen
#-----------------------------------------------------------------------
# auch Makros genannt.
# Variablen sind im Grunde genommen Zeichenketten-Typen.
name = Ted
name2="Sarah"
echo:
@echo $(name)
@echo ${name2}
@echo $name # Das funktioniert nicht, wird als $(n)ame behandelt.
@echo $(name3) # Unbekannte Variablen werden als leere Zeichenketten behandelt.
# Es git 4 Stellen um Variablen zu setzen.
# In Reihenfolge der Priorität von höchster zu niedrigster:
# 1: Befehls-Zeilen Argumente
# 2: Makefile
# 3: Shell Umbebungs-Variablen - Make importiert diese automatisch.
# 3: MAke hat einige vordefinierte Variablen.
name4 ?= Jean
# Setze die Variable nur wenn es eine gleichnamige Umgebungs-Variable noch
# nicht gibt.
override name5 = David
# Verhindert, dass Kommando-Zeilen Argumente diese Variable ändern können.
name4 +=grey
# Werte an eine Variable anhängen (inkludiert Leerzeichen).
# Muster-Spezifische Variablen Werte (GNU Erweiterung).
echo: name2 = Sara # Wahr innerhalb der passenden Regel und auch innerhalb
# rekursiver Voraussetzungen (ausser wenn es den Graphen zerstören
# kann, wenn es zu kompilizert wird!)
# Ein paar Variablen, die von Make automatisch definiert werden.
echo_inbuilt:
echo $(CC)
echo ${CXX}
echo $(FC)
echo ${CFLAGS}
echo $(CPPFLAGS)
echo ${CXXFLAGS}
echo $(LDFLAGS)
echo ${LDLIBS}
#-----------------------------------------------------------------------
# Variablen 2
#-----------------------------------------------------------------------
# Der erste Typ von Variablen wird bei jeder Verwendung ausgewertet.
# Das kann aufwendig sein, daher exisitert ein zweiter Typ von Variablen.
# Diese werden nur einmal ausgewertet. (Das ist eine GNU make Erweiterung)
var := hello
var2 ::= $(var) hello
#:= und ::= sind äquivalent.
# Diese Variablen werden prozedural ausgwertet (in der Reihenfolge in der sie
# auftauchen), die stehen daher im wiederspruch zum Rest der Sprache!
# Das funktioniert nicht
var3 ::= $(var4) and good luck
var4 ::= good night
#-----------------------------------------------------------------------
# Funktionen
#-----------------------------------------------------------------------
# Make verfügt über eine Vielzahl von Funktionen.
sourcefiles = $(wildcard *.c */*.c)
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
# Das Format ist $(func arg0,arg1,arg2...)
# Ein paar Beispiele
ls: * src/*
@echo $(filter %.txt, $^)
@echo $(notdir $^)
@echo $(join $(dir $^),$(notdir $^))
#-----------------------------------------------------------------------
# Direktiven
#-----------------------------------------------------------------------
# Inkludiere andere Makefile, sehr praktisch für platformspezifischen Code
include foo.mk
sport = tennis
# Konditionale kompiliereung
report:
ifeq ($(sport),tennis)
@echo 'game, set, match'
else
@echo "They think it's all over; it is now"
endif
# Es gibt auch ifneq, ifdef, ifndef
foo = true
ifdef $(foo)
bar = 'hello'
endif
```
### Mehr Resourcen
+ [gnu make documentation](https://www.gnu.org/software/make/manual/)
+ [software carpentry tutorial](http://swcarpentry.github.io/make-novice/)
+ learn C the hard way [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html)

View File

@ -1,281 +1,281 @@
---
category: tool
tool: docker
filename: docker.bat
contributors:
- ["Ruslan López", "http://javapro.org/"]
- ["Michael Chen", "https://github.com/ML-Chen"]
- ["Akshita Dixit", "https://github.com/akshitadixit"]
- ["Marcel Ribeiro-Dantas", "https://github.com/mribeirodantas"]
---
Docker is a tool that helps you build, test, ship and run applications
seamlessly across various machines. It replicates the environment our software
needs on any machine. You can get Docker for your machine from
https://docs.docker.com/get-docker/
It has grown in popularity over the last decade due to being lightweight and
fast as compared to virtual-machines that are bulky and slow. Unlike VMs, docker
does not need a full blown OS of its own to be loaded to start and does not
compete for resources other than what the application it is running will use.
VMs on the other hand are pretty resource intensive on our processors, disks and
memory hence running multiple VMs for various applications becomes a challenge
in a limited capacity architecture.
<pre>
┌────────────────────────┐ ┌───────────────────────┐
│ ┌───────────┐ │ │ ┌───────────┐ │
│ │ App │ │ │ │ App │ │
│ └───────────┘ │ │ └───────────┘ │
│ ┌────────┐ ┌────────┐ │ │ ┌────────┐ ┌───────┐ │
│ │ Libs │ │ Deps │ │ │ │ Libs │ │ Deps │ │
│ └────────┘ └────────┘ │ │ └────────┘ └───────┘ │
│ ┌───────────────────┐ │ │ ┌──────────────────┐ │
│ │ Guest OS │ │ │ │ Guest OS │ │
│ └───────────────────┘ │ │ └──────────────────┘ │
│ VM1 │ │ VM2 │
└────────────────────────┘ └───────────────────────┘
┌──────────────────────────────────────────────────┐
│ Hypervisor │
└──────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────┐
│ Host OS │
└──────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────┐
│ Hardware Infrastructure │
└──────────────────────────────────────────────────┘
(VM based architecture)
┌────────────────────────┐ ┌───────────────────────┐
│ ┌───────────┐ │ │ ┌───────────┐ │
│ │ App │ │ │ │ App │ │
│ └───────────┘ │ │ └───────────┘ │
│ ┌────────┐ ┌────────┐ │ │ ┌────────┐ ┌───────┐ │
│ │ Libs │ │ Deps │ │ │ │ Libs │ │ Deps │ │
│ └────────┘ └────────┘ │ │ └────────┘ └───────┘ │
│ Container1 │ │ Container2 │
└────────────────────────┘ └───────────────────────┘
┌──────────────────────────────────────────────────┐
│ Docker │
└──────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────┐
│ OS │
└──────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────┐
│ Hardware Infrastructure │
└──────────────────────────────────────────────────┘
(Docker based architecture)
</pre>
Couple of terms we will encounter frequently are Docker Images and Docker
Containers. Images are packages or templates of containers all stored in a
container registry such as [Docker Hub](https://hub.docker.com/). Containers
are standalone, executable instances of these images which include code,
runtime, system tools, system libraries and settings - everything required to
get the software up and running. Coming to Docker, it follows a client-server
architecture wherein the CLI client communicates with the server component,
which here is, the Docker Engine using RESTful API to issue commands.
## The Docker CLI
```bash
# after installing Docker from https://docs.docker.com/get-docker/
# To list available commands, either run `docker` with no parameters or execute
# `docker help`
$ docker
>>> docker [OPTIONS] COMMAND [ARG...]
docker [ --help | -v | --version ]
A self-sufficient runtime for containers.
Options:
--config string Location of client config files (default "/root/.docker")
-c, --context string Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set with "docker context use")
-D, --debug Enable debug mode
--help Print usage
-H, --host value Daemon socket(s) to connect to (default [])
-l, --log-level string Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
--tls Use TLS; implied by --tlsverify
--tlscacert string Trust certs signed only by this CA (default "/root/.docker/ca.pem")
--tlscert string Path to TLS certificate file (default "/root/.docker/cert.pem")
--tlskey string Path to TLS key file (default "/root/.docker/key.pem")
--tlsverify Use TLS and verify the remote
-v, --version Print version information and quit
Commands:
attach Attach to a running container
# […]
$ docker run hello-world
# `docker run <container-name>` is used to run a container, it will pull the
# images from Docker Hub if they don't already exist in your system. Here the
# docker client connects to the daemon which in turn pulls the "hello-world"
# image from the Docker Hub. The daemon then builds a new container from the
# image which runs the executable that produces the output streamed back to the
# client that we see on our terminals.
$ docker run -d ubuntu sleep 60s
# The -d (or --detach) flag is when we want to run a container in the background
# and return back to the terminal. Here we detach an ubuntu container from the
# terminal, the output should be the id and the command exits. If we check
# running containers, we should still see ours there:
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 133261b4894a ubuntu "sleep 60s" 3 seconds ago Up 2 seconds vigorous_gould
$ docker run <container-id> -p 3000:8000
# The -p (or --publish) flag is used to expose port 8000 inside the container to
# port 3000 outside the container. This is because the app inside the container
# runs in isolation, hence the port 8000 where the app runs is private to the
# container.
$ docker run -i
# or
$ docker run -it
# Docker runs our containers in a non-interactive mode i.e. they do not accept
# inputs or work dynamically while running. The -i flag keeps input open to the
# container, and the -t flag creates a pseudo-terminal that the shell can attach
# to (can be combined as -it)
$ docker ps -a
# The `docker ps` command only shows running containers by default. To see all
# containers, use the -a (or --all) flag
# Running the above command should output something similar in the terminal:
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 82f84bf6912b hello-world "/hello" 9 minutes ago Exited (0) 9 minutes ago eloquent_sammet
$ docker stop hello-world
# or
$ docker start hello-world
# The stop command simply stops one or more containers, and the start command
# starts the container(s) up again! `docker start -a ubuntu` will attach our
# detached container back to the terminal i.e. runs in the foreground
$ docker create alpine
# `docker create` creates a new container for us with the image specified (here,
# alpine), the container does not auto-start unlike `docker run`. This command
# is used to set up a container configuration and then `docker start` to shoot
# it up when required. Note that the status is "Created":
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 4c71c727c73d alpine "/bin/sh" 29 seconds ago Created naughty_ritchie
$ docker rm 82f84
# Removes one or more containers using their container ID.
# P.S.: we can use only the first few characters of the entire ID to identify
# containers
$ docker images
# Displays all images and their information, created here means the latest image
# tag updated on Docker Hub:
# REPOSITORY TAG IMAGE ID CREATED SIZE
# ubuntu latest a8780b506fa4 9 days ago 77.8MB
# alpine latest 9c6f07244728 3 months ago 5.54MB
# hello-world latest feb5d9fea6a5 13 months ago 13.3kB
$ docker rmi
# Removes one or more images from your system which do not have their instances
# (or containers as we know them) running. If the image has an attached
# container, either delete the container first or use the -f (or --force) flag
# to forcefully delete both the container and image.
$ docker pull busybox
# The pull command downloads the specified image on our system from Docker Hub.
$ docker exec -it 7b272 bash
# This command is used to run a command in the running container's default
# directory. Here 7b272 was our ubuntu container and the above command would
# help us interact with the container by opening a bash session.
$ docker logs <container-id>
# Displays the information logged by the specified container
# root@7b27222e4bb7:/# whoami
# root
# root@7b27222e4bb7:/# pwd
# /
# root@7b27222e4bb7:/# ls
# bin boot dev etc home lib lib32 lib64 libx3 srv sys tmp usr var
# root@7b27222e4bb7:/# exit
# exit
# More commands can be found at https://docs.docker.com/engine/reference/commandline/docker/
```
## The Dockerfile
The Dockerfile is a blueprint of a Docker image. We can mention the artifacts
from our application along with their configurations into this file in the
specific syntax to let anyone create a Docker image of our application.
### A few things to keep in mind:
* It is always strictly named `Dockerfile` without any extensions
* We have to build our custom image on top of some already available Docker base
image. (there is an empty image called `scratch` which literally lets you build
an image from scratch)
* All capitalised commands are part of the syntax, they are not case-sensitive
but used like a convention
* Below is a sample Dockerfile but you can read in depth from the [official docs](https://docs.docker.com/engine/reference/builder/).
```Dockerfile
FROM <base-image>
# define base image
ENV USERNAME='admin'\
PWD='****'
# optionally define environmental variables
RUN apt-get update
# run linux commands inside container env, does not affect host env
# This executes during the time of image creation
COPY <src> <target>
# executes on the host, copies files from src (usually on the host) to target
# on the container
ENTRYPOINT ["some-script.sh"]
# executes an entire script as an entrypoint
CMD [<args>,...]
# always part of dockerfile, introduces entry point linux command e.g.
# `CMD node server.js`
# This executes after image creation only when the container from the image
# is running.
```
### Build your images
Use the `docker build` command after wrapping your application into a Docker
image to run ( or build) it.
```bash
$ docker build <path-to-dockerfile>
# used to build an image from the specified Dockerfile
# instead of path we could also specify a URL
# -t tag is optional and used to name and tag your images for e.g.
# `$ docker build -t my-image:0.1 ./home/app`
# rebuild images everytime you make changes in the dockerfile
```
## Push your image to DockerHub
If you want your application's Docker image to be made publicly available for
any Docker user, you might wanna push it to the [Docker Hub](https://hub.docker.com/) which is a
registry of Docker images. Make sure you have an account with a username and
password on Docker Hub.
When pushing an image to Docker Hub, we must specify our Docker Hub username
as part of the source image name. We need to create the target image with the
tag name of username/image-name much like GitHub repositories.
```bash
$ docker login
# to login to Docker Hub using your username and password
$ docker tag <src-image>[:<src-tag>] <target-image>[:<target-tag>]
# this tags a local src-image to a public target-image
# e.g. `docker tag my-sample-app:1.0.0 akshitadixit/my-sample-app`
# if tags are not specified, they're defaulted to `latest`
$ docker push <target-image>[:<target-tag>]
# uploads our image to Docker Hub
# e.g. `docker push akshitadixit/my-sample-app`
# this image will be accessible under your profile's repositories as
# `https://hub.docker.com/r/username/image-name`
```
---
category: tool
tool: docker
filename: docker.bat
contributors:
- ["Ruslan López", "http://javapro.org/"]
- ["Michael Chen", "https://github.com/ML-Chen"]
- ["Akshita Dixit", "https://github.com/akshitadixit"]
- ["Marcel Ribeiro-Dantas", "https://github.com/mribeirodantas"]
---
Docker is a tool that helps you build, test, ship and run applications
seamlessly across various machines. It replicates the environment our software
needs on any machine. You can get Docker for your machine from
https://docs.docker.com/get-docker/
It has grown in popularity over the last decade due to being lightweight and
fast as compared to virtual-machines that are bulky and slow. Unlike VMs, docker
does not need a full blown OS of its own to be loaded to start and does not
compete for resources other than what the application it is running will use.
VMs on the other hand are pretty resource intensive on our processors, disks and
memory hence running multiple VMs for various applications becomes a challenge
in a limited capacity architecture.
<pre>
┌────────────────────────┐ ┌───────────────────────┐
│ ┌───────────┐ │ │ ┌───────────┐ │
│ │ App │ │ │ │ App │ │
│ └───────────┘ │ │ └───────────┘ │
│ ┌────────┐ ┌────────┐ │ │ ┌────────┐ ┌───────┐ │
│ │ Libs │ │ Deps │ │ │ │ Libs │ │ Deps │ │
│ └────────┘ └────────┘ │ │ └────────┘ └───────┘ │
│ ┌───────────────────┐ │ │ ┌──────────────────┐ │
│ │ Guest OS │ │ │ │ Guest OS │ │
│ └───────────────────┘ │ │ └──────────────────┘ │
│ VM1 │ │ VM2 │
└────────────────────────┘ └───────────────────────┘
┌──────────────────────────────────────────────────┐
│ Hypervisor │
└──────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────┐
│ Host OS │
└──────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────┐
│ Hardware Infrastructure │
└──────────────────────────────────────────────────┘
(VM based architecture)
┌────────────────────────┐ ┌───────────────────────┐
│ ┌───────────┐ │ │ ┌───────────┐ │
│ │ App │ │ │ │ App │ │
│ └───────────┘ │ │ └───────────┘ │
│ ┌────────┐ ┌────────┐ │ │ ┌────────┐ ┌───────┐ │
│ │ Libs │ │ Deps │ │ │ │ Libs │ │ Deps │ │
│ └────────┘ └────────┘ │ │ └────────┘ └───────┘ │
│ Container1 │ │ Container2 │
└────────────────────────┘ └───────────────────────┘
┌──────────────────────────────────────────────────┐
│ Docker │
└──────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────┐
│ OS │
└──────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────┐
│ Hardware Infrastructure │
└──────────────────────────────────────────────────┘
(Docker based architecture)
</pre>
Couple of terms we will encounter frequently are Docker Images and Docker
Containers. Images are packages or templates of containers all stored in a
container registry such as [Docker Hub](https://hub.docker.com/). Containers
are standalone, executable instances of these images which include code,
runtime, system tools, system libraries and settings - everything required to
get the software up and running. Coming to Docker, it follows a client-server
architecture wherein the CLI client communicates with the server component,
which here is, the Docker Engine using RESTful API to issue commands.
## The Docker CLI
```bash
# after installing Docker from https://docs.docker.com/get-docker/
# To list available commands, either run `docker` with no parameters or execute
# `docker help`
$ docker
>>> docker [OPTIONS] COMMAND [ARG...]
docker [ --help | -v | --version ]
A self-sufficient runtime for containers.
Options:
--config string Location of client config files (default "/root/.docker")
-c, --context string Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set with "docker context use")
-D, --debug Enable debug mode
--help Print usage
-H, --host value Daemon socket(s) to connect to (default [])
-l, --log-level string Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
--tls Use TLS; implied by --tlsverify
--tlscacert string Trust certs signed only by this CA (default "/root/.docker/ca.pem")
--tlscert string Path to TLS certificate file (default "/root/.docker/cert.pem")
--tlskey string Path to TLS key file (default "/root/.docker/key.pem")
--tlsverify Use TLS and verify the remote
-v, --version Print version information and quit
Commands:
attach Attach to a running container
# […]
$ docker run hello-world
# `docker run <container-name>` is used to run a container, it will pull the
# images from Docker Hub if they don't already exist in your system. Here the
# docker client connects to the daemon which in turn pulls the "hello-world"
# image from the Docker Hub. The daemon then builds a new container from the
# image which runs the executable that produces the output streamed back to the
# client that we see on our terminals.
$ docker run -d ubuntu sleep 60s
# The -d (or --detach) flag is when we want to run a container in the background
# and return back to the terminal. Here we detach an ubuntu container from the
# terminal, the output should be the id and the command exits. If we check
# running containers, we should still see ours there:
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 133261b4894a ubuntu "sleep 60s" 3 seconds ago Up 2 seconds vigorous_gould
$ docker run <container-id> -p 3000:8000
# The -p (or --publish) flag is used to expose port 8000 inside the container to
# port 3000 outside the container. This is because the app inside the container
# runs in isolation, hence the port 8000 where the app runs is private to the
# container.
$ docker run -i
# or
$ docker run -it
# Docker runs our containers in a non-interactive mode i.e. they do not accept
# inputs or work dynamically while running. The -i flag keeps input open to the
# container, and the -t flag creates a pseudo-terminal that the shell can attach
# to (can be combined as -it)
$ docker ps -a
# The `docker ps` command only shows running containers by default. To see all
# containers, use the -a (or --all) flag
# Running the above command should output something similar in the terminal:
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 82f84bf6912b hello-world "/hello" 9 minutes ago Exited (0) 9 minutes ago eloquent_sammet
$ docker stop hello-world
# or
$ docker start hello-world
# The stop command simply stops one or more containers, and the start command
# starts the container(s) up again! `docker start -a ubuntu` will attach our
# detached container back to the terminal i.e. runs in the foreground
$ docker create alpine
# `docker create` creates a new container for us with the image specified (here,
# alpine), the container does not auto-start unlike `docker run`. This command
# is used to set up a container configuration and then `docker start` to shoot
# it up when required. Note that the status is "Created":
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 4c71c727c73d alpine "/bin/sh" 29 seconds ago Created naughty_ritchie
$ docker rm 82f84
# Removes one or more containers using their container ID.
# P.S.: we can use only the first few characters of the entire ID to identify
# containers
$ docker images
# Displays all images and their information, created here means the latest image
# tag updated on Docker Hub:
# REPOSITORY TAG IMAGE ID CREATED SIZE
# ubuntu latest a8780b506fa4 9 days ago 77.8MB
# alpine latest 9c6f07244728 3 months ago 5.54MB
# hello-world latest feb5d9fea6a5 13 months ago 13.3kB
$ docker rmi
# Removes one or more images from your system which do not have their instances
# (or containers as we know them) running. If the image has an attached
# container, either delete the container first or use the -f (or --force) flag
# to forcefully delete both the container and image.
$ docker pull busybox
# The pull command downloads the specified image on our system from Docker Hub.
$ docker exec -it 7b272 bash
# This command is used to run a command in the running container's default
# directory. Here 7b272 was our ubuntu container and the above command would
# help us interact with the container by opening a bash session.
$ docker logs <container-id>
# Displays the information logged by the specified container
# root@7b27222e4bb7:/# whoami
# root
# root@7b27222e4bb7:/# pwd
# /
# root@7b27222e4bb7:/# ls
# bin boot dev etc home lib lib32 lib64 libx3 srv sys tmp usr var
# root@7b27222e4bb7:/# exit
# exit
# More commands can be found at https://docs.docker.com/engine/reference/commandline/docker/
```
## The Dockerfile
The Dockerfile is a blueprint of a Docker image. We can mention the artifacts
from our application along with their configurations into this file in the
specific syntax to let anyone create a Docker image of our application.
### A few things to keep in mind:
* It is always strictly named `Dockerfile` without any extensions
* We have to build our custom image on top of some already available Docker base
image. (there is an empty image called `scratch` which literally lets you build
an image from scratch)
* All capitalised commands are part of the syntax, they are not case-sensitive
but used like a convention
* Below is a sample Dockerfile but you can read in depth from the [official docs](https://docs.docker.com/engine/reference/builder/).
```Dockerfile
FROM <base-image>
# define base image
ENV USERNAME='admin'\
PWD='****'
# optionally define environmental variables
RUN apt-get update
# run linux commands inside container env, does not affect host env
# This executes during the time of image creation
COPY <src> <target>
# executes on the host, copies files from src (usually on the host) to target
# on the container
ENTRYPOINT ["some-script.sh"]
# executes an entire script as an entrypoint
CMD [<args>,...]
# always part of dockerfile, introduces entry point linux command e.g.
# `CMD node server.js`
# This executes after image creation only when the container from the image
# is running.
```
### Build your images
Use the `docker build` command after wrapping your application into a Docker
image to run ( or build) it.
```bash
$ docker build <path-to-dockerfile>
# used to build an image from the specified Dockerfile
# instead of path we could also specify a URL
# -t tag is optional and used to name and tag your images for e.g.
# `$ docker build -t my-image:0.1 ./home/app`
# rebuild images everytime you make changes in the dockerfile
```
## Push your image to DockerHub
If you want your application's Docker image to be made publicly available for
any Docker user, you might wanna push it to the [Docker Hub](https://hub.docker.com/) which is a
registry of Docker images. Make sure you have an account with a username and
password on Docker Hub.
When pushing an image to Docker Hub, we must specify our Docker Hub username
as part of the source image name. We need to create the target image with the
tag name of username/image-name much like GitHub repositories.
```bash
$ docker login
# to login to Docker Hub using your username and password
$ docker tag <src-image>[:<src-tag>] <target-image>[:<target-tag>]
# this tags a local src-image to a public target-image
# e.g. `docker tag my-sample-app:1.0.0 akshitadixit/my-sample-app`
# if tags are not specified, they're defaulted to `latest`
$ docker push <target-image>[:<target-tag>]
# uploads our image to Docker Hub
# e.g. `docker push akshitadixit/my-sample-app`
# this image will be accessible under your profile's repositories as
# `https://hub.docker.com/r/username/image-name`
```

View File

@ -1,167 +1,167 @@
---
language: docker
filename: docker-es.bat
contributors:
- ["Ruslan López", "http://javapro.org/"]
- ["Michael Chen", "https://github.com/ML-Chen"]
lang: es-es
---
```bat
:: descargar, instalar y ejecutar la imágen del hola mundo
docker run hello-world
:: Si esta es la primera vez, deberíais de poder ver el mensaje
:: Unable to find image 'hello-world:latest' locally
:: latest: Pulling from library/hello-world
:: 1b930d010525: Pull complete
:: Digest: sha256:4fe721ccc2e8dc7362278a29dc660d833570ec2682f4e4194f4ee23e415e1064
:: Status: Downloaded newer image for hello-world:latest
::
:: Hello from Docker!
:: This message shows that your installation appears to be working correctly.
::
:: To generate this message, Docker took the following steps:
:: 1. The Docker client contacted the Docker daemon.
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
:: (amd64)
:: 3. The Docker daemon created a new container from that image which runs the
:: executable that produces the output you are currently reading.
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
:: to your terminal.
::
:: To try something more ambitious, you can run an Ubuntu container with:
:: $ docker run -it ubuntu bash
::
:: Share images, automate workflows, and more with a free Docker ID:
:: https://hub.docker.com/
::
:: For more examples and ideas, visit:
:: https://docs.docker.com/get-started/
:: El susodicho mensaje se podría traducir como:
::
:: Hola desde Docker!
:: Este mensaje muestra que su instalación parece estar funcionando crrectamente.
::
:: Para generar este mensaje, Docker realizó los siguientes pasos:
:: 1. El cliente de Docker contactó a Docker daemon.
:: 2. El Docker daemon obtubo la imágen "hello-world" desde Docker Hub.
:: (amd64)
:: 3. El Docker daemon creó un nuevo contenedor a partir de esa imagen con la cual ejecuta el
:: ejecutable que produce la salida que estás leyendo.
:: 4. El Docker daemon transmitió dicha salida el cliente Docker, el cual
:: la envió a tu terminal.
::
:: Para intentar algo más ambicioso, puede correr un contenedor Ubuntu mediante:
:: $ docker run -it ubuntu bash
::
:: Comparte imágenes, automatice flujos y más con un Docker ID gratuito:
:: https://hub.docker.com/
:: ahora veamos las imágenes que se están ejecutando actualmente
docker ps
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
:: NAMES
:: veamos las imágenes que hemos ejecutado previamente
docker ps -a
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
:: NAMES
:: 4a76281f9c53 hello-world "/hello" 2 minutes ago Exited (0) 2 minutes ago
:: happy_poincare
:: la parte del nombre se genera automáticamente, así que probablemente sea diferente para vos
:: eliminemos nuestra imagen previamente generada
docker rm happy_poincare
:: verifiquemos si realmente fue borrada
docker ps -a
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
:: NAMES
:: especifiquemos un nombre personalizado para el contenedor
docker run --name test_container hello-world
:: Hello from Docker!
:: This message shows that your installation appears to be working correctly.
::
:: To generate this message, Docker took the following steps:
:: 1. The Docker client contacted the Docker daemon.
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
:: (amd64)
:: 3. The Docker daemon created a new container from that image which runs the
:: executable that produces the output you are currently reading.
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
:: to your terminal.
::
:: To try something more ambitious, you can run an Ubuntu container with:
:: $ docker run -it ubuntu bash
::
:: Share images, automate workflows, and more with a free Docker ID:
:: https://hub.docker.com/
::
:: For more examples and ideas, visit:
:: https://docs.docker.com/get-started/
docker ps -a
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
:: NAMES
:: d345fe1a4f41 hello-world "/hello" About a minute ago Exited (0) About a minute ago
:: test_container
:: tal como podeis ver el nombre es el que especificamos
:: obtener los registros de un contenedor nombrado
docker logs test_container
:: Hello from Docker!
:: This message shows that your installation appears to be working correctly.
::
:: To generate this message, Docker took the following steps:
:: 1. The Docker client contacted the Docker daemon.
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
:: (amd64)
:: 3. The Docker daemon created a new container from that image which runs the
:: executable that produces the output you are currently reading.
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
:: to your terminal.
::
:: To try something more ambitious, you can run an Ubuntu container with:
:: $ docker run -it ubuntu bash
::
:: Share images, automate workflows, and more with a free Docker ID:
:: https://hub.docker.com/
::
:: For more examples and ideas, visit:
:: https://docs.docker.com/get-started/
docker rm test_container
docker run ubuntu
:: Unable to find image 'ubuntu:latest' locally
:: latest: Pulling from library/ubuntu
:: 2746a4a261c9: Pull complete
:: 4c1d20cdee96: Pull complete 0d3160e1d0de: Pull complete c8e37668deea: Pull complete Digest: sha256:250cc6f3f3ffc5cdaa9d8f4946ac79821aafb4d3afc93928f0de9336eba21aa4
:: Status: Downloaded newer image for ubuntu:latest
docker ps -a
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
:: NAMES
:: c19e9e5b000a ubuntu "/bin/bash" 5 seconds ago Exited (0) 4 seconds ago
:: relaxed_nobel
:: ejecutando un contenedor en modo interactivo
docker run -it ubuntu
:: root@e2cac48323d2:/# uname
:: Linux
:: root@e2cac48323d2:/# exit
:: exit
docker rm relaxed_nobel
docker ps -a
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
:: NAMES
:: e2cac48323d2 ubuntu "/bin/bash" 2 minutes ago Exited (0) About a minute ago
:: nifty_goldwasser
docker rm nifty_goldwasser
```
---
language: docker
filename: docker-es.bat
contributors:
- ["Ruslan López", "http://javapro.org/"]
- ["Michael Chen", "https://github.com/ML-Chen"]
lang: es-es
---
```bat
:: descargar, instalar y ejecutar la imágen del hola mundo
docker run hello-world
:: Si esta es la primera vez, deberíais de poder ver el mensaje
:: Unable to find image 'hello-world:latest' locally
:: latest: Pulling from library/hello-world
:: 1b930d010525: Pull complete
:: Digest: sha256:4fe721ccc2e8dc7362278a29dc660d833570ec2682f4e4194f4ee23e415e1064
:: Status: Downloaded newer image for hello-world:latest
::
:: Hello from Docker!
:: This message shows that your installation appears to be working correctly.
::
:: To generate this message, Docker took the following steps:
:: 1. The Docker client contacted the Docker daemon.
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
:: (amd64)
:: 3. The Docker daemon created a new container from that image which runs the
:: executable that produces the output you are currently reading.
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
:: to your terminal.
::
:: To try something more ambitious, you can run an Ubuntu container with:
:: $ docker run -it ubuntu bash
::
:: Share images, automate workflows, and more with a free Docker ID:
:: https://hub.docker.com/
::
:: For more examples and ideas, visit:
:: https://docs.docker.com/get-started/
:: El susodicho mensaje se podría traducir como:
::
:: Hola desde Docker!
:: Este mensaje muestra que su instalación parece estar funcionando crrectamente.
::
:: Para generar este mensaje, Docker realizó los siguientes pasos:
:: 1. El cliente de Docker contactó a Docker daemon.
:: 2. El Docker daemon obtubo la imágen "hello-world" desde Docker Hub.
:: (amd64)
:: 3. El Docker daemon creó un nuevo contenedor a partir de esa imagen con la cual ejecuta el
:: ejecutable que produce la salida que estás leyendo.
:: 4. El Docker daemon transmitió dicha salida el cliente Docker, el cual
:: la envió a tu terminal.
::
:: Para intentar algo más ambicioso, puede correr un contenedor Ubuntu mediante:
:: $ docker run -it ubuntu bash
::
:: Comparte imágenes, automatice flujos y más con un Docker ID gratuito:
:: https://hub.docker.com/
:: ahora veamos las imágenes que se están ejecutando actualmente
docker ps
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
:: NAMES
:: veamos las imágenes que hemos ejecutado previamente
docker ps -a
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
:: NAMES
:: 4a76281f9c53 hello-world "/hello" 2 minutes ago Exited (0) 2 minutes ago
:: happy_poincare
:: la parte del nombre se genera automáticamente, así que probablemente sea diferente para vos
:: eliminemos nuestra imagen previamente generada
docker rm happy_poincare
:: verifiquemos si realmente fue borrada
docker ps -a
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
:: NAMES
:: especifiquemos un nombre personalizado para el contenedor
docker run --name test_container hello-world
:: Hello from Docker!
:: This message shows that your installation appears to be working correctly.
::
:: To generate this message, Docker took the following steps:
:: 1. The Docker client contacted the Docker daemon.
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
:: (amd64)
:: 3. The Docker daemon created a new container from that image which runs the
:: executable that produces the output you are currently reading.
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
:: to your terminal.
::
:: To try something more ambitious, you can run an Ubuntu container with:
:: $ docker run -it ubuntu bash
::
:: Share images, automate workflows, and more with a free Docker ID:
:: https://hub.docker.com/
::
:: For more examples and ideas, visit:
:: https://docs.docker.com/get-started/
docker ps -a
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
:: NAMES
:: d345fe1a4f41 hello-world "/hello" About a minute ago Exited (0) About a minute ago
:: test_container
:: tal como podeis ver el nombre es el que especificamos
:: obtener los registros de un contenedor nombrado
docker logs test_container
:: Hello from Docker!
:: This message shows that your installation appears to be working correctly.
::
:: To generate this message, Docker took the following steps:
:: 1. The Docker client contacted the Docker daemon.
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
:: (amd64)
:: 3. The Docker daemon created a new container from that image which runs the
:: executable that produces the output you are currently reading.
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
:: to your terminal.
::
:: To try something more ambitious, you can run an Ubuntu container with:
:: $ docker run -it ubuntu bash
::
:: Share images, automate workflows, and more with a free Docker ID:
:: https://hub.docker.com/
::
:: For more examples and ideas, visit:
:: https://docs.docker.com/get-started/
docker rm test_container
docker run ubuntu
:: Unable to find image 'ubuntu:latest' locally
:: latest: Pulling from library/ubuntu
:: 2746a4a261c9: Pull complete
:: 4c1d20cdee96: Pull complete 0d3160e1d0de: Pull complete c8e37668deea: Pull complete Digest: sha256:250cc6f3f3ffc5cdaa9d8f4946ac79821aafb4d3afc93928f0de9336eba21aa4
:: Status: Downloaded newer image for ubuntu:latest
docker ps -a
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
:: NAMES
:: c19e9e5b000a ubuntu "/bin/bash" 5 seconds ago Exited (0) 4 seconds ago
:: relaxed_nobel
:: ejecutando un contenedor en modo interactivo
docker run -it ubuntu
:: root@e2cac48323d2:/# uname
:: Linux
:: root@e2cac48323d2:/# exit
:: exit
docker rm relaxed_nobel
docker ps -a
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
:: NAMES
:: e2cac48323d2 ubuntu "/bin/bash" 2 minutes ago Exited (0) About a minute ago
:: nifty_goldwasser
docker rm nifty_goldwasser
```

View File

@ -1,276 +1,276 @@
---
language: toml
filename: learntoml-it.toml
contributors:
- ["Alois de Gouvello", "https://github.com/aloisdg"]
translators:
- ["Christian Grasso", "https://grasso.io"]
lang: it-it
---
TOML è l'acronimo di _Tom's Obvious, Minimal Language_. È un linguaggio per la
serializzazione di dati, progettato per i file di configurazione.
È un'alternativa a linguaggi come YAML e JSON, che punta ad essere più leggibile
per le persone. Allo stesso tempo, TOML può essere utilizzato in modo abbastanza
semplice nella maggior parte dei linguaggi di programmazione, in quanto è
progettato per essere tradotto senza ambiguità in una hash table.
Tieni presente che TOML è ancora in fase di sviluppo, e la sua specifica non è
ancora stabile. Questo documento utilizza TOML 0.4.0.
```toml
# I commenti in TOML sono fatti così.
################
# TIPI SCALARI #
################
# Il nostro oggetto root (corrispondente all'intero documento) sarà una mappa,
# anche chiamata dizionario, hash o oggetto in altri linguaggi.
# La key, il simbolo di uguale e il valore devono trovarsi sulla stessa riga,
# eccetto per alcuni tipi di valori.
key = "value"
stringa = "ciao"
numero = 42
float = 3.14
boolean = true
data = 1979-05-27T07:32:00-08:00
notazScientifica = 1e+12
"puoi utilizzare le virgolette per la key" = true # Puoi usare " oppure '
"la key può contenere" = "lettere, numeri, underscore e trattini"
############
# Stringhe #
############
# Le stringhe possono contenere solo caratteri UTF-8 validi.
# Possiamo effettuare l'escape dei caratteri, e alcuni hanno delle sequenze
# di escape compatte. Ad esempio, \t corrisponde al TAB.
stringaSemplice = "Racchiusa tra virgolette. \"Usa il backslash per l'escape\"."
stringaMultiriga = """
Racchiusa da tre virgolette doppie all'inizio e
alla fine - consente di andare a capo."""
stringaLiteral = 'Virgolette singole. Non consente di effettuare escape.'
stringaMultirigaLiteral = '''
Racchiusa da tre virgolette singole all'inizio e
alla fine - consente di andare a capo.
Anche in questo caso non si può fare escape.
Il primo ritorno a capo viene eliminato.
Tutti gli altri spazi aggiuntivi
vengono mantenuti.
'''
# Per i dati binari è consigliabile utilizzare Base64 e
# gestirli manualmente dall'applicazione.
##########
# Interi #
##########
## Gli interi possono avere o meno un segno (+, -).
## Non si possono inserire zero superflui all'inizio.
## Non è possibile inoltre utilizzare valori numerici
## non rappresentabili con una sequenza di cifre.
int1 = +42
int2 = 0
int3 = -21
## Puoi utilizzare gli underscore per migliorare la leggibilità.
## Fai attenzione a non inserirne due di seguito.
int4 = 5_349_221
int5 = 1_2_3_4_5 # VALIDO, ma da evitare
#########
# Float #
#########
# I float permettono di rappresentare numeri decimali.
flt1 = 3.1415
flt2 = -5e6
flt3 = 6.626E-34
###########
# Boolean #
###########
# I valori boolean (true/false) devono essere scritti in minuscolo.
bool1 = true
bool2 = false
############
# Data/ora #
############
data1 = 1979-05-27T07:32:00Z # Specifica RFC 3339/ISO 8601 (UTC)
data2 = 1979-05-26T15:32:00+08:00 # RFC 3339/ISO 8601 con offset
######################
# TIPI DI COLLECTION #
######################
#########
# Array #
#########
array1 = [ 1, 2, 3 ]
array2 = [ "Le", "virgole", "sono", "delimitatori" ]
array3 = [ "Non", "unire", "tipi", "diversi" ]
array4 = [ "tutte", 'le stringhe', """hanno lo stesso""", '''tipo''' ]
array5 = [
"Gli spazi vuoti", "sono", "ignorati"
]
###########
# Tabelle #
###########
# Le tabelle (o hash table o dizionari) sono collection di coppie key/value.
# Iniziano con un nome tra parentesi quadre su una linea separata.
# Le tabelle vuote (senza alcun valore) sono valide.
[tabella]
# Tutti i valori che si trovano sotto il nome della tabella
# appartengono alla tabella stessa (finchè non ne viene creata un'altra).
# L'ordine di questi valori non è garantito.
[tabella-1]
key1 = "una stringa"
key2 = 123
[tabella-2]
key1 = "un'altra stringa"
key2 = 456
# Utilizzando i punti è possibile creare delle sottotabelle.
# Ogni parte suddivisa dai punti segue le regole delle key per il nome.
[tabella-3."sotto.tabella"]
key1 = "prova"
# Ecco l'equivalente JSON della tabella precedente:
# { "tabella-3": { "sotto.tabella": { "key1": "prova" } } }
# Gli spazi non vengono considerati, ma è consigliabile
# evitare di usare spazi superflui.
[a.b.c] # consigliato
[ d.e.f ] # identico a [d.e.f]
# Non c'è bisogno di creare le tabelle superiori per creare una sottotabella.
# [x] queste
# [x.y] non
# [x.y.z] servono
[x.y.z.w] # per creare questa tabella
# Se non è stata già creata prima, puoi anche creare
# una tabella superiore più avanti.
[a.b]
c = 1
[a]
d = 2
# Non puoi definire una key o una tabella più di una volta.
# ERRORE
[a]
b = 1
[a]
c = 2
# ERRORE
[a]
b = 1
[a.b]
c = 2
# I nomi delle tabelle non possono essere vuoti.
[] # NON VALIDO
[a.] # NON VALIDO
[a..b] # NON VALIDO
[.b] # NON VALIDO
[.] # NON VALIDO
##################
# Tabelle inline #
##################
tabelleInline = { racchiuseData = "{ e }", rigaSingola = true }
punto = { x = 1, y = 2 }
####################
# Array di tabelle #
####################
# Un array di tabelle può essere creato utilizzando due parentesi quadre.
# Tutte le tabelle con questo nome saranno elementi dell'array.
# Gli elementi vengono inseriti nell'ordine in cui si trovano.
[[prodotti]]
nome = "array di tabelle"
sku = 738594937
tabelleVuoteValide = true
[[prodotti]]
[[prodotti]]
nome = "un altro item"
sku = 284758393
colore = "grigio"
# Puoi anche creare array di tabelle nested. Le sottotabelle con doppie
# parentesi quadre apparterranno alla tabella più vicina sopra di esse.
[[frutta]]
nome = "mela"
[frutto.geometria]
forma = "sferica"
nota = "Sono una proprietà del frutto"
[[frutto.colore]]
nome = "rosso"
nota = "Sono un oggetto di un array dentro mela"
[[frutto.colore]]
nome = "verde"
nota = "Sono nello stesso array di rosso"
[[frutta]]
nome = "banana"
[[frutto.colore]]
nome = "giallo"
nota = "Anche io sono un oggetto di un array, ma dentro banana"
```
Ecco l'equivalente JSON dell'ultima tabella:
```json
{
"frutta": [
{
"nome": "mela",
"geometria": { "forma": "sferica", "nota": "..."},
"colore": [
{ "nome": "rosso", "nota": "..." },
{ "nome": "verde", "nota": "..." }
]
},
{
"nome": "banana",
"colore": [
{ "nome": "giallo", "nota": "..." }
]
}
]
}
```
### Altre risorse
+ [Repository ufficiale di TOML](https://github.com/toml-lang/toml)
---
language: toml
filename: learntoml-it.toml
contributors:
- ["Alois de Gouvello", "https://github.com/aloisdg"]
translators:
- ["Christian Grasso", "https://grasso.io"]
lang: it-it
---
TOML è l'acronimo di _Tom's Obvious, Minimal Language_. È un linguaggio per la
serializzazione di dati, progettato per i file di configurazione.
È un'alternativa a linguaggi come YAML e JSON, che punta ad essere più leggibile
per le persone. Allo stesso tempo, TOML può essere utilizzato in modo abbastanza
semplice nella maggior parte dei linguaggi di programmazione, in quanto è
progettato per essere tradotto senza ambiguità in una hash table.
Tieni presente che TOML è ancora in fase di sviluppo, e la sua specifica non è
ancora stabile. Questo documento utilizza TOML 0.4.0.
```toml
# I commenti in TOML sono fatti così.
################
# TIPI SCALARI #
################
# Il nostro oggetto root (corrispondente all'intero documento) sarà una mappa,
# anche chiamata dizionario, hash o oggetto in altri linguaggi.
# La key, il simbolo di uguale e il valore devono trovarsi sulla stessa riga,
# eccetto per alcuni tipi di valori.
key = "value"
stringa = "ciao"
numero = 42
float = 3.14
boolean = true
data = 1979-05-27T07:32:00-08:00
notazScientifica = 1e+12
"puoi utilizzare le virgolette per la key" = true # Puoi usare " oppure '
"la key può contenere" = "lettere, numeri, underscore e trattini"
############
# Stringhe #
############
# Le stringhe possono contenere solo caratteri UTF-8 validi.
# Possiamo effettuare l'escape dei caratteri, e alcuni hanno delle sequenze
# di escape compatte. Ad esempio, \t corrisponde al TAB.
stringaSemplice = "Racchiusa tra virgolette. \"Usa il backslash per l'escape\"."
stringaMultiriga = """
Racchiusa da tre virgolette doppie all'inizio e
alla fine - consente di andare a capo."""
stringaLiteral = 'Virgolette singole. Non consente di effettuare escape.'
stringaMultirigaLiteral = '''
Racchiusa da tre virgolette singole all'inizio e
alla fine - consente di andare a capo.
Anche in questo caso non si può fare escape.
Il primo ritorno a capo viene eliminato.
Tutti gli altri spazi aggiuntivi
vengono mantenuti.
'''
# Per i dati binari è consigliabile utilizzare Base64 e
# gestirli manualmente dall'applicazione.
##########
# Interi #
##########
## Gli interi possono avere o meno un segno (+, -).
## Non si possono inserire zero superflui all'inizio.
## Non è possibile inoltre utilizzare valori numerici
## non rappresentabili con una sequenza di cifre.
int1 = +42
int2 = 0
int3 = -21
## Puoi utilizzare gli underscore per migliorare la leggibilità.
## Fai attenzione a non inserirne due di seguito.
int4 = 5_349_221
int5 = 1_2_3_4_5 # VALIDO, ma da evitare
#########
# Float #
#########
# I float permettono di rappresentare numeri decimali.
flt1 = 3.1415
flt2 = -5e6
flt3 = 6.626E-34
###########
# Boolean #
###########
# I valori boolean (true/false) devono essere scritti in minuscolo.
bool1 = true
bool2 = false
############
# Data/ora #
############
data1 = 1979-05-27T07:32:00Z # Specifica RFC 3339/ISO 8601 (UTC)
data2 = 1979-05-26T15:32:00+08:00 # RFC 3339/ISO 8601 con offset
######################
# TIPI DI COLLECTION #
######################
#########
# Array #
#########
array1 = [ 1, 2, 3 ]
array2 = [ "Le", "virgole", "sono", "delimitatori" ]
array3 = [ "Non", "unire", "tipi", "diversi" ]
array4 = [ "tutte", 'le stringhe', """hanno lo stesso""", '''tipo''' ]
array5 = [
"Gli spazi vuoti", "sono", "ignorati"
]
###########
# Tabelle #
###########
# Le tabelle (o hash table o dizionari) sono collection di coppie key/value.
# Iniziano con un nome tra parentesi quadre su una linea separata.
# Le tabelle vuote (senza alcun valore) sono valide.
[tabella]
# Tutti i valori che si trovano sotto il nome della tabella
# appartengono alla tabella stessa (finchè non ne viene creata un'altra).
# L'ordine di questi valori non è garantito.
[tabella-1]
key1 = "una stringa"
key2 = 123
[tabella-2]
key1 = "un'altra stringa"
key2 = 456
# Utilizzando i punti è possibile creare delle sottotabelle.
# Ogni parte suddivisa dai punti segue le regole delle key per il nome.
[tabella-3."sotto.tabella"]
key1 = "prova"
# Ecco l'equivalente JSON della tabella precedente:
# { "tabella-3": { "sotto.tabella": { "key1": "prova" } } }
# Gli spazi non vengono considerati, ma è consigliabile
# evitare di usare spazi superflui.
[a.b.c] # consigliato
[ d.e.f ] # identico a [d.e.f]
# Non c'è bisogno di creare le tabelle superiori per creare una sottotabella.
# [x] queste
# [x.y] non
# [x.y.z] servono
[x.y.z.w] # per creare questa tabella
# Se non è stata già creata prima, puoi anche creare
# una tabella superiore più avanti.
[a.b]
c = 1
[a]
d = 2
# Non puoi definire una key o una tabella più di una volta.
# ERRORE
[a]
b = 1
[a]
c = 2
# ERRORE
[a]
b = 1
[a.b]
c = 2
# I nomi delle tabelle non possono essere vuoti.
[] # NON VALIDO
[a.] # NON VALIDO
[a..b] # NON VALIDO
[.b] # NON VALIDO
[.] # NON VALIDO
##################
# Tabelle inline #
##################
tabelleInline = { racchiuseData = "{ e }", rigaSingola = true }
punto = { x = 1, y = 2 }
####################
# Array di tabelle #
####################
# Un array di tabelle può essere creato utilizzando due parentesi quadre.
# Tutte le tabelle con questo nome saranno elementi dell'array.
# Gli elementi vengono inseriti nell'ordine in cui si trovano.
[[prodotti]]
nome = "array di tabelle"
sku = 738594937
tabelleVuoteValide = true
[[prodotti]]
[[prodotti]]
nome = "un altro item"
sku = 284758393
colore = "grigio"
# Puoi anche creare array di tabelle nested. Le sottotabelle con doppie
# parentesi quadre apparterranno alla tabella più vicina sopra di esse.
[[frutta]]
nome = "mela"
[frutto.geometria]
forma = "sferica"
nota = "Sono una proprietà del frutto"
[[frutto.colore]]
nome = "rosso"
nota = "Sono un oggetto di un array dentro mela"
[[frutto.colore]]
nome = "verde"
nota = "Sono nello stesso array di rosso"
[[frutta]]
nome = "banana"
[[frutto.colore]]
nome = "giallo"
nota = "Anche io sono un oggetto di un array, ma dentro banana"
```
Ecco l'equivalente JSON dell'ultima tabella:
```json
{
"frutta": [
{
"nome": "mela",
"geometria": { "forma": "sferica", "nota": "..."},
"colore": [
{ "nome": "rosso", "nota": "..." },
{ "nome": "verde", "nota": "..." }
]
},
{
"nome": "banana",
"colore": [
{ "nome": "giallo", "nota": "..." }
]
}
]
}
```
### Altre risorse
+ [Repository ufficiale di TOML](https://github.com/toml-lang/toml)

View File

@ -1,246 +1,246 @@
---
category: tool
tool: make
contributors:
- ["Robert Steed", "https://github.com/robochat"]
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
filename: Makefile
---
A Makefile defines a graph of rules for creating a target (or targets).
Its purpose is to do the minimum amount of work needed to update a
target to the most recent version of the source. Famously written over a
weekend by Stuart Feldman in 1976, it is still widely used (particularly
on Unix and Linux) despite many competitors and criticisms.
There are many varieties of make in existence, however this article
assumes that we are using GNU make which is the standard on Linux.
```make
# Comments can be written like this.
# File should be named Makefile and then can be run as `make <target>`.
# Otherwise we use `make -f "filename" <target>`.
# Warning - only use TABS to indent in Makefiles, never spaces!
#-----------------------------------------------------------------------
# Basics
#-----------------------------------------------------------------------
# Rules are of the format
# target: <prerequisite>
# where prerequisites are optional.
# A rule - this rule will only run if file0.txt doesn't exist.
file0.txt:
echo "foo" > file0.txt
# Even comments in these 'recipe' sections get passed to the shell.
# Try `make file0.txt` or simply `make` - first rule is the default.
# This rule will only run if file0.txt is newer than file1.txt.
file1.txt: file0.txt
cat file0.txt > file1.txt
# use the same quoting rules as in the shell.
@cat file0.txt >> file1.txt
# @ stops the command from being echoed to stdout.
-@echo 'hello'
# - means that make will keep going in the case of an error.
# Try `make file1.txt` on the commandline.
# A rule can have multiple targets and multiple prerequisites
file2.txt file3.txt: file0.txt file1.txt
touch file2.txt
touch file3.txt
# Make will complain about multiple recipes for the same rule. Empty
# recipes don't count though and can be used to add new dependencies.
#-----------------------------------------------------------------------
# Phony Targets
#-----------------------------------------------------------------------
# A phony target. Any target that isn't a file.
# It will never be up to date so make will always try to run it.
all: maker process
# We can declare things out of order.
maker:
touch ex0.txt ex1.txt
# Can avoid phony rules breaking when a real file has the same name by
.PHONY: all maker process
# This is a special target. There are several others.
# A rule with a dependency on a phony target will always run
ex0.txt ex1.txt: maker
# Common phony targets are: all make clean install ...
#-----------------------------------------------------------------------
# Automatic Variables & Wildcards
#-----------------------------------------------------------------------
process: file*.txt #using a wildcard to match filenames
@echo $^ # $^ is a variable containing the list of prerequisites
@echo $@ # prints the target name
#(for multiple target rules, $@ is whichever caused the rule to run)
@echo $< # the first prerequisite listed
@echo $? # only the dependencies that are out of date
@echo $+ # all dependencies including duplicates (unlike normal)
#@echo $| # all of the 'order only' prerequisites
# Even if we split up the rule dependency definitions, $^ will find them
process: ex1.txt file0.txt
# ex1.txt will be found but file0.txt will be deduplicated.
#-----------------------------------------------------------------------
# Patterns
#-----------------------------------------------------------------------
# Can teach make how to convert certain files into other files.
%.png: %.svg
inkscape --export-png $^
# Pattern rules will only do anything if make decides to create the
# target.
# Directory paths are normally ignored when matching pattern rules. But
# make will try to use the most appropriate rule available.
small/%.png: %.svg
inkscape --export-png --export-dpi 30 $^
# make will use the last version for a pattern rule that it finds.
%.png: %.svg
@echo this rule is chosen
# However make will use the first pattern rule that can make the target
%.png: %.ps
@echo this rule is not chosen if *.svg and *.ps are both present
# make already has some pattern rules built-in. For instance, it knows
# how to turn *.c files into *.o files.
# Older makefiles might use suffix rules instead of pattern rules
.png.ps:
@echo this rule is similar to a pattern rule.
# Tell make about the suffix rule
.SUFFIXES: .png
#-----------------------------------------------------------------------
# Variables
#-----------------------------------------------------------------------
# aka. macros
# Variables are basically all string types
name = Ted
name2="Sarah"
echo:
@echo $(name)
@echo ${name2}
@echo $name # This won't work, treated as $(n)ame.
@echo $(name3) # Unknown variables are treated as empty strings.
# There are 4 places to set variables.
# In order of priority from highest to lowest:
# 1: commandline arguments
# 2: Makefile
# 3: shell environment variables - make imports these automatically.
# 4: make has some predefined variables
name4 ?= Jean
# Only set the variable if environment variable is not already defined.
override name5 = David
# Stops commandline arguments from changing this variable.
name4 +=grey
# Append values to variable (includes a space).
# Pattern-specific variable values (GNU extension).
echo: name2 = Sara # True within the matching rule
# and also within its remade recursive dependencies
# (except it can break when your graph gets too complicated!)
# Some variables defined automatically by make.
echo_inbuilt:
echo $(CC)
echo ${CXX}
echo $(FC)
echo ${CFLAGS}
echo $(CPPFLAGS)
echo ${CXXFLAGS}
echo $(LDFLAGS)
echo ${LDLIBS}
#-----------------------------------------------------------------------
# Variables 2
#-----------------------------------------------------------------------
# The first type of variables are evaluated each time they are used.
# This can be expensive, so a second type of variable exists which is
# only evaluated once. (This is a GNU make extension)
var := hello
var2 ::= $(var) hello
#:= and ::= are equivalent.
# These variables are evaluated procedurally (in the order that they
# appear), thus breaking with the rest of the language !
# This doesn't work
var3 ::= $(var4) and good luck
var4 ::= good night
#-----------------------------------------------------------------------
# Functions
#-----------------------------------------------------------------------
# make has lots of functions available.
sourcefiles = $(wildcard *.c */*.c)
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
# Format is $(func arg0,arg1,arg2...)
# Some examples
ls: * src/*
@echo $(filter %.txt, $^)
@echo $(notdir $^)
@echo $(join $(dir $^),$(notdir $^))
#-----------------------------------------------------------------------
# Directives
#-----------------------------------------------------------------------
# Include other makefiles, useful for platform specific code
include foo.mk
sport = tennis
# Conditional compilation
report:
ifeq ($(sport),tennis)
@echo 'game, set, match'
else
@echo "They think it's all over; it is now"
endif
# There are also ifneq, ifdef, ifndef
foo = true
ifdef $(foo)
bar = 'hello'
endif
```
### More Resources
+ [gnu make documentation](https://www.gnu.org/software/make/manual/)
+ [software carpentry tutorial](http://swcarpentry.github.io/make-novice/)
+ learn C the hard way [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html)
---
category: tool
tool: make
contributors:
- ["Robert Steed", "https://github.com/robochat"]
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
filename: Makefile
---
A Makefile defines a graph of rules for creating a target (or targets).
Its purpose is to do the minimum amount of work needed to update a
target to the most recent version of the source. Famously written over a
weekend by Stuart Feldman in 1976, it is still widely used (particularly
on Unix and Linux) despite many competitors and criticisms.
There are many varieties of make in existence, however this article
assumes that we are using GNU make which is the standard on Linux.
```make
# Comments can be written like this.
# File should be named Makefile and then can be run as `make <target>`.
# Otherwise we use `make -f "filename" <target>`.
# Warning - only use TABS to indent in Makefiles, never spaces!
#-----------------------------------------------------------------------
# Basics
#-----------------------------------------------------------------------
# Rules are of the format
# target: <prerequisite>
# where prerequisites are optional.
# A rule - this rule will only run if file0.txt doesn't exist.
file0.txt:
echo "foo" > file0.txt
# Even comments in these 'recipe' sections get passed to the shell.
# Try `make file0.txt` or simply `make` - first rule is the default.
# This rule will only run if file0.txt is newer than file1.txt.
file1.txt: file0.txt
cat file0.txt > file1.txt
# use the same quoting rules as in the shell.
@cat file0.txt >> file1.txt
# @ stops the command from being echoed to stdout.
-@echo 'hello'
# - means that make will keep going in the case of an error.
# Try `make file1.txt` on the commandline.
# A rule can have multiple targets and multiple prerequisites
file2.txt file3.txt: file0.txt file1.txt
touch file2.txt
touch file3.txt
# Make will complain about multiple recipes for the same rule. Empty
# recipes don't count though and can be used to add new dependencies.
#-----------------------------------------------------------------------
# Phony Targets
#-----------------------------------------------------------------------
# A phony target. Any target that isn't a file.
# It will never be up to date so make will always try to run it.
all: maker process
# We can declare things out of order.
maker:
touch ex0.txt ex1.txt
# Can avoid phony rules breaking when a real file has the same name by
.PHONY: all maker process
# This is a special target. There are several others.
# A rule with a dependency on a phony target will always run
ex0.txt ex1.txt: maker
# Common phony targets are: all make clean install ...
#-----------------------------------------------------------------------
# Automatic Variables & Wildcards
#-----------------------------------------------------------------------
process: file*.txt #using a wildcard to match filenames
@echo $^ # $^ is a variable containing the list of prerequisites
@echo $@ # prints the target name
#(for multiple target rules, $@ is whichever caused the rule to run)
@echo $< # the first prerequisite listed
@echo $? # only the dependencies that are out of date
@echo $+ # all dependencies including duplicates (unlike normal)
#@echo $| # all of the 'order only' prerequisites
# Even if we split up the rule dependency definitions, $^ will find them
process: ex1.txt file0.txt
# ex1.txt will be found but file0.txt will be deduplicated.
#-----------------------------------------------------------------------
# Patterns
#-----------------------------------------------------------------------
# Can teach make how to convert certain files into other files.
%.png: %.svg
inkscape --export-png $^
# Pattern rules will only do anything if make decides to create the
# target.
# Directory paths are normally ignored when matching pattern rules. But
# make will try to use the most appropriate rule available.
small/%.png: %.svg
inkscape --export-png --export-dpi 30 $^
# make will use the last version for a pattern rule that it finds.
%.png: %.svg
@echo this rule is chosen
# However make will use the first pattern rule that can make the target
%.png: %.ps
@echo this rule is not chosen if *.svg and *.ps are both present
# make already has some pattern rules built-in. For instance, it knows
# how to turn *.c files into *.o files.
# Older makefiles might use suffix rules instead of pattern rules
.png.ps:
@echo this rule is similar to a pattern rule.
# Tell make about the suffix rule
.SUFFIXES: .png
#-----------------------------------------------------------------------
# Variables
#-----------------------------------------------------------------------
# aka. macros
# Variables are basically all string types
name = Ted
name2="Sarah"
echo:
@echo $(name)
@echo ${name2}
@echo $name # This won't work, treated as $(n)ame.
@echo $(name3) # Unknown variables are treated as empty strings.
# There are 4 places to set variables.
# In order of priority from highest to lowest:
# 1: commandline arguments
# 2: Makefile
# 3: shell environment variables - make imports these automatically.
# 4: make has some predefined variables
name4 ?= Jean
# Only set the variable if environment variable is not already defined.
override name5 = David
# Stops commandline arguments from changing this variable.
name4 +=grey
# Append values to variable (includes a space).
# Pattern-specific variable values (GNU extension).
echo: name2 = Sara # True within the matching rule
# and also within its remade recursive dependencies
# (except it can break when your graph gets too complicated!)
# Some variables defined automatically by make.
echo_inbuilt:
echo $(CC)
echo ${CXX}
echo $(FC)
echo ${CFLAGS}
echo $(CPPFLAGS)
echo ${CXXFLAGS}
echo $(LDFLAGS)
echo ${LDLIBS}
#-----------------------------------------------------------------------
# Variables 2
#-----------------------------------------------------------------------
# The first type of variables are evaluated each time they are used.
# This can be expensive, so a second type of variable exists which is
# only evaluated once. (This is a GNU make extension)
var := hello
var2 ::= $(var) hello
#:= and ::= are equivalent.
# These variables are evaluated procedurally (in the order that they
# appear), thus breaking with the rest of the language !
# This doesn't work
var3 ::= $(var4) and good luck
var4 ::= good night
#-----------------------------------------------------------------------
# Functions
#-----------------------------------------------------------------------
# make has lots of functions available.
sourcefiles = $(wildcard *.c */*.c)
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
# Format is $(func arg0,arg1,arg2...)
# Some examples
ls: * src/*
@echo $(filter %.txt, $^)
@echo $(notdir $^)
@echo $(join $(dir $^),$(notdir $^))
#-----------------------------------------------------------------------
# Directives
#-----------------------------------------------------------------------
# Include other makefiles, useful for platform specific code
include foo.mk
sport = tennis
# Conditional compilation
report:
ifeq ($(sport),tennis)
@echo 'game, set, match'
else
@echo "They think it's all over; it is now"
endif
# There are also ifneq, ifdef, ifndef
foo = true
ifdef $(foo)
bar = 'hello'
endif
```
### More Resources
+ [gnu make documentation](https://www.gnu.org/software/make/manual/)
+ [software carpentry tutorial](http://swcarpentry.github.io/make-novice/)
+ learn C the hard way [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html)

File diff suppressed because it is too large Load Diff

View File

@ -1,245 +1,245 @@
---
category: tool
tool: make
contributors:
- ["Robert Steed", "https://github.com/robochat"]
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
translators:
- ["Rogério Gomes Rio", "https://github.com/rogerlista"]
filename: Makefile-pt
lang: pt-br
---
Um Makefile define um gráfico de regras para criar um alvo (ou alvos). Sua finalidade é fazer o mínimo de trabalho necessário para atualizar um alvo para a versão mais recente da fonte. Famosamente escrito ao longo de um fim de semana por Stuart Feldman em 1976, ainda é amplamente usada (particularmente no Unix e no Linux) apesar de muitos concorrentes e críticas.
Existem muitas variedades de make na existência, no entanto, este artigo pressupõe que estamos usando o GNU make, que é o padrão no Linux.
```make
# Comentários podem ser escritos assim.
# O arquivo deve ser nomeado Makefile e então pode ser executado como `make <alvo>`.
# Caso contrário, nós usamos `make -f "nome-do-arquivo" <alvo>`.
# Aviso - use somente TABS para identar em Makefiles, nunca espaços!
#-----------------------------------------------------------------------
# Noções básicas
#-----------------------------------------------------------------------
# Regras são do formato
# alvo: <pré-requisito>
# onde os pré-requisitos são opcionais.
# Uma regra - esta regra só será executada se o arquivo0.txt não existir.
arquivo0.txt:
echo "foo" > arquivo0.txt
# Mesmo os comentários nestas seções da 'receita' são passados para o shell.
# Experimentar `make arquivo0.txt` or simplyou simplesmente `make` - primeira regra é o padrão.
# Esta regra só será executada se arquivo0.txt for mais recente que arquivo1.txt.
arquivo1.txt: arquivo0.txt
cat arquivo0.txt > arquivo1.txt
# se as mesmas regras de citação do shell.
@cat arquivo0.txt >> arquivo1.txt
# @ pára o comando de ser ecoado para stdout.
-@echo 'hello'
# - significa que make continuará em caso de erro.
# Experimentar `make arquivo1.txt` na linha de comando.
# Uma regra pode ter vários alvos e vários pré-requisitos
arquivo2.txt arquivo3.txt: arquivo0.txt arquivo1.txt
touch arquivo2.txt
touch arquivo3.txt
# Make vai reclamar sobre várias receitas para a mesma regra. Esvaziar
# receitas não contam e podem ser usadas para adicionar novas dependências.
#-----------------------------------------------------------------------
# Alvos falsos
#-----------------------------------------------------------------------
# Um alvo falso. Qualquer alvo que não seja um arquivo.
# Ele nunca será atualizado, portanto, o make sempre tentará executá-lo.
all: maker process
# Podemos declarar as coisas fora de ordem.
maker:
touch ex0.txt ex1.txt
# Pode evitar quebrar regras falsas quando um arquivo real tem o mesmo nome
.PHONY: all maker process
# Este é um alvo especial. Existem vários outros.
# Uma regra com dependência de um alvo falso sempre será executada
ex0.txt ex1.txt: maker
# Alvos falsos comuns são: todos fazem instalação limpa ...
#-----------------------------------------------------------------------
# Variáveis Automáticas e Curingas
#-----------------------------------------------------------------------
process: Arquivo*.txt # Usando um curinga para corresponder nomes de arquivos
@echo $^ # $^ é uma variável que contém a lista de pré-requisitos
@echo $@ # imprime o nome do alvo
#(fpara várias regras alvo, $@ é o que causou a execução da regra)
@echo $< # o primeiro pré-requisito listado
@echo $? # somente as dependências que estão desatualizadas
@echo $+ # todas as dependências, incluindo duplicadas (ao contrário do normal)
#@echo $| # todos os pré-requisitos 'somente pedidos'
# Mesmo se dividirmos as definições de dependência de regra, $^ vai encontrá-los
process: ex1.txt arquivo0.txt
# ex1.txt será encontrado, mas arquivo0.txt será desduplicado.
#-----------------------------------------------------------------------
# Padrões
#-----------------------------------------------------------------------
# Pode ensinar make a converter certos arquivos em outros arquivos.
%.png: %.svg
inkscape --export-png $^
# As regras padrões só farão qualquer coisa se decidirem criar o alvo.
# Os caminhos de diretório são normalmente ignorados quando as regras de
# padrões são correspondentes. Mas make tentará usar a regra mais
# apropriada disponível.
small/%.png: %.svg
inkscape --export-png --export-dpi 30 $^
# make utilizará a última versão para uma regra de padrão que encontrar.
%.png: %.svg
@echo esta regra é escolhida
# No entanto, o make usará a primeira regra padrão que pode se tornar o alvo
%.png: %.ps
@echo esta regra não é escolhida se *.svg and *.ps estão ambos presentes
# make já tem algumas regras padrões embutidas. Por exemplo, ele sabe
# como transformar arquivos *.c em arquivos *.o.
# Makefiles antigos podem usar regras de sufixo em vez de regras padrões
.png.ps:
@echo essa regra é semelhante a uma regra de padrão.
# make sobre a regra de sufixo
.SUFFIXES: .png
#-----------------------------------------------------------------------
# Variáveis
#-----------------------------------------------------------------------
# aka. macros
# As variáveis são basicamente todos os tipos de string
name = Ted
name2="Sarah"
echo:
@echo $(name)
@echo ${name2}
@echo $name # Isso não funcionará, tratado como $ (n)ame.
@echo $(name3) # Variáveis desconhecidas são tratadas como strings vazias.
# Existem 4 lugares para definir variáveis.
# Em ordem de prioridade, do maior para o menor:
# 1: argumentos de linha de comando
# 2: Makefile
# 3: variáveis de ambiente do shell - faça importações automaticamente.
# 4: make tem algumas variáveis predefinidas
name4 ?= Jean
# Somente defina a variável se a variável de ambiente ainda não estiver definida.
override name5 = David
# Pára os argumentos da linha de comando de alterar essa variável.
name4 +=grey
# Anexar valores à variável (inclui um espaço).
# Valores variáveis específicos de padrões (extensão GNU).
echo: name2 = Sara # Verdadeiro dentro da regra de correspondência
# e também dentro de suas recursivas dependências
# (exceto que ele pode quebrar quando seu gráfico ficar muito complicado!)
# Algumas variáveis definidas automaticamente pelo make
echo_inbuilt:
echo $(CC)
echo ${CXX}
echo $(FC)
echo ${CFLAGS}
echo $(CPPFLAGS)
echo ${CXXFLAGS}
echo $(LDFLAGS)
echo ${LDLIBS}
#-----------------------------------------------------------------------
# Variáveis 2
#-----------------------------------------------------------------------
# O primeiro tipo de variáveis ​​é avaliado a cada vez que elas são usadas.
# TIsso pode ser caro, então existe um segundo tipo de variável que é
# avaliado apenas uma vez. (Esta é uma extensão do GNU make)
var := hello
var2 ::= $(var) hello
#:= e ::= são equivalentes.
# Essas variáveis são avaliadas procedimentalmente (na ordem em que
# aparecem), quebrando assim o resto da línguagem!
# Isso não funciona
var3 ::= $(var4) and good luck
var4 ::= good night
#-----------------------------------------------------------------------
# Funções
#-----------------------------------------------------------------------
# make tem muitas funções disponíveis.
sourcefiles = $(wildcard *.c */*.c)
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
# O formato é $(func arg0,arg1,arg2...)
# Alguns exemplos
ls: * src/*
@echo $(filter %.txt, $^)
@echo $(notdir $^)
@echo $(join $(dir $^),$(notdir $^))
#-----------------------------------------------------------------------
# Diretivas
#-----------------------------------------------------------------------
# Inclua outros makefiles, úteis para código específico da plataforma
include foo.mk
sport = tennis
# Compilação condicional
report:
ifeq ($(sport),tennis)
@echo 'game, set, match'
else
@echo "They think it's all over; it is now"
endif
# Há também ifneq, ifdef, ifndef
foo = true
ifdef $(foo)
bar = 'hello'
endif
```
### More Resources
+ [documentação gnu make](https://www.gnu.org/software/make/manual/)
+ [tutorial de carpintaria de software](http://swcarpentry.github.io/make-novice/)
+ aprenda C da maneira mais difícil [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html)
---
category: tool
tool: make
contributors:
- ["Robert Steed", "https://github.com/robochat"]
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
translators:
- ["Rogério Gomes Rio", "https://github.com/rogerlista"]
filename: Makefile-pt
lang: pt-br
---
Um Makefile define um gráfico de regras para criar um alvo (ou alvos). Sua finalidade é fazer o mínimo de trabalho necessário para atualizar um alvo para a versão mais recente da fonte. Famosamente escrito ao longo de um fim de semana por Stuart Feldman em 1976, ainda é amplamente usada (particularmente no Unix e no Linux) apesar de muitos concorrentes e críticas.
Existem muitas variedades de make na existência, no entanto, este artigo pressupõe que estamos usando o GNU make, que é o padrão no Linux.
```make
# Comentários podem ser escritos assim.
# O arquivo deve ser nomeado Makefile e então pode ser executado como `make <alvo>`.
# Caso contrário, nós usamos `make -f "nome-do-arquivo" <alvo>`.
# Aviso - use somente TABS para identar em Makefiles, nunca espaços!
#-----------------------------------------------------------------------
# Noções básicas
#-----------------------------------------------------------------------
# Regras são do formato
# alvo: <pré-requisito>
# onde os pré-requisitos são opcionais.
# Uma regra - esta regra só será executada se o arquivo0.txt não existir.
arquivo0.txt:
echo "foo" > arquivo0.txt
# Mesmo os comentários nestas seções da 'receita' são passados para o shell.
# Experimentar `make arquivo0.txt` or simplyou simplesmente `make` - primeira regra é o padrão.
# Esta regra só será executada se arquivo0.txt for mais recente que arquivo1.txt.
arquivo1.txt: arquivo0.txt
cat arquivo0.txt > arquivo1.txt
# se as mesmas regras de citação do shell.
@cat arquivo0.txt >> arquivo1.txt
# @ pára o comando de ser ecoado para stdout.
-@echo 'hello'
# - significa que make continuará em caso de erro.
# Experimentar `make arquivo1.txt` na linha de comando.
# Uma regra pode ter vários alvos e vários pré-requisitos
arquivo2.txt arquivo3.txt: arquivo0.txt arquivo1.txt
touch arquivo2.txt
touch arquivo3.txt
# Make vai reclamar sobre várias receitas para a mesma regra. Esvaziar
# receitas não contam e podem ser usadas para adicionar novas dependências.
#-----------------------------------------------------------------------
# Alvos falsos
#-----------------------------------------------------------------------
# Um alvo falso. Qualquer alvo que não seja um arquivo.
# Ele nunca será atualizado, portanto, o make sempre tentará executá-lo.
all: maker process
# Podemos declarar as coisas fora de ordem.
maker:
touch ex0.txt ex1.txt
# Pode evitar quebrar regras falsas quando um arquivo real tem o mesmo nome
.PHONY: all maker process
# Este é um alvo especial. Existem vários outros.
# Uma regra com dependência de um alvo falso sempre será executada
ex0.txt ex1.txt: maker
# Alvos falsos comuns são: todos fazem instalação limpa ...
#-----------------------------------------------------------------------
# Variáveis Automáticas e Curingas
#-----------------------------------------------------------------------
process: Arquivo*.txt # Usando um curinga para corresponder nomes de arquivos
@echo $^ # $^ é uma variável que contém a lista de pré-requisitos
@echo $@ # imprime o nome do alvo
#(fpara várias regras alvo, $@ é o que causou a execução da regra)
@echo $< # o primeiro pré-requisito listado
@echo $? # somente as dependências que estão desatualizadas
@echo $+ # todas as dependências, incluindo duplicadas (ao contrário do normal)
#@echo $| # todos os pré-requisitos 'somente pedidos'
# Mesmo se dividirmos as definições de dependência de regra, $^ vai encontrá-los
process: ex1.txt arquivo0.txt
# ex1.txt será encontrado, mas arquivo0.txt será desduplicado.
#-----------------------------------------------------------------------
# Padrões
#-----------------------------------------------------------------------
# Pode ensinar make a converter certos arquivos em outros arquivos.
%.png: %.svg
inkscape --export-png $^
# As regras padrões só farão qualquer coisa se decidirem criar o alvo.
# Os caminhos de diretório são normalmente ignorados quando as regras de
# padrões são correspondentes. Mas make tentará usar a regra mais
# apropriada disponível.
small/%.png: %.svg
inkscape --export-png --export-dpi 30 $^
# make utilizará a última versão para uma regra de padrão que encontrar.
%.png: %.svg
@echo esta regra é escolhida
# No entanto, o make usará a primeira regra padrão que pode se tornar o alvo
%.png: %.ps
@echo esta regra não é escolhida se *.svg and *.ps estão ambos presentes
# make já tem algumas regras padrões embutidas. Por exemplo, ele sabe
# como transformar arquivos *.c em arquivos *.o.
# Makefiles antigos podem usar regras de sufixo em vez de regras padrões
.png.ps:
@echo essa regra é semelhante a uma regra de padrão.
# make sobre a regra de sufixo
.SUFFIXES: .png
#-----------------------------------------------------------------------
# Variáveis
#-----------------------------------------------------------------------
# aka. macros
# As variáveis são basicamente todos os tipos de string
name = Ted
name2="Sarah"
echo:
@echo $(name)
@echo ${name2}
@echo $name # Isso não funcionará, tratado como $ (n)ame.
@echo $(name3) # Variáveis desconhecidas são tratadas como strings vazias.
# Existem 4 lugares para definir variáveis.
# Em ordem de prioridade, do maior para o menor:
# 1: argumentos de linha de comando
# 2: Makefile
# 3: variáveis de ambiente do shell - faça importações automaticamente.
# 4: make tem algumas variáveis predefinidas
name4 ?= Jean
# Somente defina a variável se a variável de ambiente ainda não estiver definida.
override name5 = David
# Pára os argumentos da linha de comando de alterar essa variável.
name4 +=grey
# Anexar valores à variável (inclui um espaço).
# Valores variáveis específicos de padrões (extensão GNU).
echo: name2 = Sara # Verdadeiro dentro da regra de correspondência
# e também dentro de suas recursivas dependências
# (exceto que ele pode quebrar quando seu gráfico ficar muito complicado!)
# Algumas variáveis definidas automaticamente pelo make
echo_inbuilt:
echo $(CC)
echo ${CXX}
echo $(FC)
echo ${CFLAGS}
echo $(CPPFLAGS)
echo ${CXXFLAGS}
echo $(LDFLAGS)
echo ${LDLIBS}
#-----------------------------------------------------------------------
# Variáveis 2
#-----------------------------------------------------------------------
# O primeiro tipo de variáveis ​​é avaliado a cada vez que elas são usadas.
# TIsso pode ser caro, então existe um segundo tipo de variável que é
# avaliado apenas uma vez. (Esta é uma extensão do GNU make)
var := hello
var2 ::= $(var) hello
#:= e ::= são equivalentes.
# Essas variáveis são avaliadas procedimentalmente (na ordem em que
# aparecem), quebrando assim o resto da línguagem!
# Isso não funciona
var3 ::= $(var4) and good luck
var4 ::= good night
#-----------------------------------------------------------------------
# Funções
#-----------------------------------------------------------------------
# make tem muitas funções disponíveis.
sourcefiles = $(wildcard *.c */*.c)
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
# O formato é $(func arg0,arg1,arg2...)
# Alguns exemplos
ls: * src/*
@echo $(filter %.txt, $^)
@echo $(notdir $^)
@echo $(join $(dir $^),$(notdir $^))
#-----------------------------------------------------------------------
# Diretivas
#-----------------------------------------------------------------------
# Inclua outros makefiles, úteis para código específico da plataforma
include foo.mk
sport = tennis
# Compilação condicional
report:
ifeq ($(sport),tennis)
@echo 'game, set, match'
else
@echo "They think it's all over; it is now"
endif
# Há também ifneq, ifdef, ifndef
foo = true
ifdef $(foo)
bar = 'hello'
endif
```
### More Resources
+ [documentação gnu make](https://www.gnu.org/software/make/manual/)
+ [tutorial de carpintaria de software](http://swcarpentry.github.io/make-novice/)
+ aprenda C da maneira mais difícil [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html)

View File

@ -1,225 +1,225 @@
---
category: Algorithms & Data Structures
name: Asymptotic Notation
contributors:
- ["Jake Prather", "http://github.com/JakeHP"]
- ["Divay Prakash", "http://github.com/divayprakash"]
translators:
- ["pru-mike", "http://github.com/pru-mike"]
lang: ru-ru
---
# О-символика
## Что это такое?
О-символика, или асимптотическая запись, — это система символов, позволяющая
оценить время выполнения алгоритма, устанавливая зависимость времени выполнения
от увеличения объёма входных данных. Она также известна как оценка
сложности алгоритмов. Станет ли алгоритм невероятно медленным, когда
объём входных данных увеличится? Будет ли алгоритм выполняться достаточно быстро,
если объём входных данных возрастёт? О-символика позволяет ответить на эти
вопросы.
## Можно ли по-другому найти ответы на эти вопросы?
Один способ — это подсчитать число элементарных операций в зависимости от
различных объёмов входных данных. Хотя это и приемлемое решение, тот объём
работы, которого оно потребует, даже для простых алгоритмов делает его
использование неоправданным.
Другой способ — это измерить, какое время алгоритм потребует для завершения на
различных объёмах входных данных. В то же время, точность и относительность
этого метода (полученное время будет относиться только к той машине, на которой
оно вычислено) зависит от среды выполнения: компьютерного аппаратного
обеспечения, мощности процессора и т.д.
## Виды О-символики
В первом разделе этого документа мы определили, что О-символика
позволяет оценивать алгоритмы в зависимости от изменения размера входных
данных. Представим, что алгоритм — это функция f, n — размер входных данных и
f(n) — время выполнения. Тогда для данного алгоритма f с размером входных
данных n получим какое-то результирующее время выполнения f(n).
Из этого можно построить график, где ось y — время выполнения, ось x — размер входных
данных, а точки на графике — это время выполнения для заданного размера входных
данных.
С помощью О-символики можно оценить функцию или алгоритм
несколькими различными способами. Например, можно оценить алгоритм исходя
из нижней оценки, верхней оценки, тождественной оценки. Чаще всего встречается
анализ на основе верхней оценки. Как правило, не используется нижняя оценка,
потому что она не подходит под планируемые условия. Отличный пример — алгоритмы
сортировки, особенно добавление элементов в древовидную структуру. Нижняя оценка
большинства таких алгоритмов может быть дана как одна операция. В то время как в
большинстве случаев добавляемые элементы должны быть отсортированы
соответствующим образом при помощи дерева, что может потребовать обхода целой
ветви. Это и есть худший случай, для которого планируется верхняя оценка.
### Виды функций, пределы и упрощения
```
Логарифмическая функция — log n
Линейная функция — an + b
Квадратичная функция — an^2 + bn +c
Степенная функция — an^z + . . . + an^2 + a*n^1 + a*n^0, где z — константа
Показательная функция — a^n, где a — константа
```
Приведены несколько базовых функций, используемых при определении сложности в
различных оценках. Список начинается с самой медленно возрастающей функции
(логарифм, наиболее быстрое время выполнения) и следует до самой быстро
возрастающей функции (экспонента, самое медленное время выполнения). Отметим,
что в то время, как «n», или размер входных данных, возрастает в каждой из этих функций,
результат намного быстрее возрастает в квадратичной, степенной
и показательной по сравнению с логарифмической и линейной.
Крайне важно понимать, что при использовании описанной далее нотации необходимо
использовать упрощённые выражения.
Это означает, что необходимо отбрасывать константы и слагаемые младших порядков,
потому что если размер входных данных (n в функции f(n) нашего примера)
увеличивается до бесконечности (в пределе), тогда слагаемые младших порядков
и константы становятся пренебрежительно малыми. Таким образом, если есть
константа, например, размера 2^9001 или любого другого невообразимого размера,
надо понимать, что её упрощение внесёт значительные искажения в точность
оценки.
Т.к. нам нужны упрощённые выражения, немного скорректируем нашу таблицу...
```
Логарифм — log n
Линейная функция — n
Квадратичная функция — n^2
Степенная функция — n^z, где z — константа
Показательная функция — a^n, где a — константа
```
### О Большое
О Большое, записывается как **О**, — это асимптотическая запись для оценки худшего
случая, или для ограничения заданной функции сверху. Это позволяет сделать
_**асимптотическую оценку верхней границы**_ скорости роста времени выполнения
алгоритма. Пусть `f(n)` — время выполнения алгоритма, а `g(n)` — заданная временная
сложность, которая проверяется для алгоритма. Тогда `f(n)` — это O(g(n)), если
существуют действительные константы c (c > 0) и n<sub>0</sub>, такие,
что `f(n)` <= `c g(n)` выполняется для всех n, начиная с некоторого n<sub>0</sub> (n > n<sub>0</sub>).
*Пример 1*
```
f(n) = 3log n + 100
g(n) = log n
```
Является ли `f(n)` O(g(n))?
Является ли `3 log n + 100` O(log n)?
Посмотрим на определение О Большого:
```
3log n + 100 <= c * log n
```
Существуют ли константы c и n<sub>0</sub>, такие, что выражение верно для всех n > n<sub>0</sub>?
```
3log n + 100 <= 150 * log n, n > 2 (не определенно для n = 1)
```
Да! По определению О Большого `f(n)` является O(g(n)).
*Пример 2*
```
f(n) = 3 * n^2
g(n) = n
```
Является ли `f(n)` O(g(n))?
Является ли `3 * n^2` O(n)?
Посмотрим на определение О Большого:
```
3 * n^2 <= c * n
```
Существуют ли константы c и n<sub>0</sub>, такие, что выражение верно для всех n > n<sub>0</sub>?
Нет, не существуют. `f(n)` НЕ ЯВЛЯЕТСЯ O(g(n)).
### Омега Большое
Омега Большое, записывается как **Ω**, — это асимптотическая запись для оценки
лучшего случая, или для ограничения заданной функции снизу. Это позволяет сделать
_**асимптотическую оценку нижней границы**_ скорости роста времени выполнения
алгоритма.
`f(n)` является Ω(g(n)), если существуют действительные константы
c (c > 0) и n<sub>0</sub> (n<sub>0</sub> > 0), такие, что `f(n)` >= `c g(n)` для всех n > n<sub>0</sub>.
### Примечание
Асимптотические оценки, сделанные при помощи О Большого и Омега Большого, могут
как являться, так и не являться точными. Для того чтобы обозначить, что границы не
являются асимптотически точными, используются записи О Малое и Омега Малое.
### О Малое
O Малое, записывается как **о**, — это асимптотическая запись для оценки верхней
границы времени выполнения алгоритма при условии, что граница не является
асимптотически точной.
`f(n)` является o(g(n)), если можно подобрать такие действительные константы,
что для всех c (c > 0) найдётся n<sub>0</sub> (n<sub>0</sub> > 0), так
что `f(n)` < `c g(n)` выполняется для всех n (n > n<sub>0</sub>).
Определения О-символики для О Большого и О Малого похожи. Главное отличие в том,
что если f(n) = O(g(n)), тогда условие f(n) <= c g(n) выполняется, если _**существует**_
константа c > 0, но если f(n) = o(g(n)), тогда условие f(n) < c g(n) выполняется
для _**всех**_ констант c > 0.
### Омега Малое
Омега Малое, записывается как **ω**, — это асимптотическая запись для оценки
верхней границы времени выполнения алгоритма при условии, что граница не является
асимптотически точной.
`f(n)` является ω(g(n)), если можно подобрать такие действительные константы,
что для всех c (c > 0) найдётся n<sub>0</sub> (n<sub>0</sub> > 0), так
что `f(n)` > `c g(n)` выполняется для всех n (n > n<sub>0</sub>).
Определения Ω-символики и ω-символики похожи. Главное отличие в том, что
если f(n) = Ω(g(n)), тогда условие f(n) >= c g(n) выполняется, если _**существует**_
константа c > 0, но если f(n) = ω(g(n)), тогда условие f(n) > c g(n)
выполняется для _**всех**_ констант c > 0.
### Тета
Тета, записывается как **Θ**, — это асимптотическая запись для оценки
_***асимптотически точной границы***_ времени выполнения алгоритма.
`f(n)` является Θ(g(n)), если для некоторых действительных
констант c1, c2 и n<sub>0</sub> (c1 > 0, c2 > 0, n<sub>0</sub> > 0)
`c1 g(n)` < `f(n)` < `c2 g(n)` для всех n (n > n<sub>0</sub>).
`f(n)` является Θ(g(n)) означает, что `f(n)` является O(g(n))
и `f(n)` является Ω(g(n)).
О Большое — основной инструмент для анализа сложности алгоритмов.
Также см. примеры по ссылкам.
### Заключение
Такую тему сложно изложить кратко, поэтому обязательно стоит пройти по ссылкам и
посмотреть дополнительную литературу. В ней даётся более глубокое описание с
определениями и примерами.
## Дополнительная литература
* [Алгоритмы на Java](https://www.ozon.ru/context/detail/id/18319699/)
* [Алгоритмы. Построение и анализ](https://www.ozon.ru/context/detail/id/33769775/)
## Ссылки
* [Оценки времени исполнения. Символ O()](http://algolist.manual.ru/misc/o_n.php)
* [Асимптотический анализ и теория вероятностей](https://www.lektorium.tv/course/22903)
## Ссылки (англ.)
* [Algorithms, Part I](https://www.coursera.org/learn/algorithms-part1)
* [Cheatsheet 1](http://web.mit.edu/broder/Public/asymptotics-cheatsheet.pdf)
* [Cheatsheet 2](http://bigocheatsheet.com/)
---
category: Algorithms & Data Structures
name: Asymptotic Notation
contributors:
- ["Jake Prather", "http://github.com/JakeHP"]
- ["Divay Prakash", "http://github.com/divayprakash"]
translators:
- ["pru-mike", "http://github.com/pru-mike"]
lang: ru-ru
---
# О-символика
## Что это такое?
О-символика, или асимптотическая запись, — это система символов, позволяющая
оценить время выполнения алгоритма, устанавливая зависимость времени выполнения
от увеличения объёма входных данных. Она также известна как оценка
сложности алгоритмов. Станет ли алгоритм невероятно медленным, когда
объём входных данных увеличится? Будет ли алгоритм выполняться достаточно быстро,
если объём входных данных возрастёт? О-символика позволяет ответить на эти
вопросы.
## Можно ли по-другому найти ответы на эти вопросы?
Один способ — это подсчитать число элементарных операций в зависимости от
различных объёмов входных данных. Хотя это и приемлемое решение, тот объём
работы, которого оно потребует, даже для простых алгоритмов делает его
использование неоправданным.
Другой способ — это измерить, какое время алгоритм потребует для завершения на
различных объёмах входных данных. В то же время, точность и относительность
этого метода (полученное время будет относиться только к той машине, на которой
оно вычислено) зависит от среды выполнения: компьютерного аппаратного
обеспечения, мощности процессора и т.д.
## Виды О-символики
В первом разделе этого документа мы определили, что О-символика
позволяет оценивать алгоритмы в зависимости от изменения размера входных
данных. Представим, что алгоритм — это функция f, n — размер входных данных и
f(n) — время выполнения. Тогда для данного алгоритма f с размером входных
данных n получим какое-то результирующее время выполнения f(n).
Из этого можно построить график, где ось y — время выполнения, ось x — размер входных
данных, а точки на графике — это время выполнения для заданного размера входных
данных.
С помощью О-символики можно оценить функцию или алгоритм
несколькими различными способами. Например, можно оценить алгоритм исходя
из нижней оценки, верхней оценки, тождественной оценки. Чаще всего встречается
анализ на основе верхней оценки. Как правило, не используется нижняя оценка,
потому что она не подходит под планируемые условия. Отличный пример — алгоритмы
сортировки, особенно добавление элементов в древовидную структуру. Нижняя оценка
большинства таких алгоритмов может быть дана как одна операция. В то время как в
большинстве случаев добавляемые элементы должны быть отсортированы
соответствующим образом при помощи дерева, что может потребовать обхода целой
ветви. Это и есть худший случай, для которого планируется верхняя оценка.
### Виды функций, пределы и упрощения
```
Логарифмическая функция — log n
Линейная функция — an + b
Квадратичная функция — an^2 + bn +c
Степенная функция — an^z + . . . + an^2 + a*n^1 + a*n^0, где z — константа
Показательная функция — a^n, где a — константа
```
Приведены несколько базовых функций, используемых при определении сложности в
различных оценках. Список начинается с самой медленно возрастающей функции
(логарифм, наиболее быстрое время выполнения) и следует до самой быстро
возрастающей функции (экспонента, самое медленное время выполнения). Отметим,
что в то время, как «n», или размер входных данных, возрастает в каждой из этих функций,
результат намного быстрее возрастает в квадратичной, степенной
и показательной по сравнению с логарифмической и линейной.
Крайне важно понимать, что при использовании описанной далее нотации необходимо
использовать упрощённые выражения.
Это означает, что необходимо отбрасывать константы и слагаемые младших порядков,
потому что если размер входных данных (n в функции f(n) нашего примера)
увеличивается до бесконечности (в пределе), тогда слагаемые младших порядков
и константы становятся пренебрежительно малыми. Таким образом, если есть
константа, например, размера 2^9001 или любого другого невообразимого размера,
надо понимать, что её упрощение внесёт значительные искажения в точность
оценки.
Т.к. нам нужны упрощённые выражения, немного скорректируем нашу таблицу...
```
Логарифм — log n
Линейная функция — n
Квадратичная функция — n^2
Степенная функция — n^z, где z — константа
Показательная функция — a^n, где a — константа
```
### О Большое
О Большое, записывается как **О**, — это асимптотическая запись для оценки худшего
случая, или для ограничения заданной функции сверху. Это позволяет сделать
_**асимптотическую оценку верхней границы**_ скорости роста времени выполнения
алгоритма. Пусть `f(n)` — время выполнения алгоритма, а `g(n)` — заданная временная
сложность, которая проверяется для алгоритма. Тогда `f(n)` — это O(g(n)), если
существуют действительные константы c (c > 0) и n<sub>0</sub>, такие,
что `f(n)` <= `c g(n)` выполняется для всех n, начиная с некоторого n<sub>0</sub> (n > n<sub>0</sub>).
*Пример 1*
```
f(n) = 3log n + 100
g(n) = log n
```
Является ли `f(n)` O(g(n))?
Является ли `3 log n + 100` O(log n)?
Посмотрим на определение О Большого:
```
3log n + 100 <= c * log n
```
Существуют ли константы c и n<sub>0</sub>, такие, что выражение верно для всех n > n<sub>0</sub>?
```
3log n + 100 <= 150 * log n, n > 2 (не определенно для n = 1)
```
Да! По определению О Большого `f(n)` является O(g(n)).
*Пример 2*
```
f(n) = 3 * n^2
g(n) = n
```
Является ли `f(n)` O(g(n))?
Является ли `3 * n^2` O(n)?
Посмотрим на определение О Большого:
```
3 * n^2 <= c * n
```
Существуют ли константы c и n<sub>0</sub>, такие, что выражение верно для всех n > n<sub>0</sub>?
Нет, не существуют. `f(n)` НЕ ЯВЛЯЕТСЯ O(g(n)).
### Омега Большое
Омега Большое, записывается как **Ω**, — это асимптотическая запись для оценки
лучшего случая, или для ограничения заданной функции снизу. Это позволяет сделать
_**асимптотическую оценку нижней границы**_ скорости роста времени выполнения
алгоритма.
`f(n)` является Ω(g(n)), если существуют действительные константы
c (c > 0) и n<sub>0</sub> (n<sub>0</sub> > 0), такие, что `f(n)` >= `c g(n)` для всех n > n<sub>0</sub>.
### Примечание
Асимптотические оценки, сделанные при помощи О Большого и Омега Большого, могут
как являться, так и не являться точными. Для того чтобы обозначить, что границы не
являются асимптотически точными, используются записи О Малое и Омега Малое.
### О Малое
O Малое, записывается как **о**, — это асимптотическая запись для оценки верхней
границы времени выполнения алгоритма при условии, что граница не является
асимптотически точной.
`f(n)` является o(g(n)), если можно подобрать такие действительные константы,
что для всех c (c > 0) найдётся n<sub>0</sub> (n<sub>0</sub> > 0), так
что `f(n)` < `c g(n)` выполняется для всех n (n > n<sub>0</sub>).
Определения О-символики для О Большого и О Малого похожи. Главное отличие в том,
что если f(n) = O(g(n)), тогда условие f(n) <= c g(n) выполняется, если _**существует**_
константа c > 0, но если f(n) = o(g(n)), тогда условие f(n) < c g(n) выполняется
для _**всех**_ констант c > 0.
### Омега Малое
Омега Малое, записывается как **ω**, — это асимптотическая запись для оценки
верхней границы времени выполнения алгоритма при условии, что граница не является
асимптотически точной.
`f(n)` является ω(g(n)), если можно подобрать такие действительные константы,
что для всех c (c > 0) найдётся n<sub>0</sub> (n<sub>0</sub> > 0), так
что `f(n)` > `c g(n)` выполняется для всех n (n > n<sub>0</sub>).
Определения Ω-символики и ω-символики похожи. Главное отличие в том, что
если f(n) = Ω(g(n)), тогда условие f(n) >= c g(n) выполняется, если _**существует**_
константа c > 0, но если f(n) = ω(g(n)), тогда условие f(n) > c g(n)
выполняется для _**всех**_ констант c > 0.
### Тета
Тета, записывается как **Θ**, — это асимптотическая запись для оценки
_***асимптотически точной границы***_ времени выполнения алгоритма.
`f(n)` является Θ(g(n)), если для некоторых действительных
констант c1, c2 и n<sub>0</sub> (c1 > 0, c2 > 0, n<sub>0</sub> > 0)
`c1 g(n)` < `f(n)` < `c2 g(n)` для всех n (n > n<sub>0</sub>).
`f(n)` является Θ(g(n)) означает, что `f(n)` является O(g(n))
и `f(n)` является Ω(g(n)).
О Большое — основной инструмент для анализа сложности алгоритмов.
Также см. примеры по ссылкам.
### Заключение
Такую тему сложно изложить кратко, поэтому обязательно стоит пройти по ссылкам и
посмотреть дополнительную литературу. В ней даётся более глубокое описание с
определениями и примерами.
## Дополнительная литература
* [Алгоритмы на Java](https://www.ozon.ru/context/detail/id/18319699/)
* [Алгоритмы. Построение и анализ](https://www.ozon.ru/context/detail/id/33769775/)
## Ссылки
* [Оценки времени исполнения. Символ O()](http://algolist.manual.ru/misc/o_n.php)
* [Асимптотический анализ и теория вероятностей](https://www.lektorium.tv/course/22903)
## Ссылки (англ.)
* [Algorithms, Part I](https://www.coursera.org/learn/algorithms-part1)
* [Cheatsheet 1](http://web.mit.edu/broder/Public/asymptotics-cheatsheet.pdf)
* [Cheatsheet 2](http://bigocheatsheet.com/)

View File

@ -1,125 +1,125 @@
---
language: SQL
contributors:
- ["Metin Yalçınkaya", "https://github.com/mtnylnky"]
lang: tr-tr
filename: learnsql-tr.sql
---
```sql
-- Yorumlar iki tire ile başlar
-- KISITLAR
Not null -- Bir kolon asla boş olamaz
default -- Boş olan yerlere varsayılan bir değer atar
unique -- Bir kolondaki tüm değerlerin farklı olması kısıtlaması
primary key -- Bir tablodaki her veri için kimlik bilgisi niteliğindedir
check -- Bir kolondaki değerlerin belli bir kısıtlamayı sağlamasını sağlar
-- Tablo oluşturulur
CREATE TABLE tablo1 ();
-- Tabloyu içerisinde kolonlar ile oluşturma
CREATE TABLE tablo1(id INTEGER PRIMARY KEY NOT NULL UNIQUE, ad TEXT, soyad TEXT, yas INTEGER);
-- TABLO varlığını kontrol eder
.table
-- Veri tabanında olan bütün tabloları görüntüler.
.schema
-- Satır ekle
INSERT INTO tablo1 ( ad, soyad) VALUES ("Deger1","Deger2");
-- Veritabanında tablo üzerindeki verileri görüntüle
-- Sadece 'ad' gibi sınırlı bir veri için
SELECT ad FROM tablo1;
-- Bütün veriler için
SELECT * FROM tablo1;
-- Veri güncelleme
UPDATE tablo1 SET ad = "deger1-2"; WHERE name = "Deger1";
-- Satır sil
DELETE FROM tablo1 WHERE id = 1;
DELETE FROM tablo1 WHERE ad = "Deger1" OR ad = "Deger2";
-- Tabloya sonradan kolon ekleme
ALTER TABLE tablo1 ADD COLUMN email TEXT;
-- Tablodaki kolon adı değiştirme
EXEC sp_rename ' tablo1.[ad]', Ad, 'COLUMN';
-- Tablo adı değiştirme
ALTER TABLE table1 RENAME TO Table1;
-- Tabloyu silme
DROP TABLE Table1;
-- BİR TABLOYU BAŞKA TABLO KULLANARAK DOLDURMAK
INSERT INTO Tablo2 SELECT id,ad, soyad, email from Tablo1;
-- LIKE KOMUTU
-- Belirli bir kritere göre arama yaparken kullanılır
-- Adı 'A' ile başlayan veriler
SELECT * FROM tablo1 WHERE adi LIKE "A%";
-- İçinde 'A' olan veriler
SELECT * FROM tablo1 WHERE adi LIKE "%A%";
-- LIMIT KOMUTU
-- Gösterilen satır sayısını sınırlamak için
SELECT * FROM Tablo1 LIMIT 6;
-- Gösterilen satırları belirli bir noktadan başlamak üzere sınırlamak için
SELECT * FROM Tablo1 LIMIT 6 OFFSET 3;
-- ORDER BY KOMUTU
-- Herhangi bir kolona göre gösterilen değerleri azalan veya artan şekilde sıralamak için
SELECT kolon FROM tablo1 WHERE yas ORDER BY column1, column2, .. columnN] [ASC | DESC];
SELECT * FROM Tablo1 ORDER BY yas ASC
SELECT * FROM Tablo1 ORDER BY yas DESC
-- DISTINCT ANAHTAR SÖZCÜĞÜ
-- Bu anahtar sözcükle sadece farklı değerler gösterilir.
SELECT DISTINCT yas FROM tablo1;
-- JOIN KOMUTU
-- CROSS JOIN
-- Cross join bir tablodaki her satırı ikinci tablodaki bir satır ile eşleştirmek için kulanılır.
-- Eğer birinci tabloda x satır ikinci tabloda y satır varsa sonuçta x*y satır olur.
SELECT ... FROM table1 CROSS JOIN table2 …
SELECT ad, yas FROM Tablo1 CROSS JOIN Tablo2;
-- INNER JOIN
-- Inner join iki tablodaki ortak kolon değerlerini kullanarak bir sonuç üretir.
SELECT ... FROM table1 [INNER] JOIN table2 ON conditional_expression …
SELECT ad, yas FROM Tablo1 INNER JOIN Tablo2 ON Tablo1.ad = Tablo2.soyad;
-- OUTER JOIN
-- Outer join iki tablodaki ortak kolon değerlerinin dışında kalanları kullanarak bir sonuç üretir.
SELECT isci_num, isim, dept FROM Tablo1 LEFT OUTER JOIN Tablo2 ON Tablo1.id = Tablo2.isci_num;
-- ÇEKİRDEK FONKSİYONLAR
COUNT -- Sayma
AVG -- Ortalama
ABS -- Mutlak değer
SUM -- Toplam
RANDOM -- Rastgele
ROUND -- Yuvarlama
MAX -- Maksimim
MIN -- Minimum
UPPER -- Büyük Harf
LOWER -- Küçük Harf
LENGTH -- Uzunluk
CURRENT_TIMESTAMP -- Zaman
SELECT max(yas) FROM Table1;
SELECT min(yas) FROM Table1;
SELECT avg(yas) FROM Table1;
SELECT * From Table1 WHERE yas ==18;
SELECT sum(yas) FROM Table1;
SELECT random() AS Random;
SELECT upper(ad) FROM Table1;
SELECT lower(ad) FROM Table1;
SELECT ad, length(ad) FROM Table1;
---
language: SQL
contributors:
- ["Metin Yalçınkaya", "https://github.com/mtnylnky"]
lang: tr-tr
filename: learnsql-tr.sql
---
```sql
-- Yorumlar iki tire ile başlar
-- KISITLAR
Not null -- Bir kolon asla boş olamaz
default -- Boş olan yerlere varsayılan bir değer atar
unique -- Bir kolondaki tüm değerlerin farklı olması kısıtlaması
primary key -- Bir tablodaki her veri için kimlik bilgisi niteliğindedir
check -- Bir kolondaki değerlerin belli bir kısıtlamayı sağlamasını sağlar
-- Tablo oluşturulur
CREATE TABLE tablo1 ();
-- Tabloyu içerisinde kolonlar ile oluşturma
CREATE TABLE tablo1(id INTEGER PRIMARY KEY NOT NULL UNIQUE, ad TEXT, soyad TEXT, yas INTEGER);
-- TABLO varlığını kontrol eder
.table
-- Veri tabanında olan bütün tabloları görüntüler.
.schema
-- Satır ekle
INSERT INTO tablo1 ( ad, soyad) VALUES ("Deger1","Deger2");
-- Veritabanında tablo üzerindeki verileri görüntüle
-- Sadece 'ad' gibi sınırlı bir veri için
SELECT ad FROM tablo1;
-- Bütün veriler için
SELECT * FROM tablo1;
-- Veri güncelleme
UPDATE tablo1 SET ad = "deger1-2"; WHERE name = "Deger1";
-- Satır sil
DELETE FROM tablo1 WHERE id = 1;
DELETE FROM tablo1 WHERE ad = "Deger1" OR ad = "Deger2";
-- Tabloya sonradan kolon ekleme
ALTER TABLE tablo1 ADD COLUMN email TEXT;
-- Tablodaki kolon adı değiştirme
EXEC sp_rename ' tablo1.[ad]', Ad, 'COLUMN';
-- Tablo adı değiştirme
ALTER TABLE table1 RENAME TO Table1;
-- Tabloyu silme
DROP TABLE Table1;
-- BİR TABLOYU BAŞKA TABLO KULLANARAK DOLDURMAK
INSERT INTO Tablo2 SELECT id,ad, soyad, email from Tablo1;
-- LIKE KOMUTU
-- Belirli bir kritere göre arama yaparken kullanılır
-- Adı 'A' ile başlayan veriler
SELECT * FROM tablo1 WHERE adi LIKE "A%";
-- İçinde 'A' olan veriler
SELECT * FROM tablo1 WHERE adi LIKE "%A%";
-- LIMIT KOMUTU
-- Gösterilen satır sayısını sınırlamak için
SELECT * FROM Tablo1 LIMIT 6;
-- Gösterilen satırları belirli bir noktadan başlamak üzere sınırlamak için
SELECT * FROM Tablo1 LIMIT 6 OFFSET 3;
-- ORDER BY KOMUTU
-- Herhangi bir kolona göre gösterilen değerleri azalan veya artan şekilde sıralamak için
SELECT kolon FROM tablo1 WHERE yas ORDER BY column1, column2, .. columnN] [ASC | DESC];
SELECT * FROM Tablo1 ORDER BY yas ASC
SELECT * FROM Tablo1 ORDER BY yas DESC
-- DISTINCT ANAHTAR SÖZCÜĞÜ
-- Bu anahtar sözcükle sadece farklı değerler gösterilir.
SELECT DISTINCT yas FROM tablo1;
-- JOIN KOMUTU
-- CROSS JOIN
-- Cross join bir tablodaki her satırı ikinci tablodaki bir satır ile eşleştirmek için kulanılır.
-- Eğer birinci tabloda x satır ikinci tabloda y satır varsa sonuçta x*y satır olur.
SELECT ... FROM table1 CROSS JOIN table2 …
SELECT ad, yas FROM Tablo1 CROSS JOIN Tablo2;
-- INNER JOIN
-- Inner join iki tablodaki ortak kolon değerlerini kullanarak bir sonuç üretir.
SELECT ... FROM table1 [INNER] JOIN table2 ON conditional_expression …
SELECT ad, yas FROM Tablo1 INNER JOIN Tablo2 ON Tablo1.ad = Tablo2.soyad;
-- OUTER JOIN
-- Outer join iki tablodaki ortak kolon değerlerinin dışında kalanları kullanarak bir sonuç üretir.
SELECT isci_num, isim, dept FROM Tablo1 LEFT OUTER JOIN Tablo2 ON Tablo1.id = Tablo2.isci_num;
-- ÇEKİRDEK FONKSİYONLAR
COUNT -- Sayma
AVG -- Ortalama
ABS -- Mutlak değer
SUM -- Toplam
RANDOM -- Rastgele
ROUND -- Yuvarlama
MAX -- Maksimim
MIN -- Minimum
UPPER -- Büyük Harf
LOWER -- Küçük Harf
LENGTH -- Uzunluk
CURRENT_TIMESTAMP -- Zaman
SELECT max(yas) FROM Table1;
SELECT min(yas) FROM Table1;
SELECT avg(yas) FROM Table1;
SELECT * From Table1 WHERE yas ==18;
SELECT sum(yas) FROM Table1;
SELECT random() AS Random;
SELECT upper(ad) FROM Table1;
SELECT lower(ad) FROM Table1;
SELECT ad, length(ad) FROM Table1;
```

View File

@ -1,328 +1,328 @@
---
category: tool
tool: git
contributors:
---
category: tool
tool: git
contributors:
- ["Jake Prather", "http://github.com/JakeHP"]
- ["Vinh Nguyen", "https://twitter.com/vinhnx"]
filename: LearnGit-vi.txt
lang: vi-vn
---
Git là một hệ quản lý mã nguồn và phiên bản phân tán (distributed version control and source code management system).
Nó làm được điều này là do một loạt các snapshot từ đề án của bạn, và nó hoạt động
với các snapshot đó để cung cấp cho bạn với chức năng đến phiên bản và
quản lý mã nguồn của bạn.
## Khái Niệm Versioning
### Version Control là gì?
Version Control là một hệ thống ghi lại những thay đổi ở một tập tin, hay một nhóm các tập tin, theo thời gian.
### So sánh giữa Centralized Versioning và Distributed Versioning
* Quản lý phiên bản tập trung (Centralized Versioning) tập trung vào việc đồng bộ hóa, theo dõi, và lưu trữ tập tin.
* Quản lý phiên bản phân tán (Distributed Versioning) tập trung vào việc chia sẻ các thay đổi. Mỗi sự thay đổi có một mã định dạng (id) duy nhất.
* Các hệ phân tán không có cấu trúc định sẵn. Bạn có thể thay đổi một kiểu SVN, hệ phân tán, với git.
[Thông tin thêm](http://git-scm.com/book/en/Getting-Started-About-Version-Control)
### Tại Sao Dùng Git?
* Có thể hoạt động offline.
* Cộng tác với nhau rất dễ dàng!
* Phân nhánh dễ dàng!
* Trộn (Merging)
* Git nhanh.
* Git linh hoạt.
## Kiến Trúc Git
### Repository
Một nhóm các tập tin, thư mục, các ghi chép trong quá khứ, commit, và heads. Tưởng tượng nó như là một cấu trúc dữ liệu mã nguồn,
với thuộc tính mà một "nhân tố" mã nguồn cho bạn quyền truy cập đến lịch sử sửa đổi, và một số thứ khác.
Một git repository bao gồm thư mục .git & tree đang làm việc.
### Thư mục .git (thành phần của một repository)
Thư mục .git chứa tất cả các cấu hình, log, nhánh, HEAD, và hơn nữa.
[Danh Sách Chi Tiết.](http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html)
### Tree Đang Làm (thành phần của một repository)
Đây cơ bản là các thư mục và tập tin trong repository của bạn. Nó thường được tham chiếu
thư mục đang làm việc của bạn
### Chỉ mục (thành phần của một thư mục .git)
Chỉ mục của là một staging area trong git. Nó đơn giản là một lớp riêng biệt với tree đang làm việc của bạn
từ Git repository. Điều này cho nhà phát triền nhiều lựa chọn hơn trong việc xem xét những gì được gửi đến Git
repository.
### Commit
Một git commit là một snapshot của một nhóm các thay đổi, hoặc các thao tác Working Tree của bạn.
Ví dụ, nếu bạn thêm 5 tập tin, và xóa 2 tập tin khác, những thay đổi này sẽ được chứa trong
một commit (hoặc snapshot). Commit này có thể được đẩy đến các repo khác, hoặc không!
### Nhánh
Nhánh thực chất là một con trỏ đến commit mới nhất mà bạn vừa thực hiện. Khi bạn commit,
con trỏ này sẽ cập nhật tự động và trỏ đến commit mới nhất.
### HEAD và head (thành phần của thư mục .git)
HEAD là một con trỏ đến branch hiện tại. Một repo chỉ có một HEAD *đang hoạt động*.
head là một con trỏ đến bất kỳ commit nào. Một repo có thể có nhiều head.
### Các Tài Nguyên Mang Tính Khái Niệm
* [Git For Computer Scientists](http://eagain.net/articles/git-for-computer-scientists/)
* [Git For Designers](http://hoth.entp.com/output/git_for_designers.html)
## Các Lệnh
### init
Tạo một repo Git rỗng. Các cài đặt, thông tin lưu trữ... của Git
được lưu ở một thư mục tên là ".git".
```bash
$ git init
```
### config
Để chỉnh tùy chọn. Bất kể là cho repo, hay cho hệ thống, hay điều chỉnh
toàn cục (global)
```bash
# In Ra & Và Gán Một Số Biến Tùy Chỉnh Cơ Bản (Toàn cục - Global)
$ git config --global user.email
$ git config --global user.name
$ git config --global user.email "MyEmail@Zoho.com"
$ git config --global user.name "My Name"
```
[Tìm hiểu thêm về git config.](http://git-scm.com/docs/git-config)
### help
Để cho bạn lối truy cập nhanh đến một chỉ dẫn cực kỳ chi tiết của từng lệnh. Hoặc chỉ để
nhắc bạn một số cú pháp.
```bash
# Xem nhanh các lệnh có sẵn
$ git help
# Xem tất các các lệnh
$ git help -a
# Lệnh help riêng biệt - tài liệu người dùng
# git help <command_here>
$ git help add
$ git help commit
$ git help init
```
### status
Để hiển thị sự khác nhau giữa tập tin index (cơ bản là repo đang làm việc) và HEAD commit
hiện tại.
```bash
# Sẽ hiển thị nhánh, các tập tin chưa track (chưa commit), các thay đổi và những khác biệt khác
$ git status
# Để xem các "tid bits" về git status
$ git help status
```
### add
Để thêm các tập vào tree/thư mục/repo hiện tại. Nếu bạn không `git add` các tập tin mới đến
tree/thư mục hiện tại, chúng sẽ không được kèm theo trong các commit!
```bash
# thêm một file vào thư mục hiện tại
$ git add HelloWorld.java
# thêm một file vào một thư mục khác
$ git add /path/to/file/HelloWorld.c
# Hỗ trợ Regular Expression!
$ git add ./*.java
```
### branch
Quản lý nhánh (branch). Bạn có thể xem, sửa, tạo, xóa các nhánh bằng cách dùng lệnh này.
```bash
# liệt kê các branch đang có và ở remote
$ git branch -a
# tạo branch mới
$ git branch myNewBranch
# xóa một branch
$ git branch -d myBranch
# đặt tên lại một branch
# git branch -m <oldname> <newname>
$ git branch -m myBranchName myNewBranchName
# chỉnh sửa diễn giải của một branch
$ git branch myBranchName --edit-description
```
### checkout
Cập nhật tất cả các file trong tree hiện tại để cho trùng khớp với phiên bản của index, hoặc tree cụ thể.
```bash
# Checkout (chuyển) một repo - mặc định là nhánh master
$ git checkout
# Checkout một nhánh cụ thể
$ git checkout branchName
# Tạo một nhánh mới và chuyển đến nó, tương tự: "git branch <name>; git checkout <name>"
$ git checkout -b newBranch
```
### clone
Nhân bản, hoặc sao chép, một repo hiện có thành một thư mục mới. Nó cũng thêm
các branch có remote-tracking cho mỗi branch trong một repo được nhân bản, mà
cho phép bạn push đến một remote branch.
```bash
# Nhân bản learnxinyminutes-docs
$ git clone https://github.com/adambard/learnxinyminutes-docs.git
```
### commit
Lưu trữ nội dung hiện tại của index trong một "commit" mới. Điều này cho phép tạo ra thay đổi và một ghi chú tạo ra bởi người dùng.
```bash
# commit với một ghi chú
$ git commit -m "Added multiplyNumbers() function to HelloWorld.c"
```
### diff
Hiển thị sự khác biệt giữa một file trong thư mục hiện tại, index và commits.
```bash
# Hiển thị sự khác biệt giữa thư mục hiện tại và index
$ git diff
# Hiển thị khác biệt giữa index và commit mới nhất.
$ git diff --cached
# Hiển thị khác biệt giữa thư mục đang làm việc và commit mới nhất
$ git diff HEAD
```
### grep
Cho phép bạn tìm kiếm nhanh một repo.
Các tinh chỉnh tùy chọn:
```bash
# Cảm ơn Travis Jeffery vì những lệnh này
# Đặt số của dòng được hiển thị trong kết quả tìm kiếm grep
$ git config --global grep.lineNumber true
# Làm cho kết quả tìm kiếm dễ đọc hơn, bao gồm cả gom nhóm
$ git config --global alias.g "grep --break --heading --line-number"
```
```bash
# Tìm "variableName" trong tất cả các file Java
$ git grep 'variableName' -- '*.java'
# Tìm một dòng mà có chứa "arrayListName" và, "add" hoặc "remove"
$ git grep -e 'arrayListName' --and \( -e add -e remove \)
```
Google để xem thêm các ví dụ
[Git Grep Ninja](http://travisjeffery.com/b/2012/02/search-a-git-repo-like-a-ninja)
### log
Hiển thị các commit đến repo.
```bash
# Hiện tất cả các commit
$ git log
# Hiện X commit
$ git log -n 10
# Chỉ hiện các commit đã merge merge commits
$ git log --merges
```
### merge
"Trộn" các thay đổi từ commit bên ngoài vào trong nhánh hiện tại.
```bash
# Merge branch cụ thể vào branch hiện tại.
$ git merge branchName
# Luôn khởi tạo một merge commit khi trộn (merge)
$ git merge --no-ff branchName
```
### mv
Đặt lại tên hoặc di chuyển một file
```bash
# Đặt lại tên một file
$ git mv HelloWorld.c HelloNewWorld.c
# Di chuyển một file
$ git mv HelloWorld.c ./new/path/HelloWorld.c
# Buộc đặt lại tên hoặc di chuyển
# "existingFile" đã tồn tại trong thự mục, sẽ bị ghi đè
$ git mv -f myFile existingFile
```
### pull
Pull về từ một repo và merge nó vào branch khác.
```bash
# Cập nhật repo local của bạn, bằng cách merge các thay đổi mới
# từ remote "origin" và nhánh "master".
# git pull <remote> <branch>
# git pull => hoàn toàn mặc định như => git pull origin master
$ git pull origin master
# Merge các thay đổi từ remote branch và rebase
# các commit trong branch lên trên local repo, như sau: "git pull <remote> <branch>, git rebase <branch>"
$ git pull origin master --rebase
```
### push
push và merge các thay đổi từ một branch đến một remote & branch.
- ["Vinh Nguyen", "https://twitter.com/vinhnx"]
filename: LearnGit-vi.txt
lang: vi-vn
---
Git là một hệ quản lý mã nguồn và phiên bản phân tán (distributed version control and source code management system).
Nó làm được điều này là do một loạt các snapshot từ đề án của bạn, và nó hoạt động
với các snapshot đó để cung cấp cho bạn với chức năng đến phiên bản và
quản lý mã nguồn của bạn.
## Khái Niệm Versioning
### Version Control là gì?
Version Control là một hệ thống ghi lại những thay đổi ở một tập tin, hay một nhóm các tập tin, theo thời gian.
### So sánh giữa Centralized Versioning và Distributed Versioning
* Quản lý phiên bản tập trung (Centralized Versioning) tập trung vào việc đồng bộ hóa, theo dõi, và lưu trữ tập tin.
* Quản lý phiên bản phân tán (Distributed Versioning) tập trung vào việc chia sẻ các thay đổi. Mỗi sự thay đổi có một mã định dạng (id) duy nhất.
* Các hệ phân tán không có cấu trúc định sẵn. Bạn có thể thay đổi một kiểu SVN, hệ phân tán, với git.
[Thông tin thêm](http://git-scm.com/book/en/Getting-Started-About-Version-Control)
### Tại Sao Dùng Git?
* Có thể hoạt động offline.
* Cộng tác với nhau rất dễ dàng!
* Phân nhánh dễ dàng!
* Trộn (Merging)
* Git nhanh.
* Git linh hoạt.
## Kiến Trúc Git
### Repository
Một nhóm các tập tin, thư mục, các ghi chép trong quá khứ, commit, và heads. Tưởng tượng nó như là một cấu trúc dữ liệu mã nguồn,
với thuộc tính mà một "nhân tố" mã nguồn cho bạn quyền truy cập đến lịch sử sửa đổi, và một số thứ khác.
Một git repository bao gồm thư mục .git & tree đang làm việc.
### Thư mục .git (thành phần của một repository)
Thư mục .git chứa tất cả các cấu hình, log, nhánh, HEAD, và hơn nữa.
[Danh Sách Chi Tiết.](http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html)
### Tree Đang Làm (thành phần của một repository)
Đây cơ bản là các thư mục và tập tin trong repository của bạn. Nó thường được tham chiếu
thư mục đang làm việc của bạn
### Chỉ mục (thành phần của một thư mục .git)
Chỉ mục của là một staging area trong git. Nó đơn giản là một lớp riêng biệt với tree đang làm việc của bạn
từ Git repository. Điều này cho nhà phát triền nhiều lựa chọn hơn trong việc xem xét những gì được gửi đến Git
repository.
### Commit
Một git commit là một snapshot của một nhóm các thay đổi, hoặc các thao tác Working Tree của bạn.
Ví dụ, nếu bạn thêm 5 tập tin, và xóa 2 tập tin khác, những thay đổi này sẽ được chứa trong
một commit (hoặc snapshot). Commit này có thể được đẩy đến các repo khác, hoặc không!
### Nhánh
Nhánh thực chất là một con trỏ đến commit mới nhất mà bạn vừa thực hiện. Khi bạn commit,
con trỏ này sẽ cập nhật tự động và trỏ đến commit mới nhất.
### HEAD và head (thành phần của thư mục .git)
HEAD là một con trỏ đến branch hiện tại. Một repo chỉ có một HEAD *đang hoạt động*.
head là một con trỏ đến bất kỳ commit nào. Một repo có thể có nhiều head.
### Các Tài Nguyên Mang Tính Khái Niệm
* [Git For Computer Scientists](http://eagain.net/articles/git-for-computer-scientists/)
* [Git For Designers](http://hoth.entp.com/output/git_for_designers.html)
## Các Lệnh
### init
Tạo một repo Git rỗng. Các cài đặt, thông tin lưu trữ... của Git
được lưu ở một thư mục tên là ".git".
```bash
$ git init
```
### config
Để chỉnh tùy chọn. Bất kể là cho repo, hay cho hệ thống, hay điều chỉnh
toàn cục (global)
```bash
# In Ra & Và Gán Một Số Biến Tùy Chỉnh Cơ Bản (Toàn cục - Global)
$ git config --global user.email
$ git config --global user.name
$ git config --global user.email "MyEmail@Zoho.com"
$ git config --global user.name "My Name"
```
[Tìm hiểu thêm về git config.](http://git-scm.com/docs/git-config)
### help
Để cho bạn lối truy cập nhanh đến một chỉ dẫn cực kỳ chi tiết của từng lệnh. Hoặc chỉ để
nhắc bạn một số cú pháp.
```bash
# Xem nhanh các lệnh có sẵn
$ git help
# Xem tất các các lệnh
$ git help -a
# Lệnh help riêng biệt - tài liệu người dùng
# git help <command_here>
$ git help add
$ git help commit
$ git help init
```
### status
Để hiển thị sự khác nhau giữa tập tin index (cơ bản là repo đang làm việc) và HEAD commit
hiện tại.
```bash
# Sẽ hiển thị nhánh, các tập tin chưa track (chưa commit), các thay đổi và những khác biệt khác
$ git status
# Để xem các "tid bits" về git status
$ git help status
```
### add
Để thêm các tập vào tree/thư mục/repo hiện tại. Nếu bạn không `git add` các tập tin mới đến
tree/thư mục hiện tại, chúng sẽ không được kèm theo trong các commit!
```bash
# thêm một file vào thư mục hiện tại
$ git add HelloWorld.java
# thêm một file vào một thư mục khác
$ git add /path/to/file/HelloWorld.c
# Hỗ trợ Regular Expression!
$ git add ./*.java
```
### branch
Quản lý nhánh (branch). Bạn có thể xem, sửa, tạo, xóa các nhánh bằng cách dùng lệnh này.
```bash
# liệt kê các branch đang có và ở remote
$ git branch -a
# tạo branch mới
$ git branch myNewBranch
# xóa một branch
$ git branch -d myBranch
# đặt tên lại một branch
# git branch -m <oldname> <newname>
$ git branch -m myBranchName myNewBranchName
# chỉnh sửa diễn giải của một branch
$ git branch myBranchName --edit-description
```
### checkout
Cập nhật tất cả các file trong tree hiện tại để cho trùng khớp với phiên bản của index, hoặc tree cụ thể.
```bash
# Checkout (chuyển) một repo - mặc định là nhánh master
$ git checkout
# Checkout một nhánh cụ thể
$ git checkout branchName
# Tạo một nhánh mới và chuyển đến nó, tương tự: "git branch <name>; git checkout <name>"
$ git checkout -b newBranch
```
### clone
Nhân bản, hoặc sao chép, một repo hiện có thành một thư mục mới. Nó cũng thêm
các branch có remote-tracking cho mỗi branch trong một repo được nhân bản, mà
cho phép bạn push đến một remote branch.
```bash
# Nhân bản learnxinyminutes-docs
$ git clone https://github.com/adambard/learnxinyminutes-docs.git
```
### commit
Lưu trữ nội dung hiện tại của index trong một "commit" mới. Điều này cho phép tạo ra thay đổi và một ghi chú tạo ra bởi người dùng.
```bash
# commit với một ghi chú
$ git commit -m "Added multiplyNumbers() function to HelloWorld.c"
```
### diff
Hiển thị sự khác biệt giữa một file trong thư mục hiện tại, index và commits.
```bash
# Hiển thị sự khác biệt giữa thư mục hiện tại và index
$ git diff
# Hiển thị khác biệt giữa index và commit mới nhất.
$ git diff --cached
# Hiển thị khác biệt giữa thư mục đang làm việc và commit mới nhất
$ git diff HEAD
```
### grep
Cho phép bạn tìm kiếm nhanh một repo.
Các tinh chỉnh tùy chọn:
```bash
# Cảm ơn Travis Jeffery vì những lệnh này
# Đặt số của dòng được hiển thị trong kết quả tìm kiếm grep
$ git config --global grep.lineNumber true
# Làm cho kết quả tìm kiếm dễ đọc hơn, bao gồm cả gom nhóm
$ git config --global alias.g "grep --break --heading --line-number"
```
```bash
# Tìm "variableName" trong tất cả các file Java
$ git grep 'variableName' -- '*.java'
# Tìm một dòng mà có chứa "arrayListName" và, "add" hoặc "remove"
$ git grep -e 'arrayListName' --and \( -e add -e remove \)
```
Google để xem thêm các ví dụ
[Git Grep Ninja](http://travisjeffery.com/b/2012/02/search-a-git-repo-like-a-ninja)
### log
Hiển thị các commit đến repo.
```bash
# Hiện tất cả các commit
$ git log
# Hiện X commit
$ git log -n 10
# Chỉ hiện các commit đã merge merge commits
$ git log --merges
```
### merge
"Trộn" các thay đổi từ commit bên ngoài vào trong nhánh hiện tại.
```bash
# Merge branch cụ thể vào branch hiện tại.
$ git merge branchName
# Luôn khởi tạo một merge commit khi trộn (merge)
$ git merge --no-ff branchName
```
### mv
Đặt lại tên hoặc di chuyển một file
```bash
# Đặt lại tên một file
$ git mv HelloWorld.c HelloNewWorld.c
# Di chuyển một file
$ git mv HelloWorld.c ./new/path/HelloWorld.c
# Buộc đặt lại tên hoặc di chuyển
# "existingFile" đã tồn tại trong thự mục, sẽ bị ghi đè
$ git mv -f myFile existingFile
```
### pull
Pull về từ một repo và merge nó vào branch khác.
```bash
# Cập nhật repo local của bạn, bằng cách merge các thay đổi mới
# từ remote "origin" và nhánh "master".
# git pull <remote> <branch>
# git pull => hoàn toàn mặc định như => git pull origin master
$ git pull origin master
# Merge các thay đổi từ remote branch và rebase
# các commit trong branch lên trên local repo, như sau: "git pull <remote> <branch>, git rebase <branch>"
$ git pull origin master --rebase
```
### push
push và merge các thay đổi từ một branch đến một remote & branch.
```bash
# Push và merge các thay đổi từ một repo local đến một
# remote có tên là "origin" và nhánh "master".
@ -334,68 +334,68 @@ $ git push origin master
$ git push -u origin master
# Từ lúc này, bất cứ khi nào bạn muốn push từ cùng một nhánh local đó, sử dụng lối tắt:
$ git push
```
### rebase (thận trọng)
Lấy tất cả các thay đổi mà đã được commit trên một nhánh, và replay (?) chúng trên một nhánh khác.
*Không rebase các commit mà bạn đã push đến một repo công khai*.
```bash
# Rebase experimentBranch lên master
# git rebase <basebranch> <topicbranch>
$ git rebase master experimentBranch
```
[Đọc Thêm.](http://git-scm.com/book/en/Git-Branching-Rebasing)
### reset (thận trọng)
Thiết lập lạo HEAD hiện tại đến một trạng thái cụ thể. Điều này cho phép bạn làm lại các merges,
pulls, commits, thêm, and hơn nữa. Nó là một lệnh hay nhưng cũng nguy hiểm nếu bạn không
biết mình đang làm gì.
```bash
# Thiết lập lại staging area, để trùng với commit mới nhất (để thư mục không thay đổi)
$ git reset
# Thiết lập lại staging area, để trùng với commit mới nhất, và ghi đè lên thư mục hiện tại
$ git reset --hard
# Di chuyển nhánh hiện tại đến một commit cụ thể (để thư mục không thay đổi)
# tất cả thay đổi vẫn duy trì trong thư mục.
$ git reset 31f2bb1
# Di chuyển nhánh hiện tại lùi về một commit cụ thể
# và làm cho thư mục hiện tại trùng (xóa các thay đổi chưa được commit và tất cả các commit
# sau một commit cụ thể).
$ git reset --hard 31f2bb1
```
### rm
Ngược lại với git add, git rm xóa file từ tree đang làm việc.
```bash
# xóa HelloWorld.c
$ git rm HelloWorld.c
# Xóa file từ thư mục khác
$ git rm /pather/to/the/file/HelloWorld.c
```
## Thông tin thêm
* [tryGit - A fun interactive way to learn Git.](http://try.github.io/levels/1/challenges/1)
* [git-scm - Video Tutorials](http://git-scm.com/videos)
* [git-scm - Documentation](http://git-scm.com/docs)
* [Atlassian Git - Tutorials & Workflows](https://www.atlassian.com/git/)
* [SalesForce Cheat Sheet](https://na1.salesforce.com/help/doc/en/salesforce_git_developer_cheatsheet.pdf)
* [Git - the simple guide](http://rogerdudler.github.io/git-guide/index.html)
```
### rebase (thận trọng)
Lấy tất cả các thay đổi mà đã được commit trên một nhánh, và replay (?) chúng trên một nhánh khác.
*Không rebase các commit mà bạn đã push đến một repo công khai*.
```bash
# Rebase experimentBranch lên master
# git rebase <basebranch> <topicbranch>
$ git rebase master experimentBranch
```
[Đọc Thêm.](http://git-scm.com/book/en/Git-Branching-Rebasing)
### reset (thận trọng)
Thiết lập lạo HEAD hiện tại đến một trạng thái cụ thể. Điều này cho phép bạn làm lại các merges,
pulls, commits, thêm, and hơn nữa. Nó là một lệnh hay nhưng cũng nguy hiểm nếu bạn không
biết mình đang làm gì.
```bash
# Thiết lập lại staging area, để trùng với commit mới nhất (để thư mục không thay đổi)
$ git reset
# Thiết lập lại staging area, để trùng với commit mới nhất, và ghi đè lên thư mục hiện tại
$ git reset --hard
# Di chuyển nhánh hiện tại đến một commit cụ thể (để thư mục không thay đổi)
# tất cả thay đổi vẫn duy trì trong thư mục.
$ git reset 31f2bb1
# Di chuyển nhánh hiện tại lùi về một commit cụ thể
# và làm cho thư mục hiện tại trùng (xóa các thay đổi chưa được commit và tất cả các commit
# sau một commit cụ thể).
$ git reset --hard 31f2bb1
```
### rm
Ngược lại với git add, git rm xóa file từ tree đang làm việc.
```bash
# xóa HelloWorld.c
$ git rm HelloWorld.c
# Xóa file từ thư mục khác
$ git rm /pather/to/the/file/HelloWorld.c
```
## Thông tin thêm
* [tryGit - A fun interactive way to learn Git.](http://try.github.io/levels/1/challenges/1)
* [git-scm - Video Tutorials](http://git-scm.com/videos)
* [git-scm - Documentation](http://git-scm.com/docs)
* [Atlassian Git - Tutorials & Workflows](https://www.atlassian.com/git/)
* [SalesForce Cheat Sheet](https://na1.salesforce.com/help/doc/en/salesforce_git_developer_cheatsheet.pdf)
* [Git - the simple guide](http://rogerdudler.github.io/git-guide/index.html)

View File

@ -1,316 +1,316 @@
---
language: Objective-C
contributors:
- ["Eugene Yagrushkin", "www.about.me/yagrushkin"]
- ["Yannick Loriot", "https://github.com/YannickL"]
lang: vi-vn
filename: LearnObjectiveC-vi.m
---
Objective-C ngôn ngữ lập trình chính đưc sử dụng bởi Apple cho các hệ điều hành macOS, iOS các framework tương ng của họ, Cocoa Cocoa Touch.
một ngôn ngữ lập trình mục đích tổng quát, hướng đi tượng bổ sung thêm kiểu truyền thông điệp giống Smalltalk vào ngôn ngữ lập trình C.
```objective-c
// Chú thích dòng đơn bắt đu với //
/*
Chú thích đa dòng trông như thế này.
*/
// Nhập các headers của framework Foundation với pháp #import
#import <Foundation/Foundation.h>
#import "MyClass.h"
// Đu vào chương trình của bạn một hàm gọi
// main với một kiểu trả về kiểu integer.
int main (int argc, const char * argv[])
{
// Tạo một autorelease pool đ quản bộ nhớ vào chương trình
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Sử dụng hàm NSLog() đ in ra các dòng lệnh vào console
NSLog(@"Hello World!"); // Print the string "Hello World!"
///////////////////////////////////////
// Kiểu & Biến (Types & Variables)
///////////////////////////////////////
// Khai báo số nguyên
int myPrimitive1 = 1;
long myPrimitive2 = 234554664565;
// Khai báo đi tượng
// Đt dấu nháy * vào trước tên biến cho khai báo đi tượng strong
MyClass *myObject1 = nil; // Strong
id myObject2 = nil; // Weak
// %@ một đi tượng
// 'miêu tả' ('desciption') thông lệ đ trình bày giá trị của các Đi tượng
NSLog(@"%@ và %@", myObject1, [myObject2 description]); // In ra "(null) và (null)"
// Chuỗi
NSString *worldString = @"World";
NSLog(@"Hello %@!", worldString); // In ra "Hello World!"
// tự literals
NSNumber *theLetterZNumber = @'Z';
char theLetterZ = [theLetterZNumber charValue];
NSLog(@"%c", theLetterZ);
// Số nguyên literals
NSNumber *fortyTwoNumber = @42;
int fortyTwo = [fortyTwoNumber intValue];
NSLog(@"%i", fortyTwo);
NSNumber *fortyTwoUnsignedNumber = @42U;
unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue];
NSLog(@"%u", fortyTwoUnsigned);
NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:42];
short fortyTwoShort = [fortyTwoShortNumber shortValue];
NSLog(@"%hi", fortyTwoShort);
NSNumber *fortyTwoLongNumber = @42L;
long fortyTwoLong = [fortyTwoLongNumber longValue];
NSLog(@"%li", fortyTwoLong);
// Dấu phẩy đng (floating point) literals
NSNumber *piFloatNumber = @3.141592654F;
float piFloat = [piFloatNumber floatValue];
NSLog(@"%f", piFloat);
NSNumber *piDoubleNumber = @3.1415926535;
double piDouble = [piDoubleNumber doubleValue];
NSLog(@"%f", piDouble);
// BOOL literals
NSNumber *yesNumber = @YES;
NSNumber *noNumber = @NO;
// Đi tượng Mảng
NSArray *anArray = @[@1, @2, @3, @4];
NSNumber *thirdNumber = anArray[2];
NSLog(@"Third number = %@", thirdNumber); // In ra "Third number = 3"
// Đi tượng Từ điển
NSDictionary *aDictionary = @{ @"key1" : @"value1", @"key2" : @"value2" };
NSObject *valueObject = aDictionary[@"A Key"];
NSLog(@"Đối tượng = %@", valueObject); // In ra "Object = (null)"
///////////////////////////////////////
// Toán Tử (Operators)
///////////////////////////////////////
// Các toán tử cũng hoạt đng giống như ngôn ngữ C
// dụ:
2 + 5; // => 7
4.2f + 5.1f; // => 9.3f
3 == 2; // => 0 (NO)
3 != 2; // => 1 (YES)
1 && 1; // => 1 (Logical and)
0 || 1; // => 1 (Logical or)
~0x0F; // => 0xF0 (bitwise negation)
0x0F & 0xF0; // => 0x00 (bitwise AND)
0x01 << 1; // => 0x02 (bitwise dịch trái (bởi 1))
/////////////////////////////////////////////
// Cấu Trúc Điều Khiển (Controls Structures)
/////////////////////////////////////////////
// Câu lệnh If-Else
if (NO)
{
NSLog(@"I am never run");
} else if (0)
{
NSLog(@"I am also never run");
} else
{
NSLog(@"I print");
}
// Câu lệnh Switch
switch (2)
{
case 0:
{
NSLog(@"I am never run");
} break;
case 1:
{
NSLog(@"I am also never run");
} break;
default:
{
NSLog(@"I print");
} break;
}
// Câu lệnh vòng lặp While
int ii = 0;
while (ii < 4)
{
NSLog(@"%d,", ii++); // ii++ tăng dần, sau khi sử dụng giá trị của .
} // => in ra "0,"
// "1,"
// "2,"
// "3,"
// Câu lệnh vòng lặp For
int jj;
for (jj=0; jj < 4; jj++)
{
NSLog(@"%d,", jj);
} // => in ra "0,"
// "1,"
// "2,"
// "3,"
// Câu lệnh Foreach
NSArray *values = @[@0, @1, @2, @3];
for (NSNumber *value in values)
{
NSLog(@"%@,", value);
} // => in ra "0,"
// "1,"
// "2,"
// "3,"
// Câu lệnh Try-Catch-Finally
@try
{
// Your statements here
@throw [NSException exceptionWithName:@"FileNotFoundException"
reason:@"Không Tìm Thấy Tập Tin trên Hệ Thống" userInfo:nil];
} @catch (NSException * e)
{
NSLog(@"Exception: %@", e);
} @finally
{
NSLog(@"Finally");
} // => in ra "Exception: Không Tìm Thấy Tập Tin trên Hệ Thống"
// "Finally"
///////////////////////////////////////
// Đi Tượng (Objects)
///////////////////////////////////////
// Tạo một thực thể đi tượng bằng cách phân vùng nhớ khởi tạo đi tượng đó.
// Một đi tượng sẽ không thật sự hoạt đng cho đến khi cả 2 bước alloc] init] đưc hoàn thành
MyClass *myObject = [[MyClass alloc] init];
// hình lập trình hướng đi tượng của Objective-C dựa trên việc truyền thông điệp (message)
// các thực thể đi tượng với nhau.
// Trong Objective-C một đi tượng không đơn thuần gọi phương thức; truyền thông điệp.
[myObject instanceMethodWithParameter:@"Steve Jobs"];
// Dọn dẹp vùng nhớ bạn đã dùng chương trình
[pool drain];
// Kết thúc chương trình
return 0;
}
///////////////////////////////////////
// Lớp Hàm (Classes & Functions)
///////////////////////////////////////
// Khai báo lớp của bạn một tập tin header (MyClass.h):
// pháp Khai Báo Lớp:
// @interface ClassName : ParentClassName <ImplementedProtocols>
// {
// Khai báo biến thành viên;
// }
// -/+ (type) Khai báo method;
// @end
@interface MyClass : NSObject <MyProtocol>
{
int count;
id data;
NSString *name;
}
// hiệu (notation) tiện ích đ tự đng khởi tạo public getter setter
@property int count;
@property (copy) NSString *name; // Sao chép đi tượng trong quá trình gán.
@property (readonly) id data; // Chỉ khai báo phương thức getter.
// Phương thức
+/- (return type)methodSignature:(Parameter Type *)parameterName;
// dấu '+' cho phương thức lớp
+ (NSString *)classMethod;
// dấu '-' cho phương thức thực thể
- (NSString *)instanceMethodWithParameter:(NSString *)string;
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number;
@end
// Thực thi các phương thức trong một tập tin thực thi (MyClass.m):
@implementation MyClass
// Gọi khi đi tượng đưc release
- (void)dealloc
{
}
// Phương thức khởi tạo (Constructors) một cách đ tạo các lớp
// Đây phương thức khởi tạo mặc đnh đưc gọi khi đi tượng đưc khởi tạo
- (id)init
{
if ((self = [super init]))
{
self.count = 1;
}
return self;
}
+ (NSString *)classMethod
{
return [[self alloc] init];
}
- (NSString *)instanceMethodWithParameter:(NSString *)string
{
return @"New string";
}
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number
{
return @42;
}
// Các phương thức đưc khai báo vào MyProtocol
- (void)myProtocolMethod
{
// câu lệnh
}
@end
/*
* Một protocol khai báo các phương thức thể thực thi bởi bất kỳ lớp nào.
* Các protocol chính chúng không phải các lớp. Chúng chỉ đơn giản đnh ra giao diện (interface)
* các đi tượng khác trách nhiệm sẽ thực thi.
*/
@protocol MyProtocol
- (void)myProtocolMethod;
@end
```
## Xem Thêm
+ [Wikipedia Objective-C](http://en.wikipedia.org/wiki/Objective-C)
+ Apple Docs':
+ [Learning Objective-C](http://developer.apple.com/library/ios/referencelibrary/GettingStarted/Learning_Objective-C_A_Primer/)
+ [Programming With Objective-C](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html)
+ [Object-Oriented Programming with Objective-C](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/OOP_ObjC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40005149)
+ [Coding Guidelines for Cocoa](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html)
+ [iOS For High School Students: Getting Started](http://www.raywenderlich.com/5600/ios-for-high-school-students-getting-started)
---
language: Objective-C
contributors:
- ["Eugene Yagrushkin", "www.about.me/yagrushkin"]
- ["Yannick Loriot", "https://github.com/YannickL"]
lang: vi-vn
filename: LearnObjectiveC-vi.m
---
Objective-C ngôn ngữ lập trình chính đưc sử dụng bởi Apple cho các hệ điều hành macOS, iOS các framework tương ng của họ, Cocoa Cocoa Touch.
một ngôn ngữ lập trình mục đích tổng quát, hướng đi tượng bổ sung thêm kiểu truyền thông điệp giống Smalltalk vào ngôn ngữ lập trình C.
```objective-c
// Chú thích dòng đơn bắt đu với //
/*
Chú thích đa dòng trông như thế này.
*/
// Nhập các headers của framework Foundation với pháp #import
#import <Foundation/Foundation.h>
#import "MyClass.h"
// Đu vào chương trình của bạn một hàm gọi
// main với một kiểu trả về kiểu integer.
int main (int argc, const char * argv[])
{
// Tạo một autorelease pool đ quản bộ nhớ vào chương trình
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Sử dụng hàm NSLog() đ in ra các dòng lệnh vào console
NSLog(@"Hello World!"); // Print the string "Hello World!"
///////////////////////////////////////
// Kiểu & Biến (Types & Variables)
///////////////////////////////////////
// Khai báo số nguyên
int myPrimitive1 = 1;
long myPrimitive2 = 234554664565;
// Khai báo đi tượng
// Đt dấu nháy * vào trước tên biến cho khai báo đi tượng strong
MyClass *myObject1 = nil; // Strong
id myObject2 = nil; // Weak
// %@ một đi tượng
// 'miêu tả' ('desciption') thông lệ đ trình bày giá trị của các Đi tượng
NSLog(@"%@ và %@", myObject1, [myObject2 description]); // In ra "(null) và (null)"
// Chuỗi
NSString *worldString = @"World";
NSLog(@"Hello %@!", worldString); // In ra "Hello World!"
// tự literals
NSNumber *theLetterZNumber = @'Z';
char theLetterZ = [theLetterZNumber charValue];
NSLog(@"%c", theLetterZ);
// Số nguyên literals
NSNumber *fortyTwoNumber = @42;
int fortyTwo = [fortyTwoNumber intValue];
NSLog(@"%i", fortyTwo);
NSNumber *fortyTwoUnsignedNumber = @42U;
unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue];
NSLog(@"%u", fortyTwoUnsigned);
NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:42];
short fortyTwoShort = [fortyTwoShortNumber shortValue];
NSLog(@"%hi", fortyTwoShort);
NSNumber *fortyTwoLongNumber = @42L;
long fortyTwoLong = [fortyTwoLongNumber longValue];
NSLog(@"%li", fortyTwoLong);
// Dấu phẩy đng (floating point) literals
NSNumber *piFloatNumber = @3.141592654F;
float piFloat = [piFloatNumber floatValue];
NSLog(@"%f", piFloat);
NSNumber *piDoubleNumber = @3.1415926535;
double piDouble = [piDoubleNumber doubleValue];
NSLog(@"%f", piDouble);
// BOOL literals
NSNumber *yesNumber = @YES;
NSNumber *noNumber = @NO;
// Đi tượng Mảng
NSArray *anArray = @[@1, @2, @3, @4];
NSNumber *thirdNumber = anArray[2];
NSLog(@"Third number = %@", thirdNumber); // In ra "Third number = 3"
// Đi tượng Từ điển
NSDictionary *aDictionary = @{ @"key1" : @"value1", @"key2" : @"value2" };
NSObject *valueObject = aDictionary[@"A Key"];
NSLog(@"Đối tượng = %@", valueObject); // In ra "Object = (null)"
///////////////////////////////////////
// Toán Tử (Operators)
///////////////////////////////////////
// Các toán tử cũng hoạt đng giống như ngôn ngữ C
// dụ:
2 + 5; // => 7
4.2f + 5.1f; // => 9.3f
3 == 2; // => 0 (NO)
3 != 2; // => 1 (YES)
1 && 1; // => 1 (Logical and)
0 || 1; // => 1 (Logical or)
~0x0F; // => 0xF0 (bitwise negation)
0x0F & 0xF0; // => 0x00 (bitwise AND)
0x01 << 1; // => 0x02 (bitwise dịch trái (bởi 1))
/////////////////////////////////////////////
// Cấu Trúc Điều Khiển (Controls Structures)
/////////////////////////////////////////////
// Câu lệnh If-Else
if (NO)
{
NSLog(@"I am never run");
} else if (0)
{
NSLog(@"I am also never run");
} else
{
NSLog(@"I print");
}
// Câu lệnh Switch
switch (2)
{
case 0:
{
NSLog(@"I am never run");
} break;
case 1:
{
NSLog(@"I am also never run");
} break;
default:
{
NSLog(@"I print");
} break;
}
// Câu lệnh vòng lặp While
int ii = 0;
while (ii < 4)
{
NSLog(@"%d,", ii++); // ii++ tăng dần, sau khi sử dụng giá trị của .
} // => in ra "0,"
// "1,"
// "2,"
// "3,"
// Câu lệnh vòng lặp For
int jj;
for (jj=0; jj < 4; jj++)
{
NSLog(@"%d,", jj);
} // => in ra "0,"
// "1,"
// "2,"
// "3,"
// Câu lệnh Foreach
NSArray *values = @[@0, @1, @2, @3];
for (NSNumber *value in values)
{
NSLog(@"%@,", value);
} // => in ra "0,"
// "1,"
// "2,"
// "3,"
// Câu lệnh Try-Catch-Finally
@try
{
// Your statements here
@throw [NSException exceptionWithName:@"FileNotFoundException"
reason:@"Không Tìm Thấy Tập Tin trên Hệ Thống" userInfo:nil];
} @catch (NSException * e)
{
NSLog(@"Exception: %@", e);
} @finally
{
NSLog(@"Finally");
} // => in ra "Exception: Không Tìm Thấy Tập Tin trên Hệ Thống"
// "Finally"
///////////////////////////////////////
// Đi Tượng (Objects)
///////////////////////////////////////
// Tạo một thực thể đi tượng bằng cách phân vùng nhớ khởi tạo đi tượng đó.
// Một đi tượng sẽ không thật sự hoạt đng cho đến khi cả 2 bước alloc] init] đưc hoàn thành
MyClass *myObject = [[MyClass alloc] init];
// hình lập trình hướng đi tượng của Objective-C dựa trên việc truyền thông điệp (message)
// các thực thể đi tượng với nhau.
// Trong Objective-C một đi tượng không đơn thuần gọi phương thức; truyền thông điệp.
[myObject instanceMethodWithParameter:@"Steve Jobs"];
// Dọn dẹp vùng nhớ bạn đã dùng chương trình
[pool drain];
// Kết thúc chương trình
return 0;
}
///////////////////////////////////////
// Lớp Hàm (Classes & Functions)
///////////////////////////////////////
// Khai báo lớp của bạn một tập tin header (MyClass.h):
// pháp Khai Báo Lớp:
// @interface ClassName : ParentClassName <ImplementedProtocols>
// {
// Khai báo biến thành viên;
// }
// -/+ (type) Khai báo method;
// @end
@interface MyClass : NSObject <MyProtocol>
{
int count;
id data;
NSString *name;
}
// hiệu (notation) tiện ích đ tự đng khởi tạo public getter setter
@property int count;
@property (copy) NSString *name; // Sao chép đi tượng trong quá trình gán.
@property (readonly) id data; // Chỉ khai báo phương thức getter.
// Phương thức
+/- (return type)methodSignature:(Parameter Type *)parameterName;
// dấu '+' cho phương thức lớp
+ (NSString *)classMethod;
// dấu '-' cho phương thức thực thể
- (NSString *)instanceMethodWithParameter:(NSString *)string;
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number;
@end
// Thực thi các phương thức trong một tập tin thực thi (MyClass.m):
@implementation MyClass
// Gọi khi đi tượng đưc release
- (void)dealloc
{
}
// Phương thức khởi tạo (Constructors) một cách đ tạo các lớp
// Đây phương thức khởi tạo mặc đnh đưc gọi khi đi tượng đưc khởi tạo
- (id)init
{
if ((self = [super init]))
{
self.count = 1;
}
return self;
}
+ (NSString *)classMethod
{
return [[self alloc] init];
}
- (NSString *)instanceMethodWithParameter:(NSString *)string
{
return @"New string";
}
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number
{
return @42;
}
// Các phương thức đưc khai báo vào MyProtocol
- (void)myProtocolMethod
{
// câu lệnh
}
@end
/*
* Một protocol khai báo các phương thức thể thực thi bởi bất kỳ lớp nào.
* Các protocol chính chúng không phải các lớp. Chúng chỉ đơn giản đnh ra giao diện (interface)
* các đi tượng khác trách nhiệm sẽ thực thi.
*/
@protocol MyProtocol
- (void)myProtocolMethod;
@end
```
## Xem Thêm
+ [Wikipedia Objective-C](http://en.wikipedia.org/wiki/Objective-C)
+ Apple Docs':
+ [Learning Objective-C](http://developer.apple.com/library/ios/referencelibrary/GettingStarted/Learning_Objective-C_A_Primer/)
+ [Programming With Objective-C](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html)
+ [Object-Oriented Programming with Objective-C](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/OOP_ObjC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40005149)
+ [Coding Guidelines for Cocoa](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html)
+ [iOS For High School Students: Getting Started](http://www.raywenderlich.com/5600/ios-for-high-school-students-getting-started)

File diff suppressed because it is too large Load Diff

View File

@ -1,345 +1,345 @@
---
language: elisp
contributors:
- ["Bastien Guerry", "http://bzg.fr"]
translators:
- ["Chenbo Li", "http://binarythink.net"]
filename: learn-emacs-lisp-zh.el
lang: zh-cn
---
```scheme
;; 15分钟学会Emacs Lisp (v0.2a)
;;作者bzghttps://github.com/bzg
;; 译者lichenbohttp://douban.com/people/lichenbo
;;
;; 请先阅读Peter Norvig的一篇好文:
;; http://norvig.com/21-days.html
;; 译者注中文版请见http://blog.youxu.info/21-days/
;;
;; 之后安装GNU Emacs 24.3:
;;
;; Debian: apt-get install emacs (视具体发行版而定)
;; MacOSX: http://emacsformacosx.com/emacs-builds/Emacs-24.3-universal-10.6.8.dmg
;; Windows: http://ftp.gnu.org/gnu/windows/emacs/emacs-24.3-bin-i386.zip
;;
;; 更多信息可以在这里找到:
;; http://www.gnu.org/software/emacs/#Obtaining
;; 很重要的警告:
;;
;; 按照这个教程来学习并不会对你的电脑有任何损坏
;; 除非你自己在学习的过程中愤怒地把它砸了
;; 如果出现了这种情况,我不会承担任何责任
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 打开emacs
;;
;; 按'q'消除欢迎界面
;;
;; 现在请注意窗口底部的那一个灰色长条
;;
;; "*scratch*" 是你现在编辑界面的名字。
;; 这个编辑界面叫做一个"buffer"。
;;
;; 每当你打开Emacs时都会默认打开这个scratch buffer
;; 此时你并没有在编辑任何文件而是在编辑一个buffer
;; 之后你可以将这个buffer保存到一个文件中。
;;
;; 之后的"Lisp interaction" 则是表明我们可以用的某组命令
;;
;; Emacs在每个buffer中都有一组内置的命令
;; 而当你激活某种特定的模式时,就可以使用相应的命令
;; 这里我们使用`lisp-interaction-mode'
;; 这样我们就可以使用内置的Emacs Lisp以下简称Elisp命令了。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 分号是注释开始的标志
;;
;; Elisp 是由符号表达式构成的 (即"s-表达式"或"s式"):
(+ 2 2)
;; 这个s式的意思是 "对2进行加2操作".
;; s式周围有括号而且也可以嵌套:
(+ 2 (+ 1 1))
;; 一个s式可以包含原子符号或者其他s式
;; 在上面的例子中1和2是原子符号
;; (+ 2 (+ 1 1)) 和 (+ 1 1) 是s式.
;; 在 `lisp-interaction-mode' 中你可以计算s式.
;; 把光标移到闭括号后之后按下ctrl+j以后简写为'C-j'
(+ 3 (+ 1 2))
;; ^ 光标放到这里
;; 按下`C-j' 就会输出 6
;; `C-j' 会在buffer中插入当前运算的结果
;; 而`C-xC-e' 则会在emacs最底部显示结果也就是被称作"minibuffer"的区域
;; 为了避免把我们的buffer填满无用的结果我们以后会一直用`C-xC-e'
;; `setq' 可以将一个值赋给一个变量
(setq my-name "Bastien")
;; `C-xC-e' 输出 "Bastien" (在 mini-buffer 中显示)
;; `insert' 会在光标处插入字符串:
(insert "Hello!")
;; `C-xC-e' 输出 "Hello!"
;; 在这里我们只传给了insert一个参数"Hello!", 但是
;; 我们也可以传给它更多的参数比如2个
(insert "Hello" " world!")
;; `C-xC-e' 输出 "Hello world!"
;; 你也可以用变量名来代替字符串
(insert "Hello, I am " my-name)
;; `C-xC-e' 输出 "Hello, I am Bastien"
;; 你可以把s式嵌入函数中
(defun hello () (insert "Hello, I am " my-name))
;; `C-xC-e' 输出 hello
;; 现在执行这个函数
(hello)
;; `C-xC-e' 输出 Hello, I am Bastien
;; 函数中空括号的意思是我们不需要接受任何参数
;; 但是我们不能一直总是用my-name这个变量
;; 所以我们现在使我们的函数接受一个叫做"name"的参数
(defun hello (name) (insert "Hello " name))
;; `C-xC-e' 输出 hello
;; 现在我们调用这个函数,并且将"you"作为参数传递
(hello "you")
;; `C-xC-e' 输出 "Hello you"
;; 成功!
;; 现在我们可以休息一下
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 下面我们在新的窗口中新建一个名为 "*test*" 的buffer:
(switch-to-buffer-other-window "*test*")
;; `C-xC-e' 这时屏幕上会显示两个窗口,而光标此时位于*test* buffer内
;; 用鼠标单击上面的buffer就会使光标移回。
;; 或者你可以使用 `C-xo' 使得光标跳到另一个窗口中
;; 你可以用 `progn'命令将s式结合起来:
(progn
(switch-to-buffer-other-window "*test*")
(hello "you"))
;; `C-xC-e' 此时屏幕分为两个窗口,并且在*test* buffer中显示"Hello you"
;; 现在为了简洁我们需要在每个s式后面都使用`C-xC-e'来执行,后面就不再说明了
;; 记得可以用过鼠标或者`C-xo'回到*scratch*这个buffer。
;; 清除当前buffer也是常用操作之一
(progn
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(hello "there"))
;; 也可以回到其他的窗口中
(progn
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(hello "you")
(other-window 1))
;; 你可以用 `let' 将一个值和一个局部变量绑定:
(let ((local-name "you"))
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(hello local-name)
(other-window 1))
;; 这里我们就不需要使用 `progn' 了, 因为 `let' 也可以将很多s式组合起来。
;; 格式化字符串的方法:
(format "Hello %s!\n" "visitor")
;; %s 是字符串占位符,这里被"visitor"替代.
;; \n 是换行符。
;; 现在我们用格式化的方法再重写一下我们的函数:
(defun hello (name)
(insert (format "Hello %s!\n" name)))
(hello "you")
;; 我们再用`let'新建另一个函数:
(defun greeting (name)
(let ((your-name "Bastien"))
(insert (format "Hello %s!\n\nI am %s."
name ; the argument of the function
your-name ; the let-bound variable "Bastien"
))))
;; 之后执行:
(greeting "you")
;; 有些函数可以和用户交互:
(read-from-minibuffer "Enter your name: ")
;; 这个函数会返回在执行时用户输入的信息
;; 现在我们让`greeting'函数显示你的名字:
(defun greeting (from-name)
(let ((your-name (read-from-minibuffer "Enter your name: ")))
(insert (format "Hello!\n\nI am %s and you are %s."
from-name ; the argument of the function
your-name ; the let-bound var, entered at prompt
))))
(greeting "Bastien")
;; 我们让结果在另一个窗口中显示:
(defun greeting (from-name)
(let ((your-name (read-from-minibuffer "Enter your name: ")))
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(insert (format "Hello %s!\n\nI am %s." your-name from-name))
(other-window 1)))
;; 测试一下:
(greeting "Bastien")
;; 第二节结束,休息一下吧。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 我们将一些名字存到列表中:
(setq list-of-names '("Sarah" "Chloe" "Mathilde"))
;; 用 `car'来取得第一个名字:
(car list-of-names)
;; 用 `cdr'取得剩下的名字:
(cdr list-of-names)
;; 用 `push'把名字添加到列表的开头:
(push "Stephanie" list-of-names)
;; 注意: `car' 和 `cdr' 并不修改列表本身, 但是 `push' 却会对列表本身进行操作.
;; 这个区别是很重要的: 有些函数没有任何副作用(比如`car'
;; 但还有一些却是有的 (比如 `push').
;; 我们来对`list-of-names'列表中的每一个元素都使用hello函数:
(mapcar 'hello list-of-names)
;; 将 `greeting' 改进,使的我们能够对`list-of-names'中的所有名字执行:
(defun greeting ()
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(mapcar 'hello list-of-names)
(other-window 1))
(greeting)
;; 记得我们之前定义的 `hello' 函数吗? 这个函数接受一个参数,名字。
;; `mapcar' 调用 `hello', 并将`list-of-names'作为参数先后传给`hello'
;; 现在我们对显示的buffer中的内容进行一些更改
(defun replace-hello-by-bonjour ()
(switch-to-buffer-other-window "*test*")
(goto-char (point-min))
(while (search-forward "Hello")
(replace-match "Bonjour"))
(other-window 1))
;; (goto-char (point-min)) 将光标移到buffer的开始
;; (search-forward "Hello") 查找字符串"Hello"
;; (while x y) 当x返回某个值时执行y这个s式
;; 当x返回`nil' (空), 退出循环
(replace-hello-by-bonjour)
;; 你会看到所有在*test* buffer中出现的"Hello"字样都被换成了"Bonjour"
;; 你也会得到以下错误提示: "Search failed: Hello".
;;
;; 如果要避免这个错误, 你需要告诉 `search-forward' 这个命令是否在
;; buffer的某个地方停止查找, 并且在什么都没找到时是否应该不给出错误提示
;; (search-forward "Hello" nil t) 可以达到这个要求:
;; `nil' 参数的意思是 : 查找并不限于某个范围内
;; `t' 参数的意思是: 当什么都没找到时,不给出错误提示
;; 在下面的函数中我们用到了s式并且不给出任何错误提示:
(defun hello-to-bonjour ()
(switch-to-buffer-other-window "*test*")
(erase-buffer)
;; 为`list-of-names'中的每个名字调用hello
(mapcar 'hello list-of-names)
(goto-char (point-min))
;; 将"Hello" 替换为"Bonjour"
(while (search-forward "Hello" nil t)
(replace-match "Bonjour"))
(other-window 1))
(hello-to-bonjour)
;; 给这些名字加粗:
(defun boldify-names ()
(switch-to-buffer-other-window "*test*")
(goto-char (point-min))
(while (re-search-forward "Bonjour \\(.+\\)!" nil t)
(add-text-properties (match-beginning 1)
(match-end 1)
(list 'face 'bold)))
(other-window 1))
;; 这个函数使用了 `re-search-forward':
;; 和查找一个字符串不同,你用这个命令可以查找一个模式,即正则表达式
;; 正则表达式 "Bonjour \\(.+\\)!" 的意思是:
;; 字符串 "Bonjour ", 之后跟着
;; 一组 | \\( ... \\) 结构
;; 任意字符 | . 的含义
;; 有可能重复的 | + 的含义
;; 之后跟着 "!" 这个字符串
;; 准备好了?试试看。
(boldify-names)
;; `add-text-properties' 可以添加文字属性, 比如文字样式
;; 好的,我们成功了!
;; 如果你想对一个变量或者函数有更多的了解:
;;
;; C-h v 变量 回车
;; C-h f 函数 回车
;;
;; 阅读Emacs Lisp官方文档:
;;
;; C-h i m elisp 回车
;;
;; 在线阅读Emacs Lisp文档:
;; https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html
;; 感谢以下同学的建议和反馈:
;; - Wes Hardaker
;; - notbob
;; - Kevin Montuori
;; - Arne Babenhauserheide
;; - Alan Schmitt
;; - spacegoing
```
---
language: elisp
contributors:
- ["Bastien Guerry", "http://bzg.fr"]
translators:
- ["Chenbo Li", "http://binarythink.net"]
filename: learn-emacs-lisp-zh.el
lang: zh-cn
---
```scheme
;; 15分钟学会Emacs Lisp (v0.2a)
;;作者bzghttps://github.com/bzg
;; 译者lichenbohttp://douban.com/people/lichenbo
;;
;; 请先阅读Peter Norvig的一篇好文:
;; http://norvig.com/21-days.html
;; 译者注中文版请见http://blog.youxu.info/21-days/
;;
;; 之后安装GNU Emacs 24.3:
;;
;; Debian: apt-get install emacs (视具体发行版而定)
;; MacOSX: http://emacsformacosx.com/emacs-builds/Emacs-24.3-universal-10.6.8.dmg
;; Windows: http://ftp.gnu.org/gnu/windows/emacs/emacs-24.3-bin-i386.zip
;;
;; 更多信息可以在这里找到:
;; http://www.gnu.org/software/emacs/#Obtaining
;; 很重要的警告:
;;
;; 按照这个教程来学习并不会对你的电脑有任何损坏
;; 除非你自己在学习的过程中愤怒地把它砸了
;; 如果出现了这种情况,我不会承担任何责任
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 打开emacs
;;
;; 按'q'消除欢迎界面
;;
;; 现在请注意窗口底部的那一个灰色长条
;;
;; "*scratch*" 是你现在编辑界面的名字。
;; 这个编辑界面叫做一个"buffer"。
;;
;; 每当你打开Emacs时都会默认打开这个scratch buffer
;; 此时你并没有在编辑任何文件而是在编辑一个buffer
;; 之后你可以将这个buffer保存到一个文件中。
;;
;; 之后的"Lisp interaction" 则是表明我们可以用的某组命令
;;
;; Emacs在每个buffer中都有一组内置的命令
;; 而当你激活某种特定的模式时,就可以使用相应的命令
;; 这里我们使用`lisp-interaction-mode'
;; 这样我们就可以使用内置的Emacs Lisp以下简称Elisp命令了。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 分号是注释开始的标志
;;
;; Elisp 是由符号表达式构成的 (即"s-表达式"或"s式"):
(+ 2 2)
;; 这个s式的意思是 "对2进行加2操作".
;; s式周围有括号而且也可以嵌套:
(+ 2 (+ 1 1))
;; 一个s式可以包含原子符号或者其他s式
;; 在上面的例子中1和2是原子符号
;; (+ 2 (+ 1 1)) 和 (+ 1 1) 是s式.
;; 在 `lisp-interaction-mode' 中你可以计算s式.
;; 把光标移到闭括号后之后按下ctrl+j以后简写为'C-j'
(+ 3 (+ 1 2))
;; ^ 光标放到这里
;; 按下`C-j' 就会输出 6
;; `C-j' 会在buffer中插入当前运算的结果
;; 而`C-xC-e' 则会在emacs最底部显示结果也就是被称作"minibuffer"的区域
;; 为了避免把我们的buffer填满无用的结果我们以后会一直用`C-xC-e'
;; `setq' 可以将一个值赋给一个变量
(setq my-name "Bastien")
;; `C-xC-e' 输出 "Bastien" (在 mini-buffer 中显示)
;; `insert' 会在光标处插入字符串:
(insert "Hello!")
;; `C-xC-e' 输出 "Hello!"
;; 在这里我们只传给了insert一个参数"Hello!", 但是
;; 我们也可以传给它更多的参数比如2个
(insert "Hello" " world!")
;; `C-xC-e' 输出 "Hello world!"
;; 你也可以用变量名来代替字符串
(insert "Hello, I am " my-name)
;; `C-xC-e' 输出 "Hello, I am Bastien"
;; 你可以把s式嵌入函数中
(defun hello () (insert "Hello, I am " my-name))
;; `C-xC-e' 输出 hello
;; 现在执行这个函数
(hello)
;; `C-xC-e' 输出 Hello, I am Bastien
;; 函数中空括号的意思是我们不需要接受任何参数
;; 但是我们不能一直总是用my-name这个变量
;; 所以我们现在使我们的函数接受一个叫做"name"的参数
(defun hello (name) (insert "Hello " name))
;; `C-xC-e' 输出 hello
;; 现在我们调用这个函数,并且将"you"作为参数传递
(hello "you")
;; `C-xC-e' 输出 "Hello you"
;; 成功!
;; 现在我们可以休息一下
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 下面我们在新的窗口中新建一个名为 "*test*" 的buffer:
(switch-to-buffer-other-window "*test*")
;; `C-xC-e' 这时屏幕上会显示两个窗口,而光标此时位于*test* buffer内
;; 用鼠标单击上面的buffer就会使光标移回。
;; 或者你可以使用 `C-xo' 使得光标跳到另一个窗口中
;; 你可以用 `progn'命令将s式结合起来:
(progn
(switch-to-buffer-other-window "*test*")
(hello "you"))
;; `C-xC-e' 此时屏幕分为两个窗口,并且在*test* buffer中显示"Hello you"
;; 现在为了简洁我们需要在每个s式后面都使用`C-xC-e'来执行,后面就不再说明了
;; 记得可以用过鼠标或者`C-xo'回到*scratch*这个buffer。
;; 清除当前buffer也是常用操作之一
(progn
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(hello "there"))
;; 也可以回到其他的窗口中
(progn
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(hello "you")
(other-window 1))
;; 你可以用 `let' 将一个值和一个局部变量绑定:
(let ((local-name "you"))
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(hello local-name)
(other-window 1))
;; 这里我们就不需要使用 `progn' 了, 因为 `let' 也可以将很多s式组合起来。
;; 格式化字符串的方法:
(format "Hello %s!\n" "visitor")
;; %s 是字符串占位符,这里被"visitor"替代.
;; \n 是换行符。
;; 现在我们用格式化的方法再重写一下我们的函数:
(defun hello (name)
(insert (format "Hello %s!\n" name)))
(hello "you")
;; 我们再用`let'新建另一个函数:
(defun greeting (name)
(let ((your-name "Bastien"))
(insert (format "Hello %s!\n\nI am %s."
name ; the argument of the function
your-name ; the let-bound variable "Bastien"
))))
;; 之后执行:
(greeting "you")
;; 有些函数可以和用户交互:
(read-from-minibuffer "Enter your name: ")
;; 这个函数会返回在执行时用户输入的信息
;; 现在我们让`greeting'函数显示你的名字:
(defun greeting (from-name)
(let ((your-name (read-from-minibuffer "Enter your name: ")))
(insert (format "Hello!\n\nI am %s and you are %s."
from-name ; the argument of the function
your-name ; the let-bound var, entered at prompt
))))
(greeting "Bastien")
;; 我们让结果在另一个窗口中显示:
(defun greeting (from-name)
(let ((your-name (read-from-minibuffer "Enter your name: ")))
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(insert (format "Hello %s!\n\nI am %s." your-name from-name))
(other-window 1)))
;; 测试一下:
(greeting "Bastien")
;; 第二节结束,休息一下吧。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 我们将一些名字存到列表中:
(setq list-of-names '("Sarah" "Chloe" "Mathilde"))
;; 用 `car'来取得第一个名字:
(car list-of-names)
;; 用 `cdr'取得剩下的名字:
(cdr list-of-names)
;; 用 `push'把名字添加到列表的开头:
(push "Stephanie" list-of-names)
;; 注意: `car' 和 `cdr' 并不修改列表本身, 但是 `push' 却会对列表本身进行操作.
;; 这个区别是很重要的: 有些函数没有任何副作用(比如`car'
;; 但还有一些却是有的 (比如 `push').
;; 我们来对`list-of-names'列表中的每一个元素都使用hello函数:
(mapcar 'hello list-of-names)
;; 将 `greeting' 改进,使的我们能够对`list-of-names'中的所有名字执行:
(defun greeting ()
(switch-to-buffer-other-window "*test*")
(erase-buffer)
(mapcar 'hello list-of-names)
(other-window 1))
(greeting)
;; 记得我们之前定义的 `hello' 函数吗? 这个函数接受一个参数,名字。
;; `mapcar' 调用 `hello', 并将`list-of-names'作为参数先后传给`hello'
;; 现在我们对显示的buffer中的内容进行一些更改
(defun replace-hello-by-bonjour ()
(switch-to-buffer-other-window "*test*")
(goto-char (point-min))
(while (search-forward "Hello")
(replace-match "Bonjour"))
(other-window 1))
;; (goto-char (point-min)) 将光标移到buffer的开始
;; (search-forward "Hello") 查找字符串"Hello"
;; (while x y) 当x返回某个值时执行y这个s式
;; 当x返回`nil' (空), 退出循环
(replace-hello-by-bonjour)
;; 你会看到所有在*test* buffer中出现的"Hello"字样都被换成了"Bonjour"
;; 你也会得到以下错误提示: "Search failed: Hello".
;;
;; 如果要避免这个错误, 你需要告诉 `search-forward' 这个命令是否在
;; buffer的某个地方停止查找, 并且在什么都没找到时是否应该不给出错误提示
;; (search-forward "Hello" nil t) 可以达到这个要求:
;; `nil' 参数的意思是 : 查找并不限于某个范围内
;; `t' 参数的意思是: 当什么都没找到时,不给出错误提示
;; 在下面的函数中我们用到了s式并且不给出任何错误提示:
(defun hello-to-bonjour ()
(switch-to-buffer-other-window "*test*")
(erase-buffer)
;; 为`list-of-names'中的每个名字调用hello
(mapcar 'hello list-of-names)
(goto-char (point-min))
;; 将"Hello" 替换为"Bonjour"
(while (search-forward "Hello" nil t)
(replace-match "Bonjour"))
(other-window 1))
(hello-to-bonjour)
;; 给这些名字加粗:
(defun boldify-names ()
(switch-to-buffer-other-window "*test*")
(goto-char (point-min))
(while (re-search-forward "Bonjour \\(.+\\)!" nil t)
(add-text-properties (match-beginning 1)
(match-end 1)
(list 'face 'bold)))
(other-window 1))
;; 这个函数使用了 `re-search-forward':
;; 和查找一个字符串不同,你用这个命令可以查找一个模式,即正则表达式
;; 正则表达式 "Bonjour \\(.+\\)!" 的意思是:
;; 字符串 "Bonjour ", 之后跟着
;; 一组 | \\( ... \\) 结构
;; 任意字符 | . 的含义
;; 有可能重复的 | + 的含义
;; 之后跟着 "!" 这个字符串
;; 准备好了?试试看。
(boldify-names)
;; `add-text-properties' 可以添加文字属性, 比如文字样式
;; 好的,我们成功了!
;; 如果你想对一个变量或者函数有更多的了解:
;;
;; C-h v 变量 回车
;; C-h f 函数 回车
;;
;; 阅读Emacs Lisp官方文档:
;;
;; C-h i m elisp 回车
;;
;; 在线阅读Emacs Lisp文档:
;; https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html
;; 感谢以下同学的建议和反馈:
;; - Wes Hardaker
;; - notbob
;; - Kevin Montuori
;; - Arne Babenhauserheide
;; - Alan Schmitt
;; - spacegoing
```

File diff suppressed because it is too large Load Diff