mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2025-08-06 14:56:54 +02:00
Convert \r\n to \n
This commit is contained in:
@@ -1,212 +1,212 @@
|
|||||||
---
|
---
|
||||||
category: tool
|
category: tool
|
||||||
tool: amd
|
tool: amd
|
||||||
contributors:
|
contributors:
|
||||||
- ["Frederik Ring", "https://github.com/m90"]
|
- ["Frederik Ring", "https://github.com/m90"]
|
||||||
filename: learnamd.js
|
filename: learnamd.js
|
||||||
---
|
---
|
||||||
|
|
||||||
## Getting Started with AMD
|
## Getting Started with AMD
|
||||||
|
|
||||||
The **Asynchronous Module Definition** API specifies a mechanism for defining
|
The **Asynchronous Module Definition** API specifies a mechanism for defining
|
||||||
JavaScript modules such that the module and its dependencies can be asynchronously
|
JavaScript modules such that the module and its dependencies can be asynchronously
|
||||||
loaded. This is particularly well suited for the browser environment where
|
loaded. This is particularly well suited for the browser environment where
|
||||||
synchronous loading of modules incurs performance, usability, debugging, and
|
synchronous loading of modules incurs performance, usability, debugging, and
|
||||||
cross-domain access problems.
|
cross-domain access problems.
|
||||||
|
|
||||||
### Basic concept
|
### Basic concept
|
||||||
```javascript
|
```javascript
|
||||||
// The basic AMD API consists of nothing but two methods: `define` and `require`
|
// The basic AMD API consists of nothing but two methods: `define` and `require`
|
||||||
// and is all about module definition and consumption:
|
// and is all about module definition and consumption:
|
||||||
// `define(id?, dependencies?, factory)` defines a module
|
// `define(id?, dependencies?, factory)` defines a module
|
||||||
// `require(dependencies, callback)` imports a set of dependencies and
|
// `require(dependencies, callback)` imports a set of dependencies and
|
||||||
// consumes them in the passed callback
|
// consumes them in the passed callback
|
||||||
|
|
||||||
// Let's start by using define to define a new named module
|
// Let's start by using define to define a new named module
|
||||||
// that has no dependencies. We'll do so by passing a name
|
// that has no dependencies. We'll do so by passing a name
|
||||||
// and a factory function to define:
|
// and a factory function to define:
|
||||||
define('awesomeAMD', function(){
|
define('awesomeAMD', function(){
|
||||||
var isAMDAwesome = function(){
|
var isAMDAwesome = function(){
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
// The return value of a module's factory function is
|
// The return value of a module's factory function is
|
||||||
// what other modules or require calls will receive when
|
// what other modules or require calls will receive when
|
||||||
// requiring our `awesomeAMD` module.
|
// requiring our `awesomeAMD` module.
|
||||||
// The exported value can be anything, (constructor) functions,
|
// The exported value can be anything, (constructor) functions,
|
||||||
// objects, primitives, even undefined (although that won't help too much).
|
// objects, primitives, even undefined (although that won't help too much).
|
||||||
return isAMDAwesome;
|
return isAMDAwesome;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Now, let's define another module that depends upon our `awesomeAMD` module.
|
// Now, let's define another module that depends upon our `awesomeAMD` module.
|
||||||
// Notice that there's an additional argument defining our
|
// Notice that there's an additional argument defining our
|
||||||
// module's dependencies now:
|
// module's dependencies now:
|
||||||
define('loudmouth', ['awesomeAMD'], function(awesomeAMD){
|
define('loudmouth', ['awesomeAMD'], function(awesomeAMD){
|
||||||
// dependencies will be passed to the factory's arguments
|
// dependencies will be passed to the factory's arguments
|
||||||
// in the order they are specified
|
// in the order they are specified
|
||||||
var tellEveryone = function(){
|
var tellEveryone = function(){
|
||||||
if (awesomeAMD()){
|
if (awesomeAMD()){
|
||||||
alert('This is sOoOo rad!');
|
alert('This is sOoOo rad!');
|
||||||
} else {
|
} else {
|
||||||
alert('Pretty dull, isn\'t it?');
|
alert('Pretty dull, isn\'t it?');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return tellEveryone;
|
return tellEveryone;
|
||||||
});
|
});
|
||||||
|
|
||||||
// As we do know how to use define now, let's use `require` to
|
// As we do know how to use define now, let's use `require` to
|
||||||
// kick off our program. `require`'s signature is `(arrayOfDependencies, callback)`.
|
// kick off our program. `require`'s signature is `(arrayOfDependencies, callback)`.
|
||||||
require(['loudmouth'], function(loudmouth){
|
require(['loudmouth'], function(loudmouth){
|
||||||
loudmouth();
|
loudmouth();
|
||||||
});
|
});
|
||||||
|
|
||||||
// To make this tutorial run code, let's implement a very basic
|
// To make this tutorial run code, let's implement a very basic
|
||||||
// (non-asynchronous) version of AMD right here on the spot:
|
// (non-asynchronous) version of AMD right here on the spot:
|
||||||
function define(name, deps, factory){
|
function define(name, deps, factory){
|
||||||
// notice how modules without dependencies are handled
|
// notice how modules without dependencies are handled
|
||||||
define[name] = require(factory ? deps : [], factory || deps);
|
define[name] = require(factory ? deps : [], factory || deps);
|
||||||
}
|
}
|
||||||
|
|
||||||
function require(deps, callback){
|
function require(deps, callback){
|
||||||
var args = [];
|
var args = [];
|
||||||
// first let's retrieve all the dependencies needed
|
// first let's retrieve all the dependencies needed
|
||||||
// by the require call
|
// by the require call
|
||||||
for (var i = 0; i < deps.length; i++){
|
for (var i = 0; i < deps.length; i++){
|
||||||
args[i] = define[deps[i]];
|
args[i] = define[deps[i]];
|
||||||
}
|
}
|
||||||
// satisfy all the callback's dependencies
|
// satisfy all the callback's dependencies
|
||||||
return callback.apply(null, args);
|
return callback.apply(null, args);
|
||||||
}
|
}
|
||||||
// you can see this code in action here: http://jsfiddle.net/qap949pd/
|
// you can see this code in action here: http://jsfiddle.net/qap949pd/
|
||||||
```
|
```
|
||||||
|
|
||||||
### Real-world usage with require.js
|
### 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:
|
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
|
```javascript
|
||||||
/* file: app/main.js */
|
/* file: app/main.js */
|
||||||
require(['modules/someClass'], function(SomeClass){
|
require(['modules/someClass'], function(SomeClass){
|
||||||
// the callback is deferred until the dependency is loaded
|
// the callback is deferred until the dependency is loaded
|
||||||
var thing = new SomeClass();
|
var thing = new SomeClass();
|
||||||
});
|
});
|
||||||
console.log('So here we are, waiting!'); // this will run first
|
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`:
|
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/
|
* app/
|
||||||
* main.js
|
* main.js
|
||||||
* modules/
|
* modules/
|
||||||
* someClass.js
|
* someClass.js
|
||||||
* someHelpers.js
|
* someHelpers.js
|
||||||
* ...
|
* ...
|
||||||
* daos/
|
* daos/
|
||||||
* things.js
|
* things.js
|
||||||
* ...
|
* ...
|
||||||
|
|
||||||
This means we can define `someClass` without specifying a module id:
|
This means we can define `someClass` without specifying a module id:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
/* file: app/modules/someClass.js */
|
/* file: app/modules/someClass.js */
|
||||||
define(['daos/things', 'modules/someHelpers'], function(thingsDao, helpers){
|
define(['daos/things', 'modules/someHelpers'], function(thingsDao, helpers){
|
||||||
// module definition, of course, will also happen asynchronously
|
// module definition, of course, will also happen asynchronously
|
||||||
function SomeClass(){
|
function SomeClass(){
|
||||||
this.method = function(){/**/};
|
this.method = function(){/**/};
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
return SomeClass;
|
return SomeClass;
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
To alter the default path mapping behavior use `requirejs.config(configObj)` in your `main.js`:
|
To alter the default path mapping behavior use `requirejs.config(configObj)` in your `main.js`:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
/* file: main.js */
|
/* file: main.js */
|
||||||
requirejs.config({
|
requirejs.config({
|
||||||
baseUrl : 'app',
|
baseUrl : 'app',
|
||||||
paths : {
|
paths : {
|
||||||
// you can also load modules from other locations
|
// you can also load modules from other locations
|
||||||
jquery : '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min',
|
jquery : '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min',
|
||||||
coolLibFromBower : '../bower_components/cool-lib/coollib'
|
coolLibFromBower : '../bower_components/cool-lib/coollib'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
require(['jquery', 'coolLibFromBower', 'modules/someHelpers'], function($, coolLib, helpers){
|
require(['jquery', 'coolLibFromBower', 'modules/someHelpers'], function($, coolLib, helpers){
|
||||||
// a `main` file needs to call require at least once,
|
// a `main` file needs to call require at least once,
|
||||||
// otherwise no code will ever run
|
// otherwise no code will ever run
|
||||||
coolLib.doFancyStuffWith(helpers.transform($('#foo')));
|
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:
|
`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
|
```html
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>A hundred script tags? Never again!</title>
|
<title>A hundred script tags? Never again!</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script src="require.js" data-main="app/main"></script>
|
<script src="require.js" data-main="app/main"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Optimizing a whole project using r.js
|
### 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.
|
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.
|
`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`:
|
Install it using `npm`:
|
||||||
```shell
|
```shell
|
||||||
$ npm install requirejs -g
|
$ npm install requirejs -g
|
||||||
```
|
```
|
||||||
|
|
||||||
Now you can feed it with a configuration file:
|
Now you can feed it with a configuration file:
|
||||||
```shell
|
```shell
|
||||||
$ r.js -o app.build.js
|
$ r.js -o app.build.js
|
||||||
```
|
```
|
||||||
|
|
||||||
For our above example the configuration might look like:
|
For our above example the configuration might look like:
|
||||||
```javascript
|
```javascript
|
||||||
/* file : app.build.js */
|
/* file : app.build.js */
|
||||||
({
|
({
|
||||||
name : 'main', // name of the entry point
|
name : 'main', // name of the entry point
|
||||||
out : 'main-built.js', // name of the file to write the output to
|
out : 'main-built.js', // name of the file to write the output to
|
||||||
baseUrl : 'app',
|
baseUrl : 'app',
|
||||||
paths : {
|
paths : {
|
||||||
// `empty:` tells r.js that this should still be loaded from the CDN, using
|
// `empty:` tells r.js that this should still be loaded from the CDN, using
|
||||||
// the location specified in `main.js`
|
// the location specified in `main.js`
|
||||||
jquery : 'empty:',
|
jquery : 'empty:',
|
||||||
coolLibFromBower : '../bower_components/cool-lib/coollib'
|
coolLibFromBower : '../bower_components/cool-lib/coollib'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
To use the built file in production, simply swap `data-main`:
|
To use the built file in production, simply swap `data-main`:
|
||||||
```html
|
```html
|
||||||
<script src="require.js" data-main="app/main-built"></script>
|
<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.
|
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
|
### Topics not covered in this tutorial
|
||||||
* [Loader plugins / transforms](http://requirejs.org/docs/plugins.html)
|
* [Loader plugins / transforms](http://requirejs.org/docs/plugins.html)
|
||||||
* [CommonJS style loading and exporting](http://requirejs.org/docs/commonjs.html)
|
* [CommonJS style loading and exporting](http://requirejs.org/docs/commonjs.html)
|
||||||
* [Advanced configuration](http://requirejs.org/docs/api.html#config)
|
* [Advanced configuration](http://requirejs.org/docs/api.html#config)
|
||||||
* [Shim configuration (loading non-AMD modules)](http://requirejs.org/docs/api.html#config-shim)
|
* [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)
|
* [CSS loading and optimizing with require.js](http://requirejs.org/docs/optimization.html#onecss)
|
||||||
* [Using almond.js for builds](https://github.com/jrburke/almond)
|
* [Using almond.js for builds](https://github.com/jrburke/almond)
|
||||||
|
|
||||||
### Further reading:
|
### Further reading:
|
||||||
|
|
||||||
* [Official Spec](https://github.com/amdjs/amdjs-api/wiki/AMD)
|
* [Official Spec](https://github.com/amdjs/amdjs-api/wiki/AMD)
|
||||||
* [Why AMD?](http://requirejs.org/docs/whyamd.html)
|
* [Why AMD?](http://requirejs.org/docs/whyamd.html)
|
||||||
* [Universal Module Definition](https://github.com/umdjs/umd)
|
* [Universal Module Definition](https://github.com/umdjs/umd)
|
||||||
|
|
||||||
### Implementations:
|
### Implementations:
|
||||||
|
|
||||||
* [require.js](http://requirejs.org)
|
* [require.js](http://requirejs.org)
|
||||||
* [dojo toolkit](http://dojotoolkit.org/documentation/tutorials/1.9/modules/)
|
* [dojo toolkit](http://dojotoolkit.org/documentation/tutorials/1.9/modules/)
|
||||||
* [cujo.js](http://cujojs.com/)
|
* [cujo.js](http://cujojs.com/)
|
||||||
* [curl.js](https://github.com/cujojs/curl)
|
* [curl.js](https://github.com/cujojs/curl)
|
||||||
* [lsjs](https://github.com/zazl/lsjs)
|
* [lsjs](https://github.com/zazl/lsjs)
|
||||||
* [mmd](https://github.com/alexlawrence/mmd)
|
* [mmd](https://github.com/alexlawrence/mmd)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,423 +1,423 @@
|
|||||||
---
|
---
|
||||||
language: Elixir
|
language: Elixir
|
||||||
contributors:
|
contributors:
|
||||||
- ["Joao Marques", "http://github.com/mrshankly"]
|
- ["Joao Marques", "http://github.com/mrshankly"]
|
||||||
translators:
|
translators:
|
||||||
- ["Gregor Große-Bölting", "http://www.ideen-und-soehne.de"]
|
- ["Gregor Große-Bölting", "http://www.ideen-und-soehne.de"]
|
||||||
filename: learnelixir-de.ex
|
filename: learnelixir-de.ex
|
||||||
lang: de-de
|
lang: de-de
|
||||||
---
|
---
|
||||||
|
|
||||||
Elixir ist eine moderne, funktionale Sprache für die Erlang VM. Sie ist voll
|
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
|
kompatibel mit Erlang, verfügt aber über eine freundlichere Syntax und bringt
|
||||||
viele Features mit.
|
viele Features mit.
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
|
|
||||||
# Einzeilige Kommentare werden mit der Raute gesetzt.
|
# Einzeilige Kommentare werden mit der Raute gesetzt.
|
||||||
|
|
||||||
# Es gibt keine mehrzeiligen Kommentare;
|
# Es gibt keine mehrzeiligen Kommentare;
|
||||||
# es ist aber problemlos möglich mehrere einzeilige Kommentare hintereinander
|
# es ist aber problemlos möglich mehrere einzeilige Kommentare hintereinander
|
||||||
# zu setzen (so wie hier).
|
# zu setzen (so wie hier).
|
||||||
|
|
||||||
# Mit 'iex' ruft man die Elixir-Shell auf.
|
# Mit 'iex' ruft man die Elixir-Shell auf.
|
||||||
# Zum kompilieren von Modulen dient der Befehl 'elixirc'.
|
# Zum kompilieren von Modulen dient der Befehl 'elixirc'.
|
||||||
|
|
||||||
# Beide Befehle sollten als Umgebungsvariable gesetzt sein, wenn Elixir korrekt
|
# Beide Befehle sollten als Umgebungsvariable gesetzt sein, wenn Elixir korrekt
|
||||||
# installiert wurde.
|
# installiert wurde.
|
||||||
|
|
||||||
## ---------------------------
|
## ---------------------------
|
||||||
## -- Basistypen
|
## -- Basistypen
|
||||||
## ---------------------------
|
## ---------------------------
|
||||||
|
|
||||||
# Es gibt Nummern:
|
# Es gibt Nummern:
|
||||||
3 # Integer
|
3 # Integer
|
||||||
0x1F # Integer
|
0x1F # Integer
|
||||||
3.0 # Float
|
3.0 # Float
|
||||||
|
|
||||||
# Für bessere Lesbarkeit des Codes können Unterstriche "_" als Trennzeichen verwendet werden
|
# Für bessere Lesbarkeit des Codes können Unterstriche "_" als Trennzeichen verwendet werden
|
||||||
1_000_000 == 1000000 # Integer
|
1_000_000 == 1000000 # Integer
|
||||||
1_000.567 == 1000.567 # Float
|
1_000.567 == 1000.567 # Float
|
||||||
|
|
||||||
# Atome, das sind Literale, sind Konstanten mit Namen. Sie starten mit einem
|
# Atome, das sind Literale, sind Konstanten mit Namen. Sie starten mit einem
|
||||||
# ':'.
|
# ':'.
|
||||||
:hello # Atom
|
:hello # Atom
|
||||||
|
|
||||||
# Außerdem gibt es Tupel, deren Werte im Arbeitsspeicher vorgehalten werden.
|
# Außerdem gibt es Tupel, deren Werte im Arbeitsspeicher vorgehalten werden.
|
||||||
{1,2,3} # Tupel
|
{1,2,3} # Tupel
|
||||||
|
|
||||||
# Die Werte innerhalb eines Tupels können mit der 'elem'-Funktion ausgelesen
|
# Die Werte innerhalb eines Tupels können mit der 'elem'-Funktion ausgelesen
|
||||||
# werden:
|
# werden:
|
||||||
elem({1, 2, 3}, 0) # => 1
|
elem({1, 2, 3}, 0) # => 1
|
||||||
|
|
||||||
# Listen sind als verkettete Listen implementiert.
|
# Listen sind als verkettete Listen implementiert.
|
||||||
[1, 2, 3] # list
|
[1, 2, 3] # list
|
||||||
|
|
||||||
# Auf Kopf und Rest einer Liste kann wie folgt zugegriffen werden:
|
# Auf Kopf und Rest einer Liste kann wie folgt zugegriffen werden:
|
||||||
[ kopf | rest ] = [1,2,3]
|
[ kopf | rest ] = [1,2,3]
|
||||||
kopf # => 1
|
kopf # => 1
|
||||||
rest # => [2, 3]
|
rest # => [2, 3]
|
||||||
|
|
||||||
# In Elixir, wie auch in Erlang, kennzeichnet '=' ein 'pattern matching'
|
# In Elixir, wie auch in Erlang, kennzeichnet '=' ein 'pattern matching'
|
||||||
# (Musterabgleich) und keine Zuweisung.
|
# (Musterabgleich) und keine Zuweisung.
|
||||||
# Das heißt, dass die linke Seite auf die rechte Seite 'abgeglichen' wird.
|
# 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
|
# Auf diese Weise kann im Beispiel oben auf Kopf und Rest der Liste zugegriffen
|
||||||
# werden.
|
# werden.
|
||||||
|
|
||||||
# Ein Musterabgleich wird einen Fehler werfen, wenn die beiden Seiten nicht
|
# Ein Musterabgleich wird einen Fehler werfen, wenn die beiden Seiten nicht
|
||||||
# zusammenpassen.
|
# zusammenpassen.
|
||||||
# Im folgenden Beispiel haben die Tupel eine unterschiedliche Anzahl an
|
# Im folgenden Beispiel haben die Tupel eine unterschiedliche Anzahl an
|
||||||
# Elementen:
|
# Elementen:
|
||||||
{a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2}
|
{a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2}
|
||||||
|
|
||||||
# Es gibt außerdem 'binaries',
|
# Es gibt außerdem 'binaries',
|
||||||
<<1,2,3>> # binary.
|
<<1,2,3>> # binary.
|
||||||
|
|
||||||
# Strings und 'char lists'
|
# Strings und 'char lists'
|
||||||
"hello" # String
|
"hello" # String
|
||||||
'hello' # Char-Liste
|
'hello' # Char-Liste
|
||||||
|
|
||||||
# ... und mehrzeilige Strings
|
# ... und mehrzeilige Strings
|
||||||
"""
|
"""
|
||||||
Ich bin ein
|
Ich bin ein
|
||||||
mehrzeiliger String.
|
mehrzeiliger String.
|
||||||
"""
|
"""
|
||||||
#=> "Ich bin ein\nmehrzeiliger String.\n"
|
#=> "Ich bin ein\nmehrzeiliger String.\n"
|
||||||
|
|
||||||
# Alles Strings werden in UTF-8 enkodiert:
|
# Alles Strings werden in UTF-8 enkodiert:
|
||||||
"héllò" #=> "héllò"
|
"héllò" #=> "héllò"
|
||||||
|
|
||||||
# Eigentlich sind Strings in Wahrheit nur binaries und 'char lists' einfach
|
# Eigentlich sind Strings in Wahrheit nur binaries und 'char lists' einfach
|
||||||
# Listen.
|
# Listen.
|
||||||
<<?a, ?b, ?c>> #=> "abc"
|
<<?a, ?b, ?c>> #=> "abc"
|
||||||
[?a, ?b, ?c] #=> 'abc'
|
[?a, ?b, ?c] #=> 'abc'
|
||||||
|
|
||||||
# In Elixir gibt `?a` den ASCII-Integer für den Buchstaben zurück.
|
# In Elixir gibt `?a` den ASCII-Integer für den Buchstaben zurück.
|
||||||
?a #=> 97
|
?a #=> 97
|
||||||
|
|
||||||
# Um Listen zu verbinden gibt es den Operator '++', für binaries nutzt man '<>'
|
# Um Listen zu verbinden gibt es den Operator '++', für binaries nutzt man '<>'
|
||||||
[1,2,3] ++ [4,5] #=> [1,2,3,4,5]
|
[1,2,3] ++ [4,5] #=> [1,2,3,4,5]
|
||||||
'hello ' ++ 'world' #=> 'hello world'
|
'hello ' ++ 'world' #=> 'hello world'
|
||||||
|
|
||||||
<<1,2,3>> <> <<4,5>> #=> <<1,2,3,4,5>>
|
<<1,2,3>> <> <<4,5>> #=> <<1,2,3,4,5>>
|
||||||
"hello " <> "world" #=> "hello world"
|
"hello " <> "world" #=> "hello world"
|
||||||
|
|
||||||
## ---------------------------
|
## ---------------------------
|
||||||
## -- Operatoren
|
## -- Operatoren
|
||||||
## ---------------------------
|
## ---------------------------
|
||||||
|
|
||||||
# Einfache Arithmetik
|
# Einfache Arithmetik
|
||||||
1 + 1 #=> 2
|
1 + 1 #=> 2
|
||||||
10 - 5 #=> 5
|
10 - 5 #=> 5
|
||||||
5 * 2 #=> 10
|
5 * 2 #=> 10
|
||||||
10 / 2 #=> 5.0
|
10 / 2 #=> 5.0
|
||||||
|
|
||||||
# In Elixir gibt der Operator '/' immer einen Float-Wert zurück.
|
# In Elixir gibt der Operator '/' immer einen Float-Wert zurück.
|
||||||
|
|
||||||
# Für Division mit ganzzahligen Ergebnis gibt es 'div'
|
# Für Division mit ganzzahligen Ergebnis gibt es 'div'
|
||||||
div(10, 2) #=> 5
|
div(10, 2) #=> 5
|
||||||
|
|
||||||
# Um den Rest der ganzzahligen Division zu erhalten gibt es 'rem'
|
# Um den Rest der ganzzahligen Division zu erhalten gibt es 'rem'
|
||||||
rem(10, 3) #=> 1
|
rem(10, 3) #=> 1
|
||||||
|
|
||||||
# Natürlich gibt es auch Operatoren für Booleans: 'or', 'and' und 'not'. Diese
|
# Natürlich gibt es auch Operatoren für Booleans: 'or', 'and' und 'not'. Diese
|
||||||
# Operatoren erwarten einen Boolean als erstes Argument.
|
# Operatoren erwarten einen Boolean als erstes Argument.
|
||||||
true and true #=> true
|
true and true #=> true
|
||||||
false or true #=> true
|
false or true #=> true
|
||||||
# 1 and true #=> ** (ArgumentError) argument error
|
# 1 and true #=> ** (ArgumentError) argument error
|
||||||
|
|
||||||
# Elixir bietet auch '||', '&&' und '!', die Argumente jedweden Typs
|
# Elixir bietet auch '||', '&&' und '!', die Argumente jedweden Typs
|
||||||
# akzeptieren. Alle Werte außer 'false' und 'nil' werden zu wahr evaluiert.
|
# akzeptieren. Alle Werte außer 'false' und 'nil' werden zu wahr evaluiert.
|
||||||
1 || true #=> 1
|
1 || true #=> 1
|
||||||
false && 1 #=> false
|
false && 1 #=> false
|
||||||
nil && 20 #=> nil
|
nil && 20 #=> nil
|
||||||
|
|
||||||
!true #=> false
|
!true #=> false
|
||||||
|
|
||||||
# Für Vergleiche gibt es die Operatoren `==`, `!=`, `===`, `!==`, `<=`, `>=`,
|
# Für Vergleiche gibt es die Operatoren `==`, `!=`, `===`, `!==`, `<=`, `>=`,
|
||||||
# `<` und `>`
|
# `<` und `>`
|
||||||
1 == 1 #=> true
|
1 == 1 #=> true
|
||||||
1 != 1 #=> false
|
1 != 1 #=> false
|
||||||
1 < 2 #=> true
|
1 < 2 #=> true
|
||||||
|
|
||||||
# '===' und '!==' sind strikter beim Vergleich von Integern und Floats:
|
# '===' und '!==' sind strikter beim Vergleich von Integern und Floats:
|
||||||
1 == 1.0 #=> true
|
1 == 1.0 #=> true
|
||||||
1 === 1.0 #=> false
|
1 === 1.0 #=> false
|
||||||
|
|
||||||
# Es ist außerdem möglich zwei verschiedene Datentypen zu vergleichen:
|
# Es ist außerdem möglich zwei verschiedene Datentypen zu vergleichen:
|
||||||
1 < :hello #=> true
|
1 < :hello #=> true
|
||||||
|
|
||||||
# Die gesamte Ordnung über die Datentypen ist wie folgt definiert:
|
# Die gesamte Ordnung über die Datentypen ist wie folgt definiert:
|
||||||
# number < atom < reference < functions < port < pid < tuple < list < bitstring
|
# number < atom < reference < functions < port < pid < tuple < list < bitstring
|
||||||
|
|
||||||
# Um Joe Armstrong zu zitieren: "The actual order is not important, but that a
|
# Um Joe Armstrong zu zitieren: "The actual order is not important, but that a
|
||||||
# total ordering is well defined is important."
|
# total ordering is well defined is important."
|
||||||
|
|
||||||
## ---------------------------
|
## ---------------------------
|
||||||
## -- Kontrollstrukturen
|
## -- Kontrollstrukturen
|
||||||
## ---------------------------
|
## ---------------------------
|
||||||
|
|
||||||
# Es gibt die `if`-Verzweigung
|
# Es gibt die `if`-Verzweigung
|
||||||
if false do
|
if false do
|
||||||
"Dies wird nie jemand sehen..."
|
"Dies wird nie jemand sehen..."
|
||||||
else
|
else
|
||||||
"...aber dies!"
|
"...aber dies!"
|
||||||
end
|
end
|
||||||
|
|
||||||
# ...und ebenso `unless`
|
# ...und ebenso `unless`
|
||||||
unless true do
|
unless true do
|
||||||
"Dies wird nie jemand sehen..."
|
"Dies wird nie jemand sehen..."
|
||||||
else
|
else
|
||||||
"...aber dies!"
|
"...aber dies!"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Du erinnerst dich an 'pattern matching'? Viele Kontrollstrukturen in Elixir
|
# Du erinnerst dich an 'pattern matching'? Viele Kontrollstrukturen in Elixir
|
||||||
# arbeiten damit.
|
# arbeiten damit.
|
||||||
|
|
||||||
# 'case' erlaubt es uns Werte mit vielerlei Mustern zu vergleichen.
|
# 'case' erlaubt es uns Werte mit vielerlei Mustern zu vergleichen.
|
||||||
case {:one, :two} do
|
case {:one, :two} do
|
||||||
{:four, :five} ->
|
{:four, :five} ->
|
||||||
"Das wird nicht passen"
|
"Das wird nicht passen"
|
||||||
{:one, x} ->
|
{:one, x} ->
|
||||||
"Das schon und außerdem wird es ':two' dem Wert 'x' zuweisen."
|
"Das schon und außerdem wird es ':two' dem Wert 'x' zuweisen."
|
||||||
_ ->
|
_ ->
|
||||||
"Dieser Fall greift immer."
|
"Dieser Fall greift immer."
|
||||||
end
|
end
|
||||||
|
|
||||||
# Es ist eine übliche Praxis '_' einen Wert zuzuweisen, sofern dieser Wert
|
# Es ist eine übliche Praxis '_' einen Wert zuzuweisen, sofern dieser Wert
|
||||||
# nicht weiter verwendet wird.
|
# nicht weiter verwendet wird.
|
||||||
# Wenn wir uns zum Beispiel nur für den Kopf einer Liste interessieren:
|
# Wenn wir uns zum Beispiel nur für den Kopf einer Liste interessieren:
|
||||||
[kopf | _] = [1,2,3]
|
[kopf | _] = [1,2,3]
|
||||||
kopf #=> 1
|
kopf #=> 1
|
||||||
|
|
||||||
# Für bessere Lesbarkeit können wir auch das Folgende machen:
|
# Für bessere Lesbarkeit können wir auch das Folgende machen:
|
||||||
[kopf | _rest] = [:a, :b, :c]
|
[kopf | _rest] = [:a, :b, :c]
|
||||||
kopf #=> :a
|
kopf #=> :a
|
||||||
|
|
||||||
# Mit 'cond' können diverse Bedingungen zur selben Zeit überprüft werden. Man
|
# Mit 'cond' können diverse Bedingungen zur selben Zeit überprüft werden. Man
|
||||||
# benutzt 'cond' statt viele if-Verzweigungen zu verschachteln.
|
# benutzt 'cond' statt viele if-Verzweigungen zu verschachteln.
|
||||||
cond do
|
cond do
|
||||||
1 + 1 == 3 ->
|
1 + 1 == 3 ->
|
||||||
"Ich werde nie aufgerufen."
|
"Ich werde nie aufgerufen."
|
||||||
2 * 5 == 12 ->
|
2 * 5 == 12 ->
|
||||||
"Ich auch nicht."
|
"Ich auch nicht."
|
||||||
1 + 2 == 3 ->
|
1 + 2 == 3 ->
|
||||||
"Aber ich!"
|
"Aber ich!"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Es ist üblich eine letzte Bedingung einzufügen, die immer zu wahr evaluiert.
|
# Es ist üblich eine letzte Bedingung einzufügen, die immer zu wahr evaluiert.
|
||||||
cond do
|
cond do
|
||||||
1 + 1 == 3 ->
|
1 + 1 == 3 ->
|
||||||
"Ich werde nie aufgerufen."
|
"Ich werde nie aufgerufen."
|
||||||
2 * 5 == 12 ->
|
2 * 5 == 12 ->
|
||||||
"Ich auch nicht."
|
"Ich auch nicht."
|
||||||
true ->
|
true ->
|
||||||
"Aber ich! (dies ist im Grunde ein 'else')"
|
"Aber ich! (dies ist im Grunde ein 'else')"
|
||||||
end
|
end
|
||||||
|
|
||||||
# 'try/catch' wird verwendet um Werte zu fangen, die zuvor 'geworfen' wurden.
|
# 'try/catch' wird verwendet um Werte zu fangen, die zuvor 'geworfen' wurden.
|
||||||
# Das Konstrukt unterstützt außerdem eine 'after'-Klausel die aufgerufen wird,
|
# Das Konstrukt unterstützt außerdem eine 'after'-Klausel die aufgerufen wird,
|
||||||
# egal ob zuvor ein Wert gefangen wurde.
|
# egal ob zuvor ein Wert gefangen wurde.
|
||||||
try do
|
try do
|
||||||
throw(:hello)
|
throw(:hello)
|
||||||
catch
|
catch
|
||||||
nachricht -> "#{nachricht} gefangen."
|
nachricht -> "#{nachricht} gefangen."
|
||||||
after
|
after
|
||||||
IO.puts("Ich bin die 'after'-Klausel.")
|
IO.puts("Ich bin die 'after'-Klausel.")
|
||||||
end
|
end
|
||||||
#=> Ich bin die 'after'-Klausel.
|
#=> Ich bin die 'after'-Klausel.
|
||||||
# ":hello gefangen"
|
# ":hello gefangen"
|
||||||
|
|
||||||
## ---------------------------
|
## ---------------------------
|
||||||
## -- Module und Funktionen
|
## -- Module und Funktionen
|
||||||
## ---------------------------
|
## ---------------------------
|
||||||
|
|
||||||
# Anonyme Funktionen (man beachte den Punkt)
|
# Anonyme Funktionen (man beachte den Punkt)
|
||||||
square = fn(x) -> x * x end
|
square = fn(x) -> x * x end
|
||||||
square.(5) #=> 25
|
square.(5) #=> 25
|
||||||
|
|
||||||
# Anonyme Funktionen unterstützen auch 'pattern' und 'guards'. Guards erlauben
|
# Anonyme Funktionen unterstützen auch 'pattern' und 'guards'. Guards erlauben
|
||||||
# es die Mustererkennung zu justieren und werden mit dem Schlüsselwort 'when'
|
# es die Mustererkennung zu justieren und werden mit dem Schlüsselwort 'when'
|
||||||
# eingeführt:
|
# eingeführt:
|
||||||
f = fn
|
f = fn
|
||||||
x, y when x > 0 -> x + y
|
x, y when x > 0 -> x + y
|
||||||
x, y -> x * y
|
x, y -> x * y
|
||||||
end
|
end
|
||||||
|
|
||||||
f.(1, 3) #=> 4
|
f.(1, 3) #=> 4
|
||||||
f.(-1, 3) #=> -3
|
f.(-1, 3) #=> -3
|
||||||
|
|
||||||
# Elixir bietet zahlreiche eingebaute Funktionen. Diese sind im gleichen
|
# Elixir bietet zahlreiche eingebaute Funktionen. Diese sind im gleichen
|
||||||
# Geltungsbereich ('scope') verfügbar.
|
# Geltungsbereich ('scope') verfügbar.
|
||||||
is_number(10) #=> true
|
is_number(10) #=> true
|
||||||
is_list("hello") #=> false
|
is_list("hello") #=> false
|
||||||
elem({1,2,3}, 0) #=> 1
|
elem({1,2,3}, 0) #=> 1
|
||||||
|
|
||||||
# Mehrere Funktionen können in einem Modul gruppiert werden. Innerhalb eines
|
# Mehrere Funktionen können in einem Modul gruppiert werden. Innerhalb eines
|
||||||
# Moduls ist es möglich mit dem Schlüsselwort 'def' eine Funktion zu
|
# Moduls ist es möglich mit dem Schlüsselwort 'def' eine Funktion zu
|
||||||
# definieren.
|
# definieren.
|
||||||
defmodule Math do
|
defmodule Math do
|
||||||
def sum(a, b) do
|
def sum(a, b) do
|
||||||
a + b
|
a + b
|
||||||
end
|
end
|
||||||
|
|
||||||
def square(x) do
|
def square(x) do
|
||||||
x * x
|
x * x
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Math.sum(1, 2) #=> 3
|
Math.sum(1, 2) #=> 3
|
||||||
Math.square(3) #=> 9
|
Math.square(3) #=> 9
|
||||||
|
|
||||||
# Um unser einfaches Mathe-Modul zu kompilieren muss es unter 'math.ex'
|
# Um unser einfaches Mathe-Modul zu kompilieren muss es unter 'math.ex'
|
||||||
# gesichert werden. Anschließend kann es mit 'elixirc' im Terminal aufgerufen
|
# gesichert werden. Anschließend kann es mit 'elixirc' im Terminal aufgerufen
|
||||||
# werden: elixirc math.ex
|
# werden: elixirc math.ex
|
||||||
|
|
||||||
# Innerhalb eines Moduls definieren wir private Funktionen mit 'defp'. Eine
|
# Innerhalb eines Moduls definieren wir private Funktionen mit 'defp'. Eine
|
||||||
# Funktion, die mit 'def' erstellt wurde, kann von anderen Modulen aufgerufen
|
# Funktion, die mit 'def' erstellt wurde, kann von anderen Modulen aufgerufen
|
||||||
# werden; eine private Funktion kann nur lokal angesprochen werden.
|
# werden; eine private Funktion kann nur lokal angesprochen werden.
|
||||||
defmodule PrivateMath do
|
defmodule PrivateMath do
|
||||||
def sum(a, b) do
|
def sum(a, b) do
|
||||||
do_sum(a, b)
|
do_sum(a, b)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_sum(a, b) do
|
defp do_sum(a, b) do
|
||||||
a + b
|
a + b
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
PrivateMath.sum(1, 2) #=> 3
|
PrivateMath.sum(1, 2) #=> 3
|
||||||
# PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError)
|
# PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError)
|
||||||
|
|
||||||
# Auch Funktionsdeklarationen unterstützen 'guards' und Mustererkennung:
|
# Auch Funktionsdeklarationen unterstützen 'guards' und Mustererkennung:
|
||||||
defmodule Geometry do
|
defmodule Geometry do
|
||||||
def area({:rectangle, w, h}) do
|
def area({:rectangle, w, h}) do
|
||||||
w * h
|
w * h
|
||||||
end
|
end
|
||||||
|
|
||||||
def area({:circle, r}) when is_number(r) do
|
def area({:circle, r}) when is_number(r) do
|
||||||
3.14 * r * r
|
3.14 * r * r
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Geometry.area({:rectangle, 2, 3}) #=> 6
|
Geometry.area({:rectangle, 2, 3}) #=> 6
|
||||||
Geometry.area({:circle, 3}) #=> 28.25999999999999801048
|
Geometry.area({:circle, 3}) #=> 28.25999999999999801048
|
||||||
# Geometry.area({:circle, "not_a_number"})
|
# Geometry.area({:circle, "not_a_number"})
|
||||||
#=> ** (FunctionClauseError) no function clause matching in Geometry.area/1
|
#=> ** (FunctionClauseError) no function clause matching in Geometry.area/1
|
||||||
|
|
||||||
# Wegen der Unveränderlichkeit von Variablen ist Rekursion ein wichtiger
|
# Wegen der Unveränderlichkeit von Variablen ist Rekursion ein wichtiger
|
||||||
# Bestandteil von Elixir.
|
# Bestandteil von Elixir.
|
||||||
defmodule Recursion do
|
defmodule Recursion do
|
||||||
def sum_list([head | tail], acc) do
|
def sum_list([head | tail], acc) do
|
||||||
sum_list(tail, acc + head)
|
sum_list(tail, acc + head)
|
||||||
end
|
end
|
||||||
|
|
||||||
def sum_list([], acc) do
|
def sum_list([], acc) do
|
||||||
acc
|
acc
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Recursion.sum_list([1,2,3], 0) #=> 6
|
Recursion.sum_list([1,2,3], 0) #=> 6
|
||||||
|
|
||||||
# Elixir-Module unterstützen Attribute. Es gibt eingebaute Attribute, ebenso
|
# Elixir-Module unterstützen Attribute. Es gibt eingebaute Attribute, ebenso
|
||||||
# ist es möglich eigene Attribute hinzuzufügen.
|
# ist es möglich eigene Attribute hinzuzufügen.
|
||||||
defmodule MyMod do
|
defmodule MyMod do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Dies ist ein eingebautes Attribut in einem Beispiel-Modul
|
Dies ist ein eingebautes Attribut in einem Beispiel-Modul
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@my_data 100 # Dies ist ein selbst-definiertes Attribut.
|
@my_data 100 # Dies ist ein selbst-definiertes Attribut.
|
||||||
IO.inspect(@my_data) #=> 100
|
IO.inspect(@my_data) #=> 100
|
||||||
end
|
end
|
||||||
|
|
||||||
## ---------------------------
|
## ---------------------------
|
||||||
## -- 'Records' und Ausnahmebehandlung
|
## -- 'Records' und Ausnahmebehandlung
|
||||||
## ---------------------------
|
## ---------------------------
|
||||||
|
|
||||||
# 'Records' sind im Grunde Strukturen, die es erlauben einem Wert einen eigenen
|
# 'Records' sind im Grunde Strukturen, die es erlauben einem Wert einen eigenen
|
||||||
# Namen zuzuweisen.
|
# Namen zuzuweisen.
|
||||||
defrecord Person, name: nil, age: 0, height: 0
|
defrecord Person, name: nil, age: 0, height: 0
|
||||||
|
|
||||||
joe_info = Person.new(name: "Joe", age: 30, height: 180)
|
joe_info = Person.new(name: "Joe", age: 30, height: 180)
|
||||||
#=> Person[name: "Joe", age: 30, height: 180]
|
#=> Person[name: "Joe", age: 30, height: 180]
|
||||||
|
|
||||||
# Zugriff auf den Wert von 'name'
|
# Zugriff auf den Wert von 'name'
|
||||||
joe_info.name #=> "Joe"
|
joe_info.name #=> "Joe"
|
||||||
|
|
||||||
# Den Wert von 'age' überschreiben
|
# Den Wert von 'age' überschreiben
|
||||||
joe_info = joe_info.age(31) #=> Person[name: "Joe", age: 31, height: 180]
|
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,
|
# Der 'try'-Block wird zusammen mit dem 'rescue'-Schlüsselwort dazu verwendet,
|
||||||
# um Ausnahmen beziehungsweise Fehler zu behandeln.
|
# um Ausnahmen beziehungsweise Fehler zu behandeln.
|
||||||
try do
|
try do
|
||||||
raise "Irgendein Fehler."
|
raise "Irgendein Fehler."
|
||||||
rescue
|
rescue
|
||||||
RuntimeError -> "Laufzeit-Fehler gefangen."
|
RuntimeError -> "Laufzeit-Fehler gefangen."
|
||||||
_error -> "Und dies fängt jeden Fehler."
|
_error -> "Und dies fängt jeden Fehler."
|
||||||
end
|
end
|
||||||
|
|
||||||
# Alle Ausnahmen haben das Attribut 'message'
|
# Alle Ausnahmen haben das Attribut 'message'
|
||||||
try do
|
try do
|
||||||
raise "ein Fehler"
|
raise "ein Fehler"
|
||||||
rescue
|
rescue
|
||||||
x in [RuntimeError] ->
|
x in [RuntimeError] ->
|
||||||
x.message
|
x.message
|
||||||
end
|
end
|
||||||
|
|
||||||
## ---------------------------
|
## ---------------------------
|
||||||
## -- Nebenläufigkeit
|
## -- Nebenläufigkeit
|
||||||
## ---------------------------
|
## ---------------------------
|
||||||
|
|
||||||
# Elixir beruht auf dem Aktoren-Model zur Behandlung der Nebenläufigkeit. Alles
|
# 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
|
# was man braucht um in Elixir nebenläufige Programme zu schreiben sind drei
|
||||||
# Primitive: Prozesse erzeugen, Nachrichten senden und Nachrichten empfangen.
|
# Primitive: Prozesse erzeugen, Nachrichten senden und Nachrichten empfangen.
|
||||||
|
|
||||||
# Um einen neuen Prozess zu erzeugen nutzen wir die 'spawn'-Funktion, die
|
# Um einen neuen Prozess zu erzeugen nutzen wir die 'spawn'-Funktion, die
|
||||||
# wiederum eine Funktion als Argument entgegen nimmt.
|
# wiederum eine Funktion als Argument entgegen nimmt.
|
||||||
f = fn -> 2 * 2 end #=> #Function<erl_eval.20.80484245>
|
f = fn -> 2 * 2 end #=> #Function<erl_eval.20.80484245>
|
||||||
spawn(f) #=> #PID<0.40.0>
|
spawn(f) #=> #PID<0.40.0>
|
||||||
|
|
||||||
# 'spawn' gibt eine pid (einen Identifikator des Prozesses) zurück. Diese kann
|
# 'spawn' gibt eine pid (einen Identifikator des Prozesses) zurück. Diese kann
|
||||||
# nun verwendet werden, um Nachrichten an den Prozess zu senden. Um
|
# 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
|
# 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
|
# in der Lage sein Nachrichten zu empfangen. Dies wird mit dem
|
||||||
# 'receive'-Mechanismus sichergestellt:
|
# 'receive'-Mechanismus sichergestellt:
|
||||||
defmodule Geometry do
|
defmodule Geometry do
|
||||||
def area_loop do
|
def area_loop do
|
||||||
receive do
|
receive do
|
||||||
{:rectangle, w, h} ->
|
{:rectangle, w, h} ->
|
||||||
IO.puts("Area = #{w * h}")
|
IO.puts("Area = #{w * h}")
|
||||||
area_loop()
|
area_loop()
|
||||||
{:circle, r} ->
|
{:circle, r} ->
|
||||||
IO.puts("Area = #{3.14 * r * r}")
|
IO.puts("Area = #{3.14 * r * r}")
|
||||||
area_loop()
|
area_loop()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Kompiliere das Modul, starte einen Prozess und gib die 'area_loop' Funktion
|
# Kompiliere das Modul, starte einen Prozess und gib die 'area_loop' Funktion
|
||||||
# in der Shell mit, etwa so:
|
# in der Shell mit, etwa so:
|
||||||
pid = spawn(fn -> Geometry.area_loop() end) #=> #PID<0.40.0>
|
pid = spawn(fn -> Geometry.area_loop() end) #=> #PID<0.40.0>
|
||||||
|
|
||||||
# Sende eine Nachricht an die 'pid', die ein Muster im 'receive'-Ausdruck
|
# Sende eine Nachricht an die 'pid', die ein Muster im 'receive'-Ausdruck
|
||||||
# erfüllt:
|
# erfüllt:
|
||||||
pid <- {:rectangle, 2, 3}
|
pid <- {:rectangle, 2, 3}
|
||||||
#=> Area = 6
|
#=> Area = 6
|
||||||
# {:rectangle,2,3}
|
# {:rectangle,2,3}
|
||||||
|
|
||||||
pid <- {:circle, 2}
|
pid <- {:circle, 2}
|
||||||
#=> Area = 12.56000000000000049738
|
#=> Area = 12.56000000000000049738
|
||||||
# {:circle,2}
|
# {:circle,2}
|
||||||
|
|
||||||
# Die Shell selbst ist ein Prozess und mit dem Schlüsselwort 'self' kann man
|
# Die Shell selbst ist ein Prozess und mit dem Schlüsselwort 'self' kann man
|
||||||
# die aktuelle pid herausfinden.
|
# die aktuelle pid herausfinden.
|
||||||
self() #=> #PID<0.27.0>
|
self() #=> #PID<0.27.0>
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Referenzen und weitere Lektüre
|
## Referenzen und weitere Lektüre
|
||||||
|
|
||||||
* [Getting started guide](http://elixir-lang.org/getting_started/1.html) auf der [elixir Website](http://elixir-lang.org)
|
* [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/)
|
* [Elixir Documentation](http://elixir-lang.org/docs/master/)
|
||||||
* ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) von Fred Hebert
|
* ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) von Fred Hebert
|
||||||
* "Programming Erlang: Software for a Concurrent World" von Joe Armstrong
|
* "Programming Erlang: Software for a Concurrent World" von Joe Armstrong
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,263 +1,263 @@
|
|||||||
---
|
---
|
||||||
category: tool
|
category: tool
|
||||||
tool: make
|
tool: make
|
||||||
contributors:
|
contributors:
|
||||||
- ["Robert Steed", "https://github.com/robochat"]
|
- ["Robert Steed", "https://github.com/robochat"]
|
||||||
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
|
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
|
||||||
translators:
|
translators:
|
||||||
- ["Martin Schimandl", "https://github.com/Git-Jiro"]
|
- ["Martin Schimandl", "https://github.com/Git-Jiro"]
|
||||||
filename: Makefile-de
|
filename: Makefile-de
|
||||||
lang: de-de
|
lang: de-de
|
||||||
---
|
---
|
||||||
|
|
||||||
Eine Makefile definiert einen Graphen von Regeln um ein Ziel (oder Ziele)
|
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
|
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
|
ein Ziel in Einklang mit dem Quellcode zu bringen. Make wurde berühmterweise
|
||||||
von Stuart Feldman 1976 übers Wochenende geschrieben. Make ist noch immer
|
von Stuart Feldman 1976 übers Wochenende geschrieben. Make ist noch immer
|
||||||
sehr verbreitet (vorallem im Unix Umfeld) obwohl es bereits sehr viel
|
sehr verbreitet (vorallem im Unix Umfeld) obwohl es bereits sehr viel
|
||||||
Konkurrenz und Kritik zu Make gibt.
|
Konkurrenz und Kritik zu Make gibt.
|
||||||
|
|
||||||
Es gibt eine Vielzahl an Varianten von Make, dieser Artikel beschäftigt sich
|
Es gibt eine Vielzahl an Varianten von Make, dieser Artikel beschäftigt sich
|
||||||
mit der Version GNU Make. Diese Version ist Standard auf Linux.
|
mit der Version GNU Make. Diese Version ist Standard auf Linux.
|
||||||
|
|
||||||
```make
|
```make
|
||||||
|
|
||||||
# Kommentare können so geschrieben werden.
|
# Kommentare können so geschrieben werden.
|
||||||
|
|
||||||
# Dateien sollten Makefile heißen, denn dann können sie als `make <ziel>`
|
# Dateien sollten Makefile heißen, denn dann können sie als `make <ziel>`
|
||||||
# aufgerufen werden. Ansonsten muss `make -f "dateiname" <ziel>` verwendet
|
# aufgerufen werden. Ansonsten muss `make -f "dateiname" <ziel>` verwendet
|
||||||
# werden.
|
# werden.
|
||||||
|
|
||||||
# Warnung - Es sollten nur TABULATOREN zur Einrückung im Makefile verwendet
|
# Warnung - Es sollten nur TABULATOREN zur Einrückung im Makefile verwendet
|
||||||
# werden. Niemals Leerzeichen!
|
# werden. Niemals Leerzeichen!
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Grundlagen
|
# Grundlagen
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# Eine Regel - Diese Regel wird nur abgearbeitet wenn die Datei file0.txt
|
# Eine Regel - Diese Regel wird nur abgearbeitet wenn die Datei file0.txt
|
||||||
# nicht existiert.
|
# nicht existiert.
|
||||||
file0.txt:
|
file0.txt:
|
||||||
echo "foo" > file0.txt
|
echo "foo" > file0.txt
|
||||||
# Selbst Kommentare in der 'Rezept' Sektion werden an die Shell
|
# Selbst Kommentare in der 'Rezept' Sektion werden an die Shell
|
||||||
# weitergegeben. Versuche `make file0.txt` oder einfach `make`
|
# weitergegeben. Versuche `make file0.txt` oder einfach `make`
|
||||||
# die erste Regel ist die Standard-Regel.
|
# die erste Regel ist die Standard-Regel.
|
||||||
|
|
||||||
|
|
||||||
# Diese Regel wird nur abgearbeitet, wenn file0.txt aktueller als file1.txt ist.
|
# Diese Regel wird nur abgearbeitet, wenn file0.txt aktueller als file1.txt ist.
|
||||||
file1.txt: file0.txt
|
file1.txt: file0.txt
|
||||||
cat file0.txt > file1.txt
|
cat file0.txt > file1.txt
|
||||||
# Verwende die selben Quoting-Regeln wie die Shell
|
# Verwende die selben Quoting-Regeln wie die Shell
|
||||||
@cat file0.txt >> file1.txt
|
@cat file0.txt >> file1.txt
|
||||||
# @ unterdrückt die Ausgabe des Befehls an stdout.
|
# @ unterdrückt die Ausgabe des Befehls an stdout.
|
||||||
-@echo 'hello'
|
-@echo 'hello'
|
||||||
# - bedeutet, dass Make die Abarbeitung fortsetzt auch wenn Fehler
|
# - bedeutet, dass Make die Abarbeitung fortsetzt auch wenn Fehler
|
||||||
# passieren.
|
# passieren.
|
||||||
# Versuche `make file1.txt` auf der Kommandozeile.
|
# Versuche `make file1.txt` auf der Kommandozeile.
|
||||||
|
|
||||||
# Eine Regel kann mehrere Ziele und mehrere Voraussetzungen haben.
|
# Eine Regel kann mehrere Ziele und mehrere Voraussetzungen haben.
|
||||||
file2.txt file3.txt: file0.txt file1.txt
|
file2.txt file3.txt: file0.txt file1.txt
|
||||||
touch file2.txt
|
touch file2.txt
|
||||||
touch file3.txt
|
touch file3.txt
|
||||||
|
|
||||||
# Make wird sich beschweren, wenn es mehrere Rezepte für die gleiche Regel gibt.
|
# 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
|
# Leere Rezepte zählen nicht und können dazu verwendet werden weitere
|
||||||
# Voraussetzungen hinzuzufügen.
|
# Voraussetzungen hinzuzufügen.
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Phony-Ziele
|
# Phony-Ziele
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# Ein Phony-Ziel ist ein Ziel, das keine Datei ist.
|
# Ein Phony-Ziel ist ein Ziel, das keine Datei ist.
|
||||||
# Es wird nie aktuell sein, daher wird Make immer versuchen, es abzuarbeiten
|
# Es wird nie aktuell sein, daher wird Make immer versuchen, es abzuarbeiten
|
||||||
all: maker process
|
all: maker process
|
||||||
|
|
||||||
# Es ist erlaubt Dinge ausserhalb der Reihenfolge zu deklarieren.
|
# Es ist erlaubt Dinge ausserhalb der Reihenfolge zu deklarieren.
|
||||||
maker:
|
maker:
|
||||||
touch ex0.txt ex1.txt
|
touch ex0.txt ex1.txt
|
||||||
|
|
||||||
# Um das Fehlschlagen von Phony-Regeln zu vermeiden wenn eine echte Datei den
|
# Um das Fehlschlagen von Phony-Regeln zu vermeiden wenn eine echte Datei den
|
||||||
# selben namen wie ein Phony-Ziel hat:
|
# selben namen wie ein Phony-Ziel hat:
|
||||||
.PHONY: all maker process
|
.PHONY: all maker process
|
||||||
# Das ist ein spezielles Ziel. Es gibt noch ein paar mehr davon.
|
# Das ist ein spezielles Ziel. Es gibt noch ein paar mehr davon.
|
||||||
|
|
||||||
# Eine Regel mit einem Phony-Ziel als Voraussetzung wird immer abgearbeitet
|
# Eine Regel mit einem Phony-Ziel als Voraussetzung wird immer abgearbeitet
|
||||||
ex0.txt ex1.txt: maker
|
ex0.txt ex1.txt: maker
|
||||||
|
|
||||||
# Häufige Phony-Ziele sind: all make clean install ...
|
# Häufige Phony-Ziele sind: all make clean install ...
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Automatische Variablen & Wildcards
|
# Automatische Variablen & Wildcards
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
process: file*.txt # Eine Wildcard um Dateinamen zu vergleichen
|
process: file*.txt # Eine Wildcard um Dateinamen zu vergleichen
|
||||||
@echo $^ # $^ ist eine Variable die eine Liste aller
|
@echo $^ # $^ ist eine Variable die eine Liste aller
|
||||||
# Voraussetzungen enthält.
|
# Voraussetzungen enthält.
|
||||||
@echo $@ # Namen des Ziels ausgeben.
|
@echo $@ # Namen des Ziels ausgeben.
|
||||||
#(Bei mehreren Ziel-Regeln enthält $@ den Verursacher der Abarbeitung
|
#(Bei mehreren Ziel-Regeln enthält $@ den Verursacher der Abarbeitung
|
||||||
#der Regel.)
|
#der Regel.)
|
||||||
@echo $< # Die erste Voraussetzung aus der Liste
|
@echo $< # Die erste Voraussetzung aus der Liste
|
||||||
@echo $? # Nur die Voraussetzungen, die nicht aktuell sind.
|
@echo $? # Nur die Voraussetzungen, die nicht aktuell sind.
|
||||||
@echo $+ # Alle Voraussetzungen inklusive Duplikate (nicht wie Üblich)
|
@echo $+ # Alle Voraussetzungen inklusive Duplikate (nicht wie Üblich)
|
||||||
#@echo $| # Alle 'order only' Voraussetzungen
|
#@echo $| # Alle 'order only' Voraussetzungen
|
||||||
|
|
||||||
# Selbst wenn wir die Voraussetzungen der Regel aufteilen, $^ wird sie finden.
|
# Selbst wenn wir die Voraussetzungen der Regel aufteilen, $^ wird sie finden.
|
||||||
process: ex1.txt file0.txt
|
process: ex1.txt file0.txt
|
||||||
# ex1.txt wird gefunden werden, aber file0.txt wird dedupliziert.
|
# ex1.txt wird gefunden werden, aber file0.txt wird dedupliziert.
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Muster
|
# Muster
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# Mit Mustern kann man make beibringen wie Dateien in andere Dateien
|
# Mit Mustern kann man make beibringen wie Dateien in andere Dateien
|
||||||
# umgewandelt werden.
|
# umgewandelt werden.
|
||||||
|
|
||||||
%.png: %.svg
|
%.png: %.svg
|
||||||
inkscape --export-png $^
|
inkscape --export-png $^
|
||||||
|
|
||||||
# Muster-Vergleichs-Regeln werden nur abgearbeitet, wenn make entscheidet das
|
# Muster-Vergleichs-Regeln werden nur abgearbeitet, wenn make entscheidet das
|
||||||
# Ziel zu erzeugen
|
# Ziel zu erzeugen
|
||||||
|
|
||||||
# Verzeichnis-Pfade werden normalerweise bei Muster-Vergleichs-Regeln ignoriert.
|
# Verzeichnis-Pfade werden normalerweise bei Muster-Vergleichs-Regeln ignoriert.
|
||||||
# Aber make wird versuchen die am besten passende Regel zu verwenden.
|
# Aber make wird versuchen die am besten passende Regel zu verwenden.
|
||||||
small/%.png: %.svg
|
small/%.png: %.svg
|
||||||
inkscape --export-png --export-dpi 30 $^
|
inkscape --export-png --export-dpi 30 $^
|
||||||
|
|
||||||
# Make wird die letzte Version einer Muster-Vergleichs-Regel verwenden, die es
|
# Make wird die letzte Version einer Muster-Vergleichs-Regel verwenden, die es
|
||||||
# findet.
|
# findet.
|
||||||
%.png: %.svg
|
%.png: %.svg
|
||||||
@echo this rule is chosen
|
@echo this rule is chosen
|
||||||
|
|
||||||
# Allerdings wird make die erste Muster-Vergleicher-Regel verwenden, die das
|
# Allerdings wird make die erste Muster-Vergleicher-Regel verwenden, die das
|
||||||
# Ziel erzeugen kann.
|
# Ziel erzeugen kann.
|
||||||
%.png: %.ps
|
%.png: %.ps
|
||||||
@echo this rule is not chosen if *.svg and *.ps are both present
|
@echo this rule is not chosen if *.svg and *.ps are both present
|
||||||
|
|
||||||
# Make hat bereits ein paar eingebaute Muster-Vergleichs-Regelen. Zum Beispiel
|
# Make hat bereits ein paar eingebaute Muster-Vergleichs-Regelen. Zum Beispiel
|
||||||
# weiß Make wie man aus *.c Dateien *.o Dateien erzeugt.
|
# weiß Make wie man aus *.c Dateien *.o Dateien erzeugt.
|
||||||
|
|
||||||
# Ältere Versionen von Make verwenden möglicherweise Suffix-Regeln anstatt
|
# Ältere Versionen von Make verwenden möglicherweise Suffix-Regeln anstatt
|
||||||
# Muster-Vergleichs-Regeln.
|
# Muster-Vergleichs-Regeln.
|
||||||
.png.ps:
|
.png.ps:
|
||||||
@echo this rule is similar to a pattern rule.
|
@echo this rule is similar to a pattern rule.
|
||||||
|
|
||||||
# Aktivieren der Suffix-Regel
|
# Aktivieren der Suffix-Regel
|
||||||
.SUFFIXES: .png
|
.SUFFIXES: .png
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Variablen
|
# Variablen
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# auch Makros genannt.
|
# auch Makros genannt.
|
||||||
|
|
||||||
# Variablen sind im Grunde genommen Zeichenketten-Typen.
|
# Variablen sind im Grunde genommen Zeichenketten-Typen.
|
||||||
|
|
||||||
name = Ted
|
name = Ted
|
||||||
name2="Sarah"
|
name2="Sarah"
|
||||||
|
|
||||||
echo:
|
echo:
|
||||||
@echo $(name)
|
@echo $(name)
|
||||||
@echo ${name2}
|
@echo ${name2}
|
||||||
@echo $name # Das funktioniert nicht, wird als $(n)ame behandelt.
|
@echo $name # Das funktioniert nicht, wird als $(n)ame behandelt.
|
||||||
@echo $(name3) # Unbekannte Variablen werden als leere Zeichenketten behandelt.
|
@echo $(name3) # Unbekannte Variablen werden als leere Zeichenketten behandelt.
|
||||||
|
|
||||||
# Es git 4 Stellen um Variablen zu setzen.
|
# Es git 4 Stellen um Variablen zu setzen.
|
||||||
# In Reihenfolge der Priorität von höchster zu niedrigster:
|
# In Reihenfolge der Priorität von höchster zu niedrigster:
|
||||||
# 1: Befehls-Zeilen Argumente
|
# 1: Befehls-Zeilen Argumente
|
||||||
# 2: Makefile
|
# 2: Makefile
|
||||||
# 3: Shell Umbebungs-Variablen - Make importiert diese automatisch.
|
# 3: Shell Umbebungs-Variablen - Make importiert diese automatisch.
|
||||||
# 3: MAke hat einige vordefinierte Variablen.
|
# 3: MAke hat einige vordefinierte Variablen.
|
||||||
|
|
||||||
name4 ?= Jean
|
name4 ?= Jean
|
||||||
# Setze die Variable nur wenn es eine gleichnamige Umgebungs-Variable noch
|
# Setze die Variable nur wenn es eine gleichnamige Umgebungs-Variable noch
|
||||||
# nicht gibt.
|
# nicht gibt.
|
||||||
|
|
||||||
override name5 = David
|
override name5 = David
|
||||||
# Verhindert, dass Kommando-Zeilen Argumente diese Variable ändern können.
|
# Verhindert, dass Kommando-Zeilen Argumente diese Variable ändern können.
|
||||||
|
|
||||||
name4 +=grey
|
name4 +=grey
|
||||||
# Werte an eine Variable anhängen (inkludiert Leerzeichen).
|
# Werte an eine Variable anhängen (inkludiert Leerzeichen).
|
||||||
|
|
||||||
# Muster-Spezifische Variablen Werte (GNU Erweiterung).
|
# Muster-Spezifische Variablen Werte (GNU Erweiterung).
|
||||||
echo: name2 = Sara # Wahr innerhalb der passenden Regel und auch innerhalb
|
echo: name2 = Sara # Wahr innerhalb der passenden Regel und auch innerhalb
|
||||||
# rekursiver Voraussetzungen (ausser wenn es den Graphen zerstören
|
# rekursiver Voraussetzungen (ausser wenn es den Graphen zerstören
|
||||||
# kann, wenn es zu kompilizert wird!)
|
# kann, wenn es zu kompilizert wird!)
|
||||||
|
|
||||||
# Ein paar Variablen, die von Make automatisch definiert werden.
|
# Ein paar Variablen, die von Make automatisch definiert werden.
|
||||||
echo_inbuilt:
|
echo_inbuilt:
|
||||||
echo $(CC)
|
echo $(CC)
|
||||||
echo ${CXX}
|
echo ${CXX}
|
||||||
echo $(FC)
|
echo $(FC)
|
||||||
echo ${CFLAGS}
|
echo ${CFLAGS}
|
||||||
echo $(CPPFLAGS)
|
echo $(CPPFLAGS)
|
||||||
echo ${CXXFLAGS}
|
echo ${CXXFLAGS}
|
||||||
echo $(LDFLAGS)
|
echo $(LDFLAGS)
|
||||||
echo ${LDLIBS}
|
echo ${LDLIBS}
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Variablen 2
|
# Variablen 2
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# Der erste Typ von Variablen wird bei jeder Verwendung ausgewertet.
|
# Der erste Typ von Variablen wird bei jeder Verwendung ausgewertet.
|
||||||
# Das kann aufwendig sein, daher exisitert ein zweiter Typ von Variablen.
|
# Das kann aufwendig sein, daher exisitert ein zweiter Typ von Variablen.
|
||||||
# Diese werden nur einmal ausgewertet. (Das ist eine GNU make Erweiterung)
|
# Diese werden nur einmal ausgewertet. (Das ist eine GNU make Erweiterung)
|
||||||
|
|
||||||
var := hello
|
var := hello
|
||||||
var2 ::= $(var) hello
|
var2 ::= $(var) hello
|
||||||
#:= und ::= sind äquivalent.
|
#:= und ::= sind äquivalent.
|
||||||
|
|
||||||
# Diese Variablen werden prozedural ausgwertet (in der Reihenfolge in der sie
|
# Diese Variablen werden prozedural ausgwertet (in der Reihenfolge in der sie
|
||||||
# auftauchen), die stehen daher im wiederspruch zum Rest der Sprache!
|
# auftauchen), die stehen daher im wiederspruch zum Rest der Sprache!
|
||||||
|
|
||||||
# Das funktioniert nicht
|
# Das funktioniert nicht
|
||||||
var3 ::= $(var4) and good luck
|
var3 ::= $(var4) and good luck
|
||||||
var4 ::= good night
|
var4 ::= good night
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Funktionen
|
# Funktionen
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# Make verfügt über eine Vielzahl von Funktionen.
|
# Make verfügt über eine Vielzahl von Funktionen.
|
||||||
|
|
||||||
sourcefiles = $(wildcard *.c */*.c)
|
sourcefiles = $(wildcard *.c */*.c)
|
||||||
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
|
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
|
||||||
|
|
||||||
# Das Format ist $(func arg0,arg1,arg2...)
|
# Das Format ist $(func arg0,arg1,arg2...)
|
||||||
|
|
||||||
# Ein paar Beispiele
|
# Ein paar Beispiele
|
||||||
ls: * src/*
|
ls: * src/*
|
||||||
@echo $(filter %.txt, $^)
|
@echo $(filter %.txt, $^)
|
||||||
@echo $(notdir $^)
|
@echo $(notdir $^)
|
||||||
@echo $(join $(dir $^),$(notdir $^))
|
@echo $(join $(dir $^),$(notdir $^))
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Direktiven
|
# Direktiven
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# Inkludiere andere Makefile, sehr praktisch für platformspezifischen Code
|
# Inkludiere andere Makefile, sehr praktisch für platformspezifischen Code
|
||||||
include foo.mk
|
include foo.mk
|
||||||
|
|
||||||
sport = tennis
|
sport = tennis
|
||||||
# Konditionale kompiliereung
|
# Konditionale kompiliereung
|
||||||
report:
|
report:
|
||||||
ifeq ($(sport),tennis)
|
ifeq ($(sport),tennis)
|
||||||
@echo 'game, set, match'
|
@echo 'game, set, match'
|
||||||
else
|
else
|
||||||
@echo "They think it's all over; it is now"
|
@echo "They think it's all over; it is now"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Es gibt auch ifneq, ifdef, ifndef
|
# Es gibt auch ifneq, ifdef, ifndef
|
||||||
|
|
||||||
foo = true
|
foo = true
|
||||||
|
|
||||||
ifdef $(foo)
|
ifdef $(foo)
|
||||||
bar = 'hello'
|
bar = 'hello'
|
||||||
endif
|
endif
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Mehr Resourcen
|
### Mehr Resourcen
|
||||||
|
|
||||||
+ [gnu make documentation](https://www.gnu.org/software/make/manual/)
|
+ [gnu make documentation](https://www.gnu.org/software/make/manual/)
|
||||||
+ [software carpentry tutorial](http://swcarpentry.github.io/make-novice/)
|
+ [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)
|
+ learn C the hard way [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html)
|
||||||
|
|
||||||
|
@@ -1,281 +1,281 @@
|
|||||||
---
|
---
|
||||||
category: tool
|
category: tool
|
||||||
tool: docker
|
tool: docker
|
||||||
filename: docker.bat
|
filename: docker.bat
|
||||||
contributors:
|
contributors:
|
||||||
- ["Ruslan López", "http://javapro.org/"]
|
- ["Ruslan López", "http://javapro.org/"]
|
||||||
- ["Michael Chen", "https://github.com/ML-Chen"]
|
- ["Michael Chen", "https://github.com/ML-Chen"]
|
||||||
- ["Akshita Dixit", "https://github.com/akshitadixit"]
|
- ["Akshita Dixit", "https://github.com/akshitadixit"]
|
||||||
- ["Marcel Ribeiro-Dantas", "https://github.com/mribeirodantas"]
|
- ["Marcel Ribeiro-Dantas", "https://github.com/mribeirodantas"]
|
||||||
---
|
---
|
||||||
|
|
||||||
Docker is a tool that helps you build, test, ship and run applications
|
Docker is a tool that helps you build, test, ship and run applications
|
||||||
seamlessly across various machines. It replicates the environment our software
|
seamlessly across various machines. It replicates the environment our software
|
||||||
needs on any machine. You can get Docker for your machine from
|
needs on any machine. You can get Docker for your machine from
|
||||||
https://docs.docker.com/get-docker/
|
https://docs.docker.com/get-docker/
|
||||||
|
|
||||||
It has grown in popularity over the last decade due to being lightweight and
|
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
|
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
|
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.
|
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
|
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
|
memory hence running multiple VMs for various applications becomes a challenge
|
||||||
in a limited capacity architecture.
|
in a limited capacity architecture.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
┌────────────────────────┐ ┌───────────────────────┐
|
┌────────────────────────┐ ┌───────────────────────┐
|
||||||
│ ┌───────────┐ │ │ ┌───────────┐ │
|
│ ┌───────────┐ │ │ ┌───────────┐ │
|
||||||
│ │ App │ │ │ │ App │ │
|
│ │ App │ │ │ │ App │ │
|
||||||
│ └───────────┘ │ │ └───────────┘ │
|
│ └───────────┘ │ │ └───────────┘ │
|
||||||
│ ┌────────┐ ┌────────┐ │ │ ┌────────┐ ┌───────┐ │
|
│ ┌────────┐ ┌────────┐ │ │ ┌────────┐ ┌───────┐ │
|
||||||
│ │ Libs │ │ Deps │ │ │ │ Libs │ │ Deps │ │
|
│ │ Libs │ │ Deps │ │ │ │ Libs │ │ Deps │ │
|
||||||
│ └────────┘ └────────┘ │ │ └────────┘ └───────┘ │
|
│ └────────┘ └────────┘ │ │ └────────┘ └───────┘ │
|
||||||
│ ┌───────────────────┐ │ │ ┌──────────────────┐ │
|
│ ┌───────────────────┐ │ │ ┌──────────────────┐ │
|
||||||
│ │ Guest OS │ │ │ │ Guest OS │ │
|
│ │ Guest OS │ │ │ │ Guest OS │ │
|
||||||
│ └───────────────────┘ │ │ └──────────────────┘ │
|
│ └───────────────────┘ │ │ └──────────────────┘ │
|
||||||
│ VM1 │ │ VM2 │
|
│ VM1 │ │ VM2 │
|
||||||
└────────────────────────┘ └───────────────────────┘
|
└────────────────────────┘ └───────────────────────┘
|
||||||
┌──────────────────────────────────────────────────┐
|
┌──────────────────────────────────────────────────┐
|
||||||
│ Hypervisor │
|
│ Hypervisor │
|
||||||
└──────────────────────────────────────────────────┘
|
└──────────────────────────────────────────────────┘
|
||||||
┌──────────────────────────────────────────────────┐
|
┌──────────────────────────────────────────────────┐
|
||||||
│ Host OS │
|
│ Host OS │
|
||||||
└──────────────────────────────────────────────────┘
|
└──────────────────────────────────────────────────┘
|
||||||
┌──────────────────────────────────────────────────┐
|
┌──────────────────────────────────────────────────┐
|
||||||
│ Hardware Infrastructure │
|
│ Hardware Infrastructure │
|
||||||
└──────────────────────────────────────────────────┘
|
└──────────────────────────────────────────────────┘
|
||||||
(VM based architecture)
|
(VM based architecture)
|
||||||
|
|
||||||
┌────────────────────────┐ ┌───────────────────────┐
|
┌────────────────────────┐ ┌───────────────────────┐
|
||||||
│ ┌───────────┐ │ │ ┌───────────┐ │
|
│ ┌───────────┐ │ │ ┌───────────┐ │
|
||||||
│ │ App │ │ │ │ App │ │
|
│ │ App │ │ │ │ App │ │
|
||||||
│ └───────────┘ │ │ └───────────┘ │
|
│ └───────────┘ │ │ └───────────┘ │
|
||||||
│ ┌────────┐ ┌────────┐ │ │ ┌────────┐ ┌───────┐ │
|
│ ┌────────┐ ┌────────┐ │ │ ┌────────┐ ┌───────┐ │
|
||||||
│ │ Libs │ │ Deps │ │ │ │ Libs │ │ Deps │ │
|
│ │ Libs │ │ Deps │ │ │ │ Libs │ │ Deps │ │
|
||||||
│ └────────┘ └────────┘ │ │ └────────┘ └───────┘ │
|
│ └────────┘ └────────┘ │ │ └────────┘ └───────┘ │
|
||||||
│ Container1 │ │ Container2 │
|
│ Container1 │ │ Container2 │
|
||||||
└────────────────────────┘ └───────────────────────┘
|
└────────────────────────┘ └───────────────────────┘
|
||||||
┌──────────────────────────────────────────────────┐
|
┌──────────────────────────────────────────────────┐
|
||||||
│ Docker │
|
│ Docker │
|
||||||
└──────────────────────────────────────────────────┘
|
└──────────────────────────────────────────────────┘
|
||||||
┌──────────────────────────────────────────────────┐
|
┌──────────────────────────────────────────────────┐
|
||||||
│ OS │
|
│ OS │
|
||||||
└──────────────────────────────────────────────────┘
|
└──────────────────────────────────────────────────┘
|
||||||
┌──────────────────────────────────────────────────┐
|
┌──────────────────────────────────────────────────┐
|
||||||
│ Hardware Infrastructure │
|
│ Hardware Infrastructure │
|
||||||
└──────────────────────────────────────────────────┘
|
└──────────────────────────────────────────────────┘
|
||||||
(Docker based architecture)
|
(Docker based architecture)
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
Couple of terms we will encounter frequently are Docker Images and Docker
|
Couple of terms we will encounter frequently are Docker Images and Docker
|
||||||
Containers. Images are packages or templates of containers all stored in a
|
Containers. Images are packages or templates of containers all stored in a
|
||||||
container registry such as [Docker Hub](https://hub.docker.com/). Containers
|
container registry such as [Docker Hub](https://hub.docker.com/). Containers
|
||||||
are standalone, executable instances of these images which include code,
|
are standalone, executable instances of these images which include code,
|
||||||
runtime, system tools, system libraries and settings - everything required to
|
runtime, system tools, system libraries and settings - everything required to
|
||||||
get the software up and running. Coming to Docker, it follows a client-server
|
get the software up and running. Coming to Docker, it follows a client-server
|
||||||
architecture wherein the CLI client communicates with the server component,
|
architecture wherein the CLI client communicates with the server component,
|
||||||
which here is, the Docker Engine using RESTful API to issue commands.
|
which here is, the Docker Engine using RESTful API to issue commands.
|
||||||
|
|
||||||
## The Docker CLI
|
## The Docker CLI
|
||||||
```bash
|
```bash
|
||||||
# after installing Docker from https://docs.docker.com/get-docker/
|
# after installing Docker from https://docs.docker.com/get-docker/
|
||||||
# To list available commands, either run `docker` with no parameters or execute
|
# To list available commands, either run `docker` with no parameters or execute
|
||||||
# `docker help`
|
# `docker help`
|
||||||
$ docker
|
$ docker
|
||||||
|
|
||||||
>>> docker [OPTIONS] COMMAND [ARG...]
|
>>> docker [OPTIONS] COMMAND [ARG...]
|
||||||
docker [ --help | -v | --version ]
|
docker [ --help | -v | --version ]
|
||||||
|
|
||||||
A self-sufficient runtime for containers.
|
A self-sufficient runtime for containers.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--config string Location of client config files (default "/root/.docker")
|
--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")
|
-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
|
-D, --debug Enable debug mode
|
||||||
--help Print usage
|
--help Print usage
|
||||||
-H, --host value Daemon socket(s) to connect to (default [])
|
-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")
|
-l, --log-level string Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
|
||||||
--tls Use TLS; implied by --tlsverify
|
--tls Use TLS; implied by --tlsverify
|
||||||
--tlscacert string Trust certs signed only by this CA (default "/root/.docker/ca.pem")
|
--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")
|
--tlscert string Path to TLS certificate file (default "/root/.docker/cert.pem")
|
||||||
--tlskey string Path to TLS key file (default "/root/.docker/key.pem")
|
--tlskey string Path to TLS key file (default "/root/.docker/key.pem")
|
||||||
--tlsverify Use TLS and verify the remote
|
--tlsverify Use TLS and verify the remote
|
||||||
-v, --version Print version information and quit
|
-v, --version Print version information and quit
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
attach Attach to a running container
|
attach Attach to a running container
|
||||||
# […]
|
# […]
|
||||||
|
|
||||||
$ docker run hello-world
|
$ docker run hello-world
|
||||||
# `docker run <container-name>` is used to run a container, it will pull the
|
# `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
|
# 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"
|
# 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 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
|
# image which runs the executable that produces the output streamed back to the
|
||||||
# client that we see on our terminals.
|
# client that we see on our terminals.
|
||||||
|
|
||||||
$ docker run -d ubuntu sleep 60s
|
$ docker run -d ubuntu sleep 60s
|
||||||
# The -d (or --detach) flag is when we want to run a container in the background
|
# 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
|
# 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
|
# terminal, the output should be the id and the command exits. If we check
|
||||||
# running containers, we should still see ours there:
|
# running containers, we should still see ours there:
|
||||||
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||||
# 133261b4894a ubuntu "sleep 60s" 3 seconds ago Up 2 seconds vigorous_gould
|
# 133261b4894a ubuntu "sleep 60s" 3 seconds ago Up 2 seconds vigorous_gould
|
||||||
|
|
||||||
$ docker run <container-id> -p 3000:8000
|
$ docker run <container-id> -p 3000:8000
|
||||||
# The -p (or --publish) flag is used to expose port 8000 inside the container to
|
# 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
|
# 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
|
# runs in isolation, hence the port 8000 where the app runs is private to the
|
||||||
# container.
|
# container.
|
||||||
|
|
||||||
$ docker run -i
|
$ docker run -i
|
||||||
# or
|
# or
|
||||||
$ docker run -it
|
$ docker run -it
|
||||||
# Docker runs our containers in a non-interactive mode i.e. they do not accept
|
# 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
|
# 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
|
# container, and the -t flag creates a pseudo-terminal that the shell can attach
|
||||||
# to (can be combined as -it)
|
# to (can be combined as -it)
|
||||||
|
|
||||||
$ docker ps -a
|
$ docker ps -a
|
||||||
# The `docker ps` command only shows running containers by default. To see all
|
# The `docker ps` command only shows running containers by default. To see all
|
||||||
# containers, use the -a (or --all) flag
|
# containers, use the -a (or --all) flag
|
||||||
# Running the above command should output something similar in the terminal:
|
# Running the above command should output something similar in the terminal:
|
||||||
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||||
# 82f84bf6912b hello-world "/hello" 9 minutes ago Exited (0) 9 minutes ago eloquent_sammet
|
# 82f84bf6912b hello-world "/hello" 9 minutes ago Exited (0) 9 minutes ago eloquent_sammet
|
||||||
|
|
||||||
|
|
||||||
$ docker stop hello-world
|
$ docker stop hello-world
|
||||||
# or
|
# or
|
||||||
$ docker start hello-world
|
$ docker start hello-world
|
||||||
# The stop command simply stops one or more containers, and the start command
|
# 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
|
# 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
|
# detached container back to the terminal i.e. runs in the foreground
|
||||||
|
|
||||||
$ docker create alpine
|
$ docker create alpine
|
||||||
# `docker create` creates a new container for us with the image specified (here,
|
# `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
|
# 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
|
# is used to set up a container configuration and then `docker start` to shoot
|
||||||
# it up when required. Note that the status is "Created":
|
# it up when required. Note that the status is "Created":
|
||||||
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||||
# 4c71c727c73d alpine "/bin/sh" 29 seconds ago Created naughty_ritchie
|
# 4c71c727c73d alpine "/bin/sh" 29 seconds ago Created naughty_ritchie
|
||||||
|
|
||||||
$ docker rm 82f84
|
$ docker rm 82f84
|
||||||
# Removes one or more containers using their container ID.
|
# 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
|
# P.S.: we can use only the first few characters of the entire ID to identify
|
||||||
# containers
|
# containers
|
||||||
|
|
||||||
$ docker images
|
$ docker images
|
||||||
# Displays all images and their information, created here means the latest image
|
# Displays all images and their information, created here means the latest image
|
||||||
# tag updated on Docker Hub:
|
# tag updated on Docker Hub:
|
||||||
# REPOSITORY TAG IMAGE ID CREATED SIZE
|
# REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||||
# ubuntu latest a8780b506fa4 9 days ago 77.8MB
|
# ubuntu latest a8780b506fa4 9 days ago 77.8MB
|
||||||
# alpine latest 9c6f07244728 3 months ago 5.54MB
|
# alpine latest 9c6f07244728 3 months ago 5.54MB
|
||||||
# hello-world latest feb5d9fea6a5 13 months ago 13.3kB
|
# hello-world latest feb5d9fea6a5 13 months ago 13.3kB
|
||||||
|
|
||||||
$ docker rmi
|
$ docker rmi
|
||||||
# Removes one or more images from your system which do not have their instances
|
# 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
|
# (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
|
# container, either delete the container first or use the -f (or --force) flag
|
||||||
# to forcefully delete both the container and image.
|
# to forcefully delete both the container and image.
|
||||||
|
|
||||||
$ docker pull busybox
|
$ docker pull busybox
|
||||||
# The pull command downloads the specified image on our system from Docker Hub.
|
# The pull command downloads the specified image on our system from Docker Hub.
|
||||||
|
|
||||||
$ docker exec -it 7b272 bash
|
$ docker exec -it 7b272 bash
|
||||||
# This command is used to run a command in the running container's default
|
# 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
|
# directory. Here 7b272 was our ubuntu container and the above command would
|
||||||
# help us interact with the container by opening a bash session.
|
# help us interact with the container by opening a bash session.
|
||||||
|
|
||||||
$ docker logs <container-id>
|
$ docker logs <container-id>
|
||||||
# Displays the information logged by the specified container
|
# Displays the information logged by the specified container
|
||||||
# root@7b27222e4bb7:/# whoami
|
# root@7b27222e4bb7:/# whoami
|
||||||
# root
|
# root
|
||||||
# root@7b27222e4bb7:/# pwd
|
# root@7b27222e4bb7:/# pwd
|
||||||
# /
|
# /
|
||||||
# root@7b27222e4bb7:/# ls
|
# root@7b27222e4bb7:/# ls
|
||||||
# bin boot dev etc home lib lib32 lib64 libx3 srv sys tmp usr var
|
# bin boot dev etc home lib lib32 lib64 libx3 srv sys tmp usr var
|
||||||
# root@7b27222e4bb7:/# exit
|
# root@7b27222e4bb7:/# exit
|
||||||
# exit
|
# exit
|
||||||
|
|
||||||
# More commands can be found at https://docs.docker.com/engine/reference/commandline/docker/
|
# More commands can be found at https://docs.docker.com/engine/reference/commandline/docker/
|
||||||
```
|
```
|
||||||
## The Dockerfile
|
## The Dockerfile
|
||||||
The Dockerfile is a blueprint of a Docker image. We can mention the artifacts
|
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
|
from our application along with their configurations into this file in the
|
||||||
specific syntax to let anyone create a Docker image of our application.
|
specific syntax to let anyone create a Docker image of our application.
|
||||||
|
|
||||||
### A few things to keep in mind:
|
### A few things to keep in mind:
|
||||||
* It is always strictly named `Dockerfile` without any extensions
|
* It is always strictly named `Dockerfile` without any extensions
|
||||||
* We have to build our custom image on top of some already available Docker base
|
* 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
|
image. (there is an empty image called `scratch` which literally lets you build
|
||||||
an image from scratch)
|
an image from scratch)
|
||||||
* All capitalised commands are part of the syntax, they are not case-sensitive
|
* All capitalised commands are part of the syntax, they are not case-sensitive
|
||||||
but used like a convention
|
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/).
|
* Below is a sample Dockerfile but you can read in depth from the [official docs](https://docs.docker.com/engine/reference/builder/).
|
||||||
|
|
||||||
```Dockerfile
|
```Dockerfile
|
||||||
FROM <base-image>
|
FROM <base-image>
|
||||||
# define base image
|
# define base image
|
||||||
|
|
||||||
ENV USERNAME='admin'\
|
ENV USERNAME='admin'\
|
||||||
PWD='****'
|
PWD='****'
|
||||||
# optionally define environmental variables
|
# optionally define environmental variables
|
||||||
|
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
# run linux commands inside container env, does not affect host env
|
# run linux commands inside container env, does not affect host env
|
||||||
# This executes during the time of image creation
|
# This executes during the time of image creation
|
||||||
|
|
||||||
COPY <src> <target>
|
COPY <src> <target>
|
||||||
# executes on the host, copies files from src (usually on the host) to target
|
# executes on the host, copies files from src (usually on the host) to target
|
||||||
# on the container
|
# on the container
|
||||||
|
|
||||||
ENTRYPOINT ["some-script.sh"]
|
ENTRYPOINT ["some-script.sh"]
|
||||||
# executes an entire script as an entrypoint
|
# executes an entire script as an entrypoint
|
||||||
|
|
||||||
CMD [<args>,...]
|
CMD [<args>,...]
|
||||||
# always part of dockerfile, introduces entry point linux command e.g.
|
# always part of dockerfile, introduces entry point linux command e.g.
|
||||||
# `CMD node server.js`
|
# `CMD node server.js`
|
||||||
# This executes after image creation only when the container from the image
|
# This executes after image creation only when the container from the image
|
||||||
# is running.
|
# is running.
|
||||||
```
|
```
|
||||||
### Build your images
|
### Build your images
|
||||||
Use the `docker build` command after wrapping your application into a Docker
|
Use the `docker build` command after wrapping your application into a Docker
|
||||||
image to run ( or build) it.
|
image to run ( or build) it.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
||||||
$ docker build <path-to-dockerfile>
|
$ docker build <path-to-dockerfile>
|
||||||
# used to build an image from the specified Dockerfile
|
# used to build an image from the specified Dockerfile
|
||||||
# instead of path we could also specify a URL
|
# instead of path we could also specify a URL
|
||||||
# -t tag is optional and used to name and tag your images for e.g.
|
# -t tag is optional and used to name and tag your images for e.g.
|
||||||
# `$ docker build -t my-image:0.1 ./home/app`
|
# `$ docker build -t my-image:0.1 ./home/app`
|
||||||
# rebuild images everytime you make changes in the dockerfile
|
# rebuild images everytime you make changes in the dockerfile
|
||||||
```
|
```
|
||||||
|
|
||||||
## Push your image to DockerHub
|
## Push your image to DockerHub
|
||||||
If you want your application's Docker image to be made publicly available for
|
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
|
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
|
registry of Docker images. Make sure you have an account with a username and
|
||||||
password on Docker Hub.
|
password on Docker Hub.
|
||||||
|
|
||||||
When pushing an image to Docker Hub, we must specify our Docker Hub username
|
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
|
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.
|
tag name of username/image-name much like GitHub repositories.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ docker login
|
$ docker login
|
||||||
# to login to Docker Hub using your username and password
|
# to login to Docker Hub using your username and password
|
||||||
|
|
||||||
$ docker tag <src-image>[:<src-tag>] <target-image>[:<target-tag>]
|
$ docker tag <src-image>[:<src-tag>] <target-image>[:<target-tag>]
|
||||||
# this tags a local src-image to a public target-image
|
# 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`
|
# e.g. `docker tag my-sample-app:1.0.0 akshitadixit/my-sample-app`
|
||||||
# if tags are not specified, they're defaulted to `latest`
|
# if tags are not specified, they're defaulted to `latest`
|
||||||
|
|
||||||
$ docker push <target-image>[:<target-tag>]
|
$ docker push <target-image>[:<target-tag>]
|
||||||
# uploads our image to Docker Hub
|
# uploads our image to Docker Hub
|
||||||
# e.g. `docker push akshitadixit/my-sample-app`
|
# e.g. `docker push akshitadixit/my-sample-app`
|
||||||
# this image will be accessible under your profile's repositories as
|
# this image will be accessible under your profile's repositories as
|
||||||
# `https://hub.docker.com/r/username/image-name`
|
# `https://hub.docker.com/r/username/image-name`
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@@ -1,167 +1,167 @@
|
|||||||
---
|
---
|
||||||
language: docker
|
language: docker
|
||||||
filename: docker-es.bat
|
filename: docker-es.bat
|
||||||
contributors:
|
contributors:
|
||||||
- ["Ruslan López", "http://javapro.org/"]
|
- ["Ruslan López", "http://javapro.org/"]
|
||||||
- ["Michael Chen", "https://github.com/ML-Chen"]
|
- ["Michael Chen", "https://github.com/ML-Chen"]
|
||||||
lang: es-es
|
lang: es-es
|
||||||
---
|
---
|
||||||
|
|
||||||
```bat
|
```bat
|
||||||
:: descargar, instalar y ejecutar la imágen del hola mundo
|
:: descargar, instalar y ejecutar la imágen del hola mundo
|
||||||
docker run hello-world
|
docker run hello-world
|
||||||
|
|
||||||
:: Si esta es la primera vez, deberíais de poder ver el mensaje
|
:: Si esta es la primera vez, deberíais de poder ver el mensaje
|
||||||
:: Unable to find image 'hello-world:latest' locally
|
:: Unable to find image 'hello-world:latest' locally
|
||||||
:: latest: Pulling from library/hello-world
|
:: latest: Pulling from library/hello-world
|
||||||
:: 1b930d010525: Pull complete
|
:: 1b930d010525: Pull complete
|
||||||
:: Digest: sha256:4fe721ccc2e8dc7362278a29dc660d833570ec2682f4e4194f4ee23e415e1064
|
:: Digest: sha256:4fe721ccc2e8dc7362278a29dc660d833570ec2682f4e4194f4ee23e415e1064
|
||||||
:: Status: Downloaded newer image for hello-world:latest
|
:: Status: Downloaded newer image for hello-world:latest
|
||||||
::
|
::
|
||||||
:: Hello from Docker!
|
:: Hello from Docker!
|
||||||
:: This message shows that your installation appears to be working correctly.
|
:: This message shows that your installation appears to be working correctly.
|
||||||
::
|
::
|
||||||
:: To generate this message, Docker took the following steps:
|
:: To generate this message, Docker took the following steps:
|
||||||
:: 1. The Docker client contacted the Docker daemon.
|
:: 1. The Docker client contacted the Docker daemon.
|
||||||
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
||||||
:: (amd64)
|
:: (amd64)
|
||||||
:: 3. The Docker daemon created a new container from that image which runs the
|
:: 3. The Docker daemon created a new container from that image which runs the
|
||||||
:: executable that produces the output you are currently reading.
|
:: executable that produces the output you are currently reading.
|
||||||
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
|
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
|
||||||
:: to your terminal.
|
:: to your terminal.
|
||||||
::
|
::
|
||||||
:: To try something more ambitious, you can run an Ubuntu container with:
|
:: To try something more ambitious, you can run an Ubuntu container with:
|
||||||
:: $ docker run -it ubuntu bash
|
:: $ docker run -it ubuntu bash
|
||||||
::
|
::
|
||||||
:: Share images, automate workflows, and more with a free Docker ID:
|
:: Share images, automate workflows, and more with a free Docker ID:
|
||||||
:: https://hub.docker.com/
|
:: https://hub.docker.com/
|
||||||
::
|
::
|
||||||
:: For more examples and ideas, visit:
|
:: For more examples and ideas, visit:
|
||||||
:: https://docs.docker.com/get-started/
|
:: https://docs.docker.com/get-started/
|
||||||
:: El susodicho mensaje se podría traducir como:
|
:: El susodicho mensaje se podría traducir como:
|
||||||
::
|
::
|
||||||
:: Hola desde Docker!
|
:: Hola desde Docker!
|
||||||
:: Este mensaje muestra que su instalación parece estar funcionando crrectamente.
|
:: Este mensaje muestra que su instalación parece estar funcionando crrectamente.
|
||||||
::
|
::
|
||||||
:: Para generar este mensaje, Docker realizó los siguientes pasos:
|
:: Para generar este mensaje, Docker realizó los siguientes pasos:
|
||||||
:: 1. El cliente de Docker contactó a Docker daemon.
|
:: 1. El cliente de Docker contactó a Docker daemon.
|
||||||
:: 2. El Docker daemon obtubo la imágen "hello-world" desde Docker Hub.
|
:: 2. El Docker daemon obtubo la imágen "hello-world" desde Docker Hub.
|
||||||
:: (amd64)
|
:: (amd64)
|
||||||
:: 3. El Docker daemon creó un nuevo contenedor a partir de esa imagen con la cual ejecuta el
|
:: 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.
|
:: ejecutable que produce la salida que estás leyendo.
|
||||||
:: 4. El Docker daemon transmitió dicha salida el cliente Docker, el cual
|
:: 4. El Docker daemon transmitió dicha salida el cliente Docker, el cual
|
||||||
:: la envió a tu terminal.
|
:: la envió a tu terminal.
|
||||||
::
|
::
|
||||||
:: Para intentar algo más ambicioso, puede correr un contenedor Ubuntu mediante:
|
:: Para intentar algo más ambicioso, puede correr un contenedor Ubuntu mediante:
|
||||||
:: $ docker run -it ubuntu bash
|
:: $ docker run -it ubuntu bash
|
||||||
::
|
::
|
||||||
:: Comparte imágenes, automatice flujos y más con un Docker ID gratuito:
|
:: Comparte imágenes, automatice flujos y más con un Docker ID gratuito:
|
||||||
:: https://hub.docker.com/
|
:: https://hub.docker.com/
|
||||||
|
|
||||||
:: ahora veamos las imágenes que se están ejecutando actualmente
|
:: ahora veamos las imágenes que se están ejecutando actualmente
|
||||||
docker ps
|
docker ps
|
||||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||||
:: NAMES
|
:: NAMES
|
||||||
|
|
||||||
:: veamos las imágenes que hemos ejecutado previamente
|
:: veamos las imágenes que hemos ejecutado previamente
|
||||||
docker ps -a
|
docker ps -a
|
||||||
|
|
||||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||||
:: NAMES
|
:: NAMES
|
||||||
:: 4a76281f9c53 hello-world "/hello" 2 minutes ago Exited (0) 2 minutes ago
|
:: 4a76281f9c53 hello-world "/hello" 2 minutes ago Exited (0) 2 minutes ago
|
||||||
:: happy_poincare
|
:: happy_poincare
|
||||||
:: la parte del nombre se genera automáticamente, así que probablemente sea diferente para vos
|
:: la parte del nombre se genera automáticamente, así que probablemente sea diferente para vos
|
||||||
|
|
||||||
:: eliminemos nuestra imagen previamente generada
|
:: eliminemos nuestra imagen previamente generada
|
||||||
docker rm happy_poincare
|
docker rm happy_poincare
|
||||||
|
|
||||||
:: verifiquemos si realmente fue borrada
|
:: verifiquemos si realmente fue borrada
|
||||||
docker ps -a
|
docker ps -a
|
||||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||||
:: NAMES
|
:: NAMES
|
||||||
|
|
||||||
:: especifiquemos un nombre personalizado para el contenedor
|
:: especifiquemos un nombre personalizado para el contenedor
|
||||||
docker run --name test_container hello-world
|
docker run --name test_container hello-world
|
||||||
:: Hello from Docker!
|
:: Hello from Docker!
|
||||||
:: This message shows that your installation appears to be working correctly.
|
:: This message shows that your installation appears to be working correctly.
|
||||||
::
|
::
|
||||||
:: To generate this message, Docker took the following steps:
|
:: To generate this message, Docker took the following steps:
|
||||||
:: 1. The Docker client contacted the Docker daemon.
|
:: 1. The Docker client contacted the Docker daemon.
|
||||||
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
||||||
:: (amd64)
|
:: (amd64)
|
||||||
:: 3. The Docker daemon created a new container from that image which runs the
|
:: 3. The Docker daemon created a new container from that image which runs the
|
||||||
:: executable that produces the output you are currently reading.
|
:: executable that produces the output you are currently reading.
|
||||||
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
|
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
|
||||||
:: to your terminal.
|
:: to your terminal.
|
||||||
::
|
::
|
||||||
:: To try something more ambitious, you can run an Ubuntu container with:
|
:: To try something more ambitious, you can run an Ubuntu container with:
|
||||||
:: $ docker run -it ubuntu bash
|
:: $ docker run -it ubuntu bash
|
||||||
::
|
::
|
||||||
:: Share images, automate workflows, and more with a free Docker ID:
|
:: Share images, automate workflows, and more with a free Docker ID:
|
||||||
:: https://hub.docker.com/
|
:: https://hub.docker.com/
|
||||||
::
|
::
|
||||||
:: For more examples and ideas, visit:
|
:: For more examples and ideas, visit:
|
||||||
:: https://docs.docker.com/get-started/
|
:: https://docs.docker.com/get-started/
|
||||||
|
|
||||||
docker ps -a
|
docker ps -a
|
||||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||||
:: NAMES
|
:: NAMES
|
||||||
:: d345fe1a4f41 hello-world "/hello" About a minute ago Exited (0) About a minute ago
|
:: d345fe1a4f41 hello-world "/hello" About a minute ago Exited (0) About a minute ago
|
||||||
:: test_container
|
:: test_container
|
||||||
:: tal como podeis ver el nombre es el que especificamos
|
:: tal como podeis ver el nombre es el que especificamos
|
||||||
|
|
||||||
:: obtener los registros de un contenedor nombrado
|
:: obtener los registros de un contenedor nombrado
|
||||||
docker logs test_container
|
docker logs test_container
|
||||||
:: Hello from Docker!
|
:: Hello from Docker!
|
||||||
:: This message shows that your installation appears to be working correctly.
|
:: This message shows that your installation appears to be working correctly.
|
||||||
::
|
::
|
||||||
:: To generate this message, Docker took the following steps:
|
:: To generate this message, Docker took the following steps:
|
||||||
:: 1. The Docker client contacted the Docker daemon.
|
:: 1. The Docker client contacted the Docker daemon.
|
||||||
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
||||||
:: (amd64)
|
:: (amd64)
|
||||||
:: 3. The Docker daemon created a new container from that image which runs the
|
:: 3. The Docker daemon created a new container from that image which runs the
|
||||||
:: executable that produces the output you are currently reading.
|
:: executable that produces the output you are currently reading.
|
||||||
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
|
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
|
||||||
:: to your terminal.
|
:: to your terminal.
|
||||||
::
|
::
|
||||||
:: To try something more ambitious, you can run an Ubuntu container with:
|
:: To try something more ambitious, you can run an Ubuntu container with:
|
||||||
:: $ docker run -it ubuntu bash
|
:: $ docker run -it ubuntu bash
|
||||||
::
|
::
|
||||||
:: Share images, automate workflows, and more with a free Docker ID:
|
:: Share images, automate workflows, and more with a free Docker ID:
|
||||||
:: https://hub.docker.com/
|
:: https://hub.docker.com/
|
||||||
::
|
::
|
||||||
:: For more examples and ideas, visit:
|
:: For more examples and ideas, visit:
|
||||||
:: https://docs.docker.com/get-started/
|
:: https://docs.docker.com/get-started/
|
||||||
|
|
||||||
docker rm test_container
|
docker rm test_container
|
||||||
|
|
||||||
docker run ubuntu
|
docker run ubuntu
|
||||||
:: Unable to find image 'ubuntu:latest' locally
|
:: Unable to find image 'ubuntu:latest' locally
|
||||||
:: latest: Pulling from library/ubuntu
|
:: latest: Pulling from library/ubuntu
|
||||||
:: 2746a4a261c9: Pull complete
|
:: 2746a4a261c9: Pull complete
|
||||||
:: 4c1d20cdee96: Pull complete 0d3160e1d0de: Pull complete c8e37668deea: Pull complete Digest: sha256:250cc6f3f3ffc5cdaa9d8f4946ac79821aafb4d3afc93928f0de9336eba21aa4
|
:: 4c1d20cdee96: Pull complete 0d3160e1d0de: Pull complete c8e37668deea: Pull complete Digest: sha256:250cc6f3f3ffc5cdaa9d8f4946ac79821aafb4d3afc93928f0de9336eba21aa4
|
||||||
:: Status: Downloaded newer image for ubuntu:latest
|
:: Status: Downloaded newer image for ubuntu:latest
|
||||||
|
|
||||||
docker ps -a
|
docker ps -a
|
||||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||||
:: NAMES
|
:: NAMES
|
||||||
:: c19e9e5b000a ubuntu "/bin/bash" 5 seconds ago Exited (0) 4 seconds ago
|
:: c19e9e5b000a ubuntu "/bin/bash" 5 seconds ago Exited (0) 4 seconds ago
|
||||||
:: relaxed_nobel
|
:: relaxed_nobel
|
||||||
|
|
||||||
:: ejecutando un contenedor en modo interactivo
|
:: ejecutando un contenedor en modo interactivo
|
||||||
docker run -it ubuntu
|
docker run -it ubuntu
|
||||||
:: root@e2cac48323d2:/# uname
|
:: root@e2cac48323d2:/# uname
|
||||||
:: Linux
|
:: Linux
|
||||||
:: root@e2cac48323d2:/# exit
|
:: root@e2cac48323d2:/# exit
|
||||||
:: exit
|
:: exit
|
||||||
|
|
||||||
docker rm relaxed_nobel
|
docker rm relaxed_nobel
|
||||||
|
|
||||||
docker ps -a
|
docker ps -a
|
||||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||||
:: NAMES
|
:: NAMES
|
||||||
:: e2cac48323d2 ubuntu "/bin/bash" 2 minutes ago Exited (0) About a minute ago
|
:: e2cac48323d2 ubuntu "/bin/bash" 2 minutes ago Exited (0) About a minute ago
|
||||||
:: nifty_goldwasser
|
:: nifty_goldwasser
|
||||||
|
|
||||||
docker rm nifty_goldwasser
|
docker rm nifty_goldwasser
|
||||||
```
|
```
|
||||||
|
@@ -1,276 +1,276 @@
|
|||||||
---
|
---
|
||||||
language: toml
|
language: toml
|
||||||
filename: learntoml-it.toml
|
filename: learntoml-it.toml
|
||||||
contributors:
|
contributors:
|
||||||
- ["Alois de Gouvello", "https://github.com/aloisdg"]
|
- ["Alois de Gouvello", "https://github.com/aloisdg"]
|
||||||
translators:
|
translators:
|
||||||
- ["Christian Grasso", "https://grasso.io"]
|
- ["Christian Grasso", "https://grasso.io"]
|
||||||
lang: it-it
|
lang: it-it
|
||||||
---
|
---
|
||||||
|
|
||||||
TOML è l'acronimo di _Tom's Obvious, Minimal Language_. È un linguaggio per la
|
TOML è l'acronimo di _Tom's Obvious, Minimal Language_. È un linguaggio per la
|
||||||
serializzazione di dati, progettato per i file di configurazione.
|
serializzazione di dati, progettato per i file di configurazione.
|
||||||
|
|
||||||
È un'alternativa a linguaggi come YAML e JSON, che punta ad essere più leggibile
|
È 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
|
per le persone. Allo stesso tempo, TOML può essere utilizzato in modo abbastanza
|
||||||
semplice nella maggior parte dei linguaggi di programmazione, in quanto è
|
semplice nella maggior parte dei linguaggi di programmazione, in quanto è
|
||||||
progettato per essere tradotto senza ambiguità in una hash table.
|
progettato per essere tradotto senza ambiguità in una hash table.
|
||||||
|
|
||||||
Tieni presente che TOML è ancora in fase di sviluppo, e la sua specifica non è
|
Tieni presente che TOML è ancora in fase di sviluppo, e la sua specifica non è
|
||||||
ancora stabile. Questo documento utilizza TOML 0.4.0.
|
ancora stabile. Questo documento utilizza TOML 0.4.0.
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
# I commenti in TOML sono fatti così.
|
# I commenti in TOML sono fatti così.
|
||||||
|
|
||||||
################
|
################
|
||||||
# TIPI SCALARI #
|
# TIPI SCALARI #
|
||||||
################
|
################
|
||||||
|
|
||||||
# Il nostro oggetto root (corrispondente all'intero documento) sarà una mappa,
|
# Il nostro oggetto root (corrispondente all'intero documento) sarà una mappa,
|
||||||
# anche chiamata dizionario, hash o oggetto in altri linguaggi.
|
# anche chiamata dizionario, hash o oggetto in altri linguaggi.
|
||||||
|
|
||||||
# La key, il simbolo di uguale e il valore devono trovarsi sulla stessa riga,
|
# La key, il simbolo di uguale e il valore devono trovarsi sulla stessa riga,
|
||||||
# eccetto per alcuni tipi di valori.
|
# eccetto per alcuni tipi di valori.
|
||||||
key = "value"
|
key = "value"
|
||||||
stringa = "ciao"
|
stringa = "ciao"
|
||||||
numero = 42
|
numero = 42
|
||||||
float = 3.14
|
float = 3.14
|
||||||
boolean = true
|
boolean = true
|
||||||
data = 1979-05-27T07:32:00-08:00
|
data = 1979-05-27T07:32:00-08:00
|
||||||
notazScientifica = 1e+12
|
notazScientifica = 1e+12
|
||||||
"puoi utilizzare le virgolette per la key" = true # Puoi usare " oppure '
|
"puoi utilizzare le virgolette per la key" = true # Puoi usare " oppure '
|
||||||
"la key può contenere" = "lettere, numeri, underscore e trattini"
|
"la key può contenere" = "lettere, numeri, underscore e trattini"
|
||||||
|
|
||||||
############
|
############
|
||||||
# Stringhe #
|
# Stringhe #
|
||||||
############
|
############
|
||||||
|
|
||||||
# Le stringhe possono contenere solo caratteri UTF-8 validi.
|
# Le stringhe possono contenere solo caratteri UTF-8 validi.
|
||||||
# Possiamo effettuare l'escape dei caratteri, e alcuni hanno delle sequenze
|
# Possiamo effettuare l'escape dei caratteri, e alcuni hanno delle sequenze
|
||||||
# di escape compatte. Ad esempio, \t corrisponde al TAB.
|
# di escape compatte. Ad esempio, \t corrisponde al TAB.
|
||||||
stringaSemplice = "Racchiusa tra virgolette. \"Usa il backslash per l'escape\"."
|
stringaSemplice = "Racchiusa tra virgolette. \"Usa il backslash per l'escape\"."
|
||||||
|
|
||||||
stringaMultiriga = """
|
stringaMultiriga = """
|
||||||
Racchiusa da tre virgolette doppie all'inizio e
|
Racchiusa da tre virgolette doppie all'inizio e
|
||||||
alla fine - consente di andare a capo."""
|
alla fine - consente di andare a capo."""
|
||||||
|
|
||||||
stringaLiteral = 'Virgolette singole. Non consente di effettuare escape.'
|
stringaLiteral = 'Virgolette singole. Non consente di effettuare escape.'
|
||||||
|
|
||||||
stringaMultirigaLiteral = '''
|
stringaMultirigaLiteral = '''
|
||||||
Racchiusa da tre virgolette singole all'inizio e
|
Racchiusa da tre virgolette singole all'inizio e
|
||||||
alla fine - consente di andare a capo.
|
alla fine - consente di andare a capo.
|
||||||
Anche in questo caso non si può fare escape.
|
Anche in questo caso non si può fare escape.
|
||||||
Il primo ritorno a capo viene eliminato.
|
Il primo ritorno a capo viene eliminato.
|
||||||
Tutti gli altri spazi aggiuntivi
|
Tutti gli altri spazi aggiuntivi
|
||||||
vengono mantenuti.
|
vengono mantenuti.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# Per i dati binari è consigliabile utilizzare Base64 e
|
# Per i dati binari è consigliabile utilizzare Base64 e
|
||||||
# gestirli manualmente dall'applicazione.
|
# gestirli manualmente dall'applicazione.
|
||||||
|
|
||||||
##########
|
##########
|
||||||
# Interi #
|
# Interi #
|
||||||
##########
|
##########
|
||||||
|
|
||||||
## Gli interi possono avere o meno un segno (+, -).
|
## Gli interi possono avere o meno un segno (+, -).
|
||||||
## Non si possono inserire zero superflui all'inizio.
|
## Non si possono inserire zero superflui all'inizio.
|
||||||
## Non è possibile inoltre utilizzare valori numerici
|
## Non è possibile inoltre utilizzare valori numerici
|
||||||
## non rappresentabili con una sequenza di cifre.
|
## non rappresentabili con una sequenza di cifre.
|
||||||
int1 = +42
|
int1 = +42
|
||||||
int2 = 0
|
int2 = 0
|
||||||
int3 = -21
|
int3 = -21
|
||||||
|
|
||||||
## Puoi utilizzare gli underscore per migliorare la leggibilità.
|
## Puoi utilizzare gli underscore per migliorare la leggibilità.
|
||||||
## Fai attenzione a non inserirne due di seguito.
|
## Fai attenzione a non inserirne due di seguito.
|
||||||
int4 = 5_349_221
|
int4 = 5_349_221
|
||||||
int5 = 1_2_3_4_5 # VALIDO, ma da evitare
|
int5 = 1_2_3_4_5 # VALIDO, ma da evitare
|
||||||
|
|
||||||
#########
|
#########
|
||||||
# Float #
|
# Float #
|
||||||
#########
|
#########
|
||||||
|
|
||||||
# I float permettono di rappresentare numeri decimali.
|
# I float permettono di rappresentare numeri decimali.
|
||||||
flt1 = 3.1415
|
flt1 = 3.1415
|
||||||
flt2 = -5e6
|
flt2 = -5e6
|
||||||
flt3 = 6.626E-34
|
flt3 = 6.626E-34
|
||||||
|
|
||||||
###########
|
###########
|
||||||
# Boolean #
|
# Boolean #
|
||||||
###########
|
###########
|
||||||
|
|
||||||
# I valori boolean (true/false) devono essere scritti in minuscolo.
|
# I valori boolean (true/false) devono essere scritti in minuscolo.
|
||||||
bool1 = true
|
bool1 = true
|
||||||
bool2 = false
|
bool2 = false
|
||||||
|
|
||||||
############
|
############
|
||||||
# Data/ora #
|
# Data/ora #
|
||||||
############
|
############
|
||||||
|
|
||||||
data1 = 1979-05-27T07:32:00Z # Specifica RFC 3339/ISO 8601 (UTC)
|
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
|
data2 = 1979-05-26T15:32:00+08:00 # RFC 3339/ISO 8601 con offset
|
||||||
|
|
||||||
######################
|
######################
|
||||||
# TIPI DI COLLECTION #
|
# TIPI DI COLLECTION #
|
||||||
######################
|
######################
|
||||||
|
|
||||||
#########
|
#########
|
||||||
# Array #
|
# Array #
|
||||||
#########
|
#########
|
||||||
|
|
||||||
array1 = [ 1, 2, 3 ]
|
array1 = [ 1, 2, 3 ]
|
||||||
array2 = [ "Le", "virgole", "sono", "delimitatori" ]
|
array2 = [ "Le", "virgole", "sono", "delimitatori" ]
|
||||||
array3 = [ "Non", "unire", "tipi", "diversi" ]
|
array3 = [ "Non", "unire", "tipi", "diversi" ]
|
||||||
array4 = [ "tutte", 'le stringhe', """hanno lo stesso""", '''tipo''' ]
|
array4 = [ "tutte", 'le stringhe', """hanno lo stesso""", '''tipo''' ]
|
||||||
array5 = [
|
array5 = [
|
||||||
"Gli spazi vuoti", "sono", "ignorati"
|
"Gli spazi vuoti", "sono", "ignorati"
|
||||||
]
|
]
|
||||||
|
|
||||||
###########
|
###########
|
||||||
# Tabelle #
|
# Tabelle #
|
||||||
###########
|
###########
|
||||||
|
|
||||||
# Le tabelle (o hash table o dizionari) sono collection di coppie key/value.
|
# Le tabelle (o hash table o dizionari) sono collection di coppie key/value.
|
||||||
# Iniziano con un nome tra parentesi quadre su una linea separata.
|
# Iniziano con un nome tra parentesi quadre su una linea separata.
|
||||||
# Le tabelle vuote (senza alcun valore) sono valide.
|
# Le tabelle vuote (senza alcun valore) sono valide.
|
||||||
[tabella]
|
[tabella]
|
||||||
|
|
||||||
# Tutti i valori che si trovano sotto il nome della tabella
|
# Tutti i valori che si trovano sotto il nome della tabella
|
||||||
# appartengono alla tabella stessa (finchè non ne viene creata un'altra).
|
# appartengono alla tabella stessa (finchè non ne viene creata un'altra).
|
||||||
# L'ordine di questi valori non è garantito.
|
# L'ordine di questi valori non è garantito.
|
||||||
[tabella-1]
|
[tabella-1]
|
||||||
key1 = "una stringa"
|
key1 = "una stringa"
|
||||||
key2 = 123
|
key2 = 123
|
||||||
|
|
||||||
[tabella-2]
|
[tabella-2]
|
||||||
key1 = "un'altra stringa"
|
key1 = "un'altra stringa"
|
||||||
key2 = 456
|
key2 = 456
|
||||||
|
|
||||||
# Utilizzando i punti è possibile creare delle sottotabelle.
|
# Utilizzando i punti è possibile creare delle sottotabelle.
|
||||||
# Ogni parte suddivisa dai punti segue le regole delle key per il nome.
|
# Ogni parte suddivisa dai punti segue le regole delle key per il nome.
|
||||||
[tabella-3."sotto.tabella"]
|
[tabella-3."sotto.tabella"]
|
||||||
key1 = "prova"
|
key1 = "prova"
|
||||||
|
|
||||||
# Ecco l'equivalente JSON della tabella precedente:
|
# Ecco l'equivalente JSON della tabella precedente:
|
||||||
# { "tabella-3": { "sotto.tabella": { "key1": "prova" } } }
|
# { "tabella-3": { "sotto.tabella": { "key1": "prova" } } }
|
||||||
|
|
||||||
# Gli spazi non vengono considerati, ma è consigliabile
|
# Gli spazi non vengono considerati, ma è consigliabile
|
||||||
# evitare di usare spazi superflui.
|
# evitare di usare spazi superflui.
|
||||||
[a.b.c] # consigliato
|
[a.b.c] # consigliato
|
||||||
[ d.e.f ] # identico a [d.e.f]
|
[ d.e.f ] # identico a [d.e.f]
|
||||||
|
|
||||||
# Non c'è bisogno di creare le tabelle superiori per creare una sottotabella.
|
# Non c'è bisogno di creare le tabelle superiori per creare una sottotabella.
|
||||||
# [x] queste
|
# [x] queste
|
||||||
# [x.y] non
|
# [x.y] non
|
||||||
# [x.y.z] servono
|
# [x.y.z] servono
|
||||||
[x.y.z.w] # per creare questa tabella
|
[x.y.z.w] # per creare questa tabella
|
||||||
|
|
||||||
# Se non è stata già creata prima, puoi anche creare
|
# Se non è stata già creata prima, puoi anche creare
|
||||||
# una tabella superiore più avanti.
|
# una tabella superiore più avanti.
|
||||||
[a.b]
|
[a.b]
|
||||||
c = 1
|
c = 1
|
||||||
|
|
||||||
[a]
|
[a]
|
||||||
d = 2
|
d = 2
|
||||||
|
|
||||||
# Non puoi definire una key o una tabella più di una volta.
|
# Non puoi definire una key o una tabella più di una volta.
|
||||||
|
|
||||||
# ERRORE
|
# ERRORE
|
||||||
[a]
|
[a]
|
||||||
b = 1
|
b = 1
|
||||||
|
|
||||||
[a]
|
[a]
|
||||||
c = 2
|
c = 2
|
||||||
|
|
||||||
# ERRORE
|
# ERRORE
|
||||||
[a]
|
[a]
|
||||||
b = 1
|
b = 1
|
||||||
|
|
||||||
[a.b]
|
[a.b]
|
||||||
c = 2
|
c = 2
|
||||||
|
|
||||||
# I nomi delle tabelle non possono essere vuoti.
|
# I nomi delle tabelle non possono essere vuoti.
|
||||||
[] # NON VALIDO
|
[] # NON VALIDO
|
||||||
[a.] # NON VALIDO
|
[a.] # NON VALIDO
|
||||||
[a..b] # NON VALIDO
|
[a..b] # NON VALIDO
|
||||||
[.b] # NON VALIDO
|
[.b] # NON VALIDO
|
||||||
[.] # NON VALIDO
|
[.] # NON VALIDO
|
||||||
|
|
||||||
##################
|
##################
|
||||||
# Tabelle inline #
|
# Tabelle inline #
|
||||||
##################
|
##################
|
||||||
|
|
||||||
tabelleInline = { racchiuseData = "{ e }", rigaSingola = true }
|
tabelleInline = { racchiuseData = "{ e }", rigaSingola = true }
|
||||||
punto = { x = 1, y = 2 }
|
punto = { x = 1, y = 2 }
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# Array di tabelle #
|
# Array di tabelle #
|
||||||
####################
|
####################
|
||||||
|
|
||||||
# Un array di tabelle può essere creato utilizzando due parentesi quadre.
|
# Un array di tabelle può essere creato utilizzando due parentesi quadre.
|
||||||
# Tutte le tabelle con questo nome saranno elementi dell'array.
|
# Tutte le tabelle con questo nome saranno elementi dell'array.
|
||||||
# Gli elementi vengono inseriti nell'ordine in cui si trovano.
|
# Gli elementi vengono inseriti nell'ordine in cui si trovano.
|
||||||
|
|
||||||
[[prodotti]]
|
[[prodotti]]
|
||||||
nome = "array di tabelle"
|
nome = "array di tabelle"
|
||||||
sku = 738594937
|
sku = 738594937
|
||||||
tabelleVuoteValide = true
|
tabelleVuoteValide = true
|
||||||
|
|
||||||
[[prodotti]]
|
[[prodotti]]
|
||||||
|
|
||||||
[[prodotti]]
|
[[prodotti]]
|
||||||
nome = "un altro item"
|
nome = "un altro item"
|
||||||
sku = 284758393
|
sku = 284758393
|
||||||
colore = "grigio"
|
colore = "grigio"
|
||||||
|
|
||||||
# Puoi anche creare array di tabelle nested. Le sottotabelle con doppie
|
# Puoi anche creare array di tabelle nested. Le sottotabelle con doppie
|
||||||
# parentesi quadre apparterranno alla tabella più vicina sopra di esse.
|
# parentesi quadre apparterranno alla tabella più vicina sopra di esse.
|
||||||
|
|
||||||
[[frutta]]
|
[[frutta]]
|
||||||
nome = "mela"
|
nome = "mela"
|
||||||
|
|
||||||
[frutto.geometria]
|
[frutto.geometria]
|
||||||
forma = "sferica"
|
forma = "sferica"
|
||||||
nota = "Sono una proprietà del frutto"
|
nota = "Sono una proprietà del frutto"
|
||||||
|
|
||||||
[[frutto.colore]]
|
[[frutto.colore]]
|
||||||
nome = "rosso"
|
nome = "rosso"
|
||||||
nota = "Sono un oggetto di un array dentro mela"
|
nota = "Sono un oggetto di un array dentro mela"
|
||||||
|
|
||||||
[[frutto.colore]]
|
[[frutto.colore]]
|
||||||
nome = "verde"
|
nome = "verde"
|
||||||
nota = "Sono nello stesso array di rosso"
|
nota = "Sono nello stesso array di rosso"
|
||||||
|
|
||||||
[[frutta]]
|
[[frutta]]
|
||||||
nome = "banana"
|
nome = "banana"
|
||||||
|
|
||||||
[[frutto.colore]]
|
[[frutto.colore]]
|
||||||
nome = "giallo"
|
nome = "giallo"
|
||||||
nota = "Anche io sono un oggetto di un array, ma dentro banana"
|
nota = "Anche io sono un oggetto di un array, ma dentro banana"
|
||||||
```
|
```
|
||||||
|
|
||||||
Ecco l'equivalente JSON dell'ultima tabella:
|
Ecco l'equivalente JSON dell'ultima tabella:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"frutta": [
|
"frutta": [
|
||||||
{
|
{
|
||||||
"nome": "mela",
|
"nome": "mela",
|
||||||
"geometria": { "forma": "sferica", "nota": "..."},
|
"geometria": { "forma": "sferica", "nota": "..."},
|
||||||
"colore": [
|
"colore": [
|
||||||
{ "nome": "rosso", "nota": "..." },
|
{ "nome": "rosso", "nota": "..." },
|
||||||
{ "nome": "verde", "nota": "..." }
|
{ "nome": "verde", "nota": "..." }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"nome": "banana",
|
"nome": "banana",
|
||||||
"colore": [
|
"colore": [
|
||||||
{ "nome": "giallo", "nota": "..." }
|
{ "nome": "giallo", "nota": "..." }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Altre risorse
|
### Altre risorse
|
||||||
|
|
||||||
+ [Repository ufficiale di TOML](https://github.com/toml-lang/toml)
|
+ [Repository ufficiale di TOML](https://github.com/toml-lang/toml)
|
||||||
|
@@ -1,246 +1,246 @@
|
|||||||
---
|
---
|
||||||
category: tool
|
category: tool
|
||||||
tool: make
|
tool: make
|
||||||
contributors:
|
contributors:
|
||||||
- ["Robert Steed", "https://github.com/robochat"]
|
- ["Robert Steed", "https://github.com/robochat"]
|
||||||
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
|
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
|
||||||
filename: Makefile
|
filename: Makefile
|
||||||
---
|
---
|
||||||
|
|
||||||
A Makefile defines a graph of rules for creating a target (or targets).
|
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
|
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
|
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
|
weekend by Stuart Feldman in 1976, it is still widely used (particularly
|
||||||
on Unix and Linux) despite many competitors and criticisms.
|
on Unix and Linux) despite many competitors and criticisms.
|
||||||
|
|
||||||
There are many varieties of make in existence, however this article
|
There are many varieties of make in existence, however this article
|
||||||
assumes that we are using GNU make which is the standard on Linux.
|
assumes that we are using GNU make which is the standard on Linux.
|
||||||
|
|
||||||
```make
|
```make
|
||||||
|
|
||||||
# Comments can be written like this.
|
# Comments can be written like this.
|
||||||
|
|
||||||
# File should be named Makefile and then can be run as `make <target>`.
|
# File should be named Makefile and then can be run as `make <target>`.
|
||||||
# Otherwise we use `make -f "filename" <target>`.
|
# Otherwise we use `make -f "filename" <target>`.
|
||||||
|
|
||||||
# Warning - only use TABS to indent in Makefiles, never spaces!
|
# Warning - only use TABS to indent in Makefiles, never spaces!
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Basics
|
# Basics
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# Rules are of the format
|
# Rules are of the format
|
||||||
# target: <prerequisite>
|
# target: <prerequisite>
|
||||||
# where prerequisites are optional.
|
# where prerequisites are optional.
|
||||||
|
|
||||||
# A rule - this rule will only run if file0.txt doesn't exist.
|
# A rule - this rule will only run if file0.txt doesn't exist.
|
||||||
file0.txt:
|
file0.txt:
|
||||||
echo "foo" > file0.txt
|
echo "foo" > file0.txt
|
||||||
# Even comments in these 'recipe' sections get passed to the shell.
|
# Even comments in these 'recipe' sections get passed to the shell.
|
||||||
# Try `make file0.txt` or simply `make` - first rule is the default.
|
# 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.
|
# This rule will only run if file0.txt is newer than file1.txt.
|
||||||
file1.txt: file0.txt
|
file1.txt: file0.txt
|
||||||
cat file0.txt > file1.txt
|
cat file0.txt > file1.txt
|
||||||
# use the same quoting rules as in the shell.
|
# use the same quoting rules as in the shell.
|
||||||
@cat file0.txt >> file1.txt
|
@cat file0.txt >> file1.txt
|
||||||
# @ stops the command from being echoed to stdout.
|
# @ stops the command from being echoed to stdout.
|
||||||
-@echo 'hello'
|
-@echo 'hello'
|
||||||
# - means that make will keep going in the case of an error.
|
# - means that make will keep going in the case of an error.
|
||||||
# Try `make file1.txt` on the commandline.
|
# Try `make file1.txt` on the commandline.
|
||||||
|
|
||||||
# A rule can have multiple targets and multiple prerequisites
|
# A rule can have multiple targets and multiple prerequisites
|
||||||
file2.txt file3.txt: file0.txt file1.txt
|
file2.txt file3.txt: file0.txt file1.txt
|
||||||
touch file2.txt
|
touch file2.txt
|
||||||
touch file3.txt
|
touch file3.txt
|
||||||
|
|
||||||
# Make will complain about multiple recipes for the same rule. Empty
|
# Make will complain about multiple recipes for the same rule. Empty
|
||||||
# recipes don't count though and can be used to add new dependencies.
|
# recipes don't count though and can be used to add new dependencies.
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Phony Targets
|
# Phony Targets
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# A phony target. Any target that isn't a file.
|
# 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.
|
# It will never be up to date so make will always try to run it.
|
||||||
all: maker process
|
all: maker process
|
||||||
|
|
||||||
# We can declare things out of order.
|
# We can declare things out of order.
|
||||||
maker:
|
maker:
|
||||||
touch ex0.txt ex1.txt
|
touch ex0.txt ex1.txt
|
||||||
|
|
||||||
# Can avoid phony rules breaking when a real file has the same name by
|
# Can avoid phony rules breaking when a real file has the same name by
|
||||||
.PHONY: all maker process
|
.PHONY: all maker process
|
||||||
# This is a special target. There are several others.
|
# This is a special target. There are several others.
|
||||||
|
|
||||||
# A rule with a dependency on a phony target will always run
|
# A rule with a dependency on a phony target will always run
|
||||||
ex0.txt ex1.txt: maker
|
ex0.txt ex1.txt: maker
|
||||||
|
|
||||||
# Common phony targets are: all make clean install ...
|
# Common phony targets are: all make clean install ...
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Automatic Variables & Wildcards
|
# Automatic Variables & Wildcards
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
process: file*.txt #using a wildcard to match filenames
|
process: file*.txt #using a wildcard to match filenames
|
||||||
@echo $^ # $^ is a variable containing the list of prerequisites
|
@echo $^ # $^ is a variable containing the list of prerequisites
|
||||||
@echo $@ # prints the target name
|
@echo $@ # prints the target name
|
||||||
#(for multiple target rules, $@ is whichever caused the rule to run)
|
#(for multiple target rules, $@ is whichever caused the rule to run)
|
||||||
@echo $< # the first prerequisite listed
|
@echo $< # the first prerequisite listed
|
||||||
@echo $? # only the dependencies that are out of date
|
@echo $? # only the dependencies that are out of date
|
||||||
@echo $+ # all dependencies including duplicates (unlike normal)
|
@echo $+ # all dependencies including duplicates (unlike normal)
|
||||||
#@echo $| # all of the 'order only' prerequisites
|
#@echo $| # all of the 'order only' prerequisites
|
||||||
|
|
||||||
# Even if we split up the rule dependency definitions, $^ will find them
|
# Even if we split up the rule dependency definitions, $^ will find them
|
||||||
process: ex1.txt file0.txt
|
process: ex1.txt file0.txt
|
||||||
# ex1.txt will be found but file0.txt will be deduplicated.
|
# ex1.txt will be found but file0.txt will be deduplicated.
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Patterns
|
# Patterns
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# Can teach make how to convert certain files into other files.
|
# Can teach make how to convert certain files into other files.
|
||||||
|
|
||||||
%.png: %.svg
|
%.png: %.svg
|
||||||
inkscape --export-png $^
|
inkscape --export-png $^
|
||||||
|
|
||||||
# Pattern rules will only do anything if make decides to create the
|
# Pattern rules will only do anything if make decides to create the
|
||||||
# target.
|
# target.
|
||||||
|
|
||||||
# Directory paths are normally ignored when matching pattern rules. But
|
# Directory paths are normally ignored when matching pattern rules. But
|
||||||
# make will try to use the most appropriate rule available.
|
# make will try to use the most appropriate rule available.
|
||||||
small/%.png: %.svg
|
small/%.png: %.svg
|
||||||
inkscape --export-png --export-dpi 30 $^
|
inkscape --export-png --export-dpi 30 $^
|
||||||
|
|
||||||
# make will use the last version for a pattern rule that it finds.
|
# make will use the last version for a pattern rule that it finds.
|
||||||
%.png: %.svg
|
%.png: %.svg
|
||||||
@echo this rule is chosen
|
@echo this rule is chosen
|
||||||
|
|
||||||
# However make will use the first pattern rule that can make the target
|
# However make will use the first pattern rule that can make the target
|
||||||
%.png: %.ps
|
%.png: %.ps
|
||||||
@echo this rule is not chosen if *.svg and *.ps are both present
|
@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
|
# make already has some pattern rules built-in. For instance, it knows
|
||||||
# how to turn *.c files into *.o files.
|
# how to turn *.c files into *.o files.
|
||||||
|
|
||||||
# Older makefiles might use suffix rules instead of pattern rules
|
# Older makefiles might use suffix rules instead of pattern rules
|
||||||
.png.ps:
|
.png.ps:
|
||||||
@echo this rule is similar to a pattern rule.
|
@echo this rule is similar to a pattern rule.
|
||||||
|
|
||||||
# Tell make about the suffix rule
|
# Tell make about the suffix rule
|
||||||
.SUFFIXES: .png
|
.SUFFIXES: .png
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Variables
|
# Variables
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# aka. macros
|
# aka. macros
|
||||||
|
|
||||||
# Variables are basically all string types
|
# Variables are basically all string types
|
||||||
|
|
||||||
name = Ted
|
name = Ted
|
||||||
name2="Sarah"
|
name2="Sarah"
|
||||||
|
|
||||||
echo:
|
echo:
|
||||||
@echo $(name)
|
@echo $(name)
|
||||||
@echo ${name2}
|
@echo ${name2}
|
||||||
@echo $name # This won't work, treated as $(n)ame.
|
@echo $name # This won't work, treated as $(n)ame.
|
||||||
@echo $(name3) # Unknown variables are treated as empty strings.
|
@echo $(name3) # Unknown variables are treated as empty strings.
|
||||||
|
|
||||||
# There are 4 places to set variables.
|
# There are 4 places to set variables.
|
||||||
# In order of priority from highest to lowest:
|
# In order of priority from highest to lowest:
|
||||||
# 1: commandline arguments
|
# 1: commandline arguments
|
||||||
# 2: Makefile
|
# 2: Makefile
|
||||||
# 3: shell environment variables - make imports these automatically.
|
# 3: shell environment variables - make imports these automatically.
|
||||||
# 4: make has some predefined variables
|
# 4: make has some predefined variables
|
||||||
|
|
||||||
name4 ?= Jean
|
name4 ?= Jean
|
||||||
# Only set the variable if environment variable is not already defined.
|
# Only set the variable if environment variable is not already defined.
|
||||||
|
|
||||||
override name5 = David
|
override name5 = David
|
||||||
# Stops commandline arguments from changing this variable.
|
# Stops commandline arguments from changing this variable.
|
||||||
|
|
||||||
name4 +=grey
|
name4 +=grey
|
||||||
# Append values to variable (includes a space).
|
# Append values to variable (includes a space).
|
||||||
|
|
||||||
# Pattern-specific variable values (GNU extension).
|
# Pattern-specific variable values (GNU extension).
|
||||||
echo: name2 = Sara # True within the matching rule
|
echo: name2 = Sara # True within the matching rule
|
||||||
# and also within its remade recursive dependencies
|
# and also within its remade recursive dependencies
|
||||||
# (except it can break when your graph gets too complicated!)
|
# (except it can break when your graph gets too complicated!)
|
||||||
|
|
||||||
# Some variables defined automatically by make.
|
# Some variables defined automatically by make.
|
||||||
echo_inbuilt:
|
echo_inbuilt:
|
||||||
echo $(CC)
|
echo $(CC)
|
||||||
echo ${CXX}
|
echo ${CXX}
|
||||||
echo $(FC)
|
echo $(FC)
|
||||||
echo ${CFLAGS}
|
echo ${CFLAGS}
|
||||||
echo $(CPPFLAGS)
|
echo $(CPPFLAGS)
|
||||||
echo ${CXXFLAGS}
|
echo ${CXXFLAGS}
|
||||||
echo $(LDFLAGS)
|
echo $(LDFLAGS)
|
||||||
echo ${LDLIBS}
|
echo ${LDLIBS}
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Variables 2
|
# Variables 2
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# The first type of variables are evaluated each time they are used.
|
# 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
|
# This can be expensive, so a second type of variable exists which is
|
||||||
# only evaluated once. (This is a GNU make extension)
|
# only evaluated once. (This is a GNU make extension)
|
||||||
|
|
||||||
var := hello
|
var := hello
|
||||||
var2 ::= $(var) hello
|
var2 ::= $(var) hello
|
||||||
#:= and ::= are equivalent.
|
#:= and ::= are equivalent.
|
||||||
|
|
||||||
# These variables are evaluated procedurally (in the order that they
|
# These variables are evaluated procedurally (in the order that they
|
||||||
# appear), thus breaking with the rest of the language !
|
# appear), thus breaking with the rest of the language !
|
||||||
|
|
||||||
# This doesn't work
|
# This doesn't work
|
||||||
var3 ::= $(var4) and good luck
|
var3 ::= $(var4) and good luck
|
||||||
var4 ::= good night
|
var4 ::= good night
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Functions
|
# Functions
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# make has lots of functions available.
|
# make has lots of functions available.
|
||||||
|
|
||||||
sourcefiles = $(wildcard *.c */*.c)
|
sourcefiles = $(wildcard *.c */*.c)
|
||||||
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
|
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
|
||||||
|
|
||||||
# Format is $(func arg0,arg1,arg2...)
|
# Format is $(func arg0,arg1,arg2...)
|
||||||
|
|
||||||
# Some examples
|
# Some examples
|
||||||
ls: * src/*
|
ls: * src/*
|
||||||
@echo $(filter %.txt, $^)
|
@echo $(filter %.txt, $^)
|
||||||
@echo $(notdir $^)
|
@echo $(notdir $^)
|
||||||
@echo $(join $(dir $^),$(notdir $^))
|
@echo $(join $(dir $^),$(notdir $^))
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Directives
|
# Directives
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# Include other makefiles, useful for platform specific code
|
# Include other makefiles, useful for platform specific code
|
||||||
include foo.mk
|
include foo.mk
|
||||||
|
|
||||||
sport = tennis
|
sport = tennis
|
||||||
# Conditional compilation
|
# Conditional compilation
|
||||||
report:
|
report:
|
||||||
ifeq ($(sport),tennis)
|
ifeq ($(sport),tennis)
|
||||||
@echo 'game, set, match'
|
@echo 'game, set, match'
|
||||||
else
|
else
|
||||||
@echo "They think it's all over; it is now"
|
@echo "They think it's all over; it is now"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# There are also ifneq, ifdef, ifndef
|
# There are also ifneq, ifdef, ifndef
|
||||||
|
|
||||||
foo = true
|
foo = true
|
||||||
|
|
||||||
ifdef $(foo)
|
ifdef $(foo)
|
||||||
bar = 'hello'
|
bar = 'hello'
|
||||||
endif
|
endif
|
||||||
```
|
```
|
||||||
|
|
||||||
### More Resources
|
### More Resources
|
||||||
|
|
||||||
+ [gnu make documentation](https://www.gnu.org/software/make/manual/)
|
+ [gnu make documentation](https://www.gnu.org/software/make/manual/)
|
||||||
+ [software carpentry tutorial](http://swcarpentry.github.io/make-novice/)
|
+ [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)
|
+ learn C the hard way [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html)
|
||||||
|
1530
opengl.html.markdown
1530
opengl.html.markdown
File diff suppressed because it is too large
Load Diff
@@ -1,245 +1,245 @@
|
|||||||
---
|
---
|
||||||
category: tool
|
category: tool
|
||||||
tool: make
|
tool: make
|
||||||
contributors:
|
contributors:
|
||||||
- ["Robert Steed", "https://github.com/robochat"]
|
- ["Robert Steed", "https://github.com/robochat"]
|
||||||
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
|
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
|
||||||
translators:
|
translators:
|
||||||
- ["Rogério Gomes Rio", "https://github.com/rogerlista"]
|
- ["Rogério Gomes Rio", "https://github.com/rogerlista"]
|
||||||
filename: Makefile-pt
|
filename: Makefile-pt
|
||||||
|
|
||||||
lang: pt-br
|
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.
|
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.
|
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
|
```make
|
||||||
|
|
||||||
# Comentários podem ser escritos assim.
|
# Comentários podem ser escritos assim.
|
||||||
|
|
||||||
# O arquivo deve ser nomeado Makefile e então pode ser executado como `make <alvo>`.
|
# 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>`.
|
# Caso contrário, nós usamos `make -f "nome-do-arquivo" <alvo>`.
|
||||||
|
|
||||||
# Aviso - use somente TABS para identar em Makefiles, nunca espaços!
|
# Aviso - use somente TABS para identar em Makefiles, nunca espaços!
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Noções básicas
|
# Noções básicas
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# Regras são do formato
|
# Regras são do formato
|
||||||
# alvo: <pré-requisito>
|
# alvo: <pré-requisito>
|
||||||
# onde os pré-requisitos são opcionais.
|
# onde os pré-requisitos são opcionais.
|
||||||
|
|
||||||
# Uma regra - esta regra só será executada se o arquivo0.txt não existir.
|
# Uma regra - esta regra só será executada se o arquivo0.txt não existir.
|
||||||
arquivo0.txt:
|
arquivo0.txt:
|
||||||
echo "foo" > arquivo0.txt
|
echo "foo" > arquivo0.txt
|
||||||
# Mesmo os comentários nestas seções da 'receita' são passados para o shell.
|
# 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.
|
# 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.
|
# Esta regra só será executada se arquivo0.txt for mais recente que arquivo1.txt.
|
||||||
arquivo1.txt: arquivo0.txt
|
arquivo1.txt: arquivo0.txt
|
||||||
cat arquivo0.txt > arquivo1.txt
|
cat arquivo0.txt > arquivo1.txt
|
||||||
# se as mesmas regras de citação do shell.
|
# se as mesmas regras de citação do shell.
|
||||||
@cat arquivo0.txt >> arquivo1.txt
|
@cat arquivo0.txt >> arquivo1.txt
|
||||||
# @ pára o comando de ser ecoado para stdout.
|
# @ pára o comando de ser ecoado para stdout.
|
||||||
-@echo 'hello'
|
-@echo 'hello'
|
||||||
# - significa que make continuará em caso de erro.
|
# - significa que make continuará em caso de erro.
|
||||||
# Experimentar `make arquivo1.txt` na linha de comando.
|
# Experimentar `make arquivo1.txt` na linha de comando.
|
||||||
|
|
||||||
# Uma regra pode ter vários alvos e vários pré-requisitos
|
# Uma regra pode ter vários alvos e vários pré-requisitos
|
||||||
arquivo2.txt arquivo3.txt: arquivo0.txt arquivo1.txt
|
arquivo2.txt arquivo3.txt: arquivo0.txt arquivo1.txt
|
||||||
touch arquivo2.txt
|
touch arquivo2.txt
|
||||||
touch arquivo3.txt
|
touch arquivo3.txt
|
||||||
|
|
||||||
# Make vai reclamar sobre várias receitas para a mesma regra. Esvaziar
|
# 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.
|
# receitas não contam e podem ser usadas para adicionar novas dependências.
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Alvos falsos
|
# Alvos falsos
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# Um alvo falso. Qualquer alvo que não seja um arquivo.
|
# Um alvo falso. Qualquer alvo que não seja um arquivo.
|
||||||
# Ele nunca será atualizado, portanto, o make sempre tentará executá-lo.
|
# Ele nunca será atualizado, portanto, o make sempre tentará executá-lo.
|
||||||
all: maker process
|
all: maker process
|
||||||
|
|
||||||
# Podemos declarar as coisas fora de ordem.
|
# Podemos declarar as coisas fora de ordem.
|
||||||
maker:
|
maker:
|
||||||
touch ex0.txt ex1.txt
|
touch ex0.txt ex1.txt
|
||||||
|
|
||||||
# Pode evitar quebrar regras falsas quando um arquivo real tem o mesmo nome
|
# Pode evitar quebrar regras falsas quando um arquivo real tem o mesmo nome
|
||||||
.PHONY: all maker process
|
.PHONY: all maker process
|
||||||
# Este é um alvo especial. Existem vários outros.
|
# Este é um alvo especial. Existem vários outros.
|
||||||
|
|
||||||
# Uma regra com dependência de um alvo falso sempre será executada
|
# Uma regra com dependência de um alvo falso sempre será executada
|
||||||
ex0.txt ex1.txt: maker
|
ex0.txt ex1.txt: maker
|
||||||
|
|
||||||
# Alvos falsos comuns são: todos fazem instalação limpa ...
|
# Alvos falsos comuns são: todos fazem instalação limpa ...
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Variáveis Automáticas e Curingas
|
# Variáveis Automáticas e Curingas
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
process: Arquivo*.txt # Usando um curinga para corresponder nomes de arquivos
|
process: Arquivo*.txt # Usando um curinga para corresponder nomes de arquivos
|
||||||
@echo $^ # $^ é uma variável que contém a lista de pré-requisitos
|
@echo $^ # $^ é uma variável que contém a lista de pré-requisitos
|
||||||
@echo $@ # imprime o nome do alvo
|
@echo $@ # imprime o nome do alvo
|
||||||
#(fpara várias regras alvo, $@ é o que causou a execução da regra)
|
#(fpara várias regras alvo, $@ é o que causou a execução da regra)
|
||||||
@echo $< # o primeiro pré-requisito listado
|
@echo $< # o primeiro pré-requisito listado
|
||||||
@echo $? # somente as dependências que estão desatualizadas
|
@echo $? # somente as dependências que estão desatualizadas
|
||||||
@echo $+ # todas as dependências, incluindo duplicadas (ao contrário do normal)
|
@echo $+ # todas as dependências, incluindo duplicadas (ao contrário do normal)
|
||||||
#@echo $| # todos os pré-requisitos 'somente pedidos'
|
#@echo $| # todos os pré-requisitos 'somente pedidos'
|
||||||
|
|
||||||
# Mesmo se dividirmos as definições de dependência de regra, $^ vai encontrá-los
|
# Mesmo se dividirmos as definições de dependência de regra, $^ vai encontrá-los
|
||||||
process: ex1.txt arquivo0.txt
|
process: ex1.txt arquivo0.txt
|
||||||
# ex1.txt será encontrado, mas arquivo0.txt será desduplicado.
|
# ex1.txt será encontrado, mas arquivo0.txt será desduplicado.
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Padrões
|
# Padrões
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# Pode ensinar make a converter certos arquivos em outros arquivos.
|
# Pode ensinar make a converter certos arquivos em outros arquivos.
|
||||||
|
|
||||||
%.png: %.svg
|
%.png: %.svg
|
||||||
inkscape --export-png $^
|
inkscape --export-png $^
|
||||||
|
|
||||||
# As regras padrões só farão qualquer coisa se decidirem criar o alvo.
|
# 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
|
# 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
|
# padrões são correspondentes. Mas make tentará usar a regra mais
|
||||||
# apropriada disponível.
|
# apropriada disponível.
|
||||||
small/%.png: %.svg
|
small/%.png: %.svg
|
||||||
inkscape --export-png --export-dpi 30 $^
|
inkscape --export-png --export-dpi 30 $^
|
||||||
|
|
||||||
# make utilizará a última versão para uma regra de padrão que encontrar.
|
# make utilizará a última versão para uma regra de padrão que encontrar.
|
||||||
%.png: %.svg
|
%.png: %.svg
|
||||||
@echo esta regra é escolhida
|
@echo esta regra é escolhida
|
||||||
|
|
||||||
# No entanto, o make usará a primeira regra padrão que pode se tornar o alvo
|
# No entanto, o make usará a primeira regra padrão que pode se tornar o alvo
|
||||||
%.png: %.ps
|
%.png: %.ps
|
||||||
@echo esta regra não é escolhida se *.svg and *.ps estão ambos presentes
|
@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
|
# make já tem algumas regras padrões embutidas. Por exemplo, ele sabe
|
||||||
# como transformar arquivos *.c em arquivos *.o.
|
# como transformar arquivos *.c em arquivos *.o.
|
||||||
|
|
||||||
# Makefiles antigos podem usar regras de sufixo em vez de regras padrões
|
# Makefiles antigos podem usar regras de sufixo em vez de regras padrões
|
||||||
.png.ps:
|
.png.ps:
|
||||||
@echo essa regra é semelhante a uma regra de padrão.
|
@echo essa regra é semelhante a uma regra de padrão.
|
||||||
|
|
||||||
# make sobre a regra de sufixo
|
# make sobre a regra de sufixo
|
||||||
.SUFFIXES: .png
|
.SUFFIXES: .png
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Variáveis
|
# Variáveis
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# aka. macros
|
# aka. macros
|
||||||
|
|
||||||
# As variáveis são basicamente todos os tipos de string
|
# As variáveis são basicamente todos os tipos de string
|
||||||
|
|
||||||
name = Ted
|
name = Ted
|
||||||
name2="Sarah"
|
name2="Sarah"
|
||||||
|
|
||||||
echo:
|
echo:
|
||||||
@echo $(name)
|
@echo $(name)
|
||||||
@echo ${name2}
|
@echo ${name2}
|
||||||
@echo $name # Isso não funcionará, tratado como $ (n)ame.
|
@echo $name # Isso não funcionará, tratado como $ (n)ame.
|
||||||
@echo $(name3) # Variáveis desconhecidas são tratadas como strings vazias.
|
@echo $(name3) # Variáveis desconhecidas são tratadas como strings vazias.
|
||||||
|
|
||||||
# Existem 4 lugares para definir variáveis.
|
# Existem 4 lugares para definir variáveis.
|
||||||
# Em ordem de prioridade, do maior para o menor:
|
# Em ordem de prioridade, do maior para o menor:
|
||||||
# 1: argumentos de linha de comando
|
# 1: argumentos de linha de comando
|
||||||
# 2: Makefile
|
# 2: Makefile
|
||||||
# 3: variáveis de ambiente do shell - faça importações automaticamente.
|
# 3: variáveis de ambiente do shell - faça importações automaticamente.
|
||||||
# 4: make tem algumas variáveis predefinidas
|
# 4: make tem algumas variáveis predefinidas
|
||||||
|
|
||||||
name4 ?= Jean
|
name4 ?= Jean
|
||||||
# Somente defina a variável se a variável de ambiente ainda não estiver definida.
|
# Somente defina a variável se a variável de ambiente ainda não estiver definida.
|
||||||
|
|
||||||
override name5 = David
|
override name5 = David
|
||||||
# Pára os argumentos da linha de comando de alterar essa variável.
|
# Pára os argumentos da linha de comando de alterar essa variável.
|
||||||
|
|
||||||
name4 +=grey
|
name4 +=grey
|
||||||
# Anexar valores à variável (inclui um espaço).
|
# Anexar valores à variável (inclui um espaço).
|
||||||
|
|
||||||
# Valores variáveis específicos de padrões (extensão GNU).
|
# Valores variáveis específicos de padrões (extensão GNU).
|
||||||
echo: name2 = Sara # Verdadeiro dentro da regra de correspondência
|
echo: name2 = Sara # Verdadeiro dentro da regra de correspondência
|
||||||
# e também dentro de suas recursivas dependências
|
# e também dentro de suas recursivas dependências
|
||||||
# (exceto que ele pode quebrar quando seu gráfico ficar muito complicado!)
|
# (exceto que ele pode quebrar quando seu gráfico ficar muito complicado!)
|
||||||
|
|
||||||
# Algumas variáveis definidas automaticamente pelo make
|
# Algumas variáveis definidas automaticamente pelo make
|
||||||
echo_inbuilt:
|
echo_inbuilt:
|
||||||
echo $(CC)
|
echo $(CC)
|
||||||
echo ${CXX}
|
echo ${CXX}
|
||||||
echo $(FC)
|
echo $(FC)
|
||||||
echo ${CFLAGS}
|
echo ${CFLAGS}
|
||||||
echo $(CPPFLAGS)
|
echo $(CPPFLAGS)
|
||||||
echo ${CXXFLAGS}
|
echo ${CXXFLAGS}
|
||||||
echo $(LDFLAGS)
|
echo $(LDFLAGS)
|
||||||
echo ${LDLIBS}
|
echo ${LDLIBS}
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Variáveis 2
|
# Variáveis 2
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# O primeiro tipo de variáveis é avaliado a cada vez que elas são usadas.
|
# 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 é
|
# 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)
|
# avaliado apenas uma vez. (Esta é uma extensão do GNU make)
|
||||||
|
|
||||||
var := hello
|
var := hello
|
||||||
var2 ::= $(var) hello
|
var2 ::= $(var) hello
|
||||||
#:= e ::= são equivalentes.
|
#:= e ::= são equivalentes.
|
||||||
|
|
||||||
# Essas variáveis são avaliadas procedimentalmente (na ordem em que
|
# Essas variáveis são avaliadas procedimentalmente (na ordem em que
|
||||||
# aparecem), quebrando assim o resto da línguagem!
|
# aparecem), quebrando assim o resto da línguagem!
|
||||||
|
|
||||||
# Isso não funciona
|
# Isso não funciona
|
||||||
var3 ::= $(var4) and good luck
|
var3 ::= $(var4) and good luck
|
||||||
var4 ::= good night
|
var4 ::= good night
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Funções
|
# Funções
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# make tem muitas funções disponíveis.
|
# make tem muitas funções disponíveis.
|
||||||
|
|
||||||
sourcefiles = $(wildcard *.c */*.c)
|
sourcefiles = $(wildcard *.c */*.c)
|
||||||
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
|
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
|
||||||
|
|
||||||
# O formato é $(func arg0,arg1,arg2...)
|
# O formato é $(func arg0,arg1,arg2...)
|
||||||
|
|
||||||
# Alguns exemplos
|
# Alguns exemplos
|
||||||
ls: * src/*
|
ls: * src/*
|
||||||
@echo $(filter %.txt, $^)
|
@echo $(filter %.txt, $^)
|
||||||
@echo $(notdir $^)
|
@echo $(notdir $^)
|
||||||
@echo $(join $(dir $^),$(notdir $^))
|
@echo $(join $(dir $^),$(notdir $^))
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Diretivas
|
# Diretivas
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
# Inclua outros makefiles, úteis para código específico da plataforma
|
# Inclua outros makefiles, úteis para código específico da plataforma
|
||||||
include foo.mk
|
include foo.mk
|
||||||
|
|
||||||
sport = tennis
|
sport = tennis
|
||||||
# Compilação condicional
|
# Compilação condicional
|
||||||
report:
|
report:
|
||||||
ifeq ($(sport),tennis)
|
ifeq ($(sport),tennis)
|
||||||
@echo 'game, set, match'
|
@echo 'game, set, match'
|
||||||
else
|
else
|
||||||
@echo "They think it's all over; it is now"
|
@echo "They think it's all over; it is now"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Há também ifneq, ifdef, ifndef
|
# Há também ifneq, ifdef, ifndef
|
||||||
|
|
||||||
foo = true
|
foo = true
|
||||||
|
|
||||||
ifdef $(foo)
|
ifdef $(foo)
|
||||||
bar = 'hello'
|
bar = 'hello'
|
||||||
endif
|
endif
|
||||||
```
|
```
|
||||||
|
|
||||||
### More Resources
|
### More Resources
|
||||||
|
|
||||||
+ [documentação gnu make](https://www.gnu.org/software/make/manual/)
|
+ [documentação gnu make](https://www.gnu.org/software/make/manual/)
|
||||||
+ [tutorial de carpintaria de software](http://swcarpentry.github.io/make-novice/)
|
+ [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)
|
+ aprenda C da maneira mais difícil [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html)
|
||||||
|
@@ -1,225 +1,225 @@
|
|||||||
---
|
---
|
||||||
category: Algorithms & Data Structures
|
category: Algorithms & Data Structures
|
||||||
name: Asymptotic Notation
|
name: Asymptotic Notation
|
||||||
contributors:
|
contributors:
|
||||||
- ["Jake Prather", "http://github.com/JakeHP"]
|
- ["Jake Prather", "http://github.com/JakeHP"]
|
||||||
- ["Divay Prakash", "http://github.com/divayprakash"]
|
- ["Divay Prakash", "http://github.com/divayprakash"]
|
||||||
translators:
|
translators:
|
||||||
- ["pru-mike", "http://github.com/pru-mike"]
|
- ["pru-mike", "http://github.com/pru-mike"]
|
||||||
lang: ru-ru
|
lang: ru-ru
|
||||||
---
|
---
|
||||||
|
|
||||||
# О-символика
|
# О-символика
|
||||||
|
|
||||||
## Что это такое?
|
## Что это такое?
|
||||||
|
|
||||||
О-символика, или асимптотическая запись, — это система символов, позволяющая
|
О-символика, или асимптотическая запись, — это система символов, позволяющая
|
||||||
оценить время выполнения алгоритма, устанавливая зависимость времени выполнения
|
оценить время выполнения алгоритма, устанавливая зависимость времени выполнения
|
||||||
от увеличения объёма входных данных. Она также известна как оценка
|
от увеличения объёма входных данных. Она также известна как оценка
|
||||||
сложности алгоритмов. Станет ли алгоритм невероятно медленным, когда
|
сложности алгоритмов. Станет ли алгоритм невероятно медленным, когда
|
||||||
объём входных данных увеличится? Будет ли алгоритм выполняться достаточно быстро,
|
объём входных данных увеличится? Будет ли алгоритм выполняться достаточно быстро,
|
||||||
если объём входных данных возрастёт? О-символика позволяет ответить на эти
|
если объём входных данных возрастёт? О-символика позволяет ответить на эти
|
||||||
вопросы.
|
вопросы.
|
||||||
|
|
||||||
## Можно ли по-другому найти ответы на эти вопросы?
|
## Можно ли по-другому найти ответы на эти вопросы?
|
||||||
|
|
||||||
Один способ — это подсчитать число элементарных операций в зависимости от
|
Один способ — это подсчитать число элементарных операций в зависимости от
|
||||||
различных объёмов входных данных. Хотя это и приемлемое решение, тот объём
|
различных объёмов входных данных. Хотя это и приемлемое решение, тот объём
|
||||||
работы, которого оно потребует, даже для простых алгоритмов делает его
|
работы, которого оно потребует, даже для простых алгоритмов делает его
|
||||||
использование неоправданным.
|
использование неоправданным.
|
||||||
|
|
||||||
Другой способ — это измерить, какое время алгоритм потребует для завершения на
|
Другой способ — это измерить, какое время алгоритм потребует для завершения на
|
||||||
различных объёмах входных данных. В то же время, точность и относительность
|
различных объёмах входных данных. В то же время, точность и относительность
|
||||||
этого метода (полученное время будет относиться только к той машине, на которой
|
этого метода (полученное время будет относиться только к той машине, на которой
|
||||||
оно вычислено) зависит от среды выполнения: компьютерного аппаратного
|
оно вычислено) зависит от среды выполнения: компьютерного аппаратного
|
||||||
обеспечения, мощности процессора и т.д.
|
обеспечения, мощности процессора и т.д.
|
||||||
|
|
||||||
## Виды О-символики
|
## Виды О-символики
|
||||||
|
|
||||||
В первом разделе этого документа мы определили, что О-символика
|
В первом разделе этого документа мы определили, что О-символика
|
||||||
позволяет оценивать алгоритмы в зависимости от изменения размера входных
|
позволяет оценивать алгоритмы в зависимости от изменения размера входных
|
||||||
данных. Представим, что алгоритм — это функция f, n — размер входных данных и
|
данных. Представим, что алгоритм — это функция f, n — размер входных данных и
|
||||||
f(n) — время выполнения. Тогда для данного алгоритма f с размером входных
|
f(n) — время выполнения. Тогда для данного алгоритма f с размером входных
|
||||||
данных n получим какое-то результирующее время выполнения f(n).
|
данных n получим какое-то результирующее время выполнения f(n).
|
||||||
Из этого можно построить график, где ось y — время выполнения, ось x — размер входных
|
Из этого можно построить график, где ось y — время выполнения, ось x — размер входных
|
||||||
данных, а точки на графике — это время выполнения для заданного размера входных
|
данных, а точки на графике — это время выполнения для заданного размера входных
|
||||||
данных.
|
данных.
|
||||||
|
|
||||||
С помощью О-символики можно оценить функцию или алгоритм
|
С помощью О-символики можно оценить функцию или алгоритм
|
||||||
несколькими различными способами. Например, можно оценить алгоритм исходя
|
несколькими различными способами. Например, можно оценить алгоритм исходя
|
||||||
из нижней оценки, верхней оценки, тождественной оценки. Чаще всего встречается
|
из нижней оценки, верхней оценки, тождественной оценки. Чаще всего встречается
|
||||||
анализ на основе верхней оценки. Как правило, не используется нижняя оценка,
|
анализ на основе верхней оценки. Как правило, не используется нижняя оценка,
|
||||||
потому что она не подходит под планируемые условия. Отличный пример — алгоритмы
|
потому что она не подходит под планируемые условия. Отличный пример — алгоритмы
|
||||||
сортировки, особенно добавление элементов в древовидную структуру. Нижняя оценка
|
сортировки, особенно добавление элементов в древовидную структуру. Нижняя оценка
|
||||||
большинства таких алгоритмов может быть дана как одна операция. В то время как в
|
большинства таких алгоритмов может быть дана как одна операция. В то время как в
|
||||||
большинстве случаев добавляемые элементы должны быть отсортированы
|
большинстве случаев добавляемые элементы должны быть отсортированы
|
||||||
соответствующим образом при помощи дерева, что может потребовать обхода целой
|
соответствующим образом при помощи дерева, что может потребовать обхода целой
|
||||||
ветви. Это и есть худший случай, для которого планируется верхняя оценка.
|
ветви. Это и есть худший случай, для которого планируется верхняя оценка.
|
||||||
|
|
||||||
### Виды функций, пределы и упрощения
|
### Виды функций, пределы и упрощения
|
||||||
|
|
||||||
```
|
```
|
||||||
Логарифмическая функция — log n
|
Логарифмическая функция — log n
|
||||||
Линейная функция — an + b
|
Линейная функция — an + b
|
||||||
Квадратичная функция — an^2 + bn +c
|
Квадратичная функция — an^2 + bn +c
|
||||||
Степенная функция — an^z + . . . + an^2 + a*n^1 + a*n^0, где z — константа
|
Степенная функция — an^z + . . . + an^2 + a*n^1 + a*n^0, где z — константа
|
||||||
Показательная функция — a^n, где a — константа
|
Показательная функция — a^n, где a — константа
|
||||||
```
|
```
|
||||||
|
|
||||||
Приведены несколько базовых функций, используемых при определении сложности в
|
Приведены несколько базовых функций, используемых при определении сложности в
|
||||||
различных оценках. Список начинается с самой медленно возрастающей функции
|
различных оценках. Список начинается с самой медленно возрастающей функции
|
||||||
(логарифм, наиболее быстрое время выполнения) и следует до самой быстро
|
(логарифм, наиболее быстрое время выполнения) и следует до самой быстро
|
||||||
возрастающей функции (экспонента, самое медленное время выполнения). Отметим,
|
возрастающей функции (экспонента, самое медленное время выполнения). Отметим,
|
||||||
что в то время, как «n», или размер входных данных, возрастает в каждой из этих функций,
|
что в то время, как «n», или размер входных данных, возрастает в каждой из этих функций,
|
||||||
результат намного быстрее возрастает в квадратичной, степенной
|
результат намного быстрее возрастает в квадратичной, степенной
|
||||||
и показательной по сравнению с логарифмической и линейной.
|
и показательной по сравнению с логарифмической и линейной.
|
||||||
|
|
||||||
Крайне важно понимать, что при использовании описанной далее нотации необходимо
|
Крайне важно понимать, что при использовании описанной далее нотации необходимо
|
||||||
использовать упрощённые выражения.
|
использовать упрощённые выражения.
|
||||||
Это означает, что необходимо отбрасывать константы и слагаемые младших порядков,
|
Это означает, что необходимо отбрасывать константы и слагаемые младших порядков,
|
||||||
потому что если размер входных данных (n в функции f(n) нашего примера)
|
потому что если размер входных данных (n в функции f(n) нашего примера)
|
||||||
увеличивается до бесконечности (в пределе), тогда слагаемые младших порядков
|
увеличивается до бесконечности (в пределе), тогда слагаемые младших порядков
|
||||||
и константы становятся пренебрежительно малыми. Таким образом, если есть
|
и константы становятся пренебрежительно малыми. Таким образом, если есть
|
||||||
константа, например, размера 2^9001 или любого другого невообразимого размера,
|
константа, например, размера 2^9001 или любого другого невообразимого размера,
|
||||||
надо понимать, что её упрощение внесёт значительные искажения в точность
|
надо понимать, что её упрощение внесёт значительные искажения в точность
|
||||||
оценки.
|
оценки.
|
||||||
|
|
||||||
Т.к. нам нужны упрощённые выражения, немного скорректируем нашу таблицу...
|
Т.к. нам нужны упрощённые выражения, немного скорректируем нашу таблицу...
|
||||||
|
|
||||||
```
|
```
|
||||||
Логарифм — log n
|
Логарифм — log n
|
||||||
Линейная функция — n
|
Линейная функция — n
|
||||||
Квадратичная функция — n^2
|
Квадратичная функция — n^2
|
||||||
Степенная функция — n^z, где z — константа
|
Степенная функция — n^z, где z — константа
|
||||||
Показательная функция — a^n, где a — константа
|
Показательная функция — a^n, где a — константа
|
||||||
```
|
```
|
||||||
|
|
||||||
### О Большое
|
### О Большое
|
||||||
О Большое, записывается как **О**, — это асимптотическая запись для оценки худшего
|
О Большое, записывается как **О**, — это асимптотическая запись для оценки худшего
|
||||||
случая, или для ограничения заданной функции сверху. Это позволяет сделать
|
случая, или для ограничения заданной функции сверху. Это позволяет сделать
|
||||||
_**асимптотическую оценку верхней границы**_ скорости роста времени выполнения
|
_**асимптотическую оценку верхней границы**_ скорости роста времени выполнения
|
||||||
алгоритма. Пусть `f(n)` — время выполнения алгоритма, а `g(n)` — заданная временная
|
алгоритма. Пусть `f(n)` — время выполнения алгоритма, а `g(n)` — заданная временная
|
||||||
сложность, которая проверяется для алгоритма. Тогда `f(n)` — это O(g(n)), если
|
сложность, которая проверяется для алгоритма. Тогда `f(n)` — это O(g(n)), если
|
||||||
существуют действительные константы c (c > 0) и n<sub>0</sub>, такие,
|
существуют действительные константы c (c > 0) и n<sub>0</sub>, такие,
|
||||||
что `f(n)` <= `c g(n)` выполняется для всех n, начиная с некоторого n<sub>0</sub> (n > n<sub>0</sub>).
|
что `f(n)` <= `c g(n)` выполняется для всех n, начиная с некоторого n<sub>0</sub> (n > n<sub>0</sub>).
|
||||||
|
|
||||||
*Пример 1*
|
*Пример 1*
|
||||||
|
|
||||||
```
|
```
|
||||||
f(n) = 3log n + 100
|
f(n) = 3log n + 100
|
||||||
g(n) = log n
|
g(n) = log n
|
||||||
```
|
```
|
||||||
|
|
||||||
Является ли `f(n)` O(g(n))?
|
Является ли `f(n)` O(g(n))?
|
||||||
Является ли `3 log n + 100` O(log n)?
|
Является ли `3 log n + 100` O(log n)?
|
||||||
Посмотрим на определение О Большого:
|
Посмотрим на определение О Большого:
|
||||||
|
|
||||||
```
|
```
|
||||||
3log n + 100 <= c * log n
|
3log n + 100 <= c * log n
|
||||||
```
|
```
|
||||||
|
|
||||||
Существуют ли константы c и n<sub>0</sub>, такие, что выражение верно для всех n > n<sub>0</sub>?
|
Существуют ли константы c и n<sub>0</sub>, такие, что выражение верно для всех n > n<sub>0</sub>?
|
||||||
|
|
||||||
```
|
```
|
||||||
3log n + 100 <= 150 * log n, n > 2 (не определенно для n = 1)
|
3log n + 100 <= 150 * log n, n > 2 (не определенно для n = 1)
|
||||||
```
|
```
|
||||||
|
|
||||||
Да! По определению О Большого `f(n)` является O(g(n)).
|
Да! По определению О Большого `f(n)` является O(g(n)).
|
||||||
|
|
||||||
*Пример 2*
|
*Пример 2*
|
||||||
|
|
||||||
```
|
```
|
||||||
f(n) = 3 * n^2
|
f(n) = 3 * n^2
|
||||||
g(n) = n
|
g(n) = n
|
||||||
```
|
```
|
||||||
|
|
||||||
Является ли `f(n)` O(g(n))?
|
Является ли `f(n)` O(g(n))?
|
||||||
Является ли `3 * n^2` O(n)?
|
Является ли `3 * n^2` O(n)?
|
||||||
Посмотрим на определение О Большого:
|
Посмотрим на определение О Большого:
|
||||||
|
|
||||||
```
|
```
|
||||||
3 * n^2 <= c * n
|
3 * n^2 <= c * n
|
||||||
```
|
```
|
||||||
|
|
||||||
Существуют ли константы c и n<sub>0</sub>, такие, что выражение верно для всех n > n<sub>0</sub>?
|
Существуют ли константы c и n<sub>0</sub>, такие, что выражение верно для всех n > n<sub>0</sub>?
|
||||||
Нет, не существуют. `f(n)` НЕ ЯВЛЯЕТСЯ O(g(n)).
|
Нет, не существуют. `f(n)` НЕ ЯВЛЯЕТСЯ O(g(n)).
|
||||||
|
|
||||||
### Омега Большое
|
### Омега Большое
|
||||||
Омега Большое, записывается как **Ω**, — это асимптотическая запись для оценки
|
Омега Большое, записывается как **Ω**, — это асимптотическая запись для оценки
|
||||||
лучшего случая, или для ограничения заданной функции снизу. Это позволяет сделать
|
лучшего случая, или для ограничения заданной функции снизу. Это позволяет сделать
|
||||||
_**асимптотическую оценку нижней границы**_ скорости роста времени выполнения
|
_**асимптотическую оценку нижней границы**_ скорости роста времени выполнения
|
||||||
алгоритма.
|
алгоритма.
|
||||||
|
|
||||||
`f(n)` является Ω(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>.
|
c (c > 0) и n<sub>0</sub> (n<sub>0</sub> > 0), такие, что `f(n)` >= `c g(n)` для всех n > n<sub>0</sub>.
|
||||||
|
|
||||||
### Примечание
|
### Примечание
|
||||||
|
|
||||||
Асимптотические оценки, сделанные при помощи О Большого и Омега Большого, могут
|
Асимптотические оценки, сделанные при помощи О Большого и Омега Большого, могут
|
||||||
как являться, так и не являться точными. Для того чтобы обозначить, что границы не
|
как являться, так и не являться точными. Для того чтобы обозначить, что границы не
|
||||||
являются асимптотически точными, используются записи О Малое и Омега Малое.
|
являются асимптотически точными, используются записи О Малое и Омега Малое.
|
||||||
|
|
||||||
### О Малое
|
### О Малое
|
||||||
O Малое, записывается как **о**, — это асимптотическая запись для оценки верхней
|
O Малое, записывается как **о**, — это асимптотическая запись для оценки верхней
|
||||||
границы времени выполнения алгоритма при условии, что граница не является
|
границы времени выполнения алгоритма при условии, что граница не является
|
||||||
асимптотически точной.
|
асимптотически точной.
|
||||||
|
|
||||||
`f(n)` является o(g(n)), если можно подобрать такие действительные константы,
|
`f(n)` является o(g(n)), если можно подобрать такие действительные константы,
|
||||||
что для всех c (c > 0) найдётся n<sub>0</sub> (n<sub>0</sub> > 0), так
|
что для всех 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)` < `c g(n)` выполняется для всех n (n > n<sub>0</sub>).
|
||||||
|
|
||||||
Определения О-символики для О Большого и О Малого похожи. Главное отличие в том,
|
Определения О-символики для О Большого и О Малого похожи. Главное отличие в том,
|
||||||
что если f(n) = O(g(n)), тогда условие f(n) <= c g(n) выполняется, если _**существует**_
|
что если 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) = o(g(n)), тогда условие f(n) < c g(n) выполняется
|
||||||
для _**всех**_ констант c > 0.
|
для _**всех**_ констант c > 0.
|
||||||
|
|
||||||
### Омега Малое
|
### Омега Малое
|
||||||
Омега Малое, записывается как **ω**, — это асимптотическая запись для оценки
|
Омега Малое, записывается как **ω**, — это асимптотическая запись для оценки
|
||||||
верхней границы времени выполнения алгоритма при условии, что граница не является
|
верхней границы времени выполнения алгоритма при условии, что граница не является
|
||||||
асимптотически точной.
|
асимптотически точной.
|
||||||
|
|
||||||
`f(n)` является ω(g(n)), если можно подобрать такие действительные константы,
|
`f(n)` является ω(g(n)), если можно подобрать такие действительные константы,
|
||||||
что для всех c (c > 0) найдётся n<sub>0</sub> (n<sub>0</sub> > 0), так
|
что для всех 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)` > `c g(n)` выполняется для всех n (n > n<sub>0</sub>).
|
||||||
|
|
||||||
Определения Ω-символики и ω-символики похожи. Главное отличие в том, что
|
Определения Ω-символики и ω-символики похожи. Главное отличие в том, что
|
||||||
если f(n) = Ω(g(n)), тогда условие f(n) >= c g(n) выполняется, если _**существует**_
|
если 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)), тогда условие f(n) > c g(n)
|
||||||
выполняется для _**всех**_ констант c > 0.
|
выполняется для _**всех**_ констант c > 0.
|
||||||
|
|
||||||
### Тета
|
### Тета
|
||||||
Тета, записывается как **Θ**, — это асимптотическая запись для оценки
|
Тета, записывается как **Θ**, — это асимптотическая запись для оценки
|
||||||
_***асимптотически точной границы***_ времени выполнения алгоритма.
|
_***асимптотически точной границы***_ времени выполнения алгоритма.
|
||||||
|
|
||||||
`f(n)` является Θ(g(n)), если для некоторых действительных
|
`f(n)` является Θ(g(n)), если для некоторых действительных
|
||||||
констант c1, c2 и n<sub>0</sub> (c1 > 0, c2 > 0, n<sub>0</sub> > 0)
|
констант 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>).
|
`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)) означает, что `f(n)` является O(g(n))
|
||||||
и `f(n)` является Ω(g(n)).
|
и `f(n)` является Ω(g(n)).
|
||||||
|
|
||||||
О Большое — основной инструмент для анализа сложности алгоритмов.
|
О Большое — основной инструмент для анализа сложности алгоритмов.
|
||||||
Также см. примеры по ссылкам.
|
Также см. примеры по ссылкам.
|
||||||
|
|
||||||
### Заключение
|
### Заключение
|
||||||
Такую тему сложно изложить кратко, поэтому обязательно стоит пройти по ссылкам и
|
Такую тему сложно изложить кратко, поэтому обязательно стоит пройти по ссылкам и
|
||||||
посмотреть дополнительную литературу. В ней даётся более глубокое описание с
|
посмотреть дополнительную литературу. В ней даётся более глубокое описание с
|
||||||
определениями и примерами.
|
определениями и примерами.
|
||||||
|
|
||||||
|
|
||||||
## Дополнительная литература
|
## Дополнительная литература
|
||||||
|
|
||||||
* [Алгоритмы на Java](https://www.ozon.ru/context/detail/id/18319699/)
|
* [Алгоритмы на Java](https://www.ozon.ru/context/detail/id/18319699/)
|
||||||
* [Алгоритмы. Построение и анализ](https://www.ozon.ru/context/detail/id/33769775/)
|
* [Алгоритмы. Построение и анализ](https://www.ozon.ru/context/detail/id/33769775/)
|
||||||
|
|
||||||
## Ссылки
|
## Ссылки
|
||||||
|
|
||||||
* [Оценки времени исполнения. Символ O()](http://algolist.manual.ru/misc/o_n.php)
|
* [Оценки времени исполнения. Символ O()](http://algolist.manual.ru/misc/o_n.php)
|
||||||
* [Асимптотический анализ и теория вероятностей](https://www.lektorium.tv/course/22903)
|
* [Асимптотический анализ и теория вероятностей](https://www.lektorium.tv/course/22903)
|
||||||
|
|
||||||
## Ссылки (англ.)
|
## Ссылки (англ.)
|
||||||
|
|
||||||
* [Algorithms, Part I](https://www.coursera.org/learn/algorithms-part1)
|
* [Algorithms, Part I](https://www.coursera.org/learn/algorithms-part1)
|
||||||
* [Cheatsheet 1](http://web.mit.edu/broder/Public/asymptotics-cheatsheet.pdf)
|
* [Cheatsheet 1](http://web.mit.edu/broder/Public/asymptotics-cheatsheet.pdf)
|
||||||
* [Cheatsheet 2](http://bigocheatsheet.com/)
|
* [Cheatsheet 2](http://bigocheatsheet.com/)
|
||||||
|
|
||||||
|
@@ -1,125 +1,125 @@
|
|||||||
---
|
---
|
||||||
language: SQL
|
language: SQL
|
||||||
contributors:
|
contributors:
|
||||||
- ["Metin Yalçınkaya", "https://github.com/mtnylnky"]
|
- ["Metin Yalçınkaya", "https://github.com/mtnylnky"]
|
||||||
lang: tr-tr
|
lang: tr-tr
|
||||||
filename: learnsql-tr.sql
|
filename: learnsql-tr.sql
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
-- Yorumlar iki tire ile başlar
|
-- Yorumlar iki tire ile başlar
|
||||||
|
|
||||||
-- KISITLAR
|
-- KISITLAR
|
||||||
Not null -- Bir kolon asla boş olamaz
|
Not null -- Bir kolon asla boş olamaz
|
||||||
default -- Boş olan yerlere varsayılan bir değer atar
|
default -- Boş olan yerlere varsayılan bir değer atar
|
||||||
unique -- Bir kolondaki tüm değerlerin farklı olması kısıtlaması
|
unique -- Bir kolondaki tüm değerlerin farklı olması kısıtlaması
|
||||||
primary key -- Bir tablodaki her veri için kimlik bilgisi niteliğindedir
|
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
|
check -- Bir kolondaki değerlerin belli bir kısıtlamayı sağlamasını sağlar
|
||||||
|
|
||||||
-- Tablo oluşturulur
|
-- Tablo oluşturulur
|
||||||
CREATE TABLE tablo1 ();
|
CREATE TABLE tablo1 ();
|
||||||
|
|
||||||
-- Tabloyu içerisinde kolonlar ile oluşturma
|
-- Tabloyu içerisinde kolonlar ile oluşturma
|
||||||
CREATE TABLE tablo1(id INTEGER PRIMARY KEY NOT NULL UNIQUE, ad TEXT, soyad TEXT, yas INTEGER);
|
CREATE TABLE tablo1(id INTEGER PRIMARY KEY NOT NULL UNIQUE, ad TEXT, soyad TEXT, yas INTEGER);
|
||||||
|
|
||||||
-- TABLO varlığını kontrol eder
|
-- TABLO varlığını kontrol eder
|
||||||
.table
|
.table
|
||||||
|
|
||||||
-- Veri tabanında olan bütün tabloları görüntüler.
|
-- Veri tabanında olan bütün tabloları görüntüler.
|
||||||
.schema
|
.schema
|
||||||
|
|
||||||
-- Satır ekle
|
-- Satır ekle
|
||||||
INSERT INTO tablo1 ( ad, soyad) VALUES ("Deger1","Deger2");
|
INSERT INTO tablo1 ( ad, soyad) VALUES ("Deger1","Deger2");
|
||||||
|
|
||||||
-- Veritabanında tablo üzerindeki verileri görüntüle
|
-- Veritabanında tablo üzerindeki verileri görüntüle
|
||||||
-- Sadece 'ad' gibi sınırlı bir veri için
|
-- Sadece 'ad' gibi sınırlı bir veri için
|
||||||
SELECT ad FROM tablo1;
|
SELECT ad FROM tablo1;
|
||||||
-- Bütün veriler için
|
-- Bütün veriler için
|
||||||
SELECT * FROM tablo1;
|
SELECT * FROM tablo1;
|
||||||
|
|
||||||
-- Veri güncelleme
|
-- Veri güncelleme
|
||||||
UPDATE tablo1 SET ad = "deger1-2"; WHERE name = "Deger1";
|
UPDATE tablo1 SET ad = "deger1-2"; WHERE name = "Deger1";
|
||||||
|
|
||||||
-- Satır sil
|
-- Satır sil
|
||||||
DELETE FROM tablo1 WHERE id = 1;
|
DELETE FROM tablo1 WHERE id = 1;
|
||||||
DELETE FROM tablo1 WHERE ad = "Deger1" OR ad = "Deger2";
|
DELETE FROM tablo1 WHERE ad = "Deger1" OR ad = "Deger2";
|
||||||
|
|
||||||
-- Tabloya sonradan kolon ekleme
|
-- Tabloya sonradan kolon ekleme
|
||||||
ALTER TABLE tablo1 ADD COLUMN email TEXT;
|
ALTER TABLE tablo1 ADD COLUMN email TEXT;
|
||||||
|
|
||||||
-- Tablodaki kolon adı değiştirme
|
-- Tablodaki kolon adı değiştirme
|
||||||
EXEC sp_rename ' tablo1.[ad]', Ad, 'COLUMN';
|
EXEC sp_rename ' tablo1.[ad]', Ad, 'COLUMN';
|
||||||
|
|
||||||
-- Tablo adı değiştirme
|
-- Tablo adı değiştirme
|
||||||
ALTER TABLE table1 RENAME TO Table1;
|
ALTER TABLE table1 RENAME TO Table1;
|
||||||
|
|
||||||
-- Tabloyu silme
|
-- Tabloyu silme
|
||||||
DROP TABLE Table1;
|
DROP TABLE Table1;
|
||||||
|
|
||||||
-- BİR TABLOYU BAŞKA TABLO KULLANARAK DOLDURMAK
|
-- BİR TABLOYU BAŞKA TABLO KULLANARAK DOLDURMAK
|
||||||
INSERT INTO Tablo2 SELECT id,ad, soyad, email from Tablo1;
|
INSERT INTO Tablo2 SELECT id,ad, soyad, email from Tablo1;
|
||||||
|
|
||||||
-- LIKE KOMUTU
|
-- LIKE KOMUTU
|
||||||
-- Belirli bir kritere göre arama yaparken kullanılır
|
-- Belirli bir kritere göre arama yaparken kullanılır
|
||||||
-- Adı 'A' ile başlayan veriler
|
-- Adı 'A' ile başlayan veriler
|
||||||
SELECT * FROM tablo1 WHERE adi LIKE "A%";
|
SELECT * FROM tablo1 WHERE adi LIKE "A%";
|
||||||
-- İçinde 'A' olan veriler
|
-- İçinde 'A' olan veriler
|
||||||
SELECT * FROM tablo1 WHERE adi LIKE "%A%";
|
SELECT * FROM tablo1 WHERE adi LIKE "%A%";
|
||||||
|
|
||||||
-- LIMIT KOMUTU
|
-- LIMIT KOMUTU
|
||||||
-- Gösterilen satır sayısını sınırlamak için
|
-- Gösterilen satır sayısını sınırlamak için
|
||||||
SELECT * FROM Tablo1 LIMIT 6;
|
SELECT * FROM Tablo1 LIMIT 6;
|
||||||
-- Gösterilen satırları belirli bir noktadan başlamak üzere sınırlamak için
|
-- Gösterilen satırları belirli bir noktadan başlamak üzere sınırlamak için
|
||||||
SELECT * FROM Tablo1 LIMIT 6 OFFSET 3;
|
SELECT * FROM Tablo1 LIMIT 6 OFFSET 3;
|
||||||
|
|
||||||
-- ORDER BY KOMUTU
|
-- ORDER BY KOMUTU
|
||||||
-- Herhangi bir kolona göre gösterilen değerleri azalan veya artan şekilde sıralamak için
|
-- 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 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 ASC
|
||||||
SELECT * FROM Tablo1 ORDER BY yas DESC
|
SELECT * FROM Tablo1 ORDER BY yas DESC
|
||||||
|
|
||||||
-- DISTINCT ANAHTAR SÖZCÜĞÜ
|
-- DISTINCT ANAHTAR SÖZCÜĞÜ
|
||||||
-- Bu anahtar sözcükle sadece farklı değerler gösterilir.
|
-- Bu anahtar sözcükle sadece farklı değerler gösterilir.
|
||||||
SELECT DISTINCT yas FROM tablo1;
|
SELECT DISTINCT yas FROM tablo1;
|
||||||
|
|
||||||
-- JOIN KOMUTU
|
-- JOIN KOMUTU
|
||||||
-- CROSS JOIN
|
-- CROSS JOIN
|
||||||
-- Cross join bir tablodaki her satırı ikinci tablodaki bir satır ile eşleştirmek için kulanılır.
|
-- 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.
|
-- 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 ... FROM table1 CROSS JOIN table2 …
|
||||||
SELECT ad, yas FROM Tablo1 CROSS JOIN Tablo2;
|
SELECT ad, yas FROM Tablo1 CROSS JOIN Tablo2;
|
||||||
|
|
||||||
-- INNER JOIN
|
-- INNER JOIN
|
||||||
-- Inner join iki tablodaki ortak kolon değerlerini kullanarak bir sonuç üretir.
|
-- Inner join iki tablodaki ortak kolon değerlerini kullanarak bir sonuç üretir.
|
||||||
SELECT ... FROM table1 [INNER] JOIN table2 ON conditional_expression …
|
SELECT ... FROM table1 [INNER] JOIN table2 ON conditional_expression …
|
||||||
SELECT ad, yas FROM Tablo1 INNER JOIN Tablo2 ON Tablo1.ad = Tablo2.soyad;
|
SELECT ad, yas FROM Tablo1 INNER JOIN Tablo2 ON Tablo1.ad = Tablo2.soyad;
|
||||||
|
|
||||||
-- OUTER JOIN
|
-- OUTER JOIN
|
||||||
-- Outer join iki tablodaki ortak kolon değerlerinin dışında kalanları kullanarak bir sonuç üretir.
|
-- 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;
|
SELECT isci_num, isim, dept FROM Tablo1 LEFT OUTER JOIN Tablo2 ON Tablo1.id = Tablo2.isci_num;
|
||||||
|
|
||||||
-- ÇEKİRDEK FONKSİYONLAR
|
-- ÇEKİRDEK FONKSİYONLAR
|
||||||
COUNT -- Sayma
|
COUNT -- Sayma
|
||||||
AVG -- Ortalama
|
AVG -- Ortalama
|
||||||
ABS -- Mutlak değer
|
ABS -- Mutlak değer
|
||||||
SUM -- Toplam
|
SUM -- Toplam
|
||||||
RANDOM -- Rastgele
|
RANDOM -- Rastgele
|
||||||
ROUND -- Yuvarlama
|
ROUND -- Yuvarlama
|
||||||
MAX -- Maksimim
|
MAX -- Maksimim
|
||||||
MIN -- Minimum
|
MIN -- Minimum
|
||||||
UPPER -- Büyük Harf
|
UPPER -- Büyük Harf
|
||||||
LOWER -- Küçük Harf
|
LOWER -- Küçük Harf
|
||||||
LENGTH -- Uzunluk
|
LENGTH -- Uzunluk
|
||||||
CURRENT_TIMESTAMP -- Zaman
|
CURRENT_TIMESTAMP -- Zaman
|
||||||
|
|
||||||
SELECT max(yas) FROM Table1;
|
SELECT max(yas) FROM Table1;
|
||||||
SELECT min(yas) FROM Table1;
|
SELECT min(yas) FROM Table1;
|
||||||
SELECT avg(yas) FROM Table1;
|
SELECT avg(yas) FROM Table1;
|
||||||
SELECT * From Table1 WHERE yas ==18;
|
SELECT * From Table1 WHERE yas ==18;
|
||||||
SELECT sum(yas) FROM Table1;
|
SELECT sum(yas) FROM Table1;
|
||||||
SELECT random() AS Random;
|
SELECT random() AS Random;
|
||||||
SELECT upper(ad) FROM Table1;
|
SELECT upper(ad) FROM Table1;
|
||||||
SELECT lower(ad) FROM Table1;
|
SELECT lower(ad) FROM Table1;
|
||||||
SELECT ad, length(ad) FROM Table1;
|
SELECT ad, length(ad) FROM Table1;
|
||||||
```
|
```
|
@@ -1,328 +1,328 @@
|
|||||||
---
|
---
|
||||||
category: tool
|
category: tool
|
||||||
tool: git
|
tool: git
|
||||||
contributors:
|
contributors:
|
||||||
- ["Jake Prather", "http://github.com/JakeHP"]
|
- ["Jake Prather", "http://github.com/JakeHP"]
|
||||||
- ["Vinh Nguyen", "https://twitter.com/vinhnx"]
|
- ["Vinh Nguyen", "https://twitter.com/vinhnx"]
|
||||||
filename: LearnGit-vi.txt
|
filename: LearnGit-vi.txt
|
||||||
lang: vi-vn
|
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).
|
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
|
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à
|
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.
|
quản lý mã nguồn của bạn.
|
||||||
|
|
||||||
## Khái Niệm Versioning
|
## Khái Niệm Versioning
|
||||||
|
|
||||||
### Version Control là gì?
|
### 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.
|
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
|
### 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 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.
|
* 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.
|
* 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)
|
[Thông tin thêm](http://git-scm.com/book/en/Getting-Started-About-Version-Control)
|
||||||
|
|
||||||
### Tại Sao Dùng Git?
|
### Tại Sao Dùng Git?
|
||||||
|
|
||||||
* Có thể hoạt động offline.
|
* Có thể hoạt động offline.
|
||||||
* Cộng tác với nhau rất dễ dàng!
|
* Cộng tác với nhau rất dễ dàng!
|
||||||
* Phân nhánh dễ dàng!
|
* Phân nhánh dễ dàng!
|
||||||
* Trộn (Merging)
|
* Trộn (Merging)
|
||||||
* Git nhanh.
|
* Git nhanh.
|
||||||
* Git linh hoạt.
|
* Git linh hoạt.
|
||||||
|
|
||||||
## Kiến Trúc Git
|
## Kiến Trúc Git
|
||||||
|
|
||||||
|
|
||||||
### Repository
|
### 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,
|
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.
|
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.
|
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 (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.
|
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)
|
[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)
|
### 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
|
Đâ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
|
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 (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
|
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
|
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.
|
repository.
|
||||||
|
|
||||||
### Commit
|
### 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.
|
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
|
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!
|
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
|
||||||
|
|
||||||
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,
|
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.
|
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 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 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.
|
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
|
### 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 Computer Scientists](http://eagain.net/articles/git-for-computer-scientists/)
|
||||||
* [Git For Designers](http://hoth.entp.com/output/git_for_designers.html)
|
* [Git For Designers](http://hoth.entp.com/output/git_for_designers.html)
|
||||||
|
|
||||||
|
|
||||||
## Các Lệnh
|
## Các Lệnh
|
||||||
|
|
||||||
|
|
||||||
### init
|
### init
|
||||||
|
|
||||||
Tạo một repo Git rỗng. Các cài đặt, thông tin lưu trữ... của Git
|
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".
|
được lưu ở một thư mục tên là ".git".
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ git init
|
$ git init
|
||||||
```
|
```
|
||||||
|
|
||||||
### config
|
### config
|
||||||
|
|
||||||
Để chỉnh tùy chọn. Bất kể là cho repo, hay cho hệ thống, hay điều chỉnh
|
Để 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)
|
toàn cục (global)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# In Ra & Và Gán Một Số Biến Tùy Chỉnh Cơ Bản (Toàn cục - Global)
|
# 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.email
|
||||||
$ git config --global user.name
|
$ git config --global user.name
|
||||||
|
|
||||||
$ git config --global user.email "MyEmail@Zoho.com"
|
$ git config --global user.email "MyEmail@Zoho.com"
|
||||||
$ git config --global user.name "My Name"
|
$ git config --global user.name "My Name"
|
||||||
```
|
```
|
||||||
|
|
||||||
[Tìm hiểu thêm về git config.](http://git-scm.com/docs/git-config)
|
[Tìm hiểu thêm về git config.](http://git-scm.com/docs/git-config)
|
||||||
|
|
||||||
### help
|
### 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ỉ để
|
Để 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.
|
nhắc bạn một số cú pháp.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Xem nhanh các lệnh có sẵn
|
# Xem nhanh các lệnh có sẵn
|
||||||
$ git help
|
$ git help
|
||||||
|
|
||||||
# Xem tất các các lệnh
|
# Xem tất các các lệnh
|
||||||
$ git help -a
|
$ git help -a
|
||||||
|
|
||||||
# Lệnh help riêng biệt - tài liệu người dùng
|
# Lệnh help riêng biệt - tài liệu người dùng
|
||||||
# git help <command_here>
|
# git help <command_here>
|
||||||
$ git help add
|
$ git help add
|
||||||
$ git help commit
|
$ git help commit
|
||||||
$ git help init
|
$ git help init
|
||||||
```
|
```
|
||||||
|
|
||||||
### status
|
### 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 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.
|
hiện tại.
|
||||||
|
|
||||||
|
|
||||||
```bash
|
```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
|
# 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
|
$ git status
|
||||||
|
|
||||||
# Để xem các "tid bits" về git status
|
# Để xem các "tid bits" về git status
|
||||||
$ git help status
|
$ git help status
|
||||||
```
|
```
|
||||||
|
|
||||||
### add
|
### 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
|
Để 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!
|
tree/thư mục hiện tại, chúng sẽ không được kèm theo trong các commit!
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# thêm một file vào thư mục hiện tại
|
# thêm một file vào thư mục hiện tại
|
||||||
$ git add HelloWorld.java
|
$ git add HelloWorld.java
|
||||||
|
|
||||||
# thêm một file vào một thư mục khác
|
# thêm một file vào một thư mục khác
|
||||||
$ git add /path/to/file/HelloWorld.c
|
$ git add /path/to/file/HelloWorld.c
|
||||||
|
|
||||||
# Hỗ trợ Regular Expression!
|
# Hỗ trợ Regular Expression!
|
||||||
$ git add ./*.java
|
$ git add ./*.java
|
||||||
```
|
```
|
||||||
|
|
||||||
### branch
|
### 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.
|
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
|
```bash
|
||||||
# liệt kê các branch đang có và ở remote
|
# liệt kê các branch đang có và ở remote
|
||||||
$ git branch -a
|
$ git branch -a
|
||||||
|
|
||||||
# tạo branch mới
|
# tạo branch mới
|
||||||
$ git branch myNewBranch
|
$ git branch myNewBranch
|
||||||
|
|
||||||
# xóa một branch
|
# xóa một branch
|
||||||
$ git branch -d myBranch
|
$ git branch -d myBranch
|
||||||
|
|
||||||
# đặt tên lại một branch
|
# đặt tên lại một branch
|
||||||
# git branch -m <oldname> <newname>
|
# git branch -m <oldname> <newname>
|
||||||
$ git branch -m myBranchName myNewBranchName
|
$ git branch -m myBranchName myNewBranchName
|
||||||
|
|
||||||
# chỉnh sửa diễn giải của một branch
|
# chỉnh sửa diễn giải của một branch
|
||||||
$ git branch myBranchName --edit-description
|
$ git branch myBranchName --edit-description
|
||||||
```
|
```
|
||||||
|
|
||||||
### checkout
|
### 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ể.
|
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
|
```bash
|
||||||
# Checkout (chuyển) một repo - mặc định là nhánh master
|
# Checkout (chuyển) một repo - mặc định là nhánh master
|
||||||
$ git checkout
|
$ git checkout
|
||||||
# Checkout một nhánh cụ thể
|
# Checkout một nhánh cụ thể
|
||||||
$ git checkout branchName
|
$ 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>"
|
# 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
|
$ git checkout -b newBranch
|
||||||
```
|
```
|
||||||
|
|
||||||
### clone
|
### 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
|
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à
|
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.
|
cho phép bạn push đến một remote branch.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Nhân bản learnxinyminutes-docs
|
# Nhân bản learnxinyminutes-docs
|
||||||
$ git clone https://github.com/adambard/learnxinyminutes-docs.git
|
$ git clone https://github.com/adambard/learnxinyminutes-docs.git
|
||||||
```
|
```
|
||||||
|
|
||||||
### commit
|
### 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.
|
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
|
```bash
|
||||||
# commit với một ghi chú
|
# commit với một ghi chú
|
||||||
$ git commit -m "Added multiplyNumbers() function to HelloWorld.c"
|
$ git commit -m "Added multiplyNumbers() function to HelloWorld.c"
|
||||||
```
|
```
|
||||||
|
|
||||||
### diff
|
### 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.
|
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
|
```bash
|
||||||
# Hiển thị sự khác biệt giữa thư mục hiện tại và index
|
# Hiển thị sự khác biệt giữa thư mục hiện tại và index
|
||||||
$ git diff
|
$ git diff
|
||||||
|
|
||||||
# Hiển thị khác biệt giữa index và commit mới nhất.
|
# Hiển thị khác biệt giữa index và commit mới nhất.
|
||||||
$ git diff --cached
|
$ 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
|
# 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
|
$ git diff HEAD
|
||||||
```
|
```
|
||||||
|
|
||||||
### grep
|
### grep
|
||||||
|
|
||||||
Cho phép bạn tìm kiếm nhanh một repo.
|
Cho phép bạn tìm kiếm nhanh một repo.
|
||||||
|
|
||||||
Các tinh chỉnh tùy chọn:
|
Các tinh chỉnh tùy chọn:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Cảm ơn Travis Jeffery vì những lệnh này
|
# 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
|
# Đặ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
|
$ 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
|
# 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"
|
$ git config --global alias.g "grep --break --heading --line-number"
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Tìm "variableName" trong tất cả các file Java
|
# Tìm "variableName" trong tất cả các file Java
|
||||||
$ git grep 'variableName' -- '*.java'
|
$ git grep 'variableName' -- '*.java'
|
||||||
|
|
||||||
# Tìm một dòng mà có chứa "arrayListName" và, "add" hoặc "remove"
|
# 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 \)
|
$ git grep -e 'arrayListName' --and \( -e add -e remove \)
|
||||||
```
|
```
|
||||||
|
|
||||||
Google để xem thêm các ví dụ
|
Google để xem thêm các ví dụ
|
||||||
[Git Grep Ninja](http://travisjeffery.com/b/2012/02/search-a-git-repo-like-a-ninja)
|
[Git Grep Ninja](http://travisjeffery.com/b/2012/02/search-a-git-repo-like-a-ninja)
|
||||||
|
|
||||||
### log
|
### log
|
||||||
|
|
||||||
Hiển thị các commit đến repo.
|
Hiển thị các commit đến repo.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Hiện tất cả các commit
|
# Hiện tất cả các commit
|
||||||
$ git log
|
$ git log
|
||||||
|
|
||||||
# Hiện X commit
|
# Hiện X commit
|
||||||
$ git log -n 10
|
$ git log -n 10
|
||||||
|
|
||||||
# Chỉ hiện các commit đã merge merge commits
|
# Chỉ hiện các commit đã merge merge commits
|
||||||
$ git log --merges
|
$ git log --merges
|
||||||
```
|
```
|
||||||
|
|
||||||
### merge
|
### merge
|
||||||
|
|
||||||
"Trộn" các thay đổi từ commit bên ngoài vào trong nhánh hiện tại.
|
"Trộn" các thay đổi từ commit bên ngoài vào trong nhánh hiện tại.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Merge branch cụ thể vào branch hiện tại.
|
# Merge branch cụ thể vào branch hiện tại.
|
||||||
$ git merge branchName
|
$ git merge branchName
|
||||||
|
|
||||||
# Luôn khởi tạo một merge commit khi trộn (merge)
|
# Luôn khởi tạo một merge commit khi trộn (merge)
|
||||||
$ git merge --no-ff branchName
|
$ git merge --no-ff branchName
|
||||||
```
|
```
|
||||||
|
|
||||||
### mv
|
### mv
|
||||||
|
|
||||||
Đặt lại tên hoặc di chuyển một file
|
Đặt lại tên hoặc di chuyển một file
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Đặt lại tên một file
|
# Đặt lại tên một file
|
||||||
$ git mv HelloWorld.c HelloNewWorld.c
|
$ git mv HelloWorld.c HelloNewWorld.c
|
||||||
|
|
||||||
# Di chuyển một file
|
# Di chuyển một file
|
||||||
$ git mv HelloWorld.c ./new/path/HelloWorld.c
|
$ git mv HelloWorld.c ./new/path/HelloWorld.c
|
||||||
|
|
||||||
# Buộc đặt lại tên hoặc di chuyển
|
# Buộc đặt lại tên hoặc di chuyển
|
||||||
# "existingFile" đã tồn tại trong thự mục, sẽ bị ghi đè
|
# "existingFile" đã tồn tại trong thự mục, sẽ bị ghi đè
|
||||||
$ git mv -f myFile existingFile
|
$ git mv -f myFile existingFile
|
||||||
```
|
```
|
||||||
|
|
||||||
### pull
|
### pull
|
||||||
|
|
||||||
Pull về từ một repo và merge nó vào branch khác.
|
Pull về từ một repo và merge nó vào branch khác.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Cập nhật repo local của bạn, bằng cách merge các thay đổi mới
|
# 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".
|
# từ remote "origin" và nhánh "master".
|
||||||
# git pull <remote> <branch>
|
# git pull <remote> <branch>
|
||||||
# git pull => hoàn toàn mặc định như => git pull origin master
|
# git pull => hoàn toàn mặc định như => git pull origin master
|
||||||
$ git pull origin master
|
$ git pull origin master
|
||||||
|
|
||||||
# Merge các thay đổi từ remote branch và rebase
|
# 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>"
|
# 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
|
$ git pull origin master --rebase
|
||||||
```
|
```
|
||||||
|
|
||||||
### push
|
### push
|
||||||
|
|
||||||
push và merge các thay đổi từ một branch đến một remote & branch.
|
push và merge các thay đổi từ một branch đến một remote & branch.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Push và merge các thay đổi từ một repo local đến một
|
# 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".
|
# remote có tên là "origin" và nhánh "master".
|
||||||
@@ -334,68 +334,68 @@ $ git push origin master
|
|||||||
$ git push -u 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:
|
# 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
|
$ git push
|
||||||
```
|
```
|
||||||
|
|
||||||
### rebase (thận trọng)
|
### 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.
|
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*.
|
*Không rebase các commit mà bạn đã push đến một repo công khai*.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Rebase experimentBranch lên master
|
# Rebase experimentBranch lên master
|
||||||
# git rebase <basebranch> <topicbranch>
|
# git rebase <basebranch> <topicbranch>
|
||||||
$ git rebase master experimentBranch
|
$ git rebase master experimentBranch
|
||||||
```
|
```
|
||||||
|
|
||||||
[Đọc Thêm.](http://git-scm.com/book/en/Git-Branching-Rebasing)
|
[Đọc Thêm.](http://git-scm.com/book/en/Git-Branching-Rebasing)
|
||||||
|
|
||||||
### reset (thận trọng)
|
### 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,
|
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
|
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ì.
|
biết mình đang làm gì.
|
||||||
|
|
||||||
```bash
|
```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)
|
# 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
|
$ 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
|
# 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
|
$ 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)
|
# 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.
|
# tất cả thay đổi vẫn duy trì trong thư mục.
|
||||||
$ git reset 31f2bb1
|
$ git reset 31f2bb1
|
||||||
|
|
||||||
# Di chuyển nhánh hiện tại lùi về một commit cụ thể
|
# 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
|
# 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ể).
|
# sau một commit cụ thể).
|
||||||
$ git reset --hard 31f2bb1
|
$ git reset --hard 31f2bb1
|
||||||
```
|
```
|
||||||
|
|
||||||
### rm
|
### rm
|
||||||
|
|
||||||
Ngược lại với git add, git rm xóa file từ tree đang làm việc.
|
Ngược lại với git add, git rm xóa file từ tree đang làm việc.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# xóa HelloWorld.c
|
# xóa HelloWorld.c
|
||||||
$ git rm HelloWorld.c
|
$ git rm HelloWorld.c
|
||||||
|
|
||||||
# Xóa file từ thư mục khác
|
# Xóa file từ thư mục khác
|
||||||
$ git rm /pather/to/the/file/HelloWorld.c
|
$ git rm /pather/to/the/file/HelloWorld.c
|
||||||
```
|
```
|
||||||
|
|
||||||
## Thông tin thêm
|
## Thông tin thêm
|
||||||
|
|
||||||
* [tryGit - A fun interactive way to learn Git.](http://try.github.io/levels/1/challenges/1)
|
* [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 - Video Tutorials](http://git-scm.com/videos)
|
||||||
|
|
||||||
* [git-scm - Documentation](http://git-scm.com/docs)
|
* [git-scm - Documentation](http://git-scm.com/docs)
|
||||||
|
|
||||||
* [Atlassian Git - Tutorials & Workflows](https://www.atlassian.com/git/)
|
* [Atlassian Git - Tutorials & Workflows](https://www.atlassian.com/git/)
|
||||||
|
|
||||||
* [SalesForce Cheat Sheet](https://na1.salesforce.com/help/doc/en/salesforce_git_developer_cheatsheet.pdf)
|
* [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)
|
* [Git - the simple guide](http://rogerdudler.github.io/git-guide/index.html)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,316 +1,316 @@
|
|||||||
---
|
---
|
||||||
language: Objective-C
|
language: Objective-C
|
||||||
contributors:
|
contributors:
|
||||||
- ["Eugene Yagrushkin", "www.about.me/yagrushkin"]
|
- ["Eugene Yagrushkin", "www.about.me/yagrushkin"]
|
||||||
- ["Yannick Loriot", "https://github.com/YannickL"]
|
- ["Yannick Loriot", "https://github.com/YannickL"]
|
||||||
lang: vi-vn
|
lang: vi-vn
|
||||||
filename: LearnObjectiveC-vi.m
|
filename: LearnObjectiveC-vi.m
|
||||||
---
|
---
|
||||||
|
|
||||||
Objective-C là 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 và các framework tương ứng của họ, Cocoa và Cocoa Touch.
|
Objective-C là 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 và các framework tương ứng của họ, Cocoa và Cocoa Touch.
|
||||||
Nó là một ngôn ngữ lập trình mục đích tổng quát, hướng đối tượng có 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.
|
Nó là một ngôn ngữ lập trình mục đích tổng quát, hướng đối tượng có 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
|
```objective-c
|
||||||
// Chú thích dòng đơn bắt đầu với //
|
// Chú thích dòng đơn bắt đầu với //
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Chú thích đa dòng trông như thế này.
|
Chú thích đa dòng trông như thế này.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Nhập các headers của framework Foundation với cú pháp #import
|
// Nhập các headers của framework Foundation với cú pháp #import
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "MyClass.h"
|
#import "MyClass.h"
|
||||||
|
|
||||||
// Đầu vào chương trình của bạn là một hàm gọi là
|
// Đầu vào chương trình của bạn là một hàm gọi là
|
||||||
// main với một kiểu trả về kiểu integer.
|
// main với một kiểu trả về kiểu integer.
|
||||||
int main (int argc, const char * argv[])
|
int main (int argc, const char * argv[])
|
||||||
{
|
{
|
||||||
// Tạo một autorelease pool để quản lý bộ nhớ vào chương trình
|
// Tạo một autorelease pool để quản lý bộ nhớ vào chương trình
|
||||||
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
|
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
// Sử dụng hàm NSLog() để in ra các dòng lệnh vào console
|
// 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!"
|
NSLog(@"Hello World!"); // Print the string "Hello World!"
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
// Kiểu & Biến (Types & Variables)
|
// Kiểu & Biến (Types & Variables)
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
|
|
||||||
// Khai báo số nguyên
|
// Khai báo số nguyên
|
||||||
int myPrimitive1 = 1;
|
int myPrimitive1 = 1;
|
||||||
long myPrimitive2 = 234554664565;
|
long myPrimitive2 = 234554664565;
|
||||||
|
|
||||||
// Khai báo đối tượng
|
// 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
|
// Đặ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
|
MyClass *myObject1 = nil; // Strong
|
||||||
id myObject2 = nil; // Weak
|
id myObject2 = nil; // Weak
|
||||||
// %@ là một đối tượng
|
// %@ là một đối tượng
|
||||||
// 'miêu tả' ('desciption') là thông lệ để trình bày giá trị của các Đối tượng
|
// 'miêu tả' ('desciption') là 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)"
|
NSLog(@"%@ và %@", myObject1, [myObject2 description]); // In ra "(null) và (null)"
|
||||||
|
|
||||||
// Chuỗi
|
// Chuỗi
|
||||||
NSString *worldString = @"World";
|
NSString *worldString = @"World";
|
||||||
NSLog(@"Hello %@!", worldString); // In ra "Hello World!"
|
NSLog(@"Hello %@!", worldString); // In ra "Hello World!"
|
||||||
|
|
||||||
// Ký tự literals
|
// Ký tự literals
|
||||||
NSNumber *theLetterZNumber = @'Z';
|
NSNumber *theLetterZNumber = @'Z';
|
||||||
char theLetterZ = [theLetterZNumber charValue];
|
char theLetterZ = [theLetterZNumber charValue];
|
||||||
NSLog(@"%c", theLetterZ);
|
NSLog(@"%c", theLetterZ);
|
||||||
|
|
||||||
// Số nguyên literals
|
// Số nguyên literals
|
||||||
NSNumber *fortyTwoNumber = @42;
|
NSNumber *fortyTwoNumber = @42;
|
||||||
int fortyTwo = [fortyTwoNumber intValue];
|
int fortyTwo = [fortyTwoNumber intValue];
|
||||||
NSLog(@"%i", fortyTwo);
|
NSLog(@"%i", fortyTwo);
|
||||||
|
|
||||||
NSNumber *fortyTwoUnsignedNumber = @42U;
|
NSNumber *fortyTwoUnsignedNumber = @42U;
|
||||||
unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue];
|
unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue];
|
||||||
NSLog(@"%u", fortyTwoUnsigned);
|
NSLog(@"%u", fortyTwoUnsigned);
|
||||||
|
|
||||||
NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:42];
|
NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:42];
|
||||||
short fortyTwoShort = [fortyTwoShortNumber shortValue];
|
short fortyTwoShort = [fortyTwoShortNumber shortValue];
|
||||||
NSLog(@"%hi", fortyTwoShort);
|
NSLog(@"%hi", fortyTwoShort);
|
||||||
|
|
||||||
NSNumber *fortyTwoLongNumber = @42L;
|
NSNumber *fortyTwoLongNumber = @42L;
|
||||||
long fortyTwoLong = [fortyTwoLongNumber longValue];
|
long fortyTwoLong = [fortyTwoLongNumber longValue];
|
||||||
NSLog(@"%li", fortyTwoLong);
|
NSLog(@"%li", fortyTwoLong);
|
||||||
|
|
||||||
// Dấu phẩy động (floating point) literals
|
// Dấu phẩy động (floating point) literals
|
||||||
NSNumber *piFloatNumber = @3.141592654F;
|
NSNumber *piFloatNumber = @3.141592654F;
|
||||||
float piFloat = [piFloatNumber floatValue];
|
float piFloat = [piFloatNumber floatValue];
|
||||||
NSLog(@"%f", piFloat);
|
NSLog(@"%f", piFloat);
|
||||||
|
|
||||||
NSNumber *piDoubleNumber = @3.1415926535;
|
NSNumber *piDoubleNumber = @3.1415926535;
|
||||||
double piDouble = [piDoubleNumber doubleValue];
|
double piDouble = [piDoubleNumber doubleValue];
|
||||||
NSLog(@"%f", piDouble);
|
NSLog(@"%f", piDouble);
|
||||||
|
|
||||||
// BOOL literals
|
// BOOL literals
|
||||||
NSNumber *yesNumber = @YES;
|
NSNumber *yesNumber = @YES;
|
||||||
NSNumber *noNumber = @NO;
|
NSNumber *noNumber = @NO;
|
||||||
|
|
||||||
// Đối tượng Mảng
|
// Đối tượng Mảng
|
||||||
NSArray *anArray = @[@1, @2, @3, @4];
|
NSArray *anArray = @[@1, @2, @3, @4];
|
||||||
NSNumber *thirdNumber = anArray[2];
|
NSNumber *thirdNumber = anArray[2];
|
||||||
NSLog(@"Third number = %@", thirdNumber); // In ra "Third number = 3"
|
NSLog(@"Third number = %@", thirdNumber); // In ra "Third number = 3"
|
||||||
|
|
||||||
// Đối tượng Từ điển
|
// Đối tượng Từ điển
|
||||||
NSDictionary *aDictionary = @{ @"key1" : @"value1", @"key2" : @"value2" };
|
NSDictionary *aDictionary = @{ @"key1" : @"value1", @"key2" : @"value2" };
|
||||||
NSObject *valueObject = aDictionary[@"A Key"];
|
NSObject *valueObject = aDictionary[@"A Key"];
|
||||||
NSLog(@"Đối tượng = %@", valueObject); // In ra "Object = (null)"
|
NSLog(@"Đối tượng = %@", valueObject); // In ra "Object = (null)"
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
// Toán Tử (Operators)
|
// Toán Tử (Operators)
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
|
|
||||||
// Các toán tử cũng hoạt động giống như ngôn ngữ C
|
// Các toán tử cũng hoạt động giống như ngôn ngữ C
|
||||||
// Ví dụ:
|
// Ví dụ:
|
||||||
2 + 5; // => 7
|
2 + 5; // => 7
|
||||||
4.2f + 5.1f; // => 9.3f
|
4.2f + 5.1f; // => 9.3f
|
||||||
3 == 2; // => 0 (NO)
|
3 == 2; // => 0 (NO)
|
||||||
3 != 2; // => 1 (YES)
|
3 != 2; // => 1 (YES)
|
||||||
1 && 1; // => 1 (Logical and)
|
1 && 1; // => 1 (Logical and)
|
||||||
0 || 1; // => 1 (Logical or)
|
0 || 1; // => 1 (Logical or)
|
||||||
~0x0F; // => 0xF0 (bitwise negation)
|
~0x0F; // => 0xF0 (bitwise negation)
|
||||||
0x0F & 0xF0; // => 0x00 (bitwise AND)
|
0x0F & 0xF0; // => 0x00 (bitwise AND)
|
||||||
0x01 << 1; // => 0x02 (bitwise dịch trái (bởi 1))
|
0x01 << 1; // => 0x02 (bitwise dịch trái (bởi 1))
|
||||||
|
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
// Cấu Trúc Điều Khiển (Controls Structures)
|
// Cấu Trúc Điều Khiển (Controls Structures)
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
|
|
||||||
// Câu lệnh If-Else
|
// Câu lệnh If-Else
|
||||||
if (NO)
|
if (NO)
|
||||||
{
|
{
|
||||||
NSLog(@"I am never run");
|
NSLog(@"I am never run");
|
||||||
} else if (0)
|
} else if (0)
|
||||||
{
|
{
|
||||||
NSLog(@"I am also never run");
|
NSLog(@"I am also never run");
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
NSLog(@"I print");
|
NSLog(@"I print");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Câu lệnh Switch
|
// Câu lệnh Switch
|
||||||
switch (2)
|
switch (2)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
NSLog(@"I am never run");
|
NSLog(@"I am never run");
|
||||||
} break;
|
} break;
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
NSLog(@"I am also never run");
|
NSLog(@"I am also never run");
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
NSLog(@"I print");
|
NSLog(@"I print");
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Câu lệnh vòng lặp While
|
// Câu lệnh vòng lặp While
|
||||||
int ii = 0;
|
int ii = 0;
|
||||||
while (ii < 4)
|
while (ii < 4)
|
||||||
{
|
{
|
||||||
NSLog(@"%d,", ii++); // ii++ tăng dần, sau khi sử dụng giá trị của nó.
|
NSLog(@"%d,", ii++); // ii++ tăng dần, sau khi sử dụng giá trị của nó.
|
||||||
} // => in ra "0,"
|
} // => in ra "0,"
|
||||||
// "1,"
|
// "1,"
|
||||||
// "2,"
|
// "2,"
|
||||||
// "3,"
|
// "3,"
|
||||||
|
|
||||||
// Câu lệnh vòng lặp For
|
// Câu lệnh vòng lặp For
|
||||||
int jj;
|
int jj;
|
||||||
for (jj=0; jj < 4; jj++)
|
for (jj=0; jj < 4; jj++)
|
||||||
{
|
{
|
||||||
NSLog(@"%d,", jj);
|
NSLog(@"%d,", jj);
|
||||||
} // => in ra "0,"
|
} // => in ra "0,"
|
||||||
// "1,"
|
// "1,"
|
||||||
// "2,"
|
// "2,"
|
||||||
// "3,"
|
// "3,"
|
||||||
|
|
||||||
// Câu lệnh Foreach
|
// Câu lệnh Foreach
|
||||||
NSArray *values = @[@0, @1, @2, @3];
|
NSArray *values = @[@0, @1, @2, @3];
|
||||||
for (NSNumber *value in values)
|
for (NSNumber *value in values)
|
||||||
{
|
{
|
||||||
NSLog(@"%@,", value);
|
NSLog(@"%@,", value);
|
||||||
} // => in ra "0,"
|
} // => in ra "0,"
|
||||||
// "1,"
|
// "1,"
|
||||||
// "2,"
|
// "2,"
|
||||||
// "3,"
|
// "3,"
|
||||||
|
|
||||||
// Câu lệnh Try-Catch-Finally
|
// Câu lệnh Try-Catch-Finally
|
||||||
@try
|
@try
|
||||||
{
|
{
|
||||||
// Your statements here
|
// Your statements here
|
||||||
@throw [NSException exceptionWithName:@"FileNotFoundException"
|
@throw [NSException exceptionWithName:@"FileNotFoundException"
|
||||||
reason:@"Không Tìm Thấy Tập Tin trên Hệ Thống" userInfo:nil];
|
reason:@"Không Tìm Thấy Tập Tin trên Hệ Thống" userInfo:nil];
|
||||||
} @catch (NSException * e)
|
} @catch (NSException * e)
|
||||||
{
|
{
|
||||||
NSLog(@"Exception: %@", e);
|
NSLog(@"Exception: %@", e);
|
||||||
} @finally
|
} @finally
|
||||||
{
|
{
|
||||||
NSLog(@"Finally");
|
NSLog(@"Finally");
|
||||||
} // => in ra "Exception: Không Tìm Thấy Tập Tin trên Hệ Thống"
|
} // => in ra "Exception: Không Tìm Thấy Tập Tin trên Hệ Thống"
|
||||||
// "Finally"
|
// "Finally"
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
// Đối Tượng (Objects)
|
// Đối Tượng (Objects)
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
|
|
||||||
// Tạo một thực thể đối tượng bằng cách phân vùng nhớ và khởi tạo đối tượng đó.
|
// Tạo một thực thể đối tượng bằng cách phân vùng nhớ và 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
|
// 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];
|
MyClass *myObject = [[MyClass alloc] init];
|
||||||
|
|
||||||
// Mô 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)
|
// Mô 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)
|
||||||
// và các thực thể đối tượng với nhau.
|
// và 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; nó truyền thông điệp.
|
// Trong Objective-C một đối tượng không đơn thuần gọi phương thức; nó truyền thông điệp.
|
||||||
[myObject instanceMethodWithParameter:@"Steve Jobs"];
|
[myObject instanceMethodWithParameter:@"Steve Jobs"];
|
||||||
|
|
||||||
// Dọn dẹp vùng nhớ mà bạn đã dùng ở chương trình
|
// Dọn dẹp vùng nhớ mà bạn đã dùng ở chương trình
|
||||||
[pool drain];
|
[pool drain];
|
||||||
|
|
||||||
// Kết thúc chương trình
|
// Kết thúc chương trình
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
// Lớp và Hàm (Classes & Functions)
|
// Lớp và Hàm (Classes & Functions)
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
|
|
||||||
// Khai báo lớp của bạn ở một tập tin header (MyClass.h):
|
// Khai báo lớp của bạn ở một tập tin header (MyClass.h):
|
||||||
// Cú pháp Khai Báo Lớp:
|
// Cú pháp Khai Báo Lớp:
|
||||||
// @interface ClassName : ParentClassName <ImplementedProtocols>
|
// @interface ClassName : ParentClassName <ImplementedProtocols>
|
||||||
// {
|
// {
|
||||||
// Khai báo biến thành viên;
|
// Khai báo biến thành viên;
|
||||||
// }
|
// }
|
||||||
// -/+ (type) Khai báo method;
|
// -/+ (type) Khai báo method;
|
||||||
// @end
|
// @end
|
||||||
@interface MyClass : NSObject <MyProtocol>
|
@interface MyClass : NSObject <MyProtocol>
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
id data;
|
id data;
|
||||||
NSString *name;
|
NSString *name;
|
||||||
}
|
}
|
||||||
// Ký hiệu (notation) tiện ích để tự động khởi tạo public getter và setter
|
// Ký hiệu (notation) tiện ích để tự động khởi tạo public getter và setter
|
||||||
@property int count;
|
@property int count;
|
||||||
@property (copy) NSString *name; // Sao chép đối tượng trong quá trình gán.
|
@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.
|
@property (readonly) id data; // Chỉ khai báo phương thức getter.
|
||||||
|
|
||||||
// Phương thức
|
// Phương thức
|
||||||
+/- (return type)methodSignature:(Parameter Type *)parameterName;
|
+/- (return type)methodSignature:(Parameter Type *)parameterName;
|
||||||
|
|
||||||
// dấu '+' cho phương thức lớp
|
// dấu '+' cho phương thức lớp
|
||||||
+ (NSString *)classMethod;
|
+ (NSString *)classMethod;
|
||||||
|
|
||||||
// dấu '-' cho phương thức thực thể
|
// dấu '-' cho phương thức thực thể
|
||||||
- (NSString *)instanceMethodWithParameter:(NSString *)string;
|
- (NSString *)instanceMethodWithParameter:(NSString *)string;
|
||||||
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number;
|
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
// Thực thi các phương thức trong một tập tin thực thi (MyClass.m):
|
// Thực thi các phương thức trong một tập tin thực thi (MyClass.m):
|
||||||
|
|
||||||
@implementation MyClass
|
@implementation MyClass
|
||||||
|
|
||||||
// Gọi khi đối tượng được release
|
// Gọi khi đối tượng được release
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phương thức khởi tạo (Constructors) là một cách để tạo các lớp
|
// Phương thức khởi tạo (Constructors) là một cách để tạo các lớp
|
||||||
// Đây là phương thức khởi tạo mặc định được gọi khi đối tượng được khởi tạo
|
// Đây là 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
|
- (id)init
|
||||||
{
|
{
|
||||||
if ((self = [super init]))
|
if ((self = [super init]))
|
||||||
{
|
{
|
||||||
self.count = 1;
|
self.count = 1;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSString *)classMethod
|
+ (NSString *)classMethod
|
||||||
{
|
{
|
||||||
return [[self alloc] init];
|
return [[self alloc] init];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)instanceMethodWithParameter:(NSString *)string
|
- (NSString *)instanceMethodWithParameter:(NSString *)string
|
||||||
{
|
{
|
||||||
return @"New string";
|
return @"New string";
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number
|
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number
|
||||||
{
|
{
|
||||||
return @42;
|
return @42;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Các phương thức được khai báo vào MyProtocol
|
// Các phương thức được khai báo vào MyProtocol
|
||||||
- (void)myProtocolMethod
|
- (void)myProtocolMethod
|
||||||
{
|
{
|
||||||
// câu lệnh
|
// câu lệnh
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Một protocol khai báo các phương thức mà có thể thực thi bởi bất kỳ lớp nào.
|
* Một protocol khai báo các phương thức mà 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 là các lớp. Chúng chỉ đơn giản là định ra giao diện (interface)
|
* Các protocol chính chúng không phải là các lớp. Chúng chỉ đơn giản là định ra giao diện (interface)
|
||||||
* mà các đối tượng khác có trách nhiệm sẽ thực thi.
|
* mà các đối tượng khác có trách nhiệm sẽ thực thi.
|
||||||
*/
|
*/
|
||||||
@protocol MyProtocol
|
@protocol MyProtocol
|
||||||
- (void)myProtocolMethod;
|
- (void)myProtocolMethod;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
## Xem Thêm
|
## Xem Thêm
|
||||||
|
|
||||||
+ [Wikipedia Objective-C](http://en.wikipedia.org/wiki/Objective-C)
|
+ [Wikipedia Objective-C](http://en.wikipedia.org/wiki/Objective-C)
|
||||||
|
|
||||||
+ Apple Docs':
|
+ Apple Docs':
|
||||||
+ [Learning Objective-C](http://developer.apple.com/library/ios/referencelibrary/GettingStarted/Learning_Objective-C_A_Primer/)
|
+ [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)
|
+ [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)
|
+ [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)
|
+ [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)
|
+ [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
@@ -1,345 +1,345 @@
|
|||||||
---
|
---
|
||||||
language: elisp
|
language: elisp
|
||||||
contributors:
|
contributors:
|
||||||
- ["Bastien Guerry", "http://bzg.fr"]
|
- ["Bastien Guerry", "http://bzg.fr"]
|
||||||
translators:
|
translators:
|
||||||
- ["Chenbo Li", "http://binarythink.net"]
|
- ["Chenbo Li", "http://binarythink.net"]
|
||||||
filename: learn-emacs-lisp-zh.el
|
filename: learn-emacs-lisp-zh.el
|
||||||
lang: zh-cn
|
lang: zh-cn
|
||||||
---
|
---
|
||||||
|
|
||||||
```scheme
|
```scheme
|
||||||
;; 15分钟学会Emacs Lisp (v0.2a)
|
;; 15分钟学会Emacs Lisp (v0.2a)
|
||||||
;;(作者:bzg,https://github.com/bzg
|
;;(作者:bzg,https://github.com/bzg
|
||||||
;; 译者:lichenbo,http://douban.com/people/lichenbo)
|
;; 译者:lichenbo,http://douban.com/people/lichenbo)
|
||||||
;;
|
;;
|
||||||
;; 请先阅读Peter Norvig的一篇好文:
|
;; 请先阅读Peter Norvig的一篇好文:
|
||||||
;; http://norvig.com/21-days.html
|
;; http://norvig.com/21-days.html
|
||||||
;; (译者注:中文版请见http://blog.youxu.info/21-days/)
|
;; (译者注:中文版请见http://blog.youxu.info/21-days/)
|
||||||
;;
|
;;
|
||||||
;; 之后安装GNU Emacs 24.3:
|
;; 之后安装GNU Emacs 24.3:
|
||||||
;;
|
;;
|
||||||
;; Debian: apt-get install emacs (视具体发行版而定)
|
;; Debian: apt-get install emacs (视具体发行版而定)
|
||||||
;; MacOSX: http://emacsformacosx.com/emacs-builds/Emacs-24.3-universal-10.6.8.dmg
|
;; 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
|
;; Windows: http://ftp.gnu.org/gnu/windows/emacs/emacs-24.3-bin-i386.zip
|
||||||
;;
|
;;
|
||||||
;; 更多信息可以在这里找到:
|
;; 更多信息可以在这里找到:
|
||||||
;; http://www.gnu.org/software/emacs/#Obtaining
|
;; http://www.gnu.org/software/emacs/#Obtaining
|
||||||
|
|
||||||
;; 很重要的警告:
|
;; 很重要的警告:
|
||||||
;;
|
;;
|
||||||
;; 按照这个教程来学习并不会对你的电脑有任何损坏
|
;; 按照这个教程来学习并不会对你的电脑有任何损坏
|
||||||
;; 除非你自己在学习的过程中愤怒地把它砸了
|
;; 除非你自己在学习的过程中愤怒地把它砸了
|
||||||
;; 如果出现了这种情况,我不会承担任何责任
|
;; 如果出现了这种情况,我不会承担任何责任
|
||||||
;;
|
;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;; 打开emacs
|
;; 打开emacs
|
||||||
;;
|
;;
|
||||||
;; 按'q'消除欢迎界面
|
;; 按'q'消除欢迎界面
|
||||||
;;
|
;;
|
||||||
;; 现在请注意窗口底部的那一个灰色长条
|
;; 现在请注意窗口底部的那一个灰色长条
|
||||||
;;
|
;;
|
||||||
;; "*scratch*" 是你现在编辑界面的名字。
|
;; "*scratch*" 是你现在编辑界面的名字。
|
||||||
;; 这个编辑界面叫做一个"buffer"。
|
;; 这个编辑界面叫做一个"buffer"。
|
||||||
;;
|
;;
|
||||||
;; 每当你打开Emacs时,都会默认打开这个scratch buffer
|
;; 每当你打开Emacs时,都会默认打开这个scratch buffer
|
||||||
;; 此时你并没有在编辑任何文件,而是在编辑一个buffer
|
;; 此时你并没有在编辑任何文件,而是在编辑一个buffer
|
||||||
;; 之后你可以将这个buffer保存到一个文件中。
|
;; 之后你可以将这个buffer保存到一个文件中。
|
||||||
;;
|
;;
|
||||||
;; 之后的"Lisp interaction" 则是表明我们可以用的某组命令
|
;; 之后的"Lisp interaction" 则是表明我们可以用的某组命令
|
||||||
;;
|
;;
|
||||||
;; Emacs在每个buffer中都有一组内置的命令
|
;; Emacs在每个buffer中都有一组内置的命令
|
||||||
;; 而当你激活某种特定的模式时,就可以使用相应的命令
|
;; 而当你激活某种特定的模式时,就可以使用相应的命令
|
||||||
;; 这里我们使用`lisp-interaction-mode',
|
;; 这里我们使用`lisp-interaction-mode',
|
||||||
;; 这样我们就可以使用内置的Emacs Lisp(以下简称Elisp)命令了。
|
;; 这样我们就可以使用内置的Emacs Lisp(以下简称Elisp)命令了。
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;; 分号是注释开始的标志
|
;; 分号是注释开始的标志
|
||||||
;;
|
;;
|
||||||
;; Elisp 是由符号表达式构成的 (即"s-表达式"或"s式"):
|
;; Elisp 是由符号表达式构成的 (即"s-表达式"或"s式"):
|
||||||
(+ 2 2)
|
(+ 2 2)
|
||||||
|
|
||||||
;; 这个s式的意思是 "对2进行加2操作".
|
;; 这个s式的意思是 "对2进行加2操作".
|
||||||
|
|
||||||
;; s式周围有括号,而且也可以嵌套:
|
;; s式周围有括号,而且也可以嵌套:
|
||||||
(+ 2 (+ 1 1))
|
(+ 2 (+ 1 1))
|
||||||
|
|
||||||
;; 一个s式可以包含原子符号或者其他s式
|
;; 一个s式可以包含原子符号或者其他s式
|
||||||
;; 在上面的例子中,1和2是原子符号
|
;; 在上面的例子中,1和2是原子符号
|
||||||
;; (+ 2 (+ 1 1)) 和 (+ 1 1) 是s式.
|
;; (+ 2 (+ 1 1)) 和 (+ 1 1) 是s式.
|
||||||
|
|
||||||
;; 在 `lisp-interaction-mode' 中你可以计算s式.
|
;; 在 `lisp-interaction-mode' 中你可以计算s式.
|
||||||
;; 把光标移到闭括号后,之后按下ctrl+j(以后简写为'C-j')
|
;; 把光标移到闭括号后,之后按下ctrl+j(以后简写为'C-j')
|
||||||
|
|
||||||
(+ 3 (+ 1 2))
|
(+ 3 (+ 1 2))
|
||||||
;; ^ 光标放到这里
|
;; ^ 光标放到这里
|
||||||
;; 按下`C-j' 就会输出 6
|
;; 按下`C-j' 就会输出 6
|
||||||
|
|
||||||
;; `C-j' 会在buffer中插入当前运算的结果
|
;; `C-j' 会在buffer中插入当前运算的结果
|
||||||
|
|
||||||
;; 而`C-xC-e' 则会在emacs最底部显示结果,也就是被称作"minibuffer"的区域
|
;; 而`C-xC-e' 则会在emacs最底部显示结果,也就是被称作"minibuffer"的区域
|
||||||
;; 为了避免把我们的buffer填满无用的结果,我们以后会一直用`C-xC-e'
|
;; 为了避免把我们的buffer填满无用的结果,我们以后会一直用`C-xC-e'
|
||||||
|
|
||||||
;; `setq' 可以将一个值赋给一个变量
|
;; `setq' 可以将一个值赋给一个变量
|
||||||
(setq my-name "Bastien")
|
(setq my-name "Bastien")
|
||||||
;; `C-xC-e' 输出 "Bastien" (在 mini-buffer 中显示)
|
;; `C-xC-e' 输出 "Bastien" (在 mini-buffer 中显示)
|
||||||
|
|
||||||
;; `insert' 会在光标处插入字符串:
|
;; `insert' 会在光标处插入字符串:
|
||||||
(insert "Hello!")
|
(insert "Hello!")
|
||||||
;; `C-xC-e' 输出 "Hello!"
|
;; `C-xC-e' 输出 "Hello!"
|
||||||
|
|
||||||
;; 在这里我们只传给了insert一个参数"Hello!", 但是
|
;; 在这里我们只传给了insert一个参数"Hello!", 但是
|
||||||
;; 我们也可以传给它更多的参数,比如2个:
|
;; 我们也可以传给它更多的参数,比如2个:
|
||||||
|
|
||||||
(insert "Hello" " world!")
|
(insert "Hello" " world!")
|
||||||
;; `C-xC-e' 输出 "Hello world!"
|
;; `C-xC-e' 输出 "Hello world!"
|
||||||
|
|
||||||
;; 你也可以用变量名来代替字符串
|
;; 你也可以用变量名来代替字符串
|
||||||
(insert "Hello, I am " my-name)
|
(insert "Hello, I am " my-name)
|
||||||
;; `C-xC-e' 输出 "Hello, I am Bastien"
|
;; `C-xC-e' 输出 "Hello, I am Bastien"
|
||||||
|
|
||||||
;; 你可以把s式嵌入函数中
|
;; 你可以把s式嵌入函数中
|
||||||
(defun hello () (insert "Hello, I am " my-name))
|
(defun hello () (insert "Hello, I am " my-name))
|
||||||
;; `C-xC-e' 输出 hello
|
;; `C-xC-e' 输出 hello
|
||||||
|
|
||||||
;; 现在执行这个函数
|
;; 现在执行这个函数
|
||||||
(hello)
|
(hello)
|
||||||
;; `C-xC-e' 输出 Hello, I am Bastien
|
;; `C-xC-e' 输出 Hello, I am Bastien
|
||||||
|
|
||||||
;; 函数中空括号的意思是我们不需要接受任何参数
|
;; 函数中空括号的意思是我们不需要接受任何参数
|
||||||
;; 但是我们不能一直总是用my-name这个变量
|
;; 但是我们不能一直总是用my-name这个变量
|
||||||
;; 所以我们现在使我们的函数接受一个叫做"name"的参数
|
;; 所以我们现在使我们的函数接受一个叫做"name"的参数
|
||||||
|
|
||||||
(defun hello (name) (insert "Hello " name))
|
(defun hello (name) (insert "Hello " name))
|
||||||
;; `C-xC-e' 输出 hello
|
;; `C-xC-e' 输出 hello
|
||||||
|
|
||||||
;; 现在我们调用这个函数,并且将"you"作为参数传递
|
;; 现在我们调用这个函数,并且将"you"作为参数传递
|
||||||
|
|
||||||
(hello "you")
|
(hello "you")
|
||||||
;; `C-xC-e' 输出 "Hello you"
|
;; `C-xC-e' 输出 "Hello you"
|
||||||
|
|
||||||
;; 成功!
|
;; 成功!
|
||||||
|
|
||||||
;; 现在我们可以休息一下
|
;; 现在我们可以休息一下
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;; 下面我们在新的窗口中新建一个名为 "*test*" 的buffer:
|
;; 下面我们在新的窗口中新建一个名为 "*test*" 的buffer:
|
||||||
|
|
||||||
(switch-to-buffer-other-window "*test*")
|
(switch-to-buffer-other-window "*test*")
|
||||||
;; `C-xC-e' 这时屏幕上会显示两个窗口,而光标此时位于*test* buffer内
|
;; `C-xC-e' 这时屏幕上会显示两个窗口,而光标此时位于*test* buffer内
|
||||||
|
|
||||||
;; 用鼠标单击上面的buffer就会使光标移回。
|
;; 用鼠标单击上面的buffer就会使光标移回。
|
||||||
;; 或者你可以使用 `C-xo' 使得光标跳到另一个窗口中
|
;; 或者你可以使用 `C-xo' 使得光标跳到另一个窗口中
|
||||||
|
|
||||||
;; 你可以用 `progn'命令将s式结合起来:
|
;; 你可以用 `progn'命令将s式结合起来:
|
||||||
(progn
|
(progn
|
||||||
(switch-to-buffer-other-window "*test*")
|
(switch-to-buffer-other-window "*test*")
|
||||||
(hello "you"))
|
(hello "you"))
|
||||||
;; `C-xC-e' 此时屏幕分为两个窗口,并且在*test* buffer中显示"Hello you"
|
;; `C-xC-e' 此时屏幕分为两个窗口,并且在*test* buffer中显示"Hello you"
|
||||||
|
|
||||||
;; 现在为了简洁,我们需要在每个s式后面都使用`C-xC-e'来执行,后面就不再说明了
|
;; 现在为了简洁,我们需要在每个s式后面都使用`C-xC-e'来执行,后面就不再说明了
|
||||||
|
|
||||||
;; 记得可以用过鼠标或者`C-xo'回到*scratch*这个buffer。
|
;; 记得可以用过鼠标或者`C-xo'回到*scratch*这个buffer。
|
||||||
|
|
||||||
;; 清除当前buffer也是常用操作之一:
|
;; 清除当前buffer也是常用操作之一:
|
||||||
(progn
|
(progn
|
||||||
(switch-to-buffer-other-window "*test*")
|
(switch-to-buffer-other-window "*test*")
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(hello "there"))
|
(hello "there"))
|
||||||
|
|
||||||
;; 也可以回到其他的窗口中
|
;; 也可以回到其他的窗口中
|
||||||
(progn
|
(progn
|
||||||
(switch-to-buffer-other-window "*test*")
|
(switch-to-buffer-other-window "*test*")
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(hello "you")
|
(hello "you")
|
||||||
(other-window 1))
|
(other-window 1))
|
||||||
|
|
||||||
;; 你可以用 `let' 将一个值和一个局部变量绑定:
|
;; 你可以用 `let' 将一个值和一个局部变量绑定:
|
||||||
(let ((local-name "you"))
|
(let ((local-name "you"))
|
||||||
(switch-to-buffer-other-window "*test*")
|
(switch-to-buffer-other-window "*test*")
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(hello local-name)
|
(hello local-name)
|
||||||
(other-window 1))
|
(other-window 1))
|
||||||
|
|
||||||
;; 这里我们就不需要使用 `progn' 了, 因为 `let' 也可以将很多s式组合起来。
|
;; 这里我们就不需要使用 `progn' 了, 因为 `let' 也可以将很多s式组合起来。
|
||||||
|
|
||||||
;; 格式化字符串的方法:
|
;; 格式化字符串的方法:
|
||||||
(format "Hello %s!\n" "visitor")
|
(format "Hello %s!\n" "visitor")
|
||||||
|
|
||||||
;; %s 是字符串占位符,这里被"visitor"替代.
|
;; %s 是字符串占位符,这里被"visitor"替代.
|
||||||
;; \n 是换行符。
|
;; \n 是换行符。
|
||||||
|
|
||||||
;; 现在我们用格式化的方法再重写一下我们的函数:
|
;; 现在我们用格式化的方法再重写一下我们的函数:
|
||||||
(defun hello (name)
|
(defun hello (name)
|
||||||
(insert (format "Hello %s!\n" name)))
|
(insert (format "Hello %s!\n" name)))
|
||||||
|
|
||||||
(hello "you")
|
(hello "you")
|
||||||
|
|
||||||
;; 我们再用`let'新建另一个函数:
|
;; 我们再用`let'新建另一个函数:
|
||||||
(defun greeting (name)
|
(defun greeting (name)
|
||||||
(let ((your-name "Bastien"))
|
(let ((your-name "Bastien"))
|
||||||
(insert (format "Hello %s!\n\nI am %s."
|
(insert (format "Hello %s!\n\nI am %s."
|
||||||
name ; the argument of the function
|
name ; the argument of the function
|
||||||
your-name ; the let-bound variable "Bastien"
|
your-name ; the let-bound variable "Bastien"
|
||||||
))))
|
))))
|
||||||
|
|
||||||
;; 之后执行:
|
;; 之后执行:
|
||||||
(greeting "you")
|
(greeting "you")
|
||||||
|
|
||||||
;; 有些函数可以和用户交互:
|
;; 有些函数可以和用户交互:
|
||||||
(read-from-minibuffer "Enter your name: ")
|
(read-from-minibuffer "Enter your name: ")
|
||||||
|
|
||||||
;; 这个函数会返回在执行时用户输入的信息
|
;; 这个函数会返回在执行时用户输入的信息
|
||||||
|
|
||||||
;; 现在我们让`greeting'函数显示你的名字:
|
;; 现在我们让`greeting'函数显示你的名字:
|
||||||
(defun greeting (from-name)
|
(defun greeting (from-name)
|
||||||
(let ((your-name (read-from-minibuffer "Enter your name: ")))
|
(let ((your-name (read-from-minibuffer "Enter your name: ")))
|
||||||
(insert (format "Hello!\n\nI am %s and you are %s."
|
(insert (format "Hello!\n\nI am %s and you are %s."
|
||||||
from-name ; the argument of the function
|
from-name ; the argument of the function
|
||||||
your-name ; the let-bound var, entered at prompt
|
your-name ; the let-bound var, entered at prompt
|
||||||
))))
|
))))
|
||||||
|
|
||||||
(greeting "Bastien")
|
(greeting "Bastien")
|
||||||
|
|
||||||
;; 我们让结果在另一个窗口中显示:
|
;; 我们让结果在另一个窗口中显示:
|
||||||
(defun greeting (from-name)
|
(defun greeting (from-name)
|
||||||
(let ((your-name (read-from-minibuffer "Enter your name: ")))
|
(let ((your-name (read-from-minibuffer "Enter your name: ")))
|
||||||
(switch-to-buffer-other-window "*test*")
|
(switch-to-buffer-other-window "*test*")
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(insert (format "Hello %s!\n\nI am %s." your-name from-name))
|
(insert (format "Hello %s!\n\nI am %s." your-name from-name))
|
||||||
(other-window 1)))
|
(other-window 1)))
|
||||||
|
|
||||||
;; 测试一下:
|
;; 测试一下:
|
||||||
(greeting "Bastien")
|
(greeting "Bastien")
|
||||||
|
|
||||||
;; 第二节结束,休息一下吧。
|
;; 第二节结束,休息一下吧。
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;; 我们将一些名字存到列表中:
|
;; 我们将一些名字存到列表中:
|
||||||
(setq list-of-names '("Sarah" "Chloe" "Mathilde"))
|
(setq list-of-names '("Sarah" "Chloe" "Mathilde"))
|
||||||
|
|
||||||
;; 用 `car'来取得第一个名字:
|
;; 用 `car'来取得第一个名字:
|
||||||
(car list-of-names)
|
(car list-of-names)
|
||||||
|
|
||||||
;; 用 `cdr'取得剩下的名字:
|
;; 用 `cdr'取得剩下的名字:
|
||||||
(cdr list-of-names)
|
(cdr list-of-names)
|
||||||
|
|
||||||
;; 用 `push'把名字添加到列表的开头:
|
;; 用 `push'把名字添加到列表的开头:
|
||||||
(push "Stephanie" list-of-names)
|
(push "Stephanie" list-of-names)
|
||||||
|
|
||||||
;; 注意: `car' 和 `cdr' 并不修改列表本身, 但是 `push' 却会对列表本身进行操作.
|
;; 注意: `car' 和 `cdr' 并不修改列表本身, 但是 `push' 却会对列表本身进行操作.
|
||||||
;; 这个区别是很重要的: 有些函数没有任何副作用(比如`car')
|
;; 这个区别是很重要的: 有些函数没有任何副作用(比如`car')
|
||||||
;; 但还有一些却是有的 (比如 `push').
|
;; 但还有一些却是有的 (比如 `push').
|
||||||
|
|
||||||
;; 我们来对`list-of-names'列表中的每一个元素都使用hello函数:
|
;; 我们来对`list-of-names'列表中的每一个元素都使用hello函数:
|
||||||
(mapcar 'hello list-of-names)
|
(mapcar 'hello list-of-names)
|
||||||
|
|
||||||
;; 将 `greeting' 改进,使的我们能够对`list-of-names'中的所有名字执行:
|
;; 将 `greeting' 改进,使的我们能够对`list-of-names'中的所有名字执行:
|
||||||
(defun greeting ()
|
(defun greeting ()
|
||||||
(switch-to-buffer-other-window "*test*")
|
(switch-to-buffer-other-window "*test*")
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(mapcar 'hello list-of-names)
|
(mapcar 'hello list-of-names)
|
||||||
(other-window 1))
|
(other-window 1))
|
||||||
|
|
||||||
(greeting)
|
(greeting)
|
||||||
|
|
||||||
;; 记得我们之前定义的 `hello' 函数吗? 这个函数接受一个参数,名字。
|
;; 记得我们之前定义的 `hello' 函数吗? 这个函数接受一个参数,名字。
|
||||||
;; `mapcar' 调用 `hello', 并将`list-of-names'作为参数先后传给`hello'
|
;; `mapcar' 调用 `hello', 并将`list-of-names'作为参数先后传给`hello'
|
||||||
|
|
||||||
;; 现在我们对显示的buffer中的内容进行一些更改:
|
;; 现在我们对显示的buffer中的内容进行一些更改:
|
||||||
|
|
||||||
(defun replace-hello-by-bonjour ()
|
(defun replace-hello-by-bonjour ()
|
||||||
(switch-to-buffer-other-window "*test*")
|
(switch-to-buffer-other-window "*test*")
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
(while (search-forward "Hello")
|
(while (search-forward "Hello")
|
||||||
(replace-match "Bonjour"))
|
(replace-match "Bonjour"))
|
||||||
(other-window 1))
|
(other-window 1))
|
||||||
|
|
||||||
;; (goto-char (point-min)) 将光标移到buffer的开始
|
;; (goto-char (point-min)) 将光标移到buffer的开始
|
||||||
;; (search-forward "Hello") 查找字符串"Hello"
|
;; (search-forward "Hello") 查找字符串"Hello"
|
||||||
;; (while x y) 当x返回某个值时执行y这个s式
|
;; (while x y) 当x返回某个值时执行y这个s式
|
||||||
;; 当x返回`nil' (空), 退出循环
|
;; 当x返回`nil' (空), 退出循环
|
||||||
|
|
||||||
(replace-hello-by-bonjour)
|
(replace-hello-by-bonjour)
|
||||||
|
|
||||||
;; 你会看到所有在*test* buffer中出现的"Hello"字样都被换成了"Bonjour"
|
;; 你会看到所有在*test* buffer中出现的"Hello"字样都被换成了"Bonjour"
|
||||||
|
|
||||||
;; 你也会得到以下错误提示: "Search failed: Hello".
|
;; 你也会得到以下错误提示: "Search failed: Hello".
|
||||||
;;
|
;;
|
||||||
;; 如果要避免这个错误, 你需要告诉 `search-forward' 这个命令是否在
|
;; 如果要避免这个错误, 你需要告诉 `search-forward' 这个命令是否在
|
||||||
;; buffer的某个地方停止查找, 并且在什么都没找到时是否应该不给出错误提示
|
;; buffer的某个地方停止查找, 并且在什么都没找到时是否应该不给出错误提示
|
||||||
|
|
||||||
;; (search-forward "Hello" nil t) 可以达到这个要求:
|
;; (search-forward "Hello" nil t) 可以达到这个要求:
|
||||||
|
|
||||||
;; `nil' 参数的意思是 : 查找并不限于某个范围内
|
;; `nil' 参数的意思是 : 查找并不限于某个范围内
|
||||||
;; `t' 参数的意思是: 当什么都没找到时,不给出错误提示
|
;; `t' 参数的意思是: 当什么都没找到时,不给出错误提示
|
||||||
|
|
||||||
;; 在下面的函数中,我们用到了s式,并且不给出任何错误提示:
|
;; 在下面的函数中,我们用到了s式,并且不给出任何错误提示:
|
||||||
|
|
||||||
(defun hello-to-bonjour ()
|
(defun hello-to-bonjour ()
|
||||||
(switch-to-buffer-other-window "*test*")
|
(switch-to-buffer-other-window "*test*")
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
;; 为`list-of-names'中的每个名字调用hello
|
;; 为`list-of-names'中的每个名字调用hello
|
||||||
(mapcar 'hello list-of-names)
|
(mapcar 'hello list-of-names)
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
;; 将"Hello" 替换为"Bonjour"
|
;; 将"Hello" 替换为"Bonjour"
|
||||||
(while (search-forward "Hello" nil t)
|
(while (search-forward "Hello" nil t)
|
||||||
(replace-match "Bonjour"))
|
(replace-match "Bonjour"))
|
||||||
(other-window 1))
|
(other-window 1))
|
||||||
|
|
||||||
(hello-to-bonjour)
|
(hello-to-bonjour)
|
||||||
|
|
||||||
;; 给这些名字加粗:
|
;; 给这些名字加粗:
|
||||||
|
|
||||||
(defun boldify-names ()
|
(defun boldify-names ()
|
||||||
(switch-to-buffer-other-window "*test*")
|
(switch-to-buffer-other-window "*test*")
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
(while (re-search-forward "Bonjour \\(.+\\)!" nil t)
|
(while (re-search-forward "Bonjour \\(.+\\)!" nil t)
|
||||||
(add-text-properties (match-beginning 1)
|
(add-text-properties (match-beginning 1)
|
||||||
(match-end 1)
|
(match-end 1)
|
||||||
(list 'face 'bold)))
|
(list 'face 'bold)))
|
||||||
(other-window 1))
|
(other-window 1))
|
||||||
|
|
||||||
;; 这个函数使用了 `re-search-forward':
|
;; 这个函数使用了 `re-search-forward':
|
||||||
;; 和查找一个字符串不同,你用这个命令可以查找一个模式,即正则表达式
|
;; 和查找一个字符串不同,你用这个命令可以查找一个模式,即正则表达式
|
||||||
|
|
||||||
;; 正则表达式 "Bonjour \\(.+\\)!" 的意思是:
|
;; 正则表达式 "Bonjour \\(.+\\)!" 的意思是:
|
||||||
;; 字符串 "Bonjour ", 之后跟着
|
;; 字符串 "Bonjour ", 之后跟着
|
||||||
;; 一组 | \\( ... \\) 结构
|
;; 一组 | \\( ... \\) 结构
|
||||||
;; 任意字符 | . 的含义
|
;; 任意字符 | . 的含义
|
||||||
;; 有可能重复的 | + 的含义
|
;; 有可能重复的 | + 的含义
|
||||||
;; 之后跟着 "!" 这个字符串
|
;; 之后跟着 "!" 这个字符串
|
||||||
|
|
||||||
;; 准备好了?试试看。
|
;; 准备好了?试试看。
|
||||||
|
|
||||||
(boldify-names)
|
(boldify-names)
|
||||||
|
|
||||||
;; `add-text-properties' 可以添加文字属性, 比如文字样式
|
;; `add-text-properties' 可以添加文字属性, 比如文字样式
|
||||||
|
|
||||||
;; 好的,我们成功了!
|
;; 好的,我们成功了!
|
||||||
|
|
||||||
;; 如果你想对一个变量或者函数有更多的了解:
|
;; 如果你想对一个变量或者函数有更多的了解:
|
||||||
;;
|
;;
|
||||||
;; C-h v 变量 回车
|
;; C-h v 变量 回车
|
||||||
;; C-h f 函数 回车
|
;; C-h f 函数 回车
|
||||||
;;
|
;;
|
||||||
;; 阅读Emacs Lisp官方文档:
|
;; 阅读Emacs Lisp官方文档:
|
||||||
;;
|
;;
|
||||||
;; C-h i m elisp 回车
|
;; C-h i m elisp 回车
|
||||||
;;
|
;;
|
||||||
;; 在线阅读Emacs Lisp文档:
|
;; 在线阅读Emacs Lisp文档:
|
||||||
;; https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html
|
;; https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html
|
||||||
|
|
||||||
;; 感谢以下同学的建议和反馈:
|
;; 感谢以下同学的建议和反馈:
|
||||||
;; - Wes Hardaker
|
;; - Wes Hardaker
|
||||||
;; - notbob
|
;; - notbob
|
||||||
;; - Kevin Montuori
|
;; - Kevin Montuori
|
||||||
;; - Arne Babenhauserheide
|
;; - Arne Babenhauserheide
|
||||||
;; - Alan Schmitt
|
;; - Alan Schmitt
|
||||||
;; - spacegoing
|
;; - spacegoing
|
||||||
```
|
```
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user